<s>
const
char
*
avr_out_movmem
(
rtx_insn
*
insn
ATTRIBUTE_UNUSED
,
rtx
*
op
,
int
*
plen
)
{
addr_space_t
as
=
(
addr_space_t
)
INTVAL
(
op
[
0
]
)
;
machine_mode
loop_mode
=
GET_MODE
(
op
[
1
]
)
;
bool
sbiw_p
=
test_hard_reg_class
(
ADDW_REGS
,
op
[
1
]
)
;
rtx
xop
[
3
]
;
if
(
plen
)
*
plen
=
0
;
xop
[
0
]
=
op
[
0
]
;
xop
[
1
]
=
op
[
1
]
;
xop
[
2
]
=
tmp_reg_rtx
;
avr_asm_len
(
"0:"
,
xop
,
plen
,
0
)
;
switch
(
as
)
{
default
:
gcc_unreachable
(
)
;
case
ADDR_SPACE_GENERIC
:
avr_asm_len
(
"ld %2,Z+"
,
xop
,
plen
,
1
)
;
break
;
case
ADDR_SPACE_FLASH
:
if
(
AVR_HAVE_LPMX
)
avr_asm_len
(
"lpm %2,Z+"
,
xop
,
plen
,
1
)
;
else
avr_asm_len
(
"lpm"
CR_TAB
"adiw r30,1"
,
xop
,
plen
,
2
)
;
break
;
case
ADDR_SPACE_FLASH1
:
case
ADDR_SPACE_FLASH2
:
case
ADDR_SPACE_FLASH3
:
case
ADDR_SPACE_FLASH4
:
case
ADDR_SPACE_FLASH5
:
if
(
AVR_HAVE_ELPMX
)
avr_asm_len
(
"elpm %2,Z+"
,
xop
,
plen
,
1
)
;
else
avr_asm_len
(
"elpm"
CR_TAB
"adiw r30,1"
,
xop
,
plen
,
2
)
;
break
;
}
avr_asm_len
(
"st X+,%2"
,
xop
,
plen
,
1
)
;
if
(
QImode
==
loop_mode
)
{
avr_asm_len
(
"dec %1"
,
xop
,
plen
,
1
)
;
}
else
if
(
sbiw_p
)
{
avr_asm_len
(
"sbiw %1,1"
,
xop
,
plen
,
1
)
;
}
else
{
avr_asm_len
(
"subi %A1,1"
CR_TAB
"sbci %B1,0"
,
xop
,
plen
,
2
)
;
}
return
avr_asm_len
(
"brne 0b"
,
xop
,
plen
,
1
)
;
}
</s>

Print assembler for movmem_qi , movmem_hi insns ... $ 0 : Address Space $ 1 , $ 2 : Loop register Z : Source address X : Destination address


<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>
const
char
*
avr_out_round
(
rtx_insn
*
insn
ATTRIBUTE_UNUSED
,
rtx
*
xop
,
int
*
plen
)
{
machine_mode
mode
=
GET_MODE
(
xop
[
0
]
)
;
machine_mode
imode
=
int_mode_for_mode
(
mode
)
;
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
(
VOIDmode
,
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
(
VOIDmode
,
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>
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
(
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 .


"%qT uses address space %qs beyond flash of %d KiB"

"%s %q+D uses address space %qs beyond flash of %d KiB"

"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> static inline int avr_popcount ( unsigned int val ) { int pop = 0 ; while ( val ) { val &= val - 1 ; pop ++ ; } return pop ; } </s>

Custom function to count number of set bits .


<s> bool avr_popcount_each_byte ( rtx xval , int n_bytes , int pop_mask ) { int i ; machine_mode mode = GET_MODE ( xval ) ; if ( VOIDmode == mode ) mode = SImode ; for ( 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 ( 0 == ( pop_mask & ( 1 << avr_popcount ( val8 ) ) ) ) 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 int avr_regs_to_save ( HARD_REG_SET * set ) { int reg , 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 ( reg = 0 ; reg < 32 ; reg ++ ) { if ( fixed_regs [ reg ] ) continue ; if ( ( int_or_sig_p && ! crtl -> is_leaf && call_used_regs [ reg ] ) || ( df_regs_ever_live_p ( reg ) && ( int_or_sig_p || ! call_used_regs [ 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 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 next = next_real_insn ( insn ) ; rtx pat = PATTERN ( next ) ; 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 .


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 ( machine_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 ' .


<s> static reg_class_t avr_secondary_reload ( bool in_p , rtx x , reg_class_t reload_class ATTRIBUTE_UNUSED , machine_mode mode , secondary_reload_info * sri ) { if ( in_p && MEM_P ( x ) && ! ADDR_SPACE_GENERIC_P ( MEM_ADDR_SPACE ( x ) ) && ADDR_SPACE_MEMX != MEM_ADDR_SPACE ( x ) ) { switch ( mode ) { default : gcc_unreachable ( ) ; case QImode : sri -> icode = CODE_FOR_reload_inqi ; break ; case QQmode : sri -> icode = CODE_FOR_reload_inqq ; break ; case UQQmode : sri -> icode = CODE_FOR_reload_inuqq ; break ; case HImode : sri -> icode = CODE_FOR_reload_inhi ; break ; case HQmode : sri -> icode = CODE_FOR_reload_inhq ; break ; case HAmode : sri -> icode = CODE_FOR_reload_inha ; break ; case UHQmode : sri -> icode = CODE_FOR_reload_inuhq ; break ; case UHAmode : sri -> icode = CODE_FOR_reload_inuha ; break ; case PSImode : sri -> icode = CODE_FOR_reload_inpsi ; break ; case SImode : sri -> icode = CODE_FOR_reload_insi ; break ; case SFmode : sri -> icode = CODE_FOR_reload_insf ; break ; case SQmode : sri -> icode = CODE_FOR_reload_insq ; break ; case SAmode : sri -> icode = CODE_FOR_reload_insa ; break ; case USQmode : sri -> icode = CODE_FOR_reload_inusq ; break ; case USAmode : sri -> icode = CODE_FOR_reload_inusa ; break ; } } return NO_REGS ; } </s>


"unknown core architecture %qs specified with %qs"

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


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

"%qs appears to be a misspelled %s handler"

Sanity cheching for above function attributes .


<s> 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> 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 ) , 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 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 ( VOIDmode , 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 ( VOIDmode , 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 ) { rtx_insn * insn ; gcc_assert ( MEM_P ( sfr ) ) ; insn = emit_move_insn ( tmp_reg_rtx , sfr ) ; if ( frame_related_p ) RTX_FRAME_RELATED_P ( insn ) = 1 ; emit_push_byte ( AVR_TMP_REGNO , 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 .


"\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 ) { rtx_insn * insn ; int length ; for ( insn = insns , length = 0 ; 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
(
GET_CODE
(
operands
[
2
]
)
==
CONST_INT
)
{
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> 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> static int sequent_regs_live ( void ) { int reg ; int live_seq = 0 ; int cur_seq = 0 ; for ( reg = 0 ; reg <= LAST_CALLEE_SAVED_REG ; ++ reg ) { if ( fixed_regs [ reg ] ) { if ( live_seq != 0 ) return 0 ; else continue ; } if ( ! call_used_regs [ 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


<s>
void
avr_final_prescan_insn
(
rtx_insn
*
insn
,
rtx
*
operand
ATTRIBUTE_UNUSED
,
int
num_operands
ATTRIBUTE_UNUSED
)
{
if
(
avr_log
.
rtx_costs
)
{
rtx
set
=
single_set
(
insn
)
;
if
(
set
)
fprintf
(
asm_out_file
,
"/* DEBUG: cost = %d.  */\n"
,
set_src_cost
(
SET_SRC
(
set
)
,
GET_MODE
(
SET_DEST
(
set
)
)
,
optimize_insn_for_speed_p
(
)
)
)
;
else
fprintf
(
asm_out_file
,
"/* DEBUG: pattern-cost = %d.  */\n"
,
rtx_cost
(
PATTERN
(
insn
)
,
VOIDmode
,
INSN
,
0
,
optimize_insn_for_speed_p
(
)
)
)
;
}
}
</s>

avr
"/* DEBUG: cost = %d.  */\n"
"/* DEBUG: pattern-cost = %d.  */\n"
0


<s> int avr_hard_regno_call_part_clobbered ( unsigned regno , machine_mode mode ) { if ( ! avr_hard_regno_mode_ok ( regno , mode ) ) return 0 ; return ( ( regno <= LAST_CALLEE_SAVED_REG && regno + GET_MODE_SIZE ( mode ) > ( LAST_CALLEE_SAVED_REG + 1 ) ) || ( regno < REG_Y && regno + GET_MODE_SIZE ( mode ) > REG_Y ) || ( regno < REG_Z && regno + GET_MODE_SIZE ( mode ) > REG_Z ) ) ; } </s>

Implement ` HARD_REGNO_CALL_PART_CLOBBERED ' .


"variable %q+D located in address space %qs beyond flash "

"variable %q+D located in address space %qs"

" which is not supported for architecture %qs"

"variable %q+D must be const in order to be put into"

Add the section attribute if the variable is in progmem .


<s>
const
char
*
avr_out_round
(
rtx_insn
*
insn
ATTRIBUTE_UNUSED
,
rtx
*
xop
,
int
*
plen
)
{
machine_mode
mode
=
GET_MODE
(
xop
[
0
]
)
;
machine_mode
imode
=
int_mode_for_mode
(
mode
)
;
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 ' .


"%qT uses address space %qs beyond flash of %d KiB"

"%s %q+D uses address space %qs beyond flash of %d KiB"

"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 .


"pointer offset from symbol maybe incorrect"


<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 ) ; 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 .


<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
int
avr_address_cost
(
rtx
x
,
machine_mode
mode
ATTRIBUTE_UNUSED
,
addr_space_t
as
ATTRIBUTE_UNUSED
,
bool
speed
ATTRIBUTE_UNUSED
)
{
int
cost
=
4
;
if
(
GET_CODE
(
x
)
==
PLUS
&&
CONST_INT_P
(
XEXP
(
x
,
1
)
)
&&
(
REG_P
(
XEXP
(
x
,
0
)
)
||
SUBREG_P
(
XEXP
(
x
,
0
)
)
)
)
{
if
(
INTVAL
(
XEXP
(
x
,
1
)
)
>
MAX_LD_OFFSET
(
mode
)
)
cost
=
18
;
}
else
if
(
CONSTANT_ADDRESS_P
(
x
)
)
{
if
(
optimize
>
0
&&
io_address_operand
(
x
,
QImode
)
)
cost
=
2
;
if
(
AVR_TINY
&&
avr_address_tiny_absdata_p
(
x
,
QImode
)
)
cost
=
2
;
}
if
(
avr_log
.
address_cost
)
avr_edump
(
"\n%?: %d = %r\n"
,
cost
,
x
)
;
return
cost
;
}
</s>

Calculate the cost of a memory address .


<s> static void avr_asm_init_sections ( void ) { readonly_data_section -> unnamed . callback = avr_output_data_section_asm_op ; data_section -> unnamed . callback = avr_output_data_section_asm_op ; bss_section -> unnamed . callback = avr_output_bss_section_asm_op ; } </s>

Implement ` TARGET_ASM_INIT_SECTIONS ' .


<s>
static
bool
avr_assemble_integer
(
rtx
x
,
unsigned
int
size
,
int
aligned_p
)
{
if
(
size
==
POINTER_SIZE
/
BITS_PER_UNIT
&&
aligned_p
&&
text_segment_operand
(
x
,
VOIDmode
)
)
{
fputs
(
"\t.word\tgs("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")\n"
,
asm_out_file
)
;
return
true
;
}
else
if
(
GET_MODE
(
x
)
==
PSImode
)
{
fputs
(
"\t.byte\tlo8("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")"
ASM_COMMENT_START
"need binutils PR13503\n"
,
asm_out_file
)
;
fputs
(
"\t.byte\thi8("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")"
ASM_COMMENT_START
"need binutils PR13503\n"
,
asm_out_file
)
;
fputs
(
"\t.byte\thh8("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")"
ASM_COMMENT_START
"need binutils PR13503\n"
,
asm_out_file
)
;
return
true
;
}
else
if
(
CONST_FIXED_P
(
x
)
)
{
for
(
unsigned
n
=
0
;
n
<
size
;
n
++
)
{
rtx
xn
=
simplify_gen_subreg
(
QImode
,
x
,
GET_MODE
(
x
)
,
n
)
;
default_assemble_integer
(
xn
,
1
,
aligned_p
)
;
}
return
true
;
}
if
(
AVR_TINY
&&
avr_address_tiny_pm_p
(
x
)
)
{
x
=
plus_constant
(
Pmode
,
x
,
AVR_TINY_PM_OFFSET
)
;
}
return
default_assemble_integer
(
x
,
size
,
aligned_p
)
;
}
</s>

Target hook for assembling integer objects . The AVR version needs special handling for references to certain labels .


"\n;; Failed condition for casesi_<mode>_sequence\n\n"

Perform some extra checks on operands of casesi_ < mode > _sequence . Not all operand dependencies can be described by means of predicates . This function performs left over checks and should always return true . Returning false means that someone changed the casesi expander but did not adjust casesi_ < mode > _sequence .


"%q+D has incompatible attributes %qs and %qs"

Implement ` TARGET_ENCODE_SECTION_INFO ' .


"%s expects a compile time integer constant"

"%s expects a compile time long integer constant"

"rounding to %d bits has no effect for "

"fixed-point value with %d fractional bits"

Expand an expression EXP that calls a built-in function , with result going to TARGET if that 's convenient ( and in mode MODE if that 's convenient ) . SUBTARGET may be used as the target for computing one of EXP 's operands . IGNORE is nonzero if the value is to be ignored .


<s> void avr_expand_prologue ( void ) { HARD_REG_SET set ; HOST_WIDE_INT size ; size = get_frame_size ( ) + avr_outgoing_args_size ( ) ; cfun -> machine -> stack_usage = 0 ; if ( cfun -> machine -> is_naked ) { return ; } avr_regs_to_save ( & set ) ; if ( cfun -> machine -> is_interrupt || cfun -> machine -> is_signal ) { if ( cfun -> machine -> is_interrupt ) emit_insn ( gen_enable_interrupt ( ) ) ; emit_push_byte ( AVR_ZERO_REGNO , true ) ; emit_push_byte ( AVR_TMP_REGNO , true ) ; emit_push_sfr ( sreg_rtx , false , false ) ; emit_move_insn ( zero_reg_rtx , const0_rtx ) ; emit_use ( zero_reg_rtx ) ; if ( AVR_HAVE_RAMPD ) emit_push_sfr ( rampd_rtx , false , true ) ; if ( AVR_HAVE_RAMPX && TEST_HARD_REG_BIT ( set , REG_X ) && TEST_HARD_REG_BIT ( set , REG_X + 1 ) ) { emit_push_sfr ( rampx_rtx , false , true ) ; } if ( AVR_HAVE_RAMPY && ( frame_pointer_needed || ( TEST_HARD_REG_BIT ( set , REG_Y ) && TEST_HARD_REG_BIT ( set , REG_Y + 1 ) ) ) ) { emit_push_sfr ( rampy_rtx , false , true ) ; } if ( AVR_HAVE_RAMPZ && TEST_HARD_REG_BIT ( set , REG_Z ) && TEST_HARD_REG_BIT ( set , REG_Z + 1 ) ) { emit_push_sfr ( rampz_rtx , false , AVR_HAVE_RAMPD ) ; } } avr_prologue_setup_frame ( size , set ) ; if ( flag_stack_usage_info ) current_function_static_stack_size = cfun -> machine -> stack_usage + INCOMING_FRAME_SP_OFFSET ; } </s>


<s> static rtx avr_find_unused_d_reg ( rtx_insn * insn , rtx exclude ) { bool isr_p = ( avr_interrupt_function_p ( current_function_decl ) || avr_signal_function_p ( current_function_decl ) ) ; for ( int regno = 16 ; regno < 32 ; regno ++ ) { rtx reg = all_regs_rtx [ regno ] ; if ( ( exclude && reg_overlap_mentioned_p ( exclude , reg ) ) || fixed_regs [ regno ] ) { continue ; } if ( ! df_regs_ever_live_p ( regno ) && ( TREE_THIS_VOLATILE ( current_function_decl ) || cfun -> machine -> is_OS_task || cfun -> machine -> is_OS_main || ( ! isr_p && call_used_regs [ regno ] ) ) ) { return reg ; } if ( df_regs_ever_live_p ( regno ) && reg_unused_after ( insn , reg ) ) { return reg ; } } return NULL_RTX ; } </s>

Fixme : This is a hack because secondary reloads do n't works as expected . Find an unused d-register to be used as scratch in INSN . EXCLUDE is either NULL_RTX or some register . In the case where EXCLUDE is a register , skip all possible return values that overlap EXCLUDE . The policy for the returned register is similar to that of ` reg_unused_after ' , i.e . the returned register may overlap the SET_DEST of INSN . Return a QImode d-register or NULL_RTX if nothing found .


"fixed register %s used to pass parameter to function"

Update the summarizer variable CUM to advance past an argument in the argument list .


<s> int avr_hard_regno_call_part_clobbered ( unsigned regno , machine_mode mode ) { if ( ! avr_hard_regno_mode_ok ( regno , mode ) ) return 0 ; return ( ( regno <= LAST_CALLEE_SAVED_REG && regno + GET_MODE_SIZE ( mode ) > 1 + LAST_CALLEE_SAVED_REG ) || ( regno < REG_Y && regno + GET_MODE_SIZE ( mode ) > REG_Y ) || ( regno < REG_Z && regno + GET_MODE_SIZE ( mode ) > REG_Z ) ) ; } </s>


"variable %q+D must be const in order to be put into"


";; Sequence not recognized, giving up.\n\n"

Return true if we see an insn stream generated by casesi expander together with an extension to SImode of the switch value . If this is the case , fill in the insns from casesi to INSNS [ 1 .. 5 ] and the SImode extension to INSNS [ 0 ] . Moreover , extract the operands of pattern casesi_ < mode > _sequence forged from the sequence to recog_data .


<s>
static
avr_map_op_t
avr_map_decompose
(
unsigned
int
f
,
const
avr_map_op_t
*
g
,
bool
val_const_p
)
{
bool
val_used_p
=
0
!=
avr_map_metric
(
f
,
MAP_MASK_PREIMAGE_F
)
;
avr_map_op_t
f_ginv
=
*
g
;
unsigned
int
ginv
=
g
->
ginv
;
f_ginv
.
cost
=
1
;
for
(
int
i
=
7
;
i
>=
0
;
i
)
{
int
x
=
avr_map
(
f
,
i
)
;
if
(
x
<=
7
)
{
x
=
avr_map
(
ginv
,
x
)
;
if
(
x
>
7
)
return
f_ginv
;
}
f_ginv
.
map
=
(
f_ginv
.
map
<<
4
)
+
x
;
}
if
(
0
==
avr_map_metric
(
f_ginv
.
map
,
MAP_NONFIXED_0_7
)
)
{
f_ginv
.
cost
=
2
+
(
val_used_p
&&
!
val_const_p
)
;
}
else
{
rtx
xop
[
4
]
;
xop
[
0
]
=
all_regs_rtx
[
24
]
;
xop
[
1
]
=
gen_int_mode
(
f_ginv
.
map
,
SImode
)
;
xop
[
2
]
=
all_regs_rtx
[
25
]
;
xop
[
3
]
=
val_used_p
xop
[
0
]
:
const0_rtx
;
avr_out_insert_bits
(
xop
,
&
f_ginv
.
cost
)
;
f_ginv
.
cost
+=
val_const_p
&&
val_used_p
1
:
0
;
}
f_ginv
.
cost
+=
g
->
cost
;
if
(
avr_log
.
builtin
)
avr_edump
(
" %s%d=%d"
,
g
->
str
,
g
->
arg
,
f_ginv
.
cost
)
;
return
f_ginv
;
}
</s>

Try to decompose F as F = ( F o G^-1 ) o G as described above . The result is a struct representing F o G^-1 and G. If result.cost < 0 then such a decomposition does not exist .


<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 ( 0 == ( pop_mask & ( 1 << popcount_hwi ( val8 ) ) ) ) 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 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_regs [ reg ] ) || ( df_regs_ever_live_p ( reg ) && ( int_or_sig_p || ! call_used_regs [ 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 .


"%<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 .


"unknown core architecture %qs specified with %qs"

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


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

Sanity cheching for above function attributes .


<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_regs [ 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


<s> static rtx avr_builtin_setjmp_frame_value ( void ) { rtx xval = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_subhi3 ( xval , virtual_stack_vars_rtx , gen_int_mode ( avr_starting_frame_offset ( ) , Pmode ) ) ) ; return xval ; } </s>

Actual start of frame is virtual_stack_vars_rtx this is offset from frame pointer by +TARGET_STARTING_FRAME_OFFSET . Using saved frame = virtual_stack_vars_rtx - TARGET_STARTING_FRAME_OFFSET avoids creating add/sub of offset in nonlocal goto and setjmp .


<s> static bool avr_hard_regno_call_part_clobbered ( unsigned regno , machine_mode mode ) { if ( ! avr_hard_regno_mode_ok ( regno , mode ) ) return 0 ; return ( ( regno <= LAST_CALLEE_SAVED_REG && regno + GET_MODE_SIZE ( mode ) > 1 + LAST_CALLEE_SAVED_REG ) || ( regno < REG_Y && regno + GET_MODE_SIZE ( mode ) > REG_Y ) || ( regno < REG_Z && regno + GET_MODE_SIZE ( mode ) > REG_Z ) ) ; } </s>

Implement ` HARD_REGNO_CALL_PART_CLOBBERED ' .


"internal compiler error.  Incorrect shift:"


<s>
const
char
*
ashlsi3_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 %D0,%C1"
CR_TAB
"mov %C0,%B1"
CR_TAB
"mov %B0,%A1"
CR_TAB
"clr %A0"
)
;
else
return
(
"clr %A0"
CR_TAB
"mov %B0,%A1"
CR_TAB
"mov %C0,%B1"
CR_TAB
"mov %D0,%C1"
)
;
}
case
16
:
{
int
reg0
=
true_regnum
(
operands
[
0
]
)
;
int
reg1
=
true_regnum
(
operands
[
1
]
)
;
if
(
reg0
+
2
==
reg1
)
return
*
len
=
2
,
(
"clr %B0"
CR_TAB
"clr %A0"
)
;
if
(
AVR_HAVE_MOVW
)
return
*
len
=
3
,
(
"movw %C0,%A1"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
else
return
*
len
=
4
,
(
"mov %C0,%A1"
CR_TAB
"mov %D0,%B1"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
}
case
24
:
*
len
=
4
;
return
(
"mov %D0,%A1"
CR_TAB
"clr %C0"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
case
31
:
*
len
=
6
;
return
(
"clr %D0"
CR_TAB
"lsr %A0"
CR_TAB
"ror %D0"
CR_TAB
"clr %C0"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
}
len
=
t
;
}
out_shift_with_cnt
(
"lsl %A0"
CR_TAB
"rol %B0"
CR_TAB
"rol %C0"
CR_TAB
"rol %D0"
,
insn
,
operands
,
len
,
4
)
;
return
""
;
}
</s>


8bit arithmetic shift right ( ( signed char ) x > > i )


<s>
const
char
*
ashrsi3_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
]
)
)
{
case
8
:
{
int
reg0
=
true_regnum
(
operands
[
0
]
)
;
int
reg1
=
true_regnum
(
operands
[
1
]
)
;
*
len
=
6
;
if
(
reg0
<=
reg1
)
return
(
"mov %A0,%B1"
CR_TAB
"mov %B0,%C1"
CR_TAB
"mov %C0,%D1"
CR_TAB
"clr %D0"
CR_TAB
"sbrc %C0,7"
CR_TAB
"dec %D0"
)
;
else
return
(
"clr %D0"
CR_TAB
"sbrc %D1,7"
CR_TAB
"dec %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
=
4
,
(
"clr %D0"
CR_TAB
"sbrc %B0,7"
CR_TAB
"com %D0"
CR_TAB
"mov %C0,%D0"
)
;
if
(
AVR_HAVE_MOVW
)
return
*
len
=
5
,
(
"movw %A0,%C1"
CR_TAB
"clr %D0"
CR_TAB
"sbrc %B0,7"
CR_TAB
"com %D0"
CR_TAB
"mov %C0,%D0"
)
;
else
return
*
len
=
6
,
(
"mov %B0,%D1"
CR_TAB
"mov %A0,%C1"
CR_TAB
"clr %D0"
CR_TAB
"sbrc %B0,7"
CR_TAB
"com %D0"
CR_TAB
"mov %C0,%D0"
)
;
}
case
24
:
return
*
len
=
6
,
(
"mov %A0,%D1"
CR_TAB
"clr %D0"
CR_TAB
"sbrc %A0,7"
CR_TAB
"com %D0"
CR_TAB
"mov %B0,%D0"
CR_TAB
"mov %C0,%D0"
)
;
default
:
if
(
INTVAL
(
operands
[
2
]
)
<
32
)
break
;
case
31
:
if
(
AVR_HAVE_MOVW
)
return
*
len
=
4
,
(
"lsl %D0"
CR_TAB
"sbc %A0,%A0"
CR_TAB
"mov %B0,%A0"
CR_TAB
"movw %C0,%A0"
)
;
else
return
*
len
=
5
,
(
"lsl %D0"
CR_TAB
"sbc %A0,%A0"
CR_TAB
"mov %B0,%A0"
CR_TAB
"mov %C0,%A0"
CR_TAB
"mov %D0,%A0"
)
;
}
len
=
t
;
}
out_shift_with_cnt
(
"asr %D0"
CR_TAB
"ror %C0"
CR_TAB
"ror %B0"
CR_TAB
"ror %A0"
,
insn
,
operands
,
len
,
4
)
;
return
""
;
}
</s>

32bit arithmetic shift right ( ( signed long ) x > > i )


<s> static bool avr_2word_insn_p ( rtx_insn * insn ) { if ( TARGET_SKIP_BUG || ! insn || get_attr_length ( insn ) != 2 ) { return false ; } switch ( INSN_CODE ( insn ) ) { default : return false ; case CODE_FOR_movqi_insn : case CODE_FOR_movuqq_insn : case CODE_FOR_movqq_insn : { rtx set = single_set ( insn ) ; rtx src = SET_SRC ( set ) ; rtx dest = SET_DEST ( set ) ; if ( MEM_P ( dest ) && ( REG_P ( src ) || src == CONST0_RTX ( GET_MODE ( dest ) ) ) ) { return CONSTANT_ADDRESS_P ( XEXP ( dest , 0 ) ) ; } else if ( REG_P ( dest ) && MEM_P ( src ) ) { return CONSTANT_ADDRESS_P ( XEXP ( src , 0 ) ) ; } return false ; } case CODE_FOR_call_insn : case CODE_FOR_call_value_insn : return true ; } } </s>

Helper for jump_over_one_insn_p : Test if INSN is a 2-word instruction and thus is suitable to be skipped by CPSE , SBRC , etc .


<s> int avr_accumulate_outgoing_args ( void ) { if ( ! cfun ) return TARGET_ACCUMULATE_OUTGOING_ARGS ; return ( TARGET_ACCUMULATE_OUTGOING_ARGS && ! ( cfun -> calls_setjmp || cfun -> has_nonlocal_label ) ) ; } </s>

Implement ` ACCUMULATE_OUTGOING_ARGS ' .


<s>
static
int
avr_address_cost
(
rtx
x
,
machine_mode
mode
ATTRIBUTE_UNUSED
,
addr_space_t
as
ATTRIBUTE_UNUSED
,
bool
speed
ATTRIBUTE_UNUSED
)
{
int
cost
=
4
;
if
(
GET_CODE
(
x
)
==
PLUS
&&
CONST_INT_P
(
XEXP
(
x
,
1
)
)
&&
(
REG_P
(
XEXP
(
x
,
0
)
)
||
SUBREG_P
(
XEXP
(
x
,
0
)
)
)
)
{
if
(
INTVAL
(
XEXP
(
x
,
1
)
)
>
MAX_LD_OFFSET
(
mode
)
)
cost
=
18
;
}
else
if
(
CONSTANT_ADDRESS_P
(
x
)
)
{
if
(
io_address_operand
(
x
,
QImode
)
)
cost
=
2
;
if
(
AVR_TINY
&&
avr_address_tiny_absdata_p
(
x
,
QImode
)
)
cost
=
2
;
}
if
(
avr_log
.
address_cost
)
avr_edump
(
"\n%?: %d = %r\n"
,
cost
,
x
)
;
return
cost
;
}
</s>

Calculate the cost of a memory address .


<s> static bool avr_address_tiny_absdata_p ( rtx x , machine_mode mode ) { if ( CONST == GET_CODE ( x ) ) x = XEXP ( XEXP ( x , 0 ) , 0 ) ; if ( SYMBOL_REF_P ( x ) ) return SYMBOL_REF_FLAGS ( x ) & AVR_SYMBOL_FLAG_TINY_ABSDATA ; if ( CONST_INT_P ( x ) && IN_RANGE ( INTVAL ( x ) , 0 , 0xc0 - GET_MODE_SIZE ( mode ) ) ) return true ; return false ; } </s>

Return true if rtx X is a CONST_INT , CONST or SYMBOL_REF address with the ` absdata ' variable attribute , i.e . respective data can be read / written by LDS / STS instruction . This is used only for AVR_TINY .


<s> static bool avr_address_tiny_pm_p ( rtx x ) { if ( CONST == GET_CODE ( x ) ) x = XEXP ( XEXP ( x , 0 ) , 0 ) ; if ( SYMBOL_REF_P ( x ) ) return SYMBOL_REF_FLAGS ( x ) & AVR_SYMBOL_FLAG_TINY_PM ; return false ; } </s>

Return true if rtx X is a CONST or SYMBOL_REF with progmem . This must be used for AVR_TINY only because on other cores the flash memory is not visible in the RAM address range and can not be read by , say , LD instruction .


<s> static scalar_int_mode avr_addr_space_address_mode ( addr_space_t as ) { return avr_addrspace [ as ] . pointer_size == 3 ? PSImode : HImode ; } </s>

Implement ` TARGET_ADDR_SPACE_ADDRESS_MODE ' .


<s>
static
rtx
avr_addr_space_convert
(
rtx
src
,
tree
type_from
,
tree
type_to
)
{
addr_space_t
as_from
=
TYPE_ADDR_SPACE
(
TREE_TYPE
(
type_from
)
)
;
addr_space_t
as_to
=
TYPE_ADDR_SPACE
(
TREE_TYPE
(
type_to
)
)
;
if
(
avr_log
.
progmem
)
avr_edump
(
"\n%!: op = %r\nfrom = %t\nto = %t\n"
,
src
,
type_from
,
type_to
)
;
if
(
as_from
!=
ADDR_SPACE_MEMX
&&
as_to
==
ADDR_SPACE_MEMX
)
{
int
msb
;
rtx
sym
=
src
;
rtx
reg
=
gen_reg_rtx
(
PSImode
)
;
while
(
CONST
==
GET_CODE
(
sym
)
||
PLUS
==
GET_CODE
(
sym
)
)
sym
=
XEXP
(
sym
,
0
)
;
if
(
SYMBOL_REF_P
(
sym
)
&&
ADDR_SPACE_FLASH
==
AVR_SYMBOL_GET_ADDR_SPACE
(
sym
)
)
{
as_from
=
ADDR_SPACE_FLASH
;
}
msb
=
ADDR_SPACE_GENERIC_P
(
as_from
)
0x80
:
avr_addrspace
[
as_from
]
.
segment
;
src
=
force_reg
(
Pmode
,
src
)
;
emit_insn
(
msb
==
0
gen_zero_extendhipsi2
(
reg
,
src
)
:
gen_n_extendhipsi2
(
reg
,
gen_int_mode
(
msb
,
QImode
)
,
src
)
)
;
return
reg
;
}
if
(
as_from
==
ADDR_SPACE_MEMX
&&
as_to
!=
ADDR_SPACE_MEMX
)
{
rtx
new_src
=
gen_reg_rtx
(
Pmode
)
;
src
=
force_reg
(
PSImode
,
src
)
;
emit_move_insn
(
new_src
,
simplify_gen_subreg
(
Pmode
,
src
,
PSImode
,
0
)
)
;
return
new_src
;
}
return
src
;
}
</s>

Implement ` TARGET_ADDR_SPACE_CONVERT ' .


<s> static void avr_addr_space_diagnose_usage ( addr_space_t as , location_t loc ) { ( void ) avr_addr_space_supported_p ( as , loc ) ; } </s>

Implement ` TARGET_ADDR_SPACE_DIAGNOSE_USAGE ' .


Implement ` TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P ' .


<s>
static
rtx
avr_addr_space_legitimize_address
(
rtx
x
,
rtx
old_x
,
machine_mode
mode
,
addr_space_t
as
)
{
if
(
ADDR_SPACE_GENERIC_P
(
as
)
)
return
avr_legitimize_address
(
x
,
old_x
,
mode
)
;
if
(
avr_log
.
legitimize_address
)
{
avr_edump
(
"\n%?: mode=%m\n %r\n"
,
mode
,
old_x
)
;
}
return
old_x
;
}
</s>

Implement ` TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS ' .


<s> static scalar_int_mode avr_addr_space_pointer_mode ( addr_space_t as ) { return avr_addr_space_address_mode ( as ) ; } </s>

Implement ` TARGET_ADDR_SPACE_POINTER_MODE ' .


<s> static bool avr_addr_space_subset_p ( addr_space_t subset ATTRIBUTE_UNUSED , addr_space_t superset ATTRIBUTE_UNUSED ) { return true ; } </s>

Implement ` TARGET_ADDR_SPACE_SUBSET_P ' .


"address spaces are not supported for reduced "

"address space %qs not supported for devices with "

Return true if we support address space AS for the architecture in effect and false , otherwise . If LOC is not UNKNOWN_LOCATION then also issue a respective error .


Choose the order in which to allocate hard registers for pseudo-registers local to a basic block . Store the desired register order in the array ` reg_alloc_order ' . Element 0 should be the register to allocate first ; element 1 , the next register ; and so on .


<s> static void avr_adjust_type_node ( tree * node , machine_mode mode , int sat_p ) { * node = make_node ( FIXED_POINT_TYPE ) ; TYPE_SATURATING ( * node ) = sat_p ; TYPE_UNSIGNED ( * node ) = UNSIGNED_FIXED_POINT_MODE_P ( mode ) ; TYPE_IBIT ( * node ) = GET_MODE_IBIT ( mode ) ; TYPE_FBIT ( * node ) = GET_MODE_FBIT ( mode ) ; TYPE_PRECISION ( * node ) = GET_MODE_BITSIZE ( mode ) ; SET_TYPE_ALIGN ( * node , 8 ) ; SET_TYPE_MODE ( * node , mode ) ; layout_type ( * node ) ; } </s>


<s> static bool avr_allocate_stack_slots_for_args ( void ) { return ! cfun -> machine -> is_naked ; } </s>

Implement ` TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS '


<s>
static
void
avr_asm_final_postscan_insn
(
FILE
*
stream
,
rtx_insn
*
insn
,
rtx
*
,
int
)
{
if
(
cfun
->
machine
->
gasisr
.
yes
&&
!
next_real_insn
(
insn
)
)
{
app_disable
(
)
;
fprintf
(
stream
,
"\t__gcc_isr %d,r%d\n"
,
GASISR_Done
,
cfun
->
machine
->
gasisr
.
regno
)
;
}
}
</s>

When GAS generates ( parts of ) ISR prologue / epilogue for us , we must hint GAS about the end of the code to scan . There migh be code located after the last epilogue .


<s>
static
void
avr_asm_function_begin_epilogue
(
FILE
*
file
)
{
app_disable
(
)
;
fprintf
(
file
,
"/* epilogue start */\n"
)
;
}
</s>

Implement ` TARGET_ASM_FUNCTION_BEGIN_EPILOGUE ' .


".L__stack_usage = %d + __gcc_isr.n_pushed\n"

Output summary at end of function prologue .


<s> static void avr_asm_init_sections ( void ) { if ( avr_arch -> flash_pm_offset == 0 ) readonly_data_section -> unnamed . callback = avr_output_data_section_asm_op ; data_section -> unnamed . callback = avr_output_data_section_asm_op ; bss_section -> unnamed . callback = avr_output_bss_section_asm_op ; } </s>

Implement ` TARGET_ASM_INIT_SECTIONS ' .


<s> static const char * avr_asm_len ( const char * tpl , rtx * operands , int * plen , int n_words ) { if ( plen == NULL ) output_asm_insn ( tpl , operands ) ; else { if ( n_words < 0 ) * plen = - n_words ; else * plen += n_words ; } return "" ; } </s>

Helper function to print assembler resp . track instruction sequence lengths . Always return `` '' . If PLEN == NULL : Output assembler code from template TPL with operands supplied by OPERANDS . This is just forwarding to output_asm_insn . If PLEN ! = NULL : If N_WORDS > = 0 Add N_WORDS to * PLEN . If N_WORDS < 0 Set * PLEN to -N_WORDS . Do n't output anything .


<s> static void avr_asm_named_section ( const char * name , unsigned int flags , tree decl ) { if ( flags & AVR_SECTION_PROGMEM ) { addr_space_t as = ( flags & AVR_SECTION_PROGMEM ) / SECTION_MACH_DEP ; const char * old_prefix = ".rodata" ; const char * new_prefix = avr_addrspace [ as ] . section_name ; if ( startswith ( name , old_prefix ) ) { const char * sname = ACONCAT ( ( new_prefix , name + strlen ( old_prefix ) , NULL ) ) ; default_elf_asm_named_section ( sname , flags , decl ) ; return ; } default_elf_asm_named_section ( new_prefix , flags , decl ) ; return ; } if ( ! avr_need_copy_data_p ) avr_need_copy_data_p = ( startswith ( name , ".data" ) || startswith ( name , ".gnu.linkonce.d" ) ) ; if ( ! avr_need_copy_data_p && avr_arch -> flash_pm_offset == 0 ) avr_need_copy_data_p = ( startswith ( name , ".rodata" ) || startswith ( name , ".gnu.linkonce.r" ) ) ; if ( ! avr_need_clear_bss_p ) avr_need_clear_bss_p = startswith ( name , ".bss" ) ; default_elf_asm_named_section ( name , flags , decl ) ; } </s>

Track need of __do_clear_bss , __do_copy_data for named sections .


"static IO declaration for %q+D needs an address"


Worker function for TARGET_ASM_CONSTRUCTOR .


<s>
static
void
avr_asm_out_dtor
(
rtx
symbol
,
int
priority
)
{
fputs
(
"\t.global __do_global_dtors\n"
,
asm_out_file
)
;
default_dtor_section_asm_out_destructor
(
symbol
,
priority
)
;
}
</s>

Worker function for TARGET_ASM_DESTRUCTOR .


<s> static section * avr_asm_select_section ( tree decl , int reloc , unsigned HOST_WIDE_INT align ) { section * sect = default_elf_select_section ( decl , reloc , align ) ; if ( decl && DECL_P ( decl ) && avr_progmem_p ( decl , DECL_ATTRIBUTES ( decl ) ) ) { addr_space_t as = TYPE_ADDR_SPACE ( TREE_TYPE ( decl ) ) ; if ( ADDR_SPACE_GENERIC_P ( as ) ) as = ADDR_SPACE_FLASH ; if ( sect -> common . flags & SECTION_NAMED ) { const char * name = sect -> named . name ; const char * old_prefix = ".rodata" ; const char * new_prefix = avr_addrspace [ as ] . section_name ; if ( startswith ( name , old_prefix ) ) { const char * sname = ACONCAT ( ( new_prefix , name + strlen ( old_prefix ) , NULL ) ) ; return get_section ( sname , sect -> common . flags & ~ SECTION_DECLARED , sect -> named . decl ) ; } } if ( ! progmem_section [ as ] ) { progmem_section [ as ] = get_unnamed_section ( 0 , avr_output_progmem_section_asm_op , avr_addrspace [ as ] . section_name ) ; } return progmem_section [ as ] ; } return sect ; } </s>


<s>
static
bool
avr_assemble_integer
(
rtx
x
,
unsigned
int
size
,
int
aligned_p
)
{
if
(
size
==
POINTER_SIZE
/
BITS_PER_UNIT
&&
aligned_p
&&
text_segment_operand
(
x
,
VOIDmode
)
)
{
fputs
(
"\t.word\tgs("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")\n"
,
asm_out_file
)
;
return
true
;
}
else
if
(
GET_MODE
(
x
)
==
PSImode
)
{
fputs
(
"\t.byte\tlo8("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")"
ASM_COMMENT_START
"need binutils PR13503\n"
,
asm_out_file
)
;
fputs
(
"\t.byte\thi8("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")"
ASM_COMMENT_START
"need binutils PR13503\n"
,
asm_out_file
)
;
fputs
(
"\t.byte\thh8("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")"
ASM_COMMENT_START
"need binutils PR13503\n"
,
asm_out_file
)
;
return
true
;
}
else
if
(
CONST_FIXED_P
(
x
)
)
{
for
(
unsigned
n
=
0
;
n
<
size
;
n
++
)
{
rtx
xn
=
simplify_gen_subreg
(
QImode
,
x
,
GET_MODE
(
x
)
,
n
)
;
default_assemble_integer
(
xn
,
1
,
aligned_p
)
;
}
return
true
;
}
if
(
AVR_TINY
&&
avr_address_tiny_pm_p
(
x
)
)
{
x
=
plus_constant
(
Pmode
,
x
,
avr_arch
->
flash_pm_offset
)
;
}
return
default_assemble_integer
(
x
,
size
,
aligned_p
)
;
}
</s>

Target hook for assembling integer objects . The AVR version needs special handling for references to certain labels .


<s> static tree avr_build_builtin_va_list ( void ) { avr_adjust_type_node ( & ta_type_node , TAmode , 0 ) ; avr_adjust_type_node ( & uta_type_node , UTAmode , 0 ) ; avr_adjust_type_node ( & sat_ta_type_node , TAmode , 1 ) ; avr_adjust_type_node ( & sat_uta_type_node , UTAmode , 1 ) ; unsigned_long_long_accum_type_node = uta_type_node ; long_long_accum_type_node = ta_type_node ; sat_unsigned_long_long_accum_type_node = sat_uta_type_node ; sat_long_long_accum_type_node = sat_ta_type_node ; return std_build_builtin_va_list ( ) ; } </s>

Implement ` TARGET_BUILD_BUILTIN_VA_LIST ' .


<s> static tree avr_builtin_decl ( unsigned id , bool initialize_p ATTRIBUTE_UNUSED ) { if ( id < AVR_BUILTIN_COUNT ) return avr_bdesc [ id ] . fndecl ; return error_mark_node ; } </s>


<s> static bool avr_cannot_modify_jumps_p ( void ) { if ( reload_completed && cfun -> machine && cfun -> machine -> is_naked ) { return true ; } return false ; } </s>

Implement ` TARGET_CANNOT_MODITY_JUMPS_P ' .


<s> static bool avr_can_eliminate ( const int from ATTRIBUTE_UNUSED , const int to ) { return ( ( frame_pointer_needed && to == FRAME_POINTER_REGNUM ) || ! frame_pointer_needed ) ; } </s>

Return true if register FROM can be eliminated via register TO .


"\n;; Failed condition for casesi_<mode>_sequence\n\n"

Perform some extra checks on operands of casesi_ < mode > _sequence . Not all operand dependencies can be described by means of predicates . This function performs left over checks and should always return true . Returning false means that someone changed the casesi expander but did not adjust casesi_ < mode > _sequence .


<s> static unsigned int avr_case_values_threshold ( void ) { return 7 ; } </s>

Supply the default for -- param case-values-threshold=0


<s> static bool avr_class_likely_spilled_p ( reg_class_t c ) { return ( c != ALL_REGS && ( AVR_TINY ? 1 : c != ADDW_REGS ) ) ; } </s>

Return value is nonzero if pseudos that have been assigned to registers of class CLASS would likely be spilled because registers of CLASS are needed for spill registers .


<s> static unsigned char avr_class_max_nregs ( reg_class_t rclass , machine_mode mode ) { if ( rclass == CC_REG && mode == CCmode ) return 1 ; return CEIL ( GET_MODE_SIZE ( mode ) , UNITS_PER_WORD ) ; } </s>

Implement TARGET_CLASS_MAX_NREGS . Reasons described in comments for avr_hard_regno_nregs .


<s> static rtx avr_compare_pattern ( rtx_insn * insn ) { rtx pattern = single_set ( insn ) ; if ( pattern && NONJUMP_INSN_P ( insn ) && REG_P ( SET_DEST ( pattern ) ) && REGNO ( SET_DEST ( pattern ) ) == REG_CC && GET_CODE ( SET_SRC ( pattern ) ) == COMPARE ) { machine_mode mode0 = GET_MODE ( XEXP ( SET_SRC ( pattern ) , 0 ) ) ; machine_mode mode1 = GET_MODE ( XEXP ( SET_SRC ( pattern ) , 1 ) ) ; if ( ( mode0 == VOIDmode || GET_MODE_SIZE ( mode0 ) <= 4 ) && ( mode1 == VOIDmode || GET_MODE_SIZE ( mode1 ) <= 4 ) ) return pattern ; } return NULL_RTX ; } </s>


<s> static void avr_conditional_register_usage ( void ) { if ( AVR_TINY ) { const int tiny_reg_alloc_order [ ] = { 24 , 25 , 22 , 23 , 30 , 31 , 26 , 27 , 28 , 29 , 21 , 20 , 19 , 18 , 16 , 17 , 32 , 33 , 34 , 35 , 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 } ; for ( size_t i = 0 ; i <= 17 ; i ++ ) { fixed_regs [ i ] = 1 ; call_used_regs [ i ] = 1 ; } for ( size_t i = 18 ; i <= LAST_CALLEE_SAVED_REG ; i ++ ) { call_used_regs [ i ] = 0 ; } for ( size_t i = 0 ; i < ARRAY_SIZE ( tiny_reg_alloc_order ) ; i ++ ) { reg_alloc_order [ i ] = tiny_reg_alloc_order [ i ] ; } CLEAR_HARD_REG_SET ( reg_class_contents [ ( int ) ADDW_REGS ] ) ; CLEAR_HARD_REG_SET ( reg_class_contents [ ( int ) NO_LD_REGS ] ) ; } } </s>

Implement ` TARGET_CONDITIONAL_REGISTER_USAGE ' .


"conversion from address space %qs to address space %qs"


<s> static bool avr_decl_absdata_p ( tree decl , tree attributes ) { return ( TREE_CODE ( decl ) == VAR_DECL && NULL_TREE != lookup_attribute ( "absdata" , attributes ) ) ; } </s>

Return true if DECL has attribute ` absdata ' set . This function should only be used for AVR_TINY .


<s> static bool avr_decl_flash_p ( tree decl ) { if ( TREE_CODE ( decl ) != VAR_DECL || TREE_TYPE ( decl ) == error_mark_node ) { return false ; } return ! ADDR_SPACE_GENERIC_P ( TYPE_ADDR_SPACE ( TREE_TYPE ( decl ) ) ) ; } </s>

Return TRUE if DECL is a VAR_DECL located in flash and FALSE , otherwise .


<s> static bool avr_decl_maybe_lds_p ( tree node ) { if ( ! node || TREE_CODE ( node ) != VAR_DECL || DECL_SECTION_NAME ( node ) != NULL ) return false ; if ( TREE_READONLY ( node ) ) return false ; do node = TREE_TYPE ( node ) ; while ( ARRAY_TYPE == TREE_CODE ( node ) ) ; return ( node != error_mark_node && ! TYPE_READONLY ( node ) ) ; } </s>

A helper for the next function . NODE is a decl that is associated with a symbol . Return TRUE if the respective object may be accessed by LDS . There might still be other reasons for why LDS is not appropriate . This function is only appropriate for AVR_TINY .


<s> static bool avr_decl_memx_p ( tree decl ) { if ( TREE_CODE ( decl ) != VAR_DECL || TREE_TYPE ( decl ) == error_mark_node ) { return false ; } return ( ADDR_SPACE_MEMX == TYPE_ADDR_SPACE ( TREE_TYPE ( decl ) ) ) ; } </s>

Return TRUE if DECL is a VAR_DECL located in the 24-bit flash address space and FALSE , otherwise .


<s> static rtx avr_default_expand_builtin ( enum insn_code icode , tree exp , rtx target ) { rtx pat , xop [ 3 ] ; int n_args = call_expr_nargs ( exp ) ; machine_mode tmode = insn_data [ icode ] . operand [ 0 ] . mode ; gcc_assert ( n_args >= 1 && n_args <= 3 ) ; if ( target == NULL_RTX || GET_MODE ( target ) != tmode || ! insn_data [ icode ] . operand [ 0 ] . predicate ( target , tmode ) ) { target = gen_reg_rtx ( tmode ) ; } for ( int n = 0 ; n < n_args ; n ++ ) { tree arg = CALL_EXPR_ARG ( exp , n ) ; rtx op = expand_expr ( arg , NULL_RTX , VOIDmode , EXPAND_NORMAL ) ; machine_mode opmode = GET_MODE ( op ) ; machine_mode mode = insn_data [ icode ] . operand [ n + 1 ] . mode ; if ( ( opmode == SImode || opmode == VOIDmode ) && mode == HImode ) { opmode = HImode ; op = gen_lowpart ( HImode , op ) ; } gcc_assert ( opmode == mode || opmode == VOIDmode ) ; if ( ! insn_data [ icode ] . operand [ n + 1 ] . predicate ( op , mode ) ) op = copy_to_mode_reg ( mode , op ) ; xop [ n ] = op ; } switch ( n_args ) { case 1 : pat = GEN_FCN ( icode ) ( target , xop [ 0 ] ) ; break ; case 2 : pat = GEN_FCN ( icode ) ( target , xop [ 0 ] , xop [ 1 ] ) ; break ; case 3 : pat = GEN_FCN ( icode ) ( target , xop [ 0 ] , xop [ 1 ] , xop [ 2 ] ) ; break ; default : gcc_unreachable ( ) ; } if ( pat == NULL_RTX ) return NULL_RTX ; emit_insn ( pat ) ; return target ; } </s>

Subroutine of avr_expand_builtin to expand vanilla builtins with non-void result and 1 ... 3 arguments .


<s> bool avr_emit3_fix_outputs ( rtx ( * gen ) ( rtx , rtx , rtx ) , rtx * op , unsigned opmask , unsigned rmask ) { const int n = 3 ; rtx hreg [ n ] ; static bool lock = false ; gcc_assert ( opmask < ( 1u << n ) ) ; if ( lock ) return false ; avr_fix_operands ( op , hreg , opmask , rmask ) ; lock = true ; emit_insn ( gen ( op [ 0 ] , op [ 1 ] , op [ 2 ] ) ) ; lock = false ; return avr_move_fixed_operands ( op , hreg , opmask ) ; } </s>

PR63633 : The middle-end might come up with hard regs as output operands . GEN is a sequence generating function like gen_mulsi3 with 3 operands OP [ ] . RMASK is a bit mask representing a subset of hard registers R0 ... R31 : Rn is an element of that set iff bit n of RMASK is set . OPMASK describes a subset of OP [ ] : If bit n of OPMASK is 1 then OP [ n ] has to be fixed ; otherwise OP [ n ] is left alone . Emit the insn sequence as generated by GEN ( ) with all elements of OPMASK which are hard registers overlapping RMASK replaced by newly created pseudo registers . After the sequence has been emitted , emit insns that move the contents of respective pseudos to their hard regs .


<s> bool avr_emit_cpymemhi ( rtx * xop ) { HOST_WIDE_INT count ; machine_mode loop_mode ; addr_space_t as = MEM_ADDR_SPACE ( xop [ 1 ] ) ; rtx loop_reg , addr1 , a_src , a_dest , insn , xas ; rtx a_hi8 = NULL_RTX ; if ( avr_mem_flash_p ( xop [ 0 ] ) ) return false ; if ( ! CONST_INT_P ( xop [ 2 ] ) ) return false ; count = INTVAL ( xop [ 2 ] ) ; if ( count <= 0 ) return false ; a_src = XEXP ( xop [ 1 ] , 0 ) ; a_dest = XEXP ( xop [ 0 ] , 0 ) ; if ( PSImode == GET_MODE ( a_src ) ) { gcc_assert ( as == ADDR_SPACE_MEMX ) ; loop_mode = ( count < 0x100 ) ? QImode : HImode ; loop_reg = gen_rtx_REG ( loop_mode , 24 ) ; emit_move_insn ( loop_reg , gen_int_mode ( count , loop_mode ) ) ; addr1 = simplify_gen_subreg ( HImode , a_src , PSImode , 0 ) ; a_hi8 = simplify_gen_subreg ( QImode , a_src , PSImode , 2 ) ; } else { int segment = avr_addrspace [ as ] . segment ; if ( segment && avr_n_flash > 1 ) { a_hi8 = GEN_INT ( segment ) ; emit_move_insn ( rampz_rtx , a_hi8 = copy_to_mode_reg ( QImode , a_hi8 ) ) ; } else if ( ! ADDR_SPACE_GENERIC_P ( as ) ) { as = ADDR_SPACE_FLASH ; } addr1 = a_src ; loop_mode = ( count <= 0x100 ) ? QImode : HImode ; loop_reg = copy_to_mode_reg ( loop_mode , gen_int_mode ( count , loop_mode ) ) ; } xas = GEN_INT ( as ) ; emit_move_insn ( lpm_addr_reg_rtx , addr1 ) ; emit_move_insn ( gen_rtx_REG ( HImode , REG_X ) , a_dest ) ; gcc_assert ( TMP_REGNO == LPM_REGNO ) ; if ( as != ADDR_SPACE_MEMX ) { rtx ( * fun ) ( rtx , rtx , rtx ) = QImode == loop_mode ? gen_cpymem_qi : gen_cpymem_hi ; insn = fun ( xas , loop_reg , loop_reg ) ; } else { rtx ( * fun ) ( rtx , rtx ) = QImode == loop_mode ? gen_cpymemx_qi : gen_cpymemx_hi ; emit_move_insn ( gen_rtx_REG ( QImode , 23 ) , a_hi8 ) ; insn = fun ( xas , GEN_INT ( avr_addr . rampz ) ) ; } set_mem_addr_space ( SET_SRC ( XVECEXP ( insn , 0 , 0 ) ) , as ) ; emit_insn ( insn ) ; return true ; } </s>

Worker function for cpymemhi expander . XOP [ 0 ] Destination as MEM : BLK XOP [ 1 ] Source `` `` XOP [ 2 ] # Bytes to copy Return TRUE if the expansion is accomplished . Return FALSE if the operand compination is not supported .


<s> int avr_epilogue_uses ( int regno ATTRIBUTE_UNUSED ) { if ( reload_completed && cfun -> machine && ( cfun -> machine -> is_interrupt || cfun -> machine -> is_signal ) ) return 1 ; return 0 ; } </s>


"%s expects a compile time integer constant"

"%s expects a compile time long integer constant"

"rounding to %d bits has no effect for "

"fixed-point value with %d fractional bits"

Expand an expression EXP that calls a built-in function , with result going to TARGET if that 's convenient ( and in mode MODE if that 's convenient ) . SUBTARGET may be used as the target for computing one of EXP 's operands . IGNORE is nonzero if the value is to be ignored .


<s> void avr_expand_prologue ( void ) { HARD_REG_SET set ; HOST_WIDE_INT size ; size = get_frame_size ( ) + avr_outgoing_args_size ( ) ; cfun -> machine -> stack_usage = 0 ; if ( cfun -> machine -> is_naked ) { return ; } avr_regs_to_save ( & set ) ; if ( cfun -> machine -> is_interrupt || cfun -> machine -> is_signal ) { int treg = AVR_TMP_REGNO ; if ( cfun -> machine -> is_interrupt ) emit_insn ( gen_enable_interrupt ( ) ) ; if ( cfun -> machine -> gasisr . maybe ) { cfun -> machine -> gasisr . yes = 1 ; treg = avr_hregs_split_reg ( & set ) ; if ( treg < 0 ) treg = AVR_TMP_REGNO ; cfun -> machine -> gasisr . regno = treg ; cfun -> machine -> stack_usage += 3 + ( treg != AVR_TMP_REGNO ) ; emit_insn ( gen_gasisr ( GEN_INT ( GASISR_Prologue ) , GEN_INT ( treg ) ) ) ; } else { emit_push_byte ( AVR_ZERO_REGNO , true ) ; emit_push_byte ( AVR_TMP_REGNO , true ) ; emit_push_sfr ( sreg_rtx , false , false , AVR_TMP_REGNO ) ; emit_move_insn ( zero_reg_rtx , const0_rtx ) ; emit_use ( zero_reg_rtx ) ; } if ( AVR_HAVE_RAMPD ) emit_push_sfr ( rampd_rtx , false , true , treg ) ; if ( AVR_HAVE_RAMPX && TEST_HARD_REG_BIT ( set , REG_X ) && TEST_HARD_REG_BIT ( set , REG_X + 1 ) ) { emit_push_sfr ( rampx_rtx , false , true , treg ) ; } if ( AVR_HAVE_RAMPY && ( frame_pointer_needed || ( TEST_HARD_REG_BIT ( set , REG_Y ) && TEST_HARD_REG_BIT ( set , REG_Y + 1 ) ) ) ) { emit_push_sfr ( rampy_rtx , false , true , treg ) ; } if ( AVR_HAVE_RAMPZ && TEST_HARD_REG_BIT ( set , REG_Z ) && TEST_HARD_REG_BIT ( set , REG_Z + 1 ) ) { emit_push_sfr ( rampz_rtx , false , AVR_HAVE_RAMPD , treg ) ; } } avr_prologue_setup_frame ( size , set ) ; if ( flag_stack_usage_info ) current_function_static_stack_size = cfun -> machine -> stack_usage + INCOMING_FRAME_SP_OFFSET ; } </s>


<s>
static
void
avr_file_end
(
void
)
{
if
(
avr_need_copy_data_p
)
fputs
(
".global __do_copy_data\n"
,
asm_out_file
)
;
if
(
avr_need_clear_bss_p
)
fputs
(
".global __do_clear_bss\n"
,
asm_out_file
)
;
}
</s>

Outputs to the stdio stream FILE some appropriate text to go at the end of an assembler file .

avr
".global __do_copy_data\n"
".global __do_clear_bss\n"


"architecture %qs supported for assembler only"

Outputs some appropriate text to go at the start of an assembler file .


<s>
void
avr_final_prescan_insn
(
rtx_insn
*
insn
,
rtx
*
operand
ATTRIBUTE_UNUSED
,
int
num_operands
ATTRIBUTE_UNUSED
)
{
if
(
avr_log
.
rtx_costs
)
{
rtx
set
=
single_set
(
insn
)
;
if
(
set
)
fprintf
(
asm_out_file
,
"/* DEBUG: cost = %d.  */\n"
,
set_src_cost
(
SET_SRC
(
set
)
,
GET_MODE
(
SET_DEST
(
set
)
)
,
optimize_insn_for_speed_p
(
)
)
)
;
else
fprintf
(
asm_out_file
,
"/* DEBUG: pattern-cost = %d.  */\n"
,
rtx_cost
(
PATTERN
(
insn
)
,
VOIDmode
,
INSN
,
0
,
optimize_insn_for_speed_p
(
)
)
)
;
}
if
(
avr_log
.
insn_addresses
)
fprintf
(
asm_out_file
,
";; ADDR = %d\n"
,
(
int
)
INSN_ADDRESSES
(
INSN_UID
(
insn
)
)
)
;
}
</s>

avr
"/* DEBUG: cost = %d.  */\n"
"/* DEBUG: pattern-cost = %d.  */\n"
0
";; ADDR = %d\n"


<s> static rtx avr_find_unused_d_reg ( rtx_insn * insn , rtx exclude ) { bool isr_p = ( avr_interrupt_function_p ( current_function_decl ) || avr_signal_function_p ( current_function_decl ) ) ; for ( int regno = 16 ; regno < 32 ; regno ++ ) { rtx reg = all_regs_rtx [ regno ] ; if ( ( exclude && reg_overlap_mentioned_p ( exclude , reg ) ) || fixed_regs [ regno ] ) { continue ; } if ( ! df_regs_ever_live_p ( regno ) && ( TREE_THIS_VOLATILE ( current_function_decl ) || cfun -> machine -> is_OS_task || cfun -> machine -> is_OS_main || ( ! isr_p && call_used_or_fixed_reg_p ( regno ) ) ) ) { return reg ; } if ( df_regs_ever_live_p ( regno ) && reg_unused_after ( insn , reg ) ) { return reg ; } } return NULL_RTX ; } </s>

Fixme : This is a hack because secondary reloads do n't works as expected . Find an unused d-register to be used as scratch in INSN . EXCLUDE is either NULL_RTX or some register . In the case where EXCLUDE is a register , skip all possible return values that overlap EXCLUDE . The policy for the returned register is similar to that of ` reg_unused_after ' , i.e . the returned register may overlap the SET_DEST of INSN . Return a QImode d-register or NULL_RTX if nothing found .


<s> static void avr_fix_operands ( rtx * op , rtx * hreg , unsigned opmask , unsigned rmask ) { for ( ; opmask ; opmask >>= 1 , op ++ ) { rtx reg = * op ; if ( hreg ) * hreg = NULL_RTX ; if ( ( opmask & 1 ) && REG_P ( reg ) && REGNO ( reg ) < FIRST_PSEUDO_REGISTER && ( rmask & regmask ( GET_MODE ( reg ) , REGNO ( reg ) ) ) ) { * op = gen_reg_rtx ( GET_MODE ( reg ) ) ; if ( hreg == NULL ) emit_move_insn ( * op , reg ) ; else * hreg = reg ; } if ( hreg ) hreg ++ ; } } </s>

PR63633 : The middle-end might come up with hard regs as input operands . RMASK is a bit mask representing a subset of hard registers R0 ... R31 : Rn is an element of that set iff bit n of RMASK is set . OPMASK describes a subset of OP [ ] : If bit n of OPMASK is 1 then OP [ n ] has to be fixed ; otherwise OP [ n ] is left alone . For each element of OPMASK which is a hard register overlapping RMASK , replace OP [ n ] with a newly created pseudo register HREG == 0 : Also emit a move insn that copies the contents of that hard register into the new pseudo . HREG ! = 0 : Also set HREG [ n ] to the hard register .


<s> bool avr_float_lib_compare_returns_bool ( machine_mode mode , enum rtx_code ) { if ( mode == DFmode ) { return true ; } return false ; } </s>

Worker function for ` FLOAT_LIB_COMPARE_RETURNS_BOOL ' .


<s> static tree avr_fold_absfx ( tree tval ) { if ( FIXED_CST != TREE_CODE ( tval ) ) return NULL_TREE ; FIXED_VALUE_TYPE fval = TREE_FIXED_CST ( tval ) ; unsigned int bits = GET_MODE_BITSIZE ( fval . mode ) ; double_int ival = fval . data . sext ( bits ) ; if ( ! ival . is_negative ( ) ) return tval ; fval . data = ( ival == double_int :: min_value ( bits , false ) . sext ( bits ) ) ? double_int :: max_value ( bits , false ) : - ival ; return build_fixed ( TREE_TYPE ( tval ) , fval ) ; } </s>

Helper for ` avr_fold_builtin ' that folds absfx ( FIXED_CST ) .


<s> static bool avr_frame_pointer_required_p ( void ) { return ( cfun -> calls_alloca || cfun -> calls_setjmp || cfun -> has_nonlocal_label || crtl -> args . info . nregs == 0 || get_frame_size ( ) > 0 ) ; } </s>

Return 1 if frame pointer for current function required .


<s> static rtx avr_function_arg ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; int bytes = avr_num_arg_regs ( arg . mode , arg . type ) ; if ( cum -> nregs && bytes <= cum -> nregs ) return gen_rtx_REG ( arg . mode , cum -> regno - bytes ) ; return NULL_RTX ; } </s>

Controls whether a function argument is passed in a register , and which register .


"fixed register %s used to pass parameter to function"

Update the summarizer variable CUM to advance past an argument in the argument list .


<s> int avr_function_arg_regno_p ( int r ) { return AVR_TINY ? IN_RANGE ( r , 20 , 25 ) : IN_RANGE ( r , 8 , 25 ) ; } </s>

Returns nonzero if REGNO is the number of a hard register in which function arguments are sometimes passed .


<s> static bool avr_function_ok_for_sibcall ( tree decl_callee , tree exp_callee ) { tree fntype_callee ; if ( cfun -> machine -> sibcall_fails || TARGET_CALL_PROLOGUES ) { return false ; } fntype_callee = TREE_TYPE ( CALL_EXPR_FN ( exp_callee ) ) ; if ( decl_callee ) { decl_callee = TREE_TYPE ( decl_callee ) ; } else { decl_callee = fntype_callee ; while ( FUNCTION_TYPE != TREE_CODE ( decl_callee ) && METHOD_TYPE != TREE_CODE ( decl_callee ) ) { decl_callee = TREE_TYPE ( decl_callee ) ; } } if ( cfun -> machine -> is_interrupt || cfun -> machine -> is_signal || cfun -> machine -> is_naked || avr_naked_function_p ( decl_callee ) ) { return false ; } return true ; } </s>

Decide whether we can make a sibling call to a function . DECL is the declaration of the function being targeted by the call and EXP is the CALL_EXPR representing the call .


<s> static rtx avr_function_value ( const_tree type , const_tree fn_decl_or_type ATTRIBUTE_UNUSED , bool outgoing ATTRIBUTE_UNUSED ) { unsigned int offs ; if ( TYPE_MODE ( type ) != BLKmode ) return avr_libcall_value ( TYPE_MODE ( type ) , NULL_RTX ) ; offs = int_size_in_bytes ( type ) ; if ( offs < 2 ) offs = 2 ; if ( offs > 2 && offs < GET_MODE_SIZE ( SImode ) ) offs = GET_MODE_SIZE ( SImode ) ; else if ( offs > GET_MODE_SIZE ( SImode ) && offs < GET_MODE_SIZE ( DImode ) ) offs = GET_MODE_SIZE ( DImode ) ; return gen_rtx_REG ( BLKmode , avr_ret_register ( ) + 2 - offs ) ; } </s>

Create an RTX representing the place where a function returns a value of data type VALTYPE .


<s> static bool avr_function_value_regno_p ( const unsigned int regno ) { return ( regno == avr_ret_register ( ) ) ; } </s>

Implement ` TARGET_FUNCTION_VALUE_REGNO_P ' .


"%qE attribute only applies to functions"

Handle an attribute requiring a FUNCTION_DECL ; arguments as in struct attribute_spec.handler .


<s>
static
tree
avr_handle_progmem_attribute
(
tree
*
node
,
tree
name
,
tree
args
ATTRIBUTE_UNUSED
,
int
flags
ATTRIBUTE_UNUSED
,
bool
*
no_add_attrs
)
{
if
(
DECL_P
(
*
node
)
)
{
if
(
TREE_CODE
(
*
node
)
==
TYPE_DECL
)
{
tree
type
=
TREE_TYPE
(
*
node
)
;
tree
attr
=
tree_cons
(
name
,
args
,
TYPE_ATTRIBUTES
(
type
)
)
;
tree
newtype
=
build_type_attribute_variant
(
type
,
attr
)
;
TYPE_MAIN_VARIANT
(
newtype
)
=
TYPE_MAIN_VARIANT
(
type
)
;
TREE_TYPE
(
*
node
)
=
newtype
;
*
no_add_attrs
=
true
;
}
else
if
(
TREE_STATIC
(
*
node
)
||
DECL_EXTERNAL
(
*
node
)
)
{
*
no_add_attrs
=
false
;
}
else
{
warning
(
OPT_Wattributes
,
"%qE attribute ignored"
,
name
)
;
*
no_add_attrs
=
true
;
}
}
return
NULL_TREE
;
}
</s>

Handle a `` progmem '' attribute ; arguments as in struct attribute_spec.handler .


<s> static bool avr_hard_regno_call_part_clobbered ( unsigned , unsigned regno , machine_mode mode ) { if ( ! avr_hard_regno_mode_ok ( regno , mode ) ) return 0 ; return ( ( regno <= LAST_CALLEE_SAVED_REG && regno + GET_MODE_SIZE ( mode ) > 1 + LAST_CALLEE_SAVED_REG ) || ( regno < REG_Y && regno + GET_MODE_SIZE ( mode ) > REG_Y ) || ( regno < REG_Z && regno + GET_MODE_SIZE ( mode ) > REG_Z ) ) ; } </s>

Implement ` HARD_REGNO_CALL_PART_CLOBBERED ' .


<s> static bool avr_hard_regno_mode_ok ( unsigned int regno , machine_mode mode ) { if ( regno == REG_CC ) return mode == CCmode ; if ( GET_MODE_SIZE ( mode ) == 1 ) return true ; if ( GET_MODE_SIZE ( mode ) >= 4 && regno >= REG_X ) return false ; return ! ( regno & 1 ) ; } </s>

Returns 1 if a value of mode MODE can be stored starting with hard register number REGNO . On the enhanced core , anything larger than 1 byte must start in even numbered register for `` movw '' to work ( this way we do n't have to check for odd registers everywhere ) .


<s> static unsigned int avr_hard_regno_nregs ( unsigned int regno , machine_mode mode ) { if ( regno == REG_CC && mode == CCmode ) return 1 ; return CEIL ( GET_MODE_SIZE ( mode ) , UNITS_PER_WORD ) ; } </s>

Implement TARGET_HARD_REGNO_NREGS . CCmode is four units for historical reasons . If this hook is not defined , TARGET_HARD_REGNO_NREGS reports that CCmode requires four registers . Define this hook to allow CCmode to fit in a single REG_CC . For other modes and regs , return the number of words in mode ( i.e whatever the default implementation of the hook returned ) .


<s> int avr_hard_regno_rename_ok ( unsigned int old_reg , unsigned int new_reg ) { if ( ( cfun -> machine -> is_interrupt || cfun -> machine -> is_signal ) && ! df_regs_ever_live_p ( new_reg ) ) return 0 ; if ( ( ! reload_completed || frame_pointer_needed ) && ( old_reg == REG_Y || old_reg == REG_Y + 1 || new_reg == REG_Y || new_reg == REG_Y + 1 ) ) { return 0 ; } return 1 ; } </s>

Return nonzero if register OLD_REG can be renamed to register NEW_REG .


<s> static bool avr_hard_regno_scratch_ok ( unsigned int regno ) { if ( ( cfun -> machine -> is_interrupt || cfun -> machine -> is_signal ) && ! df_regs_ever_live_p ( regno ) ) return false ; if ( ( ! reload_completed || frame_pointer_needed ) && ( regno == REG_Y || regno == REG_Y + 1 ) ) { return false ; } return true ; } </s>

Returns true if SCRATCH are safe to be allocated as a scratch registers ( for a define_peephole2 ) in the current function .


<s> bool avr_has_nibble_0xf ( rtx ival ) { unsigned int map = UINTVAL ( ival ) & GET_MODE_MASK ( SImode ) ; return avr_map_metric ( map , MAP_MASK_PREIMAGE_F ) != 0 ; } </s>

Return true if IVAL has a 0xf in its hexadecimal representation and false , otherwise . Only nibbles 0 .. 7 are taken into account . Used as constraint helper for C0f and Cxf .


<s> static int avr_hregs_split_reg ( HARD_REG_SET * set ) { for ( int regno = 0 ; regno < 32 ; regno ++ ) if ( TEST_HARD_REG_BIT ( * set , regno ) ) { if ( AVR_HAVE_RAMPX && ( REG_X == regno || REG_X + 1 == regno ) && TEST_HARD_REG_BIT ( * set , REG_X ) && TEST_HARD_REG_BIT ( * set , REG_X + 1 ) ) continue ; if ( AVR_HAVE_RAMPY && ! frame_pointer_needed && ( REG_Y == regno || REG_Y + 1 == regno ) && TEST_HARD_REG_BIT ( * set , REG_Y ) && TEST_HARD_REG_BIT ( * set , REG_Y + 1 ) ) continue ; if ( AVR_HAVE_RAMPZ && ( REG_Z == regno || REG_Z + 1 == regno ) && TEST_HARD_REG_BIT ( * set , REG_Z ) && TEST_HARD_REG_BIT ( * set , REG_Z + 1 ) ) continue ; CLEAR_HARD_REG_BIT ( * set , regno ) ; return regno ; } return - 1 ; } </s>

Unset a bit in * SET . If successful , return the respective bit number . Otherwise , return -1 and * SET is unaltered .


<s> rtx avr_incoming_return_addr_rtx ( void ) { return gen_frame_mem ( HImode , plus_constant ( Pmode , stack_pointer_rtx , 1 ) ) ; } </s>

Implement ` INCOMING_RETURN_ADDR_RTX ' .


<s> int avr_initial_elimination_offset ( int from , int to ) { if ( from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM ) return 0 ; else { int offset = frame_pointer_needed ? 2 : 0 ; int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2 ; offset += avr_regs_to_save ( NULL ) ; return ( get_frame_size ( ) + avr_outgoing_args_size ( ) + avr_pc_size + 1 + offset ) ; } } </s>

Compute offset between arg_pointer and frame_pointer .


<s> void avr_init_cumulative_args ( CUMULATIVE_ARGS * cum , tree fntype , rtx libname , tree fndecl ATTRIBUTE_UNUSED ) { cum -> nregs = AVR_TINY ? 6 : 18 ; cum -> regno = FIRST_CUM_REG ; if ( ! libname && stdarg_p ( fntype ) ) cum -> nregs = 0 ; cfun -> machine -> sibcall_fails = 0 ; } </s>

Initializing the variable cum for the state at the beginning of the argument list .


<s> void avr_init_expanders ( void ) { for ( int regno = 0 ; regno < 32 ; regno ++ ) all_regs_rtx [ regno ] = gen_rtx_REG ( QImode , regno ) ; lpm_reg_rtx = all_regs_rtx [ LPM_REGNO ] ; tmp_reg_rtx = all_regs_rtx [ AVR_TMP_REGNO ] ; zero_reg_rtx = all_regs_rtx [ AVR_ZERO_REGNO ] ; cc_reg_rtx = gen_rtx_REG ( CCmode , REG_CC ) ; lpm_addr_reg_rtx = gen_rtx_REG ( HImode , REG_Z ) ; sreg_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . sreg ) ) ; rampd_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . rampd ) ) ; rampx_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . rampx ) ) ; rampy_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . rampy ) ) ; rampz_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . rampz ) ) ; xstring_empty = gen_rtx_CONST_STRING ( VOIDmode , "" ) ; xstring_e = gen_rtx_CONST_STRING ( VOIDmode , "e" ) ; if ( AVR_TINY ) avr_have_dimode = false ; } </s>


<s> static struct machine_function * avr_init_machine_status ( void ) { return ggc_cleared_alloc < machine_function > ( ) ; } </s>

Function to set up the backend function structure .


"variable %q+D must be const in order to be put into"

Add the section attribute if the variable is in progmem .


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

Return nonzero if FUNC is an interrupt function as specified by the `` interrupt '' attribute .


";; Sequence not recognized, giving up.\n\n"

Return true if we see an insn stream generated by casesi expander together with an extension to SImode of the switch value . If this is the case , fill in the insns from casesi to INSNS [ 1 .. 5 ] and the SImode extension to INSNS [ 0 ] . Moreover , extract the operands of pattern casesi_ < mode > _sequence forged from the sequence to recog_data .


<s> int avr_jump_mode ( rtx x , rtx_insn * insn ) { int dest_addr = INSN_ADDRESSES ( INSN_UID ( GET_CODE ( x ) == LABEL_REF ? XEXP ( x , 0 ) : x ) ) ; int cur_addr = INSN_ADDRESSES ( INSN_UID ( insn ) ) ; int jump_distance = cur_addr - dest_addr ; if ( IN_RANGE ( jump_distance , - 63 , 62 ) ) return 1 ; else if ( IN_RANGE ( jump_distance , - 2046 , 2045 ) ) return 2 ; else if ( AVR_HAVE_JMP_CALL ) return 3 ; return 2 ; } </s>

Choose mode for jump insn : 1 - relative jump in range -63 < = x < = 62 ; 2 - relative jump in range -2046 < = x < = 2045 ; 3 - absolute jump ( only for ATmega [ 16 ] 03 ) .


Return nonzero if X ( an RTX ) is a legitimate memory address on the target machine for a memory operand of mode MODE .


<s> static bool avr_legitimate_combined_insn ( rtx_insn * insn ) { subrtx_iterator :: array_type array ; FOR_EACH_SUBRTX ( iter , array , PATTERN ( insn ) , NONCONST ) { const_rtx op = * iter ; if ( SUBREG_P ( op ) && MEM_P ( SUBREG_REG ( op ) ) && ( GET_MODE_SIZE ( GET_MODE ( op ) ) > GET_MODE_SIZE ( GET_MODE ( SUBREG_REG ( op ) ) ) ) ) { return false ; } } return true ; } </s>

PR78883 : Filter out paradoxical SUBREGs of MEM which are not handled properly by following passes . As INSN_SCHEDULING is off and hence general_operand accepts such expressions , ditch them now .


<s>
static
rtx
avr_legitimize_address
(
rtx
x
,
rtx
oldx
,
machine_mode
mode
)
{
bool
big_offset_p
=
false
;
x
=
oldx
;
if
(
AVR_TINY
)
{
if
(
CONSTANT_ADDRESS_P
(
x
)
&&
!
avr_address_tiny_absdata_p
(
x
,
mode
)
)
{
x
=
force_reg
(
Pmode
,
x
)
;
}
}
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
;
}
</s>

Attempts to replace X with a valid memory address for an operand of mode MODE


<s>
rtx
avr_legitimize_reload_address
(
rtx
*
px
,
machine_mode
mode
,
int
opnum
,
int
type
,
int
addr_type
,
int
ind_levels
ATTRIBUTE_UNUSED
,
rtx
(
*
mk_memloc
)
(
rtx
,
int
)
)
{
rtx
x
=
*
px
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
"\n%?:%m %r\n"
,
mode
,
x
)
;
if
(
1
&&
(
GET_CODE
(
x
)
==
POST_INC
||
GET_CODE
(
x
)
==
PRE_DEC
)
)
{
push_reload
(
XEXP
(
x
,
0
)
,
XEXP
(
x
,
0
)
,
&
XEXP
(
x
,
0
)
,
&
XEXP
(
x
,
0
)
,
POINTER_REGS
,
GET_MODE
(
x
)
,
GET_MODE
(
x
)
,
0
,
0
,
opnum
,
RELOAD_OTHER
)
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
" RCLASS.1 = %R\n IN = %r\n OUT = %r\n"
,
POINTER_REGS
,
XEXP
(
x
,
0
)
,
XEXP
(
x
,
0
)
)
;
return
x
;
}
if
(
GET_CODE
(
x
)
==
PLUS
&&
REG_P
(
XEXP
(
x
,
0
)
)
&&
reg_equiv_constant
(
REGNO
(
XEXP
(
x
,
0
)
)
)
==
0
&&
CONST_INT_P
(
XEXP
(
x
,
1
)
)
&&
INTVAL
(
XEXP
(
x
,
1
)
)
>=
1
)
{
bool
fit
=
INTVAL
(
XEXP
(
x
,
1
)
)
<=
MAX_LD_OFFSET
(
mode
)
;
if
(
fit
)
{
if
(
reg_equiv_address
(
REGNO
(
XEXP
(
x
,
0
)
)
)
!=
0
)
{
int
regno
=
REGNO
(
XEXP
(
x
,
0
)
)
;
rtx
mem
=
mk_memloc
(
x
,
regno
)
;
push_reload
(
XEXP
(
mem
,
0
)
,
NULL_RTX
,
&
XEXP
(
mem
,
0
)
,
,
POINTER_REGS
,
Pmode
,
VOIDmode
,
0
,
0
,
1
,
(
enum
reload_type
)
addr_type
)
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
" RCLASS.2 = %R\n IN = %r\n OUT = %r\n"
,
POINTER_REGS
,
XEXP
(
mem
,
0
)
,
NULL_RTX
)
;
push_reload
(
mem
,
NULL_RTX
,
&
XEXP
(
x
,
0
)
,
,
BASE_POINTER_REGS
,
GET_MODE
(
x
)
,
VOIDmode
,
0
,
0
,
opnum
,
(
enum
reload_type
)
type
)
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
" RCLASS.2 = %R\n IN = %r\n OUT = %r\n"
,
BASE_POINTER_REGS
,
mem
,
NULL_RTX
)
;
return
x
;
}
}
else
if
(
!
(
frame_pointer_needed
&&
XEXP
(
x
,
0
)
==
frame_pointer_rtx
)
)
{
push_reload
(
x
,
NULL_RTX
,
px
,
,
POINTER_REGS
,
GET_MODE
(
x
)
,
VOIDmode
,
0
,
0
,
opnum
,
(
enum
reload_type
)
type
)
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
" RCLASS.3 = %R\n IN = %r\n OUT = %r\n"
,
POINTER_REGS
,
x
,
NULL_RTX
)
;
return
x
;
}
}
return
NULL_RTX
;
}
</s>

This will allow register R26/27 to be used where it is no worse than normal base pointers R28/29 or R30/31 . For example , if base offset is greater than 63 bytes or for R++ or -- R addressing .


<s> static rtx avr_libcall_value ( machine_mode mode , const_rtx func ATTRIBUTE_UNUSED ) { int offs = GET_MODE_SIZE ( mode ) ; if ( offs <= 4 ) offs = ( offs + 1 ) & ~ 1 ; return gen_rtx_REG ( mode , avr_ret_register ( ) + 2 - offs ) ; } </s>

Ceate an RTX representing the place where a library function returns a value of mode MODE .


<s> bool avr_load_libgcc_p ( rtx op ) { machine_mode mode = GET_MODE ( op ) ; int n_bytes = GET_MODE_SIZE ( mode ) ; return ( n_bytes > 2 && ! AVR_HAVE_LPMX && avr_mem_flash_p ( op ) ) ; } </s>

Return true if a value of mode MODE is read from flash by __load_ * function from libgcc .


<s> static inline int avr_lookup_function_attribute1 ( const_tree func , const char * name ) { if ( FUNCTION_DECL == TREE_CODE ( func ) ) { if ( NULL_TREE != lookup_attribute ( name , DECL_ATTRIBUTES ( func ) ) ) { return true ; } func = TREE_TYPE ( func ) ; } gcc_assert ( TREE_CODE ( func ) == FUNCTION_TYPE || TREE_CODE ( func ) == METHOD_TYPE ) ; return NULL_TREE != lookup_attribute ( name , TYPE_ATTRIBUTES ( func ) ) ; } </s>

A helper for the subsequent function attribute used to dig for attribute 'name ' in a FUNCTION_DECL or FUNCTION_TYPE


<s> static int avr_map ( unsigned int f , int x ) { return x < 8 ? ( f >> ( 4 * x ) ) & 0xf : 0 ; } </s>

Compute the image of x under f , i.e . perform x -- > f ( x )


<s>
static
avr_map_op_t
avr_map_decompose
(
unsigned
int
f
,
const
avr_map_op_t
*
g
,
bool
val_const_p
)
{
bool
val_used_p
=
avr_map_metric
(
f
,
MAP_MASK_PREIMAGE_F
)
!=
0
;
avr_map_op_t
f_ginv
=
*
g
;
unsigned
int
ginv
=
g
->
ginv
;
f_ginv
.
cost
=
1
;
for
(
int
i
=
7
;
i
>=
0
;
i
)
{
int
x
=
avr_map
(
f
,
i
)
;
if
(
x
<=
7
)
{
x
=
avr_map
(
ginv
,
x
)
;
if
(
x
>
7
)
return
f_ginv
;
}
f_ginv
.
map
=
(
f_ginv
.
map
<<
4
)
+
x
;
}
if
(
avr_map_metric
(
f_ginv
.
map
,
MAP_NONFIXED_0_7
)
==
0
)
f_ginv
.
cost
=
2
+
(
val_used_p
&&
!
val_const_p
)
;
else
{
rtx
xop
[
4
]
;
xop
[
0
]
=
all_regs_rtx
[
24
]
;
xop
[
1
]
=
gen_int_mode
(
f_ginv
.
map
,
SImode
)
;
xop
[
2
]
=
all_regs_rtx
[
25
]
;
xop
[
3
]
=
val_used_p
xop
[
0
]
:
const0_rtx
;
avr_out_insert_bits
(
xop
,
&
f_ginv
.
cost
)
;
f_ginv
.
cost
+=
val_const_p
&&
val_used_p
1
:
0
;
}
f_ginv
.
cost
+=
g
->
cost
;
if
(
avr_log
.
builtin
)
avr_edump
(
" %s%d=%d"
,
g
->
str
,
g
->
arg
,
f_ginv
.
cost
)
;
return
f_ginv
;
}
</s>

Try to decompose F as F = ( F o G^-1 ) o G as described above . The result is a struct representing F o G^-1 and G. If result.cost < 0 then such a decomposition does not exist .


<s> static rtx_insn * avr_md_asm_adjust ( vec < rtx > & , vec < rtx > & , vec < machine_mode > & , vec < const char * > & , vec < rtx > & clobbers , HARD_REG_SET & clobbered_regs , location_t ) { clobbers . safe_push ( cc_reg_rtx ) ; SET_HARD_REG_BIT ( clobbered_regs , REG_CC ) ; return NULL ; } </s>

Prepend to CLOBBERS hard registers that are automatically clobbered for an asm . We do this for CC_REGNUM to maintain source compatibility with the original cc0-based compiler .


<s> static int avr_memory_move_cost ( machine_mode mode , reg_class_t rclass ATTRIBUTE_UNUSED , bool in ATTRIBUTE_UNUSED ) { return ( mode == QImode ? 2 : mode == HImode ? 4 : mode == SImode ? 8 : mode == SFmode ? 8 : 16 ) ; } </s>


<s> static rtx avr_mem_clobber ( void ) { rtx mem = gen_rtx_MEM ( BLKmode , gen_rtx_SCRATCH ( Pmode ) ) ; MEM_VOLATILE_P ( mem ) = 1 ; return mem ; } </s>


<s> bool avr_mem_flash_p ( rtx x ) { return ( MEM_P ( x ) && ! ADDR_SPACE_GENERIC_P ( MEM_ADDR_SPACE ( x ) ) ) ; } </s>

Return TRUE if X is a MEM rtx located in flash and FALSE , otherwise .


<s> bool avr_mem_memx_p ( rtx x ) { return ( MEM_P ( x ) && ADDR_SPACE_MEMX == MEM_ADDR_SPACE ( x ) ) ; } </s>

Return TRUE if X is a MEM rtx located in the 24-bit flash address space and FALSE , otherwise .


Implement ` MODE_CODE_BASE_REG_CLASS ' .


<s> static bool avr_mode_dependent_address_p ( const_rtx addr ATTRIBUTE_UNUSED , addr_space_t as ) { return ! ADDR_SPACE_GENERIC_P ( as ) ; } </s>

Implement ` TARGET_MODE_DEPENDENT_ADDRESS_P ' .


<s>
static
void
avr_move_bits
(
rtx
*
xop
,
unsigned
int
map
,
bool
fixp_p
,
int
*
plen
)
{
int
t_bit_src
=
1
;
for
(
int
b
=
0
;
b
<
8
;
b
++
)
for
(
int
bit_dest
=
0
;
bit_dest
<
8
;
bit_dest
++
)
{
int
bit_src
=
avr_map
(
map
,
bit_dest
)
;
if
(
b
!=
bit_src
||
bit_src
>=
8
||
(
bit_dest
==
bit_src
&&
!
fixp_p
)
)
continue
;
if
(
t_bit_src
!=
bit_src
)
{
t_bit_src
=
bit_src
;
xop
[
3
]
=
GEN_INT
(
bit_src
)
;
avr_asm_len
(
"bst %T1%T3"
,
xop
,
plen
,
1
)
;
}
xop
[
3
]
=
GEN_INT
(
bit_dest
)
;
avr_asm_len
(
"bld %T0%T3"
,
xop
,
plen
,
1
)
;
}
}
</s>

Insert bits from XOP [ 1 ] into XOP [ 0 ] according to MAP . XOP [ 0 ] and XOP [ 1 ] do n't overlap . If FIXP_P = true : Move all bits according to MAP using BLD/BST sequences . If FIXP_P = false : Just move the bit if its position in the destination is different to its source position .


<s> static bool avr_move_fixed_operands ( rtx * op , rtx * hreg , unsigned mask ) { for ( ; mask ; mask >>= 1 , op ++ , hreg ++ ) if ( ( mask & 1 ) && * hreg ) emit_move_insn ( * hreg , * op ) ; return true ; } </s>

Helper for the function below : If bit n of MASK is set and HREG [ n ] ! = NULL , then emit a move insn to copy OP [ n ] to HREG [ n ] . Otherwise do nothing for that n. Return TRUE .


<s> static int avr_mul_highpart_cost ( rtx x , int ) { if ( AVR_HAVE_MUL && LSHIFTRT == GET_CODE ( x ) && MULT == GET_CODE ( XEXP ( x , 0 ) ) && CONST_INT_P ( XEXP ( x , 1 ) ) ) { machine_mode mode = GET_MODE ( x ) ; if ( HImode == mode || PSImode == mode || SImode == mode ) { return COSTS_N_INSNS ( 2 ) ; } } return 10000 ; } </s>

Cost for mul highpart . X is a LSHIFTRT , i.e . the outer TRUNCATE is already stripped off .


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

Return non-zero if FUNC is a naked function .


<s> static addr_space_t avr_nonconst_pointer_addrspace ( tree typ ) { while ( ARRAY_TYPE == TREE_CODE ( typ ) ) typ = TREE_TYPE ( typ ) ; if ( POINTER_TYPE_P ( typ ) ) { addr_space_t as ; tree target = TREE_TYPE ( typ ) ; if ( FUNCTION_TYPE == TREE_CODE ( target ) ) return avr_nonconst_pointer_addrspace ( TREE_TYPE ( target ) ) ; while ( TREE_CODE ( target ) == ARRAY_TYPE ) target = TREE_TYPE ( target ) ; as = TYPE_ADDR_SPACE ( target ) ; if ( ! ADDR_SPACE_GENERIC_P ( as ) && ! TYPE_READONLY ( target ) && avr_addr_space_supported_p ( as ) ) { return as ; } return avr_nonconst_pointer_addrspace ( target ) ; } return ADDR_SPACE_GENERIC ; } </s>

Scan type TYP for pointer references to address space ASn . Return ADDR_SPACE_GENERIC ( i.e . 0 ) if all pointers targeting the AS are also declared to be CONST . Otherwise , return the respective address space , i.e . a value ! = 0 .


<s> RTX_CODE avr_normalize_condition ( RTX_CODE condition ) { switch ( condition ) { case GT : return GE ; case GTU : return GEU ; case LE : return LT ; case LEU : return LTU ; default : gcc_unreachable ( ) ; } } </s>

Convert condition code CONDITION to the valid AVR condition code


<s> void avr_notice_update_cc ( rtx body ATTRIBUTE_UNUSED , rtx_insn * insn ) { rtx set ; enum attr_cc cc = get_attr_cc ( insn ) ; switch ( cc ) { default : break ; case CC_PLUS : case CC_LDI : { rtx * op = recog_data . operand ; int len_dummy , icc ; extract_constrain_insn_cached ( insn ) ; switch ( cc ) { default : gcc_unreachable ( ) ; case CC_PLUS : avr_out_plus ( insn , op , & len_dummy , & icc ) ; cc = ( enum attr_cc ) icc ; break ; case CC_LDI : cc = ( op [ 1 ] == CONST0_RTX ( GET_MODE ( op [ 0 ] ) ) && reg_overlap_mentioned_p ( op [ 0 ] , zero_reg_rtx ) ) ? CC_CLOBBER : CC_NONE ; break ; } break ; } } switch ( cc ) { default : gcc_unreachable ( ) ; break ; case CC_NONE : if ( cc_status . value1 || cc_status . value2 ) { HARD_REG_SET regs_used ; HARD_REG_SET regs_set ; CLEAR_HARD_REG_SET ( regs_used ) ; if ( cc_status . value1 && ! CONSTANT_P ( cc_status . value1 ) ) { find_all_hard_regs ( cc_status . value1 , & regs_used ) ; } if ( cc_status . value2 && ! CONSTANT_P ( cc_status . value2 ) ) { find_all_hard_regs ( cc_status . value2 , & regs_used ) ; } find_all_hard_reg_sets ( insn , & regs_set , false ) ; if ( hard_reg_set_intersect_p ( regs_used , regs_set ) ) { CC_STATUS_INIT ; } } break ; case CC_SET_N : CC_STATUS_INIT ; break ; case CC_SET_ZN : set = single_set ( insn ) ; CC_STATUS_INIT ; if ( set ) { cc_status . flags |= CC_NO_OVERFLOW ; cc_status . value1 = SET_DEST ( set ) ; } break ; case CC_SET_VZN : CC_STATUS_INIT ; break ; case CC_SET_CZN : set = single_set ( insn ) ; CC_STATUS_INIT ; if ( set ) { cc_status . value1 = SET_DEST ( set ) ; cc_status . flags |= CC_OVERFLOW_UNUSABLE ; } break ; case CC_COMPARE : set = single_set ( insn ) ; CC_STATUS_INIT ; if ( set ) cc_status . value1 = SET_SRC ( set ) ; break ; case CC_CLOBBER : CC_STATUS_INIT ; break ; } } </s>


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

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


<s> static int avr_num_arg_regs ( machine_mode mode , const_tree type ) { int size ; if ( mode == BLKmode ) size = int_size_in_bytes ( type ) ; else size = GET_MODE_SIZE ( mode ) ; return ( size + 1 ) & ~ 1 ; } </s>

Returns the number of registers to allocate for a function argument .


<s> static int avr_operand_rtx_cost ( rtx x , machine_mode mode , enum rtx_code outer , int opno , bool speed ) { enum rtx_code code = GET_CODE ( x ) ; int total ; switch ( code ) { case REG : case SUBREG : return 0 ; case CONST_INT : case CONST_FIXED : case CONST_DOUBLE : return COSTS_N_INSNS ( GET_MODE_SIZE ( mode ) ) ; default : break ; } total = 0 ; avr_rtx_costs ( x , mode , outer , opno , & total , speed ) ; return total ; } </s>

Mutually recursive subroutine of avr_rtx_cost for calculating the cost of an RTX operand given its context . X is the rtx of the operand , MODE is its mode , and OUTER is the rtx_code of this operand 's parent operator .


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

Return nonzero if FUNC is an OS_main function .


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

Return nonzero if FUNC is an OS_task function .


<s> static inline int avr_outgoing_args_size ( void ) { return ( ACCUMULATE_OUTGOING_ARGS ? ( HOST_WIDE_INT ) crtl -> outgoing_args_size : 0 ) ; } </s>

Report contribution of accumulated outgoing arguments to stack size .


<s>
void
avr_output_addr_vec
(
rtx_insn
*
labl
,
rtx
table
)
{
FILE
*
stream
=
asm_out_file
;
app_disable
(
)
;
if
(
DECL_SECTION_NAME
(
current_function_decl
)
&&
symtab_node
::
get
(
current_function_decl
)
&&
!
symtab_node
::
get
(
current_function_decl
)
->
implicit_section
)
{
switch_to_section
(
current_function_section
(
)
)
;
fprintf
(
stream
,
"\t.subsection\t1\n"
)
;
}
else
{
const
char
*
sec_name
=
".jumptables.gcc"
;
tree
asm_name
=
DECL_ASSEMBLER_NAME
(
current_function_decl
)
;
const
char
*
fname
=
IDENTIFIER_POINTER
(
asm_name
)
;
fname
=
targetm
.
strip_name_encoding
(
fname
)
;
sec_name
=
ACONCAT
(
(
sec_name
,
"."
,
fname
,
)
)
;
fprintf
(
stream
,
"\t.section\t%s,\"%s\",@progbits\n"
,
sec_name
,
AVR_HAVE_JMP_CALL
"a"
:
"ax"
)
;
}
ASM_OUTPUT_ALIGN
(
stream
,
1
)
;
targetm
.
asm_out
.
internal_label
(
stream
,
"L"
,
CODE_LABEL_NUMBER
(
labl
)
)
;
int
vlen
=
XVECLEN
(
table
,
0
)
;
for
(
int
idx
=
0
;
idx
<
vlen
;
idx
++
)
{
int
value
=
CODE_LABEL_NUMBER
(
XEXP
(
XVECEXP
(
table
,
0
,
idx
)
,
0
)
)
;
if
(
AVR_HAVE_JMP_CALL
)
fprintf
(
stream
,
"\t.word gs(.L%d)\n"
,
value
)
;
else
fprintf
(
stream
,
"\trjmp .L%d\n"
,
value
)
;
}
in_section
=
;
switch_to_section
(
current_function_section
(
)
)
;
}
</s>

Emit jump tables out-of-line so that branches crossing the table get shorter offsets . If we have JUMP + CALL , then put the tables in a dedicated non-.text section so that CALLs get better chance to be relaxed to RCALLs . We emit the tables by hand because ` function_rodata_section ' does not work as expected , cf . PR71151 , and we do * NOT * want the table to be in .rodata , hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited use ; and setting it to 1 attributes table lengths to branch offsets ... Moreover , fincal.c keeps switching section before each table entry which we find too fragile as to rely on section caching .


<s> static void avr_output_bss_section_asm_op ( const char * data ) { avr_need_clear_bss_p = true ; output_section_asm_op ( data ) ; } </s>

Unnamed section callback for bss_section to track need of __do_clear_bss .


<s> static void avr_output_data_section_asm_op ( const char * data ) { avr_need_copy_data_p = true ; output_section_asm_op ( data ) ; } </s>

Unnamed section callback for data_section to track need of __do_copy_data .


<s> static void avr_output_progmem_section_asm_op ( const char * data ) { fprintf ( asm_out_file , "\t.section\t%s,\"a\",@progbits\n" , data ) ; } </s>

Unnamed section callback for progmem * .data sections .


<s>
const
char
*
avr_out_addto_sp
(
rtx
*
op
,
int
*
plen
)
{
int
pc_len
=
AVR_2_BYTE_PC
2
:
3
;
int
addend
=
INTVAL
(
op
[
0
]
)
;
if
(
plen
)
*
plen
=
0
;
if
(
addend
<
0
)
{
if
(
flag_verbose_asm
||
flag_print_asm_name
)
avr_asm_len
(
ASM_COMMENT_START
"SP -= %n0"
,
op
,
plen
,
0
)
;
while
(
addend
<=
pc_len
)
{
addend
+=
pc_len
;
avr_asm_len
(
"rcall ."
,
op
,
plen
,
1
)
;
}
while
(
addend
++
<
0
)
avr_asm_len
(
"push __tmp_reg__"
,
op
,
plen
,
1
)
;
}
else
if
(
addend
>
0
)
{
if
(
flag_verbose_asm
||
flag_print_asm_name
)
avr_asm_len
(
ASM_COMMENT_START
"SP += %0"
,
op
,
plen
,
0
)
;
while
(
addend
>
0
)
avr_asm_len
(
"pop __tmp_reg__"
,
op
,
plen
,
1
)
;
}
return
""
;
}
</s>

PLEN == NULL : Output code to add CONST_INT OP [ 0 ] to SP . PLEN ! = NULL : Set * PLEN to the length of that sequence . Return `` '' .


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


<s>
const
char
*
avr_out_ashrpsi3
(
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"
CR_TAB
"sbrc %B0,7"
CR_TAB
"dec %C0"
,
op
,
plen
,
5
)
;
else
return
avr_asm_len
(
"clr %C0"
CR_TAB
"sbrc %C1,7"
CR_TAB
"dec %C0"
CR_TAB
"mov %B0,%C1"
CR_TAB
"mov %A0,%B1"
,
op
,
plen
,
5
)
;
case
16
:
if
(
dest
!=
src
+
2
)
avr_asm_len
(
"mov %A0,%C1"
,
op
,
plen
,
1
)
;
return
avr_asm_len
(
"clr %B0"
CR_TAB
"sbrc %A0,7"
CR_TAB
"com %B0"
CR_TAB
"mov %C0,%B0"
,
op
,
plen
,
4
)
;
default
:
if
(
INTVAL
(
op
[
2
]
)
<
24
)
break
;
case
23
:
return
avr_asm_len
(
"lsl %C0"
CR_TAB
"sbc %A0,%A0"
CR_TAB
"mov %B0,%A0"
CR_TAB
"mov %C0,%A0"
,
op
,
plen
,
4
)
;
}
}
out_shift_with_cnt
(
"asr %C0"
CR_TAB
"ror %B0"
CR_TAB
"ror %A0"
,
insn
,
op
,
plen
,
3
)
;
return
""
;
}
</s>


<s> const char * avr_out_compare64 ( rtx_insn * insn , rtx * op , int * plen ) { rtx xop [ 3 ] ; xop [ 0 ] = gen_rtx_REG ( DImode , 18 ) ; xop [ 1 ] = op [ 0 ] ; xop [ 2 ] = op [ 1 ] ; return avr_out_compare ( insn , xop , plen ) ; } </s>

Prepare operands of compare_const_di2 to be used with avr_out_compare .


<s>
const
char
*
avr_out_cpymem
(
rtx_insn
*
insn
ATTRIBUTE_UNUSED
,
rtx
*
op
,
int
*
plen
)
{
addr_space_t
as
=
(
addr_space_t
)
INTVAL
(
op
[
0
]
)
;
machine_mode
loop_mode
=
GET_MODE
(
op
[
1
]
)
;
bool
sbiw_p
=
test_hard_reg_class
(
ADDW_REGS
,
op
[
1
]
)
;
rtx
xop
[
3
]
;
if
(
plen
)
*
plen
=
0
;
xop
[
0
]
=
op
[
0
]
;
xop
[
1
]
=
op
[
1
]
;
xop
[
2
]
=
tmp_reg_rtx
;
avr_asm_len
(
"0:"
,
xop
,
plen
,
0
)
;
switch
(
as
)
{
default
:
gcc_unreachable
(
)
;
case
ADDR_SPACE_GENERIC
:
avr_asm_len
(
"ld %2,Z+"
,
xop
,
plen
,
1
)
;
break
;
case
ADDR_SPACE_FLASH
:
if
(
AVR_HAVE_LPMX
)
avr_asm_len
(
"lpm %2,Z+"
,
xop
,
plen
,
1
)
;
else
avr_asm_len
(
"lpm"
CR_TAB
"adiw r30,1"
,
xop
,
plen
,
2
)
;
break
;
case
ADDR_SPACE_FLASH1
:
case
ADDR_SPACE_FLASH2
:
case
ADDR_SPACE_FLASH3
:
case
ADDR_SPACE_FLASH4
:
case
ADDR_SPACE_FLASH5
:
if
(
AVR_HAVE_ELPMX
)
avr_asm_len
(
"elpm %2,Z+"
,
xop
,
plen
,
1
)
;
else
avr_asm_len
(
"elpm"
CR_TAB
"adiw r30,1"
,
xop
,
plen
,
2
)
;
break
;
}
avr_asm_len
(
"st X+,%2"
,
xop
,
plen
,
1
)
;
if
(
QImode
==
loop_mode
)
{
avr_asm_len
(
"dec %1"
,
xop
,
plen
,
1
)
;
}
else
if
(
sbiw_p
)
{
avr_asm_len
(
"sbiw %1,1"
,
xop
,
plen
,
1
)
;
}
else
{
avr_asm_len
(
"subi %A1,1"
CR_TAB
"sbci %B1,0"
,
xop
,
plen
,
2
)
;
}
return
avr_asm_len
(
"brne 0b"
,
xop
,
plen
,
1
)
;
}
</s>

Print assembler for cpymem_qi , cpymem_hi insns ... $ 0 : Address Space $ 1 , $ 2 : Loop register Z : Source address X : Destination address