<s> static void asm_print_register ( FILE * file , int regno ) { const char * name = reg_names [ regno ] ; if ( TARGET_NO_DIRECT_MODE && name [ 0 ] == '*' ) name ++ ; fprintf ( file , "%s" , name ) ; } </s>

Print the name of register 'regno ' in the assembly file .


<s> static int autoinc_mode ( rtx x ) { if ( GET_CODE ( x ) != MEM ) return CONST ; x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == PRE_INC || GET_CODE ( x ) == PRE_DEC || GET_CODE ( x ) == POST_INC || GET_CODE ( x ) == POST_DEC ) return GET_CODE ( x ) ; return CONST ; } </s>

Return the increment/decrement mode of a MEM if it is such . Return CONST if it is anything else .


<s> void create_regs_rtx ( void ) { ix_reg = gen_rtx_REG ( HImode , HARD_X_REGNUM ) ; iy_reg = gen_rtx_REG ( HImode , HARD_Y_REGNUM ) ; d_reg = gen_rtx_REG ( HImode , HARD_D_REGNUM ) ; m68hc11_soft_tmp_reg = gen_rtx_REG ( HImode , SOFT_TMP_REGNUM ) ; stack_push_word = gen_rtx_MEM ( HImode , gen_rtx_PRE_DEC ( HImode , gen_rtx_REG ( HImode , HARD_SP_REGNUM ) ) ) ; stack_pop_word = gen_rtx_MEM ( HImode , gen_rtx_POST_INC ( HImode , gen_rtx_REG ( HImode , HARD_SP_REGNUM ) ) ) ; } </s>


<s> int dead_register_here ( rtx x , rtx reg ) { rtx x_reg ; rtx p ; if ( D_REG_P ( reg ) ) x_reg = gen_rtx_REG ( SImode , HARD_X_REGNUM ) ; else x_reg = 0 ; for ( p = PREV_INSN ( x ) ; p && GET_CODE ( p ) != CODE_LABEL ; p = PREV_INSN ( p ) ) if ( INSN_P ( p ) ) { rtx body ; body = PATTERN ( p ) ; if ( GET_CODE ( body ) == CALL_INSN ) break ; if ( GET_CODE ( body ) == JUMP_INSN ) break ; if ( GET_CODE ( body ) == SET ) { rtx dst = XEXP ( body , 0 ) ; if ( GET_CODE ( dst ) == REG && REGNO ( dst ) == REGNO ( reg ) ) break ; if ( x_reg && rtx_equal_p ( dst , x_reg ) ) break ; if ( find_regno_note ( p , REG_DEAD , REGNO ( reg ) ) ) return 1 ; } else if ( reg_mentioned_p ( reg , p ) || ( x_reg && reg_mentioned_p ( x_reg , p ) ) ) break ; } for ( p = x ; p ; p = NEXT_INSN ( p ) ) { rtx body ; if ( GET_CODE ( p ) == CODE_LABEL || GET_CODE ( p ) == JUMP_INSN || GET_CODE ( p ) == CALL_INSN || GET_CODE ( p ) == BARRIER ) break ; if ( GET_CODE ( p ) != INSN ) continue ; body = PATTERN ( p ) ; if ( GET_CODE ( body ) == SET ) { rtx src = XEXP ( body , 1 ) ; rtx dst = XEXP ( body , 0 ) ; if ( GET_CODE ( dst ) == REG && REGNO ( dst ) == REGNO ( reg ) && ! reg_mentioned_p ( reg , src ) ) return 1 ; } if ( reg_mentioned_p ( reg , p ) || ( x_reg != 0 && GET_MODE ( p ) == SImode && reg_mentioned_p ( x_reg , p ) ) ) break ; } return p == 0 ? 1 : 0 ; } </s>

Finds backward in the instructions to see if register 'reg ' is dead . This is used when generating code to see if we can use 'reg ' as a scratch register . This allows us to choose a better generation of code when we know that some register dies or can be clobbered .


<s> static void emit_move_after_reload ( rtx to , rtx from , rtx scratch ) { rtx insn ; if ( TARGET_M6812 || H_REG_P ( to ) || H_REG_P ( from ) ) { insn = emit_move_insn ( to , from ) ; } else { emit_move_insn ( scratch , from ) ; insn = emit_move_insn ( to , scratch ) ; } if ( IS_STACK_PUSH ( to ) ) { REG_NOTES ( insn ) = gen_rtx_EXPR_LIST ( REG_INC , XEXP ( XEXP ( to , 0 ) , 0 ) , REG_NOTES ( insn ) ) ; } else if ( IS_STACK_POP ( from ) ) { REG_NOTES ( insn ) = gen_rtx_EXPR_LIST ( REG_INC , XEXP ( XEXP ( from , 0 ) , 0 ) , REG_NOTES ( insn ) ) ; } else if ( TARGET_M6811 && SP_REG_P ( from ) ) { REG_NOTES ( insn ) = gen_rtx_EXPR_LIST ( REG_INC , from , REG_NOTES ( insn ) ) ; } } </s>

Emit a move after the reload pass has completed . This is used to emit the prologue and epilogue .


<s> void expand_epilogue ( void ) { int size ; register int regno ; int return_size ; rtx scratch ; gcc_assert ( reload_completed == 1 ) ; size = get_frame_size ( ) ; if ( current_function_return_rtx == 0 ) return_size = 0 ; else if ( GET_CODE ( current_function_return_rtx ) == MEM ) return_size = HARD_REG_SIZE ; else return_size = GET_MODE_SIZE ( GET_MODE ( current_function_return_rtx ) ) ; if ( return_size > HARD_REG_SIZE && return_size <= 2 * HARD_REG_SIZE ) scratch = iy_reg ; else scratch = ix_reg ; for ( regno = SOFT_REG_LAST ; regno >= SOFT_REG_FIRST ; regno -- ) { if ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) { emit_move_after_reload ( gen_rtx_REG ( HImode , regno ) , stack_pop_word , scratch ) ; } } if ( TARGET_M6812 && ( size > 4 || size == 3 ) ) { emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( size ) ) ) ; } else if ( ( ! optimize_size && size > 8 ) || ( optimize_size && size > 10 ) ) { rtx insn ; insn = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , gen_rtx_SET ( VOIDmode , stack_pointer_rtx , gen_rtx_PLUS ( HImode , stack_pointer_rtx , GEN_INT ( size ) ) ) , gen_rtx_CLOBBER ( VOIDmode , scratch ) ) ) ; emit_insn ( insn ) ; } else { int i ; for ( i = 2 ; i <= size ; i += 2 ) emit_move_after_reload ( scratch , stack_pop_word , scratch ) ; if ( size & 1 ) emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , const1_rtx ) ) ; } if ( current_function_interrupt ) { emit_move_after_reload ( gen_rtx_REG ( HImode , SOFT_SAVED_XY_REGNUM ) , stack_pop_word , scratch ) ; emit_move_after_reload ( gen_rtx_REG ( HImode , SOFT_Z_REGNUM ) , stack_pop_word , scratch ) ; emit_move_after_reload ( m68hc11_soft_tmp_reg , stack_pop_word , scratch ) ; } if ( frame_pointer_needed ) emit_move_after_reload ( hard_frame_pointer_rtx , stack_pop_word , scratch ) ; else if ( current_function_trap && return_size != 0 ) { rtx addr_reg = stack_pointer_rtx ; if ( ! TARGET_M6812 ) { emit_move_after_reload ( scratch , stack_pointer_rtx , 0 ) ; addr_reg = scratch ; } emit_move_after_reload ( gen_rtx_MEM ( HImode , gen_rtx_PLUS ( HImode , addr_reg , const1_rtx ) ) , d_reg , 0 ) ; if ( return_size > HARD_REG_SIZE ) emit_move_after_reload ( gen_rtx_MEM ( HImode , gen_rtx_PLUS ( HImode , addr_reg , GEN_INT ( 3 ) ) ) , ix_reg , 0 ) ; } emit_jump_insn ( gen_return ( ) ) ; } </s>


<s> void expand_prologue ( void ) { tree func_attr ; int size ; int regno ; rtx scratch ; gcc_assert ( reload_completed == 1 ) ; size = get_frame_size ( ) ; create_regs_rtx ( ) ; func_attr = TYPE_ATTRIBUTES ( TREE_TYPE ( current_function_decl ) ) ; current_function_interrupt = lookup_attribute ( "interrupt" , func_attr ) != NULL_TREE ; current_function_trap = lookup_attribute ( "trap" , func_attr ) != NULL_TREE ; if ( lookup_attribute ( "far" , func_attr ) != NULL_TREE ) current_function_far = 1 ; else if ( lookup_attribute ( "near" , func_attr ) != NULL_TREE ) current_function_far = 0 ; else current_function_far = ( TARGET_LONG_CALLS != 0 && ! current_function_interrupt && ! current_function_trap ) ; if ( current_function_args_info . nregs == 2 ) scratch = iy_reg ; else scratch = ix_reg ; if ( frame_pointer_needed ) emit_move_after_reload ( stack_push_word , hard_frame_pointer_rtx , scratch ) ; if ( current_function_interrupt ) { emit_move_after_reload ( stack_push_word , m68hc11_soft_tmp_reg , scratch ) ; emit_move_after_reload ( stack_push_word , gen_rtx_REG ( HImode , SOFT_Z_REGNUM ) , scratch ) ; emit_move_after_reload ( stack_push_word , gen_rtx_REG ( HImode , SOFT_SAVED_XY_REGNUM ) , scratch ) ; } if ( TARGET_M6812 && ( size > 4 || size == 3 ) ) { emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - size ) ) ) ; } else if ( ( ! optimize_size && size > 8 ) || ( optimize_size && size > 10 ) ) { rtx insn ; insn = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , gen_rtx_SET ( VOIDmode , stack_pointer_rtx , gen_rtx_PLUS ( HImode , stack_pointer_rtx , GEN_INT ( - size ) ) ) , gen_rtx_CLOBBER ( VOIDmode , scratch ) ) ) ; emit_insn ( insn ) ; } else { int i ; for ( i = 2 ; i <= size ; i += 2 ) emit_move_after_reload ( stack_push_word , ix_reg , 0 ) ; if ( size & 1 ) emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , constm1_rtx ) ) ; } if ( frame_pointer_needed ) emit_move_after_reload ( hard_frame_pointer_rtx , stack_pointer_rtx , scratch ) ; for ( regno = SOFT_REG_FIRST ; regno <= SOFT_REG_LAST ; regno ++ ) { if ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) { emit_move_after_reload ( stack_push_word , gen_rtx_REG ( HImode , regno ) , scratch ) ; } } } </s>


<s> int hard_regno_mode_ok ( int regno , enum machine_mode mode ) { switch ( GET_MODE_SIZE ( mode ) ) { case 8 : return S_REGNO_P ( regno ) && m68hc11_soft_reg_count >= 4 ; case 4 : return ( X_REGNO_P ( regno ) || ( S_REGNO_P ( regno ) && m68hc11_soft_reg_count >= 2 ) ) ; case 2 : return G_REGNO_P ( regno ) ; case 1 : return G_REGNO_P ( regno ) && ! SP_REGNO_P ( regno ) ; default : return 0 ; } } </s>

Value is 1 if hard register REGNO can hold a value of machine-mode MODE .


<s>
static
int
m68hc11_address_cost
(
rtx
addr
)
{
int
cost
=
4
;
switch
(
GET_CODE
(
addr
)
)
{
case
REG
:
if
(
REGNO
(
addr
)
<
FIRST_PSEUDO_REGISTER
)
cost
=
0
;
else
cost
=
1
;
break
;
case
SYMBOL_REF
:
cost
=
8
;
break
;
case
LABEL_REF
:
case
CONST
:
cost
=
0
;
break
;
case
PLUS
:
{
register
rtx
plus0
=
XEXP
(
addr
,
0
)
;
register
rtx
plus1
=
XEXP
(
addr
,
1
)
;
if
(
GET_CODE
(
plus0
)
!=
REG
)
break
;
switch
(
GET_CODE
(
plus1
)
)
{
case
CONST_INT
:
if
(
INTVAL
(
plus1
)
>=
2
*
m68hc11_max_offset
||
INTVAL
(
plus1
)
<
m68hc11_min_offset
)
cost
=
3
;
else
if
(
INTVAL
(
plus1
)
>=
m68hc11_max_offset
)
cost
=
2
;
else
cost
=
1
;
if
(
REGNO
(
plus0
)
<
FIRST_PSEUDO_REGISTER
)
cost
+=
0
;
else
cost
+=
1
;
break
;
case
SYMBOL_REF
:
cost
=
8
;
break
;
case
CONST
:
case
LABEL_REF
:
cost
=
0
;
break
;
default
:
break
;
}
break
;
}
case
PRE_DEC
:
case
PRE_INC
:
if
(
SP_REG_P
(
XEXP
(
addr
,
0
)
)
)
cost
=
1
;
break
;
default
:
break
;
}
if
(
debug_m6811
)
{
printf
(
"Address cost: %d for :"
,
cost
)
;
fflush
(
stdout
)
;
debug_rtx
(
addr
)
;
}
return
cost
;
}
</s>

Provide the costs of an addressing mode that contains ADDR . If ADDR is not a valid address , its cost is irrelevant .


Worker function for TARGET_ASM_CONSTRUCTOR .


<s> static void m68hc11_asm_out_destructor ( rtx symbol , int priority ) { default_dtor_section_asm_out_destructor ( symbol , priority ) ; fprintf ( asm_out_file , "\t.globl\t__do_global_dtors\n" ) ; } </s>

Worker function for TARGET_ASM_DESTRUCTOR .


<s> int m68hc11_auto_inc_p ( rtx x ) { return GET_CODE ( x ) == PRE_DEC || GET_CODE ( x ) == POST_INC || GET_CODE ( x ) == POST_DEC || GET_CODE ( x ) == PRE_INC ; } </s>

Returns true if X is a PRE/POST increment decrement ( same as auto_inc_p ( ) in rtlanal.c but do not take into account the stack ) .


<s>
static
void
m68hc11_encode_section_info
(
tree
decl
,
rtx
rtl
,
int
first
ATTRIBUTE_UNUSED
)
{
tree
func_attr
;
int
trap_handler
;
int
is_far
=
0
;
if
(
TREE_CODE
(
decl
)
==
VAR_DECL
)
{
if
(
lookup_attribute
(
"page0"
,
DECL_ATTRIBUTES
(
decl
)
)
!=
0
)
m68hc11_encode_label
(
decl
)
;
return
;
}
if
(
TREE_CODE
(
decl
)
!=
FUNCTION_DECL
)
return
;
func_attr
=
TYPE_ATTRIBUTES
(
TREE_TYPE
(
decl
)
)
;
if
(
lookup_attribute
(
"far"
,
func_attr
)
!=
NULL_TREE
)
is_far
=
1
;
else
if
(
lookup_attribute
(
"near"
,
func_attr
)
==
NULL_TREE
)
is_far
=
TARGET_LONG_CALLS
!=
0
;
trap_handler
=
lookup_attribute
(
"trap"
,
func_attr
)
!=
NULL_TREE
;
if
(
trap_handler
&&
is_far
)
{
warning
(
OPT_Wattributes
,
"%<trap%> and %<far%> attributes are "
"not compatible, ignoring %<far%>"
)
;
trap_handler
=
0
;
}
if
(
trap_handler
)
{
if
(
trap_handler_symbol
!=
0
)
warning
(
OPT_Wattributes
,
"%<trap%> attribute is already used"
)
;
else
trap_handler_symbol
=
XEXP
(
rtl
,
0
)
;
}
SYMBOL_REF_FLAG
(
XEXP
(
rtl
,
0
)
)
=
is_far
;
}
</s>

We want to recognize trap handlers so that we handle calls to traps in a special manner ( by issuing the trap ) . This information is stored in SYMBOL_REF_FLAG .


<s> static rtx m68hc11_expand_compare ( enum rtx_code code , rtx op0 , rtx op1 ) { rtx ret = 0 ; gcc_assert ( GET_MODE_CLASS ( GET_MODE ( op0 ) ) != MODE_FLOAT ) ; emit_insn ( gen_rtx_SET ( VOIDmode , cc0_rtx , gen_rtx_COMPARE ( VOIDmode , op0 , op1 ) ) ) ; ret = gen_rtx_fmt_ee ( code , VOIDmode , cc0_rtx , const0_rtx ) ; return ret ; } </s>


<s>
static
void
m68hc11_file_start
(
void
)
{
default_file_start
(
)
;
fprintf
(
asm_out_file
,
"\t.mode %s\n"
,
TARGET_SHORT
"mshort"
:
"mlong"
)
;
}
</s>

Worker function for TARGET_ASM_FILE_START .


<s> struct rtx_def * m68hc11_function_arg ( const CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type ATTRIBUTE_UNUSED , int named ATTRIBUTE_UNUSED ) { if ( cum -> words != 0 ) { return NULL_RTX ; } if ( mode != BLKmode ) { if ( GET_MODE_SIZE ( mode ) == 2 * HARD_REG_SIZE ) return gen_rtx_REG ( mode , HARD_X_REGNUM ) ; if ( GET_MODE_SIZE ( mode ) > HARD_REG_SIZE ) { return NULL_RTX ; } return gen_rtx_REG ( mode , HARD_D_REGNUM ) ; } return NULL_RTX ; } </s>

Define where to put the arguments to a function . Value is zero to push the argument on the stack , or a hard register in which to store the argument . MODE is the argument 's machine mode . TYPE is the data type of the argument ( as a tree ) . This is null for libcalls where that information may not be available . CUM is a variable of type CUMULATIVE_ARGS which gives info about the preceding args and about the function being called . NAMED is nonzero if this argument is a named parameter ( otherwise it is an extra parameter matching an ellipsis ) .


<s> void m68hc11_function_arg_advance ( CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type , int named ATTRIBUTE_UNUSED ) { if ( mode != BLKmode ) { if ( cum -> words == 0 && GET_MODE_SIZE ( mode ) == 4 ) { cum -> nregs = 2 ; cum -> words = GET_MODE_SIZE ( mode ) ; } else { cum -> words += GET_MODE_SIZE ( mode ) ; if ( cum -> words <= HARD_REG_SIZE ) cum -> nregs = 1 ; } } else { cum -> words += int_size_in_bytes ( type ) ; } return ; } </s>

Update the data in CUM to advance over an argument of mode MODE and data type TYPE . ( TYPE is null for libcalls where that information may not be available . )


<s> int m68hc11_function_arg_padding ( enum machine_mode mode , tree type ) { if ( type != 0 && AGGREGATE_TYPE_P ( type ) ) return upward ; return DEFAULT_FUNCTION_ARG_PADDING ( mode , type ) ; } </s>

If defined , a C expression which determines whether , and in which direction , to pad out an argument with extra space . The value should be of type ` enum direction ' : either ` upward ' to pad above the argument , ` downward ' to pad below , or ` none ' to inhibit padding . Structures are stored left shifted in their argument slot .


<s> rtx m68hc11_gen_lowpart ( enum machine_mode mode , rtx x ) { if ( GET_CODE ( x ) == MEM && m68hc11_auto_inc_p ( XEXP ( x , 0 ) ) ) { return gen_rtx_MEM ( mode , XEXP ( x , 0 ) ) ; } if ( GET_CODE ( x ) == CONST_DOUBLE ) { long l [ 2 ] ; if ( GET_MODE_CLASS ( GET_MODE ( x ) ) == MODE_FLOAT ) { REAL_VALUE_TYPE r ; if ( GET_MODE ( x ) == SFmode ) { REAL_VALUE_FROM_CONST_DOUBLE ( r , x ) ; REAL_VALUE_TO_TARGET_SINGLE ( r , l [ 0 ] ) ; } else { rtx first , second ; split_double ( x , & first , & second ) ; return second ; } if ( mode == SImode ) return GEN_INT ( l [ 0 ] ) ; return gen_int_mode ( l [ 0 ] , HImode ) ; } else { l [ 0 ] = CONST_DOUBLE_LOW ( x ) ; } switch ( mode ) { case SImode : return GEN_INT ( l [ 0 ] ) ; case HImode : gcc_assert ( GET_MODE ( x ) == SFmode ) ; return gen_int_mode ( l [ 0 ] , HImode ) ; default : gcc_unreachable ( ) ; } } if ( mode == QImode && D_REG_P ( x ) ) return gen_rtx_REG ( mode , HARD_B_REGNUM ) ; if ( GET_CODE ( x ) == SUBREG && SUBREG_BYTE ( x ) != 0 ) { switch ( mode ) { case SImode : return gen_rtx_SUBREG ( mode , SUBREG_REG ( x ) , SUBREG_BYTE ( x ) + 4 ) ; case HImode : return gen_rtx_SUBREG ( mode , SUBREG_REG ( x ) , SUBREG_BYTE ( x ) + 2 ) ; default : gcc_unreachable ( ) ; } } x = gen_lowpart ( mode , x ) ; if ( GET_CODE ( x ) == MEM ) x = copy_rtx ( x ) ; return x ; } </s>

Low and High part extraction for 68HC11 . These routines are similar to gen_lowpart and gen_highpart but they have been fixed to work for constants and 68HC11 specific registers .


<s>
void
m68hc11_gen_rotate
(
enum
rtx_code
code
,
rtx
insn
,
rtx
operands
[
]
)
{
int
val
;
if
(
GET_CODE
(
operands
[
2
]
)
!=
CONST_INT
||
(
!
D_REG_P
(
operands
[
0
]
)
&&
!
DA_REG_P
(
operands
[
0
]
)
)
)
fatal_insn
(
"invalid rotate insn"
,
insn
)
;
val
=
INTVAL
(
operands
[
2
]
)
;
if
(
code
==
ROTATERT
)
val
=
GET_MODE_SIZE
(
GET_MODE
(
operands
[
0
]
)
)
*
BITS_PER_UNIT
val
;
if
(
GET_MODE
(
operands
[
0
]
)
!=
QImode
)
CC_STATUS_INIT
;
if
(
val
>=
5
&&
val
<=
11
)
{
if
(
TARGET_M6812
)
output_asm_insn
(
"exg\ta,b"
,
operands
)
;
else
{
output_asm_insn
(
"psha"
,
operands
)
;
output_asm_insn
(
"tba"
,
operands
)
;
output_asm_insn
(
"pulb"
,
operands
)
;
}
val
-=
8
;
}
else
if
(
val
>=
12
)
{
val
=
val
16
;
}
if
(
val
>
0
)
{
while
(
val
>=
0
)
{
if
(
GET_MODE
(
operands
[
0
]
)
!=
QImode
)
{
output_asm_insn
(
"asra"
,
operands
)
;
output_asm_insn
(
"rola"
,
operands
)
;
}
if
(
D_REG_P
(
operands
[
0
]
)
)
output_asm_insn
(
"rolb"
,
operands
)
;
if
(
GET_MODE
(
operands
[
0
]
)
!=
QImode
||
DA_REG_P
(
operands
[
0
]
)
)
output_asm_insn
(
"rola"
,
operands
)
;
}
}
else
{
while
(
++
val
<=
0
)
{
if
(
GET_MODE
(
operands
[
0
]
)
!=
QImode
)
output_asm_insn
(
"tap"
,
operands
)
;
if
(
D_REG_P
(
operands
[
0
]
)
)
output_asm_insn
(
"rorb"
,
operands
)
;
if
(
GET_MODE
(
operands
[
0
]
)
!=
QImode
||
DA_REG_P
(
operands
[
0
]
)
)
output_asm_insn
(
"rora"
,
operands
)
;
}
}
}
</s>

Generate the code for a ROTATE or ROTATERT on a QI or HI mode . The source and destination must be D or A and the shift must be a constant .


"%qs attribute only applies to functions"

Handle an attribute requiring a FUNCTION_TYPE , FIELD_DECL or TYPE_DECL ; arguments as in struct attribute_spec.handler .


<s>
static
tree
m68hc11_handle_page0_attribute
(
tree
*
node
,
tree
name
,
tree
args
ATTRIBUTE_UNUSED
,
int
flags
ATTRIBUTE_UNUSED
,
bool
*
no_add_attrs
)
{
tree
decl
=
*
node
;
if
(
TREE_STATIC
(
decl
)
||
DECL_EXTERNAL
(
decl
)
)
{
DECL_SECTION_NAME
(
decl
)
=
build_string
(
6
,
".page0"
)
;
}
else
{
warning
(
OPT_Wattributes
,
"%qs attribute ignored"
,
IDENTIFIER_POINTER
(
name
)
)
;
*
no_add_attrs
=
true
;
}
return
NULL_TREE
;
}
</s>

Handle an `` tiny_data '' attribute ; arguments as in struct attribute_spec.handler .


<s> void m68hc11_initialize_trampoline ( rtx tramp , rtx fnaddr , rtx cxt ) { const char * static_chain_reg = reg_names [ STATIC_CHAIN_REGNUM ] ; if ( * static_chain_reg == '*' ) static_chain_reg ++ ; if ( TARGET_M6811 ) { emit_move_insn ( gen_rtx_MEM ( HImode , tramp ) , GEN_INT ( 0x18ce ) ) ; emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , 2 ) ) , cxt ) ; emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , 4 ) ) , GEN_INT ( 0x18df ) ) ; emit_move_insn ( gen_rtx_MEM ( QImode , plus_constant ( tramp , 6 ) ) , gen_rtx_CONST ( QImode , gen_rtx_SYMBOL_REF ( Pmode , static_chain_reg ) ) ) ; emit_move_insn ( gen_rtx_MEM ( QImode , plus_constant ( tramp , 7 ) ) , GEN_INT ( 0x7e ) ) ; emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , 8 ) ) , fnaddr ) ; } else { emit_move_insn ( gen_rtx_MEM ( HImode , tramp ) , GEN_INT ( 0x1803 ) ) ; emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , 2 ) ) , cxt ) ; emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , 4 ) ) , gen_rtx_CONST ( HImode , gen_rtx_SYMBOL_REF ( Pmode , static_chain_reg ) ) ) ; emit_move_insn ( gen_rtx_MEM ( QImode , plus_constant ( tramp , 6 ) ) , GEN_INT ( 0x06 ) ) ; emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , 7 ) ) , fnaddr ) ; } } </s>

Emit the code to build the trampoline used to call a nested function . 68HC11 68HC12 ldy # & CXT movw # & CXT , * _.d1 sty * _.d1 jmp FNADDR jmp FNADDR


<s> int m68hc11_initial_elimination_offset ( int from , int to ) { int trap_handler ; tree func_attr ; int size ; int regno ; func_attr = TYPE_ATTRIBUTES ( TREE_TYPE ( current_function_decl ) ) ; current_function_interrupt = lookup_attribute ( "interrupt" , func_attr ) != NULL_TREE ; trap_handler = lookup_attribute ( "trap" , func_attr ) != NULL_TREE ; if ( lookup_attribute ( "far" , func_attr ) != 0 ) current_function_far = 1 ; else if ( lookup_attribute ( "near" , func_attr ) != 0 ) current_function_far = 0 ; else current_function_far = ( TARGET_LONG_CALLS != 0 && ! current_function_interrupt && ! trap_handler ) ; if ( trap_handler && from == ARG_POINTER_REGNUM ) size = 7 ; else if ( current_function_far && from == ARG_POINTER_REGNUM ) size = 1 ; else size = 0 ; if ( from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM ) { return get_frame_size ( ) + 2 + m68hc11_sp_correction + size ; } if ( from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM ) { return m68hc11_sp_correction ; } for ( regno = SOFT_REG_FIRST ; regno < SOFT_REG_LAST ; regno ++ ) { if ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) { size += 2 ; } } if ( from == ARG_POINTER_REGNUM && to == HARD_SP_REGNUM ) { return get_frame_size ( ) + size ; } if ( from == FRAME_POINTER_REGNUM && to == HARD_SP_REGNUM ) { return size ; } return 0 ; } </s>

Define the offset between two registers , one to be eliminated , and the other its replacement , at the start of a routine .


<s> void m68hc11_init_cumulative_args ( CUMULATIVE_ARGS * cum , tree fntype , rtx libname ) { tree ret_type ; z_replacement_completed = 0 ; cum -> words = 0 ; cum -> nregs = 0 ; if ( fntype == 0 ) { const char * name ; size_t len ; if ( libname == 0 || GET_CODE ( libname ) != SYMBOL_REF ) return ; name = XSTR ( libname , 0 ) ; len = strlen ( name ) ; if ( len > 3 && ( ( name [ len - 2 ] == 'd' && ( name [ len - 1 ] == 'f' || name [ len - 1 ] == 'i' ) ) || ( name [ len - 3 ] == 'd' && ( name [ len - 2 ] == 'i' || name [ len - 2 ] == 'f' ) ) ) ) { cum -> words = 1 ; cum -> nregs = 1 ; } return ; } ret_type = TREE_TYPE ( fntype ) ; if ( ret_type && aggregate_value_p ( ret_type , fntype ) ) { cum -> words = 1 ; cum -> nregs = 1 ; } } </s>

Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE . For a library call , FNTYPE is 0 .


<s> static void m68hc11_init_libfuncs ( void ) { memcpy_libfunc = init_one_libfunc ( "__memcpy" ) ; memcmp_libfunc = init_one_libfunc ( "__memcmp" ) ; memset_libfunc = init_one_libfunc ( "__memset" ) ; } </s>


<s> int m68hc11_memory_move_cost ( enum machine_mode mode , enum reg_class class , int in ATTRIBUTE_UNUSED ) { if ( class <= H_REGS && class > NO_REGS ) { if ( GET_MODE_SIZE ( mode ) <= 2 ) return COSTS_N_INSNS ( 1 ) + ( reload_completed | reload_in_progress ) ; else return COSTS_N_INSNS ( 2 ) + ( reload_completed | reload_in_progress ) ; } </s>


<s> void m68hc11_notice_keep_cc ( rtx reg ) { if ( reg == 0 || cc_prev_status . value1 == 0 || rtx_equal_p ( reg , cc_prev_status . value1 ) || ( cc_prev_status . value2 && reg_mentioned_p ( reg , cc_prev_status . value2 ) ) ) CC_STATUS_INIT ; else cc_status = cc_prev_status ; } </s>

The current instruction does not affect the flags but changes the register 'reg ' . See if the previous flags can be kept for the next instruction to avoid a comparison .


<s> void m68hc11_notice_update_cc ( rtx exp , rtx insn ATTRIBUTE_UNUSED ) { if ( GET_CODE ( exp ) == SET ) { if ( SET_DEST ( exp ) == pc_rtx ) ; else if ( GET_CODE ( SET_SRC ( exp ) ) == CALL ) { CC_STATUS_INIT ; } else if ( SET_DEST ( exp ) == cc0_rtx ) { cc_status . flags = 0 ; cc_status . value1 = XEXP ( exp , 0 ) ; cc_status . value2 = XEXP ( exp , 1 ) ; } else { cc_status . flags = 0 ; cc_status . value1 = XEXP ( exp , 0 ) ; cc_status . value2 = XEXP ( exp , 1 ) ; } } else { CC_STATUS_INIT ; } if ( cc_status . value2 != 0 ) switch ( GET_CODE ( cc_status . value2 ) ) { case IOR : case XOR : case AND : break ; case NOT : if ( GET_MODE ( cc_status . value2 ) != QImode ) CC_STATUS_INIT ; break ; case PLUS : case MINUS : case MULT : case DIV : case UDIV : case MOD : case UMOD : case NEG : if ( GET_MODE ( cc_status . value2 ) != VOIDmode ) cc_status . flags |= CC_NO_OVERFLOW ; break ; case ASHIFT : case ROTATE : case ROTATERT : if ( GET_MODE ( cc_status . value2 ) != VOIDmode ) cc_status . flags |= CC_NO_OVERFLOW ; break ; case MEM : case SYMBOL_REF : case REG : case CONST_INT : cc_status . flags |= CC_NO_OVERFLOW ; break ; default : break ; } if ( cc_status . value1 && GET_CODE ( cc_status . value1 ) == REG && cc_status . value2 && reg_overlap_mentioned_p ( cc_status . value1 , cc_status . value2 ) ) cc_status . value2 = 0 ; else if ( cc_status . value1 && side_effects_p ( cc_status . value1 ) ) cc_status . value1 = 0 ; else if ( cc_status . value2 && side_effects_p ( cc_status . value2 ) ) cc_status . value2 = 0 ; } </s>

Store in cc_status the expressions that the condition codes will describe after execution of an instruction whose pattern is EXP . Do not alter them if the instruction would not alter the cc 's .


<s> void m68hc11_output_swap ( rtx insn ATTRIBUTE_UNUSED , rtx operands [ ] ) { if ( X_REG_P ( operands [ 1 ] ) || X_REG_P ( operands [ 0 ] ) ) { if ( cc_prev_status . value1 != 0 && ( D_REG_P ( cc_prev_status . value1 ) || X_REG_P ( cc_prev_status . value1 ) ) ) { cc_status = cc_prev_status ; if ( D_REG_P ( cc_status . value1 ) ) cc_status . value1 = gen_rtx_REG ( GET_MODE ( cc_status . value1 ) , HARD_X_REGNUM ) ; else cc_status . value1 = gen_rtx_REG ( GET_MODE ( cc_status . value1 ) , HARD_D_REGNUM ) ; } else CC_STATUS_INIT ; output_asm_insn ( "xgdx" , operands ) ; } else { if ( cc_prev_status . value1 != 0 && ( D_REG_P ( cc_prev_status . value1 ) || Y_REG_P ( cc_prev_status . value1 ) ) ) { cc_status = cc_prev_status ; if ( D_REG_P ( cc_status . value1 ) ) cc_status . value1 = gen_rtx_REG ( GET_MODE ( cc_status . value1 ) , HARD_Y_REGNUM ) ; else cc_status . value1 = gen_rtx_REG ( GET_MODE ( cc_status . value1 ) , HARD_D_REGNUM ) ; } else CC_STATUS_INIT ; output_asm_insn ( "xgdy" , operands ) ; } } </s>


<s> int m68hc11_page0_symbol_p ( rtx x ) { switch ( GET_CODE ( x ) ) { case SYMBOL_REF : return XSTR ( x , 0 ) != 0 && XSTR ( x , 0 ) [ 0 ] == '@' ; case CONST : return m68hc11_page0_symbol_p ( XEXP ( x , 0 ) ) ; case PLUS : if ( ! m68hc11_page0_symbol_p ( XEXP ( x , 0 ) ) ) return 0 ; return GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT && INTVAL ( XEXP ( x , 1 ) ) < 256 && INTVAL ( XEXP ( x , 1 ) ) >= 0 ; default : return 0 ; } } </s>


<s>
static
void
m68hc11_reassign_regs
(
rtx
first
)
{
rtx
insn
;
ix_reg
=
gen_rtx_REG
(
HImode
,
HARD_X_REGNUM
)
;
iy_reg
=
gen_rtx_REG
(
HImode
,
HARD_Y_REGNUM
)
;
z_reg
=
gen_rtx_REG
(
HImode
,
HARD_Z_REGNUM
)
;
z_reg_qi
=
gen_rtx_REG
(
QImode
,
HARD_Z_REGNUM
)
;
for
(
insn
=
first
;
insn
;
insn
=
NEXT_INSN
(
insn
)
)
{
rtx
body
;
if
(
GET_CODE
(
insn
)
==
CODE_LABEL
||
GET_CODE
(
insn
)
==
NOTE
||
GET_CODE
(
insn
)
==
BARRIER
)
continue
;
if
(
!
INSN_P
(
insn
)
)
continue
;
body
=
PATTERN
(
insn
)
;
if
(
GET_CODE
(
body
)
==
CLOBBER
||
GET_CODE
(
body
)
==
USE
)
continue
;
if
(
GET_CODE
(
body
)
==
CONST_INT
||
GET_CODE
(
body
)
==
ASM_INPUT
||
GET_CODE
(
body
)
==
ASM_OPERANDS
||
GET_CODE
(
body
)
==
UNSPEC
||
GET_CODE
(
body
)
==
UNSPEC_VOLATILE
)
continue
;
if
(
GET_CODE
(
body
)
==
SET
||
GET_CODE
(
body
)
==
PARALLEL
||
GET_CODE
(
insn
)
==
CALL_INSN
||
GET_CODE
(
insn
)
==
JUMP_INSN
)
{
if
(
reg_mentioned_p
(
z_reg
,
body
)
)
{
m68hc11_z_replacement
(
insn
)
;
}
}
else
{
printf
(
"insn not handled by Z replacement:\n"
)
;
fflush
(
stdout
)
;
debug_rtx
(
insn
)
;
}
}
}
</s>

Scan all the insn and re-affects some registers - The Z register ( if it was used ) , is affected to X or Y depending on the instruction .


<s> int m68hc11_register_move_cost ( enum machine_mode mode , enum reg_class from , enum reg_class to ) { if ( from < to ) { enum reg_class tmp = to ; to = from , from = tmp ; } if ( to >= S_REGS ) return m68hc11_memory_move_cost ( mode , S_REGS , 0 ) ; else if ( from <= S_REGS ) return COSTS_N_INSNS ( 1 ) + ( reload_completed | reload_in_progress ) ; else return COSTS_N_INSNS ( 2 ) ; } </s>

Cost of moving data from a register of class 'from ' to on in class 'to ' . Reload does not check the constraint of set insns when the two registers have a move cost of 2 . Setting a higher cost will force reload to check the constraints .


<s> static void m68hc11_reorg ( void ) { int split_done = 0 ; rtx insn , first ; z_replacement_completed = 0 ; z_reg = gen_rtx_REG ( HImode , HARD_Z_REGNUM ) ; first = get_insns ( ) ; unshare_all_rtl_again ( first ) ; split_all_insns_noflow ( ) ; split_done = 1 ; z_replacement_completed = 1 ; m68hc11_reassign_regs ( first ) ; if ( optimize ) compute_bb_for_insn ( ) ; if ( optimize > 0 && split_done ) { reload_cse_regs ( first ) ; } if ( optimize ) { for ( insn = first ; insn ; insn = NEXT_INSN ( insn ) ) { if ( INSN_P ( insn ) ) { rtx * pnote ; pnote = & REG_NOTES ( insn ) ; while ( * pnote != 0 ) { if ( REG_NOTE_KIND ( * pnote ) == REG_DEAD ) * pnote = XEXP ( * pnote , 1 ) ; else pnote = & XEXP ( * pnote , 1 ) ; } } } life_analysis ( 0 , PROP_REG_INFO | PROP_DEATH_NOTES ) ; } z_replacement_completed = 2 ; if ( optimize > 0 ) split_all_insns_noflow ( ) ; { rtx insn ; for ( insn = first ; insn ; insn = NEXT_INSN ( insn ) ) { rtx body ; if ( INSN_DELETED_P ( insn ) ) continue ; if ( ! INSN_P ( insn ) ) continue ; body = PATTERN ( insn ) ; if ( GET_CODE ( body ) == SET && rtx_equal_p ( SET_SRC ( body ) , SET_DEST ( body ) ) ) { PUT_CODE ( insn , NOTE ) ; NOTE_LINE_NUMBER ( insn ) = NOTE_INSN_DELETED ; NOTE_SOURCE_FILE ( insn ) = 0 ; continue ; } } } } </s>

Machine-dependent reorg pass . Specific optimizations are defined here : - this pass changes the Z register into either X or Y ( it preserves X/Y previous values in a memory slot in page0 ) . When this pass is finished , the global variable 'z_replacement_completed ' is set to 2 .


<s> static bool m68hc11_return_in_memory ( tree type , tree fntype ATTRIBUTE_UNUSED ) { if ( TYPE_MODE ( type ) == BLKmode ) { HOST_WIDE_INT size = int_size_in_bytes ( type ) ; return ( size == - 1 || size > 4 ) ; } else return GET_MODE_SIZE ( TYPE_MODE ( type ) ) > 4 ; } </s>

Return true if type TYPE should be returned in memory . Blocks and data types largers than 4 bytes can not be returned in the register ( D + X = 4 ) .


<s> int m68hc11_small_indexed_indirect_p ( rtx operand , enum machine_mode mode ) { rtx base , offset ; int addr_mode ; if ( GET_CODE ( operand ) == REG && reload_in_progress && REGNO ( operand ) >= FIRST_PSEUDO_REGISTER && reg_equiv_memory_loc [ REGNO ( operand ) ] ) { operand = reg_equiv_memory_loc [ REGNO ( operand ) ] ; operand = eliminate_regs ( operand , 0 , NULL_RTX ) ; } if ( GET_CODE ( operand ) != MEM ) return 0 ; operand = XEXP ( operand , 0 ) ; if ( CONSTANT_ADDRESS_P ( operand ) ) return 1 ; if ( PUSH_POP_ADDRESS_P ( operand ) ) return 1 ; addr_mode = m68hc11_mov_addr_mode | ( reload_completed ? ADDR_STRICT : 0 ) ; if ( ! m68hc11_valid_addressing_p ( operand , mode , addr_mode ) ) return 0 ; if ( TARGET_M6812 && GET_CODE ( operand ) == PLUS && ( reload_completed | reload_in_progress ) ) { base = XEXP ( operand , 0 ) ; offset = XEXP ( operand , 1 ) ; if ( GET_CODE ( base ) != CONST_INT && GET_CODE ( offset ) != CONST_INT ) return 0 ; if ( GET_CODE ( base ) == CONST_INT ) offset = base ; switch ( GET_MODE_SIZE ( mode ) ) { case 8 : if ( INTVAL ( offset ) < - 16 + 6 || INTVAL ( offset ) > 15 - 6 ) return 0 ; break ; case 4 : if ( INTVAL ( offset ) < - 16 + 2 || INTVAL ( offset ) > 15 - 2 ) return 0 ; break ; default : if ( INTVAL ( offset ) < - 16 || INTVAL ( offset ) > 15 ) return 0 ; break ; } } return 1 ; } </s>

Returns 1 if the operand fits in a 68HC11 indirect mode or in a 68HC12 1-byte index addressing mode .


<s> static const char * m68hc11_strip_name_encoding ( const char * str ) { return str + ( * str == '*' || * str == '@' || * str == '&' ) ; } </s>


<s> static rtx m68hc11_struct_value_rtx ( tree fntype ATTRIBUTE_UNUSED , int incoming ATTRIBUTE_UNUSED ) { return gen_rtx_REG ( Pmode , HARD_D_REGNUM ) ; } </s>

Worker function for TARGET_STRUCT_VALUE_RTX .


<s> int m68hc11_valid_addressing_p ( rtx operand , enum machine_mode mode , int addr_mode ) { rtx base , offset ; switch ( GET_CODE ( operand ) ) { case MEM : if ( ( addr_mode & ADDR_INDIRECT ) && GET_MODE_SIZE ( mode ) <= 2 ) return m68hc11_valid_addressing_p ( XEXP ( operand , 0 ) , mode , addr_mode & ( ADDR_STRICT | ADDR_OFFSET ) ) ; return 0 ; case POST_INC : case PRE_INC : case POST_DEC : case PRE_DEC : if ( addr_mode & ADDR_INCDEC ) return m68hc11_valid_addressing_p ( XEXP ( operand , 0 ) , mode , addr_mode & ADDR_STRICT ) ; return 0 ; case PLUS : base = XEXP ( operand , 0 ) ; if ( GET_CODE ( base ) == MEM ) return 0 ; offset = XEXP ( operand , 1 ) ; if ( GET_CODE ( offset ) == MEM ) return 0 ; if ( GET_CODE ( base ) == REG && GET_CODE ( offset ) == REG ) { if ( ! ( addr_mode & ADDR_INDEXED ) ) return 0 ; addr_mode &= ADDR_STRICT ; if ( REGNO_OK_FOR_BASE_P2 ( REGNO ( base ) , addr_mode ) && REGNO_OK_FOR_INDEX_P2 ( REGNO ( offset ) , addr_mode ) ) return 1 ; if ( REGNO_OK_FOR_BASE_P2 ( REGNO ( offset ) , addr_mode ) && REGNO_OK_FOR_INDEX_P2 ( REGNO ( base ) , addr_mode ) ) return 1 ; return 0 ; } if ( ! ( addr_mode & ADDR_OFFSET ) ) return 0 ; if ( GET_CODE ( base ) == REG ) { if ( ! VALID_CONSTANT_OFFSET_P ( offset , mode ) ) return 0 ; if ( ! ( addr_mode & ADDR_STRICT ) ) return 1 ; return REGNO_OK_FOR_BASE_P2 ( REGNO ( base ) , 1 ) ; } if ( GET_CODE ( offset ) == REG ) { if ( ! VALID_CONSTANT_OFFSET_P ( base , mode ) ) return 0 ; if ( ! ( addr_mode & ADDR_STRICT ) ) return 1 ; return REGNO_OK_FOR_BASE_P2 ( REGNO ( offset ) , 1 ) ; } return 0 ; case REG : return REGNO_OK_FOR_BASE_P2 ( REGNO ( operand ) , addr_mode & ADDR_STRICT ) ; case CONST_INT : if ( addr_mode & ADDR_CONST ) return VALID_CONSTANT_OFFSET_P ( operand , mode ) ; return 0 ; default : return 0 ; } } </s>

Return 1 if the operand is a valid indexed addressing mode . For 68hc11 : n , r with n in [ 0 .. 255 ] and r in A_REGS class For 68hc12 : n , r no constraint on the constant , r in A_REGS class .


<s> int memory_reload_operand ( rtx operand , enum machine_mode mode ATTRIBUTE_UNUSED ) { return GET_CODE ( operand ) == MEM && GET_CODE ( XEXP ( operand , 0 ) ) == PLUS && ( ( GET_CODE ( XEXP ( XEXP ( operand , 0 ) , 0 ) ) == REG && GET_CODE ( XEXP ( XEXP ( operand , 0 ) , 1 ) ) == CONST_INT ) || ( GET_CODE ( XEXP ( XEXP ( operand , 0 ) , 1 ) ) == REG && GET_CODE ( XEXP ( XEXP ( operand , 0 ) , 0 ) ) == CONST_INT ) ) ; } </s>


<s> static int must_parenthesize ( rtx op ) { const char * name ; switch ( GET_CODE ( op ) ) { case SYMBOL_REF : name = XSTR ( op , 0 ) ; return ( strcasecmp ( name , "a" ) == 0 || strcasecmp ( name , "b" ) == 0 || strcasecmp ( name , "d" ) == 0 || strcasecmp ( name , "x" ) == 0 || strcasecmp ( name , "y" ) == 0 || strcasecmp ( name , "ix" ) == 0 || strcasecmp ( name , "iy" ) == 0 || strcasecmp ( name , "pc" ) == 0 || strcasecmp ( name , "sp" ) == 0 || strcasecmp ( name , "ccr" ) == 0 ) ? 1 : 0 ; case PLUS : case MINUS : return must_parenthesize ( XEXP ( op , 0 ) ) || must_parenthesize ( XEXP ( op , 1 ) ) ; case MEM : case CONST : case ZERO_EXTEND : case SIGN_EXTEND : return must_parenthesize ( XEXP ( op , 0 ) ) ; case CONST_DOUBLE : case CONST_INT : case LABEL_REF : case CODE_LABEL : default : return 0 ; } } </s>

Returns true if the operand 'op ' must be printed with parenthesis around it . This must be done only if there is a symbol whose name is a processor register .


<s> int next_insn_test_reg ( rtx insn , rtx reg ) { rtx body ; insn = next_nonnote_insn ( insn ) ; if ( GET_CODE ( insn ) != INSN ) return 0 ; body = PATTERN ( insn ) ; if ( sets_cc0_p ( body ) != 1 ) return 0 ; if ( rtx_equal_p ( XEXP ( body , 1 ) , reg ) == 0 ) return 0 ; return 1 ; } </s>

Returns 1 if the next insn after 'insn ' is a test of the register 'reg ' . This is used to decide whether a move that set flags should be used instead .


<s> int symbolic_memory_operand ( rtx op , enum machine_mode mode ) { switch ( GET_CODE ( op ) ) { case SYMBOL_REF : case LABEL_REF : return 1 ; case CONST : op = XEXP ( op , 0 ) ; return ( ( GET_CODE ( XEXP ( op , 0 ) ) == SYMBOL_REF || GET_CODE ( XEXP ( op , 0 ) ) == LABEL_REF ) && GET_CODE ( XEXP ( op , 1 ) ) == CONST_INT ) ; case CONST_DOUBLE : return GET_MODE ( op ) == mode ; case PLUS : return symbolic_memory_operand ( XEXP ( op , 0 ) , mode ) && symbolic_memory_operand ( XEXP ( op , 1 ) , mode ) ; default : return 0 ; } } </s>

Returns 1 if OP is a memory reference involving a symbolic constant that is not in the constant pool .


<s> void create_regs_rtx ( ) { ix_reg = gen_rtx ( REG , HImode , HARD_X_REGNUM ) ; iy_reg = gen_rtx ( REG , HImode , HARD_Y_REGNUM ) ; d_reg = gen_rtx ( REG , HImode , HARD_D_REGNUM ) ; da_reg = gen_rtx ( REG , QImode , HARD_A_REGNUM ) ; m68hc11_soft_tmp_reg = gen_rtx ( REG , HImode , SOFT_TMP_REGNUM ) ; stack_push_word = gen_rtx ( MEM , HImode , gen_rtx ( PRE_DEC , HImode , gen_rtx ( REG , HImode , HARD_SP_REGNUM ) ) ) ; stack_pop_word = gen_rtx ( MEM , HImode , gen_rtx ( POST_INC , HImode , gen_rtx ( REG , HImode , HARD_SP_REGNUM ) ) ) ; } </s>


<s> void expand_epilogue ( ) { int size ; register int regno ; int return_size ; rtx scratch ; if ( reload_completed != 1 ) abort ( ) ; size = get_frame_size ( ) ; if ( current_function_return_rtx == 0 ) return_size = 0 ; else if ( GET_CODE ( current_function_return_rtx ) == MEM ) return_size = HARD_REG_SIZE ; else return_size = GET_MODE_SIZE ( GET_MODE ( current_function_return_rtx ) ) ; if ( return_size > HARD_REG_SIZE ) scratch = iy_reg ; else scratch = ix_reg ; for ( regno = SOFT_REG_LAST ; regno >= SOFT_REG_FIRST ; regno -- ) { if ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) { emit_move_after_reload ( gen_rtx ( REG , HImode , regno ) , stack_pop_word , scratch ) ; } } if ( TARGET_M6812 && ( size > 4 || size == 3 ) ) { emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( size ) ) ) ; } else if ( size > 8 ) { rtx insn ; insn = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , gen_rtx_SET ( VOIDmode , stack_pointer_rtx , gen_rtx_PLUS ( HImode , stack_pointer_rtx , GEN_INT ( size ) ) ) , gen_rtx_CLOBBER ( VOIDmode , scratch ) ) ) ; emit_insn ( insn ) ; } else { int i ; for ( i = 2 ; i <= size ; i += 2 ) emit_move_after_reload ( scratch , stack_pop_word , scratch ) ; if ( size & 1 ) emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( 1 ) ) ) ; } if ( frame_pointer_needed ) emit_move_after_reload ( hard_frame_pointer_rtx , stack_pop_word , scratch ) ; if ( current_function_interrupt ) { emit_move_after_reload ( gen_rtx ( REG , HImode , SOFT_SAVED_XY_REGNUM ) , stack_pop_word , scratch ) ; emit_move_after_reload ( gen_rtx ( REG , HImode , SOFT_Z_REGNUM ) , stack_pop_word , scratch ) ; emit_move_after_reload ( m68hc11_soft_tmp_reg , stack_pop_word , scratch ) ; } else if ( current_function_trap && return_size != 0 ) { rtx addr_reg = stack_pointer_rtx ; if ( ! TARGET_M6812 ) { emit_move_after_reload ( scratch , stack_pointer_rtx , 0 ) ; addr_reg = scratch ; } emit_move_after_reload ( gen_rtx ( MEM , HImode , gen_rtx ( PLUS , HImode , addr_reg , GEN_INT ( 1 ) ) ) , d_reg , 0 ) ; if ( return_size > HARD_REG_SIZE ) emit_move_after_reload ( gen_rtx ( MEM , HImode , gen_rtx ( PLUS , HImode , addr_reg , GEN_INT ( 3 ) ) ) , ix_reg , 0 ) ; } emit_jump_insn ( gen_return ( ) ) ; } </s>


<s> void expand_prologue ( ) { tree func_attr ; int size ; int regno ; rtx scratch ; if ( reload_completed != 1 ) abort ( ) ; size = get_frame_size ( ) ; create_regs_rtx ( ) ; func_attr = TYPE_ATTRIBUTES ( TREE_TYPE ( current_function_decl ) ) ; current_function_interrupt = lookup_attribute ( "interrupt" , func_attr ) != NULL_TREE ; current_function_trap = lookup_attribute ( "trap" , func_attr ) != NULL_TREE ; if ( current_function_args_info . nregs == 2 ) scratch = iy_reg ; else scratch = ix_reg ; if ( current_function_interrupt ) { emit_move_after_reload ( stack_push_word , m68hc11_soft_tmp_reg , scratch ) ; emit_move_after_reload ( stack_push_word , gen_rtx ( REG , HImode , SOFT_Z_REGNUM ) , scratch ) ; emit_move_after_reload ( stack_push_word , gen_rtx ( REG , HImode , SOFT_SAVED_XY_REGNUM ) , scratch ) ; } if ( frame_pointer_needed ) emit_move_after_reload ( stack_push_word , hard_frame_pointer_rtx , scratch ) ; if ( TARGET_M6812 && ( size > 4 || size == 3 ) ) { emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - size ) ) ) ; } else if ( size > 8 ) { rtx insn ; insn = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , gen_rtx_SET ( VOIDmode , stack_pointer_rtx , gen_rtx_PLUS ( HImode , stack_pointer_rtx , GEN_INT ( - size ) ) ) , gen_rtx_CLOBBER ( VOIDmode , scratch ) ) ) ; emit_insn ( insn ) ; } else { int i ; for ( i = 2 ; i <= size ; i += 2 ) emit_move_after_reload ( stack_push_word , ix_reg , 0 ) ; if ( size & 1 ) emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - 1 ) ) ) ; } if ( frame_pointer_needed ) emit_move_after_reload ( hard_frame_pointer_rtx , stack_pointer_rtx , scratch ) ; for ( regno = SOFT_REG_FIRST ; regno <= SOFT_REG_LAST ; regno ++ ) { if ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) { emit_move_after_reload ( stack_push_word , gen_rtx ( REG , HImode , regno ) , scratch ) ; } } } </s>