📄 m68k.md
字号:
/* clr insns on 68000 read before writing. This isn't so on the 68010, but we have no alternative for it. */ && (TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))) return \"clr%.w %0\"; else if (DATA_REG_P (operands[0]) && INTVAL (operands[1]) < 128 && INTVAL (operands[1]) >= -128) {#if defined(MOTOROLA) && !defined(CRDS) return \"moveq%.l %1,%0\";#else return \"moveq %1,%0\";#endif } else if (INTVAL (operands[1]) < 0x8000 && INTVAL (operands[1]) >= -0x8000) return \"move%.w %1,%0\"; } else if (CONSTANT_P (operands[1])) return \"move%.l %1,%0\";#ifndef SGS_NO_LI /* Recognize the insn before a tablejump, one that refers to a table of offsets. Such an insn will need to refer to a label on the insn. So output one. Use the label-number of the table of offsets to generate this label. */ if (GET_CODE (operands[1]) == MEM && GET_CODE (XEXP (operands[1], 0)) == PLUS && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF || GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF) && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) != PLUS) { rtx labelref; if (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF) labelref = XEXP (XEXP (operands[1], 0), 0); else labelref = XEXP (XEXP (operands[1], 0), 1);#if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)#ifdef SGS asm_fprintf (asm_out_file, \"\\tset %LLI%d,.+2\\n\", CODE_LABEL_NUMBER (XEXP (labelref, 0)));#else /* not SGS */ asm_fprintf (asm_out_file, \"\\t.set %LLI%d,.+2\\n\", CODE_LABEL_NUMBER (XEXP (labelref, 0)));#endif /* not SGS */#else /* SGS_SWITCH_TABLES or not MOTOROLA */ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\", CODE_LABEL_NUMBER (XEXP (labelref, 0)));#ifdef SGS_SWITCH_TABLES /* Set flag saying we need to define the symbol LD%n (with value L%n-LI%n) at the end of the switch table. */ switch_table_difference_label_flag = 1;#endif /* SGS_SWITCH_TABLES */#endif /* SGS_SWITCH_TABLES or not MOTOROLA */ }#endif /* SGS_NO_LI */ return \"move%.w %1,%0\";}")(define_insn "movstricthi" [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) (match_operand:HI 1 "general_operand" "rmn"))] "" "*{ if (GET_CODE (operands[1]) == CONST_INT) { if (operands[1] == const0_rtx && (DATA_REG_P (operands[0]) || GET_CODE (operands[0]) == MEM) /* clr insns on 68000 read before writing. This isn't so on the 68010, but we have no alternative for it. */ && (TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))) return \"clr%.w %0\"; } return \"move%.w %1,%0\";}")(define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=d,*a,m,m,?*a") (match_operand:QI 1 "general_operand" "dmi*a,d*a,dmi,?*a,m"))] "" "*{ rtx xoperands[4]; /* This is probably useless, since it loses for pushing a struct of several bytes a byte at a time. */ if (GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx) { xoperands[1] = operands[1]; xoperands[2] = gen_rtx (MEM, QImode, gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx)); /* Just pushing a byte puts it in the high byte of the halfword. */ /* We must put it in the low-order, high-numbered byte. */ output_asm_insn (\"move%.b %1,%-\;move%.b %@,%2\", xoperands); return \"\"; } /* HACK Alert. This is a quick fix while RMS makes up his mind about what he wants to do about this case. */ /* if d0 is used in the address calculation, use d1 */ if (refers_to_regno_p (0, 1, PATTERN (insn), NULL_PTR)) { /* Moving a byte into an address register is not possible. */ /* Use d1 as an intermediate, but don't clobber its contents. */ if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM) return \"exg %/d1,%0\;move%.b %1,%/d1\;exg %/d1,%0\"; /* Likewise for moving from an address reg. */ if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM) return \"exg %/d1,%1\;move%.b %/d1,%0\;exg %/d1,%1\"; } else { /* Moving a byte into an address register is not possible. */ /* Use d0 as an intermediate, but don't clobber its contents. */ if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM) return \"exg %/d0,%0\;move%.b %1,%/d0\;exg %/d0,%0\"; /* Likewise for moving from an address reg. */ if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM) return \"exg %/d0,%1\;move%.b %/d0,%0\;exg %/d0,%1\"; } /* clr and st insns on 68000 read before writing. This isn't so on the 68010, but we have no alternative for it. */ if (TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { if (operands[1] == const0_rtx) return \"clr%.b %0\"; if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == -1) { CC_STATUS_INIT; return \"st %0\"; } } if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1])) return \"move%.l %1,%0\"; if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1])) return \"move%.w %1,%0\"; return \"move%.b %1,%0\";}")(define_insn "movstrictqi" [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) (match_operand:QI 1 "general_operand" "dmn"))] "" "*{ if (operands[1] == const0_rtx /* clr insns on 68000 read before writing. This isn't so on the 68010, but we have no alternative for it. */ && (TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))) return \"clr%.b %0\"; return \"move%.b %1,%0\";}")(define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=rmf,x,y,rm,!x,!rm") (match_operand:SF 1 "general_operand" "rmfF,xH,rmF,y,rm,x"))]; [(set (match_operand:SF 0 "general_operand" "=rmf"); (match_operand:SF 1 "general_operand" "rmfF"))] "" "*{ if (which_alternative >= 4) return \"fpmove%.s %1,fpa0\;fpmove%.s fpa0,%0\"; if (FPA_REG_P (operands[0])) { if (FPA_REG_P (operands[1])) return \"fpmove%.s %x1,%x0\"; else if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_single (operands); else if (FP_REG_P (operands[1])) return \"fmove%.s %1,sp@-\;fpmove%.d sp@+, %0\"; return \"fpmove%.s %x1,%x0\"; } if (FPA_REG_P (operands[1])) { if (FP_REG_P (operands[0])) return \"fpmove%.s %x1,sp@-\;fmove%.s sp@+,%0\"; else return \"fpmove%.s %x1,%x0\"; } if (FP_REG_P (operands[0])) { if (FP_REG_P (operands[1])) return \"f%$move%.x %1,%0\"; else if (ADDRESS_REG_P (operands[1])) return \"move%.l %1,%-\;f%$move%.s %+,%0\"; else if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_single (operands); return \"f%$move%.s %f1,%0\"; } if (FP_REG_P (operands[1])) { if (ADDRESS_REG_P (operands[0])) return \"fmove%.s %1,%-\;move%.l %+,%0\"; return \"fmove%.s %f1,%0\"; } return \"move%.l %1,%0\";}")(define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>,y,rm,x,!x,!rm") (match_operand:DF 1 "general_operand" "rf,m,rofE<>,rmE,y,xH,rm,x"))]; [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>"); (match_operand:DF 1 "general_operand" "rf,m,rofF<>"))] "" "*{ if (which_alternative == 6) return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\"; if (FPA_REG_P (operands[0])) { if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_double (operands); if (FP_REG_P (operands[1])) return \"fmove%.d %1,sp@-\;fpmove%.d sp@+,%x0\"; return \"fpmove%.d %x1,%x0\"; } else if (FPA_REG_P (operands[1])) { if (FP_REG_P(operands[0])) return \"fpmove%.d %x1,sp@-\;fmoved sp@+,%0\"; else return \"fpmove%.d %x1,%x0\"; } if (FP_REG_P (operands[0])) { if (FP_REG_P (operands[1])) return \"f%&move%.x %1,%0\"; if (REG_P (operands[1])) { rtx xoperands[2]; xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); output_asm_insn (\"move%.l %1,%-\", xoperands); output_asm_insn (\"move%.l %1,%-\", operands); return \"f%&move%.d %+,%0\"; } if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_double (operands); return \"f%&move%.d %f1,%0\"; } else if (FP_REG_P (operands[1])) { if (REG_P (operands[0])) { output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands); operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); return \"move%.l %+,%0\"; } else return \"fmove%.d %f1,%0\"; } return output_move_double (operands);}");; movdi can apply to fp regs in some cases(define_insn "movdi" ;; Let's see if it really still needs to handle fp regs, and, if so, why. [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,y,rm,!*x,!rm") (match_operand:DI 1 "general_operand" "rF,m,roi<>F,rmiF,y,rmF,*x"))]; [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,!&rm,!&f,y,rm,x,!x,!rm"); (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfmF,rmi,y,rm,x"))]; [(set (match_operand:DI 0 "general_operand" "=rm,&rf,&ro<>,!&rm,!&f"); (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfF"))] "" "*{ if (which_alternative == 8) return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\"; if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1])) return \"fpmove%.d %x1,%x0\"; if (FP_REG_P (operands[0])) { if (FP_REG_P (operands[1])) return \"fmove%.x %1,%0\"; if (REG_P (operands[1])) { rtx xoperands[2]; xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); output_asm_insn (\"move%.l %1,%-\", xoperands); output_asm_insn (\"move%.l %1,%-\", operands); return \"fmove%.d %+,%0\"; } if (GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_double (operands); return \"fmove%.d %f1,%0\"; } else if (FP_REG_P (operands[1])) { if (REG_P (operands[0])) { output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands); operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); return \"move%.l %+,%0\"; } else return \"fmove%.d %f1,%0\"; } return output_move_double (operands);}");; Thus goes after the move instructions;; because the move instructions are better (require no spilling);; when they can apply. It goes before the add/sub insns;; so we will prefer it to them.(define_insn "pushasi" [(set (match_operand:SI 0 "push_operand" "=m") (match_operand:SI 1 "address_operand" "p"))] "" "pea %a1");; truncation instructions(define_insn "truncsiqi2" [(set (match_operand:QI 0 "general_operand" "=dm,d") (truncate:QI (match_operand:SI 1 "general_operand" "doJ,i")))] "" "*{ if (GET_CODE (operands[0]) == REG) { /* Must clear condition codes, since the move.l bases them on the entire 32 bits, not just the desired 8 bits. */ CC_STATUS_INIT; return \"move%.l %1,%0\"; } if (GET_CODE (operands[1]) == MEM) operands[1] = adj_offsettable_operand (operands[1], 3); return \"move%.b %1,%0\";}")(define_insn "trunchiqi2" [(set (match_operand:QI 0 "general_operand" "=dm,d") (truncate:QI (match_operand:HI 1 "general_operand" "doJ,i")))] "" "*{ if (GET_CODE (operands[0]) == REG && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[1]) == CONST_INT)) { /* Must clear condition codes, since the move.w bases them on the entire 16 bits, not just the desired 8 bits. */ CC_STATUS_INIT; return \"move%.w %1,%0\"; } if (GET_CODE (operands[0]) == REG) { /* Must clear condition codes, since the move.l bases them on the entire 32 bits, not just the desired 8 bits. */ CC_STATUS_INIT; return \"move%.l %1,%0\"; } if (GET_CODE (operands[1]) == MEM) operands[1] = adj_offsettable_operand (operands[1], 1); return \"move%.b %1,%0\";}")(define_insn "truncsihi2" [(set (match_operand:HI 0 "general_operand" "=dm,d") (truncate:HI (match_operand:SI 1 "general_operand" "roJ,i")))] "" "*{ if (GET_CODE (operands[0]) == REG) { /* Must clear condition codes, since the move.l bases them on the entire 32 bits, not just the desired 8 bits. */ CC_STATUS_INIT; return \"move%.l %1,%0\"; } if (GET_CODE (operands[1]) == MEM) operands[1] = adj_offsettable_operand (operands[1], 2); return \"move%.w %1,%0\";}");; zero extension instructions(define_expand "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "") (const_int 0)) (set (strict_low_part (match_dup 2)) (match_operand:HI 1 "general_operand" ""))] "" "{ operands[1] = make_safe_from (operands[1], operands[0]); if (GET_CODE (operands[0]) == SUBREG) operands[2] = gen_rtx (SUBREG, HImode, SUBREG_REG (operands[0]), SUBREG_WORD (operands[0])); else operands[2] = gen_rtx (SUBREG, HImode, operands[0], 0);}")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -