<s>
const
char
*
avr_out_insert_bits
(
rtx
*
op
,
int
*
plen
)
{
unsigned
int
map
=
UINTVAL
(
op
[
1
]
)
&
GET_MODE_MASK
(
SImode
)
;
unsigned
mask_fixed
;
bool
fixp_p
=
true
;
rtx
xop
[
4
]
;
xop
[
0
]
=
op
[
0
]
;
xop
[
1
]
=
op
[
2
]
;
xop
[
2
]
=
op
[
3
]
;
gcc_assert
(
REG_P
(
xop
[
2
]
)
||
CONST_INT_P
(
xop
[
2
]
)
)
;
if
(
plen
)
*
plen
=
0
;
else
if
(
flag_print_asm_name
)
fprintf
(
asm_out_file
,
ASM_COMMENT_START
"map = 0x%08x\n"
,
map
)
;
mask_fixed
=
avr_map_metric
(
map
,
MAP_MASK_FIXED_0_7
)
;
if
(
REGNO
(
xop
[
0
]
)
==
REGNO
(
xop
[
1
]
)
)
{
avr_asm_len
(
"mov __tmp_reg__,%1"
,
xop
,
plen
,
1
)
;
xop
[
1
]
=
tmp_reg_rtx
;
fixp_p
=
false
;
}
if
(
avr_map_metric
(
map
,
MAP_MASK_PREIMAGE_F
)
)
{
int
n_fix
=
0
,
n_nofix
=
0
;
gcc_assert
(
REG_P
(
xop
[
2
]
)
)
;
avr_move_bits
(
xop
,
map
,
true
,
&
n_fix
)
;
avr_move_bits
(
xop
,
map
,
false
,
&
n_nofix
)
;
if
(
fixp_p
&&
n_fix
n_nofix
>
3
)
{
xop
[
3
]
=
gen_int_mode
(
~
mask_fixed
,
QImode
)
;
avr_asm_len
(
"eor %0,%1"
CR_TAB
"andi %0,%3"
CR_TAB
"eor %0,%1"
,
xop
,
plen
,
3
)
;
fixp_p
=
false
;
}
}
else
{
if
(
fixp_p
&&
mask_fixed
)
{
avr_asm_len
(
"mov %0,%1"
,
xop
,
plen
,
1
)
;
fixp_p
=
false
;
}
}
avr_move_bits
(
xop
,
map
,
fixp_p
,
plen
)
;
return
""
;
}
</s>

PLEN == 0 : Print assembler code for ` insert_bits ' . PLEN ! = 0 : Compute code length in bytes . OP [ 0 ] : Result OP [ 1 ] : The mapping composed of nibbles . If nibble no . N is 0 : Bit N of result is copied from bit OP [ 2 ] .0 ... ... 7 : Bit N of result is copied from bit OP [ 2 ] .7 0xf : Bit N of result is copied from bit OP [ 3 ] .N OP [ 2 ] : Bits to be inserted OP [ 3 ] : Target value


<s>
const
char
*
avr_out_insert_notbit
(
rtx_insn
*
insn
,
rtx
operands
[
]
,
rtx
xbitno
,
int
*
plen
)
{
rtx
op
[
4
]
=
{
operands
[
0
]
,
operands
[
1
]
,
operands
[
2
]
,
xbitno
==
NULL_RTX
operands
[
3
]
:
xbitno
}
;
if
(
INTVAL
(
op
[
1
]
)
==
7
&&
test_hard_reg_class
(
LD_REGS
,
op
[
0
]
)
)
{
if
(
INTVAL
(
op
[
3
]
)
==
7
&&
REGNO
(
op
[
0
]
)
==
REGNO
(
op
[
2
]
)
)
{
avr_asm_len
(
"subi %0,0x80"
,
op
,
plen
,
1
)
;
}
else
{
avr_asm_len
(
"bst %2,%3"
CR_TAB
"bld %0,%1"
CR_TAB
"subi %0,0x80"
,
op
,
plen
,
3
)
;
}
}
else
if
(
test_hard_reg_class
(
LD_REGS
,
op
[
0
]
)
&&
(
INTVAL
(
op
[
1
]
)
!=
INTVAL
(
op
[
3
]
)
||
!
reg_overlap_mentioned_p
(
op
[
0
]
,
op
[
2
]
)
)
)
{
avr_asm_len
(
"andi %0,~(1<<%1)"
CR_TAB
"sbrs %2,%3"
CR_TAB
"ori %0,1<<%1"
,
op
,
plen
,
3
)
;
}
else
{
avr_asm_len
(
"com %2"
CR_TAB
"bst %2,%3"
,
op
,
plen
,
2
)
;
if
(
!
reg_unused_after
(
insn
,
op
[
2
]
)
||
reg_overlap_mentioned_p
(
op
[
0
]
,
op
[
2
]
)
)
{
avr_asm_len
(
"com %2"
,
op
,
plen
,
1
)
;
}
avr_asm_len
(
"bld %0,%1"
,
op
,
plen
,
1
)
;
}
return
""
;
}
</s>

Output instructions to insert an inverted bit into OPERANDS [ 0 ] : $ 0. $ 1 = ~ $ 2. $ 3 if XBITNO = NULL $ 0. $ 1 = ~ $ 2.XBITNO if XBITNO ! = NULL . If PLEN = NULL then output the respective instruction sequence which is a combination of BST / BLD and some instruction ( s ) to invert the bit . If PLEN ! = NULL then store the length of the sequence ( in words ) in * PLEN . Return `` '' .


<s>
static
const
char
*
avr_out_load_psi_reg_no_disp_tiny
(
rtx_insn
*
insn
,
rtx
*
op
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
base
=
XEXP
(
src
,
0
)
;
int
reg_dest
=
true_regnum
(
dest
)
;
int
reg_base
=
true_regnum
(
base
)
;
if
(
reg_base
==
reg_dest
)
{
return
avr_asm_len
(
TINY_ADIW
(
%
E1
,
%
F1
,
2
)
CR_TAB
"ld %C0,%1"
CR_TAB
"ld __tmp_reg__,-%1"
CR_TAB
TINY_SBIW
(
%
E1
,
%
F1
,
1
)
CR_TAB
"ld %A0,%1"
CR_TAB
"mov %B0,__tmp_reg__"
,
op
,
plen
,
8
)
;
}
else
{
avr_asm_len
(
"ld %A0,%1+"
CR_TAB
"ld %B0,%1+"
CR_TAB
"ld %C0,%1"
,
op
,
plen
,
3
)
;
if
(
reg_dest
!=
reg_base
2
&&
!
reg_unused_after
(
insn
,
base
)
)
{
avr_asm_len
(
TINY_SBIW
(
%
E1
,
%
F1
,
2
)
,
op
,
plen
,
2
)
;
}
return
""
;
}
}
</s>

Handle loads of 24-bit types from memory to register .


<s>
static
const
char
*
avr_out_lpm_no_lpmx
(
rtx_insn
*
insn
,
rtx
*
xop
,
int
*
plen
)
{
rtx
dest
=
xop
[
0
]
;
rtx
addr
=
xop
[
1
]
;
int
n_bytes
=
GET_MODE_SIZE
(
GET_MODE
(
dest
)
)
;
int
regno_dest
;
regno_dest
=
REGNO
(
dest
)
;
xop
[
3
]
=
lpm_reg_rtx
;
switch
(
GET_CODE
(
addr
)
)
{
default
:
gcc_unreachable
(
)
;
case
REG
:
gcc_assert
(
REG_Z
==
REGNO
(
addr
)
)
;
switch
(
n_bytes
)
{
default
:
gcc_unreachable
(
)
;
case
1
:
avr_asm_len
(
"%4lpm"
,
xop
,
plen
,
1
)
;
if
(
regno_dest
!=
LPM_REGNO
)
avr_asm_len
(
"mov %0,%3"
,
xop
,
plen
,
1
)
;
return
""
;
case
2
:
if
(
REGNO
(
dest
)
==
REG_Z
)
return
avr_asm_len
(
"%4lpm"
CR_TAB
"push %3"
CR_TAB
"adiw %2,1"
CR_TAB
"%4lpm"
CR_TAB
"mov %B0,%3"
CR_TAB
"pop %A0"
,
xop
,
plen
,
6
)
;
avr_asm_len
(
"%4lpm"
CR_TAB
"mov %A0,%3"
CR_TAB
"adiw %2,1"
CR_TAB
"%4lpm"
CR_TAB
"mov %B0,%3"
,
xop
,
plen
,
5
)
;
if
(
!
reg_unused_after
(
insn
,
addr
)
)
avr_asm_len
(
"sbiw %2,1"
,
xop
,
plen
,
1
)
;
break
;
}
break
;
case
POST_INC
:
gcc_assert
(
REG_Z
==
REGNO
(
XEXP
(
addr
,
0
)
)
&&
n_bytes
<=
4
)
;
if
(
regno_dest
==
LPM_REGNO
)
avr_asm_len
(
"%4lpm"
CR_TAB
"adiw %2,1"
,
xop
,
plen
,
2
)
;
else
avr_asm_len
(
"%4lpm"
CR_TAB
"mov %A0,%3"
CR_TAB
"adiw %2,1"
,
xop
,
plen
,
3
)
;
if
(
n_bytes
>=
2
)
avr_asm_len
(
"%4lpm"
CR_TAB
"mov %B0,%3"
CR_TAB
"adiw %2,1"
,
xop
,
plen
,
3
)
;
if
(
n_bytes
>=
3
)
avr_asm_len
(
"%4lpm"
CR_TAB
"mov %C0,%3"
CR_TAB
"adiw %2,1"
,
xop
,
plen
,
3
)
;
if
(
n_bytes
>=
4
)
avr_asm_len
(
"%4lpm"
CR_TAB
"mov %D0,%3"
CR_TAB
"adiw %2,1"
,
xop
,
plen
,
3
)
;
break
;
}
return
""
;
}
</s>

Helper function for the next function in the case where only restricted version of LPM instruction is available .


<s>
const
char
*
avr_out_lshrpsi3
(
rtx_insn
*
insn
,
rtx
*
op
,
int
*
plen
)
{
int
dest
=
REGNO
(
op
[
0
]
)
;
int
src
=
REGNO
(
op
[
1
]
)
;
if
(
CONST_INT_P
(
op
[
2
]
)
)
{
if
(
plen
)
*
plen
=
0
;
switch
(
INTVAL
(
op
[
2
]
)
)
{
case
8
:
if
(
dest
<=
src
)
return
avr_asm_len
(
"mov %A0,%B1"
CR_TAB
"mov %B0,%C1"
CR_TAB
"clr %C0"
,
op
,
plen
,
3
)
;
else
return
avr_asm_len
(
"clr %C0"
CR_TAB
"mov %B0,%C1"
CR_TAB
"mov %A0,%B1"
,
op
,
plen
,
3
)
;
case
16
:
if
(
dest
!=
src
+
2
)
avr_asm_len
(
"mov %A0,%C1"
,
op
,
plen
,
1
)
;
return
avr_asm_len
(
"clr %B0"
CR_TAB
"clr %C0"
,
op
,
plen
,
2
)
;
default
:
if
(
INTVAL
(
op
[
2
]
)
<
24
)
break
;
case
23
:
return
avr_asm_len
(
"clr %A0"
CR_TAB
"sbrc %C0,7"
CR_TAB
"inc %A0"
CR_TAB
"clr %B0"
CR_TAB
"clr %C0"
,
op
,
plen
,
5
)
;
}
}
out_shift_with_cnt
(
"lsr %C0"
CR_TAB
"ror %B0"
CR_TAB
"ror %A0"
,
insn
,
op
,
plen
,
3
)
;
return
""
;
}
</s>


<s>
static
const
char
*
avr_out_movhi_mr_r_xmega
(
rtx_insn
*
insn
,
rtx
op
[
]
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
base
=
XEXP
(
dest
,
0
)
;
int
reg_base
=
true_regnum
(
base
)
;
int
reg_src
=
true_regnum
(
src
)
;
int
mem_volatile_p
=
MEM_VOLATILE_P
(
dest
)
;
if
(
CONSTANT_ADDRESS_P
(
base
)
)
{
return
io_address_operand
(
base
,
HImode
)
avr_asm_len
(
"out %i0,%A1"
CR_TAB
"out %i0+1,%B1"
,
op
,
plen
,
2
)
:
avr_asm_len
(
"sts %m0,%A1"
CR_TAB
"sts %m0+1,%B1"
,
op
,
plen
,
4
)
;
}
if
(
reg_base
>
0
)
{
if
(
reg_base
!=
REG_X
)
return
avr_asm_len
(
"st %0,%A1"
CR_TAB
"std %0+1,%B1"
,
op
,
plen
,
2
)
;
if
(
reg_src
==
REG_X
)
avr_asm_len
(
"mov __tmp_reg__,r27"
CR_TAB
"st X,r26"
CR_TAB
"adiw r26,1"
CR_TAB
"st X,__tmp_reg__"
,
op
,
plen
,
4
)
;
else
avr_asm_len
(
"st X+,%A1"
CR_TAB
"st X,%B1"
,
op
,
plen
,
2
)
;
return
reg_unused_after
(
insn
,
base
)
""
:
avr_asm_len
(
"sbiw r26,1"
,
op
,
plen
,
1
)
;
}
else
if
(
GET_CODE
(
base
)
==
PLUS
)
{
int
disp
=
INTVAL
(
XEXP
(
base
,
1
)
)
;
reg_base
=
REGNO
(
XEXP
(
base
,
0
)
)
;
if
(
disp
>
MAX_LD_OFFSET
(
GET_MODE
(
dest
)
)
)
{
if
(
reg_base
!=
REG_Y
)
fatal_insn
(
"incorrect insn:"
,
insn
)
;
return
disp
<=
63
+
MAX_LD_OFFSET
(
GET_MODE
(
dest
)
)
avr_asm_len
(
"adiw r28,%o0-62"
CR_TAB
"std Y+62,%A1"
CR_TAB
"std Y+63,%B1"
CR_TAB
"sbiw r28,%o0-62"
,
op
,
plen
,
4
)
:
avr_asm_len
(
"subi r28,lo8(-%o0)"
CR_TAB
"sbci r29,hi8(-%o0)"
CR_TAB
"st Y,%A1"
CR_TAB
"std Y+1,%B1"
CR_TAB
"subi r28,lo8(%o0)"
CR_TAB
"sbci r29,hi8(%o0)"
,
op
,
plen
,
6
)
;
}
if
(
reg_base
!=
REG_X
)
return
avr_asm_len
(
"std %A0,%A1"
CR_TAB
"std %B0,%B1"
,
op
,
plen
,
2
)
;
return
reg_src
==
REG_X
avr_asm_len
(
"mov __tmp_reg__,r26"
CR_TAB
"mov __zero_reg__,r27"
CR_TAB
"adiw r26,%o0"
CR_TAB
"st X+,__tmp_reg__"
CR_TAB
"st X,__zero_reg__"
CR_TAB
"clr __zero_reg__"
CR_TAB
"sbiw r26,%o0+1"
,
op
,
plen
,
7
)
:
avr_asm_len
(
"adiw r26,%o0"
CR_TAB
"st X+,%A1"
CR_TAB
"st X,%B1"
CR_TAB
"sbiw r26,%o0+1"
,
op
,
plen
,
4
)
;
}
else
if
(
GET_CODE
(
base
)
==
PRE_DEC
)
{
if
(
!
mem_volatile_p
)
return
avr_asm_len
(
"st %0,%B1"
CR_TAB
"st %0,%A1"
,
op
,
plen
,
2
)
;
return
REGNO
(
XEXP
(
base
,
0
)
)
==
REG_X
avr_asm_len
(
"sbiw r26,2"
CR_TAB
"st X+,%A1"
CR_TAB
"st X,%B1"
CR_TAB
"sbiw r26,1"
,
op
,
plen
,
4
)
:
avr_asm_len
(
"sbiw %r0,2"
CR_TAB
"st %p0,%A1"
CR_TAB
"std %p0+1,%B1"
,
op
,
plen
,
3
)
;
}
else
if
(
GET_CODE
(
base
)
==
POST_INC
)
{
return
avr_asm_len
(
"st %0,%A1"
CR_TAB
"st %0,%B1"
,
op
,
plen
,
2
)
;
}
fatal_insn
(
"unknown move insn:"
,
insn
)
;
return
""
;
}
</s>

Helper for the next function for XMEGA . It does the same but with low byte first .


<s>
static
const
char
*
avr_out_movhi_r_mr_pre_dec_tiny
(
rtx_insn
*
insn
,
rtx
op
[
]
,
int
*
plen
)
{
int
mem_volatile_p
=
0
;
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
base
=
XEXP
(
src
,
0
)
;
mem_volatile_p
=
MEM_VOLATILE_P
(
src
)
;
if
(
reg_overlap_mentioned_p
(
dest
,
XEXP
(
base
,
0
)
)
)
fatal_insn
(
"incorrect insn:"
,
insn
)
;
if
(
!
mem_volatile_p
)
return
avr_asm_len
(
"ld %B0,%1"
CR_TAB
"ld %A0,%1"
,
op
,
plen
,
2
)
;
return
avr_asm_len
(
TINY_SBIW
(
%
I1
,
%
J1
,
2
)
CR_TAB
"ld %A0,%p1+"
CR_TAB
"ld %B0,%p1"
CR_TAB
TINY_SBIW
(
%
I1
,
%
J1
,
1
)
,
op
,
plen
,
6
)
;
}
</s>

Same as movhi_r_mr , but TINY does not have ADIW , SBIW and LDD


<s>
static
const
char
*
avr_out_movhi_r_mr_reg_disp_tiny
(
rtx_insn
*
insn
,
rtx
op
[
]
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
base
=
XEXP
(
src
,
0
)
;
int
reg_dest
=
true_regnum
(
dest
)
;
int
reg_base
=
true_regnum
(
XEXP
(
base
,
0
)
)
;
if
(
reg_base
==
reg_dest
)
{
return
avr_asm_len
(
TINY_ADIW
(
%
I1
,
%
J1
,
%
o1
)
CR_TAB
"ld __tmp_reg__,%b1+"
CR_TAB
"ld %B0,%b1"
CR_TAB
"mov %A0,__tmp_reg__"
,
op
,
plen
,
5
)
;
}
else
{
avr_asm_len
(
TINY_ADIW
(
%
I1
,
%
J1
,
%
o1
)
CR_TAB
"ld %A0,%b1+"
CR_TAB
"ld %B0,%b1"
,
op
,
plen
,
4
)
;
if
(
!
reg_unused_after
(
insn
,
XEXP
(
base
,
0
)
)
)
avr_asm_len
(
TINY_SBIW
(
%
I1
,
%
J1
,
%
o1
+
1
)
,
op
,
plen
,
2
)
;
return
""
;
}
}
</s>


<s>
static
const
char
*
avr_out_movhi_r_mr_reg_no_disp_tiny
(
rtx_insn
*
insn
,
rtx
op
[
]
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
base
=
XEXP
(
src
,
0
)
;
int
reg_dest
=
true_regnum
(
dest
)
;
int
reg_base
=
true_regnum
(
base
)
;
if
(
reg_dest
==
reg_base
)
return
avr_asm_len
(
"ld __tmp_reg__,%1+"
CR_TAB
"ld %B0,%1"
CR_TAB
"mov %A0,__tmp_reg__"
,
op
,
plen
,
3
)
;
avr_asm_len
(
"ld %A0,%1+"
CR_TAB
"ld %B0,%1"
,
op
,
plen
,
2
)
;
if
(
!
reg_unused_after
(
insn
,
base
)
)
avr_asm_len
(
TINY_SBIW
(
%
E1
,
%
F1
,
1
)
,
op
,
plen
,
2
)
;
return
""
;
}
</s>


<s>
const
char
*
avr_out_movpsi
(
rtx_insn
*
insn
,
rtx
*
op
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
if
(
avr_mem_flash_p
(
src
)
||
avr_mem_flash_p
(
dest
)
)
{
return
avr_out_lpm
(
insn
,
op
,
plen
)
;
}
if
(
register_operand
(
dest
,
VOIDmode
)
)
{
if
(
register_operand
(
src
,
VOIDmode
)
)
{
if
(
true_regnum
(
dest
)
>
true_regnum
(
src
)
)
{
avr_asm_len
(
"mov %C0,%C1"
,
op
,
plen
,
1
)
;
if
(
AVR_HAVE_MOVW
)
return
avr_asm_len
(
"movw %A0,%A1"
,
op
,
plen
,
1
)
;
else
return
avr_asm_len
(
"mov %B0,%B1"
CR_TAB
"mov %A0,%A1"
,
op
,
plen
,
2
)
;
}
else
{
if
(
AVR_HAVE_MOVW
)
avr_asm_len
(
"movw %A0,%A1"
,
op
,
plen
,
1
)
;
else
avr_asm_len
(
"mov %A0,%A1"
CR_TAB
"mov %B0,%B1"
,
op
,
plen
,
2
)
;
return
avr_asm_len
(
"mov %C0,%C1"
,
op
,
plen
,
1
)
;
}
}
else
if
(
CONSTANT_P
(
src
)
)
{
return
avr_out_reload_inpsi
(
op
,
NULL_RTX
,
plen
)
;
}
else
if
(
MEM_P
(
src
)
)
return
avr_out_load_psi
(
insn
,
op
,
plen
)
;
}
else
if
(
MEM_P
(
dest
)
)
{
rtx
xop
[
2
]
;
xop
[
0
]
=
dest
;
xop
[
1
]
=
src
==
CONST0_RTX
(
GET_MODE
(
dest
)
)
zero_reg_rtx
:
src
;
return
avr_out_store_psi
(
insn
,
xop
,
plen
)
;
}
fatal_insn
(
"invalid insn:"
,
insn
)
;
return
""
;
}
</s>


<s>
static
const
char
*
avr_out_movqi_r_mr_reg_disp_tiny
(
rtx_insn
*
insn
,
rtx
op
[
]
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
x
=
XEXP
(
src
,
0
)
;
avr_asm_len
(
TINY_ADIW
(
%
I1
,
%
J1
,
%
o1
)
CR_TAB
"ld %0,%b1"
,
op
,
plen
,
3
)
;
if
(
!
reg_overlap_mentioned_p
(
dest
,
XEXP
(
x
,
0
)
)
&&
!
reg_unused_after
(
insn
,
XEXP
(
x
,
0
)
)
)
avr_asm_len
(
TINY_SBIW
(
%
I1
,
%
J1
,
%
o1
)
,
op
,
plen
,
2
)
;
return
""
;
}
</s>

Same as out_movqi_r_mr , but TINY does not have ADIW or SBIW


<s>
static
const
char
*
avr_out_plus_symbol
(
rtx
*
xop
,
enum
rtx_code
code
,
int
*
plen
,
int
*
pcc
)
{
machine_mode
mode
=
GET_MODE
(
xop
[
0
]
)
;
gcc_assert
(
mode
==
HImode
||
mode
==
PSImode
)
;
*
pcc
=
MINUS
==
code
(
int
)
CC_SET_CZN
:
(
int
)
CC_SET_N
;
avr_asm_len
(
PLUS
==
code
"subi %A0,lo8(-(%2))"
CR_TAB
"sbci %B0,hi8(-(%2))"
:
"subi %A0,lo8(%2)"
CR_TAB
"sbci %B0,hi8(%2)"
,
xop
,
plen
,
2
)
;
if
(
PSImode
==
mode
)
avr_asm_len
(
PLUS
==
code
"sbci %C0,hlo8(-(%2))"
:
"sbci %C0,hlo8(%2)"
,
xop
,
plen
,
1
)
;
return
""
;
}
</s>

Output addition/subtraction of register XOP [ 0 ] and a constant XOP [ 2 ] that is ont a compile-time constant : XOP [ 0 ] = XOP [ 0 ] +/- XOP [ 2 ] This is a helper for the function below . The only insns that need this are additions/subtraction for pointer modes , i.e . HImode and PSImode .


<s>
const
char
*
avr_out_round
(
rtx_insn
*
insn
ATTRIBUTE_UNUSED
,
rtx
*
xop
,
int
*
plen
)
{
scalar_mode
mode
=
as_a
<
scalar_mode
>
(
GET_MODE
(
xop
[
0
]
)
)
;
scalar_int_mode
imode
=
int_mode_for_mode
(
mode
)
.
require
(
)
;
int
fbit
=
(
int
)
GET_MODE_FBIT
(
mode
)
;
double_int
i_add
=
double_int_zero
.
set_bit
(
fbit
1
INTVAL
(
xop
[
2
]
)
)
;
wide_int
wi_add
=
wi
::
set_bit_in_zero
(
fbit
1
INTVAL
(
xop
[
2
]
)
,
GET_MODE_PRECISION
(
imode
)
)
;
int
len_add
=
0
,
*
plen_add
=
plen
&
len_add
:
;
int
len_and
=
0
,
*
plen_and
=
plen
&
len_and
:
;
rtx
xadd
=
const_fixed_from_double_int
(
i_add
,
mode
)
;
rtx
xpattern
,
xsrc
,
op
[
4
]
;
xsrc
=
SIGNED_FIXED_POINT_MODE_P
(
mode
)
gen_rtx_SS_PLUS
(
mode
,
xop
[
1
]
,
xadd
)
:
gen_rtx_US_PLUS
(
mode
,
xop
[
1
]
,
xadd
)
;
xpattern
=
gen_rtx_SET
(
xop
[
0
]
,
xsrc
)
;
op
[
0
]
=
xop
[
0
]
;
op
[
1
]
=
xop
[
1
]
;
op
[
2
]
=
xadd
;
avr_out_plus
(
xpattern
,
op
,
plen_add
,
,
false
)
;
avr_asm_len
(
"rjmp 1f"
CR_TAB
"0:"
,
,
plen_add
,
1
)
;
rtx
xreg
=
simplify_gen_subreg
(
imode
,
xop
[
0
]
,
mode
,
0
)
;
rtx
xmask
=
immed_wide_int_const
(
wi_add
wi_add
,
imode
)
;
xpattern
=
gen_rtx_SET
(
xreg
,
gen_rtx_AND
(
imode
,
xreg
,
xmask
)
)
;
op
[
0
]
=
xreg
;
op
[
1
]
=
xreg
;
op
[
2
]
=
xmask
;
op
[
3
]
=
gen_rtx_SCRATCH
(
QImode
)
;
avr_out_bitop
(
xpattern
,
op
,
plen_and
)
;
avr_asm_len
(
"1:"
,
,
plen
,
0
)
;
if
(
plen
)
*
plen
=
len_add
+
len_and
;
return
""
;
}
</s>

Output fixed-point rounding . XOP [ 0 ] = XOP [ 1 ] is the operand to round . XOP [ 2 ] is the rounding point , a CONST_INT . The function prints the instruction sequence if PLEN = NULL and computes the length in words of the sequence if PLEN ! = NULL . Most of this function deals with preparing operands for calls to ` avr_out_plus ' and ` avr_out_bitop ' .


<s>
const
char
*
avr_out_sbxx_branch
(
rtx_insn
*
insn
,
rtx
operands
[
]
)
{
enum
rtx_code
comp
=
GET_CODE
(
operands
[
0
]
)
;
bool
long_jump
=
get_attr_length
(
insn
)
>=
4
;
bool
reverse
=
long_jump
||
jump_over_one_insn_p
(
insn
,
operands
[
3
]
)
;
if
(
comp
==
GE
)
comp
=
EQ
;
else
if
(
comp
==
LT
)
comp
=
NE
;
if
(
reverse
)
comp
=
reverse_condition
(
comp
)
;
switch
(
GET_CODE
(
operands
[
1
]
)
)
{
default
:
gcc_unreachable
(
)
;
case
CONST_INT
:
case
CONST
:
case
SYMBOL_REF
:
if
(
low_io_address_operand
(
operands
[
1
]
,
QImode
)
)
{
if
(
comp
==
EQ
)
output_asm_insn
(
"sbis %i1,%2"
,
operands
)
;
else
output_asm_insn
(
"sbic %i1,%2"
,
operands
)
;
}
else
{
gcc_assert
(
io_address_operand
(
operands
[
1
]
,
QImode
)
)
;
output_asm_insn
(
"in __tmp_reg__,%i1"
,
operands
)
;
if
(
comp
==
EQ
)
output_asm_insn
(
"sbrs __tmp_reg__,%2"
,
operands
)
;
else
output_asm_insn
(
"sbrc __tmp_reg__,%2"
,
operands
)
;
}
break
;
case
REG
:
if
(
comp
==
EQ
)
output_asm_insn
(
"sbrs %T1%T2"
,
operands
)
;
else
output_asm_insn
(
"sbrc %T1%T2"
,
operands
)
;
break
;
}
if
(
long_jump
)
return
(
"rjmp .+4"
CR_TAB
"jmp %x3"
)
;
if
(
!
reverse
)
return
"rjmp %x3"
;
return
""
;
}
</s>

Output a branch that tests a single bit of a register ( QI , HI or SImode ) or memory location in the I/O space ( QImode only ) . Operand 0 : comparison operator ( must be EQ or NE , compare bit to zero ) . Operand 1 : register operand to test , or CONST_INT memory address . Operand 2 : bit number ( for QImode operand ) or mask ( HImode , SImode ) . Operand 3 : label to jump to if the test is true .


<s>
const
char
*
avr_out_sign_extend
(
rtx_insn
*
insn
,
rtx
*
xop
,
int
*
plen
)
{
unsigned
n_src
=
GET_MODE_SIZE
(
GET_MODE
(
xop
[
1
]
)
)
;
unsigned
n_dest
=
GET_MODE_SIZE
(
GET_MODE
(
xop
[
0
]
)
)
;
rtx
r_msb
=
all_regs_rtx
[
REGNO
(
xop
[
1
]
)
+
n_src
1
]
;
if
(
plen
)
*
plen
=
0
;
if
(
REGNO
(
xop
[
0
]
)
!=
REGNO
(
xop
[
1
]
)
)
{
gcc_assert
(
n_src
<=
2
)
;
if
(
n_src
==
2
)
avr_asm_len
(
AVR_HAVE_MOVW
"movw %0,%1"
:
"mov %B0,%B1"
,
xop
,
plen
,
1
)
;
if
(
n_src
==
1
||
!
AVR_HAVE_MOVW
)
avr_asm_len
(
"mov %A0,%A1"
,
xop
,
plen
,
1
)
;
}
if
(
REGNO
(
xop
[
0
]
)
==
REGNO
(
xop
[
1
]
)
||
!
reg_unused_after
(
insn
,
r_msb
)
)
{
avr_asm_len
(
"mov __tmp_reg__,%0"
,
&
r_msb
,
plen
,
1
)
;
r_msb
=
tmp_reg_rtx
;
}
avr_asm_len
(
"lsl %0"
,
&
r_msb
,
plen
,
1
)
;
for
(
unsigned
n
=
n_src
;
n
<
n_dest
;
n
++
)
avr_asm_len
(
"sbc %0,%0"
,
&
all_regs_rtx
[
REGNO
(
xop
[
0
]
)
+
n
]
,
plen
,
1
)
;
return
""
;
}
</s>

Output sign extension from XOP [ 1 ] to XOP [ 0 ] and return `` '' . If PLEN == NULL , print assembler instructions to perform the operation ; otherwise , set * PLEN to the length of the instruction sequence ( in words ) as printed with PLEN == NULL .


<s>
static
const
char
*
avr_out_store_psi
(
rtx_insn
*
insn
,
rtx
*
op
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
base
=
XEXP
(
dest
,
0
)
;
int
reg_base
=
true_regnum
(
base
)
;
if
(
CONSTANT_ADDRESS_P
(
base
)
)
{
int
n_words
=
AVR_TINY
3
:
6
;
return
avr_asm_len
(
"sts %m0,%A1"
CR_TAB
"sts %m0+1,%B1"
CR_TAB
"sts %m0+2,%C1"
,
op
,
plen
,
n_words
)
;
}
if
(
reg_base
>
0
)
{
if
(
AVR_TINY
)
return
avr_out_store_psi_reg_no_disp_tiny
(
insn
,
op
,
plen
)
;
if
(
reg_base
==
REG_X
)
{
gcc_assert
(
!
reg_overlap_mentioned_p
(
base
,
src
)
)
;
avr_asm_len
(
"st %0+,%A1"
CR_TAB
"st %0+,%B1"
CR_TAB
"st %0,%C1"
,
op
,
plen
,
3
)
;
if
(
!
reg_unused_after
(
insn
,
base
)
)
avr_asm_len
(
"sbiw r26,2"
,
op
,
plen
,
1
)
;
return
""
;
}
else
return
avr_asm_len
(
"st %0,%A1"
CR_TAB
"std %0+1,%B1"
CR_TAB
"std %0+2,%C1"
,
op
,
plen
,
3
)
;
}
else
if
(
GET_CODE
(
base
)
==
PLUS
)
{
int
disp
=
INTVAL
(
XEXP
(
base
,
1
)
)
;
if
(
AVR_TINY
)
return
avr_out_store_psi_reg_disp_tiny
(
insn
,
op
,
plen
)
;
reg_base
=
REGNO
(
XEXP
(
base
,
0
)
)
;
if
(
disp
>
MAX_LD_OFFSET
(
GET_MODE
(
dest
)
)
)
{
if
(
reg_base
!=
REG_Y
)
fatal_insn
(
"incorrect insn:"
,
insn
)
;
if
(
disp
<=
63
+
MAX_LD_OFFSET
(
GET_MODE
(
dest
)
)
)
return
avr_asm_len
(
"adiw r28,%o0-61"
CR_TAB
"std Y+61,%A1"
CR_TAB
"std Y+62,%B1"
CR_TAB
"std Y+63,%C1"
CR_TAB
"sbiw r28,%o0-61"
,
op
,
plen
,
5
)
;
return
avr_asm_len
(
"subi r28,lo8(-%o0)"
CR_TAB
"sbci r29,hi8(-%o0)"
CR_TAB
"st Y,%A1"
CR_TAB
"std Y+1,%B1"
CR_TAB
"std Y+2,%C1"
CR_TAB
"subi r28,lo8(%o0)"
CR_TAB
"sbci r29,hi8(%o0)"
,
op
,
plen
,
7
)
;
}
if
(
reg_base
==
REG_X
)
{
gcc_assert
(
!
reg_overlap_mentioned_p
(
XEXP
(
base
,
0
)
,
src
)
)
;
avr_asm_len
(
"adiw r26,%o0"
CR_TAB
"st X+,%A1"
CR_TAB
"st X+,%B1"
CR_TAB
"st X,%C1"
,
op
,
plen
,
4
)
;
if
(
!
reg_unused_after
(
insn
,
XEXP
(
base
,
0
)
)
)
avr_asm_len
(
"sbiw r26,%o0+2"
,
op
,
plen
,
1
)
;
return
""
;
}
return
avr_asm_len
(
"std %A0,%A1"
CR_TAB
"std %B0,%B1"
CR_TAB
"std %C0,%C1"
,
op
,
plen
,
3
)
;
}
else
if
(
GET_CODE
(
base
)
==
PRE_DEC
)
return
avr_asm_len
(
"st %0,%C1"
CR_TAB
"st %0,%B1"
CR_TAB
"st %0,%A1"
,
op
,
plen
,
3
)
;
else
if
(
GET_CODE
(
base
)
==
POST_INC
)
return
avr_asm_len
(
"st %0,%A1"
CR_TAB
"st %0,%B1"
CR_TAB
"st %0,%C1"
,
op
,
plen
,
3
)
;
fatal_insn
(
"unknown move insn:"
,
insn
)
;
return
""
;
}
</s>

Handle store of 24-bit type from register or zero to memory .


<s>
const
char
*
avr_out_tsthi
(
rtx_insn
*
insn
,
rtx
*
op
,
int
*
plen
)
{
if
(
compare_sign_p
(
insn
)
)
{
avr_asm_len
(
"tst %B0"
,
op
,
plen
,
1
)
;
}
else
if
(
reg_unused_after
(
insn
,
op
[
0
]
)
&&
compare_eq_p
(
insn
)
)
{
avr_asm_len
(
"or %A0,%B0"
,
op
,
plen
,
1
)
;
}
else
{
avr_out_compare
(
insn
,
op
,
plen
)
;
}
return
""
;
}
</s>


<s>
const
char
*
avr_out_tstpsi
(
rtx_insn
*
insn
,
rtx
*
op
,
int
*
plen
)
{
if
(
compare_sign_p
(
insn
)
)
{
avr_asm_len
(
"tst %C0"
,
op
,
plen
,
1
)
;
}
else
if
(
reg_unused_after
(
insn
,
op
[
0
]
)
&&
compare_eq_p
(
insn
)
)
{
avr_asm_len
(
"or %A0,%B0"
CR_TAB
"or %A0,%C0"
,
op
,
plen
,
2
)
;
}
else
{
avr_out_compare
(
insn
,
op
,
plen
)
;
}
return
""
;
}
</s>


<s>
const
char
*
avr_out_tstsi
(
rtx_insn
*
insn
,
rtx
*
op
,
int
*
plen
)
{
if
(
compare_sign_p
(
insn
)
)
{
avr_asm_len
(
"tst %D0"
,
op
,
plen
,
1
)
;
}
else
if
(
reg_unused_after
(
insn
,
op
[
0
]
)
&&
compare_eq_p
(
insn
)
)
{
avr_asm_len
(
"or %A0,%B0"
CR_TAB
"or %A0,%C0"
CR_TAB
"or %A0,%D0"
,
op
,
plen
,
3
)
;
}
else
{
avr_out_compare
(
insn
,
op
,
plen
)
;
}
return
""
;
}
</s>


<s>
const
char
*
avr_out_xload
(
rtx_insn
*
insn
ATTRIBUTE_UNUSED
,
rtx
*
op
,
int
*
plen
)
{
rtx
xop
[
4
]
;
xop
[
0
]
=
op
[
0
]
;
xop
[
1
]
=
op
[
1
]
;
xop
[
2
]
=
lpm_addr_reg_rtx
;
xop
[
3
]
=
AVR_HAVE_LPMX
op
[
0
]
:
lpm_reg_rtx
;
avr_asm_len
(
AVR_HAVE_LPMX
"lpm %3,%a2"
:
"lpm"
,
xop
,
plen
,
1
)
;
avr_asm_len
(
"sbrc %1,7"
CR_TAB
"ld %3,%a2"
,
xop
,
plen
,
2
)
;
if
(
REGNO
(
xop
[
0
]
)
!=
REGNO
(
xop
[
3
]
)
)
avr_asm_len
(
"mov %0,%3"
,
xop
,
plen
,
1
)
;
return
""
;
}
</s>


<s> static rtx_insn * avr_parallel_insn_from_insns ( rtx_insn * i [ 5 ] ) { rtvec vec = gen_rtvec ( 5 , PATTERN ( i [ 0 ] ) , PATTERN ( i [ 1 ] ) , PATTERN ( i [ 2 ] ) , PATTERN ( i [ 3 ] ) , PATTERN ( i [ 4 ] ) ) ; start_sequence ( ) ; emit ( gen_rtx_PARALLEL ( VOIDmode , vec ) ) ; rtx_insn * insn = get_insns ( ) ; end_sequence ( ) ; return insn ; } </s>

Make one parallel insn with all the patterns from insns i [ 0 ] .. i [ 5 ] .


"pointer targeting address space %qs must be const in %qT"

"pointer targeting address space %qs must be const"

Sanity check NODE so that all pointers targeting non-generic address spaces go along with CONST qualifier . Writing to these address spaces should be detected and complained about as early as possible .


<s> bool avr_popcount_each_byte ( rtx xval , int n_bytes , int pop_mask ) { machine_mode mode = GET_MODE ( xval ) ; if ( VOIDmode == mode ) mode = SImode ; for ( int i = 0 ; i < n_bytes ; i ++ ) { rtx xval8 = simplify_gen_subreg ( QImode , xval , mode , i ) ; unsigned int val8 = UINTVAL ( xval8 ) & GET_MODE_MASK ( QImode ) ; if ( ( pop_mask & ( 1 << popcount_hwi ( val8 ) ) ) == 0 ) return false ; } return true ; } </s>

Constraint helper function . XVAL is a CONST_INT or a CONST_DOUBLE . Return true if the least significant N_BYTES bytes of XVAL all have a popcount in POP_MASK and false , otherwise . POP_MASK represents a subset of integers which contains an integer N iff bit N of POP_MASK is set .


"pointer offset from symbol maybe incorrect"


<s> static bool avr_print_operand_punct_valid_p ( unsigned char code ) { return code == '~' || code == '!' ; } </s>

Implement ` TARGET_PRINT_OPERAND_PUNCT_VALID_P ' .


<s> int avr_progmem_p ( tree decl , tree attributes ) { tree a ; if ( TREE_CODE ( decl ) != VAR_DECL ) return 0 ; if ( avr_decl_memx_p ( decl ) ) return 2 ; if ( avr_decl_flash_p ( decl ) ) return 1 ; if ( NULL_TREE != lookup_attribute ( "progmem" , attributes ) ) return - 1 ; a = decl ; do a = TREE_TYPE ( a ) ; while ( TREE_CODE ( a ) == ARRAY_TYPE ) ; if ( a == error_mark_node ) return 0 ; if ( NULL_TREE != lookup_attribute ( "progmem" , TYPE_ATTRIBUTES ( a ) ) ) return - 1 ; return 0 ; } </s>

Look for attribute ` progmem ' in DECL if found return 1 , otherwise 0 .


<s> static int avr_register_move_cost ( machine_mode mode ATTRIBUTE_UNUSED , reg_class_t from , reg_class_t to ) { return ( from == STACK_REG ? 6 : to == STACK_REG ? 12 : 2 ) ; } </s>


<s> bool avr_regno_mode_code_ok_for_base_p ( int regno , machine_mode mode ATTRIBUTE_UNUSED , addr_space_t as ATTRIBUTE_UNUSED , RTX_CODE outer_code , RTX_CODE index_code ATTRIBUTE_UNUSED ) { bool ok = false ; if ( ! ADDR_SPACE_GENERIC_P ( as ) ) { if ( regno < FIRST_PSEUDO_REGISTER && regno == REG_Z ) { return true ; } if ( reg_renumber ) { regno = reg_renumber [ regno ] ; if ( regno == REG_Z ) { return true ; } } return false ; } if ( regno < FIRST_PSEUDO_REGISTER && ( regno == REG_X || regno == REG_Y || regno == REG_Z || regno == ARG_POINTER_REGNUM ) ) { ok = true ; } else if ( reg_renumber ) { regno = reg_renumber [ regno ] ; if ( regno == REG_X || regno == REG_Y || regno == REG_Z || regno == ARG_POINTER_REGNUM ) { ok = true ; } } if ( avr_strict_X && PLUS == outer_code && regno == REG_X ) { ok = false ; } return ok ; } </s>

Implement ` REGNO_MODE_CODE_OK_FOR_BASE_P ' .


<s> static int avr_regs_to_save ( HARD_REG_SET * set ) { int count ; int int_or_sig_p = cfun -> machine -> is_interrupt || cfun -> machine -> is_signal ; if ( set ) CLEAR_HARD_REG_SET ( * set ) ; count = 0 ; if ( TREE_THIS_VOLATILE ( current_function_decl ) || cfun -> machine -> is_OS_task || cfun -> machine -> is_OS_main ) return 0 ; for ( int reg = 0 ; reg < 32 ; reg ++ ) { if ( fixed_regs [ reg ] ) continue ; if ( ( int_or_sig_p && ! crtl -> is_leaf && call_used_or_fixed_reg_p ( reg ) ) || ( df_regs_ever_live_p ( reg ) && ( int_or_sig_p || ! call_used_or_fixed_reg_p ( reg ) ) && ! ( frame_pointer_needed && ( reg == REG_Y || reg == REG_Y + 1 ) ) ) ) { if ( set ) SET_HARD_REG_BIT ( * set , reg ) ; count ++ ; } } return count ; } </s>

Return the number of hard registers to push/pop in the prologue/epilogue of the current function , and optionally store these registers in SET .


<s> static inline bool avr_reg_ok_for_addr_p ( rtx reg , addr_space_t as , RTX_CODE outer_code , bool strict ) { return ( REG_P ( reg ) && ( avr_regno_mode_code_ok_for_base_p ( REGNO ( reg ) , QImode , as , outer_code , UNKNOWN ) || ( ! strict && REGNO ( reg ) >= FIRST_PSEUDO_REGISTER ) ) ) ; } </s>

Helper function for ` avr_legitimate_address_p ' .


<s> static bool avr_reg_ok_for_pgm_addr ( rtx reg , bool strict ) { gcc_assert ( REG_P ( reg ) ) ; if ( strict ) { return REGNO ( reg ) == REG_Z ; } if ( can_create_pseudo_p ( ) && REGNO ( reg ) < REG_Z ) { return false ; } return true ; } </s>


<s> static void avr_reorg ( void ) { rtx_insn * insn = get_insns ( ) ; for ( insn = next_real_insn ( insn ) ; insn ; insn = next_real_insn ( insn ) ) { rtx pattern = avr_compare_pattern ( insn ) ; if ( ! pattern ) continue ; if ( optimize && avr_reorg_remove_redundant_compare ( insn ) ) { continue ; } if ( compare_diff_p ( insn ) ) { rtx_insn * next = next_real_insn ( insn ) ; rtx pat = PATTERN ( next ) ; if ( GET_CODE ( pat ) == PARALLEL ) pat = XVECEXP ( pat , 0 , 0 ) ; pattern = SET_SRC ( pattern ) ; if ( true_regnum ( XEXP ( pattern , 0 ) ) >= 0 && true_regnum ( XEXP ( pattern , 1 ) ) >= 0 ) { rtx x = XEXP ( pattern , 0 ) ; rtx src = SET_SRC ( pat ) ; rtx t = XEXP ( src , 0 ) ; PUT_CODE ( t , swap_condition ( GET_CODE ( t ) ) ) ; XEXP ( pattern , 0 ) = XEXP ( pattern , 1 ) ; XEXP ( pattern , 1 ) = x ; INSN_CODE ( next ) = - 1 ; } else if ( true_regnum ( XEXP ( pattern , 0 ) ) >= 0 && XEXP ( pattern , 1 ) == const0_rtx ) { rtx src = SET_SRC ( pat ) ; rtx t = XEXP ( src , 0 ) ; PUT_CODE ( t , swap_condition ( GET_CODE ( t ) ) ) ; XEXP ( pattern , 1 ) = XEXP ( pattern , 0 ) ; XEXP ( pattern , 0 ) = const0_rtx ; INSN_CODE ( next ) = - 1 ; INSN_CODE ( insn ) = - 1 ; } else if ( true_regnum ( XEXP ( pattern , 0 ) ) >= 0 && CONST_INT_P ( XEXP ( pattern , 1 ) ) ) { rtx x = XEXP ( pattern , 1 ) ; rtx src = SET_SRC ( pat ) ; rtx t = XEXP ( src , 0 ) ; machine_mode mode = GET_MODE ( XEXP ( pattern , 0 ) ) ; if ( avr_simplify_comparison_p ( mode , GET_CODE ( t ) , x ) ) { XEXP ( pattern , 1 ) = gen_int_mode ( INTVAL ( x ) + 1 , mode ) ; PUT_CODE ( t , avr_normalize_condition ( GET_CODE ( t ) ) ) ; INSN_CODE ( next ) = - 1 ; INSN_CODE ( insn ) = - 1 ; } } } } } </s>

This function optimizes conditional jumps .


"%<builtin_return_address%> contains only 2 bytes"

Return contents of MEM at frame pointer + stack size + 1 ( +2 if 3-byte PC ) . This is return address of function .


<s> static bool avr_return_in_memory ( const_tree type , const_tree fntype ATTRIBUTE_UNUSED ) { HOST_WIDE_INT size = int_size_in_bytes ( type ) ; HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8 ; if ( size == - 1 || size > ret_size_limit ) { return true ; } else { return false ; } } </s>

Worker function for TARGET_RETURN_IN_MEMORY .


<s> static inline unsigned int avr_ret_register ( void ) { return 24 ; } </s>

Returns register number for function return value .


The AVR backend 's rtx_cost function . X is rtx expression whose cost is to be calculated . Return true if the complete cost has been computed , and false if subexpressions should be scanned . In either case , * TOTAL contains the cost result .


<s> static bool avr_scalar_mode_supported_p ( scalar_mode mode ) { if ( ALL_FIXED_POINT_MODE_P ( mode ) ) return true ; if ( PSImode == mode ) return true ; return default_scalar_mode_supported_p ( mode ) ; } </s>

Implement ` TARGET_SCALAR_MODE_SUPPORTED_P ' .


"only uninitialized variables can be placed in the "

Implement ` TARGET_SECTION_TYPE_FLAGS ' .


"unknown core architecture %qs specified with %qs"

Set ` avr_arch ' as specified by ` -mmcu= ' . Return true on success .


"function attributes %qs and %qs are mutually exclusive"

"%qs handler, missing %<__vector%> prefix"

" in AVR-LibC.  Consider %<#include <avr/interrupt.h>%>"

Sanity cheching for above function attributes .


<s> static int avr_signal_function_p ( tree func ) { return avr_lookup_function_attribute1 ( func , "signal" ) ; } </s>

Return nonzero if FUNC is a signal function as specified by the `` signal '' attribute .


<s> int avr_simple_epilogue ( void ) { return ( ! frame_pointer_needed && get_frame_size ( ) == 0 && avr_outgoing_args_size ( ) == 0 && avr_regs_to_save ( NULL ) == 0 && ! cfun -> machine -> is_interrupt && ! cfun -> machine -> is_signal && ! cfun -> machine -> is_naked && ! TREE_THIS_VOLATILE ( current_function_decl ) ) ; } </s>

Return 1 if the function epilogue is just a single `` ret '' .


<s> int avr_simplify_comparison_p ( machine_mode mode , RTX_CODE op , rtx x ) { unsigned int max = ( mode == QImode ? 0xff : mode == HImode ? 0xffff : mode == PSImode ? 0xffffff : mode == SImode ? 0xffffffff : 0 ) ; if ( max && op && CONST_INT_P ( x ) ) { if ( unsigned_condition ( op ) != op ) max >>= 1 ; if ( max != ( INTVAL ( x ) & max ) && INTVAL ( x ) != 0xff ) return 1 ; } return 0 ; } </s>

Return 0 if undefined , 1 if always true or always false .


<s> static HOST_WIDE_INT avr_starting_frame_offset ( void ) { return 1 + avr_outgoing_args_size ( ) ; } </s>

This is the offset from the frame pointer register to the first stack slot that contains a variable living in the frame .


<s> static char * avr_tolower ( char * lo , const char * up ) { char * lo0 = lo ; for ( ; * up ; up ++ , lo ++ ) * lo = TOLOWER ( * up ) ; * lo = '\0' ; return lo0 ; } </s>

Transform UP into lowercase and write the result to LO . You must provide enough space for LO . Return LO .


<s> rtx avr_to_int_mode ( rtx x ) { machine_mode mode = GET_MODE ( x ) ; return VOIDmode == mode ? x : simplify_gen_subreg ( int_mode_for_mode ( mode ) . require ( ) , x , mode , 0 ) ; } </s>

Access some RTX as INT_MODE . If X is a CONST_FIXED we can get the bit representation of X by `` casting '' it to CONST_INT .


<s> static bool avr_use_by_pieces_infrastructure_p ( unsigned HOST_WIDE_INT size , unsigned int align ATTRIBUTE_UNUSED , enum by_pieces_operation op , bool speed_p ) { if ( op != MOVE_BY_PIECES || ( speed_p && size > MOVE_MAX_PIECES ) ) return default_use_by_pieces_infrastructure_p ( size , align , op , speed_p ) ; return size <= MOVE_MAX_PIECES ; } </s>

Prefer sequence of loads/stores for moves of size upto two - two pairs of load/store instructions are always better than the 5 instruction sequence for a loop ( 1 instruction for loop counter setup , and 4 for the body of the loop ) .


<s> static bool avr_warn_func_return ( tree decl ) { return ! avr_naked_function_p ( decl ) ; } </s>


<s> bool avr_xload_libgcc_p ( machine_mode mode ) { int n_bytes = GET_MODE_SIZE ( mode ) ; return ( n_bytes > 1 || avr_n_flash > 1 ) ; } </s>

Return true if a value of mode MODE is read by __xload_ * function .


<s> static RTX_CODE compare_condition ( rtx_insn * insn ) { rtx_insn * next = next_real_insn ( insn ) ; if ( next && JUMP_P ( next ) ) { rtx pat = PATTERN ( next ) ; if ( GET_CODE ( pat ) == PARALLEL ) pat = XVECEXP ( pat , 0 , 0 ) ; rtx src = SET_SRC ( pat ) ; if ( IF_THEN_ELSE == GET_CODE ( src ) ) return GET_CODE ( XEXP ( src , 0 ) ) ; } return UNKNOWN ; } </s>

Returns the condition of compare insn INSN , or UNKNOWN .


<s> static bool compare_diff_p ( rtx_insn * insn ) { RTX_CODE cond = compare_condition ( insn ) ; return ( cond == GT || cond == GTU || cond == LE || cond == LEU ) ? cond : 0 ; } </s>

Returns nonzero if the next insn is a JUMP_INSN with a condition that needs to be swapped ( GT , GTU , LE , LEU ) .


<s> static bool compare_eq_p ( rtx_insn * insn ) { RTX_CODE cond = compare_condition ( insn ) ; return ( cond == EQ || cond == NE ) ; } </s>

Returns nonzero if INSN is a compare insn with the EQ or NE condition .


<s> static bool compare_sign_p ( rtx_insn * insn ) { RTX_CODE cond = compare_condition ( insn ) ; return ( cond == GE || cond == LT ) ; } </s>

Returns nonzero if INSN is a tst insn that only tests the sign .


<s> void avr_pass_pre_proep :: compute_maybe_gasisr ( function * fun ) { for ( rtx_insn * insn = get_insns ( ) ; insn ; insn = NEXT_INSN ( insn ) ) { if ( CALL_P ( insn ) ) return ; if ( AVR_HAVE_JMP_CALL && JUMP_TABLE_DATA_P ( insn ) ) return ; if ( JUMP_P ( insn ) && find_reg_note ( insn , REG_NON_LOCAL_GOTO , NULL_RTX ) ) return ; } fun -> machine -> gasisr . maybe = 1 ; } </s>

Set fun- > machine- > gasisr.maybe provided we do n't find anything that prohibits GAS generating parts of ISR prologues / epilogues for us .


<s> static const char * cond_string ( enum rtx_code code ) { bool cc_overflow_unusable = false ; switch ( code ) { case NE : return "ne" ; case EQ : return "eq" ; case GE : if ( cc_overflow_unusable ) return "pl" ; else return "ge" ; case LT : if ( cc_overflow_unusable ) return "mi" ; else return "lt" ; case GEU : return "sh" ; case LTU : return "lo" ; default : gcc_unreachable ( ) ; } return "" ; } </s>

Return assembly language string which identifies a comparison type .

avr "ne" "eq" "pl" "ge" "mi" "lt" "sh" "lo" ""


<s> static void emit_pop_byte ( unsigned regno ) { rtx mem , reg ; mem = gen_rtx_PRE_INC ( HImode , stack_pointer_rtx ) ; mem = gen_frame_mem ( QImode , mem ) ; reg = gen_rtx_REG ( QImode , regno ) ; emit_insn ( gen_rtx_SET ( reg , mem ) ) ; } </s>

Helper for avr_expand_epilogue . Emit a pop of a byte register .


<s> static void emit_push_byte ( unsigned regno , bool frame_related_p ) { rtx mem , reg ; rtx_insn * insn ; mem = gen_rtx_POST_DEC ( HImode , stack_pointer_rtx ) ; mem = gen_frame_mem ( QImode , mem ) ; reg = gen_rtx_REG ( QImode , regno ) ; insn = emit_insn ( gen_rtx_SET ( mem , reg ) ) ; if ( frame_related_p ) RTX_FRAME_RELATED_P ( insn ) = 1 ; cfun -> machine -> stack_usage ++ ; } </s>

Helper for expand_prologue . Emit a push of a byte register .


<s> static void emit_push_sfr ( rtx sfr , bool frame_related_p , bool clr_p , int treg ) { rtx_insn * insn ; gcc_assert ( MEM_P ( sfr ) ) ; insn = emit_move_insn ( all_regs_rtx [ treg ] , sfr ) ; if ( frame_related_p ) RTX_FRAME_RELATED_P ( insn ) = 1 ; emit_push_byte ( treg , frame_related_p ) ; if ( clr_p ) { insn = emit_move_insn ( sfr , const0_rtx ) ; if ( frame_related_p ) RTX_FRAME_RELATED_P ( insn ) = 1 ; } } </s>

Helper for expand_prologue . Emit a push of a SFR via tmp_reg . SFR is a MEM representing the memory location of the SFR . If CLR_P then clear the SFR after the push using zero_reg .


<s> virtual unsigned int execute ( function * fun ) { if ( avr_gasisr_prologues && ! fun -> machine -> is_no_gccisr && ( fun -> machine -> is_interrupt || fun -> machine -> is_signal ) && ! cfun -> machine -> is_naked && ! cfun -> calls_setjmp && ! cfun -> has_nonlocal_label && ! cfun -> has_forced_label_in_static ) { compute_maybe_gasisr ( fun ) ; } return 0 ; } </s>


"\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n"

Test for extra memory constraint ' Q ' . It 's a memory address based on Y or Z pointer with valid displacement .


<s> int get_sequence_length ( rtx_insn * insns ) { int length = 0 ; for ( rtx_insn * insn = insns ; insn ; insn = NEXT_INSN ( insn ) ) length += get_attr_length ( insn ) ; return length ; } </s>


"internal compiler error.  Incorrect shift:"

8bit logic shift right ( ( unsigned char ) x > > i )


<s>
const
char
*
lshrsi3_out
(
rtx_insn
*
insn
,
rtx
operands
[
]
,
int
*
len
)
{
if
(
CONST_INT_P
(
operands
[
2
]
)
)
{
int
k
;
int
*
t
=
len
;
if
(
!
len
)
len
=
&
k
;
switch
(
INTVAL
(
operands
[
2
]
)
)
{
default
:
if
(
INTVAL
(
operands
[
2
]
)
<
32
)
break
;
if
(
AVR_HAVE_MOVW
)
return
*
len
=
3
,
(
"clr %D0"
CR_TAB
"clr %C0"
CR_TAB
"movw %A0,%C0"
)
;
*
len
=
4
;
return
(
"clr %D0"
CR_TAB
"clr %C0"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
case
8
:
{
int
reg0
=
true_regnum
(
operands
[
0
]
)
;
int
reg1
=
true_regnum
(
operands
[
1
]
)
;
*
len
=
4
;
if
(
reg0
<=
reg1
)
return
(
"mov %A0,%B1"
CR_TAB
"mov %B0,%C1"
CR_TAB
"mov %C0,%D1"
CR_TAB
"clr %D0"
)
;
else
return
(
"clr %D0"
CR_TAB
"mov %C0,%D1"
CR_TAB
"mov %B0,%C1"
CR_TAB
"mov %A0,%B1"
)
;
}
case
16
:
{
int
reg0
=
true_regnum
(
operands
[
0
]
)
;
int
reg1
=
true_regnum
(
operands
[
1
]
)
;
if
(
reg0
==
reg1
+
2
)
return
*
len
=
2
,
(
"clr %C0"
CR_TAB
"clr %D0"
)
;
if
(
AVR_HAVE_MOVW
)
return
*
len
=
3
,
(
"movw %A0,%C1"
CR_TAB
"clr %C0"
CR_TAB
"clr %D0"
)
;
else
return
*
len
=
4
,
(
"mov %B0,%D1"
CR_TAB
"mov %A0,%C1"
CR_TAB
"clr %C0"
CR_TAB
"clr %D0"
)
;
}
case
24
:
return
*
len
=
4
,
(
"mov %A0,%D1"
CR_TAB
"clr %B0"
CR_TAB
"clr %C0"
CR_TAB
"clr %D0"
)
;
case
31
:
*
len
=
6
;
return
(
"clr %A0"
CR_TAB
"sbrc %D0,7"
CR_TAB
"inc %A0"
CR_TAB
"clr %B0"
CR_TAB
"clr %C0"
CR_TAB
"clr %D0"
)
;
}
len
=
t
;
}
out_shift_with_cnt
(
"lsr %D0"
CR_TAB
"ror %C0"
CR_TAB
"ror %B0"
CR_TAB
"ror %A0"
,
insn
,
operands
,
len
,
4
)
;
return
""
;
}
</s>

32bit logic shift right ( ( unsigned int ) x > > i )


<s> const char * output_reload_inhi ( rtx * op , rtx clobber_reg , int * plen ) { output_reload_in_const ( op , clobber_reg , plen , false ) ; return "" ; } </s>

Reload the constant OP [ 1 ] into the HI register OP [ 0 ] . CLOBBER_REG is a QI clobber reg needed to move vast majority of consts into a NO_LD_REGS register . If CLOBBER_REG is NULL_RTX we either do n't need a clobber reg or have to cook one up . PLEN == NULL : Output instructions . PLEN ! = NULL : Output nothing . Set * PLEN to number of words occupied by the insns printed . Return `` '' .


<s>
const
char
*
output_reload_insisf
(
rtx
*
op
,
rtx
clobber_reg
,
int
*
len
)
{
if
(
AVR_HAVE_MOVW
&&
!
test_hard_reg_class
(
LD_REGS
,
op
[
0
]
)
&&
(
CONST_INT_P
(
op
[
1
]
)
||
CONST_FIXED_P
(
op
[
1
]
)
||
CONST_DOUBLE_P
(
op
[
1
]
)
)
)
{
int
len_clr
,
len_noclr
;
output_reload_in_const
(
op
,
clobber_reg
,
&
len_clr
,
true
)
;
output_reload_in_const
(
op
,
clobber_reg
,
&
len_noclr
,
false
)
;
if
(
len_noclr
len_clr
==
4
)
{
avr_asm_len
(
"mov %A0,__zero_reg__"
CR_TAB
"mov %B0,__zero_reg__"
CR_TAB
"movw %C0,%A0"
,
&
op
[
0
]
,
len
,
3
)
;
output_reload_in_const
(
op
,
clobber_reg
,
len
,
true
)
;
if
(
len
)
*
len
+=
3
;
return
""
;
}
}
output_reload_in_const
(
op
,
clobber_reg
,
len
,
false
)
;
return
""
;
}
</s>

Reload a SI or SF compile time constant OP [ 1 ] into the register OP [ 0 ] . CLOBBER_REG is a QI clobber reg needed to move vast majority of consts into a NO_LD_REGS register . If CLOBBER_REG is NULL_RTX we either do n't need a clobber reg or have to cook one up . LEN == NULL : Output instructions . LEN ! = NULL : Output nothing . Set * LEN to number of words occupied by the insns printed . Return `` '' .


"address operand requires constraint for"

Return a pointer register name as a string


<s> int reg_unused_after ( rtx_insn * insn , rtx reg ) { return ( dead_or_set_p ( insn , reg ) || ( REG_P ( reg ) && _reg_unused_after ( insn , reg ) ) ) ; } </s>

Return nonzero if REG is not used after INSN . We assume REG is a reload reg , and therefore does not live past labels or calls or jumps .


<s>
const
char
*
ret_cond_branch
(
rtx
x
,
int
len
,
int
reverse
)
{
RTX_CODE
cond
=
reverse
reverse_condition
(
GET_CODE
(
x
)
)
:
GET_CODE
(
x
)
;
bool
cc_overflow_unusable
=
false
;
switch
(
cond
)
{
case
GT
:
if
(
cc_overflow_unusable
)
return
(
len
==
1
(
"breq .+2"
CR_TAB
"brpl %0"
)
:
len
==
2
(
"breq .+4"
CR_TAB
"brmi .+2"
CR_TAB
"rjmp %0"
)
:
(
"breq .+6"
CR_TAB
"brmi .+4"
CR_TAB
"jmp %0"
)
)
;
else
return
(
len
==
1
(
"breq .+2"
CR_TAB
"brge %0"
)
:
len
==
2
(
"breq .+4"
CR_TAB
"brlt .+2"
CR_TAB
"rjmp %0"
)
:
(
"breq .+6"
CR_TAB
"brlt .+4"
CR_TAB
"jmp %0"
)
)
;
case
GTU
:
return
(
len
==
1
(
"breq .+2"
CR_TAB
"brsh %0"
)
:
len
==
2
(
"breq .+4"
CR_TAB
"brlo .+2"
CR_TAB
"rjmp %0"
)
:
(
"breq .+6"
CR_TAB
"brlo .+4"
CR_TAB
"jmp %0"
)
)
;
case
LE
:
if
(
cc_overflow_unusable
)
return
(
len
==
1
(
"breq %0"
CR_TAB
"brmi %0"
)
:
len
==
2
(
"breq .+2"
CR_TAB
"brpl .+2"
CR_TAB
"rjmp %0"
)
:
(
"breq .+2"
CR_TAB
"brpl .+4"
CR_TAB
"jmp %0"
)
)
;
else
return
(
len
==
1
(
"breq %0"
CR_TAB
"brlt %0"
)
:
len
==
2
(
"breq .+2"
CR_TAB
"brge .+2"
CR_TAB
"rjmp %0"
)
:
(
"breq .+2"
CR_TAB
"brge .+4"
CR_TAB
"jmp %0"
)
)
;
case
LEU
:
return
(
len
==
1
(
"breq %0"
CR_TAB
"brlo %0"
)
:
len
==
2
(
"breq .+2"
CR_TAB
"brsh .+2"
CR_TAB
"rjmp %0"
)
:
(
"breq .+2"
CR_TAB
"brsh .+4"
CR_TAB
"jmp %0"
)
)
;
default
:
if
(
reverse
)
{
switch
(
len
)
{
case
1
:
return
"br%k1 %0"
;
case
2
:
return
(
"br%j1 .+2"
CR_TAB
"rjmp %0"
)
;
default
:
return
(
"br%j1 .+4"
CR_TAB
"jmp %0"
)
;
}
}
else
{
switch
(
len
)
{
case
1
:
return
"br%j1 %0"
;
case
2
:
return
(
"br%k1 .+2"
CR_TAB
"rjmp %0"
)
;
default
:
return
(
"br%k1 .+4"
CR_TAB
"jmp %0"
)
;
}
}
}
return
""
;
}
</s>

return an AVR condition jump commands . X is a comparison RTX . LEN is a number returned by avr_jump_mode function . if REVERSE nonzero then condition code in X must be reversed .


<s> static int sequent_regs_live ( void ) { int live_seq = 0 ; int cur_seq = 0 ; for ( int reg = 0 ; reg <= LAST_CALLEE_SAVED_REG ; ++ reg ) { if ( fixed_regs [ reg ] ) { if ( live_seq != 0 ) return 0 ; else continue ; } if ( ! call_used_or_fixed_reg_p ( reg ) ) { if ( df_regs_ever_live_p ( reg ) ) { ++ live_seq ; ++ cur_seq ; } else cur_seq = 0 ; } } if ( ! frame_pointer_needed ) { if ( df_regs_ever_live_p ( REG_Y ) ) { ++ live_seq ; ++ cur_seq ; } else cur_seq = 0 ; if ( df_regs_ever_live_p ( REG_Y + 1 ) ) { ++ live_seq ; ++ cur_seq ; } else cur_seq = 0 ; } else { cur_seq += 2 ; live_seq += 2 ; } return ( cur_seq == live_seq ) ? live_seq : 0 ; } </s>

This function checks sequence of live registers


"Running spec function '%s' with %d args\n\n"

"strange device name %qs after %qs: bad character %qc"

Implement spec function ` device-specs-file麓 . Compose -specs= < specs-file-name > % s . If everything went well then argv [ 0 ] is the inflated ( absolute ) specs directory and argv [ 1 ] is a device or core name as supplied by -mmcu= * . When building GCC the path might be relative .


<s>
const
char
*
avr_double_lib
(
int
argc
,
const
char
*
*
argv
)
{
int
dbl
=
64
;
int
dbl
=
32
;
int
ldb
=
64
;
int
ldb
=
32
;
for
(
int
i
=
0
;
i
<
argc
;
i
++
)
{
if
(
strcmp
(
argv
[
i
]
,
"mdouble=32"
)
==
0
)
{
dbl
=
32
;
ldb
=
dbl
;
}
else
if
(
strcmp
(
argv
[
i
]
,
"mdouble=64"
)
==
0
)
{
ldb
=
dbl
=
64
;
}
else
if
(
strcmp
(
argv
[
i
]
,
"mlong-double=32"
)
==
0
)
{
ldb
=
dbl
=
32
;
}
else
if
(
strcmp
(
argv
[
i
]
,
"mlong-double=64"
)
==
0
)
{
ldb
=
64
;
dbl
=
ldb
;
}
}
return
concat
(
" %<mdouble=* -mdouble="
,
dbl
==
32
"32"
:
"64"
,
" %<mlong-double=* -mlong-double="
,
ldb
==
32
"32"
:
"64"
,
)
;
}
</s>

Re-build the -mdouble= and -mlong-double= options . This is needed because these options are not independent of each other .


<s> static bool str_prefix_p ( const char * str , const char * prefix ) { return 0 == strncmp ( str , prefix , strlen ( prefix ) ) ; } </s>

Return true iff STR starts with PREFIX .


<s> static bool str_prefix_p ( const char * str , const char * prefix ) { return strncmp ( str , prefix , strlen ( prefix ) ) == 0 ; } </s>


<s> int main ( void ) { for ( const avr_mcu_t * mcu = avr_mcu_types ; mcu -> name ; mcu ++ ) print_mcu ( mcu ) ; return EXIT_SUCCESS ; } </s>

Main program to convert flat files into built-in initialization code .


<s> static int c_prefix ( const char * str ) { static const char * const prefixes [ ] = { "attiny" , "atmega" , "atxmega" , "ata" , "at90" , "avr" } ; int i , n = ( int ) ( ARRAY_SIZE ( prefixes ) ) ; for ( i = 0 ; i < n ; i ++ ) if ( str_prefix_p ( str , prefixes [ i ] ) ) return i ; return n ; } </s>

Used by string comparator to group MCUs by their name prefix like `` attiny '' or `` atmega '' .

avr "attiny" "atmega" "atxmega" "ata" "at90" "avr" 0


"@c Copyright (C) 2012-2023 Free Software Foundation, Inc.\n"

"@c For copying conditions, see the file "

"@c This file is generated automatically using\n"


<s> static int comparator ( const void * va , const void * vb ) { const char * a = * ( const char * const * ) va ; const char * b = * ( const char * const * ) vb ; while ( * a && * b ) { if ( letter ( * a ) && digit ( * b ) ) return - 1 ; if ( digit ( * a ) && letter ( * b ) ) return 1 ; if ( * a != * b ) return * a - * b ; a ++ ; b ++ ; } return * a - * b ; } </s>

Compare two MCUs and order them for easy lookup .


"@c Copyright (C) 2012-2015 Free Software Foundation, Inc.\n"


"@c Copyright (C) 2012-2016 Free Software Foundation, Inc.\n"


"@c Copyright (C) 2012-2017 Free Software Foundation, Inc.\n"


"@c Copyright (C) 2012-2018 Free Software Foundation, Inc.\n"


"@c Copyright (C) 2012-2019 Free Software Foundation, Inc.\n"


<s> static int comparator ( const void * va , const void * vb ) { const avr_mcu_t * mcu_a = * ( const avr_mcu_t * const * ) va ; const avr_mcu_t * mcu_b = * ( const avr_mcu_t * const * ) vb ; const char * a = mcu_a -> name ; const char * b = mcu_b -> name ; int c = c_prefix ( a ) - c_prefix ( b ) ; if ( c ) return c ; c = ( int ) mcu_a -> flash_size - ( int ) mcu_b -> flash_size ; if ( c ) return c ; while ( * a && * b ) { c = c_number ( a ) - c_number ( b ) ; if ( c ) return c ; if ( * a != * b ) return * a - * b ; a ++ ; b ++ ; } return * a - * b ; } </s>


<s> static int c_number ( const char * a ) { int val = 0 ; if ( digit ( * a ) && ! digit ( * ( a - 1 ) ) ) { while ( digit ( * a ) ) val = 10 * val + ( * a ++ ) - '0' ; } return val ; } </s>

If A starts a group of digits , return their value as a number .


<s> static int c_prefix ( const char * str ) { static const char * const prefixes [ ] = { "attiny" , "atmega" , "atxmega" , "ata" , "at90" } ; int i , n = ( int ) ( sizeof ( prefixes ) / sizeof ( * prefixes ) ) ; for ( i = 0 ; i < n ; i ++ ) if ( str_prefix_p ( str , prefixes [ i ] ) ) return i ; return n ; } </s>

avr "attiny" "atmega" "atxmega" "ata" "at90" 0


"@c Copyright (C) 2012-2022 Free Software Foundation, Inc.\n"


<s> static int str_prefix_p ( const char * str , const char * prefix ) { return strncmp ( str , prefix , strlen ( prefix ) ) == 0 ; } </s>