📄 stormy16.c
字号:
&& (lookup_attribute ("below100", DECL_ATTRIBUTES (decl)) || lookup_attribute ("BELOW100", DECL_ATTRIBUTES (decl)))) { const char *newsection = 0; char *newname; tree idp; rtx rtlname, rtl; const char *oldname; rtl = r; rtlname = XEXP (rtl, 0); if (GET_CODE (rtlname) == SYMBOL_REF) oldname = XSTR (rtlname, 0); else if (GET_CODE (rtlname) == MEM && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) oldname = XSTR (XEXP (rtlname, 0), 0); else abort (); if (DECL_INITIAL (decl)) { newsection = ".data_below100"; DECL_SECTION_NAME (decl) = build_string (strlen (newsection), newsection); } newname = alloca (strlen (oldname) + 4); sprintf (newname, "@b.%s", oldname); idp = get_identifier (newname); XEXP (rtl, 0) = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); }}const char *xstormy16_strip_name_encoding (const char *name){ while (1) { if (name[0] == '@' && name[2] == '.') name += 3; else if (name[0] == '*') name ++; else return name; }}/* Output constructors and destructors. Just like default_named_section_asm_out_* but don't set the sections writable. */#undef TARGET_ASM_CONSTRUCTOR#define TARGET_ASM_CONSTRUCTOR xstormy16_asm_out_constructor#undef TARGET_ASM_DESTRUCTOR#define TARGET_ASM_DESTRUCTOR xstormy16_asm_out_destructorstatic voidxstormy16_asm_out_destructor (rtx symbol, int priority){ const char *section = ".dtors"; char buf[16]; /* ??? This only works reliably with the GNU linker. */ if (priority != DEFAULT_INIT_PRIORITY) { sprintf (buf, ".dtors.%.5u", /* Invert the numbering so the linker puts us in the proper order; constructors are run from right to left, and the linker sorts in increasing order. */ MAX_INIT_PRIORITY - priority); section = buf; } named_section_flags (section, 0); assemble_align (POINTER_SIZE); assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);}static voidxstormy16_asm_out_constructor (rtx symbol, int priority){ const char *section = ".ctors"; char buf[16]; /* ??? This only works reliably with the GNU linker. */ if (priority != DEFAULT_INIT_PRIORITY) { sprintf (buf, ".ctors.%.5u", /* Invert the numbering so the linker puts us in the proper order; constructors are run from right to left, and the linker sorts in increasing order. */ MAX_INIT_PRIORITY - priority); section = buf; } named_section_flags (section, 0); assemble_align (POINTER_SIZE); assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);}/* Print a memory address as an operand to reference that memory location. */voidxstormy16_print_operand_address (FILE *file, rtx address){ HOST_WIDE_INT offset; int pre_dec, post_inc; /* There are a few easy cases. */ if (GET_CODE (address) == CONST_INT) { fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (address) & 0xFFFF); return; } if (CONSTANT_P (address) || GET_CODE (address) == CODE_LABEL) { output_addr_const (file, address); return; } /* Otherwise, it's hopefully something of the form (plus:HI (pre_dec:HI (reg:HI ...)) (const_int ...)) */ if (GET_CODE (address) == PLUS) { if (GET_CODE (XEXP (address, 1)) != CONST_INT) abort (); offset = INTVAL (XEXP (address, 1)); address = XEXP (address, 0); } else offset = 0; pre_dec = (GET_CODE (address) == PRE_DEC); post_inc = (GET_CODE (address) == POST_INC); if (pre_dec || post_inc) address = XEXP (address, 0); if (GET_CODE (address) != REG) abort (); fputc ('(', file); if (pre_dec) fputs ("--", file); fputs (reg_names [REGNO (address)], file); if (post_inc) fputs ("++", file); if (offset != 0) fprintf (file, "," HOST_WIDE_INT_PRINT_DEC, offset); fputc (')', file);}/* Print an operand to an assembler instruction. */voidxstormy16_print_operand (FILE *file, rtx x, int code){ switch (code) { case 'B': /* There is either one bit set, or one bit clear, in X. Print it preceded by '#'. */ { static int bits_set[8] = { 0, 1, 1, 2, 1, 2, 2, 3 }; HOST_WIDE_INT xx = 1; HOST_WIDE_INT l; if (GET_CODE (x) == CONST_INT) xx = INTVAL (x); else output_operand_lossage ("'B' operand is not constant"); /* GCC sign-extends masks with the MSB set, so we have to detect all the cases that differ only in sign extension beyond the bits we care about. Normally, the predicates and constraints ensure that we have the right values. This works correctly for valid masks. */ if (bits_set[xx & 7] <= 1) { /* Remove sign extension bits. */ if ((~xx & ~(HOST_WIDE_INT)0xff) == 0) xx &= 0xff; else if ((~xx & ~(HOST_WIDE_INT)0xffff) == 0) xx &= 0xffff; l = exact_log2 (xx); } else { /* Add sign extension bits. */ if ((xx & ~(HOST_WIDE_INT)0xff) == 0) xx |= ~(HOST_WIDE_INT)0xff; else if ((xx & ~(HOST_WIDE_INT)0xffff) == 0) xx |= ~(HOST_WIDE_INT)0xffff; l = exact_log2 (~xx); } if (l == -1) output_operand_lossage ("'B' operand has multiple bits set"); fprintf (file, IMMEDIATE_PREFIX HOST_WIDE_INT_PRINT_DEC, l); return; } case 'C': /* Print the symbol without a surrounding @fptr(). */ if (GET_CODE (x) == SYMBOL_REF) assemble_name (file, XSTR (x, 0)); else if (GET_CODE (x) == LABEL_REF) output_asm_label (x); else xstormy16_print_operand_address (file, x); return; case 'o': case 'O': /* Print the immediate operand less one, preceded by '#'. For 'O', negate it first. */ { HOST_WIDE_INT xx = 0; if (GET_CODE (x) == CONST_INT) xx = INTVAL (x); else output_operand_lossage ("'o' operand is not constant"); if (code == 'O') xx = -xx; fprintf (file, IMMEDIATE_PREFIX HOST_WIDE_INT_PRINT_DEC, xx - 1); return; } case 'b': /* Print the shift mask for bp/bn. */ { HOST_WIDE_INT xx = 1; HOST_WIDE_INT l; if (GET_CODE (x) == CONST_INT) xx = INTVAL (x); else output_operand_lossage ("'B' operand is not constant"); l = 7 - xx; fputs (IMMEDIATE_PREFIX, file); fprintf (file, HOST_WIDE_INT_PRINT_DEC, l); return; } case 0: /* Handled below. */ break; default: output_operand_lossage ("xstormy16_print_operand: unknown code"); return; } switch (GET_CODE (x)) { case REG: fputs (reg_names [REGNO (x)], file); break; case MEM: xstormy16_print_operand_address (file, XEXP (x, 0)); break; default: /* Some kind of constant or label; an immediate operand, so prefix it with '#' for the assembler. */ fputs (IMMEDIATE_PREFIX, file); output_addr_const (file, x); break; } return;}/* Expander for the `casesi' pattern. INDEX is the index of the switch statement. LOWER_BOUND is a CONST_INT that is the value of INDEX corresponding to the first table entry. RANGE is the number of table entries. TABLE is an ADDR_VEC that is the jump table. DEFAULT_LABEL is the address to branch to if INDEX is outside the range LOWER_BOUND to LOWER_BOUND+RANGE-1.*/void xstormy16_expand_casesi (rtx index, rtx lower_bound, rtx range, rtx table, rtx default_label){ HOST_WIDE_INT range_i = INTVAL (range); rtx int_index; /* This code uses 'br', so it can deal only with tables of size up to 8192 entries. */ if (range_i >= 8192) sorry ("switch statement of size %lu entries too large", (unsigned long) range_i); index = expand_binop (SImode, sub_optab, index, lower_bound, NULL_RTX, 0, OPTAB_LIB_WIDEN); emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, SImode, 1, default_label); int_index = gen_lowpart_common (HImode, index); emit_insn (gen_ashlhi3 (int_index, int_index, const2_rtx)); emit_jump_insn (gen_tablejump_pcrel (int_index, table));}/* Output an ADDR_VEC. It is output as a sequence of 'jmpf' instructions, without label or alignment or any other special constructs. We know that the previous instruction will be the `tablejump_pcrel' output above. TODO: it might be nice to output 'br' instructions if they could all reach. */voidxstormy16_output_addr_vec (FILE *file, rtx label ATTRIBUTE_UNUSED, rtx table){ int vlen, idx; function_section (current_function_decl); vlen = XVECLEN (table, 0); for (idx = 0; idx < vlen; idx++) { fputs ("\tjmpf ", file); output_asm_label (XEXP (XVECEXP (table, 0, idx), 0)); fputc ('\n', file); }}/* Expander for the `call' patterns. INDEX is the index of the switch statement. LOWER_BOUND is a CONST_INT that is the value of INDEX corresponding to the first table entry. RANGE is the number of table entries. TABLE is an ADDR_VEC that is the jump table. DEFAULT_LABEL is the address to branch to if INDEX is outside the range LOWER_BOUND to LOWER_BOUND+RANGE-1.*/void xstormy16_expand_call (rtx retval, rtx dest, rtx counter){ rtx call, temp; enum machine_mode mode; if (GET_CODE (dest) != MEM) abort (); dest = XEXP (dest, 0); if (! CONSTANT_P (dest) && GET_CODE (dest) != REG) dest = force_reg (Pmode, dest); if (retval == NULL) mode = VOIDmode; else mode = GET_MODE (retval); call = gen_rtx_CALL (mode, gen_rtx_MEM (FUNCTION_MODE, dest), counter); if (retval) call = gen_rtx_SET (VOIDmode, retval, call); if (! CONSTANT_P (dest)) { temp = gen_reg_rtx (HImode); emit_move_insn (temp, const0_rtx); } else temp = const0_rtx; call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, gen_rtx_USE (VOIDmode, temp))); emit_call_insn (call);}/* Expanders for multiword computational operations. *//* Expander for arithmetic operations; emit insns to compute (set DEST (CODE:MODE SRC0 SRC1)) using CARRY as a temporary. When CODE is COMPARE, a branch template is generated (this saves duplicating code in xstormy16_split_cbranch). */void xstormy16_expand_arith (enum machine_mode mode, enum rtx_code code, rtx dest, rtx src0, rtx src1, rtx carry){ int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; int i; int firstloop = 1; if (code == NEG) emit_move_insn (src0, const0_rtx); for (i = 0; i < num_words; i++) { rtx w_src0, w_src1, w_dest; rtx insn; w_src0 = simplify_gen_subreg (word_mode, src0, mode, i * UNITS_PER_WORD); w_src1 = simplify_gen_subreg (word_mode, src1, mode, i * UNITS_PER_WORD); w_dest = simplify_gen_subreg (word_mode, dest, mode, i * UNITS_PER_WORD); switch (code) { case PLUS: if (firstloop && GET_CODE (w_src1) == CONST_INT && INTVAL (w_src1) == 0) continue; if (firstloop) insn = gen_addchi4 (w_dest, w_src0, w_src1, carry); else insn = gen_addchi5 (w_dest, w_src0, w_src1, carry, carry); break; case NEG: case MINUS: case COMPARE: if (code == COMPARE && i == num_words - 1) { rtx branch, sub, clobber, sub_1; sub_1 = gen_rtx_MINUS (HImode, w_src0, gen_rtx_ZERO_EXTEND (HImode, carry)); sub = gen_rtx_SET (VOIDmode, w_dest, gen_rtx_MINUS (HImode,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -