📄 mips.c
字号:
sprintf (volatile_buffer, "%%{%s%%}", ret); ret = volatile_buffer; } } else if (code1 == CONST_INT || (code1 == CONST_DOUBLE && GET_MODE (op1) == VOIDmode)) { if (code1 == CONST_DOUBLE) { /* This can happen when storing constants into long long bitfields. Just store the least significant word of the value. */ operands[1] = op1 = GEN_INT (CONST_DOUBLE_LOW (op1)); } if (INTVAL (op1) == 0) { if (GP_REG_P (regno0)) ret = "move\t%0,%z1"; else if (FP_REG_P (regno0)) { delay = DELAY_LOAD; ret = "mtc1\t%z1,%0"; } else if (MD_REG_P (regno0)) { delay = DELAY_HILO; ret = "mt%0\t%."; } } else if (GP_REG_P (regno0)) ret = (INTVAL (op1) < 0) ? "li\t%0,%1\t\t\t# %X1" : "li\t%0,%X1\t\t# %1"; } else if (code1 == CONST_DOUBLE && mode == SFmode) { if (op1 == CONST0_RTX (SFmode)) { if (GP_REG_P (regno0)) ret = "move\t%0,%."; else if (FP_REG_P (regno0)) { delay = DELAY_LOAD; ret = "mtc1\t%.,%0"; } } else { delay = DELAY_LOAD; ret = "li.s\t%0,%1"; } } else if (code1 == LABEL_REF) { if (TARGET_STATS) mips_count_memory_refs (op1, 1); ret = "la\t%0,%a1"; } else if (code1 == SYMBOL_REF || code1 == CONST) { if (HALF_PIC_P () && CONSTANT_P (op1) && HALF_PIC_ADDRESS_P (op1)) { rtx offset = const0_rtx; if (GET_CODE (op1) == CONST) op1 = eliminate_constant_term (XEXP (op1, 0), &offset); if (GET_CODE (op1) == SYMBOL_REF) { operands[2] = HALF_PIC_PTR (op1); if (TARGET_STATS) mips_count_memory_refs (operands[2], 1); if (INTVAL (offset) == 0) { delay = DELAY_LOAD; ret = (unsignedp && TARGET_64BIT ? "lwu\t%0,%2" : "lw\t%0,%2"); } else { dslots_load_total++; operands[3] = offset; if (unsignedp && TARGET_64BIT) ret = (SMALL_INT (offset)) ? "lwu\t%0,%2%#\n\tadd\t%0,%0,%3" : "lwu\t%0,%2%#\n\t%[li\t%@,%3\n\tadd\t%0,%0,%@%]"; else ret = (SMALL_INT (offset)) ? "lw\t%0,%2%#\n\tadd\t%0,%0,%3" : "lw\t%0,%2%#\n\t%[li\t%@,%3\n\tadd\t%0,%0,%@%]"; } } } else { if (TARGET_STATS) mips_count_memory_refs (op1, 1); ret = "la\t%0,%a1"; } } else if (code1 == PLUS) { rtx add_op0 = XEXP (op1, 0); rtx add_op1 = XEXP (op1, 1); if (GET_CODE (XEXP (op1, 1)) == REG && GET_CODE (XEXP (op1, 0)) == CONST_INT) { add_op0 = XEXP (op1, 1); /* reverse operands */ add_op1 = XEXP (op1, 0); } operands[2] = add_op0; operands[3] = add_op1; ret = "add%:\t%0,%2,%3"; } } else if (code0 == MEM) { if (TARGET_STATS) mips_count_memory_refs (op0, 1); if (code1 == REG) { int regno1 = REGNO (op1) + subreg_word1; if (GP_REG_P (regno1)) { switch (mode) { default: break; case SFmode: ret = "sw\t%1,%0"; break; case SImode: ret = "sw\t%1,%0"; break; case HImode: ret = "sh\t%1,%0"; break; case QImode: ret = "sb\t%1,%0"; break; } } else if (FP_REG_P (regno1) && (mode == SImode || mode == SFmode)) ret = "s.s\t%1,%0"; } else if (code1 == CONST_INT && INTVAL (op1) == 0) { switch (mode) { default: break; case SFmode: ret = "sw\t%z1,%0"; break; case SImode: ret = "sw\t%z1,%0"; break; case HImode: ret = "sh\t%z1,%0"; break; case QImode: ret = "sb\t%z1,%0"; break; } } else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode)) { switch (mode) { default: break; case SFmode: ret = "sw\t%.,%0"; break; case SImode: ret = "sw\t%.,%0"; break; case HImode: ret = "sh\t%.,%0"; break; case QImode: ret = "sb\t%.,%0"; break; } } if (ret != (char *)0 && MEM_VOLATILE_P (op0)) { int i = strlen (ret); if (i > sizeof (volatile_buffer) - sizeof ("%{%}")) abort (); sprintf (volatile_buffer, "%%{%s%%}", ret); ret = volatile_buffer; } } if (ret == (char *)0) { abort_with_insn (insn, "Bad move"); return 0; } if (delay != DELAY_NONE) return mips_fill_delay_slot (ret, delay, operands, insn); return ret;}/* Return the appropriate instructions to move 2 words */char *mips_move_2words (operands, insn) rtx operands[]; rtx insn;{ char *ret = 0; rtx op0 = operands[0]; rtx op1 = operands[1]; enum rtx_code code0 = GET_CODE (operands[0]); enum rtx_code code1 = GET_CODE (operands[1]); int subreg_word0 = 0; int subreg_word1 = 0; enum delay_type delay = DELAY_NONE; while (code0 == SUBREG) { subreg_word0 += SUBREG_WORD (op0); op0 = SUBREG_REG (op0); code0 = GET_CODE (op0); } while (code1 == SUBREG) { subreg_word1 += SUBREG_WORD (op1); op1 = SUBREG_REG (op1); code1 = GET_CODE (op1); } if (code0 == REG) { int regno0 = REGNO (op0) + subreg_word0; if (code1 == REG) { int regno1 = REGNO (op1) + subreg_word1; /* Just in case, don't do anything for assigning a register to itself, unless we are filling a delay slot. */ if (regno0 == regno1 && set_nomacro == 0) ret = ""; else if (FP_REG_P (regno0)) { if (FP_REG_P (regno1)) ret = "mov.d\t%0,%1"; else { delay = DELAY_LOAD; if (TARGET_FLOAT64) { if (!TARGET_64BIT) abort_with_insn (insn, "Bad move");#ifdef TARGET_FP_CALL_32 if (FP_CALL_GP_REG_P (regno1)) ret = "dsll\t%1,32\n\tor\t%1,%D1\n\tdmtc1\t%1,%0"; else#endif ret = "dmtc1\t%1,%0"; } else ret = "mtc1\t%L1,%0\n\tmtc1\t%M1,%D0"; } } else if (FP_REG_P (regno1)) { delay = DELAY_LOAD; if (TARGET_FLOAT64) { if (!TARGET_64BIT) abort_with_insn (insn, "Bad move");#ifdef TARGET_FP_CALL_32 if (FP_CALL_GP_REG_P (regno0)) ret = "dmfc1\t%0,%1\n\tmfc1\t%D0,%1\n\tdsrl\t%0,32"; else#endif ret = "dmfc1\t%0,%1"; } else ret = "mfc1\t%L0,%1\n\tmfc1\t%M0,%D1"; } else if (MD_REG_P (regno0) && GP_REG_P (regno1)) { delay = DELAY_HILO; if (TARGET_64BIT) { if (regno0 != HILO_REGNUM) ret = "mt%0\t%1"; else if (regno1 == 0) ret = "mtlo\t%.\n\tmthi\t%."; } else ret = "mthi\t%M1\n\tmtlo\t%L1"; } else if (GP_REG_P (regno0) && MD_REG_P (regno1)) { delay = DELAY_HILO; if (TARGET_64BIT) { if (regno1 != HILO_REGNUM) ret = "mf%1\t%0"; } else ret = "mfhi\t%M0\n\tmflo\t%L0"; } else if (TARGET_64BIT) ret = "move\t%0,%1"; else if (regno0 != (regno1+1)) ret = "move\t%0,%1\n\tmove\t%D0,%D1"; else ret = "move\t%D0,%D1\n\tmove\t%0,%1"; } else if (code1 == CONST_DOUBLE) { /* Move zero from $0 unless !TARGET_64BIT and recipient is 64-bit fp reg, in which case generate a constant. */ if (op1 != CONST0_RTX (GET_MODE (op1)) || (TARGET_FLOAT64 && !TARGET_64BIT && FP_REG_P (regno0))) { if (GET_MODE (op1) == DFmode) { delay = DELAY_LOAD;#ifdef TARGET_FP_CALL_32 if (FP_CALL_GP_REG_P (regno0)) { if (TARGET_FLOAT64 && !TARGET_64BIT) { split_double (op1, operands + 2, operands + 3); ret = "li\t%0,%2\n\tli\t%D0,%3"; } else ret = "li.d\t%0,%1\n\tdsll\t%D0,%0,32\n\tdsrl\t%D0,32\n\tdsrl\t%0,32"; } else#endif ret = "li.d\t%0,%1"; } else if (TARGET_64BIT) ret = "dli\t%0,%1"; else { split_double (op1, operands + 2, operands + 3); ret = "li\t%0,%2\n\tli\t%D0,%3"; } } else { if (GP_REG_P (regno0)) ret = (TARGET_64BIT#ifdef TARGET_FP_CALL_32 && ! FP_CALL_GP_REG_P (regno0)#endif ) ? "move\t%0,%." : "move\t%0,%.\n\tmove\t%D0,%."; else if (FP_REG_P (regno0)) { delay = DELAY_LOAD; ret = (TARGET_64BIT) ? "dmtc1\t%.,%0" : "mtc1\t%.,%0\n\tmtc1\t%.,%D0"; } } } else if (code1 == CONST_INT && INTVAL (op1) == 0) { if (GP_REG_P (regno0)) ret = (TARGET_64BIT) ? "move\t%0,%." : "move\t%0,%.\n\tmove\t%D0,%."; else if (FP_REG_P (regno0)) { delay = DELAY_LOAD; ret = (TARGET_64BIT) ? "dmtc1\t%.,%0" : (TARGET_FLOAT64 ? "li.d\t%0,%1" : "mtc1\t%.,%0\n\tmtc1\t%.,%D0"); } else if (MD_REG_P (regno0)) { delay = DELAY_HILO; if (regno0 != HILO_REGNUM) ret = "mt%0\t%.\n"; else ret = "mtlo\t%.\n\tmthi\t%."; } } else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0)) { if (TARGET_64BIT) { if (HOST_BITS_PER_WIDE_INT < 64) /* We can't use 'X' for negative numbers, because then we won't get the right value for the upper 32 bits. */ ret = ((INTVAL (op1) < 0) ? "dli\t%0,%1\t\t\t# %X1" : "dli\t%0,%X1\t\t# %1"); else /* We must use 'X', because otherwise LONG_MIN will print as a number that the assembler won't accept. */ ret = "dli\t%0,%X1\t\t# %1"; } else { operands[2] = GEN_INT (INTVAL (operands[1]) >= 0 ? 0 : -1); ret = "li\t%M0,%2\n\tli\t%L0,%1"; } } else if (code1 == MEM) { delay = DELAY_LOAD; if (TARGET_STATS) mips_count_memory_refs (op1, 2); if (FP_REG_P (regno0)) ret = "l.d\t%0,%1"; else if (TARGET_64BIT) {#ifdef TARGET_FP_CALL_32 if (FP_CALL_GP_REG_P (regno0)) { if (offsettable_address_p (FALSE, SImode, op1)) ret = "lwu\t%0,%1\n\tlwu\t%D0,4+%1"; else ret = "ld\t%0,%1\n\tdsll\t%D0,%0,32\n\tdsrl\t%D0,32\n\tdsrl\t%0,32"; } else#endif ret = "ld\t%0,%1"; } else if (offsettable_address_p (1, DFmode, XEXP (op1, 0))) { operands[2] = adj_offsettable_operand (op1, 4); if (reg_mentioned_p (op0, op1)) ret = "lw\t%D0,%2\n\tlw\t%0,%1"; else ret = "lw\t%0,%1\n\tlw\t%D0,%2"; } if (ret != (char *)0 && MEM_VOLATILE_P (op1)) { int i = strlen (ret); if (i > sizeof (volatile_buffer) - sizeof ("%{%}")) abort (); sprintf (volatile_buffer, "%%{%s%%}", ret); ret = volatile_buffer; } } else if (code1 == LABEL_REF || code1 == SYMBOL_REF || code1 == CONST) { if (TARGET_STATS) mips_count_memory_refs (op1, 2); ret = "dla\t%0,%a1"; } } else if (code0 == MEM) { if (code1 == REG) { int regno1 = REGNO (op1) + subreg_word1; if (FP_REG_P (regno1)) ret = "s.d\t%1,%0"; else if (TARGET_64BIT) {#ifdef TARGET_FP_CALL_32 if (FP_CALL_GP_REG_P (regno1)) ret = "dsll\t%1,32\n\tor\t%1,%D1\n\tsd\t%1,%0"; else#endif ret = "sd\t%1,%0"; } else if (offsettable_address_p (1, DFmode, XEXP (op0, 0))) { operands[2] = adj_offsettable_operand (op0, 4); ret = "sw\t%1,%0\n\tsw\t%D1,%2"; } } else if (((code1 == CONST_INT && INTVAL (op1) == 0) || (code1 == CONST_DOUBLE && op1 == CONST0_RTX (GET_MODE (op1)))) && (TARGET_64BIT || offsettable_address_p (1, DFmode, XEXP (op0, 0)))) { if (TARGET_64BIT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -