📄 mips.md
字号:
")(define_insn "extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") (sign_extend:SI (match_operand:QI 1 "general_operand" "r,m")))] "" "*{ if (which_alternative == 0) { output_asm_insn (\"sll\\t%0,%1,0x18\\t#sign extendqisi2\\t %1 -> %0\", operands); return \"sra\\t%0,%0,0x18\\t#sign extendqisi2\\t %1 -> %0\"; } else return \"lb\\t%0,%1\\t#sign extendqisi2 %1 -> %0\";}")(define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] "" "cvt.d.s\\t%0,%1\\t#extendsfdf2\\t %1 -> %0");;;; ....................;;;; CONVERSIONS;;;; ....................(define_insn "fix_truncdfsi2_internal" [(set (match_operand:DF 0 "register_operand" "=f") (fix:DF (match_operand:DF 1 "register_operand" "f"))) (clobber (match_operand:SI 2 "register_operand" "r"))] "" "trunc.w.d %0,%1,%2")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] "" "mfc1\\t%0,%1")(define_expand "fix_truncdfsi2" [(set (match_operand:SI 0 "register_operand" "=r") (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] "" "{ rtx reg1 = gen_reg_rtx (DFmode); /* fp reg that gets trunc result */ rtx reg2 = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */ emit_insn (gen_fix_truncdfsi2_internal (reg1, operands[1], reg2)); operands[1] = reg1; /* Fall through and generate default code */}")(define_insn "fix_truncsfsi2_internal" [(set (match_operand:SF 0 "register_operand" "=f") (fix:SF (match_operand:SF 1 "register_operand" "f"))) (clobber (match_operand:SI 2 "register_operand" "r"))] "" "trunc.w.s %0,%1,%2")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] "" "mfc1\\t%0,%1")(define_expand "fix_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "=r") (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] "" "{ rtx reg1 = gen_reg_rtx (SFmode); /* fp reg that gets trunc result */ rtx reg2 = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */ emit_insn (gen_fix_truncsfsi2_internal (reg1, operands[1], reg2)); operands[1] = reg1; /* Fall through and generate default code */}")(define_insn "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=f") (float:DF (match_operand:SI 1 "register_operand" "r")))] "" "mtc1\\t%1,%0\\t\\t#floatsidf2\\t%1 -> %0\;cvt.d.w\\t%0,%0")(define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=f") (float:SF (match_operand:SI 1 "register_operand" "r")))] "" "mtc1\\t%1,%0\\t\\t#floatsisf2\\t%1 -> %0\;cvt.s.w\\t%0,%0")(define_expand "fixuns_truncdfsi2" [(set (match_operand:SI 0 "register_operand" "") (unsigned_fix:SI (match_operand:DF 1 "register_operand" "")))] "" "{ rtx reg1 = gen_reg_rtx (DFmode); rtx reg2 = gen_reg_rtx (DFmode); rtx reg3 = gen_reg_rtx (SImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31); if (reg1) /* turn off complaints about unreached code */ { emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); do_pending_stack_adjust (); emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, gen_rtx (COMPARE, DFmode, operands[1], reg1))); emit_jump_insn (gen_bge (label1)); emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, label2))); emit_barrier (); emit_label (label1); emit_move_insn (reg2, gen_rtx (MINUS, DFmode, operands[1], reg1)); emit_move_insn (reg3, gen_rtx (CONST_INT, VOIDmode, 0x80000000)); emit_insn (gen_fix_truncdfsi2 (operands[0], reg2)); emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); emit_label (label2); /* allow REG_NOTES to be set on last insn (labels don't have enough fields, and can't be used for REG_NOTES anyway). */ emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); DONE; }}")(define_expand "fixuns_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "") (unsigned_fix:SI (match_operand:SF 1 "register_operand" "")))] "" "{ rtx reg1 = gen_reg_rtx (SFmode); rtx reg2 = gen_reg_rtx (SFmode); rtx reg3 = gen_reg_rtx (SImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31); if (reg1) /* turn off complaints about unreached code */ { emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); do_pending_stack_adjust (); emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, gen_rtx (COMPARE, SFmode, operands[1], reg1))); emit_jump_insn (gen_bge (label1)); emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, label2))); emit_barrier (); emit_label (label1); emit_move_insn (reg2, gen_rtx (MINUS, SFmode, operands[1], reg1)); emit_move_insn (reg3, gen_rtx (CONST_INT, VOIDmode, 0x80000000)); emit_insn (gen_fix_truncsfsi2 (operands[0], reg2)); emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); emit_label (label2); /* allow REG_NOTES to be set on last insn (labels don't have enough fields, and can't be used for REG_NOTES anyway). */ emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); DONE; }}") ;;- Wild things used when ;;- unions make double and int ;;- overlap. ;;- ;;- This must be supported ;;- since corresponding code ;;- gets generated(define_insn "" [(set (subreg:DF (match_operand:DI 0 "register_operand" "=ry") 0) (match_operand:DF 1 "register_operand" "rf")) (clobber (match_operand 2 "register_operand" "rf"))] "" "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")(define_insn "" [(set (subreg:DF (match_operand:DI 0 "register_operand" "=ry") 0) (match_operand:DF 1 "register_operand" "rf"))] "" "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")(define_insn "" [(set (match_operand:DF 0 "register_operand" "=rf") (subreg:DF (match_operand:DI 1 "register_operand" "ry") 0)) (clobber (match_operand 2 "register_operand" "rf"))] "" "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")(define_insn "" [(set (match_operand:DF 0 "register_operand" "=rf") (subreg:DF (match_operand:DI 1 "register_operand" "ry") 0))] "" "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1");;;; ....................;;;; MOVES;;;; and;;;; LOADS AND STORES;;;; ....................;; unaligned word moves generated to move unaligned structs;; to/from registers.;; We use (use (reg:SI 0)) to select this pattern rather than the;; normal movsi. Make these before the normal move patterns so they;; match first.(define_expand "movsi_unaligned" [(parallel [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" "")) (use (reg:SI 0))])] "" "{ extern rtx force_reg (); extern rtx gen_movsi_ulw (); extern rtx gen_movsi (); if (GET_CODE (operands[0]) == MEM && !register_operand (operands[1], SImode)) { rtx reg = gen_reg_rtx (SImode); emit_insn (gen_movsi_ulw (reg, operands[1])); operands[1] = reg; } /* Generate appropriate load, store. If not a load or store, do a normal movsi. */ if (GET_CODE (operands[0]) != MEM && GET_CODE (operands[1]) != MEM) { emit_insn (gen_movsi (operands[0], operands[1])); DONE; } /* Fall through and generate normal code. */}")(define_insn "movsi_ulw" [(set (match_operand:SI 0 "register_operand" "=&r,r,r") (match_operand:SI 1 "general_operand" "o,r,n")) (use (reg:SI 0))] "" "*{ extern rtx eliminate_constant_term (); switch (which_alternative) { case 0: /* reg <- memory */ { int offset = 0; rtx addr = XEXP (operands[1], 0); rtx mem_addr = eliminate_constant_term (addr, &offset); /* The stack/frame pointers are always aligned, so we can convert to the faster lw if we are referencing an aligned stack location. */ if ((offset & ~3) == 0 && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) return \"lw\\t%0,%1\"; if (TARGET_GAS) { enum rtx_code code = GET_CODE (addr); if (code == CONST || code == SYMBOL_REF || code == LABEL_REF) { operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 1); return \".set\\tnoat\\n\\tla\\t%2,%1\;ulw\\t%0,0(%2)\\n\\t.set\\tat\"; } } } return \"ulw\\t%0,%1\"; case 1: /* reg <- reg */ return \"move\\t%0,%1\"; case 2: /* reg <- integer constant */ return \"li\\t%0,%1\"; }}")(define_insn "movsi_usw" [(set (match_operand:SI 0 "memory_operand" "=&o") (match_operand:SI 1 "register_operand" "r")) (use (reg:SI 0))] "" "*{ extern rtx eliminate_constant_term (); int offset = 0; rtx addr = XEXP (operands[0], 0); rtx mem_addr = eliminate_constant_term (addr, &offset); /* The stack/frame pointers are always aligned, so we can convert to the faster sw if we are referencing an aligned stack location. At present, it is not recognized if the frame pointer is omitted. */ if ((offset & ~3) == 0 && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) return \"sw\\t%1,%0\"; if (TARGET_GAS) { enum rtx_code code = GET_CODE (XEXP (operands[0], 0)); if (code == CONST || code == SYMBOL_REF || code == LABEL_REF) { operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 1); return \".set\\tnoat\\n\\tla\\t%2,%0\;usw\\t%1,0(%2)\\n\\t.set\\tat\"; } } return \"usw\\t%1,%0\";}")(define_insn "movdi" [(set (match_operand:DI 0 "general_operand" "=r,*r,*m") (match_operand:DI 1 "general_operand" "r,*miF,*r"))] "" "*{ extern rtx adj_offsettable_operand (); extern int offsettable_address_p (); if (which_alternative == 0) { /* Move REGISTER <- REGISTER */ if (REGNO (operands[0]) != (REGNO (operands[1])+1)) return \"move\\t%0,%1\\n\\tmove\\t%D0,%D1\"; else return \"move\\t%D0,%D1\\n\\tmove\\t%0,%1\"; } else if (which_alternative == 1) { if (GET_CODE (operands[1]) == MEM) { /* REGISTER <- MEMORY */ if (offsettable_address_p (1, DImode, XEXP (operands[1], 0))) { operands[2] = adj_offsettable_operand (operands[1], 4); return \"lw\\t%0,%1\;lw\\t%D0,%2\"; } else { operands[2] = gen_rtx (REG, Pmode, 1); return \".set\\tnoat\;la\\t%2,%1\;lw\\t%0,0(%2)\;lw\\t%D0,4(%2)\;set\\tat\"; } } /* REGISTER <- small integer constant */ else if (CONSTANT_P (operands[1])) { operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) >= 0 ? 0 : -1); return \"li\\t%M0,%2\;li\\t%L0,%1\"; } /* Register <- large integer constant */ else if (GET_CODE (operands[1]) == CONST_DOUBLE) { operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[1])); operands[3] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (operands[1])); return \"li\\t%M0,%3\;li\\t%L0,%2\"; } } else if (which_alternative == 2 && GET_CODE (operands[0]) == MEM) { /* Memory <- Register */ if (offsettable_address_p (1, DImode, XEXP (operands[0], 0))) { operands[2] = adj_offsettable_operand (operands[0], 4); return \"sw\\t%1,%0\;sw\\t%D1,%2\"; } else { operands[2] = gen_rtx (REG, Pmode, 1); return \".set\\tnoat\;la\\t%2,%0\;sw\\t%1,0(%2)\;sw\\t%D1,4(%2)\;set\\tat\"; } } abort_with_insn (insn, \"impossible case in movdi\"); return \"\";}")(define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=r,r,m,r,r,m,*r") (match_operand:SI 1 "general_operand" "r,m,r,i,J,J,*p"))] "" "*{ enum rtx_code code0 = GET_CODE (operands[0]); enum rtx_code code1 = GET_CODE (operands[1]); if (code0 == REG && code1 == REG) return \"move\\t%0,%1\"; else if (code0 == REG && code1 == MEM) return \"lw\\t%0,%1\"; else if (code0 == MEM && code1 == REG) return \"sw\\t%1,%0\"; else if (code0 == REG && code1 == CONST_INT) return \"li\\t%0,%1\"; else if (code0 == MEM && code1 == CONST_INT && INTVAL (operands[1]) == 0) return \"sw\\t$0,%0\"; else if (code0 == REG && CONSTANT_P (operands[1])) return \"la\\t%0,%a1\"; else if (code0 == REG && code1 == PLUS && GET_CODE (XEXP (operands[1], 0)) == REG && GET_CODE (XEXP (operands[1], 1)) == CONST_INT) { operands[2] = XEXP (operands[1], 0); operands[3] = XEXP (operands[1], 1); return \"add%:\\t%0,%2,%3\"; } abort_with_insn (insn, \"Bad movsi\"); return 0;}")(define_insn "movhi" [(set (match_operand:HI 0 "general_operand" "=r,r,m,r,r,m") (match_operand:HI 1 "general_operand" "r,m,r,i,J,J"))] "" "*{ enum rtx_code code0 = GET_CODE (operands[0]); enum rtx_code code1 = GET_CODE (operands[1]); if (code0 == REG && code1 == REG) return \"move\\t%0,%1\"; else if (code0 == REG && code1 == MEM) return \"lh\\t%0,%1\"; else if (code0 == MEM && code1 == REG) return \"sh\\t%1,%0\"; else if (code0 == REG && code1 == CONST_INT) return \"li\\t%0,%1\"; else if (code0 == MEM && code1 == CONST_INT && INTVAL (operands[1]) == 0) return \"sh\\t$0,%0\"; else if (code0 == REG && CONSTANT_P (operands[1])) return \"la\\t%0,%a1\"; else if (code0 == REG && code1 == PLUS && GET_CODE (XEXP (operands[1], 0)) == REG && GET_CODE (XEXP (operands[1], 1)) == CONST_INT) { operands[2] = XEXP (operands[1], 0); operands[3] = XEXP (operands[1], 1); return \"add%:\\t%0,%2,%3\"; } abort_with_insn (insn, \"Bad movhi\"); return 0;}")(define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=r,r,m,r,r,m") (match_operand:QI 1 "general_operand" "r,m,r,i,J,J"))] "" "*{ enum rtx_code code0 = GET_CODE (operands[0]); enum rtx_code code1 = GET_CODE (operands[1]); if (code0 == REG && code1 == REG) return \"move\\t%0,%1\"; else if (code0 == REG && code1 == MEM) return \"lb\\t%0,%1\"; else if (code0 == MEM && code1 == REG) return \"sb\\t%1,%0\"; else if (code0 == REG && code1 == CONST_INT) return \"li\\t%0,%1\";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -