📄 m68k.c
字号:
{ if (MOTOROLA) asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n", current_frame.offset + fsize, M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.reg_mask); else asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n", M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.offset + fsize, current_frame.reg_mask); } } else /* !TARGET_COLDFIRE */ { if (big) { if (MOTOROLA) asm_fprintf (stream, "\tmovm.l -%wd(%s,%Ra1.l),%I0x%x\n", current_frame.offset + fsize, M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.reg_mask); else asm_fprintf (stream, "\tmoveml %s@(-%wd,%Ra1:l),%I0x%x\n", M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.offset + fsize, current_frame.reg_mask); } else if (restore_from_sp) { asm_fprintf (stream, MOTOROLA ? "\tmovm.l (%Rsp)+,%I0x%x\n" : "\tmoveml %Rsp@+,%I0x%x\n", current_frame.reg_mask); } else { if (MOTOROLA) asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n", current_frame.offset + fsize, M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.reg_mask); else asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n", M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.offset + fsize, current_frame.reg_mask); } } } if (current_frame.fpu_rev_mask) { if (big) { if (MOTOROLA) asm_fprintf (stream, "\tfmovm -%wd(%s,%Ra1.l),%I0x%x\n", current_frame.foffset + fsize, M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.fpu_rev_mask); else asm_fprintf (stream, "\tfmovem %s@(-%wd,%Ra1:l),%I0x%x\n", M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.foffset + fsize, current_frame.fpu_rev_mask); } else if (restore_from_sp) { if (MOTOROLA) asm_fprintf (stream, "\tfmovm (%Rsp)+,%I0x%x\n", current_frame.fpu_rev_mask); else asm_fprintf (stream, "\tfmovem %Rsp@+,%I0x%x\n", current_frame.fpu_rev_mask); } else { if (MOTOROLA) asm_fprintf (stream, "\tfmovm -%wd(%s),%I0x%x\n", current_frame.foffset + fsize, M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.fpu_rev_mask); else asm_fprintf (stream, "\tfmovem %s@(-%wd),%I0x%x\n", M68K_REGNAME(FRAME_POINTER_REGNUM), current_frame.foffset + fsize, current_frame.fpu_rev_mask); } } if (frame_pointer_needed) fprintf (stream, "\tunlk %s\n", M68K_REGNAME(FRAME_POINTER_REGNUM)); else if (fsize_with_regs) { if (fsize_with_regs <= 8) { if (!TARGET_COLDFIRE) asm_fprintf (stream, "\taddq" ASM_DOT "w %I%wd,%Rsp\n", fsize_with_regs); else asm_fprintf (stream, "\taddq" ASM_DOT "l %I%wd,%Rsp\n", fsize_with_regs); } else if (fsize_with_regs <= 16 && TARGET_CPU32) { /* On the CPU32 it is faster to use two addqw instructions to add a small integer (8 < N <= 16) to a register. */ asm_fprintf (stream, "\taddq" ASM_DOT "w %I8,%Rsp\n" "\taddq" ASM_DOT "w %I%wd,%Rsp\n", fsize_with_regs - 8); } else if (fsize_with_regs < 0x8000) { if (TARGET_68040) asm_fprintf (stream, "\tadd" ASM_DOT "w %I%wd,%Rsp\n", fsize_with_regs); else asm_fprintf (stream, MOTOROLA ? "\tlea (%wd,%Rsp),%Rsp\n" : "\tlea %Rsp@(%wd),%Rsp\n", fsize_with_regs); } else asm_fprintf (stream, "\tadd" ASM_DOT "l %I%wd,%Rsp\n", fsize_with_regs); } if (current_function_calls_eh_return) asm_fprintf (stream, "\tadd" ASM_DOT"l %Ra0,%Rsp\n"); if (m68k_interrupt_function_p (current_function_decl)) fprintf (stream, "\trte\n"); else if (current_function_pops_args) asm_fprintf (stream, "\trtd %I%d\n", current_function_pops_args); else fprintf (stream, "\trts\n");}/* Return true if X is a valid comparison operator for the dbcc instruction. Note it rejects floating point comparison operators. (In the future we could use Fdbcc). It also rejects some comparisons when CC_NO_OVERFLOW is set. */ intvalid_dbcc_comparison_p_2 (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){ switch (GET_CODE (x)) { case EQ: case NE: case GTU: case LTU: case GEU: case LEU: return 1; /* Reject some when CC_NO_OVERFLOW is set. This may be over conservative */ case GT: case LT: case GE: case LE: return ! (cc_prev_status.flags & CC_NO_OVERFLOW); default: return 0; }}/* Return nonzero if flags are currently in the 68881 flag register. */intflags_in_68881 (void){ /* We could add support for these in the future */ return cc_status.flags & CC_IN_68881;}/* Output a BSR instruction suitable for PIC code. */voidm68k_output_pic_call(rtx dest){ const char *out; if (!(GET_CODE (dest) == MEM && GET_CODE (XEXP (dest, 0)) == SYMBOL_REF)) out = "jsr %0"; /* We output a BSR instruction if we're building for a target that supports long branches. Otherwise we generate one of two sequences: a shorter one that uses a GOT entry or a longer one that doesn't. We use the -Os command-line flag to decide which to generate. Both sequences take the same time to execute on the ColdFire. */ else if (TARGET_PCREL) out = "bsr.l %o0"; else if (TARGET_68020)#if defined(USE_GAS) out = "bsr.l %0@PLTPC";#else out = "bsr %0@PLTPC";#endif else if (optimize_size || TARGET_ID_SHARED_LIBRARY) out = "move.l %0@GOT(%%a5), %%a1\n\tjsr (%%a1)"; else out = "lea %0-.-8,%%a1\n\tjsr 0(%%pc,%%a1)"; output_asm_insn(out, &dest);}/* Output a dbCC; jCC sequence. Note we do not handle the floating point version of this sequence (Fdbcc). We also do not handle alternative conditions when CC_NO_OVERFLOW is set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will kick those out before we get here. */voidoutput_dbcc_and_branch (rtx *operands){ switch (GET_CODE (operands[3])) { case EQ: output_asm_insn (MOTOROLA ? "dbeq %0,%l1\n\tjbeq %l2" : "dbeq %0,%l1\n\tjeq %l2", operands); break; case NE: output_asm_insn (MOTOROLA ? "dbne %0,%l1\n\tjbne %l2" : "dbne %0,%l1\n\tjne %l2", operands); break; case GT: output_asm_insn (MOTOROLA ? "dbgt %0,%l1\n\tjbgt %l2" : "dbgt %0,%l1\n\tjgt %l2", operands); break; case GTU: output_asm_insn (MOTOROLA ? "dbhi %0,%l1\n\tjbhi %l2" : "dbhi %0,%l1\n\tjhi %l2", operands); break; case LT: output_asm_insn (MOTOROLA ? "dblt %0,%l1\n\tjblt %l2" : "dblt %0,%l1\n\tjlt %l2", operands); break; case LTU: output_asm_insn (MOTOROLA ? "dbcs %0,%l1\n\tjbcs %l2" : "dbcs %0,%l1\n\tjcs %l2", operands); break; case GE: output_asm_insn (MOTOROLA ? "dbge %0,%l1\n\tjbge %l2" : "dbge %0,%l1\n\tjge %l2", operands); break; case GEU: output_asm_insn (MOTOROLA ? "dbcc %0,%l1\n\tjbcc %l2" : "dbcc %0,%l1\n\tjcc %l2", operands); break; case LE: output_asm_insn (MOTOROLA ? "dble %0,%l1\n\tjble %l2" : "dble %0,%l1\n\tjle %l2", operands); break; case LEU: output_asm_insn (MOTOROLA ? "dbls %0,%l1\n\tjbls %l2" : "dbls %0,%l1\n\tjls %l2", operands); break; default: gcc_unreachable (); } /* If the decrement is to be done in SImode, then we have to compensate for the fact that dbcc decrements in HImode. */ switch (GET_MODE (operands[0])) { case SImode: output_asm_insn (MOTOROLA ? "clr%.w %0\n\tsubq%.l #1,%0\n\tjbpl %l1" : "clr%.w %0\n\tsubq%.l #1,%0\n\tjpl %l1", operands); break; case HImode: break; default: gcc_unreachable (); }}const char *output_scc_di (rtx op, rtx operand1, rtx operand2, rtx dest){ rtx loperands[7]; enum rtx_code op_code = GET_CODE (op); /* This does not produce a useful cc. */ CC_STATUS_INIT; /* The m68k cmp.l instruction requires operand1 to be a reg as used below. Swap the operands and change the op if these requirements are not fulfilled. */ if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG) { rtx tmp = operand1; operand1 = operand2; operand2 = tmp; op_code = swap_condition (op_code); } loperands[0] = operand1; if (GET_CODE (operand1) == REG) loperands[1] = gen_rtx_REG (SImode, REGNO (operand1) + 1); else loperands[1] = adjust_address (operand1, SImode, 4); if (operand2 != const0_rtx) { loperands[2] = operand2; if (GET_CODE (operand2) == REG) loperands[3] = gen_rtx_REG (SImode, REGNO (operand2) + 1); else loperands[3] = adjust_address (operand2, SImode, 4); } loperands[4] = gen_label_rtx (); if (operand2 != const0_rtx) { output_asm_insn (MOTOROLA ? "cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1" : "cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands); } else { if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (loperands[0])) output_asm_insn ("tst%.l %0", loperands); else { output_asm_insn ("cmp%.w #0,%0", loperands); } output_asm_insn (MOTOROLA ? "jbne %l4" : "jne %l4", loperands); if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (loperands[1])) output_asm_insn ("tst%.l %1", loperands); else output_asm_insn ("cmp%.w #0,%1", loperands); } loperands[5] = dest; switch (op_code) { case EQ: (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("seq %5", loperands); break; case NE: (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("sne %5", loperands); break; case GT: loperands[6] = gen_label_rtx (); output_asm_insn (MOTOROLA ? "shi %5\n\tjbra %l6" : "shi %5\n\tjra %l6", loperands); (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("sgt %5", loperands); (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[6])); break; case GTU: (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("shi %5", loperands); break; case LT: loperands[6] = gen_label_rtx (); output_asm_insn (MOTOROLA ? "scs %5\n\tjbra %l6" : "scs %5\n\tjra %l6", loperands); (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("slt %5", loperands); (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[6])); break; case LTU: (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("scs %5", loperands); break; case GE: loperands[6] = gen_label_rtx (); output_asm_insn (MOTOROLA ? "scc %5\n\tjbra %l6" : "scc %5\n\tjra %l6", loperands); (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("sge %5", loperands); (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[6])); break; case GEU: (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("scc %5", loperands); break; case LE: loperands[6] = gen_label_rtx (); output_asm_insn (MOTOROLA ? "sls %5\n\tjbra %l6" : "sls %5\n\tjra %l6", loperands);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -