📄 m68k.c
字号:
#endif if (! inited_FPA_table) init_FPA_table (); REAL_VALUE_FROM_CONST_DOUBLE (r, x); for (i=0; i<12; i++) { if (REAL_VALUES_EQUAL (r, values_FPA[i])) return (codes_FPA[i]); } if (GET_MODE (x) == SFmode) { for (i=25; i<38; i++) { if (REAL_VALUES_EQUAL (r, values_FPA[i])) return (codes_FPA[i]); } } else { for (i=12; i<25; i++) { if (REAL_VALUES_EQUAL (r, values_FPA[i])) return (codes_FPA[i]); } } return 0x0;}#endif /* define SUPPORT_SUN_FPA *//* A C compound statement to output to stdio stream STREAM the assembler syntax for an instruction operand X. X is an RTL expression. CODE is a value that can be used to specify one of several ways of printing the operand. It is used when identical operands must be printed differently depending on the context. CODE comes from the `%' specification that was used to request printing of the operand. If the specification was just `%DIGIT' then CODE is 0; if the specification was `%LTR DIGIT' then CODE is the ASCII code for LTR. If X is a register, this macro should print the register's name. The names can be found in an array `reg_names' whose type is `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'. When the machine description has a specification `%PUNCT' (a `%' followed by a punctuation character), this macro is called with a null pointer for X and the punctuation character for CODE. The m68k specific codes are: '.' for dot needed in Motorola-style opcode names. '-' for an operand pushing on the stack: sp@-, -(sp) or -(%sp) depending on the style of syntax. '+' for an operand pushing on the stack: sp@+, (sp)+ or (%sp)+ depending on the style of syntax. '@' for a reference to the top word on the stack: sp@, (sp) or (%sp) depending on the style of syntax. '#' for an immediate operand prefix (# in MIT and Motorola syntax but & in SGS syntax). '!' for the cc register (used in an `and to cc' insn). '$' for the letter `s' in an op code, but only on the 68040. '&' for the letter `d' in an op code, but only on the 68040. '/' for register prefix needed by longlong.h. 'b' for byte insn (no effect, on the Sun; this is for the ISI). 'd' to force memory addressing to be absolute, not relative. 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex) 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather than directly). Second part of 'y' below. 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex), or print pair of registers as rx:ry. 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs CONST_DOUBLE's as SunFPA constant RAM registers if possible, so it should not be used except for the SunFPA. */voidprint_operand (file, op, letter) FILE *file; /* file to write to */ rtx op; /* operand to print */ int letter; /* %<letter> or 0 */{ int i; if (letter == '.') {#ifdef MOTOROLA asm_fprintf (file, ".");#endif } else if (letter == '#') { asm_fprintf (file, "%0I"); } else if (letter == '-') {#ifdef MOTOROLA asm_fprintf (file, "-(%Rsp)");#else asm_fprintf (file, "%Rsp@-");#endif } else if (letter == '+') {#ifdef MOTOROLA asm_fprintf (file, "(%Rsp)+");#else asm_fprintf (file, "%Rsp@+");#endif } else if (letter == '@') {#ifdef MOTOROLA asm_fprintf (file, "(%Rsp)");#else asm_fprintf (file, "%Rsp@");#endif } else if (letter == '!') { asm_fprintf (file, "%Rfpcr"); } else if (letter == '$') { if (TARGET_68040_ONLY) { fprintf (file, "s"); } } else if (letter == '&') { if (TARGET_68040_ONLY) { fprintf (file, "d"); } } else if (letter == '/') { asm_fprintf (file, "%R"); } else if (GET_CODE (op) == REG) {#ifdef SUPPORT_SUN_FPA if (REGNO (op) < 16 && (letter == 'y' || letter == 'x') && GET_MODE (op) == DFmode) { fprintf (file, "%s:%s", reg_names[REGNO (op)], reg_names[REGNO (op)+1]); } else#endif { if (letter == 'R') /* Print out the second register name of a register pair. I.e., R (6) => 7. */ fputs (reg_names[REGNO (op) + 1], file); else fputs (reg_names[REGNO (op)], file); } } else if (GET_CODE (op) == MEM) { output_address (XEXP (op, 0)); if (letter == 'd' && ! TARGET_68020 && CONSTANT_ADDRESS_P (XEXP (op, 0)) && !(GET_CODE (XEXP (op, 0)) == CONST_INT && INTVAL (XEXP (op, 0)) < 0x8000 && INTVAL (XEXP (op, 0)) >= -0x8000)) { fprintf (file, ":l"); } }#ifdef SUPPORT_SUN_FPA else if ((letter == 'y' || letter == 'w') && GET_CODE (op) == CONST_DOUBLE && (i = standard_sun_fpa_constant_p (op))) { fprintf (file, "%%%d", i & 0x1ff); }#endif else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode) { REAL_VALUE_TYPE r; REAL_VALUE_FROM_CONST_DOUBLE (r, op); ASM_OUTPUT_FLOAT_OPERAND (letter, file, r); } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode) { REAL_VALUE_TYPE r; REAL_VALUE_FROM_CONST_DOUBLE (r, op); ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r); } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode) { REAL_VALUE_TYPE r; REAL_VALUE_FROM_CONST_DOUBLE (r, op); ASM_OUTPUT_DOUBLE_OPERAND (file, r); } else { asm_fprintf (file, "%0I"); output_addr_const (file, op); }}/* A C compound statement to output to stdio stream STREAM the assembler syntax for an instruction operand that is a memory reference whose address is ADDR. ADDR is an RTL expression. Note that this contains a kludge that knows that the only reason we have an address (plus (label_ref...) (reg...)) when not generating PIC code is in the insn before a tablejump, and we know that m68k.md generates a label LInnn: on such an insn. It is possible for PIC to generate a (plus (label_ref...) (reg...)) and we handle that just like we would a (plus (symbol_ref...) (reg...)). Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)" fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results we want. This difference can be accommodated by using an assembler define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END macro. See m68k/sgs.h for an example; for versions without the bug. Some assemblers refuse all the above solutions. The workaround is to emit "K(pc,d0.l*2)" with K being a small constant known to give the right behaviour. They also do not like things like "pea 1.w", so we simple leave off the .w on small constants. This routine is responsible for distinguishing between -fpic and -fPIC style relocations in an address. When generating -fpic code the offset is output in word mode (eg movel a5@(_foo:w), a0). When generating -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */#ifndef ASM_OUTPUT_CASE_FETCH#ifdef MOTOROLA#ifdef SGS#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\ asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)#else#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\ asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)#endif#else#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\ asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)#endif#endif /* ASM_OUTPUT_CASE_FETCH */voidprint_operand_address (file, addr) FILE *file; rtx addr;{ register rtx reg1, reg2, breg, ireg; rtx offset; switch (GET_CODE (addr)) { case REG:#ifdef MOTOROLA fprintf (file, "(%s)", reg_names[REGNO (addr)]);#else fprintf (file, "%s@", reg_names[REGNO (addr)]);#endif break; case PRE_DEC:#ifdef MOTOROLA fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);#else fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);#endif break; case POST_INC:#ifdef MOTOROLA fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);#else fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);#endif break; case PLUS: reg1 = reg2 = ireg = breg = offset = 0; if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) { offset = XEXP (addr, 0); addr = XEXP (addr, 1); } else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) { offset = XEXP (addr, 1); addr = XEXP (addr, 0); } if (GET_CODE (addr) != PLUS) { ; } else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) { reg1 = XEXP (addr, 0); addr = XEXP (addr, 1); } else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) { reg1 = XEXP (addr, 1); addr = XEXP (addr, 0); } else if (GET_CODE (XEXP (addr, 0)) == MULT) { reg1 = XEXP (addr, 0); addr = XEXP (addr, 1); } else if (GET_CODE (XEXP (addr, 1)) == MULT) { reg1 = XEXP (addr, 1); addr = XEXP (addr, 0); } else if (GET_CODE (XEXP (addr, 0)) == REG) { reg1 = XEXP (addr, 0); addr = XEXP (addr, 1); } else if (GET_CODE (XEXP (addr, 1)) == REG) { reg1 = XEXP (addr, 1); addr = XEXP (addr, 0); } if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT || GET_CODE (addr) == SIGN_EXTEND) { if (reg1 == 0) { reg1 = addr; } else { reg2 = addr; } addr = 0; }#if 0 /* for OLD_INDEXING */ else if (GET_CODE (addr) == PLUS) { if (GET_CODE (XEXP (addr, 0)) == REG) { reg2 = XEXP (addr, 0); addr = XEXP (addr, 1); } else if (GET_CODE (XEXP (addr, 1)) == REG) { reg2 = XEXP (addr, 1); addr = XEXP (addr, 0); } }#endif if (offset != 0) { if (addr != 0) { abort (); } addr = offset; } if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND || GET_CODE (reg1) == MULT)) || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) { breg = reg2; ireg = reg1; } else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) { breg = reg1; ireg = reg2; } if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF && ! (flag_pic && ireg == pic_offset_table_rtx)) { int scale = 1; if (GET_CODE (ireg) == MULT) { scale = INTVAL (XEXP (ireg, 1)); ireg = XEXP (ireg, 0); } if (GET_CODE (ireg) == SIGN_EXTEND) { ASM_OUTPUT_CASE_FETCH (file, CODE_LABEL_NUMBER (XEXP (addr, 0)), reg_names[REGNO (XEXP (ireg, 0))]); fprintf (file, "w"); } else { ASM_OUTPUT_CASE_FETCH (file, CODE_LABEL_NUMBER (XEXP (addr, 0)), reg_names[REGNO (ireg)]); fprintf (file, "l"); } if (scale != 1) {#ifdef MOTOROLA fprintf (file, "*%d", scale);#else fprintf (file, ":%d", scale);#endif } putc (')', file); break; } if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF && ! (flag_pic && breg == pic_offset_table_rtx)) { ASM_OUTPUT_CASE_FETCH (file, CODE_LABEL_NUMBER (XEXP (addr, 0)), reg_names[REGNO (breg)]); fprintf (file, "l)"); break; } if (ireg != 0 || breg != 0) { int scale = 1; if (breg == 0) { abort (); } if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF) { abort (); }#ifdef MOTOROLA if (addr != 0) { output_addr_const (file, addr); if (flag_pic && (breg == pic_offset_table_rtx)) fprintf (file, "@GOT"); } fprintf (file, "(%s", reg_names[REGNO (breg)]); if (ireg != 0) { putc (',', file); }#else fprintf (file, "%s@(", reg_names[REGNO (breg)]); if (addr != 0) { output_addr_const (file, addr); if ((flag_pic == 1) && (breg == pic_offset_table_rtx)) fprintf (file, ":w"); if ((flag_pic == 2) && (breg == pic_offset_table_rtx)) fprintf (file, ":l"); } if (addr != 0 && ireg != 0) { putc (',', file); }#endif if (ireg != 0 && GET_CODE (ireg) == MULT) { scale = INTVAL (XEXP (ireg, 1)); ireg = XEXP (ireg, 0); } if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) {#ifdef MOTOROLA fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);#else fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);#endif } else if (ireg != 0) {#ifdef MOTOROLA fprintf (file, "%s.l", reg_names[REGNO (ireg)]);#else fprintf (file, "%s:l", reg_names[REGNO (ireg)]);#endif } if (scale != 1) {#ifdef MOTOROLA fprintf (file, "*%d", scale);#else fprintf (file, ":%d", scale);#endif } putc (')', file); break; } else if (reg1 != 0 && GET_CODE (addr) == L
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -