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);
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')
{
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;
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
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);
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 "";
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) */
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
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)
{
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);
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
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 "";
}
;; 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.
""
"*{
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" "")
\"%!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\");
\"%!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\");
(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"
"@
(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")])
"(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")])
"(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")])