📄 m68hc11.c
字号:
else if (mode == HImode) { return gen_int_mode (val >> 16, HImode); } } if (mode == QImode && D_REG_P (x)) return gen_rtx (REG, mode, HARD_A_REGNUM); /* There is no way in GCC to represent the upper part of a word register. To obtain the 8-bit upper part of a soft register, we change the reg into a mem rtx. This is possible because they are physically located in memory. There is no offset because we are big-endian. */ if (mode == QImode && S_REG_P (x)) { int pos; /* Avoid the '*' for direct addressing mode when this addressing mode is disabled. */ pos = TARGET_NO_DIRECT_MODE ? 1 : 0; return gen_rtx (MEM, QImode, gen_rtx (SYMBOL_REF, Pmode, ®_names[REGNO (x)][pos])); } /* gen_highpart crashes when it is called with a SUBREG. */ if (GET_CODE (x) == SUBREG) { return gen_rtx (SUBREG, mode, XEXP (x, 0), XEXP (x, 1)); } if (GET_CODE (x) == REG) { if (REGNO (x) < FIRST_PSEUDO_REGISTER) return gen_rtx (REG, mode, REGNO (x)); else return gen_rtx_SUBREG (mode, x, 0); } if (GET_CODE (x) == MEM) { x = change_address (x, mode, 0); /* Return a different rtx to avoid to share it in several insns (when used by a split pattern). Sharing addresses within a MEM breaks the Z register replacement (and reloading). */ if (GET_CODE (x) == MEM) x = copy_rtx (x); return x; } abort ();}/* Obscure register manipulation. *//* Finds backward in the instructions to see if register 'reg' is dead. This is used when generating code to see if we can use 'reg' as a scratch register. This allows us to choose a better generation of code when we know that some register dies or can be clobbered. */intdead_register_here (x, reg) rtx x; rtx reg;{ rtx x_reg; rtx p; if (D_REG_P (reg)) x_reg = gen_rtx (REG, SImode, HARD_X_REGNUM); else x_reg = 0; for (p = PREV_INSN (x); p && GET_CODE (p) != CODE_LABEL; p = PREV_INSN (p)) if (GET_RTX_CLASS (GET_CODE (p)) == 'i') { rtx body; body = PATTERN (p); if (GET_CODE (body) == CALL_INSN) break; if (GET_CODE (body) == JUMP_INSN) break; if (GET_CODE (body) == SET) { rtx dst = XEXP (body, 0); if (GET_CODE (dst) == REG && REGNO (dst) == REGNO (reg)) break; if (x_reg && rtx_equal_p (dst, x_reg)) break; if (find_regno_note (p, REG_DEAD, REGNO (reg))) return 1; } else if (reg_mentioned_p (reg, p) || (x_reg && reg_mentioned_p (x_reg, p))) break; } /* Scan forward to see if the register is set in some insns and never used since then. */ for (p = x /*NEXT_INSN (x) */ ; p; p = NEXT_INSN (p)) { rtx body; if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN || GET_CODE (p) == CALL_INSN || GET_CODE (p) == BARRIER) break; if (GET_CODE (p) != INSN) continue; body = PATTERN (p); if (GET_CODE (body) == SET) { rtx src = XEXP (body, 1); rtx dst = XEXP (body, 0); if (GET_CODE (dst) == REG && REGNO (dst) == REGNO (reg) && !reg_mentioned_p (reg, src)) return 1; } /* Register is used (may be in source or in dest). */ if (reg_mentioned_p (reg, p) || (x_reg != 0 && GET_MODE (p) == SImode && reg_mentioned_p (x_reg, p))) break; } return p == 0 ? 1 : 0;}/* Code generation operations called from machine description file. *//* Print the name of register 'regno' in the assembly file. */static voidasm_print_register (file, regno) FILE *file; int regno;{ const char *name = reg_names[regno]; if (TARGET_NO_DIRECT_MODE && name[0] == '*') name++; fprintf (file, "%s", name);}/* 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 M68HC11 specific codes are: 'b' for the low part of the operand. 'h' for the high part of the operand The 'b' or 'h' modifiers have no effect if the operand has the QImode and is not a S_REG_P (soft register). If the operand is a hard register, these two modifiers have no effect. 't' generate the temporary scratch register. The operand is ignored. 'T' generate the low-part temporary scratch register. The operand is ignored. */voidprint_operand (file, op, letter) FILE *file; rtx op; int letter;{ if (letter == 't') { asm_print_register (file, SOFT_TMP_REGNUM); return; } else if (letter == 'T') { asm_print_register (file, SOFT_TMP_REGNUM); fprintf (file, "+1"); return; } else if (letter == '#') { asm_fprintf (file, "%0I"); } if (GET_CODE (op) == REG) { if (letter == 'b' && S_REG_P (op)) { asm_print_register (file, REGNO (op)); fprintf (file, "+1"); } else if (letter == 'b' && D_REG_P (op)) { asm_print_register (file, HARD_B_REGNUM); } else { asm_print_register (file, REGNO (op)); } return; } if (GET_CODE (op) == SYMBOL_REF && (letter == 'b' || letter == 'h')) { if (letter == 'b') asm_fprintf (file, "%0I%%lo("); else asm_fprintf (file, "%0I%%hi("); output_addr_const (file, op); fprintf (file, ")"); return; } /* Get the low or high part of the operand when 'b' or 'h' modifiers are specified. If we already have a QImode, there is nothing to do. */ if (GET_MODE (op) == HImode || GET_MODE (op) == VOIDmode) { if (letter == 'b') { op = m68hc11_gen_lowpart (QImode, op); } else if (letter == 'h') { op = m68hc11_gen_highpart (QImode, op); } } if (GET_CODE (op) == MEM) { rtx base = XEXP (op, 0); switch (GET_CODE (base)) { case PRE_DEC: if (TARGET_M6812) { fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (op))); asm_print_register (file, REGNO (XEXP (base, 0))); } else abort (); break; case POST_DEC: if (TARGET_M6812) { fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op))); asm_print_register (file, REGNO (XEXP (base, 0))); fprintf (file, "-"); } else abort (); break; case POST_INC: if (TARGET_M6812) { fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op))); asm_print_register (file, REGNO (XEXP (base, 0))); fprintf (file, "+"); } else abort (); break; case PRE_INC: if (TARGET_M6812) { fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (op))); asm_print_register (file, REGNO (XEXP (base, 0))); } else abort (); break; default: output_address (base); break; } } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode) { REAL_VALUE_TYPE r; long l; REAL_VALUE_FROM_CONST_DOUBLE (r, op); REAL_VALUE_TO_TARGET_SINGLE (r, l); asm_fprintf (file, "%I0x%lx", l); } else if (GET_CODE (op) == CONST_DOUBLE && (GET_MODE (op) == DFmode || GET_MODE (op) == XFmode)) { char dstr[30]; real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (op), sizeof (dstr), 0, 1); asm_fprintf (file, "%I0r%s", dstr); } else { int need_parenthesize = 0; if (letter != 'i') asm_fprintf (file, "%0I"); else need_parenthesize = must_parenthesize (op); if (need_parenthesize) fprintf (file, "("); output_addr_const (file, op); if (need_parenthesize) fprintf (file, ")"); }}/* Returns true if the operand 'op' must be printed with parenthesis arround it. This must be done only if there is a symbol whose name is a processor register. */static intmust_parenthesize (op) rtx op;{ const char *name; switch (GET_CODE (op)) { case SYMBOL_REF: name = XSTR (op, 0); /* Avoid a conflict between symbol name and a possible register. */ return (strcasecmp (name, "a") == 0 || strcasecmp (name, "b") == 0 || strcasecmp (name, "d") == 0 || strcasecmp (name, "x") == 0 || strcasecmp (name, "y") == 0 || strcasecmp (name, "ix") == 0 || strcasecmp (name, "iy") == 0 || strcasecmp (name, "pc") == 0 || strcasecmp (name, "sp") == 0 || strcasecmp (name, "ccr") == 0) ? 1 : 0; case PLUS: case MINUS: return must_parenthesize (XEXP (op, 0)) || must_parenthesize (XEXP (op, 1)); case MEM: case CONST: case ZERO_EXTEND: case SIGN_EXTEND: return must_parenthesize (XEXP (op, 0)); case CONST_DOUBLE: case CONST_INT: case LABEL_REF: case CODE_LABEL: default: return 0; }}/* 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. */voidprint_operand_address (file, addr) FILE *file; rtx addr;{ rtx base; rtx offset; int need_parenthesis = 0; switch (GET_CODE (addr)) { case REG: if (!REG_P (addr) || !REG_OK_FOR_BASE_STRICT_P (addr)) abort (); fprintf (file, "0,"); asm_print_register (file, REGNO (addr)); break; case MEM: base = XEXP (addr, 0); switch (GET_CODE (base)) { case PRE_DEC: if (TARGET_M6812) { fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (addr))); asm_print_register (file, REGNO (XEXP (base, 0))); } else abort (); break; case POST_DEC: if (TARGET_M6812) { fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr))); asm_print_register (file, REGNO (XEXP (base, 0))); fprintf (file, "-"); } else abort (); break; case POST_INC: if (TARGET_M6812) { fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr))); asm_print_register (file, REGNO (XEXP (base, 0))); fprintf (file, "+"); } else abort (); break; case PRE_INC: if (TARGET_M6812) { fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (addr))); asm_print_register (file, REGNO (XEXP (base, 0))); } else abort (); break; default: need_parenthesis = must_parenthesize (base); if (need_parenthesis) fprintf (file, "("); output_addr_const (file, base); if (need_parenthesis) fprintf (file, ")"); break; } break; case PLUS: base = XEXP (addr, 0); offset = XEXP (addr, 1); if (!G_REG_P (base) && G_REG_P (offset)) { base = XEXP (addr, 1); offset = XEXP (addr, 0); } if ((CONSTANT_ADDRESS_P (base)) && (CONSTANT_ADDRESS_P (offset))) { need_parenthesis = must_parenthesize (addr); if (need_parenthesis) fprintf (file, "("); output_addr_const (file, base); fprintf (file, "+"); output_addr_const (file, offset); if (need_parenthesis) fprintf (file, ")"); } else if (REG_P (base) && REG_OK_FOR_BASE_STRICT_P (base)) { if (REG_P (offset)) { if (TARGET_M6812) { asm_print_register (file, REGNO (offset)); fprintf (file, ","); asm_print_register (file, REGNO (base)); } else abort (); } else { need_parenthesis = must_parenthesize
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -