diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/avr/avr-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/avr/avr.c | 104 | ||||
-rw-r--r-- | gcc/config/avr/avr.h | 100 |
3 files changed, 98 insertions, 107 deletions
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index 09f8271..8f6cb87 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -109,6 +109,7 @@ extern int avr_jump_mode (rtx x, rtx insn); extern int test_hard_reg_class (enum reg_class rclass, rtx x); extern int jump_over_one_insn_p (rtx insn, rtx dest); +extern int avr_hard_regno_nregs (int regno, enum machine_mode mode); extern int avr_hard_regno_mode_ok (int regno, enum machine_mode mode); extern void final_prescan_insn (rtx insn, rtx *operand, int num_operands); extern int avr_simplify_comparison_p (enum machine_mode mode, diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 846c796..5d4dbd3 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -686,31 +686,28 @@ avr_regs_to_save (HARD_REG_SET *set) /* Return true if register FROM can be eliminated via register TO. */ static bool -avr_can_eliminate (const int from, const int to) +avr_can_eliminate (int from ATTRIBUTE_UNUSED, int to) { - return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) - || (frame_pointer_needed && to == FRAME_POINTER_REGNUM) - || ((from == FRAME_POINTER_REGNUM - || from == FRAME_POINTER_REGNUM + 1) - && !frame_pointer_needed)); + return to == HARD_FRAME_POINTER_REGNUM; } /* Compute offset between arg_pointer and frame_pointer. */ int -avr_initial_elimination_offset (int from, int to) +avr_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED) { - if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) - return 0; - else + int offset = 0; + + if (from == ARG_POINTER_REGNUM) { - int offset = frame_pointer_needed ? 2 : 0; - int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2; - + offset += AVR_HAVE_EIJMP_EICALL ? 3 : 2; + offset += frame_pointer_needed ? 2 : 0; offset += avr_regs_to_save (NULL); - return (get_frame_size () + avr_outgoing_args_size() - + avr_pc_size + 1 + offset); + offset += get_frame_size (); + offset += 1; /* post-dec stack space */ } + + return offset; } /* Actual start of frame is virtual_stack_vars_rtx this is offset from @@ -902,12 +899,12 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) notes to the front. Thus we build them in the reverse order of how we want dwarf2out to process them. */ - /* The function does always set frame_pointer_rtx, but whether that + /* The function does always set hard_frame_pointer_rtx, but whether that is going to be permanent in the function is frame_pointer_needed. */ add_reg_note (insn, REG_CFA_ADJUST_CFA, gen_rtx_SET (VOIDmode, (frame_pointer_needed - ? frame_pointer_rtx + ? hard_frame_pointer_rtx : stack_pointer_rtx), plus_constant (stack_pointer_rtx, -(size + live_seq)))); @@ -952,7 +949,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) if (frame_pointer_needed && size == 0) { - insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); + insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; } @@ -987,7 +984,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) || !current_function_is_leaf); fp = my_fp = (frame_pointer_needed - ? frame_pointer_rtx + ? hard_frame_pointer_rtx : gen_rtx_REG (Pmode, REG_X)); if (AVR_HAVE_8BIT_SP) @@ -995,7 +992,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) /* The high byte (r29) does not change: Prefer SUBI (1 cycle) over ABIW (2 cycles, same size). */ - my_fp = all_regs_rtx[FRAME_POINTER_REGNUM]; + my_fp = all_regs_rtx[HARD_FRAME_POINTER_REGNUM]; } /************ Method 1: Adjust frame pointer ************/ @@ -1260,13 +1257,13 @@ expand_epilogue (bool sibcall_p) if (!frame_pointer_needed) { - emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); + emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); } if (size) { - emit_move_insn (frame_pointer_rtx, - plus_constant (frame_pointer_rtx, size)); + emit_move_insn (hard_frame_pointer_rtx, + plus_constant (hard_frame_pointer_rtx, size)); } emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode))); @@ -1285,7 +1282,7 @@ expand_epilogue (bool sibcall_p) || !current_function_is_leaf); fp = my_fp = (frame_pointer_needed - ? frame_pointer_rtx + ? hard_frame_pointer_rtx : gen_rtx_REG (Pmode, REG_X)); if (AVR_HAVE_8BIT_SP) @@ -1293,7 +1290,7 @@ expand_epilogue (bool sibcall_p) /* The high byte (r29) does not change: Prefer SUBI (1 cycle) over SBIW (2 cycles). */ - my_fp = all_regs_rtx[FRAME_POINTER_REGNUM]; + my_fp = all_regs_rtx[HARD_FRAME_POINTER_REGNUM]; } /********** Method 1: Adjust fp register **********/ @@ -1534,37 +1531,8 @@ avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) memory address for an operand of mode MODE */ static rtx -avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode) +avr_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode) { - bool big_offset_p = false; - - x = oldx; - - if (GET_CODE (oldx) == PLUS - && REG_P (XEXP (oldx, 0))) - { - if (REG_P (XEXP (oldx, 1))) - x = force_reg (GET_MODE (oldx), oldx); - else if (CONST_INT_P (XEXP (oldx, 1))) - { - int offs = INTVAL (XEXP (oldx, 1)); - if (frame_pointer_rtx != XEXP (oldx, 0) - && offs > MAX_LD_OFFSET (mode)) - { - big_offset_p = true; - x = force_reg (GET_MODE (oldx), oldx); - } - } - } - - if (avr_log.legitimize_address) - { - avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx); - - if (x != oldx) - avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x); - } - return x; } @@ -1634,7 +1602,7 @@ avr_legitimize_reload_address (rtx *px, enum machine_mode mode, } } else if (! (frame_pointer_needed - && XEXP (x, 0) == frame_pointer_rtx)) + && XEXP (x, 0) == hard_frame_pointer_rtx)) { push_reload (x, NULL_RTX, px, NULL, POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0, @@ -8366,6 +8334,19 @@ extra_constraint_Q (rtx x) return ok; } +/* Returns the number of registers required to hold a value of MODE. */ + +int +avr_hard_regno_nregs (int regno, enum machine_mode mode) +{ + /* The fake registers are designed to hold exactly a pointer. */ + if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM) + return 1; + + return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; +} + + /* Convert condition code CONDITION to the valid AVR condition code. */ RTX_CODE @@ -8789,6 +8770,10 @@ jump_over_one_insn_p (rtx insn, rtx dest) int avr_hard_regno_mode_ok (int regno, enum machine_mode mode) { + /* The fake registers are designed to hold exactly a pointer. */ + if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM) + return mode == Pmode; + /* NOTE: 8-bit values must not be disallowed for R28 or R29. Disallowing QI et al. in these regs might lead to code like (set (subreg:QI (reg:HI 28) n) ...) @@ -8812,7 +8797,6 @@ avr_hard_regno_mode_ok (int regno, enum machine_mode mode) return 0; /* All modes larger than 8 bits should start in an even register. */ - return !(regno & 1); } @@ -8872,7 +8856,8 @@ avr_regno_mode_code_ok_for_base_p (int regno, && (regno == REG_X || regno == REG_Y || regno == REG_Z - || regno == ARG_POINTER_REGNUM)) + || regno == ARG_POINTER_REGNUM + || regno == FRAME_POINTER_REGNUM)) { ok = true; } @@ -8883,7 +8868,8 @@ avr_regno_mode_code_ok_for_base_p (int regno, if (regno == REG_X || regno == REG_Y || regno == REG_Z - || regno == ARG_POINTER_REGNUM) + || regno == ARG_POINTER_REGNUM + || regno == FRAME_POINTER_REGNUM) { ok = true; } diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 33017ba..a231b7f 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -231,45 +231,47 @@ enum #define FIRST_PSEUDO_REGISTER 36 -#define FIXED_REGISTERS {\ - 1,1,/* r0 r1 */\ - 0,0,/* r2 r3 */\ - 0,0,/* r4 r5 */\ - 0,0,/* r6 r7 */\ - 0,0,/* r8 r9 */\ - 0,0,/* r10 r11 */\ - 0,0,/* r12 r13 */\ - 0,0,/* r14 r15 */\ - 0,0,/* r16 r17 */\ - 0,0,/* r18 r19 */\ - 0,0,/* r20 r21 */\ - 0,0,/* r22 r23 */\ - 0,0,/* r24 r25 */\ - 0,0,/* r26 r27 */\ - 0,0,/* r28 r29 */\ - 0,0,/* r30 r31 */\ - 1,1,/* STACK */\ - 1,1 /* arg pointer */ } +#define FIXED_REGISTERS { \ + 1,1,/* r0 r1 */ \ + 0,0,/* r2 r3 */ \ + 0,0,/* r4 r5 */ \ + 0,0,/* r6 r7 */ \ + 0,0,/* r8 r9 */ \ + 0,0,/* r10 r11 */ \ + 0,0,/* r12 r13 */ \ + 0,0,/* r14 r15 */ \ + 0,0,/* r16 r17 */ \ + 0,0,/* r18 r19 */ \ + 0,0,/* r20 r21 */ \ + 0,0,/* r22 r23 */ \ + 0,0,/* r24 r25 */ \ + 0,0,/* r26 r27 */ \ + 0,0,/* r28 r29 */ \ + 0,0,/* r30 r31 */ \ + 1,1,/* STACK */ \ + 1, /* arg pointer */ \ + 1 /* frame pointer */ } #define CALL_USED_REGISTERS { \ 1,1,/* r0 r1 */ \ - 0,0,/* r2 r3 */ \ - 0,0,/* r4 r5 */ \ - 0,0,/* r6 r7 */ \ - 0,0,/* r8 r9 */ \ - 0,0,/* r10 r11 */ \ - 0,0,/* r12 r13 */ \ - 0,0,/* r14 r15 */ \ - 0,0,/* r16 r17 */ \ - 1,1,/* r18 r19 */ \ - 1,1,/* r20 r21 */ \ - 1,1,/* r22 r23 */ \ - 1,1,/* r24 r25 */ \ - 1,1,/* r26 r27 */ \ - 0,0,/* r28 r29 */ \ - 1,1,/* r30 r31 */ \ - 1,1,/* STACK */ \ - 1,1 /* arg pointer */ } + 0,0,/* r2 r3 */ \ + 0,0,/* r4 r5 */ \ + 0,0,/* r6 r7 */ \ + 0,0,/* r8 r9 */ \ + 0,0,/* r10 r11 */ \ + 0,0,/* r12 r13 */ \ + 0,0,/* r14 r15 */ \ + 0,0,/* r16 r17 */ \ + 1,1,/* r18 r19 */ \ + 1,1,/* r20 r21 */ \ + 1,1,/* r22 r23 */ \ + 1,1,/* r24 r25 */ \ + 1,1,/* r26 r27 */ \ + 0,0,/* r28 r29 */ \ + 1,1,/* r30 r31 */ \ + 1,1,/* STACK */ \ + 1, /* arg pointer */ \ + 1 /* frame pointer */ } #define REG_ALLOC_ORDER { \ 24,25, \ @@ -287,7 +289,7 @@ enum #define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc () -#define HARD_REGNO_NREGS(REGNO, MODE) ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) +#define HARD_REGNO_NREGS(REGNO, MODE) avr_hard_regno_nregs(REGNO, MODE) #define HARD_REGNO_MODE_OK(REGNO, MODE) avr_hard_regno_mode_ok(REGNO, MODE) @@ -337,17 +339,17 @@ enum reg_class { {3 << REG_Z,0x00000000}, /* POINTER_Z_REGS, r30 - r31 */ \ {0x00000000,0x00000003}, /* STACK_REG, STACK */ \ {(3 << REG_Y) | (3 << REG_Z), \ - 0x00000000}, /* BASE_POINTER_REGS, r28 - r31 */ \ + 0x0000000c}, /* BASE_POINTER_REGS, r28 - r31,ap,fp */ \ {(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z), \ - 0x00000000}, /* POINTER_REGS, r26 - r31 */ \ + 0x0000000c}, /* POINTER_REGS, r26 - r31 */ \ {(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z) | (3 << REG_W), \ 0x00000000}, /* ADDW_REGS, r24 - r31 */ \ {0x00ff0000,0x00000000}, /* SIMPLE_LD_REGS r16 - r23 */ \ {(3 << REG_X)|(3 << REG_Y)|(3 << REG_Z)|(3 << REG_W)|(0xff << 16), \ - 0x00000000}, /* LD_REGS, r16 - r31 */ \ + 0x0000000c}, /* LD_REGS, r16 - r31 */ \ {0x0000ffff,0x00000000}, /* NO_LD_REGS r0 - r15 */ \ - {0xffffffff,0x00000000}, /* GENERAL_REGS, r0 - r31 */ \ - {0xffffffff,0x00000003} /* ALL_REGS */ \ + {0xffffffff,0x0000000c}, /* GENERAL_REGS, r0 - r31 */ \ + {0xffffffff,0x0000000f} /* ALL_REGS */ \ } #define REGNO_REG_CLASS(R) avr_regno_reg_class(R) @@ -378,18 +380,20 @@ enum reg_class { #define STACK_POINTER_REGNUM 32 -#define FRAME_POINTER_REGNUM REG_Y +#define HARD_FRAME_POINTER_REGNUM REG_Y #define ARG_POINTER_REGNUM 34 +#define FRAME_POINTER_REGNUM 35 #define STATIC_CHAIN_REGNUM 2 #define ELIMINABLE_REGS { \ - {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \ - ,{FRAME_POINTER_REGNUM+1,STACK_POINTER_REGNUM+1}} + { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }} -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ OFFSET = avr_initial_elimination_offset (FROM, TO) #define RETURN_ADDR_RTX(count, tem) avr_return_addr_rtx (count, tem) @@ -493,7 +497,7 @@ typedef struct avr_args { "r8","r9","r10","r11","r12","r13","r14","r15", \ "r16","r17","r18","r19","r20","r21","r22","r23", \ "r24","r25","r26","r27","r28","r29","r30","r31", \ - "__SP_L__","__SP_H__","argL","argH"} + "__SP_L__","__SP_H__","ap","fp"} #define FINAL_PRESCAN_INSN(insn, operand, nop) final_prescan_insn (insn, operand,nop) |