<s> int compute_a_shift_cc ( rtx insn ATTRIBUTE_UNUSED , rtx * operands ) { rtx shift = operands [ 3 ] ; machine_mode mode = GET_MODE ( shift ) ; enum rtx_code code = GET_CODE ( shift ) ; enum shift_type shift_type ; enum shift_mode shift_mode ; struct shift_info info ; int n ; switch ( mode ) { case E_QImode : shift_mode = QIshift ; break ; case E_HImode : shift_mode = HIshift ; break ; case E_SImode : shift_mode = SIshift ; break ; default : gcc_unreachable ( ) ; } switch ( code ) { case ASHIFTRT : shift_type = SHIFT_ASHIFTRT ; break ; case LSHIFTRT : shift_type = SHIFT_LSHIFTRT ; break ; case ASHIFT : shift_type = SHIFT_ASHIFT ; break ; default : gcc_unreachable ( ) ; } gcc_assert ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) ; n = INTVAL ( operands [ 2 ] ) ; if ( n < 0 ) n = 0 ; else if ( ( unsigned int ) n > GET_MODE_BITSIZE ( mode ) ) n = GET_MODE_BITSIZE ( mode ) ; get_shift_alg ( shift_type , shift_mode , n , & info ) ; switch ( info . alg ) { case SHIFT_SPECIAL : if ( info . remainder == 0 ) return info . cc_special ; case SHIFT_INLINE : return info . cc_inline ; case SHIFT_ROT_AND : return OLD_CC_SET_ZNV ; case SHIFT_LOOP : if ( info . shift2 != NULL ) { if ( n % 2 ) return info . cc_inline ; } return OLD_CC_CLOBBER ; default : gcc_unreachable ( ) ; } } </s>

Compute which flag bits are valid after a shift insn .


<s> unsigned int compute_a_shift_length ( rtx insn ATTRIBUTE_UNUSED , rtx * operands ) { rtx shift = operands [ 3 ] ; machine_mode mode = GET_MODE ( shift ) ; enum rtx_code code = GET_CODE ( shift ) ; enum shift_type shift_type ; enum shift_mode shift_mode ; struct shift_info info ; unsigned int wlength = 0 ; switch ( mode ) { case E_QImode : shift_mode = QIshift ; break ; case E_HImode : shift_mode = HIshift ; break ; case E_SImode : shift_mode = SIshift ; break ; default : gcc_unreachable ( ) ; } switch ( code ) { case ASHIFTRT : shift_type = SHIFT_ASHIFTRT ; break ; case LSHIFTRT : shift_type = SHIFT_LSHIFTRT ; break ; case ASHIFT : shift_type = SHIFT_ASHIFT ; break ; default : gcc_unreachable ( ) ; } if ( GET_CODE ( operands [ 2 ] ) != CONST_INT ) { get_shift_alg ( shift_type , shift_mode , 1 , & info ) ; return ( 4 + h8300_asm_insn_count ( info . shift1 ) ) * 2 ; } else { int n = INTVAL ( operands [ 2 ] ) ; if ( n < 0 ) n = 0 ; else if ( ( unsigned int ) n > GET_MODE_BITSIZE ( mode ) ) n = GET_MODE_BITSIZE ( mode ) ; get_shift_alg ( shift_type , shift_mode , n , & info ) ; switch ( info . alg ) { case SHIFT_SPECIAL : wlength += h8300_asm_insn_count ( info . special ) ; if ( strstr ( info . special , "xor.l" ) != NULL ) wlength ++ ; case SHIFT_INLINE : n = info . remainder ; if ( info . shift2 != NULL ) { wlength += h8300_asm_insn_count ( info . shift2 ) * ( n / 2 ) ; n = n % 2 ; } wlength += h8300_asm_insn_count ( info . shift1 ) * n ; return 2 * wlength ; case SHIFT_ROT_AND : { int m = GET_MODE_BITSIZE ( mode ) - n ; gcc_assert ( info . shift1 ) ; if ( info . shift2 != NULL ) { wlength += h8300_asm_insn_count ( info . shift2 ) * ( m / 2 ) ; m = m % 2 ; } wlength += h8300_asm_insn_count ( info . shift1 ) * m ; switch ( mode ) { case E_QImode : wlength += 1 ; break ; case E_HImode : wlength += 2 ; break ; case E_SImode : wlength += 3 ; break ; default : gcc_unreachable ( ) ; } return 2 * wlength ; } case SHIFT_LOOP : if ( info . shift2 != NULL ) { wlength += 3 + h8300_asm_insn_count ( info . shift2 ) ; if ( n % 2 ) wlength += h8300_asm_insn_count ( info . shift1 ) ; } else { wlength += 3 + h8300_asm_insn_count ( info . shift1 ) ; } return 2 * wlength ; default : gcc_unreachable ( ) ; } } } </s>


<s> int compute_logical_op_cc ( machine_mode mode , rtx * operands ) { enum rtx_code code = GET_CODE ( operands [ 3 ] ) ; const unsigned HOST_WIDE_INT intval = ( unsigned HOST_WIDE_INT ) ( ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) && register_operand ( operands [ 1 ] , VOIDmode ) ? INTVAL ( operands [ 2 ] ) : 0x55555555 ) ; const unsigned HOST_WIDE_INT det = ( code != AND ) ? intval : ~ intval ; const unsigned HOST_WIDE_INT b0 = ( det >> 0 ) & 0xff ; const unsigned HOST_WIDE_INT b1 = ( det >> 8 ) & 0xff ; const unsigned HOST_WIDE_INT w0 = ( det >> 0 ) & 0xffff ; const unsigned HOST_WIDE_INT w1 = ( det >> 16 ) & 0xffff ; int lower_half_easy_p = 0 ; int upper_half_easy_p = 0 ; enum attr_old_cc cc = OLD_CC_CLOBBER ; switch ( mode ) { case E_HImode : if ( b0 != 0 && b1 != 0 ) { cc = OLD_CC_SET_ZNV ; } break ; case E_SImode : lower_half_easy_p = ( b0 == 0 || b1 == 0 || ( code != IOR && w0 == 0xffff ) ) ; upper_half_easy_p = ( ( code != IOR && w1 == 0xffff ) || ( code == AND && w1 == 0xff00 ) ) ; if ( w0 != 0 && w1 != 0 && ! ( lower_half_easy_p && upper_half_easy_p ) && ! ( code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 && lower_half_easy_p ) ) { cc = OLD_CC_SET_ZNV ; } else { if ( code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 ) { cc = OLD_CC_SET_ZNV ; } } break ; default : gcc_unreachable ( ) ; } return cc ; } </s>

Compute which flag bits are valid after a logical insn .


<s> unsigned int compute_logical_op_length ( machine_mode mode , rtx * operands ) { enum rtx_code code = GET_CODE ( operands [ 3 ] ) ; const unsigned HOST_WIDE_INT intval = ( unsigned HOST_WIDE_INT ) ( ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) && register_operand ( operands [ 1 ] , VOIDmode ) ? INTVAL ( operands [ 2 ] ) : 0x55555555 ) ; const unsigned HOST_WIDE_INT det = ( code != AND ) ? intval : ~ intval ; const unsigned HOST_WIDE_INT b0 = ( det >> 0 ) & 0xff ; const unsigned HOST_WIDE_INT b1 = ( det >> 8 ) & 0xff ; const unsigned HOST_WIDE_INT w0 = ( det >> 0 ) & 0xffff ; const unsigned HOST_WIDE_INT w1 = ( det >> 16 ) & 0xffff ; int lower_half_easy_p = 0 ; int upper_half_easy_p = 0 ; unsigned int length = 0 ; switch ( mode ) { case E_HImode : if ( b0 != 0 && b1 != 0 ) { length = h8300_length_from_table ( operands [ 1 ] , operands [ 2 ] , & logicw_length_table ) ; } else { if ( b0 != 0 ) length += 2 ; if ( b1 != 0 ) length += 2 ; } break ; case E_SImode : lower_half_easy_p = ( b0 == 0 || b1 == 0 || ( code != IOR && w0 == 0xffff ) ) ; upper_half_easy_p = ( ( code != IOR && w1 == 0xffff ) || ( code == AND && w1 == 0xff00 ) ) ; if ( w0 != 0 && w1 != 0 && ! ( lower_half_easy_p && upper_half_easy_p ) && ! ( code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 && lower_half_easy_p ) ) { length = h8300_length_from_table ( operands [ 1 ] , operands [ 2 ] , & logicl_length_table ) ; } else { if ( w0 == 0xffff && ( code != IOR ) ) { length += 2 ; } else if ( ( b0 != 0 ) && ( b1 != 0 ) ) { length += 4 ; } else { if ( b0 != 0 ) length += 2 ; if ( b1 != 0 ) length += 2 ; } if ( w1 == 0xffff && ( code != IOR ) ) { length += 2 ; } else if ( code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 ) { length += 2 ; } else if ( code == AND && w1 == 0xff00 ) { length += 2 ; } else { if ( w1 != 0 ) length += 4 ; } } break ; default : gcc_unreachable ( ) ; } return length ; } </s>


<s> static void h8300_emit_stack_adjustment ( int sign , HOST_WIDE_INT size , bool in_prologue ) { if ( size == 0 ) return ; if ( Pmode == HImode ) { rtx_insn * x = emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( sign * size ) ) ) ; if ( size < 4 ) F ( x , 0 ) ; } else F ( emit_insn ( gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( sign * size ) ) ) , 0 ) ; } </s>

Output assembly language to FILE for the operation OP with operand size SIZE to adjust the stack pointer .


<s> void h8300_expand_prologue ( void ) { int regno ; int saved_regs ; int n_regs ; if ( h8300_os_task_function_p ( current_function_decl ) ) return ; if ( h8300_monitor_function_p ( current_function_decl ) ) emit_insn ( gen_monitor_prologue ( ) ) ; if ( frame_pointer_needed ) { push ( HARD_FRAME_POINTER_REGNUM , true ) ; F ( emit_move_insn ( hard_frame_pointer_rtx , stack_pointer_rtx ) , 0 ) ; } saved_regs = compute_saved_regs ( ) ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno += n_regs ) { n_regs = 1 ; if ( saved_regs & ( 1 << regno ) ) { if ( TARGET_H8300S ) { if ( ( TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x0f ) == 0x0f ) n_regs = 4 ; else if ( ( TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x07 ) == 0x07 ) n_regs = 3 ; else if ( ( TARGET_H8300SX || ( regno & 1 ) == 0 ) && ( ( saved_regs >> regno ) & 0x03 ) == 0x03 ) n_regs = 2 ; } h8300_push_pop ( regno , n_regs , false , false ) ; } } h8300_emit_stack_adjustment ( - 1 , round_frame_size ( get_frame_size ( ) ) , true ) ; if ( flag_stack_usage_info ) current_function_static_stack_size = round_frame_size ( get_frame_size ( ) ) + ( __builtin_popcount ( saved_regs ) * UNITS_PER_WORD ) + ( frame_pointer_needed ? UNITS_PER_WORD : 0 ) ; } </s>

Generate RTL code for the function prologue .


"%<-mexr%> is used without %<-ms%> or %<-msx%>"

"%<-mno-exr%> is valid only with %<-ms%> or "

"%<-mn%> is not supported for linux targets"

Initialize various cpu specific globals at start up .


<s> static int h8300_register_move_cost ( machine_mode mode ATTRIBUTE_UNUSED , reg_class_t from , reg_class_t to ) { if ( from == MAC_REGS || to == MAC_REGS ) return 6 ; else return 3 ; } </s>

Implements TARGET_REGISTER_MOVE_COST . Any SI register-to-register move may need to be reloaded , so inmplement h8300_register_move_cost to return > 2 so that reload never shortcuts .


<s> int h8300_shift_needs_scratch_p ( int count , machine_mode mode , enum rtx_code type ) { enum h8_cpu cpu ; int a , lr , ar ; if ( GET_MODE_BITSIZE ( mode ) <= count ) return 1 ; if ( TARGET_H8300S ) cpu = H8_S ; else cpu = H8_300H ; switch ( mode ) { case E_QImode : a = shift_alg_qi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_qi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_qi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case E_HImode : a = shift_alg_hi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_hi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_hi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case E_SImode : a = shift_alg_si [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_si [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_si [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; default : gcc_unreachable ( ) ; } if ( type == CLOBBER ) return ( a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; else if ( type == ASHIFT ) return ( a == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; else if ( type == LSHIFTRT ) return ( lr == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; else if ( type == ASHIFTRT ) return ( ar == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; } </s>

Given COUNT and MODE of a shift , return 1 if a scratch reg may be needed for some shift with COUNT and MODE . Return 0 otherwise .


<s> bool pre_incdec_with_reg ( rtx op , unsigned int reg ) { if ( GET_CODE ( op ) != MEM ) return false ; op = XEXP ( op , 0 ) ; if ( GET_CODE ( op ) != PRE_DEC && GET_CODE ( op ) != PRE_INC ) return false ; op = XEXP ( op , 0 ) ; if ( ! REG_P ( op ) ) return false ; return REGNO ( op ) == reg ; } </s>

Return TRUE if OP is a PRE_INC or PRE_DEC instruction using REG , FALSE otherwise .


<s> static rtx push ( int rn , bool in_prologue ) { rtx reg = gen_rtx_REG ( word_mode , rn ) ; rtx x ; if ( ! TARGET_NORMAL_MODE ) x = gen_push_h8300hs_advanced ( reg ) ; else x = gen_push_h8300hs_normal ( reg ) ; x = F ( emit_insn ( x ) , 0 ) ; add_reg_note ( x , REG_INC , stack_pointer_rtx ) ; return x ; } </s>

Output RTL to push register RN onto the stack .


<s> static unsigned int compute_saved_regs ( ) { unsigned int saved_regs = 0 ; int regno ; for ( regno = 0 ; regno <= 6 ; regno ++ ) { if ( WORD_REG_USED ( regno ) ) saved_regs |= 1 << regno ; } if ( frame_pointer_needed ) saved_regs &= ~ ( 1 << FRAME_POINTER_REGNUM ) ; return saved_regs ; } </s>

Compute which registers to push/pop . Return a bit vector of registers .


<s>
void
h8300_init_once
(
)
{
static
const
char
*
const
h8_push_ops
[
2
]
=
{
"push"
,
"push.l"
}
;
static
const
char
*
const
h8_pop_ops
[
2
]
=
{
"pop"
,
"pop.l"
}
;
static
const
char
*
const
h8_mov_ops
[
2
]
=
{
"mov.w"
,
"mov.l"
}
;
if
(
TARGET_H8300
)
{
cpu_type
=
(
int
)
CPU_H8300
;
h8_reg_names
=
names_big
;
}
else
{
cpu_type
=
(
int
)
CPU_H8300H
;
h8_reg_names
=
names_extended
;
}
h8_push_op
=
h8_push_ops
[
cpu_type
]
;
h8_pop_op
=
h8_pop_ops
[
cpu_type
]
;
h8_mov_op
=
h8_mov_ops
[
cpu_type
]
;
if
(
!
TARGET_H8300S
&&
TARGET_MAC
)
{
error
(
"-ms2600 is used without -ms"
)
;
target_flags
|=
1
;
}
}
</s>


<s> unsigned int compute_a_rotate_length ( rtx * operands ) { rtx src = operands [ 1 ] ; rtx amount_rtx = operands [ 2 ] ; enum machine_mode mode = GET_MODE ( src ) ; int amount ; unsigned int length = 0 ; gcc_assert ( GET_CODE ( amount_rtx ) == CONST_INT ) ; amount = INTVAL ( amount_rtx ) ; if ( amount < 0 ) amount = 0 ; if ( ( unsigned int ) amount > GET_MODE_BITSIZE ( mode ) ) amount = GET_MODE_BITSIZE ( mode ) ; if ( ( unsigned int ) amount > GET_MODE_BITSIZE ( mode ) / ( unsigned ) 2 ) amount = GET_MODE_BITSIZE ( mode ) - amount ; if ( ( mode == HImode && TARGET_H8300 && amount >= 5 ) || ( mode == HImode && TARGET_H8300H && amount >= 6 ) || ( mode == HImode && TARGET_H8300S && amount == 8 ) || ( mode == SImode && TARGET_H8300H && amount >= 10 ) || ( mode == SImode && TARGET_H8300S && amount >= 13 ) ) { amount = GET_MODE_BITSIZE ( mode ) / 2 - amount ; length += 6 ; } if ( TARGET_H8300S ) amount = amount / 2 + amount % 2 ; length += amount * ( ( TARGET_H8300 && mode == HImode ) ? 6 : 2 ) ; return length ; } </s>


<s> int compute_a_shift_cc ( rtx insn ATTRIBUTE_UNUSED , rtx * operands ) { rtx shift = operands [ 3 ] ; enum machine_mode mode = GET_MODE ( shift ) ; enum rtx_code code = GET_CODE ( shift ) ; enum shift_type shift_type ; enum shift_mode shift_mode ; struct shift_info info ; int n ; switch ( mode ) { case QImode : shift_mode = QIshift ; break ; case HImode : shift_mode = HIshift ; break ; case SImode : shift_mode = SIshift ; break ; default : gcc_unreachable ( ) ; } switch ( code ) { case ASHIFTRT : shift_type = SHIFT_ASHIFTRT ; break ; case LSHIFTRT : shift_type = SHIFT_LSHIFTRT ; break ; case ASHIFT : shift_type = SHIFT_ASHIFT ; break ; default : gcc_unreachable ( ) ; } gcc_assert ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) ; n = INTVAL ( operands [ 2 ] ) ; if ( n < 0 ) n = 0 ; else if ( ( unsigned int ) n > GET_MODE_BITSIZE ( mode ) ) n = GET_MODE_BITSIZE ( mode ) ; get_shift_alg ( shift_type , shift_mode , n , & info ) ; switch ( info . alg ) { case SHIFT_SPECIAL : if ( info . remainder == 0 ) return info . cc_special ; case SHIFT_INLINE : return info . cc_inline ; case SHIFT_ROT_AND : return CC_SET_ZNV ; case SHIFT_LOOP : if ( info . shift2 != NULL ) { if ( n % 2 ) return info . cc_inline ; } return CC_CLOBBER ; default : gcc_unreachable ( ) ; } } </s>


<s> unsigned int compute_a_shift_length ( rtx insn ATTRIBUTE_UNUSED , rtx * operands ) { rtx shift = operands [ 3 ] ; enum machine_mode mode = GET_MODE ( shift ) ; enum rtx_code code = GET_CODE ( shift ) ; enum shift_type shift_type ; enum shift_mode shift_mode ; struct shift_info info ; unsigned int wlength = 0 ; switch ( mode ) { case QImode : shift_mode = QIshift ; break ; case HImode : shift_mode = HIshift ; break ; case SImode : shift_mode = SIshift ; break ; default : gcc_unreachable ( ) ; } switch ( code ) { case ASHIFTRT : shift_type = SHIFT_ASHIFTRT ; break ; case LSHIFTRT : shift_type = SHIFT_LSHIFTRT ; break ; case ASHIFT : shift_type = SHIFT_ASHIFT ; break ; default : gcc_unreachable ( ) ; } if ( GET_CODE ( operands [ 2 ] ) != CONST_INT ) { get_shift_alg ( shift_type , shift_mode , 1 , & info ) ; return ( 4 + h8300_asm_insn_count ( info . shift1 ) ) * 2 ; } else { int n = INTVAL ( operands [ 2 ] ) ; if ( n < 0 ) n = 0 ; else if ( ( unsigned int ) n > GET_MODE_BITSIZE ( mode ) ) n = GET_MODE_BITSIZE ( mode ) ; get_shift_alg ( shift_type , shift_mode , n , & info ) ; switch ( info . alg ) { case SHIFT_SPECIAL : wlength += h8300_asm_insn_count ( info . special ) ; if ( strstr ( info . special , "xor.l" ) != NULL ) wlength ++ ; case SHIFT_INLINE : n = info . remainder ; if ( info . shift2 != NULL ) { wlength += h8300_asm_insn_count ( info . shift2 ) * ( n / 2 ) ; n = n % 2 ; } wlength += h8300_asm_insn_count ( info . shift1 ) * n ; return 2 * wlength ; case SHIFT_ROT_AND : { int m = GET_MODE_BITSIZE ( mode ) - n ; gcc_assert ( info . shift1 ) ; if ( info . shift2 != NULL ) { wlength += h8300_asm_insn_count ( info . shift2 ) * ( m / 2 ) ; m = m % 2 ; } wlength += h8300_asm_insn_count ( info . shift1 ) * m ; switch ( mode ) { case QImode : wlength += 1 ; break ; case HImode : wlength += 2 ; break ; case SImode : gcc_assert ( ! TARGET_H8300 ) ; wlength += 3 ; break ; default : gcc_unreachable ( ) ; } return 2 * wlength ; } case SHIFT_LOOP : if ( info . shift2 != NULL ) { wlength += 3 + h8300_asm_insn_count ( info . shift2 ) ; if ( n % 2 ) wlength += h8300_asm_insn_count ( info . shift1 ) ; } else { wlength += 3 + h8300_asm_insn_count ( info . shift1 ) ; } return 2 * wlength ; default : gcc_unreachable ( ) ; } } } </s>


<s> int compute_logical_op_cc ( enum machine_mode mode , rtx * operands ) { enum rtx_code code = GET_CODE ( operands [ 3 ] ) ; const unsigned HOST_WIDE_INT intval = ( unsigned HOST_WIDE_INT ) ( ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) && register_operand ( operands [ 1 ] , VOIDmode ) ? INTVAL ( operands [ 2 ] ) : 0x55555555 ) ; const unsigned HOST_WIDE_INT det = ( code != AND ) ? intval : ~ intval ; const unsigned HOST_WIDE_INT b0 = ( det >> 0 ) & 0xff ; const unsigned HOST_WIDE_INT b1 = ( det >> 8 ) & 0xff ; const unsigned HOST_WIDE_INT w0 = ( det >> 0 ) & 0xffff ; const unsigned HOST_WIDE_INT w1 = ( det >> 16 ) & 0xffff ; int lower_half_easy_p = 0 ; int upper_half_easy_p = 0 ; enum attr_cc cc = CC_CLOBBER ; switch ( mode ) { case HImode : if ( ( TARGET_H8300H || TARGET_H8300S ) && b0 != 0 && b1 != 0 ) { cc = CC_SET_ZNV ; } break ; case SImode : if ( TARGET_H8300H || TARGET_H8300S ) { lower_half_easy_p = ( b0 == 0 || b1 == 0 || ( code != IOR && w0 == 0xffff ) ) ; upper_half_easy_p = ( ( code != IOR && w1 == 0xffff ) || ( code == AND && w1 == 0xff00 ) ) ; } if ( ( TARGET_H8300H || TARGET_H8300S ) && w0 != 0 && w1 != 0 && ! ( lower_half_easy_p && upper_half_easy_p ) && ! ( code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 && lower_half_easy_p ) ) { cc = CC_SET_ZNV ; } else { if ( ( TARGET_H8300H || TARGET_H8300S ) && code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 ) { cc = CC_SET_ZNV ; } } break ; default : gcc_unreachable ( ) ; } return cc ; } </s>


<s> int compute_plussi_cc ( rtx * operands ) { enum machine_mode mode = GET_MODE ( operands [ 0 ] ) ; gcc_assert ( mode == SImode ) ; if ( TARGET_H8300 ) { return CC_CLOBBER ; } else { if ( GET_CODE ( operands [ 2 ] ) == CONST_INT && register_operand ( operands [ 1 ] , VOIDmode ) ) { HOST_WIDE_INT intval = INTVAL ( operands [ 2 ] ) ; if ( TARGET_H8300SX && ( intval >= 1 && intval <= 7 ) ) return CC_SET_ZN ; if ( TARGET_H8300SX && ( intval >= - 7 && intval <= - 1 ) ) return CC_SET_ZN ; switch ( ( unsigned int ) intval & 0xffffffff ) { case 0x00000001 : case 0x00000002 : case 0x00000004 : return CC_NONE_0HIT ; case 0xffffffff : case 0xfffffffe : case 0xfffffffc : return CC_NONE_0HIT ; case 0x00010000 : case 0x00020000 : return CC_CLOBBER ; case 0xffff0000 : case 0xfffe0000 : return CC_CLOBBER ; } if ( ( intval & 0xffff ) == 0 ) return CC_CLOBBER ; } return CC_SET_ZN ; } } </s>

Compute which flag bits are valid after an addition insn .


<s> unsigned int compute_plussi_length ( rtx * operands ) { enum machine_mode mode = GET_MODE ( operands [ 0 ] ) ; gcc_assert ( mode == SImode ) ; if ( TARGET_H8300 ) { if ( GET_CODE ( operands [ 2 ] ) == REG ) return 6 ; if ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) { HOST_WIDE_INT n = INTVAL ( operands [ 2 ] ) ; if ( ( n & 0xffffff ) == 0 ) return 2 ; if ( ( n & 0xffff ) == 0 ) return 4 ; if ( ( n & 0xff ) == 0 ) return 6 ; } return 8 ; } else { if ( GET_CODE ( operands [ 2 ] ) == CONST_INT && register_operand ( operands [ 1 ] , VOIDmode ) ) { HOST_WIDE_INT intval = INTVAL ( operands [ 2 ] ) ; if ( TARGET_H8300SX && ( intval >= 1 && intval <= 7 ) ) return 2 ; if ( TARGET_H8300SX && ( intval >= - 7 && intval <= - 1 ) ) return 2 ; switch ( ( unsigned int ) intval & 0xffffffff ) { case 0x00000001 : case 0x00000002 : case 0x00000004 : return 2 ; case 0xffffffff : case 0xfffffffe : case 0xfffffffc : return 2 ; case 0x00010000 : case 0x00020000 : return 2 ; case 0xffff0000 : case 0xfffe0000 : return 2 ; } if ( ( intval & 0xffff ) == 0 ) return 4 ; } if ( GET_CODE ( operands [ 2 ] ) == CONST_INT && INTVAL ( operands [ 2 ] ) < 0 ) return h8300_length_from_table ( operands [ 0 ] , GEN_INT ( - INTVAL ( operands [ 2 ] ) ) , & addl_length_table ) ; else return h8300_length_from_table ( operands [ 0 ] , operands [ 2 ] , & addl_length_table ) ; return 6 ; } } </s>

Compute the length of an addition insn .


<s> int expand_a_rotate ( rtx operands [ ] ) { rtx dst = operands [ 0 ] ; rtx src = operands [ 1 ] ; rtx rotate_amount = operands [ 2 ] ; enum machine_mode mode = GET_MODE ( dst ) ; if ( h8sx_classify_shift ( mode , ROTATE , rotate_amount ) == H8SX_SHIFT_UNARY ) return false ; emit_move_insn ( dst , src ) ; if ( GET_CODE ( rotate_amount ) != CONST_INT ) { rtx counter = gen_reg_rtx ( QImode ) ; rtx start_label = gen_label_rtx ( ) ; rtx end_label = gen_label_rtx ( ) ; emit_cmp_and_jump_insns ( rotate_amount , const0_rtx , LE , NULL_RTX , QImode , 0 , end_label ) ; emit_move_insn ( counter , rotate_amount ) ; emit_label ( start_label ) ; switch ( mode ) { case QImode : emit_insn ( gen_rotlqi3_1 ( dst , dst , const1_rtx ) ) ; break ; case HImode : emit_insn ( gen_rotlhi3_1 ( dst , dst , const1_rtx ) ) ; break ; case SImode : emit_insn ( gen_rotlsi3_1 ( dst , dst , const1_rtx ) ) ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen_addqi3 ( counter , counter , constm1_rtx ) ) ; emit_cmp_and_jump_insns ( counter , const0_rtx , NE , NULL_RTX , QImode , 1 , start_label ) ; emit_label ( end_label ) ; } else { switch ( mode ) { case QImode : emit_insn ( gen_rotlqi3_1 ( dst , dst , rotate_amount ) ) ; break ; case HImode : emit_insn ( gen_rotlhi3_1 ( dst , dst , rotate_amount ) ) ; break ; case SImode : emit_insn ( gen_rotlsi3_1 ( dst , dst , rotate_amount ) ) ; break ; default : gcc_unreachable ( ) ; } } return 1 ; } </s>

A rotation by a non-constant will cause a loop to be generated , in which a rotation by one bit is used . A rotation by a constant , including the one in the loop , will be taken care of by emit_a_rotate ( ) at the insn emit time .


<s> bool expand_a_shift ( enum machine_mode mode , int code , rtx operands [ ] ) { switch ( h8sx_classify_shift ( mode , code , operands [ 2 ] ) ) { case H8SX_SHIFT_BINARY : operands [ 1 ] = force_reg ( mode , operands [ 1 ] ) ; return false ; case H8SX_SHIFT_UNARY : return false ; case H8SX_SHIFT_NONE : break ; } emit_move_insn ( operands [ 0 ] , operands [ 1 ] ) ; emit_insn ( gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , gen_rtx_SET ( VOIDmode , operands [ 0 ] , gen_rtx_fmt_ee ( code , mode , operands [ 0 ] , operands [ 2 ] ) ) , gen_rtx_CLOBBER ( VOIDmode , gen_rtx_SCRATCH ( QImode ) ) ) ) ) ; return true ; } </s>

Called from the .md file to emit code to do shifts . Returns a boolean indicating success ( currently this is always TRUE ) .


<s>
void
final_prescan_insn
(
rtx
insn
,
rtx
*
operand
ATTRIBUTE_UNUSED
,
int
num_operands
ATTRIBUTE_UNUSED
)
{
static
int
last_insn_address
=
0
;
const
int
uid
=
INSN_UID
(
insn
)
;
if
(
TARGET_ADDRESSES
)
{
fprintf
(
asm_out_file
,
"; 0x%x %d\n"
,
INSN_ADDRESSES
(
uid
)
,
INSN_ADDRESSES
(
uid
)
last_insn_address
)
;
last_insn_address
=
INSN_ADDRESSES
(
uid
)
;
}
}
</s>

If defined , a C statement to be executed just prior to the output of assembler code for INSN , to modify the extracted operands so they will be output differently . Here the argument OPVEC is the vector containing the operands extracted from INSN , and NOPERANDS is the number of elements of the vector which contain meaningful data for this insn . The contents of this vector are what will be used to convert the insn template into assembler code , so you can change the assembler output by changing the contents of the vector . We use it to check if the current insn needs a nop in front of it because of load delays , and also to update the delay slot statistics .


<s> int fix_bit_operand ( rtx * operands , enum rtx_code code ) { if ( code == AND ? single_zero_operand ( operands [ 2 ] , QImode ) : single_one_operand ( operands [ 2 ] , QImode ) ) { if ( GET_CODE ( operands [ 0 ] ) == MEM && ! OK_FOR_U ( operands [ 0 ] ) ) { rtx mem = gen_rtx_MEM ( GET_MODE ( operands [ 0 ] ) , copy_to_mode_reg ( Pmode , XEXP ( operands [ 0 ] , 0 ) ) ) ; MEM_COPY_ATTRIBUTES ( mem , operands [ 0 ] ) ; operands [ 0 ] = mem ; } if ( GET_CODE ( operands [ 1 ] ) == MEM && ! OK_FOR_U ( operands [ 1 ] ) ) { rtx mem = gen_rtx_MEM ( GET_MODE ( operands [ 1 ] ) , copy_to_mode_reg ( Pmode , XEXP ( operands [ 1 ] , 0 ) ) ) ; MEM_COPY_ATTRIBUTES ( mem , operands [ 0 ] ) ; operands [ 1 ] = mem ; } return 0 ; } operands [ 1 ] = force_reg ( QImode , operands [ 1 ] ) ; { rtx res = gen_reg_rtx ( QImode ) ; switch ( code ) { case AND : emit_insn ( gen_andqi3_1 ( res , operands [ 1 ] , operands [ 2 ] ) ) ; break ; case IOR : emit_insn ( gen_iorqi3_1 ( res , operands [ 1 ] , operands [ 2 ] ) ) ; break ; case XOR : emit_insn ( gen_xorqi3_1 ( res , operands [ 1 ] , operands [ 2 ] ) ) ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen_movqi ( operands [ 0 ] , res ) ) ; } return 1 ; } </s>

Fix the operands of a gen_xxx so that it could become a bit operating insn .


<s> rtx function_arg ( CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type , int named ) { static const char * const hand_list [ ] = { "__main" , "__cmpsi2" , "__divhi3" , "__modhi3" , "__udivhi3" , "__umodhi3" , "__divsi3" , "__modsi3" , "__udivsi3" , "__umodsi3" , "__mulhi3" , "__mulsi3" , "__reg_memcpy" , "__reg_memset" , "__ucmpsi2" , 0 , } ; rtx result = NULL_RTX ; const char * fname ; int regpass = 0 ; if ( ! named ) return NULL_RTX ; if ( TARGET_QUICKCALL ) regpass = 3 ; if ( cum -> libcall ) { const char * const * p ; fname = XSTR ( cum -> libcall , 0 ) ; for ( p = hand_list ; * p && strcmp ( * p , fname ) != 0 ; p ++ ) ; if ( * p ) regpass = 4 ; } if ( regpass ) { int size ; if ( mode == BLKmode ) size = int_size_in_bytes ( type ) ; else size = GET_MODE_SIZE ( mode ) ; if ( size + cum -> nbytes <= regpass * UNITS_PER_WORD && cum -> nbytes / UNITS_PER_WORD <= 3 ) result = gen_rtx_REG ( mode , cum -> nbytes / UNITS_PER_WORD ) ; } return result ; } </s>

Return an RTL expression containing the register for the given mode , or 0 if the argument is to be passed on the stack . INCOMING_P is nonzero if this is an incoming argument to the current function .


<s> static unsigned int h8300_asm_insn_count ( const char * template ) { unsigned int count = 1 ; for ( ; * template ; template ++ ) if ( * template == '\n' ) count ++ ; return count ; } </s>

Count the number of assembly instructions in a string TEMPLATE .


<s> static unsigned int h8300_classify_operand ( rtx op , int size , enum h8300_operand_class * class ) { enum h8300_operand_class dummy ; if ( class == 0 ) class = & dummy ; if ( CONSTANT_P ( op ) ) { * class = H8OP_IMMEDIATE ; if ( size == 1 ) return 0 ; if ( TARGET_H8300SX && size == 4 && GET_CODE ( op ) == CONST_INT && IN_RANGE ( INTVAL ( op ) , 0 , 0xffff ) ) return 2 ; return size ; } else if ( GET_CODE ( op ) == MEM ) { op = XEXP ( op , 0 ) ; if ( CONSTANT_P ( op ) ) { * class = H8OP_MEM_ABSOLUTE ; return h8300_constant_length ( op ) ; } else if ( GET_CODE ( op ) == PLUS && CONSTANT_P ( XEXP ( op , 1 ) ) ) { * class = H8OP_MEM_COMPLEX ; return h8300_displacement_length ( op , size ) ; } else if ( GET_RTX_CLASS ( GET_CODE ( op ) ) == RTX_AUTOINC ) { * class = H8OP_MEM_COMPLEX ; return 0 ; } else if ( register_operand ( op , VOIDmode ) ) { * class = H8OP_MEM_BASE ; return 0 ; } } gcc_assert ( register_operand ( op , VOIDmode ) ) ; * class = H8OP_REGISTER ; return 0 ; } </s>

Store the class of operand OP in * CLASS and return the length of any extra operand fields . SIZE is the number of bytes in OP . CLASS can be null if only the length is needed .


Return nonzero if the current function is an interrupt function .


<s> int h8300_eightbit_constant_address_p ( rtx x ) { const unsigned HOST_WIDE_INT n1 = trunc_int_for_mode ( 0xff00 , HImode ) ; const unsigned HOST_WIDE_INT n2 = trunc_int_for_mode ( 0xffff , HImode ) ; const unsigned HOST_WIDE_INT h1 = trunc_int_for_mode ( 0x00ffff00 , SImode ) ; const unsigned HOST_WIDE_INT h2 = trunc_int_for_mode ( 0x00ffffff , SImode ) ; const unsigned HOST_WIDE_INT s1 = trunc_int_for_mode ( 0xffffff00 , SImode ) ; const unsigned HOST_WIDE_INT s2 = trunc_int_for_mode ( 0xffffffff , SImode ) ; unsigned HOST_WIDE_INT addr ; if ( GET_CODE ( x ) == SYMBOL_REF ) return ( SYMBOL_REF_FLAGS ( x ) & SYMBOL_FLAG_EIGHTBIT_DATA ) != 0 ; if ( GET_CODE ( x ) != CONST_INT ) return 0 ; addr = INTVAL ( x ) ; return ( 0 || ( ( TARGET_H8300 || TARGET_NORMAL_MODE ) && IN_RANGE ( addr , n1 , n2 ) ) || ( TARGET_H8300H && IN_RANGE ( addr , h1 , h2 ) ) || ( TARGET_H8300S && IN_RANGE ( addr , s1 , s2 ) ) ) ; } </s>

Nonzero if X is a constant address suitable as an 8-bit absolute , which is a special case of the ' R ' operand .


<s> void h8300_expand_branch ( enum rtx_code code , rtx label ) { rtx tmp ; tmp = gen_rtx_fmt_ee ( code , VOIDmode , cc0_rtx , const0_rtx ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , tmp , gen_rtx_LABEL_REF ( VOIDmode , label ) , pc_rtx ) ; emit_jump_insn ( gen_rtx_SET ( VOIDmode , pc_rtx , tmp ) ) ; } </s>


<s> void h8300_expand_epilogue ( void ) { int regno ; int saved_regs ; int n_regs ; HOST_WIDE_INT frame_size ; bool returned_p ; if ( h8300_os_task_function_p ( current_function_decl ) ) return ; frame_size = round_frame_size ( get_frame_size ( ) ) ; returned_p = false ; h8300_emit_stack_adjustment ( 1 , frame_size ) ; saved_regs = compute_saved_regs ( ) ; for ( regno = FIRST_PSEUDO_REGISTER - 1 ; regno >= 0 ; regno -= n_regs ) { n_regs = 1 ; if ( saved_regs & ( 1 << regno ) ) { if ( TARGET_H8300S ) { if ( ( TARGET_H8300SX || ( regno & 3 ) == 3 ) && ( ( saved_regs << 3 >> regno ) & 0x0f ) == 0x0f ) n_regs = 4 ; else if ( ( TARGET_H8300SX || ( regno & 3 ) == 2 ) && ( ( saved_regs << 2 >> regno ) & 0x07 ) == 0x07 ) n_regs = 3 ; else if ( ( TARGET_H8300SX || ( regno & 1 ) == 1 ) && ( ( saved_regs << 1 >> regno ) & 0x03 ) == 0x03 ) n_regs = 2 ; } if ( TARGET_H8300SX && ! frame_pointer_needed && frame_size == 0 && ( saved_regs & ( ( 1 << ( regno - n_regs + 1 ) ) - 1 ) ) == 0 ) returned_p = true ; h8300_push_pop ( regno - n_regs + 1 , n_regs , 1 , returned_p ) ; } } if ( frame_pointer_needed ) { if ( TARGET_H8300SX ) returned_p = true ; h8300_push_pop ( HARD_FRAME_POINTER_REGNUM , 1 , 1 , returned_p ) ; } if ( ! returned_p ) emit_insn ( gen_rtx_RETURN ( VOIDmode ) ) ; } </s>

Generate RTL code for the function epilogue .


<s> void h8300_expand_prologue ( void ) { int regno ; int saved_regs ; int n_regs ; if ( h8300_os_task_function_p ( current_function_decl ) ) return ; if ( h8300_monitor_function_p ( current_function_decl ) ) emit_insn ( gen_monitor_prologue ( ) ) ; if ( frame_pointer_needed ) { push ( HARD_FRAME_POINTER_REGNUM ) ; emit_move_insn ( hard_frame_pointer_rtx , stack_pointer_rtx ) ; } saved_regs = compute_saved_regs ( ) ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno += n_regs ) { n_regs = 1 ; if ( saved_regs & ( 1 << regno ) ) { if ( TARGET_H8300S ) { if ( ( ! TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x0f ) == 0x0f ) n_regs = 4 ; else if ( ( ! TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x07 ) == 0x07 ) n_regs = 3 ; else if ( ( ! TARGET_H8300SX || ( regno & 1 ) == 0 ) && ( ( saved_regs >> regno ) & 0x03 ) == 0x03 ) n_regs = 2 ; } h8300_push_pop ( regno , n_regs , 0 , 0 ) ; } } h8300_emit_stack_adjustment ( - 1 , round_frame_size ( get_frame_size ( ) ) ) ; } </s>

Generate RTL code for the function prologue .


<s> static void h8300_file_start ( void ) { default_file_start ( ) ; if ( TARGET_H8300H ) fputs ( TARGET_NORMAL_MODE ? "\t.h8300hn\n" : "\t.h8300h\n" , asm_out_file ) ; else if ( TARGET_H8300SX ) fputs ( TARGET_NORMAL_MODE ? "\t.h8300sxn\n" : "\t.h8300sx\n" , asm_out_file ) ; else if ( TARGET_H8300S ) fputs ( TARGET_NORMAL_MODE ? "\t.h8300sn\n" : "\t.h8300s\n" , asm_out_file ) ; } </s>

Output assembly code for the start of the file .


<s> rtx h8300_get_index ( rtx x , enum machine_mode mode , int * size ) { int dummy , factor ; if ( size == 0 ) size = & dummy ; factor = ( mode == VOIDmode ? 0 : GET_MODE_SIZE ( mode ) ) ; if ( TARGET_H8300SX && factor <= 4 && ( mode == VOIDmode || GET_MODE_CLASS ( mode ) == MODE_INT || GET_MODE_CLASS ( mode ) == MODE_FLOAT ) ) { if ( factor <= 1 && GET_CODE ( x ) == ZERO_EXTEND ) { * size = GET_MODE_SIZE ( GET_MODE ( XEXP ( x , 0 ) ) ) ; return XEXP ( x , 0 ) ; } else { rtx index ; if ( GET_CODE ( x ) == AND && GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT && ( factor == 0 || INTVAL ( XEXP ( x , 1 ) ) == 0xff * factor || INTVAL ( XEXP ( x , 1 ) ) == 0xffff * factor ) ) { index = XEXP ( x , 0 ) ; * size = ( INTVAL ( XEXP ( x , 1 ) ) >= 0xffff ? 2 : 1 ) ; } else { index = x ; * size = 4 ; } if ( GET_CODE ( index ) == MULT && GET_CODE ( XEXP ( index , 1 ) ) == CONST_INT && ( factor == 0 || factor == INTVAL ( XEXP ( index , 1 ) ) ) ) return XEXP ( index , 0 ) ; } } * size = 0 ; return x ; } </s>

Given that X occurs in an address of the form ( plus X constant ) , return the part of X that is expected to be a register . There are four kinds of addressing mode to recognize : @ ( dd , Rn ) @ ( dd , RnL.b ) @ ( dd , Rn.w ) @ ( dd , ERn.l ) If SIZE is nonnull , and the address is one of the last three forms , set * SIZE to the index multiplication factor . Set it to 0 for plain @ ( dd , Rn ) addresses . MODE is the mode of the value being accessed . It can be VOIDmode if the address is known to be valid , but its mode is unknown .


<s>
static
tree
h8300_handle_eightbit_data_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
(
7
,
".eight"
)
;
}
else
{
warning
(
OPT_Wattributes
,
"%qs attribute ignored"
,
IDENTIFIER_POINTER
(
name
)
)
;
*
no_add_attrs
=
true
;
}
return
NULL_TREE
;
}
</s>

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


"%qs attribute only applies to functions"

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


<s>
static
tree
h8300_handle_tiny_data_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
,
".tiny"
)
;
}
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> int h8300_hard_regno_mode_ok ( int regno , enum machine_mode mode ) { if ( TARGET_H8300 ) return ( ( regno & 1 ) == 0 ) || ( mode == HImode ) || ( mode == QImode ) ; else return regno == MAC_REG ? mode == SImode : 1 ; } </s>

Worker function for HARD_REGNO_MODE_OK .


<s> int h8300_hard_regno_nregs ( int regno ATTRIBUTE_UNUSED , enum machine_mode mode ) { return ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ; } </s>

Worker function for HARD_REGNO_NREGS . We pretend the MAC register is 32bits -- we do n't have any data types on the H8 series to handle more than 32bits .


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


<s>
void
h8300_init_once
(
void
)
{
static
const
char
*
const
h8_push_ops
[
2
]
=
{
"push"
,
"push.l"
}
;
static
const
char
*
const
h8_pop_ops
[
2
]
=
{
"pop"
,
"pop.l"
}
;
static
const
char
*
const
h8_mov_ops
[
2
]
=
{
"mov.w"
,
"mov.l"
}
;
if
(
TARGET_H8300
)
{
cpu_type
=
(
int
)
CPU_H8300
;
h8_reg_names
=
names_big
;
}
else
{
cpu_type
=
(
int
)
CPU_H8300H
;
h8_reg_names
=
names_extended
;
}
h8_push_op
=
h8_push_ops
[
cpu_type
]
;
h8_pop_op
=
h8_pop_ops
[
cpu_type
]
;
h8_mov_op
=
h8_mov_ops
[
cpu_type
]
;
if
(
!
TARGET_H8300S
&&
TARGET_MAC
)
{
error
(
"-ms2600 is used without -ms"
)
;
target_flags
|=
MASK_H8300S_1
;
}
if
(
TARGET_H8300
&&
TARGET_NORMAL_MODE
)
{
error
(
"-mn is used without -mh or -ms"
)
;
target_flags
^=
MASK_NORMAL_MODE
;
}
if
(
optimize_size
)
{
shift_alg_hi
[
H8_300
]
[
SHIFT_ASHIFT
]
[
5
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300
]
[
SHIFT_ASHIFT
]
[
6
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300
]
[
SHIFT_ASHIFT
]
[
13
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300
]
[
SHIFT_ASHIFT
]
[
14
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300
]
[
SHIFT_LSHIFTRT
]
[
13
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300
]
[
SHIFT_LSHIFTRT
]
[
14
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300
]
[
SHIFT_ASHIFTRT
]
[
13
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300
]
[
SHIFT_ASHIFTRT
]
[
14
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300H
]
[
SHIFT_ASHIFT
]
[
5
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300H
]
[
SHIFT_ASHIFT
]
[
6
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300H
]
[
SHIFT_LSHIFTRT
]
[
5
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300H
]
[
SHIFT_LSHIFTRT
]
[
6
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300H
]
[
SHIFT_ASHIFTRT
]
[
5
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300H
]
[
SHIFT_ASHIFTRT
]
[
6
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300H
]
[
SHIFT_ASHIFTRT
]
[
13
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_300H
]
[
SHIFT_ASHIFTRT
]
[
14
]
=
SHIFT_LOOP
;
shift_alg_hi
[
H8_S
]
[
SHIFT_ASHIFTRT
]
[
14
]
=
SHIFT_LOOP
;
}
if
(
!
TARGET_H8300SX
)
{
h8300_move_ratio
=
3
;
}
else
if
(
flag_omit_frame_pointer
)
{
h8300_move_ratio
=
4
;
}
else
if
(
optimize_size
)
{
h8300_move_ratio
=
4
;
}
else
{
h8300_move_ratio
=
6
;
}
}
</s>

Initialize various cpu specific globals at start up .


<s> int h8300_legitimate_address_p ( enum machine_mode mode , rtx x , int strict ) { if ( h8300_rtx_ok_for_base_p ( x , strict ) ) return 1 ; if ( CONSTANT_ADDRESS_P ( x ) ) return 1 ; if ( TARGET_H8300SX && ( GET_CODE ( x ) == PRE_INC || GET_CODE ( x ) == PRE_DEC || GET_CODE ( x ) == POST_INC || GET_CODE ( x ) == POST_DEC ) && h8300_rtx_ok_for_base_p ( XEXP ( x , 0 ) , strict ) ) return 1 ; if ( GET_CODE ( x ) == PLUS && CONSTANT_ADDRESS_P ( XEXP ( x , 1 ) ) && h8300_rtx_ok_for_base_p ( h8300_get_index ( XEXP ( x , 0 ) , mode , 0 ) , strict ) ) return 1 ; return 0 ; } </s>

Return nozero if X is a legitimate address . On the H8/300 , a legitimate address has the form REG , REG+CONSTANT_ADDRESS or CONSTANT_ADDRESS .


<s> int h8300_legitimate_constant_p ( rtx x ATTRIBUTE_UNUSED ) { return 1 ; } </s>

Return nonzero if X is a legitimate constant .


<s> static void h8300_push_pop ( int regno , int nregs , int pop_p , int return_p ) { int i , j ; rtvec vec ; rtx sp , offset ; if ( ! return_p && nregs == 1 ) { if ( pop_p ) pop ( regno ) ; else push ( regno ) ; return ; } vec = rtvec_alloc ( ( return_p != 0 ) + nregs + 1 ) ; sp = stack_pointer_rtx ; i = 0 ; if ( return_p ) { RTVEC_ELT ( vec , i ) = gen_rtx_RETURN ( VOIDmode ) ; i ++ ; } for ( j = 0 ; j < nregs ; j ++ ) { rtx lhs , rhs ; if ( pop_p ) { lhs = gen_rtx_REG ( SImode , regno + j ) ; rhs = gen_rtx_MEM ( SImode , plus_constant ( sp , ( nregs - j - 1 ) * 4 ) ) ; } else { lhs = gen_rtx_MEM ( SImode , plus_constant ( sp , ( j + 1 ) * - 4 ) ) ; rhs = gen_rtx_REG ( SImode , regno + j ) ; } RTVEC_ELT ( vec , i + j ) = gen_rtx_SET ( VOIDmode , lhs , rhs ) ; } offset = GEN_INT ( ( pop_p ? nregs : - nregs ) * 4 ) ; RTVEC_ELT ( vec , i + j ) = gen_rtx_SET ( VOIDmode , sp , gen_rtx_PLUS ( Pmode , sp , offset ) ) ; emit_insn ( gen_rtx_PARALLEL ( VOIDmode , vec ) ) ; } </s>

Emit an instruction to push or pop NREGS consecutive registers starting at register REGNO . POP_P selects a pop rather than a push and RETURN_P is true if the instruction should return . It must be possible to do the requested operation in a single instruction . If NREGS == 1 & & ! RETURN_P , use a normal push or pop insn . Otherwise emit a parallel of the form : ( parallel [ ( return ) ; ; if RETURN_P ( save or restore REGNO ) ( save or restore REGNO + 1 ) ... ( save or restore REGNO + NREGS - 1 ) ( set sp ( plus sp ( const_int adjust ) ) ) ]


<s> rtx h8300_return_addr_rtx ( int count , rtx frame ) { rtx ret ; if ( count == 0 ) ret = gen_rtx_MEM ( Pmode , gen_rtx_REG ( Pmode , RETURN_ADDRESS_POINTER_REGNUM ) ) ; else if ( flag_omit_frame_pointer ) return ( rtx ) 0 ; else ret = gen_rtx_MEM ( Pmode , memory_address ( Pmode , plus_constant ( frame , UNITS_PER_WORD ) ) ) ; set_mem_alias_set ( ret , get_frame_alias_set ( ) ) ; return ret ; } </s>


<s> static bool h8300_return_in_memory ( tree type , tree fntype ATTRIBUTE_UNUSED ) { return ( TYPE_MODE ( type ) == BLKmode || GET_MODE_SIZE ( TYPE_MODE ( type ) ) > ( TARGET_H8300 ? 4 : 8 ) ) ; } </s>

Worker function for TARGET_RETURN_IN_MEMORY .


<s> int h8300_shift_needs_scratch_p ( int count , enum machine_mode mode ) { enum h8_cpu cpu ; int a , lr , ar ; if ( GET_MODE_BITSIZE ( mode ) <= count ) return 1 ; if ( TARGET_H8300 ) cpu = H8_300 ; else if ( TARGET_H8300H ) cpu = H8_300H ; else cpu = H8_S ; switch ( mode ) { case QImode : a = shift_alg_qi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_qi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_qi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case HImode : a = shift_alg_hi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_hi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_hi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case SImode : a = shift_alg_si [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_si [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_si [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; default : gcc_unreachable ( ) ; } return ( a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; } </s>

Given COUNT and MODE of a shift , return 1 if a scratch reg may be needed for some shift with COUNT and MODE . Return 0 otherwise .


<s> void h8300_swap_into_er6 ( rtx addr ) { push ( HARD_FRAME_POINTER_REGNUM ) ; emit_move_insn ( hard_frame_pointer_rtx , addr ) ; if ( REGNO ( addr ) == SP_REG ) emit_move_insn ( hard_frame_pointer_rtx , plus_constant ( hard_frame_pointer_rtx , GET_MODE_SIZE ( word_mode ) ) ) ; } </s>

Move ADDR into er6 after pushing its old value onto the stack .


<s> void h8300_swap_out_of_er6 ( rtx addr ) { if ( REGNO ( addr ) != SP_REG ) emit_move_insn ( addr , hard_frame_pointer_rtx ) ; pop ( HARD_FRAME_POINTER_REGNUM ) ; } </s>

Move the current value of er6 into ADDR and pop its old value from the stack .


<s> unsigned int h8300_unary_length ( rtx op ) { enum h8300_operand_class class ; unsigned int size , operand_length ; size = GET_MODE_SIZE ( GET_MODE ( op ) ) ; operand_length = h8300_classify_operand ( op , size , & class ) ; switch ( class ) { case H8OP_REGISTER : return 2 ; case H8OP_MEM_BASE : return ( size == 4 ? 6 : 4 ) ; case H8OP_MEM_ABSOLUTE : return operand_length + ( size == 4 ? 6 : 4 ) ; case H8OP_MEM_COMPLEX : return operand_length + 6 ; default : gcc_unreachable ( ) ; } } static unsigned int h8300_short_immediate_length ( rtx op ) { enum h8300_operand_class class ; unsigned int size , operand_length ; size = GET_MODE_SIZE ( GET_MODE ( op ) ) ; operand_length = h8300_classify_operand ( op , size , & class ) ; switch ( class ) { case H8OP_REGISTER : return 2 ; case H8OP_MEM_BASE : case H8OP_MEM_ABSOLUTE : case H8OP_MEM_COMPLEX : return 4 + operand_length ; default : gcc_unreachable ( ) ; } } </s>

Return the length of a unary instruction such as neg or not given that its operand is OP .


<s> enum h8sx_shift_type h8sx_classify_shift ( enum machine_mode mode , enum rtx_code code , rtx op ) { if ( ! TARGET_H8300SX ) return H8SX_SHIFT_NONE ; switch ( code ) { case ASHIFT : case LSHIFTRT : if ( GET_CODE ( op ) != CONST_INT ) return H8SX_SHIFT_BINARY ; if ( INTVAL ( op ) <= 0 || INTVAL ( op ) >= GET_MODE_BITSIZE ( mode ) ) return H8SX_SHIFT_NONE ; if ( exact_log2 ( INTVAL ( op ) ) >= 0 ) return H8SX_SHIFT_UNARY ; return H8SX_SHIFT_BINARY ; case ASHIFTRT : if ( op == const1_rtx || op == const2_rtx ) return H8SX_SHIFT_UNARY ; return H8SX_SHIFT_NONE ; case ROTATE : if ( GET_CODE ( op ) == CONST_INT && ( INTVAL ( op ) == 1 || INTVAL ( op ) == 2 || INTVAL ( op ) == GET_MODE_BITSIZE ( mode ) - 2 || INTVAL ( op ) == GET_MODE_BITSIZE ( mode ) - 1 ) ) return H8SX_SHIFT_UNARY ; return H8SX_SHIFT_NONE ; default : return H8SX_SHIFT_NONE ; } } </s>

Classify a shift with the given mode and code . OP is the shift amount .


<s> void notice_update_cc ( rtx body , rtx insn ) { rtx set ; switch ( get_attr_cc ( insn ) ) { case CC_NONE : break ; case CC_NONE_0HIT : if ( cc_status . value1 != 0 && reg_overlap_mentioned_p ( recog_data . operand [ 0 ] , cc_status . value1 ) ) cc_status . value1 = 0 ; if ( cc_status . value2 != 0 && reg_overlap_mentioned_p ( recog_data . operand [ 0 ] , cc_status . value2 ) ) cc_status . value2 = 0 ; break ; case CC_SET_ZN : CC_STATUS_INIT ; cc_status . flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY ; set = single_set ( insn ) ; cc_status . value1 = SET_SRC ( set ) ; if ( SET_DEST ( set ) != cc0_rtx ) cc_status . value2 = SET_DEST ( set ) ; break ; case CC_SET_ZNV : CC_STATUS_INIT ; cc_status . flags |= CC_NO_CARRY ; set = single_set ( insn ) ; cc_status . value1 = SET_SRC ( set ) ; if ( SET_DEST ( set ) != cc0_rtx ) { if ( GET_CODE ( SET_DEST ( set ) ) == STRICT_LOW_PART ) cc_status . value2 = XEXP ( SET_DEST ( set ) , 0 ) ; else cc_status . value2 = SET_DEST ( set ) ; } break ; case CC_COMPARE : CC_STATUS_INIT ; cc_status . value1 = SET_SRC ( body ) ; break ; case CC_CLOBBER : CC_STATUS_INIT ; break ; } } </s>

On the 68000 , all the insns to store in an address register fail to set the cc 's . However , in some cases these instructions can make it possibly invalid to use the saved cc 's . In those cases we clear out some or all of the saved cc 's so they wo n't be used .


<s> static void pop ( int rn ) { rtx reg = gen_rtx_REG ( word_mode , rn ) ; rtx x ; if ( TARGET_H8300 ) x = gen_pop_h8300 ( reg ) ; else if ( ! TARGET_NORMAL_MODE ) x = gen_pop_h8300hs_advanced ( reg ) ; else x = gen_pop_h8300hs_normal ( reg ) ; x = emit_insn ( x ) ; REG_NOTES ( x ) = gen_rtx_EXPR_LIST ( REG_INC , stack_pointer_rtx , 0 ) ; } </s>

Output RTL to pop register RN from the stack .


<s> void print_operand_address ( FILE * file , rtx addr ) { rtx index ; int size ; switch ( GET_CODE ( addr ) ) { case REG : fprintf ( file , "%s" , h8_reg_names [ REGNO ( addr ) ] ) ; break ; case PRE_DEC : fprintf ( file , "-%s" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case POST_INC : fprintf ( file , "%s+" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case PRE_INC : fprintf ( file , "+%s" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case POST_DEC : fprintf ( file , "%s-" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case PLUS : fprintf ( file , "(" ) ; index = h8300_get_index ( XEXP ( addr , 0 ) , VOIDmode , & size ) ; if ( GET_CODE ( index ) == REG ) { print_operand_address ( file , XEXP ( addr , 1 ) ) ; fprintf ( file , "," ) ; switch ( size ) { case 0 : print_operand_address ( file , index ) ; break ; case 1 : print_operand ( file , index , 'X' ) ; fputs ( ".b" , file ) ; break ; case 2 : print_operand ( file , index , 'T' ) ; fputs ( ".w" , file ) ; break ; case 4 : print_operand ( file , index , 'S' ) ; fputs ( ".l" , file ) ; break ; } } else { print_operand_address ( file , XEXP ( addr , 0 ) ) ; fprintf ( file , "+" ) ; print_operand_address ( file , XEXP ( addr , 1 ) ) ; } fprintf ( file , ")" ) ; break ; case CONST_INT : { int n = INTVAL ( addr ) ; if ( TARGET_H8300 ) n = ( int ) ( short ) n ; fprintf ( file , "%d" , n ) ; break ; } default : output_addr_const ( file , addr ) ; break ; } } </s>

Print the operand address represented by the rtx addr


<s> static void push ( int rn ) { rtx reg = gen_rtx_REG ( word_mode , rn ) ; rtx x ; if ( TARGET_H8300 ) x = gen_push_h8300 ( reg ) ; else if ( ! TARGET_NORMAL_MODE ) x = gen_push_h8300hs_advanced ( reg ) ; else x = gen_push_h8300hs_normal ( reg ) ; x = emit_insn ( x ) ; REG_NOTES ( x ) = gen_rtx_EXPR_LIST ( REG_INC , stack_pointer_rtx , 0 ) ; } </s>

Output RTL to push register RN onto the stack .


<s> static int round_frame_size ( int size ) { return ( ( size + STACK_BOUNDARY / BITS_PER_UNIT - 1 ) & - STACK_BOUNDARY / BITS_PER_UNIT ) ; } </s>


<s> int same_cmp_following_p ( rtx i1 ) { rtx i2 , i3 ; i2 = next_nonnote_insn ( i1 ) ; if ( i2 == NULL_RTX ) return 0 ; i3 = next_nonnote_insn ( i2 ) ; if ( i3 == NULL_RTX ) return 0 ; return ( INSN_P ( i3 ) && rtx_equal_p ( PATTERN ( i1 ) , PATTERN ( i3 ) ) && any_condjump_p ( i2 ) && onlyjump_p ( i2 ) ) ; } </s>

Return nonzero if we have the same comparison insn as I1 two insns after I1 . I1 is assumed to be a comparison insn .


<s> int same_cmp_preceding_p ( rtx i3 ) { rtx i1 , i2 ; i2 = prev_nonnote_insn ( i3 ) ; if ( i2 == NULL_RTX ) return 0 ; i1 = prev_nonnote_insn ( i2 ) ; if ( i1 == NULL_RTX ) return 0 ; return ( INSN_P ( i1 ) && rtx_equal_p ( PATTERN ( i1 ) , PATTERN ( i3 ) ) && any_condjump_p ( i2 ) && onlyjump_p ( i2 ) ) ; } </s>

Return nonzero if we have the same comparison insn as I3 two insns before I3 . I3 is assumed to be a comparison insn .


<s> void split_adds_subs ( enum machine_mode mode , rtx * operands ) { HOST_WIDE_INT val = INTVAL ( operands [ 1 ] ) ; rtx reg = operands [ 0 ] ; HOST_WIDE_INT sign = 1 ; HOST_WIDE_INT amount ; rtx ( * gen_add ) ( rtx , rtx , rtx ) ; if ( val < 0 ) { val = - val ; sign = - 1 ; } switch ( mode ) { case HImode : gen_add = gen_addhi3 ; break ; case SImode : gen_add = gen_addsi3 ; break ; default : gcc_unreachable ( ) ; } for ( amount = ( TARGET_H8300H || TARGET_H8300S ) ? 4 : 2 ; amount > 0 ; amount /= 2 ) { for ( ; val >= amount ; val -= amount ) emit_insn ( gen_add ( reg , reg , GEN_INT ( sign * amount ) ) ) ; } return ; } </s>

Split an add of a small constant into two adds/subs insns .


<s> enum attr_cc compute_a_shift_cc ( rtx insn ATTRIBUTE_UNUSED , rtx * operands ) { rtx shift = operands [ 3 ] ; machine_mode mode = GET_MODE ( shift ) ; enum rtx_code code = GET_CODE ( shift ) ; enum shift_type shift_type ; enum shift_mode shift_mode ; struct shift_info info ; int n ; switch ( mode ) { case QImode : shift_mode = QIshift ; break ; case HImode : shift_mode = HIshift ; break ; case SImode : shift_mode = SIshift ; break ; default : gcc_unreachable ( ) ; } switch ( code ) { case ASHIFTRT : shift_type = SHIFT_ASHIFTRT ; break ; case LSHIFTRT : shift_type = SHIFT_LSHIFTRT ; break ; case ASHIFT : shift_type = SHIFT_ASHIFT ; break ; default : gcc_unreachable ( ) ; } gcc_assert ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) ; n = INTVAL ( operands [ 2 ] ) ; if ( n < 0 ) n = 0 ; else if ( ( unsigned int ) n > GET_MODE_BITSIZE ( mode ) ) n = GET_MODE_BITSIZE ( mode ) ; get_shift_alg ( shift_type , shift_mode , n , & info ) ; switch ( info . alg ) { case SHIFT_SPECIAL : if ( info . remainder == 0 ) return info . cc_special ; case SHIFT_INLINE : return info . cc_inline ; case SHIFT_ROT_AND : return CC_SET_ZNV ; case SHIFT_LOOP : if ( info . shift2 != NULL ) { if ( n % 2 ) return info . cc_inline ; } return CC_CLOBBER ; default : gcc_unreachable ( ) ; } } </s>

Compute which flag bits are valid after a shift insn .


<s> unsigned int compute_a_shift_length ( rtx insn ATTRIBUTE_UNUSED , rtx * operands ) { rtx shift = operands [ 3 ] ; machine_mode mode = GET_MODE ( shift ) ; enum rtx_code code = GET_CODE ( shift ) ; enum shift_type shift_type ; enum shift_mode shift_mode ; struct shift_info info ; unsigned int wlength = 0 ; switch ( mode ) { case QImode : shift_mode = QIshift ; break ; case HImode : shift_mode = HIshift ; break ; case SImode : shift_mode = SIshift ; break ; default : gcc_unreachable ( ) ; } switch ( code ) { case ASHIFTRT : shift_type = SHIFT_ASHIFTRT ; break ; case LSHIFTRT : shift_type = SHIFT_LSHIFTRT ; break ; case ASHIFT : shift_type = SHIFT_ASHIFT ; break ; default : gcc_unreachable ( ) ; } if ( GET_CODE ( operands [ 2 ] ) != CONST_INT ) { get_shift_alg ( shift_type , shift_mode , 1 , & info ) ; return ( 4 + h8300_asm_insn_count ( info . shift1 ) ) * 2 ; } else { int n = INTVAL ( operands [ 2 ] ) ; if ( n < 0 ) n = 0 ; else if ( ( unsigned int ) n > GET_MODE_BITSIZE ( mode ) ) n = GET_MODE_BITSIZE ( mode ) ; get_shift_alg ( shift_type , shift_mode , n , & info ) ; switch ( info . alg ) { case SHIFT_SPECIAL : wlength += h8300_asm_insn_count ( info . special ) ; if ( strstr ( info . special , "xor.l" ) != NULL ) wlength ++ ; case SHIFT_INLINE : n = info . remainder ; if ( info . shift2 != NULL ) { wlength += h8300_asm_insn_count ( info . shift2 ) * ( n / 2 ) ; n = n % 2 ; } wlength += h8300_asm_insn_count ( info . shift1 ) * n ; return 2 * wlength ; case SHIFT_ROT_AND : { int m = GET_MODE_BITSIZE ( mode ) - n ; gcc_assert ( info . shift1 ) ; if ( info . shift2 != NULL ) { wlength += h8300_asm_insn_count ( info . shift2 ) * ( m / 2 ) ; m = m % 2 ; } wlength += h8300_asm_insn_count ( info . shift1 ) * m ; switch ( mode ) { case QImode : wlength += 1 ; break ; case HImode : wlength += 2 ; break ; case SImode : gcc_assert ( ! TARGET_H8300 ) ; wlength += 3 ; break ; default : gcc_unreachable ( ) ; } return 2 * wlength ; } case SHIFT_LOOP : if ( info . shift2 != NULL ) { wlength += 3 + h8300_asm_insn_count ( info . shift2 ) ; if ( n % 2 ) wlength += h8300_asm_insn_count ( info . shift1 ) ; } else { wlength += 3 + h8300_asm_insn_count ( info . shift1 ) ; } return 2 * wlength ; default : gcc_unreachable ( ) ; } } } </s>


<s> enum attr_cc compute_logical_op_cc ( machine_mode mode , rtx * operands ) { enum rtx_code code = GET_CODE ( operands [ 3 ] ) ; const unsigned HOST_WIDE_INT intval = ( unsigned HOST_WIDE_INT ) ( ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) && register_operand ( operands [ 1 ] , VOIDmode ) ? INTVAL ( operands [ 2 ] ) : 0x55555555 ) ; const unsigned HOST_WIDE_INT det = ( code != AND ) ? intval : ~ intval ; const unsigned HOST_WIDE_INT b0 = ( det >> 0 ) & 0xff ; const unsigned HOST_WIDE_INT b1 = ( det >> 8 ) & 0xff ; const unsigned HOST_WIDE_INT w0 = ( det >> 0 ) & 0xffff ; const unsigned HOST_WIDE_INT w1 = ( det >> 16 ) & 0xffff ; int lower_half_easy_p = 0 ; int upper_half_easy_p = 0 ; enum attr_cc cc = CC_CLOBBER ; switch ( mode ) { case HImode : if ( ( TARGET_H8300H || TARGET_H8300S ) && b0 != 0 && b1 != 0 ) { cc = CC_SET_ZNV ; } break ; case SImode : if ( TARGET_H8300H || TARGET_H8300S ) { lower_half_easy_p = ( b0 == 0 || b1 == 0 || ( code != IOR && w0 == 0xffff ) ) ; upper_half_easy_p = ( ( code != IOR && w1 == 0xffff ) || ( code == AND && w1 == 0xff00 ) ) ; } if ( ( TARGET_H8300H || TARGET_H8300S ) && w0 != 0 && w1 != 0 && ! ( lower_half_easy_p && upper_half_easy_p ) && ! ( code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 && lower_half_easy_p ) ) { cc = CC_SET_ZNV ; } else { if ( ( TARGET_H8300H || TARGET_H8300S ) && code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 ) { cc = CC_SET_ZNV ; } } break ; default : gcc_unreachable ( ) ; } return cc ; } </s>

Compute which flag bits are valid after a logical insn .


<s> int expand_a_rotate ( rtx operands [ ] ) { rtx dst = operands [ 0 ] ; rtx src = operands [ 1 ] ; rtx rotate_amount = operands [ 2 ] ; machine_mode mode = GET_MODE ( dst ) ; if ( h8sx_classify_shift ( mode , ROTATE , rotate_amount ) == H8SX_SHIFT_UNARY ) return false ; emit_move_insn ( dst , src ) ; if ( GET_CODE ( rotate_amount ) != CONST_INT ) { rtx counter = gen_reg_rtx ( QImode ) ; rtx_code_label * start_label = gen_label_rtx ( ) ; rtx_code_label * end_label = gen_label_rtx ( ) ; emit_cmp_and_jump_insns ( rotate_amount , const0_rtx , LE , NULL_RTX , QImode , 0 , end_label ) ; emit_move_insn ( counter , rotate_amount ) ; emit_label ( start_label ) ; switch ( mode ) { case QImode : emit_insn ( gen_rotlqi3_1 ( dst , dst , const1_rtx ) ) ; break ; case HImode : emit_insn ( gen_rotlhi3_1 ( dst , dst , const1_rtx ) ) ; break ; case SImode : emit_insn ( gen_rotlsi3_1 ( dst , dst , const1_rtx ) ) ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen_addqi3 ( counter , counter , constm1_rtx ) ) ; emit_cmp_and_jump_insns ( counter , const0_rtx , NE , NULL_RTX , QImode , 1 , start_label ) ; emit_label ( end_label ) ; } else { switch ( mode ) { case QImode : emit_insn ( gen_rotlqi3_1 ( dst , dst , rotate_amount ) ) ; break ; case HImode : emit_insn ( gen_rotlhi3_1 ( dst , dst , rotate_amount ) ) ; break ; case SImode : emit_insn ( gen_rotlsi3_1 ( dst , dst , rotate_amount ) ) ; break ; default : gcc_unreachable ( ) ; } } return 1 ; } </s>

A rotation by a non-constant will cause a loop to be generated , in which a rotation by one bit is used . A rotation by a constant , including the one in the loop , will be taken care of by emit_a_rotate ( ) at the insn emit time .


<s> bool expand_a_shift ( machine_mode mode , enum rtx_code code , rtx operands [ ] ) { switch ( h8sx_classify_shift ( mode , code , operands [ 2 ] ) ) { case H8SX_SHIFT_BINARY : operands [ 1 ] = force_reg ( mode , operands [ 1 ] ) ; return false ; case H8SX_SHIFT_UNARY : return false ; case H8SX_SHIFT_NONE : break ; } emit_move_insn ( copy_rtx ( operands [ 0 ] ) , operands [ 1 ] ) ; emit_insn ( gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , gen_rtx_SET ( VOIDmode , copy_rtx ( operands [ 0 ] ) , gen_rtx_fmt_ee ( code , mode , copy_rtx ( operands [ 0 ] ) , operands [ 2 ] ) ) , gen_rtx_CLOBBER ( VOIDmode , gen_rtx_SCRATCH ( QImode ) ) ) ) ) ; return true ; } </s>

Called from the .md file to emit code to do shifts . Returns a boolean indicating success ( currently this is always TRUE ) .


<s> void h8300_expand_branch ( rtx operands [ ] ) { enum rtx_code code = GET_CODE ( operands [ 0 ] ) ; rtx op0 = operands [ 1 ] ; rtx op1 = operands [ 2 ] ; rtx label = operands [ 3 ] ; rtx tmp ; tmp = gen_rtx_COMPARE ( VOIDmode , op0 , op1 ) ; emit_insn ( gen_rtx_SET ( VOIDmode , cc0_rtx , tmp ) ) ; tmp = gen_rtx_fmt_ee ( code , VOIDmode , cc0_rtx , const0_rtx ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , tmp , gen_rtx_LABEL_REF ( VOIDmode , label ) , pc_rtx ) ; emit_jump_insn ( gen_rtx_SET ( VOIDmode , pc_rtx , tmp ) ) ; } </s>


<s> void h8300_expand_prologue ( void ) { int regno ; int saved_regs ; int n_regs ; if ( h8300_os_task_function_p ( current_function_decl ) ) return ; if ( h8300_monitor_function_p ( current_function_decl ) ) emit_insn ( gen_monitor_prologue ( ) ) ; if ( frame_pointer_needed ) { push ( HARD_FRAME_POINTER_REGNUM , true ) ; F ( emit_move_insn ( hard_frame_pointer_rtx , stack_pointer_rtx ) , true ) ; } saved_regs = compute_saved_regs ( ) ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno += n_regs ) { n_regs = 1 ; if ( saved_regs & ( 1 << regno ) ) { if ( TARGET_H8300S ) { if ( ( ! TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x0f ) == 0x0f ) n_regs = 4 ; else if ( ( ! TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x07 ) == 0x07 ) n_regs = 3 ; else if ( ( ! TARGET_H8300SX || ( regno & 1 ) == 0 ) && ( ( saved_regs >> regno ) & 0x03 ) == 0x03 ) n_regs = 2 ; } h8300_push_pop ( regno , n_regs , false , false ) ; } } h8300_emit_stack_adjustment ( - 1 , round_frame_size ( get_frame_size ( ) ) , true ) ; } </s>

Generate RTL code for the function prologue .


<s> void h8300_expand_store ( rtx operands [ ] ) { rtx dest = operands [ 0 ] ; enum rtx_code code = GET_CODE ( operands [ 1 ] ) ; rtx op0 = operands [ 2 ] ; rtx op1 = operands [ 3 ] ; rtx tmp ; tmp = gen_rtx_COMPARE ( VOIDmode , op0 , op1 ) ; emit_insn ( gen_rtx_SET ( VOIDmode , cc0_rtx , tmp ) ) ; tmp = gen_rtx_fmt_ee ( code , GET_MODE ( dest ) , cc0_rtx , const0_rtx ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , tmp ) ) ; } </s>


<s> static rtx h8300_function_arg ( cumulative_args_t cum_v , machine_mode mode , const_tree type , bool named ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; static const char * const hand_list [ ] = { "__main" , "__cmpsi2" , "__divhi3" , "__modhi3" , "__udivhi3" , "__umodhi3" , "__divsi3" , "__modsi3" , "__udivsi3" , "__umodsi3" , "__mulhi3" , "__mulsi3" , "__reg_memcpy" , "__reg_memset" , "__ucmpsi2" , 0 , } ; rtx result = NULL_RTX ; const char * fname ; int regpass = 0 ; if ( ! named ) return NULL_RTX ; if ( TARGET_QUICKCALL ) regpass = 3 ; if ( cum -> libcall ) { const char * const * p ; fname = XSTR ( cum -> libcall , 0 ) ; for ( p = hand_list ; * p && strcmp ( * p , fname ) != 0 ; p ++ ) ; if ( * p ) regpass = 4 ; } if ( regpass ) { int size ; if ( mode == BLKmode ) size = int_size_in_bytes ( type ) ; else size = GET_MODE_SIZE ( mode ) ; if ( size + cum -> nbytes <= regpass * UNITS_PER_WORD && cum -> nbytes / UNITS_PER_WORD <= 3 ) result = gen_rtx_REG ( mode , cum -> nbytes / UNITS_PER_WORD ) ; } return result ; } </s>

If the next function argument with MODE and TYPE is to be passed in a register , return a reg RTX for the hard register in which to pass the argument . CUM represents the state after the last argument . If the argument is to be pushed , NULL_RTX is returned . On the H8/300 all normal args are pushed , unless -mquickcall in which case the first 3 arguments are passed in registers .


<s> static void h8300_function_arg_advance ( cumulative_args_t cum_v , machine_mode mode , const_tree type , bool named ATTRIBUTE_UNUSED ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; cum -> nbytes += ( mode != BLKmode ? ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) & - UNITS_PER_WORD : ( int_size_in_bytes ( type ) + UNITS_PER_WORD - 1 ) & - UNITS_PER_WORD ) ; } </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 h8300_hard_regno_mode_ok ( int regno , machine_mode mode ) { if ( TARGET_H8300 ) return ( ( regno & 1 ) == 0 ) || ( mode == HImode ) || ( mode == QImode ) ; else return regno == MAC_REG ? mode == SImode : 1 ; } </s>

Worker function for HARD_REGNO_MODE_OK .


<s> int h8300_hard_regno_nregs ( int regno ATTRIBUTE_UNUSED , machine_mode mode ) { return ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ; } </s>

Worker function for HARD_REGNO_NREGS . We pretend the MAC register is 32bits -- we do n't have any data types on the H8 series to handle more than 32bits .


<s> unsigned int h8300_insn_length_from_table ( rtx_insn * insn , rtx * operands ) { switch ( get_attr_length_table ( insn ) ) { case LENGTH_TABLE_NONE : gcc_unreachable ( ) ; case LENGTH_TABLE_ADDB : return h8300_binary_length ( insn , & addb_length_table ) ; case LENGTH_TABLE_ADDW : return h8300_binary_length ( insn , & addw_length_table ) ; case LENGTH_TABLE_ADDL : return h8300_binary_length ( insn , & addl_length_table ) ; case LENGTH_TABLE_LOGICB : return h8300_binary_length ( insn , & logicb_length_table ) ; case LENGTH_TABLE_MOVB : return h8300_move_length ( operands , & movb_length_table ) ; case LENGTH_TABLE_MOVW : return h8300_move_length ( operands , & movw_length_table ) ; case LENGTH_TABLE_MOVL : return h8300_move_length ( operands , & movl_length_table ) ; case LENGTH_TABLE_MOVA : return h8300_mova_length ( operands [ 0 ] , operands [ 1 ] , operands [ 2 ] ) ; case LENGTH_TABLE_MOVA_ZERO : return h8300_mova_length ( operands [ 0 ] , operands [ 1 ] , const0_rtx ) ; case LENGTH_TABLE_UNARY : return h8300_unary_length ( operands [ 0 ] ) ; case LENGTH_TABLE_MOV_IMM4 : return 2 + h8300_classify_operand ( operands [ 0 ] , 0 , 0 ) ; case LENGTH_TABLE_SHORT_IMMEDIATE : return h8300_short_immediate_length ( operands [ 0 ] ) ; case LENGTH_TABLE_BITFIELD : return h8300_bitfield_length ( operands [ 0 ] , operands [ 1 ] ) ; case LENGTH_TABLE_BITBRANCH : return h8300_bitfield_length ( operands [ 1 ] , operands [ 2 ] ) - 2 ; default : gcc_unreachable ( ) ; } } </s>

Compute the length of INSN based on its length_table attribute . OPERANDS is the array of its operands .


<s> static void h8300_print_operand_address ( FILE * file , rtx addr ) { rtx index ; int size ; switch ( GET_CODE ( addr ) ) { case REG : fprintf ( file , "%s" , h8_reg_names [ REGNO ( addr ) ] ) ; break ; case PRE_DEC : fprintf ( file , "-%s" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case POST_INC : fprintf ( file , "%s+" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case PRE_INC : fprintf ( file , "+%s" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case POST_DEC : fprintf ( file , "%s-" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case PLUS : fprintf ( file , "(" ) ; index = h8300_get_index ( XEXP ( addr , 0 ) , VOIDmode , & size ) ; if ( GET_CODE ( index ) == REG ) { h8300_print_operand_address ( file , XEXP ( addr , 1 ) ) ; fprintf ( file , "," ) ; switch ( size ) { case 0 : h8300_print_operand_address ( file , index ) ; break ; case 1 : h8300_print_operand ( file , index , 'X' ) ; fputs ( ".b" , file ) ; break ; case 2 : h8300_print_operand ( file , index , 'T' ) ; fputs ( ".w" , file ) ; break ; case 4 : h8300_print_operand ( file , index , 'S' ) ; fputs ( ".l" , file ) ; break ; } } else { h8300_print_operand_address ( file , XEXP ( addr , 0 ) ) ; fprintf ( file , "+" ) ; h8300_print_operand_address ( file , XEXP ( addr , 1 ) ) ; } fprintf ( file , ")" ) ; break ; case CONST_INT : { int n = INTVAL ( addr ) ; if ( TARGET_H8300 ) n = ( int ) ( short ) n ; fprintf ( file , "%d" , n ) ; break ; } default : output_addr_const ( file , addr ) ; break ; } } </s>

Output assembly language output for the address ADDR to FILE .


<s> static void h8300_push_pop ( int regno , int nregs , bool pop_p , bool return_p ) { int i , j ; rtvec vec ; rtx sp , offset , x ; if ( ! return_p && nregs == 1 ) { if ( pop_p ) pop ( regno ) ; else push ( regno , false ) ; return ; } vec = rtvec_alloc ( ( return_p ? 1 : 0 ) + nregs + 1 ) ; sp = stack_pointer_rtx ; i = 0 ; if ( return_p ) { RTVEC_ELT ( vec , i ) = ret_rtx ; i ++ ; } for ( j = 0 ; j < nregs ; j ++ ) { rtx lhs , rhs ; if ( pop_p ) { lhs = gen_rtx_REG ( SImode , regno + j ) ; rhs = gen_rtx_MEM ( SImode , plus_constant ( Pmode , sp , ( nregs - j - 1 ) * 4 ) ) ; } else { lhs = gen_rtx_MEM ( SImode , plus_constant ( Pmode , sp , ( j + 1 ) * - 4 ) ) ; rhs = gen_rtx_REG ( SImode , regno + j ) ; } RTVEC_ELT ( vec , i + j ) = gen_rtx_SET ( VOIDmode , lhs , rhs ) ; } offset = GEN_INT ( ( pop_p ? nregs : - nregs ) * 4 ) ; RTVEC_ELT ( vec , i + j ) = gen_rtx_SET ( VOIDmode , sp , gen_rtx_PLUS ( Pmode , sp , offset ) ) ; x = gen_rtx_PARALLEL ( VOIDmode , vec ) ; if ( ! pop_p ) x = Fpa ( x ) ; if ( return_p ) emit_jump_insn ( x ) ; else emit_insn ( x ) ; } </s>

Emit an instruction to push or pop NREGS consecutive registers starting at register REGNO . POP_P selects a pop rather than a push and RETURN_P is true if the instruction should return . It must be possible to do the requested operation in a single instruction . If NREGS == 1 & & ! RETURN_P , use a normal push or pop insn . Otherwise emit a parallel of the form : ( parallel [ ( return ) ; ; if RETURN_P ( save or restore REGNO ) ( save or restore REGNO + 1 ) ... ( save or restore REGNO + NREGS - 1 ) ( set sp ( plus sp ( const_int adjust ) ) ) ]


<s> int h8300_shift_needs_scratch_p ( int count , machine_mode mode ) { enum h8_cpu cpu ; int a , lr , ar ; if ( GET_MODE_BITSIZE ( mode ) <= count ) return 1 ; if ( TARGET_H8300 ) cpu = H8_300 ; else if ( TARGET_H8300H ) cpu = H8_300H ; else cpu = H8_S ; switch ( mode ) { case QImode : a = shift_alg_qi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_qi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_qi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case HImode : a = shift_alg_hi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_hi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_hi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case SImode : a = shift_alg_si [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_si [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_si [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; default : gcc_unreachable ( ) ; } return ( a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; } </s>

Given COUNT and MODE of a shift , return 1 if a scratch reg may be needed for some shift with COUNT and MODE . Return 0 otherwise .


<s> void h8300_swap_into_er6 ( rtx addr ) { rtx insn = push ( HARD_FRAME_POINTER_REGNUM , false ) ; if ( frame_pointer_needed ) add_reg_note ( insn , REG_CFA_DEF_CFA , plus_constant ( Pmode , gen_rtx_MEM ( Pmode , stack_pointer_rtx ) , 2 * UNITS_PER_WORD ) ) ; else add_reg_note ( insn , REG_CFA_ADJUST_CFA , gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , 4 ) ) ) ; emit_move_insn ( hard_frame_pointer_rtx , addr ) ; if ( REGNO ( addr ) == SP_REG ) emit_move_insn ( hard_frame_pointer_rtx , plus_constant ( Pmode , hard_frame_pointer_rtx , GET_MODE_SIZE ( word_mode ) ) ) ; } </s>

Move ADDR into er6 after pushing its old value onto the stack .


<s> void h8300_swap_out_of_er6 ( rtx addr ) { rtx insn ; if ( REGNO ( addr ) != SP_REG ) emit_move_insn ( addr , hard_frame_pointer_rtx ) ; insn = pop ( HARD_FRAME_POINTER_REGNUM ) ; if ( frame_pointer_needed ) add_reg_note ( insn , REG_CFA_DEF_CFA , plus_constant ( Pmode , hard_frame_pointer_rtx , 2 * UNITS_PER_WORD ) ) ; else add_reg_note ( insn , REG_CFA_ADJUST_CFA , gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , - 4 ) ) ) ; } </s>

Move the current value of er6 into ADDR and pop its old value from the stack .


<s> int same_cmp_following_p ( rtx i1 ) { rtx_insn * i2 , * i3 ; i2 = next_nonnote_insn ( i1 ) ; if ( i2 == NULL ) return 0 ; i3 = next_nonnote_insn ( i2 ) ; if ( i3 == NULL ) return 0 ; return ( INSN_P ( i3 ) && rtx_equal_p ( PATTERN ( i1 ) , PATTERN ( i3 ) ) && any_condjump_p ( i2 ) && onlyjump_p ( i2 ) ) ; } </s>

Return nonzero if we have the same comparison insn as I1 two insns after I1 . I1 is assumed to be a comparison insn .


<s> int same_cmp_preceding_p ( rtx i3 ) { rtx_insn * i1 , * i2 ; i2 = prev_nonnote_insn ( i3 ) ; if ( i2 == NULL ) return 0 ; i1 = prev_nonnote_insn ( i2 ) ; if ( i1 == NULL ) return 0 ; return ( INSN_P ( i1 ) && rtx_equal_p ( PATTERN ( i1 ) , PATTERN ( i3 ) ) && any_condjump_p ( i2 ) && onlyjump_p ( i2 ) ) ; } </s>

Return nonzero if we have the same comparison insn as I3 two insns before I3 . I3 is assumed to be a comparison insn .


<s> void split_adds_subs ( machine_mode mode , rtx * operands ) { HOST_WIDE_INT val = INTVAL ( operands [ 1 ] ) ; rtx reg = operands [ 0 ] ; HOST_WIDE_INT sign = 1 ; HOST_WIDE_INT amount ; rtx ( * gen_add ) ( rtx , rtx , rtx ) ; if ( val < 0 ) { val = - val ; sign = - 1 ; } switch ( mode ) { case HImode : gen_add = gen_addhi3 ; break ; case SImode : gen_add = gen_addsi3 ; break ; default : gcc_unreachable ( ) ; } for ( amount = ( TARGET_H8300H || TARGET_H8300S ) ? 4 : 2 ; amount > 0 ; amount /= 2 ) { for ( ; val >= amount ; val -= amount ) emit_insn ( gen_add ( reg , reg , GEN_INT ( sign * amount ) ) ) ; } return ; } </s>

Split an add of a small constant into two adds/subs insns .


<s> void h8300_expand_prologue ( void ) { int regno ; int saved_regs ; int n_regs ; if ( h8300_os_task_function_p ( current_function_decl ) ) return ; if ( h8300_monitor_function_p ( current_function_decl ) ) emit_insn ( gen_monitor_prologue ( ) ) ; if ( frame_pointer_needed ) { push ( HARD_FRAME_POINTER_REGNUM , true ) ; F ( emit_move_insn ( hard_frame_pointer_rtx , stack_pointer_rtx ) , true ) ; } saved_regs = compute_saved_regs ( ) ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno += n_regs ) { n_regs = 1 ; if ( saved_regs & ( 1 << regno ) ) { if ( TARGET_H8300S ) { if ( ( ! TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x0f ) == 0x0f ) n_regs = 4 ; else if ( ( ! TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x07 ) == 0x07 ) n_regs = 3 ; else if ( ( ! TARGET_H8300SX || ( regno & 1 ) == 0 ) && ( ( saved_regs >> regno ) & 0x03 ) == 0x03 ) n_regs = 2 ; } h8300_push_pop ( regno , n_regs , false , false ) ; } } h8300_emit_stack_adjustment ( - 1 , round_frame_size ( get_frame_size ( ) ) , true ) ; if ( flag_stack_usage_info ) current_function_static_stack_size = round_frame_size ( get_frame_size ( ) ) + ( __builtin_popcount ( saved_regs ) * UNITS_PER_WORD ) + ( frame_pointer_needed ? UNITS_PER_WORD : 0 ) ; } </s>


<s> int h8300_shift_needs_scratch_p ( int count , machine_mode mode ) { enum h8_cpu cpu ; int a , lr , ar ; if ( GET_MODE_BITSIZE ( mode ) <= count ) return 1 ; if ( TARGET_H8300 ) cpu = H8_300 ; else if ( TARGET_H8300S ) cpu = H8_S ; else cpu = H8_300H ; switch ( mode ) { case QImode : a = shift_alg_qi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_qi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_qi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case HImode : a = shift_alg_hi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_hi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_hi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case SImode : a = shift_alg_si [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_si [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_si [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; default : gcc_unreachable ( ) ; } return ( a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; } </s>


<s> void h8300_swap_into_er6 ( rtx addr ) { rtx insn = push ( HARD_FRAME_POINTER_REGNUM , false ) ; if ( frame_pointer_needed ) add_reg_note ( insn , REG_CFA_DEF_CFA , plus_constant ( Pmode , gen_rtx_MEM ( Pmode , stack_pointer_rtx ) , 2 * UNITS_PER_WORD ) ) ; else add_reg_note ( insn , REG_CFA_ADJUST_CFA , gen_rtx_SET ( stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , 4 ) ) ) ; emit_move_insn ( hard_frame_pointer_rtx , addr ) ; if ( REGNO ( addr ) == SP_REG ) emit_move_insn ( hard_frame_pointer_rtx , plus_constant ( Pmode , hard_frame_pointer_rtx , GET_MODE_SIZE ( word_mode ) ) ) ; } </s>


<s> void h8300_swap_out_of_er6 ( rtx addr ) { rtx insn ; if ( REGNO ( addr ) != SP_REG ) emit_move_insn ( addr , hard_frame_pointer_rtx ) ; insn = pop ( HARD_FRAME_POINTER_REGNUM ) ; if ( frame_pointer_needed ) add_reg_note ( insn , REG_CFA_DEF_CFA , plus_constant ( Pmode , hard_frame_pointer_rtx , 2 * UNITS_PER_WORD ) ) ; else add_reg_note ( insn , REG_CFA_ADJUST_CFA , gen_rtx_SET ( stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , - 4 ) ) ) ; } </s>


<s> int byte_accesses_mergeable_p ( rtx addr1 , rtx addr2 ) { HOST_WIDE_INT offset1 , offset2 ; rtx reg1 , reg2 ; if ( REG_P ( addr1 ) ) { reg1 = addr1 ; offset1 = 0 ; } else if ( GET_CODE ( addr1 ) == PLUS && REG_P ( XEXP ( addr1 , 0 ) ) && GET_CODE ( XEXP ( addr1 , 1 ) ) == CONST_INT ) { reg1 = XEXP ( addr1 , 0 ) ; offset1 = INTVAL ( XEXP ( addr1 , 1 ) ) ; } else return 0 ; if ( REG_P ( addr2 ) ) { reg2 = addr2 ; offset2 = 0 ; } else if ( GET_CODE ( addr2 ) == PLUS && REG_P ( XEXP ( addr2 , 0 ) ) && GET_CODE ( XEXP ( addr2 , 1 ) ) == CONST_INT ) { reg2 = XEXP ( addr2 , 0 ) ; offset2 = INTVAL ( XEXP ( addr2 , 1 ) ) ; } else return 0 ; if ( ( ( reg1 == stack_pointer_rtx && reg2 == stack_pointer_rtx ) || ( reg1 == frame_pointer_rtx && reg2 == frame_pointer_rtx ) ) && offset1 % 2 == 0 && offset1 + 1 == offset2 ) return 1 ; return 0 ; } </s>

Return nonzero if ADDR1 and ADDR2 point to consecutive memory locations that can be accessed as a 16-bit word .


<s> static const char * byte_reg ( rtx x , int b ) { static const char * const names_small [ ] = { "r0l" , "r0h" , "r1l" , "r1h" , "r2l" , "r2h" , "r3l" , "r3h" , "r4l" , "r4h" , "r5l" , "r5h" , "r6l" , "r6h" , "r7l" , "r7h" } ; gcc_assert ( REG_P ( x ) ) ; return names_small [ REGNO ( x ) * 2 + b ] ; } </s>

Return the byte register name for a register rtx X . B should be 0 if you want a lower byte register . B should be 1 if you want an upper byte register .


<s> unsigned int compute_a_rotate_length ( rtx * operands ) { rtx src = operands [ 1 ] ; rtx amount_rtx = operands [ 2 ] ; machine_mode mode = GET_MODE ( src ) ; int amount ; unsigned int length = 0 ; gcc_assert ( GET_CODE ( amount_rtx ) == CONST_INT ) ; amount = INTVAL ( amount_rtx ) ; if ( amount < 0 ) amount = 0 ; if ( ( unsigned int ) amount > GET_MODE_BITSIZE ( mode ) ) amount = GET_MODE_BITSIZE ( mode ) ; if ( ( unsigned int ) amount > GET_MODE_BITSIZE ( mode ) / ( unsigned ) 2 ) amount = GET_MODE_BITSIZE ( mode ) - amount ; if ( ( mode == HImode && TARGET_H8300H && amount >= 6 ) || ( mode == HImode && TARGET_H8300S && amount == 8 ) || ( mode == SImode && TARGET_H8300H && amount >= 10 ) || ( mode == SImode && TARGET_H8300S && amount >= 13 ) ) { amount = GET_MODE_BITSIZE ( mode ) / 2 - amount ; length += 6 ; } if ( TARGET_H8300S ) amount = amount / 2 + amount % 2 ; length += amount * 2 ; return length ; } </s>


<s> int compute_a_shift_cc ( rtx operands [ 3 ] , rtx_code code ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; enum shift_type shift_type ; enum shift_mode shift_mode ; struct shift_info info ; int n ; switch ( mode ) { case E_QImode : shift_mode = QIshift ; break ; case E_HImode : shift_mode = HIshift ; break ; case E_SImode : shift_mode = SIshift ; break ; default : gcc_unreachable ( ) ; } switch ( code ) { case ASHIFTRT : shift_type = SHIFT_ASHIFTRT ; break ; case LSHIFTRT : shift_type = SHIFT_LSHIFTRT ; break ; case ASHIFT : shift_type = SHIFT_ASHIFT ; break ; default : gcc_unreachable ( ) ; } gcc_assert ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) ; n = INTVAL ( operands [ 2 ] ) ; if ( n < 0 ) n = 0 ; else if ( ( unsigned int ) n > GET_MODE_BITSIZE ( mode ) ) n = GET_MODE_BITSIZE ( mode ) ; get_shift_alg ( shift_type , shift_mode , n , & info ) ; switch ( info . alg ) { case SHIFT_SPECIAL : if ( info . remainder == 0 ) return ( info . cc_special == OLD_CC_SET_ZN || info . cc_special == OLD_CC_SET_ZNV ) ; case SHIFT_INLINE : return ( info . cc_inline == OLD_CC_SET_ZN || info . cc_inline == OLD_CC_SET_ZNV ) ; case SHIFT_ROT_AND : return true ; case SHIFT_LOOP : if ( info . shift2 != NULL ) { if ( n % 2 ) return ( info . cc_inline == OLD_CC_SET_ZN || info . cc_inline == OLD_CC_SET_ZNV ) ; } return false ; default : gcc_unreachable ( ) ; } } </s>

Compute which flag bits are valid after a shift insn .


<s> unsigned int compute_a_shift_length ( rtx operands [ 3 ] , rtx_code code ) { enum machine_mode mode = GET_MODE ( operands [ 0 ] ) ; enum shift_type shift_type ; enum shift_mode shift_mode ; struct shift_info info ; unsigned int wlength = 0 ; switch ( mode ) { case E_QImode : shift_mode = QIshift ; break ; case E_HImode : shift_mode = HIshift ; break ; case E_SImode : shift_mode = SIshift ; break ; default : gcc_unreachable ( ) ; } switch ( code ) { case ASHIFTRT : shift_type = SHIFT_ASHIFTRT ; break ; case LSHIFTRT : shift_type = SHIFT_LSHIFTRT ; break ; case ASHIFT : shift_type = SHIFT_ASHIFT ; break ; default : gcc_unreachable ( ) ; } if ( GET_CODE ( operands [ 2 ] ) != CONST_INT ) { get_shift_alg ( shift_type , shift_mode , 1 , & info ) ; return ( 4 + h8300_asm_insn_count ( info . shift1 ) ) * 2 ; } else { int n = INTVAL ( operands [ 2 ] ) ; if ( n < 0 ) n = 0 ; else if ( ( unsigned int ) n > GET_MODE_BITSIZE ( mode ) ) n = GET_MODE_BITSIZE ( mode ) ; get_shift_alg ( shift_type , shift_mode , n , & info ) ; switch ( info . alg ) { case SHIFT_SPECIAL : wlength += h8300_asm_insn_count ( info . special ) ; if ( strstr ( info . special , "xor.l" ) != NULL ) wlength ++ ; case SHIFT_INLINE : n = info . remainder ; if ( info . shift2 != NULL ) { wlength += h8300_asm_insn_count ( info . shift2 ) * ( n / 2 ) ; n = n % 2 ; } wlength += h8300_asm_insn_count ( info . shift1 ) * n ; return 2 * wlength ; case SHIFT_ROT_AND : { int m = GET_MODE_BITSIZE ( mode ) - n ; gcc_assert ( info . shift1 ) ; if ( info . shift2 != NULL ) { wlength += h8300_asm_insn_count ( info . shift2 ) * ( m / 2 ) ; m = m % 2 ; } wlength += h8300_asm_insn_count ( info . shift1 ) * m ; switch ( mode ) { case E_QImode : wlength += 1 ; break ; case E_HImode : wlength += 2 ; break ; case E_SImode : wlength += 3 ; break ; default : gcc_unreachable ( ) ; } return 2 * wlength ; } case SHIFT_LOOP : if ( info . shift2 != NULL ) { wlength += 3 + h8300_asm_insn_count ( info . shift2 ) ; if ( n % 2 ) wlength += h8300_asm_insn_count ( info . shift1 ) ; } else { wlength += 3 + h8300_asm_insn_count ( info . shift1 ) ; } return 2 * wlength ; default : gcc_unreachable ( ) ; } } } </s>


<s> enum attr_cc compute_logical_op_cc ( machine_mode mode , rtx * operands ) { enum rtx_code code = GET_CODE ( operands [ 3 ] ) ; const unsigned HOST_WIDE_INT intval = ( unsigned HOST_WIDE_INT ) ( ( GET_CODE ( operands [ 2 ] ) == CONST_INT ) && register_operand ( operands [ 1 ] , VOIDmode ) ? INTVAL ( operands [ 2 ] ) : 0x55555555 ) ; const unsigned HOST_WIDE_INT det = ( code != AND ) ? intval : ~ intval ; const unsigned HOST_WIDE_INT b0 = ( det >> 0 ) & 0xff ; const unsigned HOST_WIDE_INT b1 = ( det >> 8 ) & 0xff ; const unsigned HOST_WIDE_INT w0 = ( det >> 0 ) & 0xffff ; const unsigned HOST_WIDE_INT w1 = ( det >> 16 ) & 0xffff ; int lower_half_easy_p = 0 ; int upper_half_easy_p = 0 ; enum attr_cc cc = CC_CLOBBER ; switch ( mode ) { case E_HImode : if ( ( TARGET_H8300H || TARGET_H8300S ) && b0 != 0 && b1 != 0 ) { cc = CC_SET_ZNV ; } break ; case E_SImode : if ( TARGET_H8300H || TARGET_H8300S ) { lower_half_easy_p = ( b0 == 0 || b1 == 0 || ( code != IOR && w0 == 0xffff ) ) ; upper_half_easy_p = ( ( code != IOR && w1 == 0xffff ) || ( code == AND && w1 == 0xff00 ) ) ; } if ( ( TARGET_H8300H || TARGET_H8300S ) && w0 != 0 && w1 != 0 && ! ( lower_half_easy_p && upper_half_easy_p ) && ! ( code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 && lower_half_easy_p ) ) { cc = CC_SET_ZNV ; } else { if ( ( TARGET_H8300H || TARGET_H8300S ) && code == IOR && w1 == 0xffff && ( w0 & 0x8000 ) != 0 ) { cc = CC_SET_ZNV ; } } break ; default : gcc_unreachable ( ) ; } return cc ; } </s>

Compute which flag bits are valid after a logical insn .


<s> unsigned int compute_mov_length ( rtx * operands ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; rtx dest = operands [ 0 ] ; rtx src = operands [ 1 ] ; rtx addr ; if ( GET_CODE ( src ) == MEM ) addr = XEXP ( src , 0 ) ; else if ( GET_CODE ( dest ) == MEM ) addr = XEXP ( dest , 0 ) ; else addr = NULL_RTX ; unsigned int base_length ; switch ( mode ) { case E_QImode : if ( addr == NULL_RTX ) return 2 ; if ( h8300_eightbit_constant_address_p ( addr ) ) return 2 ; base_length = 8 ; break ; case E_HImode : if ( addr == NULL_RTX ) { if ( REG_P ( src ) ) return 2 ; if ( src == const0_rtx ) return 2 ; return 4 ; } base_length = 8 ; break ; case E_SImode : if ( addr == NULL_RTX ) { if ( REG_P ( src ) ) { if ( REGNO ( src ) == MAC_REG || REGNO ( dest ) == MAC_REG ) return 4 ; else return 2 ; } if ( GET_CODE ( src ) == CONST_INT ) { int val = INTVAL ( src ) ; if ( val == 0 ) return 2 ; if ( val == ( val & 0x00ff ) || val == ( val & 0xff00 ) ) return 4 ; switch ( val & 0xffffffff ) { case 0xffffffff : case 0xfffffffe : case 0xfffffffc : case 0x0000ffff : case 0x0000fffe : case 0xffff0000 : case 0xfffe0000 : case 0x00010000 : case 0x00020000 : return 4 ; } } return 6 ; } base_length = 10 ; break ; case E_SFmode : if ( addr == NULL_RTX ) { if ( REG_P ( src ) ) return 2 ; if ( satisfies_constraint_G ( src ) ) return 2 ; return 6 ; } base_length = 10 ; break ; default : gcc_unreachable ( ) ; } if ( GET_CODE ( addr ) == PRE_DEC || GET_CODE ( addr ) == POST_INC ) return base_length - 6 ; if ( GET_CODE ( addr ) == REG ) return base_length - 6 ; if ( GET_CODE ( addr ) == PLUS && GET_CODE ( XEXP ( addr , 0 ) ) == REG && GET_CODE ( XEXP ( addr , 1 ) ) == CONST_INT && INTVAL ( XEXP ( addr , 1 ) ) > - 32768 && INTVAL ( XEXP ( addr , 1 ) ) < 32767 ) return base_length - 4 ; if ( h8300_tiny_constant_address_p ( addr ) ) return base_length - 4 ; if ( CONSTANT_P ( addr ) ) return base_length - 2 ; return base_length ; } </s>


<s> enum attr_old_cc compute_plussi_cc ( rtx * operands ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; gcc_assert ( mode == SImode ) ; if ( GET_CODE ( operands [ 2 ] ) == CONST_INT && register_operand ( operands [ 1 ] , VOIDmode ) ) { HOST_WIDE_INT intval = INTVAL ( operands [ 2 ] ) ; if ( TARGET_H8300SX && ( intval >= 1 && intval <= 7 ) ) return OLD_CC_SET_ZN ; if ( TARGET_H8300SX && ( intval >= - 7 && intval <= - 1 ) ) return OLD_CC_SET_ZN ; switch ( ( unsigned int ) intval & 0xffffffff ) { case 0x00000001 : case 0x00000002 : case 0x00000004 : return OLD_CC_NONE_0HIT ; case 0xffffffff : case 0xfffffffe : case 0xfffffffc : return OLD_CC_NONE_0HIT ; case 0x00010000 : case 0x00020000 : return OLD_CC_CLOBBER ; case 0xffff0000 : case 0xfffe0000 : return OLD_CC_CLOBBER ; } if ( ( intval & 0xffff ) == 0 ) return OLD_CC_CLOBBER ; } return OLD_CC_SET_ZN ; } </s>

Compute which flag bits are valid after an addition insn .


<s> unsigned int compute_plussi_length ( rtx * operands , bool need_flags ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; gcc_assert ( mode == SImode ) ; if ( GET_CODE ( operands [ 2 ] ) == CONST_INT && register_operand ( operands [ 1 ] , VOIDmode ) ) { HOST_WIDE_INT intval = INTVAL ( operands [ 2 ] ) ; if ( TARGET_H8300SX && ( intval >= 1 && intval <= 7 ) ) return 2 ; if ( TARGET_H8300SX && ( intval >= - 7 && intval <= - 1 ) ) return 2 ; switch ( ( unsigned int ) intval & 0xffffffff ) { case 0x00000001 : case 0x00000002 : return 2 ; case 0x00000004 : if ( need_flags ) return 6 ; else return 2 ; case 0xffffffff : case 0xfffffffe : return 2 ; case 0xfffffffc : if ( need_flags ) return 6 ; else return 2 ; case 0x00010000 : case 0x00020000 : if ( ! need_flags ) return 2 ; case 0xffff0000 : case 0xfffe0000 : if ( ! need_flags ) return 2 ; } if ( ( intval & 0xffff ) == 0 ) return 4 ; } if ( GET_CODE ( operands [ 2 ] ) == CONST_INT && INTVAL ( operands [ 2 ] ) < 0 ) return h8300_length_from_table ( operands [ 0 ] , GEN_INT ( - INTVAL ( operands [ 2 ] ) ) , & addl_length_table ) ; else return h8300_length_from_table ( operands [ 0 ] , operands [ 2 ] , & addl_length_table ) ; } </s>

Compute the length of an addition insn .


<s> static unsigned int compute_saved_regs ( void ) { unsigned int saved_regs = 0 ; int regno ; for ( regno = 0 ; regno <= HARD_FRAME_POINTER_REGNUM ; regno ++ ) { if ( WORD_REG_USED ( regno ) ) saved_regs |= 1 << regno ; } if ( frame_pointer_needed ) saved_regs &= ~ ( 1 << HARD_FRAME_POINTER_REGNUM ) ; return saved_regs ; } </s>

Compute which registers to push/pop . Return a bit vector of registers .


<s> static const char * cond_string ( enum rtx_code code ) { switch ( code ) { case NE : return "ne" ; case EQ : return "eq" ; case GE : return "ge" ; case GT : return "gt" ; case LE : return "le" ; case LT : return "lt" ; case GEU : return "hs" ; case GTU : return "hi" ; case LEU : return "ls" ; case LTU : return "lo" ; default : gcc_unreachable ( ) ; } } </s>

Return assembly language string which identifies a comparison type .


<s> int expand_a_rotate ( rtx operands [ ] ) { rtx dst = operands [ 0 ] ; rtx src = operands [ 1 ] ; rtx rotate_amount = operands [ 2 ] ; machine_mode mode = GET_MODE ( dst ) ; if ( h8sx_classify_shift ( mode , ROTATE , rotate_amount ) == H8SX_SHIFT_UNARY ) return false ; emit_move_insn ( dst , src ) ; if ( GET_CODE ( rotate_amount ) != CONST_INT ) { rtx counter = gen_reg_rtx ( QImode ) ; rtx_code_label * start_label = gen_label_rtx ( ) ; rtx_code_label * end_label = gen_label_rtx ( ) ; emit_cmp_and_jump_insns ( rotate_amount , const0_rtx , LE , NULL_RTX , QImode , 0 , end_label ) ; emit_move_insn ( counter , rotate_amount ) ; emit_label ( start_label ) ; switch ( mode ) { case E_QImode : emit_insn ( gen_rotlqi3_1 ( dst , dst , const1_rtx ) ) ; break ; case E_HImode : emit_insn ( gen_rotlhi3_1 ( dst , dst , const1_rtx ) ) ; break ; case E_SImode : emit_insn ( gen_rotlsi3_1 ( dst , dst , const1_rtx ) ) ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen_addqi3 ( counter , counter , constm1_rtx ) ) ; emit_cmp_and_jump_insns ( counter , const0_rtx , NE , NULL_RTX , QImode , 1 , start_label ) ; emit_label ( end_label ) ; } else { switch ( mode ) { case E_QImode : emit_insn ( gen_rotlqi3_1 ( dst , dst , rotate_amount ) ) ; break ; case E_HImode : emit_insn ( gen_rotlhi3_1 ( dst , dst , rotate_amount ) ) ; break ; case E_SImode : emit_insn ( gen_rotlsi3_1 ( dst , dst , rotate_amount ) ) ; break ; default : gcc_unreachable ( ) ; } } return 1 ; } </s>

A rotation by a non-constant will cause a loop to be generated , in which a rotation by one bit is used . A rotation by a constant , including the one in the loop , will be taken care of by emit_a_rotate ( ) at the insn emit time .


<s> bool expand_a_shift ( machine_mode mode , enum rtx_code code , rtx operands [ ] ) { switch ( h8sx_classify_shift ( mode , code , operands [ 2 ] ) ) { case H8SX_SHIFT_BINARY : operands [ 1 ] = force_reg ( mode , operands [ 1 ] ) ; return false ; case H8SX_SHIFT_UNARY : return false ; case H8SX_SHIFT_NONE : break ; } emit_move_insn ( copy_rtx ( operands [ 0 ] ) , operands [ 1 ] ) ; if ( operands [ 2 ] == CONST0_RTX ( QImode ) ) ; else if ( GET_CODE ( operands [ 2 ] ) == CONST_INT && ! h8300_shift_needs_scratch_p ( INTVAL ( operands [ 2 ] ) , mode , code ) ) emit_insn ( gen_rtx_SET ( copy_rtx ( operands [ 0 ] ) , gen_rtx_fmt_ee ( code , mode , copy_rtx ( operands [ 1 ] ) , operands [ 2 ] ) ) ) ; else emit_insn ( gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , gen_rtx_SET ( copy_rtx ( operands [ 0 ] ) , gen_rtx_fmt_ee ( code , mode , copy_rtx ( operands [ 0 ] ) , operands [ 2 ] ) ) , gen_rtx_CLOBBER ( VOIDmode , gen_rtx_SCRATCH ( QImode ) ) ) ) ) ; return true ; } </s>

Called from the .md file to emit code to do shifts . Returns a boolean indicating success ( currently this is always TRUE ) .


<s>
void
final_prescan_insn
(
rtx_insn
*
insn
,
rtx
*
operand
ATTRIBUTE_UNUSED
,
int
num_operands
ATTRIBUTE_UNUSED
)
{
static
int
last_insn_address
=
0
;
const
int
uid
=
INSN_UID
(
insn
)
;
if
(
TARGET_ADDRESSES
)
{
fprintf
(
asm_out_file
,
"; 0x%x %d\n"
,
INSN_ADDRESSES
(
uid
)
,
INSN_ADDRESSES
(
uid
)
last_insn_address
)
;
last_insn_address
=
INSN_ADDRESSES
(
uid
)
;
}
}
</s>

If defined , a C statement to be executed just prior to the output of assembler code for INSN , to modify the extracted operands so they will be output differently . Here the argument OPVEC is the vector containing the operands extracted from INSN , and NOPERANDS is the number of elements of the vector which contain meaningful data for this insn . The contents of this vector are what will be used to convert the insn template into assembler code , so you can change the assembler output by changing the contents of the vector . We use it to check if the current insn needs a nop in front of it because of load delays , and also to update the delay slot statistics .


<s> int fix_bit_operand ( rtx * operands , enum rtx_code code ) { if ( code == AND ? single_zero_operand ( operands [ 2 ] , QImode ) : single_one_operand ( operands [ 2 ] , QImode ) ) { if ( GET_CODE ( operands [ 0 ] ) == MEM && ! satisfies_constraint_U ( operands [ 0 ] ) ) { rtx mem = gen_rtx_MEM ( GET_MODE ( operands [ 0 ] ) , copy_to_mode_reg ( Pmode , XEXP ( operands [ 0 ] , 0 ) ) ) ; MEM_COPY_ATTRIBUTES ( mem , operands [ 0 ] ) ; operands [ 0 ] = mem ; } if ( GET_CODE ( operands [ 1 ] ) == MEM && ! satisfies_constraint_U ( operands [ 1 ] ) ) { rtx mem = gen_rtx_MEM ( GET_MODE ( operands [ 1 ] ) , copy_to_mode_reg ( Pmode , XEXP ( operands [ 1 ] , 0 ) ) ) ; MEM_COPY_ATTRIBUTES ( mem , operands [ 0 ] ) ; operands [ 1 ] = mem ; } return 0 ; } operands [ 1 ] = force_reg ( QImode , operands [ 1 ] ) ; { rtx res = gen_reg_rtx ( QImode ) ; switch ( code ) { case AND : emit_insn ( gen_andqi3_1 ( res , operands [ 1 ] , operands [ 2 ] ) ) ; break ; case IOR : emit_insn ( gen_iorqi3_1 ( res , operands [ 1 ] , operands [ 2 ] ) ) ; break ; case XOR : emit_insn ( gen_xorqi3_1 ( res , operands [ 1 ] , operands [ 2 ] ) ) ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen_movqi ( operands [ 0 ] , res ) ) ; } return 1 ; } </s>

Fix the operands of a gen_xxx so that it could become a bit operating insn .


<s> static rtx Fpa ( rtx par ) { int len = XVECLEN ( par , 0 ) ; int i ; for ( i = 0 ; i < len ; i ++ ) RTX_FRAME_RELATED_P ( XVECEXP ( par , 0 , i ) ) = 1 ; return par ; } </s>

Mark all the subexpressions of the PARALLEL rtx PAR as frame-related . Return PAR . dwarf2out.cc : dwarf2out_frame_debug_expr ignores sub-expressions of a PARALLEL rtx other than the first if they do not have the FRAME_RELATED flag set on them .


<s> static int h8300_and_costs ( rtx x ) { rtx operands [ 4 ] ; if ( GET_MODE ( x ) == QImode ) return 1 ; if ( GET_MODE ( x ) != HImode && GET_MODE ( x ) != SImode ) return 100 ; operands [ 0 ] = NULL ; operands [ 1 ] = XEXP ( x , 0 ) ; operands [ 2 ] = XEXP ( x , 1 ) ; operands [ 3 ] = x ; return compute_logical_op_length ( GET_MODE ( x ) , AND , operands , NULL ) / 2 ; } </s>


<s> static unsigned int h8300_asm_insn_count ( const char * templ ) { unsigned int count = 1 ; for ( ; * templ ; templ ++ ) if ( * templ == '\n' ) count ++ ; return count ; } </s>

Count the number of assembly instructions in a string TEMPLATE .


<s> static unsigned int h8300_binary_length ( rtx_insn * insn , const h8300_length_table * table ) { rtx set ; rtx pattern ; if ( GET_CODE ( insn ) != INSN ) gcc_unreachable ( ) ; pattern = PATTERN ( insn ) ; if ( GET_CODE ( pattern ) == PARALLEL && GET_CODE ( XVECEXP ( pattern , 0 , 0 ) ) == SET && GET_CODE ( SET_SRC ( XVECEXP ( pattern , 0 , 0 ) ) ) == COMPARE ) set = XVECEXP ( pattern , 0 , 1 ) ; else set = single_set ( insn ) ; gcc_assert ( set ) ; if ( BINARY_P ( SET_SRC ( set ) ) ) return h8300_length_from_table ( XEXP ( SET_SRC ( set ) , 0 ) , XEXP ( SET_SRC ( set ) , 1 ) , table ) ; else { gcc_assert ( GET_RTX_CLASS ( GET_CODE ( SET_SRC ( set ) ) ) == RTX_TERNARY ) ; return h8300_length_from_table ( XEXP ( XEXP ( SET_SRC ( set ) , 1 ) , 0 ) , XEXP ( XEXP ( SET_SRC ( set ) , 1 ) , 1 ) , table ) ; } } </s>

Calculate the length of general binary instruction INSN using TABLE .


<s> static unsigned int h8300_bitfield_length ( rtx op , rtx op2 ) { enum h8300_operand_class opclass ; unsigned int size , operand_length ; if ( GET_CODE ( op ) == REG ) op = op2 ; gcc_assert ( GET_CODE ( op ) != REG ) ; size = GET_MODE_SIZE ( GET_MODE ( op ) ) ; operand_length = h8300_classify_operand ( op , size , & opclass ) ; switch ( opclass ) { case H8OP_MEM_BASE : case H8OP_MEM_ABSOLUTE : case H8OP_MEM_COMPLEX : return 4 + operand_length ; default : gcc_unreachable ( ) ; } } </s>

Likewise bitfield load and store instructions .


<s> static bool h8300_can_eliminate ( const int from ATTRIBUTE_UNUSED , const int to ) { return ( to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true ) ; } </s>

Given FROM and TO register numbers , say whether this elimination is allowed . Frame pointer elimination is automatically handled . For the h8300 , if frame pointer elimination is being done , we would like to convert ap and rp into sp , not fp . All other eliminations are valid .


<s> int h8300_can_use_return_insn_p ( void ) { return ( reload_completed && ! frame_pointer_needed && get_frame_size ( ) == 0 && compute_saved_regs ( ) == 0 ) ; } </s>

Return nonzero if we can use `` rts '' for the function currently being compiled .


<s> static unsigned int h8300_classify_operand ( rtx op , int size , enum h8300_operand_class * opclass ) { enum h8300_operand_class dummy ; if ( opclass == 0 ) opclass = & dummy ; if ( CONSTANT_P ( op ) ) { * opclass = H8OP_IMMEDIATE ; if ( size == 1 ) return 0 ; if ( TARGET_H8300SX && size == 4 && GET_CODE ( op ) == CONST_INT && IN_RANGE ( INTVAL ( op ) , 0 , 0xffff ) ) return 2 ; return size ; } else if ( GET_CODE ( op ) == MEM ) { op = XEXP ( op , 0 ) ; if ( CONSTANT_P ( op ) ) { * opclass = H8OP_MEM_ABSOLUTE ; return h8300_constant_length ( op ) ; } else if ( GET_CODE ( op ) == PLUS && CONSTANT_P ( XEXP ( op , 1 ) ) ) { * opclass = H8OP_MEM_COMPLEX ; return h8300_displacement_length ( op , size ) ; } else if ( GET_RTX_CLASS ( GET_CODE ( op ) ) == RTX_AUTOINC ) { * opclass = H8OP_MEM_COMPLEX ; return 0 ; } else if ( register_operand ( op , VOIDmode ) ) { * opclass = H8OP_MEM_BASE ; return 0 ; } } gcc_assert ( register_operand ( op , VOIDmode ) ) ; * opclass = H8OP_REGISTER ; return 0 ; } </s>

Store the class of operand OP in * CLASS and return the length of any extra operand fields . SIZE is the number of bytes in OP . CLASS can be null if only the length is needed .


<s> static void h8300_conditional_register_usage ( void ) { if ( ! TARGET_MAC ) fixed_regs [ MAC_REG ] = call_used_regs [ MAC_REG ] = 1 ; } </s>

Conditionally modify register usage based on target flags .


<s> static unsigned int h8300_constant_length ( rtx constant ) { if ( GET_CODE ( constant ) == CONST_INT && IN_RANGE ( INTVAL ( constant ) , - 0x8000 , 0x7fff ) ) return 2 ; if ( Pmode == HImode || h8300_tiny_constant_address_p ( constant ) ) return 2 ; return 4 ; } </s>

Return the size of the given address or displacement constant .


Return nonzero if the current function is an interrupt function .


<s> static unsigned int h8300_displacement_length ( rtx addr , int size ) { rtx offset ; offset = XEXP ( addr , 1 ) ; if ( register_operand ( XEXP ( addr , 0 ) , VOIDmode ) && GET_CODE ( offset ) == CONST_INT && ( INTVAL ( offset ) == size || INTVAL ( offset ) == size * 2 || INTVAL ( offset ) == size * 3 ) ) return 0 ; return h8300_constant_length ( offset ) ; } </s>

Return the size of a displacement field in address ADDR , which should have the form ( plus X constant ) . SIZE is the number of bytes being accessed .


<s> int h8300_eightbit_constant_address_p ( rtx x ) { const unsigned HOST_WIDE_INT n1 = trunc_int_for_mode ( 0xff00 , HImode ) ; const unsigned HOST_WIDE_INT n2 = trunc_int_for_mode ( 0xffff , HImode ) ; const unsigned HOST_WIDE_INT h1 = trunc_int_for_mode ( 0x00ffff00 , SImode ) ; const unsigned HOST_WIDE_INT h2 = trunc_int_for_mode ( 0x00ffffff , SImode ) ; const unsigned HOST_WIDE_INT s1 = trunc_int_for_mode ( 0xffffff00 , SImode ) ; const unsigned HOST_WIDE_INT s2 = trunc_int_for_mode ( 0xffffffff , SImode ) ; unsigned HOST_WIDE_INT addr ; if ( GET_CODE ( x ) == SYMBOL_REF ) return ( SYMBOL_REF_FLAGS ( x ) & SYMBOL_FLAG_EIGHTBIT_DATA ) != 0 ; if ( GET_CODE ( x ) == CONST && GET_CODE ( XEXP ( x , 0 ) ) == PLUS && GET_CODE ( XEXP ( XEXP ( x , 0 ) , 0 ) ) == SYMBOL_REF && ( SYMBOL_REF_FLAGS ( XEXP ( XEXP ( x , 0 ) , 0 ) ) & SYMBOL_FLAG_EIGHTBIT_DATA ) != 0 ) return 1 ; if ( GET_CODE ( x ) != CONST_INT ) return 0 ; addr = INTVAL ( x ) ; return ( 0 || ( TARGET_NORMAL_MODE && IN_RANGE ( addr , n1 , n2 ) ) || ( TARGET_H8300H && IN_RANGE ( addr , h1 , h2 ) ) || ( TARGET_H8300S && IN_RANGE ( addr , s1 , s2 ) ) ) ; } </s>

Nonzero if X is a constant address suitable as an 8-bit absolute , which is a special case of the ' R ' operand .


<s> int h8300_eightbit_data_p ( tree decl ) { tree a ; if ( TREE_CODE ( decl ) != VAR_DECL ) return 0 ; a = lookup_attribute ( "eightbit_data" , DECL_ATTRIBUTES ( decl ) ) ; return a != NULL_TREE ; } </s>

Return nonzero if DECL is a variable that 's in the eight bit data area .