📄 h8300.c
字号:
pragma_saveall = 0;}/* Output assembly code for the start of the file. */asm_file_start (file) FILE *file;{ fprintf (file, ";\tGCC For the Hitachi H8/300\n"); fprintf (file, ";\tBy Hitachi America Ltd and Cygnus Support\n"); fprintf (file, ";\trelease F-1\n"); if (optimize) fprintf (file, "; -O%d\n", optimize); if (TARGET_H8300H) fprintf (file, "\n\t.h8300h\n"); else if (TARGET_H8300S) fprintf (file, "\n\t.h8300s\n"); else fprintf (file, "\n\n"); output_file_directive (file, main_input_filename);}/* Output assembly language code for the end of file. */voidasm_file_end (file) FILE *file;{ fprintf (file, "\t.end\n");}/* Return true if VALUE is a valid constant for constraint 'P'. IE: VALUE is a power of two <= 2**15. */intsmall_power_of_two (value) int value;{ switch (value) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: case 256: case 512: case 1024: case 2048: case 4096: case 8192: case 16384: case 32768: return 1; } return 0;}/* Return true if VALUE is a valid constant for constraint 'O', which means that the constant would be ok to use as a bit for a bclr instruction. */intok_for_bclr (value) int value;{ return small_power_of_two ((~value) & 0xff);}/* Return true is OP is a valid source operand for an integer move instruction. */intgeneral_operand_src (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC) return 1; return general_operand (op, mode);}/* Return true if OP is a valid destination operand for an integer move instruction. */intgeneral_operand_dst (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == PRE_DEC) return 1; return general_operand (op, mode);}/* Return true if OP is a const valid for a bit clear instruction. */into_operand (operand, mode) rtx operand; enum machine_mode mode;{ return (GET_CODE (operand) == CONST_INT && CONST_OK_FOR_O (INTVAL (operand)));}/* Return true if OP is a const valid for a bit set or bit xor instruction. */intp_operand (operand, mode) rtx operand; enum machine_mode mode;{ return (GET_CODE (operand) == CONST_INT && CONST_OK_FOR_P (INTVAL (operand)));}/* Return true if OP is a valid call operand. */intcall_insn_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == MEM) { rtx inside = XEXP (op, 0); if (register_operand (inside, Pmode)) return 1; if (CONSTANT_ADDRESS_P (inside)) return 1; } return 0;}intadds_subs_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == CONST_INT) { if (INTVAL (op) <= 4 && INTVAL (op) >= 0) return 1; if (INTVAL (op) >= -4 && INTVAL (op) <= 0) return 1; if ((TARGET_H8300H || TARGET_H8300S) && INTVAL (op) != 7 && (INTVAL (op) <= 8 && INTVAL (op) >= 0)) return 1; if ((TARGET_H8300H || TARGET_H8300S) && INTVAL (op) != -7 && (INTVAL (op) >= -8 && INTVAL (op) <= 0)) return 1; } return 0;}/* Return nonzero if op is an adds/subs operand which only requires one insn to implement. It is assumed that OP is already an adds/subs operand. */intone_insn_adds_subs_operand (op, mode) rtx op; enum machine_mode mode;{ int val = INTVAL (op); if (val == 1 || val == -1 || val == 2 || val == -2 || ((TARGET_H8300H || TARGET_H8300S) && (val == 4 || val == -4))) return 1; return 0;}char *output_adds_subs (operands) rtx *operands;{ int val = INTVAL (operands[2]); /* First get the value into the range -4..4 inclusive. The only way it can be out of this range is when TARGET_H8300H or TARGET_H8300S is true, thus it is safe to use adds #4 and subs #4. */ if (val > 4) { output_asm_insn ("adds #4,%A0", operands); val -= 4; } if (val < -4) { output_asm_insn ("subs #4,%A0", operands); val += 4; } /* Handle case were val == 4 or val == -4 and we're compiling for TARGET_H8300H or TARGET_H8300S. */ if ((TARGET_H8300H || TARGET_H8300S) && val == 4) return "adds #4,%A0"; if ((TARGET_H8300H || TARGET_H8300S) && val == -4) return "subs #4,%A0"; if (val > 2) { output_asm_insn ("adds #2,%A0", operands); val -= 2; } if (val < -2) { output_asm_insn ("subs #2,%A0", operands); val += 2; } /* val should be one or two now. */ if (val == 2) return "adds #2,%A0"; if (val == -2) return "subs #2,%A0"; /* val should be one now. */ if (val == 1) return "adds #1,%A0"; if (val == -1) return "subs #1,%A0"; /* If not optimizing, we might be asked to add 0. */ if (val == 0) return ""; /* In theory, this can't happen. */ abort ();}/* Return true if OP is a valid call operand, and OP represents an operand for a small call (4 bytes instead of 6 bytes). */intsmall_call_insn_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == MEM) { rtx inside = XEXP (op, 0); /* Register indirect is a small call. */ if (register_operand (inside, Pmode)) return 1; /* A call through the function vector is a small call too. */ if (GET_CODE (inside) == SYMBOL_REF && SYMBOL_REF_FLAG (inside)) return 1; } /* Otherwise it's a large call. */ return 0;}/* Return true if OP is a valid jump operand. */intjump_address_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == REG) return mode == Pmode; if (GET_CODE (op) == MEM) { rtx inside = XEXP (op, 0); if (register_operand (inside, Pmode)) return 1; if (CONSTANT_ADDRESS_P (inside)) return 1; } return 0;}/* Recognize valid operands for bitfield instructions. */extern int rtx_equal_function_value_matters;intbit_operand (op, mode) rtx op; enum machine_mode mode;{ /* We can except any general operand, expept that MEM operands must be limited to those that use addresses valid for the 'U' constraint. */ if (!general_operand (op, mode)) return 0; /* Accept any mem during RTL generation. Otherwise, the code that does insv and extzv will think that we can not handle memory. However, to avoid reload problems, we only accept 'U' MEM operands after RTL generation. This means that any named pattern which uses this predicate must force its operands to match 'U' before emitting RTL. */ if (GET_CODE (op) == REG) return 1; if (GET_CODE (op) == SUBREG) return 1; if (!rtx_equal_function_value_matters) { /* We're building rtl */ return GET_CODE (op) == MEM; } else { return (GET_CODE (op) == MEM && EXTRA_CONSTRAINT (op, 'U')); }}intbit_memory_operand (op, mode) rtx op; enum machine_mode mode;{ return (GET_CODE (op) == MEM && EXTRA_CONSTRAINT (op, 'U'));}/* Recognize valid operators for bit test. */inteq_operator (x, mode) rtx x; enum machine_mode mode;{ return (GET_CODE (x) == EQ || GET_CODE (x) == NE);}/* Handle machine specific pragmas for compatibility with existing compilers for the H8/300. pragma saveall generates prolog/epilog code which saves and restores all the registers on function entry. pragma interrupt saves and restores all registers, and exits with an rte instruction rather than an rts. A pointer to a function with this attribute may be safely used in an interrupt vector. */inthandle_pragma (p_getc, p_ungetc, pname) int (* p_getc) PROTO ((void)); void (* p_ungetc) PROTO ((int)); char * pname;{ int retval = 0; if (strcmp (pname, "interrupt") == 0) interrupt_handler = retval = 1; else if (strcmp (pname, "saveall") == 0) pragma_saveall = retval = 1; return retval;}/* If the next arg with MODE and TYPE is to be passed in a register, return the rtx to represent where it is passed. CUM represents the state after the last argument. NAMED is not used. */static char *hand_list[] ={ "__main", "__cmpsi2", "__divhi3", "__modhi3", "__udivhi3", "__umodhi3", "__divsi3", "__modsi3", "__udivsi3", "__umodsi3", "__mulhi3", "__mulsi3", "__reg_memcpy", "__reg_memset", "__ucmpsi2", 0,};/* Return an RTX to represent where a value with mode MODE will be returned from a function. If the result is 0, the argument is pushed. */rtxfunction_arg (cum, mode, type, named) CUMULATIVE_ARGS *cum; enum machine_mode mode; tree type; int named;{ rtx result = 0; char *fname; int regpass = 0; /* Never pass unnamed arguments in registers. */ if (!named) return 0; /* Pass 3 regs worth of data in regs when user asked on the command line. */ if (TARGET_QUICKCALL) regpass = 3; /* If calling hand written assembler, use 4 regs of args. */ if (cum->libcall) { char **p; fname = XSTR (cum->libcall, 0); /* See if this libcall is one of the hand coded ones. */ for (p = hand_list; *p && strcmp (*p, fname) != 0; p++) ; if (*p) regpass = 4; } if (regpass) { int size; if (mode == BLKmode) size = int_size_in_bytes (type); else size = GET_MODE_SIZE (mode); if (size + cum->nbytes > regpass * UNITS_PER_WORD) { result = 0; } else { switch (cum->nbytes / UNITS_PER_WORD) { case 0: result = gen_rtx (REG, mode, 0); break; case 1: result = gen_rtx (REG, mode, 1); break; case 2: result = gen_rtx (REG, mode, 2); break; case 3: result = gen_rtx (REG, mode, 3); break; default: result = 0; } } } return result;}/* Return the cost of the rtx R with code CODE. */intconst_costs (r, c) rtx r; enum rtx_code c;{ switch (c) { case CONST_INT: switch (INTVAL (r)) { case 0: case 1: case 2: case -1: case -2: return 0; case 4: case -4: if (TARGET_H8300H || TARGET_H8300S) return 0; else return 1; default: return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -