Or1k only supports ordered compares so we fall back to lib functions for unordered operations.
Doubles work on this 32-bit architecture by using register pairing as specified in: https://openrisc.io/proposals/orfpx64a32 Or1k does not support sf/df or df/sf conversions. gcc/ChangeLog: * config.gcc (or1k*-*-*): Add mhard-float and mdouble-float validations. * config/or1k/or1k.md (type): Add fpu. (fpu): New instruction reservation. (F, f, fi, FI, FOP, fop): New. (<fop><F:mode>3): New ALU instruction definition. (float<fi><F:mode>2): New conversion instruction definition. (fix_trunc<F:mode><fi>2): New conversion instruction definition. (fpcmpcc): New code iterator. (*sf_fp_insn): New instruction definition. (cstore<F:mode>4): New expand definition. (cbranch<F:mode>4): New expand definition. * config/or1k/or1k.opt (msoft-float, mhard-float, mdouble-float): New options. * doc/invoke.texi: Document msoft-float, mhard-float and mdouble-float. --- gcc/config.gcc | 1 + gcc/config/or1k/or1k.md | 103 ++++++++++++++++++++++++++++++++++++++- gcc/config/or1k/or1k.opt | 15 +++++- gcc/doc/invoke.texi | 15 ++++++ 4 files changed, 131 insertions(+), 3 deletions(-) diff --git a/gcc/config.gcc b/gcc/config.gcc index ebbab5d8b6a..8017851922e 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2541,6 +2541,7 @@ or1k*-*-*) for or1k_multilib in ${or1k_multilibs}; do case ${or1k_multilib} in mcmov | msext | msfimm | \ + mhard-float | mdouble-float | \ mhard-div | mhard-mul | \ msoft-div | msoft-mul ) TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${or1k_multilib}" diff --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md index 2dad51cd46b..202493c5ab9 100644 --- a/gcc/config/or1k/or1k.md +++ b/gcc/config/or1k/or1k.md @@ -60,7 +60,7 @@ (define_attr "length" "" (const_int 4)) (define_attr "type" - "alu,st,ld,control,multi" + "alu,st,ld,control,multi,fpu" (const_string "alu")) (define_attr "insn_support" "class1,sext,sfimm,shftimm" (const_string "class1")) @@ -93,6 +93,10 @@ (define_insn_reservation "control" 1 (eq_attr "type" "control") "cpu") +(define_insn_reservation "fpu" 2 + (eq_attr "type" "fpu") + "cpu") + ; Define delay slots for any branch (define_delay (eq_attr "type" "control") @@ -155,6 +159,46 @@ "" "l.sub\t%0, %r1, %2") +;; ------------------------------------------------------------------------- +;; Floating Point Arithmetic instructions +;; ------------------------------------------------------------------------- + +;; Mode iterator for single/double float +(define_mode_iterator F [(SF "TARGET_HARD_FLOAT") + (DF "TARGET_DOUBLE_FLOAT")]) +(define_mode_attr f [(SF "s") (DF "d")]) +(define_mode_attr fi [(SF "si") (DF "di")]) +(define_mode_attr FI [(SF "SI") (DF "DI")]) + +;; Basic arithmetic instructions +(define_code_iterator FOP [plus minus mult div]) +(define_code_attr fop [(plus "add") (minus "sub") (mult "mul") (div "div")]) + +(define_insn "<fop><F:mode>3" + [(set (match_operand:F 0 "register_operand" "=r") + (FOP:F (match_operand:F 1 "register_operand" "r") + (match_operand:F 2 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.<fop>.<f>\t%0, %1, %2" + [(set_attr "type" "fpu")]) + +;; Basic float<->int conversion +(define_insn "float<fi><F:mode>2" + [(set (match_operand:F 0 "register_operand" "=r") + (float:F + (match_operand:<FI> 1 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.itof.<f>\t%0, %1" + [(set_attr "type" "fpu")]) + +(define_insn "fix_trunc<F:mode><fi>2" + [(set (match_operand:<FI> 0 "register_operand" "=r") + (fix:<FI> + (match_operand:F 1 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.ftoi.<f>\t%0, %1" + [(set_attr "type" "fpu")]) + ;; ------------------------------------------------------------------------- ;; Logical operators ;; ------------------------------------------------------------------------- @@ -388,6 +432,31 @@ l.sf<insn>i\t%r0, %1" [(set_attr "insn_support" "*,sfimm")]) +;; Support FP comparisons too + +;; The OpenRISC FPU supports these comparisons: +;; +;; lf.sfeq.{d,s} - equality, r r, double or single precision +;; lf.sfge.{d,s} - greater than or equal, r r, double or single precision +;; lf.sfgt.{d,s} - greater than, r r, double or single precision +;; lf.sfle.{d,s} - less than or equal, r r, double or single precision +;; lf.sflt.{d,s} - less than, r r, double or single precision +;; lf.sfne.{d,s} - not equal, r r, double or single precision +;; +;; Double precision is only supported on some hardware. Only register/register +;; comparisons are supported. All comparisons are signed. + +(define_code_iterator fpcmpcc [ne eq lt gt ge le]) + +(define_insn "*sf_fp_insn" + [(set (reg:BI SR_F_REGNUM) + (fpcmpcc:BI (match_operand:F 0 "register_operand" "r") + (match_operand:F 1 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.sf<code>.<f>\t%0, %1" + [(set_attr "type" "fpu")]) + + ;; ------------------------------------------------------------------------- ;; Conditional Store instructions ;; ------------------------------------------------------------------------- @@ -408,6 +477,23 @@ DONE; }) +;; Support FP cstores too +(define_expand "cstore<F:mode>4" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:F + (match_operator 1 "ordered_comparison_operator" + [(match_operand:F 2 "register_operand" "") + (match_operand:F 3 "register_operand" "")]) + (match_dup 0) + (const_int 0)))] + "TARGET_HARD_FLOAT" +{ + or1k_expand_compare (operands + 1); + PUT_MODE (operands[1], SImode); + emit_insn (gen_rtx_SET (operands[0], operands[1])); + DONE; +}) + ;; Being able to "copy" SR_F to a general register is helpful for ;; the atomic insns, wherein the usual usage is to test the success ;; of the compare-and-swap. Representing the operation in this way, @@ -501,6 +587,21 @@ or1k_expand_compare (operands); }) +;; Support FP branching + +(define_expand "cbranch<F:mode>4" + [(set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(match_operand:F 1 "register_operand" "") + (match_operand:F 2 "register_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_HARD_FLOAT" +{ + or1k_expand_compare (operands); +}) + (define_insn "*cbranch" [(set (pc) (if_then_else diff --git a/gcc/config/or1k/or1k.opt b/gcc/config/or1k/or1k.opt index 7bdbd842dd4..9a7e1c8bae7 100644 --- a/gcc/config/or1k/or1k.opt +++ b/gcc/config/or1k/or1k.opt @@ -21,8 +21,6 @@ ; See the GCC internals manual (options.texi) for a description of ; this file's format. -; Please try to keep this file in ASCII collating order. - mhard-div Target RejectNegative InverseMask(SOFT_DIV) Use hardware divide instructions, use -msoft-div for emulation. @@ -31,6 +29,19 @@ mhard-mul Target RejectNegative InverseMask(SOFT_MUL). Use hardware multiply instructions, use -msoft-mul for emulation. +msoft-float +Target RejectNegative InverseMask(HARD_FLOAT) +Use gcc provided software routines for floating point operations. + +mhard-float +Target RejectNegative Mask(HARD_FLOAT) +Use hardware floating point instructions. + +mdouble-float +Target Mask(DOUBLE_FLOAT) +Allows generation of binaries which support 64-bit doubles on 32-bit systems by +storing doubles in register pairs. + mcmov Target RejectNegative Mask(CMOV) Allows generation of binaries which use the l.cmov instruction. If your target diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index cfc3063929b..5b474be265a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1028,6 +1028,7 @@ Objective-C and Objective-C++ Dialects}. @emph{OpenRISC Options} @gccoptlist{-mboard=@var{name} -mnewlib -mhard-mul -mhard-div @gol -msoft-mul -msoft-div @gol +-msoft-float -mhard-float -mdouble-float @gol -mcmov -mror -msext -msfimm -mshftimm} @emph{PDP-11 Options} @@ -23551,6 +23552,20 @@ default. Generate code for hardware which supports multiply instructions. This is the default. +@item -msoft-float +@opindex msoft-float +Generate code which uses library calls for floating point operations. This is +the default. + +@item -mhard-float +@opindex mhard-float +Generate code for hardware which supports floating point instructions. + +@item -mdouble-float +@opindex mdouble-float +Generate code for hardware which supports 64-bit floating point operations +on 32-bit OpenRISC targets. + @item -mcmov @opindex mcmov Generate code for hardware which supports the conditional move (@code{l.cmov}) -- 2.19.1