📄 crx.c
字号:
if (next_param == (tree) 0 && TREE_VALUE (param) != void_type_node) { cum->ints = -1; return; } }}/* Implements the macro FUNCTION_ARG_ADVANCE defined in crx.h. */voidcrx_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED){ /* l holds the number of registers required */ int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; /* If the parameter isn't passed on a register don't advance cum. */ if (!last_parm_in_reg) return; if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0)) return; if (mode == SImode || mode == HImode || mode == QImode || mode == DImode) { if (l <= 1) cum->ints += 1; else cum->ints += l; } else if (mode == SFmode || mode == DFmode) cum->ints += l; else if ((mode) == BLKmode) { if ((l = enough_regs_for_param (cum, type, mode)) != 0) cum->ints += l; }}/* Implements the macro FUNCTION_ARG_REGNO_P defined in crx.h. Return nonzero * if N is a register used for passing parameters. */intcrx_function_arg_regno_p (int n){ return (n <= MAX_REG_FOR_PASSING_ARGS && n >= MIN_REG_FOR_PASSING_ARGS);}/* ADDRESSING MODES *//* ---------------- *//* Implements the macro GO_IF_LEGITIMATE_ADDRESS defined in crx.h. * The following addressing modes are supported on CRX: * * Relocations --> const | symbol_ref | label_ref * Absolute address --> 32 bit absolute * Post increment --> reg + 12 bit disp. * Post modify --> reg + 12 bit disp. * Register relative --> reg | 32 bit disp. + reg | 4 bit + reg * Scaled index --> reg + reg | 22 bit disp. + reg + reg | * 22 disp. + reg + reg + (2 | 4 | 8) */static int crx_addr_reg_p (rtx addr_reg){ rtx reg; if (REG_P (addr_reg)) { reg = addr_reg; } else if ((GET_CODE (addr_reg) == SUBREG && REG_P (SUBREG_REG (addr_reg)) && GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg))) <= UNITS_PER_WORD)) { reg = SUBREG_REG (addr_reg); } else return FALSE; if (GET_MODE (addr_reg) != Pmode) { return FALSE; } return TRUE;}enum crx_addrtypecrx_decompose_address (rtx addr, struct crx_address *out){ rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX; rtx scale_rtx = NULL_RTX, side_effect = NULL_RTX; int scale = -1; enum crx_addrtype retval = CRX_INVALID; switch (GET_CODE (addr)) { case CONST_INT: /* Absolute address (known at compile time) */ retval = CRX_ABSOLUTE; disp = addr; if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), GET_MODE_BITSIZE (Pmode))) return CRX_INVALID; break; case CONST: case SYMBOL_REF: case LABEL_REF: /* Absolute address (known at link time) */ retval = CRX_ABSOLUTE; disp = addr; break; case REG: case SUBREG: /* Register relative address */ retval = CRX_REG_REL; base = addr; break; case PLUS: switch (GET_CODE (XEXP (addr, 0))) { case REG: case SUBREG: if (REG_P (XEXP (addr, 1))) { /* Scaled index with scale = 1 and disp. = 0 */ retval = CRX_SCALED_INDX; base = XEXP (addr, 1); index = XEXP (addr, 0); scale = 1; } else if (RTX_SIGNED_INT_FITS_N_BITS (XEXP (addr, 1), 28)) { /* Register relative address and <= 28-bit disp. */ retval = CRX_REG_REL; base = XEXP (addr, 0); disp = XEXP (addr, 1); } else return CRX_INVALID; break; case PLUS: /* Scaled index and <= 22-bit disp. */ retval = CRX_SCALED_INDX; base = XEXP (XEXP (addr, 0), 1); disp = XEXP (addr, 1); if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 22)) return CRX_INVALID; switch (GET_CODE (XEXP (XEXP (addr, 0), 0))) { case REG: /* Scaled index with scale = 0 and <= 22-bit disp. */ index = XEXP (XEXP (addr, 0), 0); scale = 1; break; case MULT: /* Scaled index with scale >= 0 and <= 22-bit disp. */ index = XEXP (XEXP (XEXP (addr, 0), 0), 0); scale_rtx = XEXP (XEXP (XEXP (addr, 0), 0), 1); if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1) return CRX_INVALID; break; default: return CRX_INVALID; } break; case MULT: /* Scaled index with scale >= 0 */ retval = CRX_SCALED_INDX; base = XEXP (addr, 1); index = XEXP (XEXP (addr, 0), 0); scale_rtx = XEXP (XEXP (addr, 0), 1); /* Scaled index with scale >= 0 and <= 22-bit disp. */ if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1) return CRX_INVALID; break; default: return CRX_INVALID; } break; case POST_INC: case POST_DEC: /* Simple post-increment */ retval = CRX_POST_INC; base = XEXP (addr, 0); side_effect = addr; break; case POST_MODIFY: /* Generic post-increment with <= 12-bit disp. */ retval = CRX_POST_INC; base = XEXP (addr, 0); side_effect = XEXP (addr, 1); if (base != XEXP (side_effect, 0)) return CRX_INVALID; switch (GET_CODE (side_effect)) { case PLUS: case MINUS: disp = XEXP (side_effect, 1); if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 12)) return CRX_INVALID; break; default: /* CRX only supports PLUS and MINUS */ return CRX_INVALID; } break; default: return CRX_INVALID; } if (base && !crx_addr_reg_p (base)) return CRX_INVALID; if (index && !crx_addr_reg_p (index)) return CRX_INVALID; out->base = base; out->index = index; out->disp = disp; out->scale = scale; out->side_effect = side_effect; return retval;}intcrx_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr, int strict){ enum crx_addrtype addrtype; struct crx_address address; if (TARGET_DEBUG_ADDR) { fprintf (stderr, "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n", GET_MODE_NAME (mode), strict); debug_rtx (addr); } addrtype = crx_decompose_address (addr, &address); if (addrtype == CRX_POST_INC && GET_MODE_SIZE (mode) > UNITS_PER_WORD) return FALSE; if (TARGET_DEBUG_ADDR) { const char *typestr; switch (addrtype) { case CRX_INVALID: typestr = "Invalid"; break; case CRX_REG_REL: typestr = "Register relative"; break; case CRX_POST_INC: typestr = "Post-increment"; break; case CRX_SCALED_INDX: typestr = "Scaled index"; break; case CRX_ABSOLUTE: typestr = "Absolute"; break; default: abort (); } fprintf (stderr, "CRX Address type: %s\n", typestr); } if (addrtype == CRX_INVALID) return FALSE; if (strict) { if (address.base && !REGNO_OK_FOR_BASE_P (REGNO (address.base))) { if (TARGET_DEBUG_ADDR) fprintf (stderr, "Base register not strict\n"); return FALSE; } if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index))) { if (TARGET_DEBUG_ADDR) fprintf (stderr, "Index register not strict\n"); return FALSE; } } return TRUE;}/* ROUTINES TO COMPUTE COSTS *//* ------------------------- *//* Return cost of the memory address x. */static intcrx_address_cost (rtx addr){ enum crx_addrtype addrtype; struct crx_address address; int cost = 2; addrtype = crx_decompose_address (addr, &address); gcc_assert (addrtype != CRX_INVALID); /* An absolute address causes a 3-word instruction */ if (addrtype == CRX_ABSOLUTE) cost+=2; /* Post-modifying addresses are more powerful. */ if (addrtype == CRX_POST_INC) cost-=2; /* Attempt to minimize number of registers in the address. */ if (address.base) cost++; if (address.index && address.scale == 1) cost+=5; if (address.disp && !INT_CST4 (INTVAL (address.disp))) cost+=2; if (TARGET_DEBUG_ADDR) { fprintf (stderr, "\n======\nTARGET_ADDRESS_COST = %d\n", cost); debug_rtx (addr); } return cost;}/* Return the cost of moving data of mode MODE between a register of class * CLASS and memory; IN is zero if the value is to be written to memory, * nonzero if it is to be read in. This cost is relative to those in * REGISTER_MOVE_COST. */intcrx_memory_move_cost (enum machine_mode mode, enum reg_class class ATTRIBUTE_UNUSED, int in ATTRIBUTE_UNUSED){ /* One LD or ST takes twice the time of a simple reg-reg move */ if (reg_classes_intersect_p (class, GENERAL_REGS)) { /* printf ("GENERAL_REGS LD/ST = %d\n", 4 * HARD_REGNO_NREGS (0, mode));*/ return 4 * HARD_REGNO_NREGS (0, mode); } else if (reg_classes_intersect_p (class, HILO_REGS)) { /* HILO to memory and vice versa */ /* printf ("HILO_REGS %s = %d\n", in ? "LD" : "ST", (REGISTER_MOVE_COST (mode, in ? GENERAL_REGS : HILO_REGS, in ? HILO_REGS : GENERAL_REGS) + 4) * HARD_REGNO_NREGS (0, mode)); */ return (REGISTER_MOVE_COST (mode, in ? GENERAL_REGS : HILO_REGS, in ? HILO_REGS : GENERAL_REGS) + 4) * HARD_REGNO_NREGS (0, mode); } else /* default (like in i386) */ { /* printf ("ANYREGS = 100\n"); */ return 100; }}/* INSTRUCTION OUTPUT *//* ------------------ *//* Check if a const_double is ok for crx store-immediate instructions */intcrx_const_double_ok (rtx op){ if (GET_MODE (op) == DFmode) { REAL_VALUE_TYPE r; long l[2]; REAL_VALUE_FROM_CONST_DOUBLE (r, op); REAL_VALUE_TO_TARGET_DOUBLE (r, l); return (UNSIGNED_INT_FITS_N_BITS (l[0], 4) && UNSIGNED_INT_FITS_N_BITS (l[1], 4)) ? 1 : 0; } if (GET_MODE (op) == SFmode) { REAL_VALUE_TYPE r; long l; REAL_VALUE_FROM_CONST_DOUBLE (r, op); REAL_VALUE_TO_TARGET_SINGLE (r, l); return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0; } return (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4) && UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4)) ? 1 : 0;}/* Implements the macro PRINT_OPERAND defined in crx.h. */voidcrx_print_operand (FILE * file, rtx x, int code){ switch (code) { case 'p' : if (GET_CODE (x) == REG) { if (GET_MODE (x) == DImode || GET_MODE (x) == DFmode) { int regno = REGNO (x); if (regno + 1 >= SP_REGNUM) abort (); fprintf (file, "{%s, %s}", reg_names[regno], reg_names[regno + 1]); return; } else { if (REGNO (x) >= SP_REGNUM) abort (); fprintf (file, "%s", reg_names[REGNO (x)]); return; } } case 'd' : { const char *crx_cmp_str; switch (GET_CODE (x)) { /* MD: compare (reg, reg or imm) but CRX: cmp (reg or imm, reg) * -> swap all non symmetric ops */ case EQ : crx_cmp_str = "eq"; break; case NE : crx_cmp_str = "ne"; break; case GT : crx_cmp_str = "lt"; break; case GTU : crx_cmp_str = "lo"; break; case LT : crx_cmp_str = "gt"; break; case LTU : crx_cmp_str = "hi"; break; case GE : crx_cmp_str = "le"; break; case GEU : crx_cmp_str = "ls"; break; case LE : crx_cmp_str = "ge"; break; case LEU : crx_cmp_str = "hs"; break; default : abort (); } fprintf (file, "%s", crx_cmp_str); return; } case 'H': /* Print high part of a double precision value. */ switch (GET_CODE (x)) { case CONST_DOUBLE: if (GET_MODE (x) == SFmode) abort (); if (GET_MODE (x) == DFmode) { /* High part of a DF const. */ REAL_VALUE_TYPE r; long l[2]; REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_TARGET_DOUBLE (r, l); fprintf (file, "$0x%lx", l[1]); return; } /* -- Fallthrough to handle DI consts -- */ case CONST_INT: { rtx high, low; split_double (x, &low, &high); putc ('$', file); output_addr_const (file, high); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -