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> 2009-12-24 Steven Bosscher <steven@gcc.gnu.org>
* store-motion.c (build_store_vectors): Clear regs_set_in_block at * 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: default:
if (CONSTANT_ADDRESS_P (addr) if (CONSTANT_ADDRESS_P (addr)
&& ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr)) && text_segment_operand (addr, VOIDmode))
|| GET_CODE (addr) == LABEL_REF))
{ {
fprintf (file, "gs("); rtx x = XEXP (addr,0);
output_addr_const (file,addr); if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
fprintf (file ,")"); {
/* 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 else
output_addr_const (file, addr); output_addr_const (file, addr);
@ -1221,12 +1242,18 @@ print_operand (FILE *file, rtx x, int code)
else if (GET_CODE (x) == MEM) else if (GET_CODE (x) == MEM)
{ {
rtx addr = XEXP (x,0); rtx addr = XEXP (x,0);
if (code == 'm')
if (CONSTANT_P (addr) && abcd)
{ {
fputc ('(', file); if (!CONSTANT_P (addr))
output_address (addr); fatal_insn ("bad address, not a constant):", addr);
fprintf (file, ")+%d", abcd); /* 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') else if (code == 'o')
{ {
@ -1257,6 +1284,18 @@ print_operand (FILE *file, rtx x, int code)
else else
print_operand_address (file, addr); 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) else if (GET_CODE (x) == CONST_DOUBLE)
{ {
long val; long val;
@ -1874,10 +1913,10 @@ out_movqi_r_mr (rtx insn, rtx op[], int *l)
if (optimize > 0 && io_address_operand (x, QImode)) if (optimize > 0 && io_address_operand (x, QImode))
{ {
*l = 1; *l = 1;
return AS2 (in,%0,%1-0x20); return AS2 (in,%0,%m1-0x20);
} }
*l = 2; *l = 2;
return AS2 (lds,%0,%1); return AS2 (lds,%0,%m1);
} }
/* memory access by reg+disp */ /* memory access by reg+disp */
else if (GET_CODE (x) == PLUS 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)) if (optimize > 0 && io_address_operand (base, HImode))
{ {
*l = 2; *l = 2;
return (AS2 (in,%A0,%A1-0x20) CR_TAB return (AS2 (in,%A0,%m1-0x20) CR_TAB
AS2 (in,%B0,%B1-0x20)); AS2 (in,%B0,%m1+1-0x20));
} }
*l = 4; *l = 4;
return (AS2 (lds,%A0,%A1) CR_TAB return (AS2 (lds,%A0,%m1) CR_TAB
AS2 (lds,%B0,%B1)); AS2 (lds,%B0,%m1+1));
} }
fatal_insn ("unknown move insn:",insn); 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,%C0,%1) CR_TAB
AS2 (ld,%D0,%1)); AS2 (ld,%D0,%1));
else if (CONSTANT_ADDRESS_P (base)) else if (CONSTANT_ADDRESS_P (base))
return *l=8, (AS2 (lds,%A0,%A1) CR_TAB return *l=8, (AS2 (lds,%A0,%m1) CR_TAB
AS2 (lds,%B0,%B1) CR_TAB AS2 (lds,%B0,%m1+1) CR_TAB
AS2 (lds,%C0,%C1) CR_TAB AS2 (lds,%C0,%m1+2) CR_TAB
AS2 (lds,%D0,%D1)); AS2 (lds,%D0,%m1+3));
fatal_insn ("unknown move insn:",insn); fatal_insn ("unknown move insn:",insn);
return ""; return "";
@ -2249,10 +2288,10 @@ out_movsi_mr_r (rtx insn, rtx op[], int *l)
l = &tmp; l = &tmp;
if (CONSTANT_ADDRESS_P (base)) if (CONSTANT_ADDRESS_P (base))
return *l=8,(AS2 (sts,%A0,%A1) CR_TAB return *l=8,(AS2 (sts,%m0,%A1) CR_TAB
AS2 (sts,%B0,%B1) CR_TAB AS2 (sts,%m0+1,%B1) CR_TAB
AS2 (sts,%C0,%C1) CR_TAB AS2 (sts,%m0+2,%C1) CR_TAB
AS2 (sts,%D0,%D1)); AS2 (sts,%m0+3,%D1));
if (reg_base > 0) /* (r) */ if (reg_base > 0) /* (r) */
{ {
if (reg_base == REG_X) /* (R26) */ 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)) if (optimize > 0 && io_address_operand (x, QImode))
{ {
*l = 1; *l = 1;
return AS2 (out,%0-0x20,%1); return AS2 (out,%m0-0x20,%1);
} }
*l = 2; *l = 2;
return AS2 (sts,%0,%1); return AS2 (sts,%m0,%1);
} }
/* memory access by reg+disp */ /* memory access by reg+disp */
else if (GET_CODE (x) == PLUS 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)) if (optimize > 0 && io_address_operand (base, HImode))
{ {
*l = 2; *l = 2;
return (AS2 (out,%B0-0x20,%B1) CR_TAB return (AS2 (out,%m0+1-0x20,%B1) CR_TAB
AS2 (out,%A0-0x20,%A1)); AS2 (out,%m0-0x20,%A1));
} }
return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB return *l = 4, (AS2 (sts,%m0+1,%B1) CR_TAB
AS2 (sts,%A0,%A1)); AS2 (sts,%m0,%A1));
} }
if (reg_base > 0) if (reg_base > 0)
{ {
@ -4502,8 +4541,7 @@ static bool
avr_assemble_integer (rtx x, unsigned int size, int aligned_p) avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
{ {
if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
&& ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x)) && text_segment_operand (x, VOIDmode) )
|| GET_CODE (x) == LABEL_REF))
{ {
fputs ("\t.word\tgs(", asm_out_file); fputs ("\t.word\tgs(", asm_out_file);
output_addr_const (asm_out_file, x); 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 (INTVAL (operands[1]) < 0x40)
{ {
if (comp == EQ) if (comp == EQ)
output_asm_insn (AS2 (sbis,%1-0x20,%2), operands); output_asm_insn (AS2 (sbis,%m1-0x20,%2), operands);
else else
output_asm_insn (AS2 (sbic,%1-0x20,%2), operands); output_asm_insn (AS2 (sbic,%m1-0x20,%2), operands);
} }
else else
{ {
output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands); output_asm_insn (AS2 (in,__tmp_reg__,%m1-0x20), operands);
if (comp == EQ) if (comp == EQ)
output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands); output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
else else
@ -5979,9 +6017,9 @@ avr_out_sbxx_branch (rtx insn, rtx operands[])
if (long_jump) if (long_jump)
return (AS1 (rjmp,.+4) CR_TAB return (AS1 (rjmp,.+4) CR_TAB
AS1 (jmp,%3)); AS1 (jmp,%x3));
if (!reverse) if (!reverse)
return AS1 (rjmp,%3); return AS1 (rjmp,%x3);
return ""; return "";
} }

View File

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

View File

@ -71,6 +71,29 @@
(define_predicate "symbol_ref_operand" (define_predicate "symbol_ref_operand"
(match_code "symbol_ref")) (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 ;; Return true if OP is a constant that contains only one 1 in its
;; binary representation. ;; binary representation.
(define_predicate "single_one_operand" (define_predicate "single_one_operand"