<s> unsigned mmix_debugger_regno ( unsigned regno ) { regno = MMIX_OUTPUT_REGNO ( regno ) ; return regno >= 224 ? ( regno - 224 ) : ( regno + 48 ) ; } </s>


"MMIX Internal: Last named vararg would not fit in a register"


<s> void mmix_conditional_register_usage ( ) { int i ; if ( TARGET_ABI_GNU ) { static const int gnu_abi_reg_alloc_order [ ] = MMIX_GNU_ABI_REG_ALLOC_ORDER ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) reg_alloc_order [ i ] = gnu_abi_reg_alloc_order [ i ] ; for ( i = 15 ; i <= 30 ; i ++ ) call_used_regs [ i ] = 0 ; for ( i = MMIX_RESERVED_GNU_ARG_0_REGNUM ; i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS ; i ++ ) fixed_regs [ i ] = 0 ; } if ( ! TARGET_TOPLEVEL_SYMBOLS ) for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( reg_names [ i ] [ 0 ] == ':' ) reg_names [ i ] ++ ; } </s>


<s>
const
char
*
mmix_data_section_asm_op
(
)
{
return
"\t.data ! mmixal:= 8H LOC 9B"
;
}
</s>


<s> rtx mmix_eh_return_handler_rtx ( ) { return gen_rtx_REG ( Pmode , MMIX_INCOMING_RETURN_ADDRESS_REGNUM ) ; } </s>


<s> rtx mmix_eh_return_stackadj_rtx ( ) { return gen_rtx_REG ( Pmode , MMIX_EH_RETURN_STACKADJ_REGNUM ) ; } </s>


<s> void mmix_init_expanders ( ) { init_machine_status = mmix_init_machine_status ; } </s>


<s>
void
mmix_override_options
(
)
{
if
(
flag_pic
)
{
warning
(
"-f%s not supported: ignored"
,
(
flag_pic
>
1
)
"PIC"
:
"pic"
)
;
flag_pic
=
0
;
}
ggc_add_rtx_root
(
&
mmix_compare_op0
,
1
)
;
ggc_add_rtx_root
(
&
mmix_compare_op1
,
1
)
;
}
</s>


<s> void mmix_setup_frame_addresses ( ) { } </s>


<s> int mmix_starting_frame_offset ( ) { return ( - 8 + ( MMIX_CFUN_HAS_LANDING_PAD ? - 16 : ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? - 8 : 0 ) ) ) ; } </s>


<s>
void
mmix_asm_output_aligned_local
(
FILE
*
stream
,
const
char
*
name
,
int
size
,
int
align
)
{
data_section
(
)
;
ASM_OUTPUT_ALIGN
(
stream
,
exact_log2
(
align
/
BITS_PER_UNIT
)
)
;
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
"\tLOC @+%d\n"
,
size
)
;
}
</s>


<s>
static
void
mmix_asm_output_mi_thunk
(
FILE
*
stream
,
tree
fndecl
ATTRIBUTE_UNUSED
,
HOST_WIDE_INT
delta
,
HOST_WIDE_INT
vcall_offset
ATTRIBUTE_UNUSED
,
tree
func
)
{
const
char
*
regname
=
reg_names
[
MMIX_FIRST_INCOMING_ARG_REGNUM
]
;
if
(
delta
>=
0
&&
delta
<
65536
)
fprintf
(
stream
,
"\tINCL %s,%d\n"
,
regname
,
(
int
)
delta
)
;
else
if
(
delta
<
0
&&
delta
>=
255
)
fprintf
(
stream
,
"\tSUBU %s,%s,%d\n"
,
regname
,
regname
,
(
int
)
delta
)
;
else
{
mmix_output_register_setting
(
stream
,
255
,
delta
,
1
)
;
fprintf
(
stream
,
"\tADDU %s,%s,$255\n"
,
regname
,
regname
)
;
}
fprintf
(
stream
,
"\tJMP "
)
;
assemble_name
(
stream
,
XSTR
(
XEXP
(
DECL_RTL
(
func
)
,
0
)
,
0
)
)
;
fprintf
(
stream
,
"\n"
)
;
}
</s>


<s>
void
mmix_asm_output_source_filename
(
FILE
*
stream
,
const
char
*
name
)
{
fprintf
(
stream
,
"# 1 "
)
;
OUTPUT_QUOTED_STRING
(
stream
,
name
)
;
fprintf
(
stream
,
"\n"
)
;
}
</s>


<s> static bool mmix_assemble_integer ( rtx x , unsigned int size , int aligned_p ) { if ( aligned_p ) switch ( size ) { case 1 : if ( GET_CODE ( x ) != CONST_INT ) { aligned_p = 0 ; break ; } fputs ( "\tBYTE\t" , asm_out_file ) ; mmix_print_operand ( asm_out_file , x , 'B' ) ; fputc ( '\n' , asm_out_file ) ; return true ; case 2 : if ( GET_CODE ( x ) != CONST_INT ) { aligned_p = 0 ; break ; } fputs ( "\tWYDE\t" , asm_out_file ) ; mmix_print_operand ( asm_out_file , x , 'W' ) ; fputc ( '\n' , asm_out_file ) ; return true ; case 4 : if ( GET_CODE ( x ) != CONST_INT ) { aligned_p = 0 ; break ; } fputs ( "\tTETRA\t" , asm_out_file ) ; mmix_print_operand ( asm_out_file , x , 'L' ) ; fputc ( '\n' , asm_out_file ) ; return true ; case 8 : gcc_assert ( GET_CODE ( x ) != CONST_DOUBLE ) ; assemble_integer_with_op ( "\tOCTA\t" , x ) ; return true ; } return default_assemble_integer ( x , size , aligned_p ) ; } </s>

Target hook for assembling integer objects . Use mmix_print_operand for WYDE and TETRA . Use mmix_output_octa to output 8-byte CONST_DOUBLEs .


<s> void mmix_conditional_register_usage ( void ) { int i ; if ( TARGET_ABI_GNU ) { static const int gnu_abi_reg_alloc_order [ ] = MMIX_GNU_ABI_REG_ALLOC_ORDER ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) reg_alloc_order [ i ] = gnu_abi_reg_alloc_order [ i ] ; for ( i = 15 ; i <= 30 ; i ++ ) call_used_regs [ i ] = 0 ; for ( i = MMIX_RESERVED_GNU_ARG_0_REGNUM ; i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS ; i ++ ) fixed_regs [ i ] = 0 ; } if ( ! TARGET_TOPLEVEL_SYMBOLS ) for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( reg_names [ i ] [ 0 ] == ':' ) reg_names [ i ] ++ ; } </s>


<s> int mmix_constant_alignment ( tree constant ATTRIBUTE_UNUSED , int basic_align ) { if ( basic_align < 32 ) return 32 ; return basic_align ; } </s>


<s> int mmix_dbx_register_number ( int regno ) { regno = MMIX_OUTPUT_REGNO ( regno ) ; return regno >= 224 ? ( regno - 224 ) : ( regno + 48 ) ; } </s>


<s> rtx mmix_dynamic_chain_address ( rtx frame ) { return plus_constant ( frame , - 8 ) ; } </s>


<s> static void mmix_emit_sp_add ( HOST_WIDE_INT offset ) { rtx insn ; if ( offset < 0 ) { if ( offset > - 255 ) insn = emit_insn ( gen_adddi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( offset ) ) ) ; else { rtx tmpr = gen_rtx_REG ( DImode , 255 ) ; RTX_FRAME_RELATED_P ( emit_move_insn ( tmpr , GEN_INT ( offset ) ) ) = 1 ; insn = emit_insn ( gen_adddi3 ( stack_pointer_rtx , stack_pointer_rtx , tmpr ) ) ; } RTX_FRAME_RELATED_P ( insn ) = 1 ; } else { if ( CONST_OK_FOR_LETTER_P ( offset , 'L' ) ) emit_insn ( gen_adddi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( offset ) ) ) ; else { rtx tmpr = gen_rtx_REG ( DImode , 255 ) ; emit_move_insn ( tmpr , GEN_INT ( offset ) ) ; insn = emit_insn ( gen_adddi3 ( stack_pointer_rtx , stack_pointer_rtx , tmpr ) ) ; } } } </s>


<s> static void mmix_encode_section_info ( tree decl , rtx rtl , int first ) { if ( ( TREE_CODE ( decl ) == VAR_DECL && ( DECL_EXTERNAL ( decl ) || TREE_PUBLIC ( decl ) ) ) || ( TREE_CODE ( decl ) == FUNCTION_DECL && TREE_PUBLIC ( decl ) ) ) ; else if ( first && DECL_P ( decl ) ) { const char * str = XSTR ( XEXP ( rtl , 0 ) , 0 ) ; int len = strlen ( str ) ; char * newstr ; newstr = ( char * ) ggc_alloc_string ( "" , len + 1 ) ; strcpy ( newstr + 1 , str ) ; * newstr = '@' ; XSTR ( XEXP ( rtl , 0 ) , 0 ) = newstr ; } if ( TREE_CODE ( decl ) == FUNCTION_DECL || TREE_CONSTANT ( decl ) || ( TREE_CODE ( decl ) == VAR_DECL && TREE_READONLY ( decl ) && ! TREE_SIDE_EFFECTS ( decl ) && ( ! DECL_INITIAL ( decl ) || TREE_CONSTANT ( DECL_INITIAL ( decl ) ) ) ) ) SYMBOL_REF_FLAG ( XEXP ( rtl , 0 ) ) = 1 ; } </s>


"stack frame not a multiple of octabyte: %wd"

Expands the function epilogue into RTX .


<s> int mmix_extra_constraint ( rtx x , int c , int strict ) { HOST_WIDEST_INT value ; if ( c == 'U' ) return strict ? strict_memory_address_p ( Pmode , x ) : memory_address_p ( Pmode , x ) ; if ( c == 'R' ) return GET_CODE ( x ) != CONST_INT && GET_CODE ( x ) != CONST_DOUBLE && mmix_constant_address_p ( x ) && ( ! TARGET_BASE_ADDRESSES || ( GET_CODE ( x ) == LABEL_REF || ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_FLAG ( x ) ) ) ) ; if ( GET_CODE ( x ) != CONST_DOUBLE || GET_MODE ( x ) != VOIDmode ) return 0 ; value = mmix_intval ( x ) ; if ( c == 'S' ) return mmix_shiftable_wyde_value ( value ) ; else if ( c == 'T' ) return mmix_shiftable_wyde_value ( ~ value ) ; return 0 ; } </s>

EXTRA_CONSTRAINT . We need this since our constants are not always expressible as CONST_INT : s , but rather often as CONST_DOUBLE : s .


<s> static void mmix_file_end ( void ) { data_section ( ) ; } </s>


<s>
static
void
mmix_file_start
(
void
)
{
default_file_start
(
)
;
fputs
(
"! mmixal:= 8H LOC Data_Section\n"
,
asm_out_file
)
;
text_section
(
)
;
}
</s>

TARGET_ASM_FILE_START . We just emit a little comment for the time being .


<s> rtx mmix_function_arg ( const CUMULATIVE_ARGS * argsp , enum machine_mode mode , tree type , int named ATTRIBUTE_UNUSED , int incoming ) { if ( type == void_type_node ) return ( argsp -> regs < MMIX_MAX_ARGS_IN_REGS ) ? gen_rtx_REG ( mode , ( incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM ) + argsp -> regs ) : NULL_RTX ; return ( argsp -> regs < MMIX_MAX_ARGS_IN_REGS && ! targetm . calls . must_pass_in_stack ( mode , type ) && ( GET_MODE_BITSIZE ( mode ) <= 64 || argsp -> lib || TARGET_LIBFUNC ) ) ? gen_rtx_REG ( mode , ( incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM ) + argsp -> regs ) : NULL_RTX ; } </s>

Return an rtx for a function argument to go in a register , and 0 for one that must go on stack .


"too large function value type, needs %d registers,\ have only %d registers for this"


<s> int mmix_function_value_regno_p ( int regno ) { return regno == MMIX_RETURN_VALUE_REGNUM ; } </s>


<s> rtx mmix_gen_compare_reg ( RTX_CODE code , rtx x , rtx y ) { enum machine_mode ccmode = SELECT_CC_MODE ( code , x , y ) ; rtx cc_reg ; enum machine_mode mode = GET_MODE ( x ) == VOIDmode ? GET_MODE ( y ) : GET_MODE_CLASS ( GET_MODE ( x ) ) == MODE_FLOAT ? DFmode : DImode ; if ( ! mmix_valid_comparison ( code , mode , x ) ) return NULL_RTX ; cc_reg = gen_reg_rtx ( ccmode ) ; if ( ! REG_P ( x ) && ! REG_P ( y ) ) x = force_reg ( mode , x ) ; if ( ! REG_P ( y ) && ( GET_CODE ( y ) != CONST_INT || ! CONST_OK_FOR_LETTER_P ( INTVAL ( y ) , 'I' ) ) ) y = force_reg ( mode , y ) ; emit_insn ( gen_rtx_SET ( VOIDmode , cc_reg , gen_rtx_COMPARE ( ccmode , x , y ) ) ) ; return cc_reg ; } </s>

X and Y are two things to compare using CODE . Emit a compare insn if possible and return the rtx for the cc-reg in the proper mode , or NULL_RTX if this is not a valid comparison .


<s> rtx mmix_get_hard_reg_initial_val ( enum machine_mode mode , int regno ) { return get_hard_reg_initial_val ( mode , regno ) ; } </s>

Wrapper for get_hard_reg_initial_val since integrate.h is n't included from insn-emit.cc .


<s> void mmix_initialize_trampoline ( rtx trampaddr , rtx fnaddr , rtx static_chain ) { emit_move_insn ( gen_rtx_MEM ( DImode , plus_constant ( trampaddr , 16 ) ) , static_chain ) ; emit_move_insn ( gen_rtx_MEM ( DImode , plus_constant ( trampaddr , 24 ) ) , fnaddr ) ; emit_insn ( gen_sync_icache ( validize_mem ( gen_rtx_MEM ( DImode , trampaddr ) ) , GEN_INT ( mmix_trampoline_size - 1 ) ) ) ; } </s>

Set the static chain and function pointer field in the trampoline . We also SYNCID here to be sure ( does n't matter in the simulator , but some day it will ) .


<s> int mmix_initial_elimination_offset ( int fromreg , int toreg ) { int regno ; int fp_sp_offset = ( get_frame_size ( ) + current_function_outgoing_args_size + 7 ) & ~ 7 ; if ( fromreg == MMIX_ARG_POINTER_REGNUM && toreg == MMIX_FRAME_POINTER_REGNUM ) return 0 ; for ( regno = MMIX_FIRST_GLOBAL_REGNUM ; regno <= 255 ; regno ++ ) if ( ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) || IS_MMIX_EH_RETURN_DATA_REG ( regno ) ) fp_sp_offset += 8 ; return fp_sp_offset + ( MMIX_CFUN_HAS_LANDING_PAD ? 16 : ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? 8 : 0 ) ) + ( fromreg == MMIX_ARG_POINTER_REGNUM ? 0 : 8 ) ; } </s>

The difference between the ( imaginary ) frame pointer and the stack pointer . Used to eliminate the frame pointer .


<s> static struct machine_function * mmix_init_machine_status ( void ) { return ggc_alloc_cleared ( sizeof ( struct machine_function ) ) ; } </s>


"MMIX Internal: This is not a constant:"

Return the bit-value for a const_int or const_double .


<s> int mmix_legitimate_address ( enum machine_mode mode ATTRIBUTE_UNUSED , rtx x , int strict_checking ) { ( ( strict_checking \ && ( REGNO ( X ) <= MMIX_LAST_GENERAL_REGISTER \ || ( reg_renumber [ REGNO ( X ) ] > 0 \ && reg_renumber [ REGNO ( X ) ] <= MMIX_LAST_GENERAL_REGISTER ) ) ) \ || ( ! strict_checking \ && ( REGNO ( X ) <= MMIX_LAST_GENERAL_REGISTER \ || REGNO ( X ) >= FIRST_PSEUDO_REGISTER \ || REGNO ( X ) == ARG_POINTER_REGNUM ) ) ) if ( REG_P ( x ) && MMIX_REG_OK ( x ) ) return 1 ; if ( GET_CODE ( x ) == PLUS ) { rtx x1 = XEXP ( x , 0 ) ; rtx x2 = XEXP ( x , 1 ) ; if ( ! REG_P ( x1 ) ) { rtx tem = x1 ; x1 = x2 ; x2 = tem ; } if ( ! REG_P ( x1 ) || ! MMIX_REG_OK ( x1 ) ) return TARGET_BASE_ADDRESSES && mmix_constant_address_p ( x ) ; if ( REG_P ( x2 ) && MMIX_REG_OK ( x2 ) ) return 1 ; if ( GET_CODE ( x2 ) == CONST_INT && CONST_OK_FOR_LETTER_P ( INTVAL ( x2 ) , 'I' ) ) return 1 ; return 0 ; } return TARGET_BASE_ADDRESSES && mmix_constant_address_p ( x ) ; } </s>

Return 1 if the address is OK , otherwise 0 . Used by GO_IF_LEGITIMATE_ADDRESS .


<s> int mmix_legitimate_constant_p ( rtx x ) { RTX_CODE code = GET_CODE ( x ) ; if ( code == CONST_INT || code == CONST_DOUBLE ) return 1 ; return CONSTANT_ADDRESS_P ( x ) ; } </s>


<s> int mmix_local_alignment ( tree type ATTRIBUTE_UNUSED , int basic_align ) { if ( basic_align < 32 ) return 32 ; return basic_align ; } </s>


<s> int mmix_local_regno ( int regno ) { return regno <= MMIX_LAST_STACK_REGISTER_REGNUM && ! call_used_regs [ regno ] ; } </s>

LOCAL_REGNO . All registers that are part of the register stack and that will be saved are local .


<s>
static
void
mmix_output_octa
(
FILE
*
stream
,
HOST_WIDEST_INT
value
,
int
do_begin_end
)
{
char
hex_format
[
sizeof
(
HOST_WIDEST_INT_PRINT_HEX
)
]
;
if
(
do_begin_end
)
fprintf
(
stream
,
"\tOCTA "
)
;
strcpy
(
hex_format
,
HOST_WIDEST_INT_PRINT_HEX
)
;
hex_format
[
0
]
=
'#'
;
hex_format
[
1
]
=
'0'
;
if
(
(
value
<
(
HOST_WIDEST_INT
)
0
&&
value
>
(
HOST_WIDEST_INT
)
10000
)
||
(
value
>=
(
HOST_WIDEST_INT
)
0
&&
value
<=
(
HOST_WIDEST_INT
)
16384
)
)
fprintf
(
stream
,
"%d"
,
(
int
)
value
)
;
else
if
(
value
>
(
HOST_WIDEST_INT
)
0
&&
value
<
(
(
HOST_WIDEST_INT
)
1
<<
31
)
*
2
)
fprintf
(
stream
,
"#%x"
,
(
unsigned
int
)
value
)
;
else
fprintf
(
stream
,
hex_format
,
value
)
;
if
(
do_begin_end
)
fprintf
(
stream
,
"\n"
)
;
}
</s>

Print a 64-bit value , optionally prefixed by assembly pseudo .


<s>
void
mmix_output_register_setting
(
FILE
*
stream
,
int
regno
,
HOST_WIDEST_INT
value
,
int
do_begin_end
)
{
if
(
do_begin_end
)
fprintf
(
stream
,
"\t"
)
;
if
(
mmix_shiftable_wyde_value
(
(
unsigned
HOST_WIDEST_INT
)
value
)
)
{
mmix_output_shiftvalue_op_from_str
(
stream
,
"SET"
,
(
unsigned
HOST_WIDEST_INT
)
value
)
;
fprintf
(
stream
,
" %s,"
,
reg_names
[
regno
]
)
;
mmix_output_shifted_value
(
stream
,
(
unsigned
HOST_WIDEST_INT
)
value
)
;
}
else
if
(
mmix_shiftable_wyde_value
(
(
unsigned
HOST_WIDEST_INT
)
value
)
)
{
mmix_output_shiftvalue_op_from_str
(
stream
,
"SET"
,
(
unsigned
HOST_WIDEST_INT
)
value
)
;
fprintf
(
stream
,
" %s,"
,
reg_names
[
regno
]
)
;
mmix_output_shifted_value
(
stream
,
(
unsigned
HOST_WIDEST_INT
)
value
)
;
fprintf
(
stream
,
"\n\tNEGU %s,0,%s"
,
reg_names
[
regno
]
,
reg_names
[
regno
]
)
;
}
else
if
(
mmix_shiftable_wyde_value
(
~
(
unsigned
HOST_WIDEST_INT
)
value
)
)
{
mmix_output_shiftvalue_op_from_str
(
stream
,
"SET"
,
~
(
unsigned
HOST_WIDEST_INT
)
value
)
;
fprintf
(
stream
,
" %s,"
,
reg_names
[
regno
]
)
;
mmix_output_shifted_value
(
stream
,
~
(
unsigned
HOST_WIDEST_INT
)
value
)
;
fprintf
(
stream
,
"\n\tNOR %s,%s,0"
,
reg_names
[
regno
]
,
reg_names
[
regno
]
)
;
}
else
{
static
const
char
*
const
higher_parts
[
]
=
{
"L"
,
"ML"
,
"MH"
,
"H"
}
;
const
char
*
op
=
"SET"
;
const
char
*
line_begin
=
""
;
int
insns
=
0
;
int
i
;
HOST_WIDEST_INT
tmpvalue
=
value
;
for
(
i
=
0
;
i
<
4
&&
tmpvalue
!=
0
;
i
++
)
{
if
(
tmpvalue
&
65535
)
insns
++
;
tmpvalue
>>=
16
;
}
if
(
TARGET_BASE_ADDRESSES
&&
insns
==
3
)
{
fprintf
(
stream
,
"LDA %s,"
,
reg_names
[
regno
]
)
;
mmix_output_octa
(
stream
,
value
,
0
)
;
}
else
{
for
(
i
=
0
;
i
<
4
&&
value
!=
0
;
i
++
)
{
if
(
value
&
65535
)
{
fprintf
(
stream
,
"%s%s%s %s,#%x"
,
line_begin
,
op
,
higher_parts
[
i
]
,
reg_names
[
regno
]
,
(
int
)
(
value
&
65535
)
)
;
op
=
"INC"
;
line_begin
=
"\n\t"
;
}
value
>>=
16
;
}
}
}
if
(
do_begin_end
)
fprintf
(
stream
,
"\n"
)
;
}
</s>

Output an optimal sequence for setting a register to a specific constant . Used in an alternative for const_ints in movdi , and when using large stack-frame offsets . Use do_begin_end to say if a line-starting TAB and newline before the first insn and after the last insn is wanted .


"MMIX Internal: %s is not a shiftable int"

Print the presumed shiftable wyde argument shifted into place ( to be output with an operand ) .


Print operator suitable for doing something with a shiftable wyde . The type of operator is passed as an asm output modifier .


<s>
void
mmix_override_options
(
void
)
{
if
(
flag_pic
)
{
warning
(
0
,
"-f%s not supported: ignored"
,
(
flag_pic
>
1
)
"PIC"
:
"pic"
)
;
flag_pic
=
0
;
}
}
</s>


<s> static bool mmix_pass_by_reference ( const CUMULATIVE_ARGS * argsp , enum machine_mode mode , tree type , bool named ATTRIBUTE_UNUSED ) { if ( targetm . calls . must_pass_in_stack ( mode , type ) ) return true ; if ( MMIX_FUNCTION_ARG_SIZE ( mode , type ) > 8 && ! TARGET_LIBFUNC && ( ! argsp || ! argsp -> lib ) ) return true ; return false ; } </s>

Returns nonzero for everything that goes by reference , 0 for everything that goes by value .


<s> enum reg_class mmix_preferred_output_reload_class ( rtx x ATTRIBUTE_UNUSED , enum reg_class class ) { return GET_CODE ( x ) == MOD && GET_MODE ( x ) == DImode ? REMAINDER_REG : class ; } </s>

PREFERRED_OUTPUT_RELOAD_CLASS . We need to extend the reload class of REMAINDER_REG and HIMULT_REG .


<s> enum reg_class mmix_preferred_reload_class ( rtx x ATTRIBUTE_UNUSED , enum reg_class class ) { return GET_CODE ( x ) == MOD && GET_MODE ( x ) == DImode ? REMAINDER_REG : class ; } </s>

PREFERRED_RELOAD_CLASS . We need to extend the reload class of REMAINDER_REG and HIMULT_REG .


"MMIX Internal: This is not a recognized address"


<s> int mmix_print_operand_punct_valid_p ( int code ATTRIBUTE_UNUSED ) { return code == '+' || code == '.' ; } </s>


<s> int mmix_register_move_cost ( enum machine_mode mode ATTRIBUTE_UNUSED , enum reg_class from , enum reg_class to ) { return ( from == GENERAL_REGS && from == to ) ? 2 : 3 ; } </s>


<s> static void mmix_reorg ( void ) { int regno ; for ( regno = MMIX_LAST_STACK_REGISTER_REGNUM ; regno >= 0 ; regno -- ) if ( ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) || ( regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed ) ) break ; if ( ! TARGET_ABI_GNU && regno < current_function_args_info . regs - 1 ) { regno = current_function_args_info . regs - 1 ; if ( regno > MMIX_RETURN_VALUE_REGNUM - 1 ) regno = MMIX_RETURN_VALUE_REGNUM - 1 ; } cfun -> machine -> highest_saved_stack_register = regno ; } </s>

Implement TARGET_MACHINE_DEPENDENT_REORG . No actual rearrangements done here ; just virtually by calculating the highest saved stack register number used to modify the register numbers at output time .


<s> rtx mmix_return_addr_rtx ( int count , rtx frame ATTRIBUTE_UNUSED ) { return count == 0 ? ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? validize_mem ( gen_rtx_MEM ( Pmode , plus_constant ( frame_pointer_rtx , - 16 ) ) ) : get_hard_reg_initial_val ( Pmode , MMIX_INCOMING_RETURN_ADDRESS_REGNUM ) ) : NULL_RTX ; } </s>


<s> int mmix_reversible_cc_mode ( enum machine_mode mode ) { return mode != CC_FPmode ; } </s>


<s> static bool mmix_rtx_costs ( rtx x ATTRIBUTE_UNUSED , int code ATTRIBUTE_UNUSED , int outer_code ATTRIBUTE_UNUSED , int * total ATTRIBUTE_UNUSED ) { return false ; } </s>


<s> enum machine_mode mmix_select_cc_mode ( RTX_CODE op , rtx x , rtx y ATTRIBUTE_UNUSED ) { if ( GET_MODE_CLASS ( GET_MODE ( x ) ) == MODE_FLOAT ) { if ( op == ORDERED || op == UNORDERED || op == UNGE || op == UNGT || op == UNLE || op == UNLT ) return CC_FUNmode ; if ( op == EQ || op == NE ) return CC_FPEQmode ; return CC_FPmode ; } if ( op == GTU || op == LTU || op == GEU || op == LEU ) return CC_UNSmode ; return CCmode ; } </s>


"MMIX Internal: Last named vararg would not fit in a register"


<s> int mmix_shiftable_wyde_value ( unsigned HOST_WIDEST_INT value ) { int i ; int has_candidate = 0 ; for ( i = 0 ; i < 4 ; i ++ ) { if ( value & 65535 ) { if ( has_candidate ) return 0 ; else has_candidate = 1 ; } value >>= 16 ; } return 1 ; } </s>

Return 1 if value is 0 .. 65535 * 2 * * ( 16 * N ) for N=0 .. 3. else return 0 .


<s> int mmix_starting_frame_offset ( void ) { return ( - 8 + ( MMIX_CFUN_HAS_LANDING_PAD ? - 16 : ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? - 8 : 0 ) ) ) ; } </s>


<s> static void mmix_target_asm_function_epilogue ( FILE * stream , HOST_WIDE_INT locals_size ATTRIBUTE_UNUSED ) { fputc ( '\n' , stream ) ; } </s>


<s>
void
mmix_trampoline_template
(
FILE
*
stream
)
{
fprintf
(
stream
,
"\tGETA $255,1F\n\t"
)
;
fprintf
(
stream
,
"LDOU %s,$255,0\n\t"
,
reg_names
[
MMIX_STATIC_CHAIN_REGNUM
]
)
;
fprintf
(
stream
,
"LDOU $255,$255,8\n\t"
)
;
fprintf
(
stream
,
"GO $255,$255,0\n"
)
;
fprintf
(
stream
,
"1H\tOCTA 0\n\t"
)
;
fprintf
(
stream
,
"OCTA 0\n"
)
;
}
</s>


<s> int mmix_use_simple_return ( void ) { int regno ; int stack_space_to_allocate = ( current_function_outgoing_args_size + current_function_pretend_args_size + get_frame_size ( ) + 7 ) & ~ 7 ; if ( ! TARGET_USE_RETURN_INSN || ! reload_completed ) return 0 ; for ( regno = 255 ; regno >= MMIX_FIRST_GLOBAL_REGNUM ; regno -- ) if ( ( ( ( regno != MMIX_FRAME_POINTER_REGNUM || ! frame_pointer_needed ) && regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) ) || IS_MMIX_EH_RETURN_DATA_REG ( regno ) ) return 0 ; if ( frame_pointer_needed ) stack_space_to_allocate += 8 ; if ( MMIX_CFUN_HAS_LANDING_PAD ) stack_space_to_allocate += 16 ; else if ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ) stack_space_to_allocate += 8 ; return stack_space_to_allocate == 0 ; } </s>

Nonzero when the function epilogue is simple enough that a single `` POP % d,0 '' should be used even within the function .


<s> int mmix_valid_comparison ( RTX_CODE code , enum machine_mode mode , rtx op ) { if ( mode == VOIDmode && op != NULL_RTX ) mode = GET_MODE ( op ) ; if ( mode == CCmode || mode == CC_UNSmode || mode == DImode ) return 1 ; if ( ( mode == CC_FPmode || mode == DFmode ) && ( code == GT || code == LT ) ) return 1 ; if ( ( mode == CC_FPEQmode || mode == DFmode ) && ( code == EQ || code == NE ) ) return 1 ; if ( ( mode == CC_FUNmode || mode == DFmode ) && ( code == ORDERED || code == UNORDERED ) ) return 1 ; return 0 ; } </s>

Returns zero if code and mode is not a valid condition from a compare-type insn . Nonzero if it is . The parameter op , if non-NULL , is the comparison of mode is CC-somethingmode .


"stack frame not a multiple of octabyte: %wd"

Expands the function epilogue into RTX .


<s> static rtx mmix_function_arg ( cumulative_args_t argsp , machine_mode mode , const_tree type , bool named ) { return mmix_function_arg_1 ( argsp , mode , type , named , false ) ; } </s>

Return an rtx for a function argument to go in a register , and 0 for one that must go on stack .


<s> static rtx mmix_function_arg_1 ( const cumulative_args_t argsp_v , machine_mode mode , const_tree type , bool named ATTRIBUTE_UNUSED , bool incoming ) { CUMULATIVE_ARGS * argsp = get_cumulative_args ( argsp_v ) ; if ( type == void_type_node ) return ( argsp -> regs < MMIX_MAX_ARGS_IN_REGS ) ? gen_rtx_REG ( mode , ( incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM ) + argsp -> regs ) : NULL_RTX ; return ( argsp -> regs < MMIX_MAX_ARGS_IN_REGS && ! targetm . calls . must_pass_in_stack ( mode , type ) && ( GET_MODE_BITSIZE ( mode ) <= 64 || argsp -> lib || TARGET_LIBFUNC ) ) ? gen_rtx_REG ( mode , ( incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM ) + argsp -> regs ) : NULL_RTX ; } </s>

Helper function for mmix_function_arg and mmix_function_incoming_arg .


<s> int mmix_initial_elimination_offset ( int fromreg , int toreg ) { int regno ; int fp_sp_offset = ( get_frame_size ( ) + crtl -> outgoing_args_size + 7 ) & ~ 7 ; if ( fromreg == MMIX_ARG_POINTER_REGNUM && toreg == MMIX_FRAME_POINTER_REGNUM ) return 0 ; for ( regno = MMIX_FIRST_GLOBAL_REGNUM ; regno <= 255 ; regno ++ ) if ( ( df_regs_ever_live_p ( regno ) && ! call_used_regs [ regno ] ) || IS_MMIX_EH_RETURN_DATA_REG ( regno ) ) fp_sp_offset += 8 ; return fp_sp_offset + ( MMIX_CFUN_HAS_LANDING_PAD ? 16 : ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? 8 : 0 ) ) + ( fromreg == MMIX_ARG_POINTER_REGNUM ? 0 : 8 ) ; } </s>

The difference between the ( imaginary ) frame pointer and the stack pointer . Used to eliminate the frame pointer .


"MMIX Internal: This is not a constant:"

Return the bit-value for a const_int or const_double .


<s>
static
void
mmix_option_override
(
void
)
{
if
(
flag_pic
)
{
warning
(
0
,
"-f%s not supported: ignored"
,
(
flag_pic
>
1
)
"PIC"
:
"pic"
)
;
flag_pic
=
0
;
}
}
</s>


<s>
static
void
mmix_output_octa
(
FILE
*
stream
,
int64_t
value
,
int
do_begin_end
)
{
if
(
do_begin_end
)
fprintf
(
stream
,
"\tOCTA "
)
;
if
(
(
value
<
(
int64_t
)
0
&&
value
>
(
int64_t
)
10000
)
||
(
value
>=
(
int64_t
)
0
&&
value
<=
(
int64_t
)
16384
)
)
fprintf
(
stream
,
"%d"
,
(
int
)
value
)
;
else
if
(
value
>
(
int64_t
)
0
&&
value
<
(
(
int64_t
)
1
<<
31
)
*
2
)
fprintf
(
stream
,
"#%x"
,
(
unsigned
int
)
value
)
;
else
if
(
sizeof
(
HOST_WIDE_INT
)
==
sizeof
(
int64_t
)
)
fprintf
(
stream
,
"#"
HOST_WIDE_INT_PRINT_HEX_PURE
,
(
HOST_WIDE_INT
)
value
)
;
else
fprintf
(
stream
,
"%"
PRIu64
,
value
)
;
if
(
do_begin_end
)
fprintf
(
stream
,
"\n"
)
;
}
</s>


<s>
void
mmix_output_register_setting
(
FILE
*
stream
,
int
regno
,
int64_t
value
,
int
do_begin_end
)
{
if
(
do_begin_end
)
fprintf
(
stream
,
"\t"
)
;
if
(
insn_const_int_ok_for_constraint
(
value
,
CONSTRAINT_K
)
)
fprintf
(
stream
,
"NEGU %s,0,%"
PRId64
,
reg_names
[
regno
]
,
value
)
;
else
if
(
mmix_shiftable_wyde_value
(
(
uint64_t
)
value
)
)
{
mmix_output_shiftvalue_op_from_str
(
stream
,
"SET"
,
(
uint64_t
)
value
)
;
fprintf
(
stream
,
" %s,"
,
reg_names
[
regno
]
)
;
mmix_output_shifted_value
(
stream
,
(
uint64_t
)
value
)
;
}
else
if
(
mmix_shiftable_wyde_value
(
(
uint64_t
)
value
)
)
{
mmix_output_shiftvalue_op_from_str
(
stream
,
"SET"
,
(
uint64_t
)
value
)
;
fprintf
(
stream
,
" %s,"
,
reg_names
[
regno
]
)
;
mmix_output_shifted_value
(
stream
,
(
uint64_t
)
value
)
;
fprintf
(
stream
,
"\n\tNEGU %s,0,%s"
,
reg_names
[
regno
]
,
reg_names
[
regno
]
)
;
}
else
if
(
mmix_shiftable_wyde_value
(
~
(
uint64_t
)
value
)
)
{
mmix_output_shiftvalue_op_from_str
(
stream
,
"SET"
,
~
(
uint64_t
)
value
)
;
fprintf
(
stream
,
" %s,"
,
reg_names
[
regno
]
)
;
mmix_output_shifted_value
(
stream
,
~
(
uint64_t
)
value
)
;
fprintf
(
stream
,
"\n\tNOR %s,%s,0"
,
reg_names
[
regno
]
,
reg_names
[
regno
]
)
;
}
else
{
static
const
char
*
const
higher_parts
[
]
=
{
"L"
,
"ML"
,
"MH"
,
"H"
}
;
const
char
*
op
=
"SET"
;
const
char
*
line_begin
=
""
;
int
insns
=
0
;
int
i
;
int64_t
tmpvalue
=
value
;
for
(
i
=
0
;
i
<
4
&&
tmpvalue
!=
0
;
i
++
)
{
if
(
tmpvalue
&
65535
)
insns
++
;
tmpvalue
>>=
16
;
}
if
(
TARGET_BASE_ADDRESSES
&&
insns
==
3
)
{
fprintf
(
stream
,
"LDA %s,"
,
reg_names
[
regno
]
)
;
mmix_output_octa
(
stream
,
value
,
0
)
;
}
else
{
for
(
i
=
0
;
i
<
4
&&
value
!=
0
;
i
++
)
{
if
(
value
&
65535
)
{
fprintf
(
stream
,
"%s%s%s %s,#%x"
,
line_begin
,
op
,
higher_parts
[
i
]
,
reg_names
[
regno
]
,
(
int
)
(
value
&
65535
)
)
;
op
=
"INC"
;
line_begin
=
"\n\t"
;
}
value
>>=
16
;
}
}
}
if
(
do_begin_end
)
fprintf
(
stream
,
"\n"
)
;
}
</s>


"MMIX Internal: %s is not a shiftable int"


<s> static bool mmix_pass_by_reference ( cumulative_args_t argsp_v , machine_mode mode , const_tree type , bool named ATTRIBUTE_UNUSED ) { CUMULATIVE_ARGS * argsp = get_cumulative_args ( argsp_v ) ; if ( targetm . calls . must_pass_in_stack ( mode , type ) ) return true ; if ( MMIX_FUNCTION_ARG_SIZE ( mode , type ) > 8 && ! TARGET_LIBFUNC && ( ! argsp || ! argsp -> lib ) ) return true ; return false ; } </s>


"MMIX Internal: This is not a recognized address"


<s> static void mmix_reorg ( void ) { int regno ; for ( regno = MMIX_LAST_STACK_REGISTER_REGNUM ; regno >= 0 ; regno -- ) if ( ( df_regs_ever_live_p ( regno ) && ! call_used_regs [ regno ] ) || ( regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed ) ) break ; if ( ! TARGET_ABI_GNU && regno < crtl -> args . info . regs - 1 ) { regno = crtl -> args . info . regs - 1 ; if ( regno > MMIX_RETURN_VALUE_REGNUM - 1 ) regno = MMIX_RETURN_VALUE_REGNUM - 1 ; } cfun -> machine -> highest_saved_stack_register = regno ; } </s>


<s> static bool mmix_rtx_costs ( rtx x ATTRIBUTE_UNUSED , int code ATTRIBUTE_UNUSED , int outer_code ATTRIBUTE_UNUSED , int opno ATTRIBUTE_UNUSED , int * total ATTRIBUTE_UNUSED , bool speed ATTRIBUTE_UNUSED ) { return false ; } </s>


"MMIX Internal: Last named vararg would not fit in a register"


<s> int mmix_use_simple_return ( void ) { int regno ; int stack_space_to_allocate = ( crtl -> outgoing_args_size + crtl -> args . pretend_args_size + get_frame_size ( ) + 7 ) & ~ 7 ; if ( ! TARGET_USE_RETURN_INSN || ! reload_completed ) return 0 ; for ( regno = 255 ; regno >= MMIX_FIRST_GLOBAL_REGNUM ; regno -- ) if ( ( ( ( regno != MMIX_FRAME_POINTER_REGNUM || ! frame_pointer_needed ) && df_regs_ever_live_p ( regno ) && ! call_used_regs [ regno ] ) ) || IS_MMIX_EH_RETURN_DATA_REG ( regno ) ) return 0 ; if ( frame_pointer_needed ) stack_space_to_allocate += 8 ; if ( MMIX_CFUN_HAS_LANDING_PAD ) stack_space_to_allocate += 16 ; else if ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ) stack_space_to_allocate += 8 ; return stack_space_to_allocate == 0 ; } </s>


<s>
void
mmix_asm_output_addr_diff_elt
(
FILE
*
stream
,
rtx
body
ATTRIBUTE_UNUSED
,
int
value
,
int
rel
)
{
fprintf
(
stream
,
"\tTETRA L%d-L%d\n"
,
value
,
rel
)
;
}
</s>


<s>
void
mmix_asm_output_addr_vec_elt
(
FILE
*
stream
,
int
value
)
{
fprintf
(
stream
,
"\tOCTA L:%d\n"
,
value
)
;
}
</s>


<s>
void
mmix_asm_output_align
(
FILE
*
stream
,
int
power
)
{
fprintf
(
stream
,
"\t.p2align %d\n"
,
power
)
;
fprintf
(
stream
,
"\tLOC @+(%d-@)&%d\n"
,
1
<<
power
,
(
1
<<
power
)
1
)
;
}
</s>


<s>
void
mmix_asm_output_aligned_common
(
FILE
*
stream
,
const
char
*
name
,
int
size
,
int
align
)
{
fprintf
(
stream
,
"\t.comm\t"
)
;
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
",%u,%u ! mmixal-incompatible COMMON\n"
,
size
,
align
/
BITS_PER_UNIT
)
;
}
</s>

mmix
"\t.comm\t"
",%u,%u ! mmixal-incompatible COMMON\n"


<s>
void
mmix_asm_output_aligned_local
(
FILE
*
stream
,
const
char
*
name
,
int
size
,
int
align
)
{
switch_to_section
(
data_section
)
;
ASM_OUTPUT_ALIGN
(
stream
,
exact_log2
(
align
/
BITS_PER_UNIT
)
)
;
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
"\tLOC @+%d\n"
,
size
)
;
}
</s>


<s>
void
mmix_asm_output_ascii
(
FILE
*
stream
,
const
char
*
string
,
int
length
)
{
while
(
length
>
0
)
{
int
chunk_size
=
length
>
60
60
:
length
;
fprintf
(
stream
,
"\tBYTE "
)
;
mmix_output_quoted_string
(
stream
,
string
,
chunk_size
)
;
string
+=
chunk_size
;
length
-=
chunk_size
;
fprintf
(
stream
,
"\n"
)
;
}
}
</s>


<s>
void
mmix_asm_output_def
(
FILE
*
stream
,
const
char
*
name
,
const
char
*
value
)
{
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
"\tIS "
)
;
assemble_name
(
stream
,
value
)
;
fputc
(
'\n'
,
stream
)
;
}
</s>


<s>
void
mmix_asm_output_internal_label
(
FILE
*
stream
,
const
char
*
name
)
{
assemble_name_raw
(
stream
,
name
)
;
fprintf
(
stream
,
"\tIS @\n"
)
;
}
</s>


<s>
void
mmix_asm_output_label
(
FILE
*
stream
,
const
char
*
name
)
{
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
"\tIS @\n"
)
;
}
</s>


<s> void mmix_asm_output_labelref ( FILE * stream , const char * name ) { int is_extern = 1 ; for ( ; ( * name == '@' || * name == '*' ) ; name ++ ) if ( * name == '@' ) is_extern = 0 ; asm_fprintf ( stream , "%s%U%s" , is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "" , name ) ; } </s>

ASM_OUTPUT_LABELREF . Strip GCC 's ' * ' and our own ' @ ' . No order is assumed .


<s>
static
void
mmix_asm_output_mi_thunk
(
FILE
*
stream
,
tree
thunk_fndecl
ATTRIBUTE_UNUSED
,
HOST_WIDE_INT
delta
,
HOST_WIDE_INT
vcall_offset
ATTRIBUTE_UNUSED
,
tree
func
)
{
const
char
*
regname
=
reg_names
[
MMIX_FIRST_INCOMING_ARG_REGNUM
]
;
const
char
*
fnname
=
IDENTIFIER_POINTER
(
DECL_ASSEMBLER_NAME
(
thunk_fndecl
)
)
;
assemble_start_function
(
thunk_fndecl
,
fnname
)
;
if
(
delta
>=
0
&&
delta
<
65536
)
fprintf
(
stream
,
"\tINCL %s,%d\n"
,
regname
,
(
int
)
delta
)
;
else
if
(
delta
<
0
&&
delta
>=
255
)
fprintf
(
stream
,
"\tSUBU %s,%s,%d\n"
,
regname
,
regname
,
(
int
)
delta
)
;
else
{
mmix_output_register_setting
(
stream
,
255
,
delta
,
1
)
;
fprintf
(
stream
,
"\tADDU %s,%s,$255\n"
,
regname
,
regname
)
;
}
fprintf
(
stream
,
"\tJMP "
)
;
assemble_name
(
stream
,
XSTR
(
XEXP
(
DECL_RTL
(
func
)
,
0
)
,
0
)
)
;
fprintf
(
stream
,
"\n"
)
;
assemble_end_function
(
thunk_fndecl
,
fnname
)
;
}
</s>


<s>
void
mmix_asm_output_reg_pop
(
FILE
*
stream
,
int
regno
)
{
fprintf
(
stream
,
"\tLDOU %s,%s,0\n\tINCL %s,8\n"
,
reg_names
[
MMIX_OUTPUT_REGNO
(
regno
)
]
,
reg_names
[
MMIX_STACK_POINTER_REGNUM
]
,
reg_names
[
MMIX_STACK_POINTER_REGNUM
]
)
;
}
</s>


<s>
void
mmix_asm_output_reg_push
(
FILE
*
stream
,
int
regno
)
{
fprintf
(
stream
,
"\tSUBU %s,%s,8\n\tSTOU %s,%s,0\n"
,
reg_names
[
MMIX_STACK_POINTER_REGNUM
]
,
reg_names
[
MMIX_STACK_POINTER_REGNUM
]
,
reg_names
[
MMIX_OUTPUT_REGNO
(
regno
)
]
,
reg_names
[
MMIX_STACK_POINTER_REGNUM
]
)
;
}
</s>


<s>
void
mmix_asm_output_skip
(
FILE
*
stream
,
int
nbytes
)
{
fprintf
(
stream
,
"\tLOC @+%d\n"
,
nbytes
)
;
}
</s>


<s>
static
void
mmix_asm_output_source_filename
(
FILE
*
stream
,
const
char
*
name
)
{
fprintf
(
stream
,
"# 1 "
)
;
OUTPUT_QUOTED_STRING
(
stream
,
name
)
;
fprintf
(
stream
,
"\n"
)
;
}
</s>


<s> int mmix_asm_preferred_eh_data_format ( int code ATTRIBUTE_UNUSED , int global ATTRIBUTE_UNUSED ) { return DW_EH_PE_absptr ; } </s>


<s>
static
void
mmix_asm_trampoline_template
(
FILE
*
stream
)
{
fprintf
(
stream
,
"\tGETA $255,1F\n\t"
)
;
fprintf
(
stream
,
"LDOU %s,$255,0\n\t"
,
reg_names
[
MMIX_STATIC_CHAIN_REGNUM
]
)
;
fprintf
(
stream
,
"LDOU $255,$255,8\n\t"
)
;
fprintf
(
stream
,
"GO $255,$255,0\n"
)
;
fprintf
(
stream
,
"1H\tOCTA 0\n\t"
)
;
fprintf
(
stream
,
"OCTA 0\n"
)
;
}
</s>


<s> static bool mmix_assemble_integer ( rtx x , unsigned int size , int aligned_p ) { if ( aligned_p ) switch ( size ) { case 1 : if ( GET_CODE ( x ) != CONST_INT ) { assemble_integer_with_op ( "\t.byte\t" , x ) ; return true ; } fputs ( "\tBYTE\t" , asm_out_file ) ; mmix_print_operand ( asm_out_file , x , 'B' ) ; fputc ( '\n' , asm_out_file ) ; return true ; case 2 : if ( GET_CODE ( x ) != CONST_INT ) { aligned_p = 0 ; break ; } fputs ( "\tWYDE\t" , asm_out_file ) ; mmix_print_operand ( asm_out_file , x , 'W' ) ; fputc ( '\n' , asm_out_file ) ; return true ; case 4 : if ( GET_CODE ( x ) != CONST_INT ) { aligned_p = 0 ; break ; } fputs ( "\tTETRA\t" , asm_out_file ) ; mmix_print_operand ( asm_out_file , x , 'L' ) ; fputc ( '\n' , asm_out_file ) ; return true ; case 8 : gcc_assert ( GET_CODE ( x ) != CONST_DOUBLE ) ; assemble_integer_with_op ( "\tOCTA\t" , x ) ; return true ; } return default_assemble_integer ( x , size , aligned_p ) ; } </s>

Target hook for assembling integer objects . Use mmix_print_operand for WYDE and TETRA . Use mmix_output_octa to output 8-byte CONST_DOUBLEs .


<s> static void mmix_conditional_register_usage ( void ) { int i ; if ( TARGET_ABI_GNU ) { static const int gnu_abi_reg_alloc_order [ ] = MMIX_GNU_ABI_REG_ALLOC_ORDER ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) reg_alloc_order [ i ] = gnu_abi_reg_alloc_order [ i ] ; for ( i = 15 ; i <= 30 ; i ++ ) call_used_regs [ i ] = 0 ; for ( i = MMIX_RESERVED_GNU_ARG_0_REGNUM ; i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS ; i ++ ) fixed_regs [ i ] = 0 ; } if ( ! TARGET_TOPLEVEL_SYMBOLS ) for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( reg_names [ i ] [ 0 ] == ':' ) reg_names [ i ] ++ ; } </s>


<s> int mmix_constant_address_p ( rtx x ) { RTX_CODE code = GET_CODE ( x ) ; int addend = 0 ; int constant_ok = TARGET_BASE_ADDRESSES != 0 ; switch ( code ) { case LABEL_REF : case SYMBOL_REF : return 1 ; case HIGH : return constant_ok ; case CONST_INT : addend = INTVAL ( x ) ; break ; case CONST_DOUBLE : if ( GET_MODE ( x ) != VOIDmode ) return constant_ok ; addend = CONST_DOUBLE_LOW ( x ) ; break ; case CONST : if ( GET_CODE ( XEXP ( x , 0 ) ) == PLUS ) { rtx x0 = XEXP ( XEXP ( x , 0 ) , 0 ) ; rtx x1 = XEXP ( XEXP ( x , 0 ) , 1 ) ; if ( ( GET_CODE ( x0 ) == SYMBOL_REF || GET_CODE ( x0 ) == LABEL_REF ) && ( GET_CODE ( x1 ) == CONST_INT || ( GET_CODE ( x1 ) == CONST_DOUBLE && GET_MODE ( x1 ) == VOIDmode ) ) ) addend = mmix_intval ( x1 ) ; else return constant_ok ; } else return constant_ok ; break ; default : return 0 ; } return constant_ok || ( addend & 3 ) == 0 ; } </s>

We must exclude constant addresses that have an increment that is not a multiple of four bytes because of restrictions of the GETA instruction , unless TARGET_BASE_ADDRESSES .


<s> int mmix_data_alignment ( tree type ATTRIBUTE_UNUSED , int basic_align ) { if ( basic_align < 32 ) return 32 ; return basic_align ; } </s>

DATA_ALIGNMENT . We have trouble getting the address of stuff that is located at other than 32-bit alignments ( GETA requirements ) , so try to give everything at least 32-bit alignment .


<s>
const
char
*
mmix_data_section_asm_op
(
void
)
{
return
"\t.data ! mmixal:= 8H LOC 9B"
;
}
</s>


<s> unsigned mmix_dbx_register_number ( unsigned regno ) { regno = MMIX_OUTPUT_REGNO ( regno ) ; return regno >= 224 ? ( regno - 224 ) : ( regno + 48 ) ; } </s>


<s> rtx mmix_dynamic_chain_address ( rtx frame ) { return plus_constant ( Pmode , frame , - 8 ) ; } </s>


<s> int mmix_eh_return_data_regno ( int n ) { if ( n >= 0 && n < 4 ) return MMIX_EH_RETURN_DATA_REGNO_START + n ; return INVALID_REGNUM ; } </s>


<s> rtx mmix_eh_return_handler_rtx ( void ) { return gen_rtx_REG ( Pmode , MMIX_INCOMING_RETURN_ADDRESS_REGNUM ) ; } </s>


<s> rtx mmix_eh_return_stackadj_rtx ( void ) { return gen_rtx_REG ( Pmode , MMIX_EH_RETURN_STACKADJ_REGNUM ) ; } </s>


<s> static void mmix_emit_sp_add ( HOST_WIDE_INT offset ) { rtx insn ; if ( offset < 0 ) { if ( offset > - 255 ) insn = emit_insn ( gen_adddi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( offset ) ) ) ; else { rtx tmpr = gen_rtx_REG ( DImode , 255 ) ; RTX_FRAME_RELATED_P ( emit_move_insn ( tmpr , GEN_INT ( offset ) ) ) = 1 ; insn = emit_insn ( gen_adddi3 ( stack_pointer_rtx , stack_pointer_rtx , tmpr ) ) ; } RTX_FRAME_RELATED_P ( insn ) = 1 ; } else { if ( insn_const_int_ok_for_constraint ( offset , CONSTRAINT_L ) ) emit_insn ( gen_adddi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( offset ) ) ) ; else { rtx tmpr = gen_rtx_REG ( DImode , 255 ) ; emit_move_insn ( tmpr , GEN_INT ( offset ) ) ; insn = emit_insn ( gen_adddi3 ( stack_pointer_rtx , stack_pointer_rtx , tmpr ) ) ; } } } </s>


<s> static void mmix_encode_section_info ( tree decl , rtx rtl , int first ) { if ( ( TREE_CODE ( decl ) == VAR_DECL && ( DECL_EXTERNAL ( decl ) || TREE_PUBLIC ( decl ) ) ) || ( TREE_CODE ( decl ) == FUNCTION_DECL && TREE_PUBLIC ( decl ) ) ) ; else if ( first && DECL_P ( decl ) ) { const char * str = XSTR ( XEXP ( rtl , 0 ) , 0 ) ; int len = strlen ( str ) ; char * newstr = XALLOCAVEC ( char , len + 2 ) ; newstr [ 0 ] = '@' ; strcpy ( newstr + 1 , str ) ; XSTR ( XEXP ( rtl , 0 ) , 0 ) = ggc_alloc_string ( newstr , len + 1 ) ; } if ( TREE_CODE ( decl ) == FUNCTION_DECL || TREE_CONSTANT ( decl ) || ( TREE_CODE ( decl ) == VAR_DECL && TREE_READONLY ( decl ) && ! TREE_SIDE_EFFECTS ( decl ) && ( ! DECL_INITIAL ( decl ) || TREE_CONSTANT ( DECL_INITIAL ( decl ) ) ) ) ) SYMBOL_REF_FLAG ( XEXP ( rtl , 0 ) ) = 1 ; } </s>


"stack frame not a multiple of octabyte: %wd"


<s> static void mmix_file_end ( void ) { switch_to_section ( data_section ) ; } </s>


<s>
static
void
mmix_file_start
(
void
)
{
default_file_start
(
)
;
fputs
(
"! mmixal:= 8H LOC Data_Section\n"
,
asm_out_file
)
;
switch_to_section
(
text_section
)
;
}
</s>

TARGET_ASM_FILE_START . We just emit a little comment for the time being .


<s> static rtx mmix_function_arg ( cumulative_args_t argsp , const function_arg_info & arg ) { return mmix_function_arg_1 ( argsp , arg , false ) ; } </s>


<s> static rtx mmix_function_arg_1 ( const cumulative_args_t argsp_v , const function_arg_info & arg , bool incoming ) { CUMULATIVE_ARGS * argsp = get_cumulative_args ( argsp_v ) ; machine_mode mode = arg . mode == VOIDmode ? DImode : arg . mode ; if ( arg . end_marker_p ( ) ) return ( argsp -> regs < MMIX_MAX_ARGS_IN_REGS ) ? gen_rtx_REG ( mode , ( incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM ) + argsp -> regs ) : NULL_RTX ; return ( argsp -> regs < MMIX_MAX_ARGS_IN_REGS && ! targetm . calls . must_pass_in_stack ( arg ) && ( GET_MODE_BITSIZE ( mode ) <= 64 || argsp -> lib || TARGET_LIBFUNC ) ) ? gen_rtx_REG ( mode , ( incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM ) + argsp -> regs ) : NULL_RTX ; } </s>


<s> int mmix_function_arg_regno_p ( int regno , int incoming ) { int first_arg_regnum = incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM ; return regno >= first_arg_regnum && regno < first_arg_regnum + MMIX_MAX_ARGS_IN_REGS ; } </s>

Return nonzero if regno is a register number where a parameter is passed , and 0 otherwise .


"too large function value type, needs %d registers,\ have only %d registers for this"


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


<s> rtx mmix_gen_compare_reg ( RTX_CODE code , rtx x , rtx y ) { machine_mode ccmode = SELECT_CC_MODE ( code , x , y ) ; return gen_reg_rtx ( ccmode ) ; } </s>

X and Y are two things to compare using CODE . Emit a compare insn if possible and return the rtx for the cc-reg in the proper mode , or NULL_RTX if this is not a valid comparison .


<s> rtx mmix_get_hard_reg_initial_val ( machine_mode mode , int regno ) { return get_hard_reg_initial_val ( mode , regno ) ; } </s>

Wrapper for get_hard_reg_initial_val since integrate.h is n't included from insn-emit.cc .


<s> int mmix_initial_elimination_offset ( int fromreg , int toreg ) { int regno ; int fp_sp_offset = ( get_frame_size ( ) + crtl -> outgoing_args_size + 7 ) & ~ 7 ; if ( fromreg == MMIX_ARG_POINTER_REGNUM && toreg == MMIX_FRAME_POINTER_REGNUM ) return 0 ; for ( regno = MMIX_FIRST_GLOBAL_REGNUM ; regno <= 255 ; regno ++ ) if ( ( df_regs_ever_live_p ( regno ) && ! call_used_or_fixed_reg_p ( regno ) ) || IS_MMIX_EH_RETURN_DATA_REG ( regno ) ) fp_sp_offset += 8 ; return fp_sp_offset + ( MMIX_CFUN_HAS_LANDING_PAD ? 16 : ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? 8 : 0 ) ) + ( fromreg == MMIX_ARG_POINTER_REGNUM ? 0 : 8 ) ; } </s>


<s> void mmix_init_expanders ( void ) { init_machine_status = mmix_init_machine_status ; } </s>


<s> static void mmix_init_libfuncs ( void ) { set_optab_libfunc ( ffs_optab , SImode , "__ffsdi2" ) ; } </s>

Unfortunately , by default __builtin_ffs is expanded to ffs for targets where INT_TYPE_SIZE < BITS_PER_WORD . That together with newlib since 2017-07-04 implementing ffs as __builtin_ffs leads to ( newlib ) ffs recursively calling itself . But , because of argument promotion , and with ffs we 're counting from the least bit , the libgcc equivalent for ffsl works equally well for int arguments , so just use that .


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


"MMIX Internal: This is not a constant:"


<s> bool mmix_legitimate_address_p ( machine_mode mode ATTRIBUTE_UNUSED , rtx x , bool strict_checking ) { ( ( strict_checking \ && ( REGNO ( X ) <= MMIX_LAST_GENERAL_REGISTER \ || ( reg_renumber [ REGNO ( X ) ] > 0 \ && reg_renumber [ REGNO ( X ) ] <= MMIX_LAST_GENERAL_REGISTER ) ) ) \ || ( ! strict_checking \ && ( REGNO ( X ) <= MMIX_LAST_GENERAL_REGISTER \ || REGNO ( X ) >= FIRST_PSEUDO_REGISTER \ || REGNO ( X ) == ARG_POINTER_REGNUM ) ) ) if ( REG_P ( x ) && MMIX_REG_OK ( x ) ) return 1 ; if ( GET_CODE ( x ) == PLUS ) { rtx x1 = XEXP ( x , 0 ) ; rtx x2 = XEXP ( x , 1 ) ; if ( ! REG_P ( x1 ) ) { rtx tem = x1 ; x1 = x2 ; x2 = tem ; } if ( ! REG_P ( x1 ) || ! MMIX_REG_OK ( x1 ) ) return TARGET_BASE_ADDRESSES && mmix_constant_address_p ( x ) ; if ( REG_P ( x2 ) && MMIX_REG_OK ( x2 ) ) return 1 ; if ( satisfies_constraint_I ( x2 ) ) return 1 ; return 0 ; } return TARGET_BASE_ADDRESSES && mmix_constant_address_p ( x ) ; } </s>

Return 1 if the address is OK , otherwise 0 .


<s> static bool mmix_legitimate_constant_p ( machine_mode mode ATTRIBUTE_UNUSED , rtx x ) { RTX_CODE code = GET_CODE ( x ) ; if ( code == CONST_INT || code == CONST_DOUBLE ) return 1 ; return CONSTANT_ADDRESS_P ( x ) ; } </s>


<s> static rtx mmix_libcall_value ( machine_mode mode , const_rtx fun ATTRIBUTE_UNUSED ) { return gen_rtx_REG ( mode , MMIX_RETURN_VALUE_REGNUM ) ; } </s>


<s> unsigned mmix_local_alignment ( tree type ATTRIBUTE_UNUSED , unsigned basic_align ) { if ( basic_align < 32 ) return 32 ; return basic_align ; } </s>


<s> int mmix_local_regno ( int regno ) { return ( regno <= MMIX_LAST_STACK_REGISTER_REGNUM && ! call_used_or_fixed_reg_p ( regno ) ) ; } </s>

LOCAL_REGNO . All registers that are part of the register stack and that will be saved are local .


<s> void mmix_make_decl_one_only ( tree decl ) { DECL_WEAK ( decl ) = 1 ; } </s>


<s> int mmix_opposite_regno ( int regno , int incoming ) { if ( incoming && regno == MMIX_OUTGOING_RETURN_VALUE_REGNUM ) return MMIX_RETURN_VALUE_REGNUM ; if ( ! incoming && regno == MMIX_RETURN_VALUE_REGNUM ) return MMIX_OUTGOING_RETURN_VALUE_REGNUM ; if ( ! mmix_function_arg_regno_p ( regno , incoming ) ) return regno ; return regno - ( incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM - MMIX_FIRST_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM - MMIX_FIRST_INCOMING_ARG_REGNUM ) ; } </s>

INCOMING_REGNO and OUTGOING_REGNO worker function . Those two macros must only be applied to function argument registers and the function return value register for the opposite use . FIXME : for their current use in gcc , it 'd be better with an explicit specific additional FUNCTION_INCOMING_ARG_REGNO_P a'la TARGET_FUNCTION_ARG / TARGET_FUNCTION_INCOMING_ARG instead of forcing the target to commit to a fixed mapping and for any unspecified register use . Particularly when thinking about the return-value , it is better to imagine INCOMING_REGNO and OUTGOING_REGNO as named CALLEE_TO_CALLER_REGNO and INNER_REGNO as named CALLER_TO_CALLEE_REGNO because the direction . The `` incoming '' and `` outgoing '' is from the perspective of the parameter-registers , but the same macro is ( must be , lacking an alternative like suggested above ) used to map the return-value-register from the same perspective . To make directions even more confusing , the macro MMIX_OUTGOING_RETURN_VALUE_REGNUM holds the number of the register in which to return a value , i.e . INCOMING_REGNO for the return-value- register as received from a called function ; the return-value on the way out .


<s>
static
void
mmix_option_override
(
void
)
{
if
(
flag_pic
)
{
warning
(
0
,
"%<-f%s%> not supported: ignored"
,
(
flag_pic
>
1
)
"PIC"
:
"pic"
)
;
flag_pic
=
0
;
}
if
(
flag_verbose_asm
||
flag_debug_asm
||
flag_dump_rtl_in_asm
)
{
targetm
.
asm_out
.
byte_op
=
"\t.byte\t"
;
targetm
.
asm_out
.
aligned_op
.
hi
=
"\t.short\t"
;
targetm
.
asm_out
.
aligned_op
.
si
=
"\t.long\t"
;
targetm
.
asm_out
.
aligned_op
.
di
=
"\t.dc.a\t"
;
}
}
</s>


<s>
static
void
mmix_output_octa
(
FILE
*
stream
,
int64_t
value
,
int
do_begin_end
)
{
if
(
do_begin_end
)
fprintf
(
stream
,
"\tOCTA "
)
;
if
(
(
value
<
(
int64_t
)
0
&&
value
>
(
int64_t
)
10000
)
||
(
value
>=
(
int64_t
)
0
&&
value
<=
(
int64_t
)
16384
)
)
fprintf
(
stream
,
"%d"
,
(
int
)
value
)
;
else
if
(
value
>
(
int64_t
)
0
&&
value
<
(
(
int64_t
)
1
<<
31
)
*
2
)
fprintf
(
stream
,
"#%x"
,
(
unsigned
int
)
value
)
;
else
if
(
sizeof
(
HOST_WIDE_INT
)
==
sizeof
(
int64_t
)
)
fprintf
(
stream
,
"#"
HOST_WIDE_INT_PRINT_HEX_PURE
,
(
HOST_WIDE_INT
)
value
)
;
else
fprintf
(
stream
,
"%"
PRIu64
,
value
)
;
if
(
do_begin_end
)
fprintf
(
stream
,
"\n"
)
;
}
</s>

Print a 64-bit value , optionally prefixed by assembly pseudo .


<s> void mmix_output_quoted_string ( FILE * stream , const char * string , int length ) { const char * string_end = string + length ; static const char * const unwanted_chars = "\"[]\\" ; while ( string < string_end ) { if ( * string && ( unsigned char ) * string < 128 && ! ISCNTRL ( * string ) && strchr ( unwanted_chars , * string ) == NULL ) { fputc ( '"' , stream ) ; while ( * string && ( unsigned char ) * string < 128 && ! ISCNTRL ( * string ) && strchr ( unwanted_chars , * string ) == NULL && string < string_end ) { fputc ( * string , stream ) ; string ++ ; } fputc ( '"' , stream ) ; if ( string < string_end ) fprintf ( stream , "," ) ; } if ( string < string_end ) { fprintf ( stream , "#%x" , * string & 255 ) ; string ++ ; if ( string < string_end ) fprintf ( stream , "," ) ; } } } </s>


<s>
void
mmix_output_register_setting
(
FILE
*
stream
,
int
regno
,
int64_t
value
,
int
do_begin_end
)
{
if
(
do_begin_end
)
fprintf
(
stream
,
"\t"
)
;
if
(
insn_const_int_ok_for_constraint
(
value
,
CONSTRAINT_K
)
)
fprintf
(
stream
,
"NEGU %s,0,%"
PRId64
,
reg_names
[
regno
]
,
value
)
;
else
if
(
mmix_shiftable_wyde_value
(
(
uint64_t
)
value
)
)
{
mmix_output_shiftvalue_op_from_str
(
stream
,
"SET"
,
(
uint64_t
)
value
)
;
fprintf
(
stream
,
" %s,"
,
reg_names
[
regno
]
)
;
mmix_output_shifted_value
(
stream
,
(
uint64_t
)
value
)
;
}
else
if
(
mmix_shiftable_wyde_value
(
(
uint64_t
)
value
)
)
{
mmix_output_shiftvalue_op_from_str
(
stream
,
"SET"
,
(
uint64_t
)
value
)
;
fprintf
(
stream
,
" %s,"
,
reg_names
[
regno
]
)
;
mmix_output_shifted_value
(
stream
,
(
uint64_t
)
value
)
;
fprintf
(
stream
,
"\n\tNEGU %s,0,%s"
,
reg_names
[
regno
]
,
reg_names
[
regno
]
)
;
}
else
if
(
mmix_shiftable_wyde_value
(
~
(
uint64_t
)
value
)
)
{
mmix_output_shiftvalue_op_from_str
(
stream
,
"SET"
,
~
(
uint64_t
)
value
)
;
fprintf
(
stream
,
" %s,"
,
reg_names
[
regno
]
)
;
mmix_output_shifted_value
(
stream
,
~
(
uint64_t
)
value
)
;
fprintf
(
stream
,
"\n\tNOR %s,%s,0"
,
reg_names
[
regno
]
,
reg_names
[
regno
]
)
;
}
else
{
static
const
char
*
const
higher_parts
[
]
=
{
"L"
,
"ML"
,
"MH"
,
"H"
}
;
const
char
*
op
=
"SET"
;
const
char
*
line_begin
=
""
;
int
insns
=
0
;
int
i
;
int64_t
tmpvalue
=
value
;
for
(
i
=
0
;
i
<
4
&&
tmpvalue
!=
0
;
i
++
)
{
if
(
tmpvalue
&
65535
)
insns
++
;
tmpvalue
>>=
16
;
}
if
(
TARGET_BASE_ADDRESSES
&&
insns
==
3
)
{
fprintf
(
stream
,
"LDA %s,"
,
reg_names
[
regno
]
)
;
mmix_output_octa
(
stream
,
value
,
0
)
;
}
else
{
for
(
i
=
0
;
i
<
4
&&
value
!=
0
;
i
++
)
{
if
(
value
&
65535
)
{
fprintf
(
stream
,
"%s%s%s %s,#%x"
,
line_begin
,
op
,
higher_parts
[
i
]
,
reg_names
[
regno
]
,
(
int
)
(
value
&
65535
)
)
;
op
=
"INC"
;
line_begin
=
"\n\t"
;
}
value
>>=
16
;
}
}
}
if
(
do_begin_end
)
fprintf
(
stream
,
"\n"
)
;
}
</s>

Output an optimal sequence for setting a register to a specific constant . Used in an alternative for const_ints in movdi , and when using large stack-frame offsets . Use do_begin_end to say if a line-starting TAB and newline before the first insn and after the last insn is wanted .


"MMIX Internal: %s is not a shiftable integer"

Print the presumed shiftable wyde argument shifted into place ( to be output with an operand ) .


Print operator suitable for doing something with a shiftable wyde . The type of operator is passed as an asm output modifier .


<s> static bool mmix_pass_by_reference ( cumulative_args_t argsp_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * argsp = get_cumulative_args ( argsp_v ) ; if ( targetm . calls . must_pass_in_stack ( arg ) ) return true ; if ( MMIX_FUNCTION_ARG_SIZE ( arg . mode , arg . type ) > 8 && ! TARGET_LIBFUNC && ( ! argsp || ! argsp -> lib ) ) return true ; return false ; } </s>

Returns nonzero for everything that goes by reference , 0 for everything that goes by value .


<s> static reg_class_t mmix_preferred_output_reload_class ( rtx x , reg_class_t rclass ) { return GET_CODE ( x ) == MOD && GET_MODE ( x ) == DImode ? REMAINDER_REG : rclass ; } </s>

PREFERRED_OUTPUT_RELOAD_CLASS . We need to extend the reload class of REMAINDER_REG and HIMULT_REG .


<s> static reg_class_t mmix_preferred_reload_class ( rtx x , reg_class_t rclass ) { return GET_CODE ( x ) == MOD && GET_MODE ( x ) == DImode ? REMAINDER_REG : rclass ; } </s>

PREFERRED_RELOAD_CLASS . We need to extend the reload class of REMAINDER_REG and HIMULT_REG .


"MMIX Internal: This is not a recognized address"


<s> static bool mmix_print_operand_punct_valid_p ( unsigned char code ) { return code == '+' || code == '.' || code == '!' ; } </s>


<s> machine_mode mmix_promote_function_mode ( const_tree type ATTRIBUTE_UNUSED , machine_mode mode , int * punsignedp ATTRIBUTE_UNUSED , const_tree fntype ATTRIBUTE_UNUSED , int for_return ) { if ( for_return == 1 ) return mode ; if ( GET_MODE_CLASS ( mode ) == MODE_INT && GET_MODE_SIZE ( mode ) < 8 ) return DImode ; else return mode ; } </s>

Worker function for TARGET_PROMOTE_FUNCTION_MODE .


<s> static int mmix_register_move_cost ( machine_mode mode ATTRIBUTE_UNUSED , reg_class_t from , reg_class_t to ) { return ( from == GENERAL_REGS && from == to ) ? 2 : 3 ; } </s>


<s> static void mmix_reorg ( void ) { int regno ; for ( regno = MMIX_LAST_STACK_REGISTER_REGNUM ; regno >= 0 ; regno -- ) if ( ( df_regs_ever_live_p ( regno ) && ! call_used_or_fixed_reg_p ( regno ) ) || ( regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed ) ) break ; if ( ! TARGET_ABI_GNU && regno < crtl -> args . info . regs - 1 ) { regno = crtl -> args . info . regs - 1 ; if ( regno > MMIX_RETURN_VALUE_REGNUM - 1 ) regno = MMIX_RETURN_VALUE_REGNUM - 1 ; } cfun -> machine -> highest_saved_stack_register = regno ; } </s>

Implement TARGET_MACHINE_DEPENDENT_REORG . No actual rearrangements done here ; just virtually by calculating the highest saved stack register number used to modify the register numbers at output time .


<s> rtx mmix_return_addr_rtx ( int count , rtx frame ATTRIBUTE_UNUSED ) { return count == 0 ? ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? validize_mem ( gen_rtx_MEM ( Pmode , plus_constant ( Pmode , frame_pointer_rtx , - 16 ) ) ) : get_hard_reg_initial_val ( Pmode , MMIX_INCOMING_RETURN_ADDRESS_REGNUM ) ) : NULL_RTX ; } </s>


<s> int mmix_reversible_cc_mode ( machine_mode mode ) { return mode != CC_FPmode ; } </s>


<s> static bool mmix_rtx_costs ( rtx x ATTRIBUTE_UNUSED , machine_mode mode ATTRIBUTE_UNUSED , int outer_code ATTRIBUTE_UNUSED , int opno ATTRIBUTE_UNUSED , int * total ATTRIBUTE_UNUSED , bool speed ATTRIBUTE_UNUSED ) { return false ; } </s>


<s> enum reg_class mmix_secondary_reload_class ( enum reg_class rclass , machine_mode mode ATTRIBUTE_UNUSED , rtx x ATTRIBUTE_UNUSED , int in_p ATTRIBUTE_UNUSED ) { if ( rclass == REMAINDER_REG || rclass == HIMULT_REG || rclass == SYSTEM_REGS ) return GENERAL_REGS ; return NO_REGS ; } </s>

SECONDARY_RELOAD_CLASS . We need to reload regs of REMAINDER_REG and HIMULT_REG elsewhere .


<s> machine_mode mmix_select_cc_mode ( RTX_CODE op , rtx x , rtx y ATTRIBUTE_UNUSED ) { if ( GET_MODE_CLASS ( GET_MODE ( x ) ) == MODE_FLOAT ) { if ( op == ORDERED || op == UNORDERED || op == UNGE || op == UNGT || op == UNLE || op == UNLT ) return CC_FUNmode ; if ( op == EQ || op == NE ) return CC_FPEQmode ; return CC_FPmode ; } if ( op == GTU || op == LTU || op == GEU || op == LEU ) return CC_UNSmode ; return CCmode ; } </s>


<s> void mmix_setup_frame_addresses ( void ) { } </s>


"MMIX Internal: Last named vararg would not fit in a register"


<s> int mmix_shiftable_wyde_value ( uint64_t value ) { int i ; int has_candidate = 0 ; for ( i = 0 ; i < 4 ; i ++ ) { if ( value & 65535 ) { if ( has_candidate ) return 0 ; else has_candidate = 1 ; } value >>= 16 ; } return 1 ; } </s>

Return 1 if value is 0 .. 65535 * 2 * * ( 16 * N ) for N=0 .. 3. else return 0 .


<s> static HOST_WIDE_INT mmix_starting_frame_offset ( void ) { return ( - 8 + ( MMIX_CFUN_HAS_LANDING_PAD ? - 16 : ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? - 8 : 0 ) ) ) ; } </s>


<s> static HOST_WIDE_INT mmix_static_rtx_alignment ( machine_mode mode ) { return MAX ( GET_MODE_ALIGNMENT ( mode ) , 32 ) ; } </s>


<s> static const char * mmix_strip_name_encoding ( const char * name ) { for ( ; ( * name == '@' || * name == '*' ) ; name ++ ) ; return name ; } </s>


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

Worker function for TARGET_STRUCT_VALUE_RTX .


<s> static void mmix_target_asm_function_epilogue ( FILE * stream ) { fputc ( '\n' , stream ) ; } </s>


<s> static void mmix_target_asm_function_prologue ( FILE * ) { cfun -> machine -> in_prologue = 1 ; } </s>

Emit the function prologue . For simplicity while the port is still in a flux , we do it as text rather than the now preferred RTL way , as ( define_insn `` function_prologue '' ) . FIXME : Translate to RTL and/or optimize some of the DWARF 2 stuff .


<s> static void mmix_trampoline_init ( rtx m_tramp , tree fndecl , rtx static_chain ) { rtx fnaddr = XEXP ( DECL_RTL ( fndecl ) , 0 ) ; rtx mem ; emit_block_move ( m_tramp , assemble_trampoline_template ( ) , GEN_INT ( 2 * UNITS_PER_WORD ) , BLOCK_OP_NORMAL ) ; mem = adjust_address ( m_tramp , DImode , 2 * UNITS_PER_WORD ) ; emit_move_insn ( mem , static_chain ) ; mem = adjust_address ( m_tramp , DImode , 3 * UNITS_PER_WORD ) ; emit_move_insn ( mem , fnaddr ) ; mem = adjust_address ( m_tramp , DImode , 0 ) ; emit_insn ( gen_sync_icache ( mem , GEN_INT ( TRAMPOLINE_SIZE - 1 ) ) ) ; } </s>

Set the static chain and function pointer field in the trampoline . We also SYNCID here to be sure ( does n't matter in the simulator , but some day it will ) .


<s> int mmix_use_simple_return ( void ) { int regno ; int stack_space_to_allocate = ( crtl -> outgoing_args_size + crtl -> args . pretend_args_size + get_frame_size ( ) + 7 ) & ~ 7 ; if ( ! TARGET_USE_RETURN_INSN || ! reload_completed ) return 0 ; for ( regno = 255 ; regno >= MMIX_FIRST_GLOBAL_REGNUM ; regno -- ) if ( ( ( ( regno != MMIX_FRAME_POINTER_REGNUM || ! frame_pointer_needed ) && df_regs_ever_live_p ( regno ) && ! call_used_or_fixed_reg_p ( regno ) ) ) || IS_MMIX_EH_RETURN_DATA_REG ( regno ) ) return 0 ; if ( frame_pointer_needed ) stack_space_to_allocate += 8 ; if ( MMIX_CFUN_HAS_LANDING_PAD ) stack_space_to_allocate += 16 ; else if ( MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ) stack_space_to_allocate += 8 ; return stack_space_to_allocate == 0 ; } </s>

Nonzero when the function epilogue is simple enough that a single `` POP % d,0 '' should be used even within the function .