?? m68k.c
字號:
reg_names[PIC_OFFSET_TABLE_REGNUM]); asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n", reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[PIC_OFFSET_TABLE_REGNUM]);#endif }}/* Return true if this function's epilogue can be output as RTL. */intuse_return_insn (){ int regno; if (!reload_completed || frame_pointer_needed || get_frame_size () != 0) return 0; /* Copied from output_function_epilogue (). We should probably create a separate layout routine to perform the common work. */ for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) return 0; return 1;}/* This function generates the assembly code for function exit, on machines that need it. Args are same as for FUNCTION_PROLOGUE. The function epilogue should not depend on the current stack pointer! It should use the frame pointer only, if there is a frame pointer. This is mandatory because of alloca; we also take advantage of it to omit stack adjustments before returning. */voidoutput_function_epilogue (stream, size) FILE *stream; int size;{ register int regno; register int mask, fmask; register int nregs; int offset, foffset, fpoffset; extern char call_used_regs[]; int fsize = (size + 3) & -4; int big = 0; rtx insn = get_last_insn (); int restore_from_sp = 0; /* If the last insn was a BARRIER, we don't have to write any code. */ if (GET_CODE (insn) == NOTE) insn = prev_nonnote_insn (insn); if (insn && GET_CODE (insn) == BARRIER) { /* Output just a no-op so that debuggers don't get confused about which function the pc is in at this address. */ asm_fprintf (stream, "\tnop\n"); return; }#ifdef FUNCTION_BLOCK_PROFILER_EXIT if (profile_block_flag == 2) { FUNCTION_BLOCK_PROFILER_EXIT (stream); }#endif#ifdef FUNCTION_EXTRA_EPILOGUE FUNCTION_EXTRA_EPILOGUE (stream, size);#endif nregs = 0; fmask = 0; fpoffset = 0;#ifdef SUPPORT_SUN_FPA for (regno = 24 ; regno < 56 ; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) nregs++; fpoffset = nregs * 8;#endif nregs = 0; if (TARGET_68881) { for (regno = 16; regno < 24; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) { nregs++; fmask |= 1 << (23 - regno); } } foffset = fpoffset + nregs * 12; nregs = 0; mask = 0; if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; for (regno = 0; regno < 16; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) { nregs++; mask |= 1 << regno; } if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) { nregs++; mask |= 1 << PIC_OFFSET_TABLE_REGNUM; } offset = foffset + nregs * 4; /* FIXME : leaf_function_p below is too strong. What we really need to know there is if there could be pending stack adjustment needed at that point. */ restore_from_sp = ! frame_pointer_needed || (! current_function_calls_alloca && leaf_function_p ()); if (offset + fsize >= 0x8000 && ! restore_from_sp && (mask || fmask || fpoffset)) {#ifdef MOTOROLA asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra1\n", -fsize);#else asm_fprintf (stream, "\tmovel %0I%d,%Ra1\n", -fsize);#endif fsize = 0, big = 1; } if (TARGET_5200 || nregs <= 2) { /* Restore each separately in the same order moveml does. Using two movel instructions instead of a single moveml is about 15% faster for the 68020 and 68030 at no expense in code size. */ int i; /* Undo the work from above. */ for (i = 0; i< 16; i++) if (mask & (1 << i)) { if (big) {#ifdef MOTOROLA asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra1.l),%s\n", offset + fsize, reg_names[FRAME_POINTER_REGNUM], reg_names[i]);#else asm_fprintf (stream, "\tmovel %s@(-%d,%Ra1:l),%s\n", reg_names[FRAME_POINTER_REGNUM], offset + fsize, reg_names[i]);#endif } else if (restore_from_sp) {#ifdef MOTOROLA asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n", reg_names[i]);#else asm_fprintf (stream, "\tmovel %Rsp@+,%s\n", reg_names[i]);#endif } else {#ifdef MOTOROLA asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n", offset + fsize, reg_names[FRAME_POINTER_REGNUM], reg_names[i]);#else asm_fprintf (stream, "\tmovel %s@(-%d),%s\n", reg_names[FRAME_POINTER_REGNUM], offset + fsize, reg_names[i]);#endif } offset = offset - 4; } } else if (mask) { if (big) {#ifdef MOTOROLA asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n", offset + fsize, reg_names[FRAME_POINTER_REGNUM], mask);#else asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n", reg_names[FRAME_POINTER_REGNUM], offset + fsize, mask);#endif } else if (restore_from_sp) {#ifdef MOTOROLA asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);#else asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);#endif } else {#ifdef MOTOROLA asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n", offset + fsize, reg_names[FRAME_POINTER_REGNUM], mask);#else asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n", reg_names[FRAME_POINTER_REGNUM], offset + fsize, mask);#endif } } if (fmask) { if (big) {#ifdef MOTOROLA asm_fprintf (stream, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n", foffset + fsize, reg_names[FRAME_POINTER_REGNUM], fmask);#else asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n", reg_names[FRAME_POINTER_REGNUM], foffset + fsize, fmask);#endif } else if (restore_from_sp) {#ifdef MOTOROLA asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);#else asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);#endif } else {#ifdef MOTOROLA asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n", foffset + fsize, reg_names[FRAME_POINTER_REGNUM], fmask);#else asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n", reg_names[FRAME_POINTER_REGNUM], foffset + fsize, fmask);#endif } } if (fpoffset != 0) for (regno = 55; regno >= 24; regno--) if (regs_ever_live[regno] && ! call_used_regs[regno]) { if (big) {#ifdef MOTOROLA asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra1.l), %s\n", fpoffset + fsize, reg_names[FRAME_POINTER_REGNUM], reg_names[regno]);#else asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra1:l), %s\n", reg_names[FRAME_POINTER_REGNUM], fpoffset + fsize, reg_names[regno]);#endif } else if (restore_from_sp) {#ifdef MOTOROLA asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n", reg_names[regno]);#else asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n", reg_names[regno]);#endif } else {#ifdef MOTOROLA asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n", fpoffset + fsize, reg_names[FRAME_POINTER_REGNUM], reg_names[regno]);#else asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n", reg_names[FRAME_POINTER_REGNUM], fpoffset + fsize, reg_names[regno]);#endif } fpoffset -= 8; } if (frame_pointer_needed) fprintf (stream, "\tunlk %s\n", reg_names[FRAME_POINTER_REGNUM]); else if (fsize) {#ifndef NO_ADDSUB_Q if (fsize + 4 <= 8) { if (!TARGET_5200) {#ifdef MOTOROLA asm_fprintf (stream, "\taddq.w %0I%d,%Rsp\n", fsize + 4);#else asm_fprintf (stream, "\taddqw %0I%d,%Rsp\n", fsize + 4);#endif } else {#ifdef MOTOROLA asm_fprintf (stream, "\taddq.l %0I%d,%Rsp\n", fsize + 4);#else asm_fprintf (stream, "\taddql %0I%d,%Rsp\n", fsize + 4);#endif } } else if (fsize + 4 <= 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() cannot handle %. */#ifdef MOTOROLA asm_fprintf (stream, "\taddq.w %0I8,%Rsp\n\taddq.w %0I%d,%Rsp\n", fsize + 4 - 8);#else asm_fprintf (stream, "\taddqw %0I8,%Rsp\n\taddqw %0I%d,%Rsp\n", fsize + 4 - 8);#endif } else#endif /* not NO_ADDSUB_Q */ if (fsize + 4 < 0x8000) { if (TARGET_68040) { /* asm_fprintf() cannot handle %. */#ifdef MOTOROLA asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);#else asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);#endif } else {#ifdef MOTOROLA asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", fsize + 4);#else asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", fsize + 4);#endif } } else { /* asm_fprintf() cannot handle %. */#ifdef MOTOROLA asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);#else asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);#endif } } if (current_function_pops_args) asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args); else fprintf (stream, "\trts\n");}/* Similar to general_operand, but exclude stack_pointer_rtx. */intnot_sp_operand (op, mode) register rtx op; enum machine_mode mode;{ return op != stack_pointer_rtx && general_operand (op, mode);}/* 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 (x, mode) 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 non-zero if flags are currently in the 68881 flag register. */intflags_in_68881 (){ /* We could add support for these in the future */ return cc_status.flags & CC_IN_68881;}/* 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 (operands) rtx *operands;{ switch (GET_CODE (operands[3])) { case EQ:#ifdef MOTOROLA output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);#else output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);#endif break; case NE:#ifdef MOTOROLA output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);#else output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);#endif break; case GT:#ifdef MOTOROLA output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);#else output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);#endif break; case GTU:#ifdef MOTOROLA output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);#else output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);#endif break; case LT:#ifdef MOTOROLA output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);#else output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);#endif break; case LTU:#ifdef MOTOROLA output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);#else output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);#endif break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -