📄 h8300.c
字号:
#else /* ... or is it asm ("mov.b %0l,r2l", ...) */ fprintf (file, "%s", names_big[REGNO (x)]);#endif break; case HImode: fprintf (file, "%s", names_big[REGNO (x)]); break; case SImode: case SFmode: fprintf (file, "%s", names_extended[REGNO (x)]); break; default: abort (); } break; case MEM: { rtx addr = XEXP (x, 0); fprintf (file, "@"); output_address (addr); /* We fall back from smaller addressing to larger addressing in various ways depending on CODE. */ switch (code) { case 'R': /* Used for mov.b and bit operations. */ if (h8300_eightbit_constant_address_p (addr)) { fprintf (file, ":8"); break; } /* Fall through. We should not get here if we are processing bit operations on H8/300 or H8/300H because 'U' constraint does not allow bit operations on the tiny area on these machines. */ case 'T': case 'S': /* Used for mov.w and mov.l. */ if (h8300_tiny_constant_address_p (addr)) fprintf (file, ":16"); break; default: break; } } break; case CONST_INT: case SYMBOL_REF: case CONST: case LABEL_REF: fprintf (file, "#"); print_operand_address (file, x); break; case CONST_DOUBLE: { long val; REAL_VALUE_TYPE rv; REAL_VALUE_FROM_CONST_DOUBLE (rv, x); REAL_VALUE_TO_TARGET_SINGLE (rv, val); fprintf (file, "#%ld", val); break; } default: 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, "%s", h8_reg_names[REGNO (addr)]); break; case PRE_DEC: fprintf (file, "-%s", h8_reg_names[REGNO (XEXP (addr, 0))]); break; case POST_INC: fprintf (file, "%s+", h8_reg_names[REGNO (XEXP (addr, 0))]); break; case PLUS: fprintf (file, "("); if (GET_CODE (XEXP (addr, 0)) == REG) { /* reg,foo */ print_operand_address (file, XEXP (addr, 1)); fprintf (file, ","); print_operand_address (file, XEXP (addr, 0)); } else { /* foo+k */ print_operand_address (file, XEXP (addr, 0)); fprintf (file, "+"); print_operand_address (file, XEXP (addr, 1)); } fprintf (file, ")"); break; case CONST_INT: { /* Since the H8/300 only has 16 bit pointers, negative values are also those >= 32768. This happens for example with pointer minus a constant. We don't want to turn (char *p - 2) into (char *p + 65534) because loop unrolling can build upon this (IE: char *p + 131068). */ int n = INTVAL (addr); if (TARGET_H8300) n = (int) (short) n; if (n < 0) /* ??? Why the special case for -ve values? */ fprintf (file, "-%d", -n); else fprintf (file, "%d", n); break; } default: output_addr_const (file, addr); break; }}/* Output all insn addresses and their sizes into the assembly language output file. This is helpful for debugging whether the length attributes in the md file are correct. This is not meant to be a user selectable option. */voidfinal_prescan_insn (insn, operand, num_operands) rtx insn, *operand ATTRIBUTE_UNUSED; int num_operands ATTRIBUTE_UNUSED;{ /* This holds the last insn address. */ static int last_insn_address = 0; int uid = INSN_UID (insn); if (TARGET_RTL_DUMP) { fprintf (asm_out_file, "\n****************"); print_rtl (asm_out_file, PATTERN (insn)); fprintf (asm_out_file, "\n"); } if (TARGET_ADDRESSES) { fprintf (asm_out_file, "; 0x%x %d\n", INSN_ADDRESSES (uid), INSN_ADDRESSES (uid) - last_insn_address); last_insn_address = INSN_ADDRESSES (uid); }}/* Prepare for an SI sized move. */intdo_movsi (operands) rtx operands[];{ rtx src = operands[1]; rtx dst = operands[0]; if (!reload_in_progress && !reload_completed) { if (!register_operand (dst, GET_MODE (dst))) { rtx tmp = gen_reg_rtx (GET_MODE (dst)); emit_move_insn (tmp, src); operands[1] = tmp; } } return 0;}/* Function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET). Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */inth8300_initial_elimination_offset (from, to) int from, to;{ int offset = 0; /* The number of bytes that the return address takes on the stack. */ int pc_size = POINTER_SIZE / BITS_PER_UNIT; if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) offset = pc_size + frame_pointer_needed * UNITS_PER_WORD; else if (from == RETURN_ADDRESS_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) offset = frame_pointer_needed * UNITS_PER_WORD; else { int regno; for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (WORD_REG_USED (regno)) offset += UNITS_PER_WORD; /* See the comments for get_frame_size. We need to round it up to STACK_BOUNDARY. */ offset += round_frame_size (get_frame_size ()); if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) /* Skip saved PC. */ offset += pc_size; } return offset;}rtxh8300_return_addr_rtx (count, frame) int count; rtx frame;{ rtx ret; if (count == 0) ret = gen_rtx_MEM (Pmode, gen_rtx_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM)); else if (flag_omit_frame_pointer) return (rtx) 0; else ret = gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (frame, UNITS_PER_WORD))); set_mem_alias_set (ret, get_frame_alias_set ()); return ret;}/* Update the condition code from the insn. */voidnotice_update_cc (body, insn) rtx body; rtx insn;{ rtx set; switch (get_attr_cc (insn)) { case CC_NONE: /* Insn does not affect CC at all. */ break; case CC_NONE_0HIT: /* Insn does not change CC, but the 0'th operand has been changed. */ if (cc_status.value1 != 0 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1)) cc_status.value1 = 0; if (cc_status.value2 != 0 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value2)) cc_status.value2 = 0; break; case CC_SET_ZN: /* Insn sets the Z,N flags of CC to recog_data.operand[0]. The V flag is unusable. The C flag may or may not be known but that's ok because alter_cond will change tests to use EQ/NE. */ CC_STATUS_INIT; cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY; set = single_set (insn); cc_status.value1 = SET_SRC (set); if (SET_DEST (set) != cc0_rtx) cc_status.value2 = SET_DEST (set); break; case CC_SET_ZNV: /* Insn sets the Z,N,V flags of CC to recog_data.operand[0]. The C flag may or may not be known but that's ok because alter_cond will change tests to use EQ/NE. */ CC_STATUS_INIT; cc_status.flags |= CC_NO_CARRY; set = single_set (insn); cc_status.value1 = SET_SRC (set); if (SET_DEST (set) != cc0_rtx) cc_status.value2 = SET_DEST (set); break; case CC_COMPARE: /* The insn is a compare instruction. */ CC_STATUS_INIT; cc_status.value1 = SET_SRC (body); break; case CC_CLOBBER: /* Insn doesn't leave CC in a usable state. */ CC_STATUS_INIT; break; }}/* Return nonzero if X is a stack pointer. */intstack_pointer_operand (x, mode) rtx x; enum machine_mode mode ATTRIBUTE_UNUSED;{ return x == stack_pointer_rtx;}/* Return nonzero if X is a constant whose absolute value is greater than 2. */intconst_int_gt_2_operand (x, mode) rtx x; enum machine_mode mode ATTRIBUTE_UNUSED;{ return (GET_CODE (x) == CONST_INT && abs (INTVAL (x)) > 2);}/* Return nonzero if X is a constant whose absolute value is no smaller than 8. */intconst_int_ge_8_operand (x, mode) rtx x; enum machine_mode mode ATTRIBUTE_UNUSED;{ return (GET_CODE (x) == CONST_INT && abs (INTVAL (x)) >= 8);}/* Recognize valid operators for bit instructions. */intbit_operator (x, mode) rtx x; enum machine_mode mode ATTRIBUTE_UNUSED;{ enum rtx_code code = GET_CODE (x); return (code == XOR || code == AND || code == IOR);}const char *output_logical_op (mode, operands) enum machine_mode mode; rtx *operands;{ /* Figure out the logical op that we need to perform. */ enum rtx_code code = GET_CODE (operands[3]); /* Pretend that every byte is affected if both operands are registers. */ unsigned HOST_WIDE_INT intval = (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT) ? INTVAL (operands[2]) : 0x55555555); /* The determinant of the algorithm. If we perform an AND, 0 affects a bit. Otherwise, 1 affects a bit. */ unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval; /* The name of an insn. */ const char *opname; char insn_buf[100]; switch (code) { case AND: opname = "and"; break; case IOR: opname = "or"; break; case XOR: opname = "xor"; break; default: abort (); } switch (mode) { case HImode: /* First, see if we can finish with one insn. */ if ((TARGET_H8300H || TARGET_H8300S) && ((det & 0x00ff) != 0) && ((det & 0xff00) != 0)) { sprintf (insn_buf, "%s.w\t%%T2,%%T0", opname); output_asm_insn (insn_buf, operands); } else { /* Take care of the lower byte. */ if ((det & 0x00ff) != 0) { sprintf (insn_buf, "%s\t%%s2,%%s0", opname); output_asm_insn (insn_buf, operands); } /* Take care of the upper byte. */ if ((det & 0xff00) != 0) { sprintf (insn_buf, "%s\t%%t2,%%t0", opname); output_asm_insn (insn_buf, operands); } } break; case SImode: /* First, see if we can finish with one insn. If code is either AND or XOR, we exclude two special cases, 0xffffff00 and 0xffff00ff, because insns like sub.w or not.w can do a better job. */ if ((TARGET_H8300H || TARGET_H8300S) && ((det & 0x0000ffff) != 0) && ((det & 0xffff0000) != 0) && (code == IOR || det != 0xffffff00) && (code == IOR || det != 0xffff00ff)) { sprintf (insn_buf, "%s.l\t%%S2,%%S0", opname); output_asm_insn (insn_buf, operands); } else { /* Take care of the lower and upper words individually. For each word, we try different methods in the order of 1) the special insn (in case of AND or XOR), 2) the word-wise insn, and 3) The byte-wise insn. */ if ((det & 0x0000ffff) == 0x0000ffff && (TARGET_H8300 ? (code == AND) : (code != IOR))) output_asm_insn ((code == AND) ? "sub.w\t%f0,%f0" : "not.w\t%f0", operands); else if ((TARGET_H8300H || TARGET_H8300S) && ((det & 0x000000ff) != 0) && ((det & 0x0000ff00) != 0)) { sprintf (insn_buf, "%s.w\t%%f2,%%f0", opname); output_asm_insn (insn_buf, operands); } else { if ((det & 0x000000ff) != 0) { sprintf (insn_buf, "%s\t%%w2,%%w0", opname); output_asm_insn (insn_buf, operands); } if ((det & 0x0000ff00) != 0) { sprintf (insn_buf, "%s\t%%x2,%%x0", opname); output_asm_insn (insn_buf, operands); } } if ((det & 0xffff0000) == 0xffff0000 && (TARGET_H8300 ? (code == AND) : (code != IOR))) output_asm_insn ((code == AND) ? "sub.w\t%e0,%e0" : "not.w\t%e0", operands); else if (TARGET_H8300H || TARGET_H8300S) { if ((det & 0xffff0000) != 0) { sprintf (insn_buf, "%s.w\t%%e2,%%e0", opname); output_asm_insn (insn_buf, operands); } } else { if ((det & 0x00ff0000) != 0) { sprintf (insn_buf, "%s\t%%y2,%%y0", opname); output_asm_insn (insn_buf, operands); } if ((det & 0xff000000) != 0) { sprintf (insn_buf, "%s\t%%z2,%%z0", opname); output_asm_insn (insn_buf, operands); } } } break; default: abort (); } return "";}unsigned intcompute_logical_op_length (mode, operands) enum machine_mode mode; rtx *operands;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -