?? m68k.c
字號:
case GE:#ifdef MOTOROLA output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);#else output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);#endif break; case GEU:#ifdef MOTOROLA output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);#else output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);#endif break; case LE:#ifdef MOTOROLA output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);#else output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);#endif break; case LEU:#ifdef MOTOROLA output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);#else output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);#endif break; default: abort (); } /* 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:#ifdef MOTOROLA output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);#else output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);#endif break; case HImode: break; default: abort (); }}char *output_scc_di(op, operand1, operand2, dest) rtx op; rtx operand1; rtx operand2; rtx dest;{ rtx loperands[7]; enum rtx_code op_code = GET_CODE (op); /* This does not produce a usefull 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] = adj_offsettable_operand (operand1, 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] = adj_offsettable_operand (operand2, 4); } loperands[4] = gen_label_rtx(); if (operand2 != const0_rtx) {#ifdef MOTOROLA#ifdef SGS_CMP_ORDER output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);#else output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);#endif#else#ifdef SGS_CMP_ORDER output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);#else output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);#endif#endif } else { if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[0])) output_asm_insn ("tst%.l %0", loperands); else {#ifdef SGS_CMP_ORDER output_asm_insn ("cmp%.w %0,%#0", loperands);#else output_asm_insn ("cmp%.w %#0,%0", loperands);#endif }#ifdef MOTOROLA output_asm_insn ("jbne %l4", loperands);#else output_asm_insn ("jne %l4", loperands);#endif if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[1])) output_asm_insn ("tst%.l %1", loperands); else {#ifdef SGS_CMP_ORDER output_asm_insn ("cmp%.w %1,%#0", loperands);#else output_asm_insn ("cmp%.w %#0,%1", loperands);#endif } } loperands[5] = dest; switch (op_code) { case EQ: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("seq %5", loperands); break; case NE: ASM_OUTPUT_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();#ifdef MOTOROLA output_asm_insn ("shi %5\n\tjbra %l6", loperands);#else output_asm_insn ("shi %5\n\tjra %l6", loperands);#endif ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("sgt %5", loperands); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[6])); break; case GTU: ASM_OUTPUT_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();#ifdef MOTOROLA output_asm_insn ("scs %5\n\tjbra %l6", loperands);#else output_asm_insn ("scs %5\n\tjra %l6", loperands);#endif ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("slt %5", loperands); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[6])); break; case LTU: ASM_OUTPUT_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();#ifdef MOTOROLA output_asm_insn ("scc %5\n\tjbra %l6", loperands);#else output_asm_insn ("scc %5\n\tjra %l6", loperands);#endif ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("sge %5", loperands); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[6])); break; case GEU: ASM_OUTPUT_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();#ifdef MOTOROLA output_asm_insn ("sls %5\n\tjbra %l6", loperands);#else output_asm_insn ("sls %5\n\tjra %l6", loperands);#endif ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("sle %5", loperands); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[6])); break; case LEU: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (loperands[4])); output_asm_insn ("sls %5", loperands); break; default: abort (); } return "";}char *output_btst (operands, countop, dataop, insn, signpos) rtx *operands; rtx countop, dataop; rtx insn; int signpos;{ operands[0] = countop; operands[1] = dataop; if (GET_CODE (countop) == CONST_INT) { register int count = INTVAL (countop); /* If COUNT is bigger than size of storage unit in use, advance to the containing unit of same size. */ if (count > signpos) { int offset = (count & ~signpos) / 8; count = count & signpos; operands[1] = dataop = adj_offsettable_operand (dataop, offset); } if (count == signpos) cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N; else cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N; /* These three statements used to use next_insns_test_no... but it appears that this should do the same job. */ if (count == 31 && next_insn_tests_no_inequality (insn)) return "tst%.l %1"; if (count == 15 && next_insn_tests_no_inequality (insn)) return "tst%.w %1"; if (count == 7 && next_insn_tests_no_inequality (insn)) return "tst%.b %1"; cc_status.flags = CC_NOT_NEGATIVE; } return "btst %0,%1";}/* Returns 1 if OP is either a symbol reference or a sum of a symbol reference and a constant. */intsymbolic_operand (op, mode) register rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ switch (GET_CODE (op)) { case SYMBOL_REF: case LABEL_REF: return 1; case CONST: op = XEXP (op, 0); return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF) && GET_CODE (XEXP (op, 1)) == CONST_INT);#if 0 /* Deleted, with corresponding change in m68k.h, so as to fit the specs. No CONST_DOUBLE is ever symbolic. */ case CONST_DOUBLE: return GET_MODE (op) == mode;#endif default: return 0; }}/* Check for sign_extend or zero_extend. Used for bit-count operands. */intextend_operator(x, mode) rtx x; enum machine_mode mode;{ if (mode != VOIDmode && GET_MODE(x) != mode) return 0; switch (GET_CODE(x)) { case SIGN_EXTEND : case ZERO_EXTEND : return 1; default : return 0; }}/* Legitimize PIC addresses. If the address is already position-independent, we return ORIG. Newly generated position-independent addresses go to REG. If we need more than one register, we lose. An address is legitimized by making an indirect reference through the Global Offset Table with the name of the symbol used as an offset. The assembler and linker are responsible for placing the address of the symbol in the GOT. The function prologue is responsible for initializing a5 to the starting address of the GOT. The assembler is also responsible for translating a symbol name into a constant displacement from the start of the GOT. A quick example may make things a little clearer: When not generating PIC code to store the value 12345 into _foo we would generate the following code: movel #12345, _foo When generating PIC two transformations are made. First, the compiler loads the address of foo into a register. So the first transformation makes: lea _foo, a0 movel #12345, a0@ The code in movsi will intercept the lea instruction and call this routine which will transform the instructions into: movel a5@(_foo:w), a0 movel #12345, a0@ That (in a nutshell) is how *all* symbol and label references are handled. */rtxlegitimize_pic_address (orig, mode, reg) rtx orig, reg; enum machine_mode mode ATTRIBUTE_UNUSED;{ rtx pic_ref = orig; /* First handle a simple SYMBOL_REF or LABEL_REF */ if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) { if (reg == 0) abort (); pic_ref = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, pic_offset_table_rtx, orig)); current_function_uses_pic_offset_table = 1; if (reload_in_progress) regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; RTX_UNCHANGING_P (pic_ref) = 1; emit_move_insn (reg, pic_ref); return reg; } else if (GET_CODE (orig) == CONST) { rtx base; /* Make sure this is CONST has not already been legitimized */ if (GET_CODE (XEXP (orig, 0)) == PLUS && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) return orig; if (reg == 0) abort (); /* legitimize both operands of the PLUS */ if (GET_CODE (XEXP (orig, 0)) == PLUS) { base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, base == reg ? 0 : reg); } else abort (); if (GET_CODE (orig) == CONST_INT) return plus_constant_for_output (base, INTVAL (orig)); pic_ref = gen_rtx_PLUS (Pmode, base, orig); /* Likewise, should we set special REG_NOTEs here? */ } return pic_ref;}typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;#define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)CONST_METHODconst_method (constant) rtx constant;{ int i; unsigned u; i = INTVAL (constant); if (USE_MOVQ (i)) return MOVQ; /* The Coldfire doesn't have byte or word operations. */ /* FIXME: This may not be useful for the m68060 either */ if (!TARGET_5200) { /* if -256 < N < 256 but N is not in range for a moveq N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */ if (USE_MOVQ (i ^ 0xff)) return NOTB; /* Likewise, try with not.w */ if (USE_MOVQ (i ^ 0xffff)) return NOTW; /* This is the only value where neg.w is useful */ if (i == -65408) return NEGW; /* Try also with swap */ u = i; if (USE_MOVQ ((u >> 16) | (u << 16))) return SWAP; } /* Otherwise, use move.l */ return MOVL;}intconst_int_cost (constant) rtx constant;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -