PR target/35013, 27192

2009-12-24  Andy Hutchinson  <hutchinsonandy@gcc.gnu.org>

	PR target/35013, 27192
	* config/avr/avr.c (print_operand_address): Print correct program
	memory address.
	Add warning for large device offset addresses.
	(avr_assemble_integer): Ditto.
	(print_operand): Add warnings for incorrect addressing.
	(out_movqi_r_mr): Tag assembler with new address codes.
	(out_movhi_r_mr): Ditto.
	(out_movsi_r_mr): Ditto.
	(out_movqi_mr_r): Ditto.
	(out_movhi_mr_r): Ditto.
	(out_movsi_mr_r): Ditto.
	* config/avr/predicates.md (text_segment_operand): New predicate.
	* config/avr/avr.md (jump): Tag assembler with new address codes.
	(call_insn): Ditto.
	(call_value_insn): Ditto.
	(*tablejump_lib): Ditto.
	(*cbi): Ditto.
	(*sbi): Ditto.
	(indirect_jump): New define_expand.
	(jcindirect_jump): New pattern for constant expression jump.
	(njcindirect_jump): Renamed old indirect_jump.

From-SVN: r155459
This commit is contained in:
Andy Hutchinson 2009-12-24 19:53:57 +00:00
parent a1b418cb9f
commit 846428f11f
4 changed files with 153 additions and 45 deletions

View File

@ -1,3 +1,28 @@
2009-12-24 Andy Hutchinson <hutchinsonandy@gcc.gnu.org>
PR target/35013, 27192
* config/avr/avr.c (print_operand_address): Print correct program
memory address.
Add warning for large device offset addresses.
(avr_assemble_integer): Ditto.
(print_operand): Add warnings for incorrect addressing.
(out_movqi_r_mr): Tag assembler with new address codes.
(out_movhi_r_mr): Ditto.
(out_movsi_r_mr): Ditto.
(out_movqi_mr_r): Ditto.
(out_movhi_mr_r): Ditto.
(out_movsi_mr_r): Ditto.
* config/avr/predicates.md (text_segment_operand): New predicate.
* config/avr/avr.md (jump): Tag assembler with new address codes.
(call_insn): Ditto.
(call_value_insn): Ditto.
(*tablejump_lib): Ditto.
(*cbi): Ditto.
(*sbi): Ditto.
(indirect_jump): New define_expand.
(jcindirect_jump): New pattern for constant expression jump.
(njcindirect_jump): Renamed old indirect_jump.
2009-12-24 Steven Bosscher <steven@gcc.gnu.org>
* store-motion.c (build_store_vectors): Clear regs_set_in_block at

View File

@ -1176,12 +1176,33 @@ print_operand_address (FILE *file, rtx addr)
default:
if (CONSTANT_ADDRESS_P (addr)
&& ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
|| GET_CODE (addr) == LABEL_REF))
&& text_segment_operand (addr, VOIDmode))
{
fprintf (file, "gs(");
output_addr_const (file,addr);
fprintf (file ,")");
rtx x = XEXP (addr,0);
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
{
/* Assembler gs() will implant word address. Make offset
a byte offset inside gs() for assembler. This is
needed because the more logical (constant+gs(sym)) is not
accepted by gas. For 128K and lower devices this is ok. For
large devices it will create a Trampoline to offset from symbol
which may not be what the user really wanted. */
fprintf (file, "gs(");
output_addr_const (file, XEXP (x,0));
fprintf (file,"+" HOST_WIDE_INT_PRINT_DEC ")", 2 * INTVAL (XEXP (x,1)));
if (AVR_3_BYTE_PC)
if (warning ( 0, "Pointer offset from symbol maybe incorrect."))
{
output_addr_const (stderr, addr);
fprintf(stderr,"\n");
}
}
else
{
fprintf (file, "gs(");
output_addr_const (file, addr);
fprintf (file, ")");
}
}
else
output_addr_const (file, addr);
@ -1221,12 +1242,18 @@ print_operand (FILE *file, rtx x, int code)
else if (GET_CODE (x) == MEM)
{
rtx addr = XEXP (x,0);
if (CONSTANT_P (addr) && abcd)
if (code == 'm')
{
fputc ('(', file);
output_address (addr);
fprintf (file, ")+%d", abcd);
if (!CONSTANT_P (addr))
fatal_insn ("bad address, not a constant):", addr);
/* Assembler template with m-code is data - not progmem section */
if (text_segment_operand (addr, VOIDmode))
if (warning ( 0, "accessing data memory with program memory address"))
{
output_addr_const (stderr, addr);
fprintf(stderr,"\n");
}
output_addr_const (file, addr);
}
else if (code == 'o')
{
@ -1257,6 +1284,18 @@ print_operand (FILE *file, rtx x, int code)
else
print_operand_address (file, addr);
}
else if (code == 'x')
{
/* Constant progmem address - like used in jmp or call */
if (0 == text_segment_operand (x, VOIDmode))
if (warning ( 0, "accessing program memory with data memory address"))
{
output_addr_const (stderr, x);
fprintf(stderr,"\n");
}
/* Use normal symbol for direct address no linker trampoline needed */
output_addr_const (file, x);
}
else if (GET_CODE (x) == CONST_DOUBLE)
{
long val;
@ -1874,10 +1913,10 @@ out_movqi_r_mr (rtx insn, rtx op[], int *l)
if (optimize > 0 && io_address_operand (x, QImode))
{
*l = 1;
return AS2 (in,%0,%1-0x20);
return AS2 (in,%0,%m1-0x20);
}
*l = 2;
return AS2 (lds,%0,%1);
return AS2 (lds,%0,%m1);
}
/* memory access by reg+disp */
else if (GET_CODE (x) == PLUS
@ -2062,12 +2101,12 @@ out_movhi_r_mr (rtx insn, rtx op[], int *l)
if (optimize > 0 && io_address_operand (base, HImode))
{
*l = 2;
return (AS2 (in,%A0,%A1-0x20) CR_TAB
AS2 (in,%B0,%B1-0x20));
return (AS2 (in,%A0,%m1-0x20) CR_TAB
AS2 (in,%B0,%m1+1-0x20));
}
*l = 4;
return (AS2 (lds,%A0,%A1) CR_TAB
AS2 (lds,%B0,%B1));
return (AS2 (lds,%A0,%m1) CR_TAB
AS2 (lds,%B0,%m1+1));
}
fatal_insn ("unknown move insn:",insn);
@ -2226,10 +2265,10 @@ out_movsi_r_mr (rtx insn, rtx op[], int *l)
AS2 (ld,%C0,%1) CR_TAB
AS2 (ld,%D0,%1));
else if (CONSTANT_ADDRESS_P (base))
return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
AS2 (lds,%B0,%B1) CR_TAB
AS2 (lds,%C0,%C1) CR_TAB
AS2 (lds,%D0,%D1));
return *l=8, (AS2 (lds,%A0,%m1) CR_TAB
AS2 (lds,%B0,%m1+1) CR_TAB
AS2 (lds,%C0,%m1+2) CR_TAB
AS2 (lds,%D0,%m1+3));
fatal_insn ("unknown move insn:",insn);
return "";
@ -2249,10 +2288,10 @@ out_movsi_mr_r (rtx insn, rtx op[], int *l)
l = &tmp;
if (CONSTANT_ADDRESS_P (base))
return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
AS2 (sts,%B0,%B1) CR_TAB
AS2 (sts,%C0,%C1) CR_TAB
AS2 (sts,%D0,%D1));
return *l=8,(AS2 (sts,%m0,%A1) CR_TAB
AS2 (sts,%m0+1,%B1) CR_TAB
AS2 (sts,%m0+2,%C1) CR_TAB
AS2 (sts,%m0+3,%D1));
if (reg_base > 0) /* (r) */
{
if (reg_base == REG_X) /* (R26) */
@ -2562,10 +2601,10 @@ out_movqi_mr_r (rtx insn, rtx op[], int *l)
if (optimize > 0 && io_address_operand (x, QImode))
{
*l = 1;
return AS2 (out,%0-0x20,%1);
return AS2 (out,%m0-0x20,%1);
}
*l = 2;
return AS2 (sts,%0,%1);
return AS2 (sts,%m0,%1);
}
/* memory access by reg+disp */
else if (GET_CODE (x) == PLUS
@ -2641,11 +2680,11 @@ out_movhi_mr_r (rtx insn, rtx op[], int *l)
if (optimize > 0 && io_address_operand (base, HImode))
{
*l = 2;
return (AS2 (out,%B0-0x20,%B1) CR_TAB
AS2 (out,%A0-0x20,%A1));
return (AS2 (out,%m0+1-0x20,%B1) CR_TAB
AS2 (out,%m0-0x20,%A1));
}
return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
AS2 (sts,%A0,%A1));
return *l = 4, (AS2 (sts,%m0+1,%B1) CR_TAB
AS2 (sts,%m0,%A1));
}
if (reg_base > 0)
{
@ -4502,8 +4541,7 @@ static bool
avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
{
if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
&& ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
|| GET_CODE (x) == LABEL_REF))
&& text_segment_operand (x, VOIDmode) )
{
fputs ("\t.word\tgs(", asm_out_file);
output_addr_const (asm_out_file, x);
@ -5944,13 +5982,13 @@ avr_out_sbxx_branch (rtx insn, rtx operands[])
if (INTVAL (operands[1]) < 0x40)
{
if (comp == EQ)
output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
output_asm_insn (AS2 (sbis,%m1-0x20,%2), operands);
else
output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
output_asm_insn (AS2 (sbic,%m1-0x20,%2), operands);
}
else
{
output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
output_asm_insn (AS2 (in,__tmp_reg__,%m1-0x20), operands);
if (comp == EQ)
output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
else
@ -5979,9 +6017,9 @@ avr_out_sbxx_branch (rtx insn, rtx operands[])
if (long_jump)
return (AS1 (rjmp,.+4) CR_TAB
AS1 (jmp,%3));
AS1 (jmp,%x3));
if (!reverse)
return AS1 (rjmp,%3);
return AS1 (rjmp,%x3);
return "";
}

View File

@ -28,9 +28,11 @@
;; D Add 3.
;; j Branch condition.
;; k Reverse branch condition.
;;..m..Constant Direct Data memory address.
;; o Displacement for (mem (plus (reg) (const_int))) operands.
;; p POST_INC or PRE_DEC address as a pointer (X, Y, Z)
;; r POST_INC or PRE_DEC address as a register (r26, r28, r30)
;;..x..Constant Direct Program memory address.
;; ~ Output 'r' if not AVR_HAVE_JMP_CALL.
;; ! Output 'e' if AVR_HAVE_EIJMP_EICALL.
@ -2732,8 +2734,8 @@
""
"*{
if (AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1)
return AS1 (jmp,%0);
return AS1 (rjmp,%0);
return AS1 (jmp,%x0);
return AS1 (rjmp,%x0);
}"
[(set (attr "length")
(if_then_else (match_operand 0 "symbol_ref_operand" "")
@ -2785,7 +2787,7 @@
\"%!icall\");
}
else if (which_alternative==2)
return AS1(%~call,%c0);
return AS1(%~call,%x0);
return (AS2 (ldi,r30,lo8(%0)) CR_TAB
AS2 (ldi,r31,hi8(%0)) CR_TAB
\"%!icall\");
@ -2822,7 +2824,7 @@
\"%!icall\");
}
else if (which_alternative==2)
return AS1(%~call,%c1);
return AS1(%~call,%x1);
return (AS2 (ldi, r30, lo8(%1)) CR_TAB
AS2 (ldi, r31, hi8(%1)) CR_TAB
\"%!icall\");
@ -2846,7 +2848,27 @@
(set_attr "length" "1")])
; indirect jump
(define_insn "indirect_jump"
(define_expand "indirect_jump"
[(set (pc) (match_operand:HI 0 "nonmemory_operand" ""))]
""
" if ((!AVR_HAVE_JMP_CALL) && !register_operand(operand0, HImode))
{
operands[0] = copy_to_mode_reg(HImode, operand0);
}"
)
; indirect jump
(define_insn "*jcindirect_jump"
[(set (pc) (match_operand:HI 0 "immediate_operand" "i"))]
""
"@
%~jmp %x0"
[(set_attr "length" "2")
(set_attr "cc" "none")])
;;
(define_insn "*njcindirect_jump"
[(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))]
"!AVR_HAVE_EIJMP_EICALL"
"@
@ -2884,7 +2906,7 @@
(use (label_ref (match_operand 1 "" "")))
(clobber (match_dup 0))]
"AVR_HAVE_JMP_CALL && TARGET_CALL_PROLOGUES"
"jmp __tablejump2__"
"%~jmp __tablejump2__"
[(set_attr "length" "2")
(set_attr "cc" "clobber")])
@ -2967,7 +2989,7 @@
"(optimize > 0)"
{
operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
return AS2 (cbi,%0-0x20,%2);
return AS2 (cbi,%m0-0x20,%2);
}
[(set_attr "length" "1")
(set_attr "cc" "none")])
@ -2979,7 +3001,7 @@
"(optimize > 0)"
{
operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
return AS2 (sbi,%0-0x20,%2);
return AS2 (sbi,%m0-0x20,%2);
}
[(set_attr "length" "1")
(set_attr "cc" "none")])

View File

@ -71,6 +71,29 @@
(define_predicate "symbol_ref_operand"
(match_code "symbol_ref"))
;; Return true if OP is a text segment reference.
;; This is needed for program memory address expressions.
(define_predicate "text_segment_operand"
(match_code "code_label,label_ref,symbol_ref,plus,const")
{
switch (GET_CODE (op))
{
case CODE_LABEL:
return true;
case LABEL_REF :
return true;
case SYMBOL_REF :
return SYMBOL_REF_FUNCTION_P (op);
case PLUS :
/* Assume canonical format of symbol + constant.
Fall through. */
case CONST :
return text_segment_operand (XEXP (op, 0), VOIDmode);
default :
return false;
}
})
;; Return true if OP is a constant that contains only one 1 in its
;; binary representation.
(define_predicate "single_one_operand"