📄 i370.h
字号:
rtx x0 = XEXP (X, 0); \ rtx x1 = XEXP (X, 1); \ if (GET_CODE (x0) == PLUS) \ { \ COUNT_REGS (XEXP (x0, 0), regs, FAIL); \ COUNT_REGS (XEXP (x0, 1), regs, FAIL); \ COUNT_REGS (x1, regs, FAIL); \ if (regs == 2) \ goto ADDR; \ } \ else if (GET_CODE (x1) == PLUS) \ { \ COUNT_REGS (x0, regs, FAIL); \ COUNT_REGS (XEXP (x1, 0), regs, FAIL); \ COUNT_REGS (XEXP (x1, 1), regs, FAIL); \ if (regs == 2) \ goto ADDR; \ } \ else \ { \ COUNT_REGS (x0, regs, FAIL); \ COUNT_REGS (x1, regs, FAIL); \ if (regs != 0) \ goto ADDR; \ } \ } \ FAIL: ; \}/* The 370 has no mode dependent addresses. */#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)/* Macro: LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. This macro is used in only one place: `memory_address' in explow.c. Several comments: (1) It's not obvious that this macro results in better code than its omission does. For historical reasons we leave it in. (2) This macro may be (???) implicated in the accidental promotion or RS operand to RX operands, which bombs out any RS, SI, SS instruction that was expecting a simple address. Note that this occurs fairly rarely ... (3) There is a bug somewhere that causes either r4 to be spilled, or causes r0 to be used as a base register. Changeing the macro below will make the bug move around, but will not make it go away ... Note that this is a rare bug ... */#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \{ \ if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ (X) = gen_rtx_PLUS (SImode, XEXP (X, 0), \ copy_to_mode_reg (SImode, XEXP (X, 1))); \ if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \ (X) = gen_rtx_PLUS (SImode, XEXP (X, 1), \ copy_to_mode_reg (SImode, XEXP (X, 0))); \ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \ (X) = gen_rtx_PLUS (SImode, XEXP (X, 1), \ force_operand (XEXP (X, 0), 0)); \ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \ (X) = gen_rtx_PLUS (SImode, XEXP (X, 0), \ force_operand (XEXP (X, 1), 0)); \ if (memory_address_p (MODE, X)) \ goto WIN; \}/* Specify the machine mode that this machine uses for the index in the tablejump instruction. */#define CASE_VECTOR_MODE SImode/* Define this if the tablejump instruction expects the table to contain offsets from the address of the table. Do not define this if the table should contain absolute addresses. *//* #define CASE_VECTOR_PC_RELATIVE *//* Define this if fixuns_trunc is the same as fix_trunc. */#define FIXUNS_TRUNC_LIKE_FIX_TRUNC/* We use "unsigned char" as default. */#define DEFAULT_SIGNED_CHAR 0/* Max number of bytes we can move from memory to memory in one reasonably fast instruction. */#define MOVE_MAX 256/* Nonzero if access to memory by bytes is slow and undesirable. */#define SLOW_BYTE_ACCESS 1/* Define if shifts truncate the shift count which implies one can omit a sign-extension or zero-extension of a shift count. *//* #define SHIFT_COUNT_TRUNCATED *//* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits is done just by pretending it is already truncated. */#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) (OUTPREC != 16)/* We assume that the store-condition-codes instructions store 0 for false and some other value for true. This is the value stored for true. *//* #define STORE_FLAG_VALUE (-1) *//* When a prototype says `char' or `short', really pass an `int'. */#define PROMOTE_PROTOTYPES 1/* Don't perform CSE on function addresses. */#define NO_FUNCTION_CSE/* Specify the machine mode that pointers have. After generation of rtl, the compiler makes no further distinction between pointers and any other objects of this machine mode. */#define Pmode SImode/* A function address in a call instruction is a byte address (for indexing purposes) so give the MEM rtx a byte's mode. */#define FUNCTION_MODE QImode/* Compute the cost of computing a constant rtl expression RTX whose rtx-code is CODE. The body of this macro is a portion of a switch statement. If the code is computed here, return it with a return statement. Otherwise, break from the switch. */#define CONST_COSTS(RTX, CODE, OUTERCODE) \ case CONST_INT: \ if ((unsigned) INTVAL (RTX) < 0xfff) return 1; \ case CONST: \ case LABEL_REF: \ case SYMBOL_REF: \ return 2; \ case CONST_DOUBLE: \ return 4;/* A C statement (sans semicolon) to update the integer variable COST based on the relationship between INSN that is dependent on DEP_INSN through the dependence LINK. The default is to make no adjustment to COST. This can be used for example to specify to the scheduler that an output- or anti-dependence does not incur the same cost as a data-dependence. We will want to use this to indicate that there is a cost associated with the loading, followed by use of base registers ... #define ADJUST_COST (INSN, LINK, DEP_INSN, COST) *//* Tell final.c how to eliminate redundant test instructions. *//* Here we define machine-dependent flags and fields in cc_status (see `conditions.h'). *//* Store in cc_status the expressions that the condition codes will describe after execution of an instruction whose pattern is EXP. Do not alter them if the instruction would not alter the cc's. On the 370, load insns do not alter the cc's. However, in some cases these instructions can make it possibly invalid to use the saved cc's. In those cases we clear out some or all of the saved cc's so they won't be used. Note that only some arith instructions set the CC. These include add, subtract, complement, various shifts. Note that multiply and divide do *not* set set the CC. Therefore, in the code below, don't set the status for MUL, DIV, etc. Note that the bitwise ops set the condition code, but not in a way that we can make use of it. So we treat these as clobbering, rather than setting the CC. These are clobbered in the individual instruction patterns that use them. Use CC_STATUS_INIT to clobber.*/#define NOTICE_UPDATE_CC(EXP, INSN) \{ \ rtx exp = (EXP); \ if (GET_CODE (exp) == PARALLEL) /* Check this */ \ exp = XVECEXP (exp, 0, 0); \ if (GET_CODE (exp) != SET) \ CC_STATUS_INIT; \ else \ { \ if (XEXP (exp, 0) == cc0_rtx) \ { \ cc_status.value1 = XEXP (exp, 0); \ cc_status.value2 = XEXP (exp, 1); \ cc_status.flags = 0; \ } \ else \ { \ if (cc_status.value1 \ && reg_mentioned_p (XEXP (exp, 0), cc_status.value1)) \ cc_status.value1 = 0; \ if (cc_status.value2 \ && reg_mentioned_p (XEXP (exp, 0), cc_status.value2)) \ cc_status.value2 = 0; \ switch (GET_CODE (XEXP (exp, 1))) \ { \ case PLUS: case MINUS: case NEG: \ case NOT: case ABS: \ CC_STATUS_SET (XEXP (exp, 0), XEXP (exp, 1)); \ \ /* mult and div don't set any cc codes !! */ \ case MULT: /* case UMULT: */ case DIV: case UDIV: \ /* and, or and xor set the cc's the wrong way !! */ \ case AND: case IOR: case XOR: \ /* some shifts set the CC some don't. */ \ case ASHIFT: case ASHIFTRT: \ do {} while (0); \ default: \ break; \ } \ } \ } \}#define CC_STATUS_SET(V1, V2) \{ \ cc_status.flags = 0; \ cc_status.value1 = (V1); \ cc_status.value2 = (V2); \ if (cc_status.value1 \ && reg_mentioned_p (cc_status.value1, cc_status.value2)) \ cc_status.value2 = 0; \}#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \{ if (cc_status.flags & CC_NO_OVERFLOW) return NO_OV; return NORMAL; }/* ------------------------------------------ *//* Control the assembler format that we output. *//* Define standard character escape sequences for non-ASCII targets only. */#ifdef TARGET_EBCDIC#define TARGET_ESC 39#define TARGET_BELL 47#define TARGET_BS 22#define TARGET_TAB 5#define TARGET_NEWLINE 21#define TARGET_VT 11#define TARGET_FF 12#define TARGET_CR 13#endif/* ======================================================== */#ifdef TARGET_HLASM#define TEXT_SECTION_ASM_OP "* Program text area"#define DATA_SECTION_ASM_OP "* Program data area"#define INIT_SECTION_ASM_OP "* Program initialization area"#define SHARED_SECTION_ASM_OP "* Program shared data"#define CTOR_LIST_BEGIN /* NO OP */#define CTOR_LIST_END /* NO OP */#define MAX_MVS_LABEL_SIZE 8/* How to refer to registers in assembler output. This sequence is indexed by compiler's hard-register-number (see above). */#define REGISTER_NAMES \{ "0", "1", "2", "3", "4", "5", "6", "7", \ "8", "9", "10", "11", "12", "13", "14", "15", \ "0", "2", "4", "6" \}#define ASM_FILE_START(FILE) \{ fputs ("\tRMODE\tANY\n", FILE); \ fputs ("\tCSECT\n", FILE); }#define ASM_FILE_END(FILE) fputs ("\tEND\n", FILE);#define ASM_COMMENT_START "*"#define ASM_APP_OFF ""#define ASM_APP_ON ""#define ASM_OUTPUT_LABEL(FILE, NAME) \{ assemble_name (FILE, NAME); fputs ("\tEQU\t*\n", FILE); }#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \{ \ char temp[MAX_MVS_LABEL_SIZE + 1]; \ if (mvs_check_alias (NAME, temp) == 2) \ { \ fprintf (FILE, "%s\tALIAS\tC'%s'\n", temp, NAME); \ } \}/* MVS externals are limited to 8 characters, upper case only. The '_' is mapped to '@', except for MVS functions, then '#'. */#define ASM_OUTPUT_LABELREF(FILE, NAME) \{ \ char *bp, ch, temp[MAX_MVS_LABEL_SIZE + 1]; \ if (!mvs_get_alias (NAME, temp)) \ strcpy (temp, NAME); \ if (!strcmp (temp,"main")) \ strcpy (temp,"gccmain"); \ if (mvs_function_check (temp)) \ ch = '#'; \ else \ ch = '@'; \ for (bp = temp; *bp; bp++) \ *bp = (*bp == '_' ? ch : TOUPPER (*bp)); \ fprintf (FILE, "%s", temp); \}#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ sprintf (LABEL, "*%s%d", PREFIX, NUM)/* Generate internal label. Since we can branch here from off page, we must reload the base register. */#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \{ \ if (!strcmp (PREFIX,"L")) \ { \ mvs_add_label(NUM); \ } \ fprintf (FILE, "%s%d\tEQU\t*\n", PREFIX, NUM); \}/* Generate case label. For HLASM we can change to the data CSECT and put the vectors out of the code body. The assembler just concatenates CSECTs with the same name. */#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \ fprintf (FILE, "\tDS\t0F\n"); \ fprintf (FILE,"\tCSECT\n"); \ fprintf (FILE, "%s%d\tEQU\t*\n", PREFIX, NUM)/* Put the CSECT back to the code body */#define ASM_OUTPUT_CASE_END(FILE, NUM, TABLE) \ assemble_name (FILE, mvs_function_name); \ fputs ("\tCSECT\n", FILE);/* This is how to output an element of a case-vector that is absolute. */#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ fprintf (FILE, "\tDC\tA(L%d)\n", VALUE)/* This is how to output an element of a case-vector that is relative. */#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\tDC\tA(L%d-L%d)\n", VALUE, REL)/* This is how to output an insn to push a register on the stack. It need not be very fast code. Right now, PUSH & POP are used only when profiling is enabled, and then, only to push the static chain reg and the function struct value reg, and only if those are used. Since profiling is not supported anyway, punt on this. */#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \ mvs_check_page (FILE, 8, 4); \ fprintf (FILE, "\tS\t13,=F'4'\n\tST\t%s,%d(13)\n", \ reg_names[REGNO], STACK_POINTER_OFFSET)/* This is how to output an insn to pop a register from the stack. It need not be very fast code. */#define ASM_OUTPUT_REG_POP(FILE, REGNO) \ mvs_check_page (FILE, 8, 0); \ fprintf (FILE, "\tL\t%s,%d(13)\n\tLA\t13,4(13)\n", \ reg_names[REGNO], STACK_POINTER_OFFSET)/* This outputs a text string. The string are chopped up to fit into an 80 byte record. Also, control and special characters, interpreted by the IBM assembler, are output numerically. */#define MVS_ASCII_TEXT_LENGTH 48#define ASM_OUTPUT_ASCII(FILE, PTR, LEN) \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -