📄 pa.c
字号:
rtx base = XEXP (XEXP (x, 0), 0); switch (GET_CODE (XEXP (x, 0))) { case PRE_DEC: case POST_DEC: fprintf (file, "-%d(0,%s)", size, reg_names [REGNO (base)]); break; case PRE_INC: case POST_INC: fprintf (file, "%d(0,%s)", size, reg_names [REGNO (base)]); break; default: output_address (XEXP (x, 0)); break; } } else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode) { union { double d; int i[2]; } u; union { float f; int i; } u1; u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1); u1.f = u.d; if (code == 'f') fprintf (file, "0r%.9g", u1.f); else fprintf (file, "0x%x", u1.i); } else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode) { union { double d; int i[2]; } u; u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1); fprintf (file, "0r%.20g", u.d); } else output_addr_const (file, x);}/* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF. */voidoutput_global_address (file, x) FILE *file; rtx x;{ if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x)) assemble_name (file, XSTR (x, 0)); else if (GET_CODE (x) == SYMBOL_REF) { assemble_name (file, XSTR (x, 0)); fprintf (file, "-$global$"); } else if (GET_CODE (x) == CONST) { char *sep = ""; int offset = 0; /* assembler wants -$global$ at end */ rtx base; if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF) { base = XEXP (XEXP (x, 0), 0); output_addr_const (file, base); } else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == CONST_INT) offset = INTVAL (XEXP (XEXP (x, 0), 0)); else abort (); if (GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF) { base = XEXP (XEXP (x, 0), 1); output_addr_const (file, base); } else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) offset = INTVAL (XEXP (XEXP (x, 0),1)); else abort (); if (GET_CODE (XEXP (x, 0)) == PLUS) { if (offset < 0) { offset = -offset; sep = "-"; } else sep = "+"; } else if (GET_CODE (XEXP (x, 0)) == MINUS && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)) sep = "-"; else abort (); if (!read_only_operand (base)) fprintf (file, "-$global$"); fprintf (file, "%s", sep); if (offset) fprintf (file,"%d", offset); } else output_addr_const (file, x);}/* MEM rtls here are never SYMBOL_REFs (I think), so fldws is safe. */char *output_floatsisf2 (operands) rtx *operands;{ if (GET_CODE (operands[1]) == MEM) return "fldws %1,%0\n\tfcnvxf,sgl,sgl %0,%0"; else if (FP_REG_P (operands[1])) return "fcnvxf,sgl,sgl %1,%0"; return "stwm %r1,4(0,30)\n\tfldws,mb -4(0,30),%0\n\tfcnvxf,sgl,sgl %0,%0";}char *output_floatsidf2 (operands) rtx *operands;{ if (GET_CODE (operands[1]) == MEM) return "fldws %1,%0\n\tfcnvxf,sgl,dbl %0,%0"; else if (FP_REG_P (operands[1])) return "fcnvxf,sgl,dbl %1,%0"; return "stwm %r1,4(0,30)\n\tfldws,mb -4(0,30),%0\n\tfcnvxf,sgl,dbl %0,%0";}enum rtx_codereverse_relop (code) enum rtx_code code;{ switch (code) { case GT: return LT; case LT: return GT; case GE: return LE; case LE: return GE; case LTU: return GTU; case GTU: return LTU; case GEU: return LEU; case LEU: return GEU; default: abort (); }}/* HP's millicode routines mean something special to the assembler. Keep track of which ones we have used. */enum millicodes { remI, remU, divI, divU, mulI, mulU, end1000 };static char imported[(int)end1000];static char *milli_names[] = {"remI", "remU", "divI", "divU", "mulI", "mulU"};static char import_string[] = ".IMPORT $$....,MILLICODE";#define MILLI_START 10static intimport_milli (code) enum millicodes code;{ char str[sizeof (import_string)]; if (!imported[(int)code]) { imported[(int)code] = 1; strcpy (str, import_string); strncpy (str + MILLI_START, milli_names[(int)code], 4); output_asm_insn (str, 0); }}/* The register constraints have put the operands and return value in the proper registers. */char *output_mul_insn (unsignedp) int unsignedp;{ if (unsignedp) { import_milli (mulU); return "bl $$mulU,31%#"; } else { import_milli (mulI); return "bl $$mulI,31%#"; }}/* If operands isn't NULL, then it's a CONST_INT with which we can do something *//* Emit the rtl for doing a division by a constant. */ /* Do magic division millicodes exist for this value? */static int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1};/* We'll use an array to keep track of the magic millicodes and whether or not we've used them already. [n][0] is signed, [n][1] is unsigned. */static int div_milli[16][2];intdiv_operand (op, mode) rtx op; enum machine_mode mode;{ return (mode == SImode && ((GET_CODE (op) == REG && REGNO (op) == 25) || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0 && INTVAL (op) < 16 && magic_milli[INTVAL (op)])));}intemit_hpdiv_const (operands, unsignedp) rtx *operands; int unsignedp;{ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16 && magic_milli[INTVAL (operands[2])]) { emit_move_insn ( gen_rtx (REG, SImode, 26), operands[1]); emit (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29), gen_rtx (unsignedp ? UDIV : DIV, SImode, gen_rtx (REG, SImode, 26), operands[2])), gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0)), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 26)), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 25)), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 31))))); emit_move_insn (operands[0], gen_rtx (REG, SImode, 29)); return 1; } return 0;}char *output_div_insn (operands, unsignedp) rtx *operands; int unsignedp;{ int divisor; /* If the divisor is a constant, try to use one of the special opcodes .*/ if (GET_CODE (operands[0]) == CONST_INT) { divisor = INTVAL (operands[0]); if (!div_milli[divisor][unsignedp]) { if (unsignedp) output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands); else output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands); div_milli[divisor][unsignedp] = 1; } if (unsignedp) return "bl $$divU_%0,31%#"; return "bl $$divI_%0,31%#"; } /* Divisor isn't a special constant. */ else { if (unsignedp) { import_milli (divU); return "bl $$divU,31%#"; } else { import_milli (divI); return "bl $$divI,31%#"; } }}/* Output a $$rem millicode to do mod. */char *output_mod_insn (unsignedp) int unsignedp;{ if (unsignedp) { import_milli (remU); return "bl $$remU,31%#"; } else { import_milli (remI); return "bl $$remI,31%#"; }}voidoutput_arg_descriptor (insn) rtx insn;{ char *arg_regs[4]; enum machine_mode arg_mode; rtx prev_insn; int i, output_flag = 0; int regno; for (i = 0; i < 4; i++) arg_regs[i] = 0; for (prev_insn = PREV_INSN (insn); GET_CODE (prev_insn) == INSN; prev_insn = PREV_INSN (prev_insn)) { if (!(GET_CODE (PATTERN (prev_insn)) == USE && GET_CODE (XEXP (PATTERN (prev_insn), 0)) == REG && FUNCTION_ARG_REGNO_P (REGNO (XEXP (PATTERN (prev_insn), 0))))) break; arg_mode = GET_MODE (XEXP (PATTERN (prev_insn), 0)); regno = REGNO (XEXP (PATTERN (prev_insn), 0)); if (regno >= 23 && regno <= 26) { arg_regs[26 - regno] = "GR"; if (arg_mode == DImode) arg_regs[25 - regno] = "GR"; } else if (!TARGET_SNAKE) /* fp args */ { if (arg_mode == SFmode) arg_regs[regno - 36] = "FR"; else {#ifdef HP_FP_ARG_DESCRIPTOR_REVERSED arg_regs[regno - 37] = "FR"; arg_regs[regno - 36] = "FU";#else arg_regs[regno - 37] = "FU"; arg_regs[regno - 36] = "FR";#endif } } else { if (arg_mode == SFmode) arg_regs[(regno - 56) / 2] = "FR"; else {#ifdef HP_FP_ARG_DESCRIPTOR_REVERSED arg_regs[(regno - 58) / 2] = "FR"; arg_regs[(regno - 58) / 2 + 1] = "FU";#else arg_regs[(regno - 58) / 2] = "FU"; arg_regs[(regno - 58) / 2 + 1] = "FR";#endif } } } fputs ("\t.CALL ", asm_out_file); for (i = 0; i < 4; i++) { if (arg_regs[i]) { if (output_flag++) fputc (',', asm_out_file); fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]); } } fputc ('\n', asm_out_file);}/* Memory loads/stores to/from the shift need to go through the general registers. */enum reg_classsecondary_reload_class (class, mode, in) enum reg_class class; enum machine_mode mode; rtx in;{ int regno = true_regnum (in); if ((TARGET_SHARED_LIBS && function_label_operand (in, mode)) || ((regno >= FIRST_PSEUDO_REGISTER || regno == -1) && ((mode == QImode || mode == HImode || mode == SImode || mode == DImode) && (class == FP_REGS || class == SNAKE_FP_REGS || class == HI_SNAKE_FP_REGS))) || (class == SHIFT_REGS && (regno <= 0 || regno >= 32))) return GENERAL_REGS; return NO_REGS;}enum directionfunction_arg_padding (mode, type) enum machine_mode mode; tree type;{ int size; if (mode == BLKmode) { if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) size = int_size_in_bytes (type) * BITS_PER_UNIT; else return upward; /* Don't know if this is right, but */ /* same as old definition. */ } else size = GET_MODE_BITSIZE (mode); if (size < PARM_BOUNDARY) return downward; else if (size % PARM_BOUNDARY) return upward; else return none;}/* Do what is necessary for `va_start'. The argument is ignored; We look at the current function to determine if stdargs or varargs is used and fill in an initial va_list. A pointer to this constructor is returned. */struct rtx_def *hppa_builtin_saveregs (arglist) tree arglist;{ rtx block, float_addr, offset, float_mem; tree fntype = TREE_TYPE (current_function_decl); int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node))) ? UNITS_PER_WORD : 0); if (argadj) offset = plus_constant (current_function_arg_offset_rtx, argadj); else offset = current_function_arg_offset_rtx; /* Store general registers on the stack. */ move_block_from_reg (23, gen_rtx (MEM, BLKmode, plus_constant (current_function_internal_arg_pointer, -16)), 4); return copy_to_reg (expand_binop (Pmode, add_optab, current_function_internal_arg_pointer, offset, 0, 0, OPTAB_LIB_WIDEN));}extern struct obstack *saveable_obstack;/* In HPUX 8.0's shared library scheme, special relocations are needed for function labels if they might be passed to a function in a shared library (because shared libraries don't live in code space), and special magic is needed to construct their address. */voidhppa_encode_label (sym) rtx sym;{ char *str = XSTR (sym, 0); int len = strlen (str); char *newstr = obstack_alloc (saveable_obstack, len + 2) ; if (str[0] == '*') *newstr++ = *str++; strcpy (newstr + 1, str); *newstr = '@'; XSTR (sym,0) = newstr;} intfunction_label_operand (op, mode) rtx op; enum machine_mode mode;{ return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));}/* Return 1 if OP is suitable for the second add operand (the unshifed operand) in an shadd instruction. Allow CONST_INT to work around a reload bug. */intshadd_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == REG) return 1; if (GET_CODE (op) == CONST_INT) return 1; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -