;; Machine description of Andes NDS32 cpu for GNU compiler ;; Copyright (C) 2012-2022 Free Software Foundation, Inc. ;; Contributed by Andes Technology Corporation. ;; ;; This file is part of GCC. ;; ;; GCC is free software; you can redistribute it and/or modify it ;; under the terms of the GNU General Public License as published ;; by the Free Software Foundation; either version 3, or (at your ;; option) any later version. ;; ;; GCC is distributed in the hope that it will be useful, but WITHOUT ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public ;; License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with GCC; see the file COPYING3. If not see ;; http://www.gnu.org/licenses/.

;;SFmode moves

(define_expand “movsf” [(set (match_operand:SF 0 “general_operand” "") (match_operand:SF 1 “general_operand” ""))] "" { /* Need to force register if mem <- !reg. */ if (MEM_P (operands[0]) && !REG_P (operands[1])) operands[1] = force_reg (SFmode, operands[1]); if (CONST_DOUBLE_P (operands[1]) && !satisfies_constraint_Cs20 (operands[1])) { const REAL_VALUE_TYPE *r; unsigned long l;

  r = CONST_DOUBLE_REAL_VALUE (operands[1]);
  REAL_VALUE_TO_TARGET_SINGLE (*r, l);

  emit_move_insn (operands[0], gen_rtx_HIGH (SFmode, operands[1]));

  if ((l & 0xFFF) != 0)
emit_insn (gen_movsf_lo (operands[0], operands[0], operands[1]));
  DONE;
}

})

(define_insn “movsf_lo” [(set (match_operand:SF 0 “register_operand” “=r”) (lo_sum:SF (match_operand:SF 1 “register_operand” “r”) (match_operand:SF 2 “immediate_operand” “i”)))] "" “ori\t%0, %1, lo12(%2)” [(set_attr “type” “alu”) (set_attr “length” “4”)] )

(define_insn “*movsf” [(set (match_operand:SF 0 “nonimmediate_operand” “=r, r, U45, U33, U37, U45, m, l, l, l, d, r, f, *f, *r, f, Q, r, r, r”) (match_operand:SF 1 “general_operand” " r, r, l, l, l, d, r, U45, U33, U37, U45, m, f, *r, *f, Q, f,Cs05,Cs20, Chig"))] “(register_operand(operands[0], SFmode) || register_operand(operands[1], SFmode))” { switch (which_alternative) { case 0: return “mov55\t%0, %1”; case 1: return “ori\t%0, %1, 0”; case 2: case 3: case 4: case 5: return nds32_output_16bit_store (operands, 4); case 6: return nds32_output_32bit_store (operands, 4); case 7: case 8: case 9: case 10: return nds32_output_16bit_load (operands, 4); case 11: return nds32_output_32bit_load (operands, 4); case 12: if (TARGET_FPU_SINGLE) return “fcpyss\t%0, %1, %1”; else return “#”; case 13: return “fmtsr\t%1, %0”; case 14: return “fmfsr\t%0, %1”; case 15: return nds32_output_float_load (operands); case 16: return nds32_output_float_store (operands); case 17: return “movi55\t%0, %1”; case 18: return “movi\t%0, %1”; case 19: return “sethi\t%0, %1”; default: gcc_unreachable (); } } [(set_attr “type” “alu,alu,store,store,store,store,store,load,load,load,load,load,fcpy,fmtsr,fmfsr,fload,fstore,alu,alu,alu”) (set_attr “length” " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 2, 4, 4") (set_attr “feature” " v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu, v1, v1, v1")])

;; Conditional Move Instructions

(define_expand “movcc” [(set (match_operand:ANYF 0 “register_operand” "") (if_then_else:ANYF (match_operand 1 “nds32_float_comparison_operator” "") (match_operand:ANYF 2 “register_operand” "") (match_operand:ANYF 3 “register_operand” "")))] "" { if (nds32_cond_move_p (operands[1])) { /* Operands[1] condition code is UNORDERED or ORDERED, and sub-operands[1] MODE isn‘t SFmode or SFmode, return FAIL for gcc, because we don’t using slt compare instruction to generate UNORDERED and ORDERED condition. */ FAIL; } else nds32_expand_float_movcc (operands); })

(define_insn “fcmov_eq” [(set (match_operand:ANYF 0 “register_operand” “=f, f”) (if_then_else:ANYF (eq (match_operand:SI 1 “register_operand” “f, f”) (const_int 0)) (match_operand:ANYF 2 “register_operand” “f, 0”) (match_operand:ANYF 3 “register_operand” “0, f”)))] "" “@ fcmovz\t%0,%2,%1 fcmovn\t%0,%3,%1” [(set_attr “type” “fcmov”) (set_attr “length” “4”)] )

(define_insn “fcmov_ne” [(set (match_operand:ANYF 0 “register_operand” “=f, f”) (if_then_else:ANYF (ne (match_operand:SI 1 “register_operand” “f, f”) (const_int 0)) (match_operand:ANYF 2 “register_operand” “f, 0”) (match_operand:ANYF 3 “register_operand” “0, f”)))] "" “@ fcmovn\t%0,%2,%1 fcmovz\t%0,%3,%1” [(set_attr “type” “fcmov”) (set_attr “length” “4”)] )

;; Arithmetic instructions.

(define_insn “add3” [(set (match_operand:ANYF 0 “register_operand” “=f”) (plus:ANYF (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”)))] "" “fadd\t %0, %1, %2” [(set_attr “type” “falu”) (set_attr “length” “4”)] )

(define_insn “sub3” [(set (match_operand:ANYF 0 “register_operand” “=f”) (minus:ANYF (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”)))] "" “fsub\t %0, %1, %2” [(set_attr “type” “falu”) (set_attr “length” “4”)] )

;; Multiplication insns.

(define_insn “mul3” [(set (match_operand:ANYF 0 “register_operand” “=f”) (mult:ANYF (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”)))] "" “fmul\t %0, %1, %2” [(set_attr “type” “fmul”) (set_attr “length” “4”)] )

(define_insn “fma4” [(set (match_operand:ANYF 0 “register_operand” “=f”) (fma:ANYF (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”) (match_operand:ANYF 3 “register_operand” “0”)))] “TARGET_EXT_FPU_FMA” “fmadd\t%0, %1, %2” [(set_attr “type” “fmac”) (set_attr “length” “4”)] )

(define_insn “fnma4” [(set (match_operand:ANYF 0 “register_operand” “=f”) (fma:ANYF (neg:ANYF (match_operand:ANYF 1 “register_operand” “f”)) (match_operand:ANYF 2 “register_operand” “f”) (match_operand:ANYF 3 “register_operand” “0”)))] “TARGET_EXT_FPU_FMA” “fmsub\t%0, %1, %2” [(set_attr “type” “fmac”) (set_attr “length” “4”)] )

(define_insn “fms4” [(set (match_operand:ANYF 0 “register_operand” “=f”) (fma:ANYF (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”) (neg:ANYF (match_operand:ANYF 3 “register_operand” “0”))))] “TARGET_EXT_FPU_FMA” “fnmsub\t%0, %1, %2” [(set_attr “type” “fmac”) (set_attr “length” “4”)] )

(define_insn “fnms4” [(set (match_operand:ANYF 0 “register_operand” “=f”) (fma:ANYF (neg:ANYF (match_operand:ANYF 1 “register_operand” “f”)) (match_operand:ANYF 2 “register_operand” “f”) (neg:ANYF (match_operand:ANYF 3 “register_operand” “0”))))] “TARGET_EXT_FPU_FMA” “fnmadd\t%0, %1, %2” [(set_attr “type” “fmac”) (set_attr “length” “4”)] )

;; Div Instructions.

(define_insn “div3” [(set (match_operand:ANYF 0 “register_operand” “=f”) (div:ANYF (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”)))] "" “fdiv\t %0, %1, %2” [(set_attr “type” “fdiv”) (set_attr “length” “4”)] )

(define_insn “sqrt2” [(set (match_operand:ANYF 0 “register_operand” “=f”) (sqrt:ANYF (match_operand:ANYF 1 “register_operand” “f”)))] "" “fsqrt\t %0, %1” [(set_attr “type” “fsqrt”) (set_attr “length” “4”)] )

;; Conditional Branch patterns

(define_expand “cstore4” [(set (match_operand:SI 0 “register_operand” "") (match_operator:SI 1 “nds32_float_comparison_operator” [(match_operand:ANYF 2 “register_operand” "") (match_operand:ANYF 3 “register_operand” "")]))] "" { nds32_expand_float_cstore (operands); DONE; })

(define_expand “cbranch4” [(set (pc) (if_then_else (match_operator 0 “nds32_float_comparison_operator” [(match_operand:ANYF 1 “register_operand” "") (match_operand:ANYF 2 “register_operand” "")]) (label_ref (match_operand 3 "" "")) (pc)))] "" { nds32_expand_float_cbranch (operands); DONE; })

;; Copysign Instructions.

(define_insn “copysignsf3” [(set (match_operand:SF 0 “register_operand” “=f”) (unspec:SF [(match_operand:SF 1 “register_operand” “f”) (match_operand:SF 2 “register_operand” “f”)] UNSPEC_COPYSIGN))] “TARGET_FPU_SINGLE” “fcpyss\t%0,%1,%2” [(set_attr “type” “fcpy”) (set_attr “length” “4”)] )

(define_insn “copysigndf3” [(set (match_operand:DF 0 “register_operand” “=f”) (unspec:DF [(match_operand:DF 1 “register_operand” “f”) (match_operand:DF 2 “register_operand” “f”)] UNSPEC_COPYSIGN))] “TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE” “fcpysd\t%0,%1,%2” [(set_attr “type” “fcpy”) (set_attr “length” “4”)] )

(define_insn “*ncopysign3” [(set (match_operand:ANYF 0 “register_operand” “=f”) (neg:ANYF (unspec:ANYF [(match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”)] UNSPEC_COPYSIGN)))] "" “fcpyns\t%0,%1,%2” [(set_attr “type” “fcpy”) (set_attr “length” “4”)] )

;; Absolute Instructions

(define_insn “abssf2” [(set (match_operand:SF 0 “register_operand” “=f, r”) (abs:SF (match_operand:SF 1 “register_operand” “f, r”)))] “TARGET_FPU_SINGLE || TARGET_EXT_PERF” “@ fabss\t%0, %1 bclr\t%0, %1, 31” [(set_attr “type” “fabs,alu”) (set_attr “length” “4”) (set_attr “feature” “fpu,pe1”)] )

(define_insn “absdf2” [(set (match_operand:DF 0 “register_operand” “=f”) (abs:DF (match_operand:DF 1 “register_operand” “f”)))] “TARGET_FPU_DOUBLE” “fabsd\t%0, %1” [(set_attr “type” “fabs”) (set_attr “length” “4”)] )

;; Negation Instructions

(define_insn “*negsf2” [(set (match_operand:SF 0 “register_operand” “=f, r”) (neg:SF (match_operand:SF 1 “register_operand” “f, r”)))] “TARGET_FPU_SINGLE || TARGET_EXT_PERF” “@ fcpynss\t%0, %1, %1 btgl\t%0, %1, 31” [(set_attr “type” “fcpy,alu”) (set_attr “length” “4”) (set_attr “feature” “fpu,pe1”)] )

(define_insn “*negdf2” [(set (match_operand:DF 0 “register_operand” “=f”) (neg:DF (match_operand:DF 1 “register_operand” “f”)))] “TARGET_FPU_DOUBLE” “fcpynsd\t%0, %1, %1” [(set_attr “type” “fcpy”) (set_attr “length” “4”)] )

;; Data Format Conversion Instructions

(define_insn “floatunssi2” [(set (match_operand:ANYF 0 “register_operand” “=f”) (unsigned_float:ANYF (match_operand:SI 1 “register_operand” “f”)))] "" “fui2\t %0, %1” [(set_attr “type” “falu”) (set_attr “length” “4”)] )

(define_insn “floatsi2” [(set (match_operand:ANYF 0 “register_operand” “=f”) (float:ANYF (match_operand:SI 1 “register_operand” “f”)))] "" “fsi2\t %0, %1” [(set_attr “type” “falu”) (set_attr “length” “4”)] )

(define_insn “fixuns_truncsi2” [(set (match_operand:SI 0 “register_operand” “=f”) (unsigned_fix:SI (fix:ANYF (match_operand:ANYF 1 “register_operand” “f”))))] "" “f2ui.z\t %0, %1” [(set_attr “type” “falu”) (set_attr “length” “4”)] )

(define_insn “fix_truncsi2” [(set (match_operand:SI 0 “register_operand” “=f”) (fix:SI (fix:ANYF (match_operand:ANYF 1 “register_operand” “f”))))] "" “f2si.z\t %0, %1” [(set_attr “type” “falu”) (set_attr “length” “4”)] )

(define_insn “extendsfdf2” [(set (match_operand:DF 0 “register_operand” “=f”) (float_extend:DF (match_operand:SF 1 “register_operand” “f”)))] “TARGET_FPU_SINGLE && TARGET_FPU_DOUBLE” “fs2d\t%0, %1” [(set_attr “type” “falu”) (set_attr “length” “4”)] )

(define_insn “truncdfsf2” [(set (match_operand:SF 0 “register_operand” “=f”) (float_truncate:SF (match_operand:DF 1 “register_operand” “f”)))] “TARGET_FPU_SINGLE && TARGET_FPU_DOUBLE” “fd2s\t%0, %1” [(set_attr “type” “falu”) (set_attr “length” “4”)] )

;; Compare Instructions

(define_insn “cmp_eq” [(set (match_operand:SI 0 “register_operand” “=f”) (eq:SI (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”)))] "" { if (NDS32_EXT_FPU_DOT_E) return “fcmpeq.e %0, %1, %2”; else return “fcmpeq\t%0, %1, %2”; } [(set_attr “type” “fcmp”) (set_attr “length” “4”)] )

(define_insn “cmp_lt” [(set (match_operand:SI 0 “register_operand” “=f”) (lt:SI (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”)))] "" { if (NDS32_EXT_FPU_DOT_E) return “fcmplt.e %0, %1, %2”; else return “fcmplt\t%0, %1, %2”; } [(set_attr “type” “fcmp”) (set_attr “length” “4”)] )

(define_insn “cmp_le” [(set (match_operand:SI 0 “register_operand” “=f”) (le:SI (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”)))] "" { if (NDS32_EXT_FPU_DOT_E) return “fcmple.e %0, %1, %2”; else return “fcmple\t%0, %1, %2”; } [(set_attr “type” “fcmp”) (set_attr “length” “4”)] )

(define_insn “cmp_un” [(set (match_operand:SI 0 “register_operand” “=f”) (unordered:SI (match_operand:ANYF 1 “register_operand” “f”) (match_operand:ANYF 2 “register_operand” “f”)))] "" { if (NDS32_EXT_FPU_DOT_E) return “fcmpun.e %0, %1, %2”; else return “fcmpun\t%0, %1, %2”; } [(set_attr “type” “fcmp”) (set_attr “length” “4”)] )

(define_split [(set (match_operand:SF 0 “register_operand” "") (match_operand:SF 1 “register_operand” ""))] “!TARGET_FPU_SINGLE && NDS32_IS_FPR_REGNUM (REGNO (operands[0])) && NDS32_IS_FPR_REGNUM (REGNO (operands[1]))” [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (match_dup 2))] { operands[2] = gen_rtx_REG (SFmode, TA_REGNUM); })

(define_split [(set (match_operand:SF 0 “register_operand” "") (match_operand:SF 1 “const_double_operand” ""))] “!satisfies_constraint_Cs20 (operands[1]) && !satisfies_constraint_Chig (operands[1])” [(set (match_dup 0) (high:SF (match_dup 1))) (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))]) ;; ----------------------------------------------------------------------------