📄 v850.c
字号:
break; case 'S': { /* if it's a reference to a TDA variable, use sst/sld vs. st/ld */ if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), FALSE)) fputs ("s", file); break; } case 'T': { /* Like an 'S' operand above, but for unsigned loads only. */ if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), TRUE)) fputs ("s", file); break; } case 'W': /* print the instruction suffix */ switch (GET_MODE (x)) { default: abort (); case QImode: fputs (".b", file); break; case HImode: fputs (".h", file); break; case SImode: fputs (".w", file); break; case SFmode: fputs (".w", file); break; } break; case '.': /* register r0 */ fputs (reg_names[0], file); break; case 'z': /* reg or zero */ if (x == const0_rtx) fputs (reg_names[0], file); else if (GET_CODE (x) == REG) fputs (reg_names[REGNO (x)], file); else abort (); break; default: switch (GET_CODE (x)) { case MEM: if (GET_CODE (XEXP (x, 0)) == CONST_INT) output_address (gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 0), XEXP (x, 0))); else output_address (XEXP (x, 0)); break; case REG: fputs (reg_names[REGNO (x)], file); break; case SUBREG: fputs (reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)], file); break; case CONST_INT: case SYMBOL_REF: case CONST: case LABEL_REF: case CODE_LABEL: print_operand_address (file, x); break; default: abort (); } break; }}/* Output assembly language output for the address ADDR to FILE. */voidprint_operand_address (file, addr) FILE *file; rtx addr;{ switch (GET_CODE (addr)) { case REG: fprintf (file, "0["); print_operand (file, addr, 0); fprintf (file, "]"); break; case LO_SUM: if (GET_CODE (XEXP (addr, 0)) == REG) { /* reg,foo */ fprintf (file, "lo("); print_operand (file, XEXP (addr, 1), 0); fprintf (file, ")["); print_operand (file, XEXP (addr, 0), 0); fprintf (file, "]"); } break; case PLUS: if (GET_CODE (XEXP (addr, 0)) == REG || GET_CODE (XEXP (addr, 0)) == SUBREG) { /* reg,foo */ print_operand (file, XEXP (addr, 1), 0); fprintf (file, "["); print_operand (file, XEXP (addr, 0), 0); fprintf (file, "]"); } else { print_operand (file, XEXP (addr, 0), 0); fprintf (file, "+"); print_operand (file, XEXP (addr, 1), 0); } break; case SYMBOL_REF: if (ENCODED_NAME_P (XSTR (addr, 0))) { char* name = XSTR (addr, 0); char* off_name; char* reg_name; if (ZDA_NAME_P (name)) { off_name = "zdaoff"; reg_name = "r0"; } else if (SDA_NAME_P (name)) { off_name = "sdaoff"; reg_name = "gp"; } else if (TDA_NAME_P (name)) { off_name = "tdaoff"; reg_name = "ep"; } else abort (); fprintf (file, "%s(", off_name); output_addr_const (file, addr); fprintf (file, ")[%s]", reg_name); } else output_addr_const (file, addr); break; case CONST: if (special_symbolref_operand (addr, VOIDmode)) { char* name = XSTR (XEXP (XEXP (addr, 0), 0), 0); char* off_name; char* reg_name; if (ZDA_NAME_P (name)) { off_name = "zdaoff"; reg_name = "r0"; } else if (SDA_NAME_P (name)) { off_name = "sdaoff"; reg_name = "gp"; } else if (TDA_NAME_P (name)) { off_name = "tdaoff"; reg_name = "ep"; } else abort (); fprintf (file, "%s(", off_name); output_addr_const (file, addr); fprintf (file, ")[%s]", reg_name); } else output_addr_const (file, addr); break; default: output_addr_const (file, addr); break; }}/* Return appropriate code to load up a 1, 2, or 4 integer/floating point value. */char *output_move_single (operands) rtx *operands;{ rtx dst = operands[0]; rtx src = operands[1]; if (REG_P (dst)) { if (REG_P (src)) return "mov %1,%0"; else if (GET_CODE (src) == CONST_INT) { HOST_WIDE_INT value = INTVAL (src); if (CONST_OK_FOR_J (value)) /* signed 5 bit immediate */ return "mov %1,%0"; else if (CONST_OK_FOR_K (value)) /* signed 16 bit immediate */ return "movea lo(%1),%.,%0"; else if (CONST_OK_FOR_L (value)) /* upper 16 bits were set */ return "movhi hi(%1),%.,%0"; else /* random constant */ return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0"; } else if (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode) { HOST_WIDE_INT high, low; const_double_split (src, &high, &low); if (CONST_OK_FOR_J (high)) /* signed 5 bit immediate */ return "mov %F1,%0"; else if (CONST_OK_FOR_K (high)) /* signed 16 bit immediate */ return "movea lo(%F1),%.,%0"; else if (CONST_OK_FOR_L (high)) /* upper 16 bits were set */ return "movhi hi(%F1),%.,%0"; else /* random constant */ return "movhi hi(%F1),%.,%0\n\tmovea lo(%F1),%0,%0"; } else if (GET_CODE (src) == MEM) return "%S1ld%W1 %1,%0"; else if (special_symbolref_operand (src, VOIDmode)) return "movea %O1(%P1),%Q1,%0"; else if (GET_CODE (src) == LABEL_REF || GET_CODE (src) == SYMBOL_REF || GET_CODE (src) == CONST) { return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0"; } else if (GET_CODE (src) == HIGH) return "movhi hi(%1),%.,%0"; else if (GET_CODE (src) == LO_SUM) { operands[2] = XEXP (src, 0); operands[3] = XEXP (src, 1); return "movea lo(%3),%2,%0"; } } else if (GET_CODE (dst) == MEM) { if (REG_P (src)) return "%S0st%W0 %1,%0"; else if (GET_CODE (src) == CONST_INT && INTVAL (src) == 0) return "%S0st%W0 %.,%0"; else if (GET_CODE (src) == CONST_DOUBLE && CONST0_RTX (GET_MODE (dst)) == src) return "%S0st%W0 %.,%0"; } fatal_insn ("output_move_single:", gen_rtx (SET, VOIDmode, dst, src)); return "";}/* Return appropriate code to load up an 8 byte integer or floating point value */char *output_move_double (operands) rtx *operands;{ enum machine_mode mode = GET_MODE (operands[0]); rtx dst = operands[0]; rtx src = operands[1]; if (register_operand (dst, mode) && register_operand (src, mode)) { if (REGNO (src) + 1 == REGNO (dst)) return "mov %R1,%R0\n\tmov %1,%0"; else return "mov %1,%0\n\tmov %R1,%R0"; } /* Storing 0 */ if (GET_CODE (dst) == MEM && ((GET_CODE (src) == CONST_INT && INTVAL (src) == 0) || (GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src)))) return "st.w %.,%0\n\tst.w %.,%R0"; if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE) { HOST_WIDE_INT high_low[2]; int i; rtx xop[10]; if (GET_CODE (src) == CONST_DOUBLE) const_double_split (src, &high_low[1], &high_low[0]); else { high_low[0] = INTVAL (src); high_low[1] = (INTVAL (src) >= 0) ? 0 : -1; } for (i = 0; i < 2; i++) { xop[0] = gen_rtx (REG, SImode, REGNO (dst)+i); xop[1] = GEN_INT (high_low[i]); output_asm_insn (output_move_single (xop), xop); } return ""; } if (GET_CODE (src) == MEM) { int ptrreg = -1; int dreg = REGNO (dst); rtx inside = XEXP (src, 0); if (GET_CODE (inside) == REG) ptrreg = REGNO (inside); else if (GET_CODE (inside) == SUBREG) ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside); else if (GET_CODE (inside) == PLUS) ptrreg = REGNO (XEXP (inside, 0)); else if (GET_CODE (inside) == LO_SUM) ptrreg = REGNO (XEXP (inside, 0)); if (dreg == ptrreg) return "ld.w %R1,%R0\n\tld.w %1,%0"; } if (GET_CODE (src) == MEM) return "ld.w %1,%0\n\tld.w %R1,%R0"; if (GET_CODE (dst) == MEM) return "st.w %1,%0\n\tst.w %R1,%R0"; return "mov %1,%0\n\tmov %R1,%R0";}/* Return maximum offset supported for a short EP memory reference of mode MODE and signedness UNSIGNEDP. */static intep_memory_offset (mode, unsignedp) enum machine_mode mode; int ATTRIBUTE_UNUSED unsignedp;{ int max_offset = 0; switch (mode) { case QImode: max_offset = (1 << 7); break; case HImode: max_offset = (1 << 8); break; case SImode: case SFmode: max_offset = (1 << 8); break; default: break; } return max_offset;}/* Return true if OP is a valid short EP memory reference */intep_memory_operand (op, mode, unsigned_load) rtx op; enum machine_mode mode; int unsigned_load;{ rtx addr, op0, op1; int max_offset; int mask; if (GET_CODE (op) != MEM) return FALSE; max_offset = ep_memory_offset (mode, unsigned_load); mask = GET_MODE_SIZE (mode) - 1; addr = XEXP (op, 0); if (GET_CODE (addr) == CONST) addr = XEXP (addr, 0); switch (GET_CODE (addr)) { default: break; case SYMBOL_REF: return TDA_NAME_P (XSTR (addr, 0)); case REG: return REGNO (addr) == EP_REGNUM; case PLUS: op0 = XEXP (addr, 0); op1 = XEXP (addr, 1); if (GET_CODE (op1) == CONST_INT && INTVAL (op1) < max_offset && INTVAL (op1) >= 0 && (INTVAL (op1) & mask) == 0) { if (GET_CODE (op0) == REG && REGNO (op0) == EP_REGNUM) return TRUE; if (GET_CODE (op0) == SYMBOL_REF && TDA_NAME_P (XSTR (op0, 0))) return TRUE; } break; } return FALSE;}/* Return true if OP is either a register or 0 */intreg_or_0_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == CONST_INT) return INTVAL (op) == 0; else if (GET_CODE (op) == CONST_DOUBLE) return CONST_DOUBLE_OK_FOR_G (op); else return register_operand (op, mode);}/* Return true if OP is either a register or a signed five bit integer */intreg_or_int5_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == CONST_INT) return CONST_OK_FOR_J (INTVAL (op)); else return register_operand (op, mode);}/* Return true if OP is a valid call operand. */intcall_address_operand (op, mode) rtx op; enum machine_mode ATTRIBUTE_UNUSED mode;{ /* Only registers are valid call operands if TARGET_LONG_CALLS. */ if (TARGET_LONG_CALLS) return GET_CODE (op) == REG; return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);}intspecial_symbolref_operand (op, mode) rtx op; enum machine_mode ATTRIBUTE_UNUSED mode;{ if (GET_CODE (op) == SYMBOL_REF) return ENCODED_NAME_P (XSTR (op, 0)); else if (GET_CODE (op) == CONST) return (GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF && ENCODED_NAME_P (XSTR (XEXP (XEXP (op, 0), 0), 0)) && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1)))); return FALSE;}intmovsi_source_operand (op, mode) rtx op; enum machine_mode mode;{ /* Some constants, as well as symbolic operands must be done with HIGH & LO_SUM patterns. */ if (CONSTANT_P (op) && GET_CODE (op) != HIGH && GET_CODE (op) != CONSTANT_P_RTX && !(GET_CODE (op) == CONST_INT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -