diff options
author | John van Groningen | 2003-05-12 14:02:41 +0000 |
---|---|---|
committer | John van Groningen | 2003-05-12 14:02:41 +0000 |
commit | f5a66e7200c23c2f12ed6f1056606b003be70ea1 (patch) | |
tree | 475b6402f35f3a37f0e39aacfbc715850c3de176 /cglin.c | |
parent | cgcode.c (diff) |
cglin.c
Diffstat (limited to 'cglin.c')
-rw-r--r-- | cglin.c | 7827 |
1 files changed, 7827 insertions, 0 deletions
@@ -0,0 +1,7827 @@ +/* + File: cglin.c + Author: John van Groningen + At: University of Nijmegen +*/ + +#include <stdio.h> +#include "cgport.h" +#include "cg.h" +#include "cgconst.h" +#include "cgiconst.h" +#include "cgrconst.h" +#include "cgtypes.h" + +#include "cglin.h" + +#include "cgcalc.h" +#include "cgstack.h" + +#define g_fhighlow + +#define LOAD_X_PARAMETER_REGISTER + +#ifdef G_POWER +# define IF_G_POWER(a) a +#else +# define IF_G_POWER(a) +#endif + +/* from cgcode.c : */ + +extern struct basic_block *first_block,*last_block; +extern struct instruction *last_instruction; + +extern LABEL *index_error_label; + +int local_data_offset; + +#pragma segment Code3 + +#define S2(s,v1,v2) s.v1;s.v2 +#define S3(s,v1,v2,v3) s.v1;s.v2;s.v3 +#define S4(s,v1,v2,v3,v4) s.v1;s.v2;s.v3;s.v4 + +#define U2(s,v1,v2) s->v1;s->v2 +#define U3(s,v1,v2,v3) s->v1;s->v2;s->v3 +#define U4(s,v1,v2,v3,v4) s->v1;s->v2;s->v3;s->v4 + +IF_G_POWER(struct instruction *last_heap_pointer_update;) + +static struct instruction *i_new_instruction (int instruction_code,int arity,int arg_size) +{ + register struct instruction *instruction; + + instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+arg_size); + + U4(instruction, instruction_next=NULL, + instruction_prev=last_instruction, + instruction_icode=instruction_code, + instruction_arity=arity); + + if (last_block->block_instructions==NULL) + last_block->block_instructions=instruction; + else + last_instruction->instruction_next=instruction; + last_instruction=instruction; + + return instruction; +} + +static struct instruction *i_new_instruction1 (int instruction_code) +{ + register struct instruction *instruction; + + instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+sizeof (struct parameter)); + + U4(instruction, instruction_next=NULL, + instruction_prev=last_instruction, + instruction_icode=instruction_code, + instruction_arity=1); + + if (last_block->block_instructions==NULL) + last_block->block_instructions=instruction; + else + last_instruction->instruction_next=instruction; + last_instruction=instruction; + + return instruction; +} + +static struct instruction *i_new_instruction2 (int instruction_code) +{ + register struct instruction *instruction; + + instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+2*sizeof (struct parameter)); + + U4(instruction, instruction_next=NULL, + instruction_prev=last_instruction, + instruction_icode=instruction_code, + instruction_arity=2); + + if (last_block->block_instructions==NULL) + last_block->block_instructions=instruction; + else + last_instruction->instruction_next=instruction; + last_instruction=instruction; + + return instruction; +} + +void i_add_i_r (LONG value,int register_1) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IADD); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=value); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +void i_add_r_r (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IADD); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +#if defined (G_POWER) || defined (sparc) +static void i_addi_r_r (LONG value,int register_1,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction (IADDI,3,3*sizeof (struct parameter)); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); + + S2 (instruction->instruction_parameters[2], parameter_type=P_IMMEDIATE, + parameter_data.i=value); +} +#endif + +#if defined (M68000) || defined (G_POWER) +# if defined (M68000) + static +# endif +void i_and_i_r (LONG value,int register_1) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IAND); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=value); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} +#endif + +#ifdef M68000 +void i_bmi_l (LABEL *label) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IBMI); + + S2 (instruction->instruction_parameters[0], parameter_type=P_LABEL, + parameter_data.l=label); +} + +LONG *i_bmi_i (VOID) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IBMI); + + instruction->instruction_parameters[0].parameter_type=P_IMMEDIATE; + + return &instruction->instruction_parameters[0].parameter_data.i; +} +#endif + +#ifdef G_POWER +void i_bnep_l (LABEL *label) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (IBNEP); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_data.l=label; +} +#endif + +#if defined (sparc) || defined (I486) +void i_bne_l (LABEL *label) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (IBNE); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_data.l=label; +} +#endif + +#ifdef M68000 +static void i_bmove_pd_pd_r (int reg_1,int reg_2,int reg_3) +{ + register struct instruction *instruction; + + instruction=i_new_instruction (IBMOVE,3,3*sizeof (struct parameter)); + + instruction->instruction_parameters[0].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[0].parameter_data.i=reg_1; + + instruction->instruction_parameters[1].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[1].parameter_data.i=reg_2; + + instruction->instruction_parameters[2].parameter_type=P_REGISTER; + instruction->instruction_parameters[2].parameter_data.i=reg_3; +} + +static void i_bmove_pi_pi_r (int reg_1,int reg_2,int reg_3) +{ + register struct instruction *instruction; + + instruction=i_new_instruction (IBMOVE,3,3*sizeof (struct parameter)); + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=reg_1; + + instruction->instruction_parameters[1].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[1].parameter_data.i=reg_2; + + instruction->instruction_parameters[2].parameter_type=P_REGISTER; + instruction->instruction_parameters[2].parameter_data.i=reg_3; +} +#endif + +#ifdef I486 +void i_btst_i_id (LONG i,int offset,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IBTST); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=i); + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.i=register_1; +} +#endif + +#if defined (sparc) || defined (I486) || defined (G_POWER) +void i_btst_i_r (LONG i,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IBTST); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=i); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} +#endif + +static void i_cmp_i_r (LONG value,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (ICMP); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=value); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +static void i_cmp_id_r (int offset,int register_1,int register_2) +{ + struct instruction *instruction; +#ifdef G_POWER + instruction=i_new_instruction2 (ICMPLW); +#else + instruction=i_new_instruction2 (ICMP); +#endif + + S3(instruction->instruction_parameters[0], parameter_type=P_INDIRECT, + parameter_offset=offset, + parameter_data.i=register_1); + + S2(instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +static void i_cmpw_d_id (LABEL *descriptor,int arity,int offset_1,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (ICMPW); + + S3(instruction->instruction_parameters[0], parameter_type=P_DESCRIPTOR_NUMBER, + parameter_offset=arity, + parameter_data.l=descriptor); + + S3(instruction->instruction_parameters[1], parameter_type=P_INDIRECT, + parameter_offset=offset_1, + parameter_data.i=register_1); +} + +#if defined (M68000) || defined (I486) +static void i_exg_r_r (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IEXG); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} +#endif + +#if defined (I486) && defined (FP_STACK_OPTIMIZATIONS) +# define set_float_register_parameter(p,r) (p).parameter_type=P_F_REGISTER; (p).parameter_flags=0; (p).parameter_data.i=(r) +#else +# define set_float_register_parameter(p,r) (p).parameter_type=P_F_REGISTER; (p).parameter_data.i=(r) +#endif + +#if defined (M68000) || defined (G_POWER) +static void i_extb_r (int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (IEXTB); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} +#endif + +#ifdef M68000 +void i_ext_r (int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (IEXT); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} +#endif + +#ifdef FP_STACK_OPTIMIZATIONS +static void i_fexg_fr_fr (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IFEXG); + + set_float_register_parameter (instruction->instruction_parameters[0],register_1); + set_float_register_parameter (instruction->instruction_parameters[1],register_2); +} +#endif + +void i_fmove_fr_fr (int register_1,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IFMOVE); + + set_float_register_parameter (instruction->instruction_parameters[0],register_1); + set_float_register_parameter (instruction->instruction_parameters[1],register_2); +} + +void i_fmove_fr_id (int register_1,int offset,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IFMOVE); + + set_float_register_parameter (instruction->instruction_parameters[0],register_1); + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} + +#ifdef M68000 +void i_fmove_fr_pd (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IFMOVE); + + set_float_register_parameter (instruction->instruction_parameters[0],register_1); + + instruction->instruction_parameters[1].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} + +void i_fmove_fr_pi (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IFMOVE); + + set_float_register_parameter (instruction->instruction_parameters[0],register_1); + + instruction->instruction_parameters[1].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} +#endif + +static void i_fmove_fr_x (int register_1,int offset,int register_2,int register_3) +{ + struct instruction *instruction; + struct index_registers *index_registers; + + instruction=i_new_instruction (IFMOVE,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + set_float_register_parameter (instruction->instruction_parameters[0],register_1); + + S3(instruction->instruction_parameters[1],parameter_type=P_INDEXED,parameter_offset=offset,parameter_data.ir=index_registers); + + index_registers->a_reg.r=register_2; + index_registers->d_reg.r=register_3; +} + +void i_fmove_id_fr (int offset,int register_2,int register_1) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IFMOVE); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.i=register_2; + + set_float_register_parameter (instruction->instruction_parameters[1],register_1); +} + +#ifdef M68000 +void i_fmove_pd_fr (int register_1,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IFMOVE); + + instruction->instruction_parameters[0].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + set_float_register_parameter (instruction->instruction_parameters[1],register_2); +} + +void i_fmove_pi_fr (int register_1,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IFMOVE); + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + set_float_register_parameter (instruction->instruction_parameters[1],register_2); +} +#endif + +static void i_fmove_if_fr (DOUBLE r,int register_1) +{ + struct instruction *instruction; + DOUBLE *rp; + + instruction=i_new_instruction2 (IFMOVE); + rp=(DOUBLE*)fast_memory_allocate (sizeof (DOUBLE)); + + instruction->instruction_parameters[0].parameter_type=P_F_IMMEDIATE; + instruction->instruction_parameters[0].parameter_data.r=rp; + *rp=r; + + set_float_register_parameter (instruction->instruction_parameters[1],register_1); +} + +static void i_fmovel_fr_r (int register_1,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IFMOVEL); + + set_float_register_parameter (instruction->instruction_parameters[0],register_1); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +static void i_fmove_x_fr (int offset,int register_1,int register_2,int register_3) +{ + struct instruction *instruction; + struct index_registers *index_registers; + + instruction=i_new_instruction (IFMOVE,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + instruction->instruction_parameters[0].parameter_type=P_INDEXED; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_1; + index_registers->d_reg.r=register_2; + + set_float_register_parameter (instruction->instruction_parameters[1],register_3); +} + +void i_jmp_id (int offset_1,int register_1,int n_a_registers) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IJMP); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.reg.r=register_1; + + instruction->instruction_parameters[0].parameter_data.reg.u=n_a_registers; +} + +#if defined (G_POWER) || defined (I486) +void i_jmp_id_profile (int offset_1,int register_1,int n_a_registers) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IJMPP); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.reg.r=register_1; + + instruction->instruction_parameters[0].parameter_data.reg.u=n_a_registers; +} +#endif + +void i_jmp_l (LABEL *label,int n_a_registers) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IJMP); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_data.l=label; + + instruction->instruction_parameters[0].parameter_offset=n_a_registers; +} + +#if defined (G_POWER) || defined (I486) +void i_jmp_l_profile (LABEL *label,int offset) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IJMPP); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_data.l=label; + + instruction->instruction_parameters[0].parameter_offset=offset; +} +#endif + +#ifdef I486 +void i_jmp_r (int a_reg) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IJMP); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[0].parameter_data.i=a_reg; +} + +void i_jmp_r_profile (int a_reg) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IJMPP); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[0].parameter_data.i=a_reg; +} +#endif + +#if defined (M68000) || defined (I486) +void i_jsr_id (int offset,int register_1,int n_a_registers) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (IJSR); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.reg.r=register_1; + + instruction->instruction_parameters[0].parameter_data.reg.u=n_a_registers; +} + +void i_jsr_l (LABEL *label,int n_a_registers) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IJSR); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_data.l=label; + + instruction->instruction_parameters[0].parameter_offset=n_a_registers; +} +#else +void i_jsr_id_id (int offset_1,int register_1,int offset_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IJSR); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; +/* instruction->instruction_parameters[1].parameter_data.reg.r=B_STACK_POINTER; */ + instruction->instruction_parameters[1].parameter_data.i=offset_2; +} + +void i_jsr_l_id (LABEL *label,int offset) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IJSR); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_data.l=label; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; +/* instruction->instruction_parameters[1].parameter_data.reg.r=B_STACK_POINTER; */ + instruction->instruction_parameters[1].parameter_data.i=offset; +} + +# ifdef G_POWER + void i_jsr_id_idu (int offset_1,int register_1,int offset_2) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IJSR); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; +/* instruction->instruction_parameters[1].parameter_data.reg.r=B_STACK_POINTER; */ + instruction->instruction_parameters[1].parameter_data.i=offset_2; + } + + void i_jsr_l_idu (LABEL *label,int offset) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IJSR); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_data.l=label; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; +/* instruction->instruction_parameters[1].parameter_data.reg.r=B_STACK_POINTER; */ + instruction->instruction_parameters[1].parameter_data.i=offset; + } +# endif +#endif + +#ifdef I486 +void i_jsr_r (int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (IJSR); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[0].parameter_data.reg.r=register_1; +} +#endif + +#if defined (sparc) || defined (G_POWER) +# ifdef sparc +void i_call_l (LABEL *label) +# else +void i_call_l (LABEL *label,int frame_size) +# endif +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IJSR); + + S2(instruction->instruction_parameters[0], parameter_type=P_LABEL, + parameter_data.l=label); + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; +# ifdef G_POWER + instruction->instruction_parameters[1].parameter_data.i=frame_size; +# endif +} + +# ifdef sparc +void i_call_r (int register_1) +# else +void i_call_r (int register_1,int frame_size) +# endif +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IJSR); + + S2(instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.reg.r=register_1); + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; +# ifdef G_POWER + instruction->instruction_parameters[1].parameter_data.i=frame_size; +# endif +} +#endif + +void i_lea_id_r (int offset,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (ILEA); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.reg.r=register_1; + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_data.reg.r=register_2; +} + +void i_lea_l_i_r (LABEL *label,int offset,int register_1) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (ILEA); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.l=label; + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_data.reg.r=register_1; +} + +#if defined (sparc) || defined (I486) || defined (G_POWER) +static void i_lea_x_r (int register_1,int register_2,int register_3) +{ + register struct instruction *instruction; + register struct index_registers *index_registers; + + instruction=i_new_instruction (ILEA,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + instruction->instruction_parameters[0].parameter_type=P_INDEXED; + instruction->instruction_parameters[0].parameter_offset=0; + instruction->instruction_parameters[0].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_1; + index_registers->d_reg.r=register_2; + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_data.i=register_3; +} +#endif + +#if defined (G_POWER) || defined (sparc) +static void i_lsli_r_r (LONG value,int register_1,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction (ILSLI,3,3*sizeof (struct parameter)); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); + + S2 (instruction->instruction_parameters[2], parameter_type=P_IMMEDIATE, + parameter_data.i=value); +} +#endif + +static void i_moveb_id_r (int offset,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVEB); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +#if !(defined (M68000) || defined (I486)) +static void i_moveb_x_r (int register_1,int register_2,int register_3) +{ + struct instruction *instruction; + struct index_registers *index_registers; + + instruction=i_new_instruction (IMOVEB,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + instruction->instruction_parameters[0].parameter_type=P_INDEXED; + instruction->instruction_parameters[0].parameter_offset=0; + instruction->instruction_parameters[0].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_1; + index_registers->d_reg.r=register_2; + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_data.i=register_3; +} +#else +static void i_moveb_x_r (int offset,int register_1,int register_2,int register_3) +{ + struct instruction *instruction; + struct index_registers *index_registers; + + instruction=i_new_instruction (IMOVEB,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + instruction->instruction_parameters[0].parameter_type=P_INDEXED; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_1; + index_registers->d_reg.r=register_2; + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_data.i=register_3; +} +#endif + +#ifdef M68000 +static void i_movem_id (int offset_1,int register_1,int n_arguments,int arguments[]) +{ + register struct instruction *instruction; + register struct parameter *parameter; + register int argument_number; + + instruction=i_new_instruction (IMOVEM,n_arguments+1,(n_arguments+1)*sizeof (struct parameter)); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + parameter=&instruction->instruction_parameters[1]; + + for (argument_number=0; argument_number<n_arguments; ++argument_number){ + parameter->parameter_type=P_REGISTER; + parameter->parameter_data.i=arguments[argument_number]; + ++parameter; + } +} + +void i_movem_pd (int register_1,int n_arguments,int arguments[]) +{ + struct instruction *instruction; + struct parameter *parameter; + int argument_number; + + instruction=i_new_instruction (IMOVEM,n_arguments+1,(n_arguments+1)*sizeof (struct parameter)); + + instruction->instruction_parameters[n_arguments].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[n_arguments].parameter_data.i=register_1; + + parameter=&instruction->instruction_parameters[0]; + + for (argument_number=0; argument_number<n_arguments; ++argument_number){ + parameter->parameter_type=P_REGISTER; + parameter->parameter_data.i=arguments[argument_number]; + ++parameter; + } +} + +void i_movem_pi (int register_1,int n_arguments,int arguments[]) +{ + struct instruction *instruction; + struct parameter *parameter; + int argument_number; + + instruction=i_new_instruction (IMOVEM,n_arguments+1,(n_arguments+1)*sizeof (struct parameter)); + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + parameter=&instruction->instruction_parameters[1]; + + for (argument_number=0; argument_number<n_arguments; ++argument_number){ + parameter->parameter_type=P_REGISTER; + parameter->parameter_data.i=arguments[argument_number]; + ++parameter; + } +} + +void i_movem_id_r (int offset,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVEM); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} +#endif + +void i_movew_id_r (int offset,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVEW); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +static void i_move_i_id (LONG i,int offset_1,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=i); + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset_1; + instruction->instruction_parameters[1].parameter_data.i=register_1; +} + +#ifdef M68000 +static void i_move_i_pi (LONG i,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=i); + + instruction->instruction_parameters[1].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_1; +} +#endif + +void i_move_i_r (LONG i,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=i); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +#if defined (M68000) || defined (I486) +static void i_move_i_x (LONG i,int offset,int register_1,int register_2) +{ + register struct instruction *instruction; + register struct index_registers *index_registers; + + instruction=i_new_instruction + (IMOVE,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=i); + + instruction->instruction_parameters[1].parameter_type=P_INDEXED; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_1; + index_registers->d_reg.r=register_2; +} + +void i_move_id_pd (int offset_1,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} +#endif + +#ifdef M68000 +static void i_move_id_pi (int offset_1,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} +#endif + +static void i_move_d_r (LABEL *descriptor,int arity,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_DESCRIPTOR_NUMBER; + instruction->instruction_parameters[0].parameter_offset=arity; + instruction->instruction_parameters[0].parameter_data.l=descriptor; + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +void i_move_id_id (int offset_1,int register_1,int offset_2,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset_2; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} + +void i_move_id_r (int offset,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +#ifdef G_POWER + void i_move_idu_r (int offset,int register_1,int register_2) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT_WITH_UPDATE; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_data.i=register_2; + } + + void i_move_id_idu (int offset1,int register_1,int offset2,int register_2) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; + instruction->instruction_parameters[1].parameter_offset=offset2; + instruction->instruction_parameters[1].parameter_data.i=register_2; + } + + void i_move_r_idu (int register_1,int offset,int register_2) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.i=register_2; + } + + void i_movew_id_idu (int offset1,int register_1,int offset2,int register_2) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVEW); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; + instruction->instruction_parameters[1].parameter_offset=offset2; + instruction->instruction_parameters[1].parameter_data.i=register_2; + } + + void i_movew_r_idu (int register_1,int offset,int register_2) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVEW); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.i=register_2; + } +#endif + +#if defined (M68000) || defined (I486) +static void i_move_id_x (int offset_1,int register_1,int offset_2,int register_2,int register_3) +{ + register struct instruction *instruction; + register struct index_registers *index_registers; + + instruction=i_new_instruction + (IMOVE,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDEXED; + instruction->instruction_parameters[1].parameter_offset=offset_2; + instruction->instruction_parameters[1].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_2; + index_registers->d_reg.r=register_3; +} +#endif + +void i_move_l_r (LABEL *label,int register_1) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_data.l=label; + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +#ifdef M68000 +void i_move_pd_r (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +void i_move_pi_id (int register_1,int offset_2,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset_2; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} + +static void i_move_pi_pi (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} +#endif + +#if defined (M68000) | defined (I486) +void i_move_pi_r (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} +#endif + +#ifdef M68000 +static void i_move_pi_x (int register_1,int offset,int register_2,int register_3) +{ + register struct instruction *instruction; + register struct index_registers *index_registers; + + instruction=i_new_instruction + (IMOVE,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDEXED; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_2; + index_registers->d_reg.r=register_3; +} +#endif + +#ifdef G_POWER +static struct instruction *instruction_move_r_idhp (int register_1,LONG offset) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_HP; + instruction->instruction_parameters[1].parameter_data.i=offset; + + return instruction; +} +#endif + +#if defined (I486) + void i_move_r_l (int register_1,LABEL *label) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + S2 (instruction->instruction_parameters[1], parameter_type=P_LABEL, + parameter_data.l=label); + } +#endif + +void i_move_r_id (int register_1,int offset,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} + +#if defined (M68000) | defined (I486) +void i_move_r_pd (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + instruction->instruction_parameters[1].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} +#endif + +#ifdef M68000 +void i_move_r_pi (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + instruction->instruction_parameters[1].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} +#endif + +void i_move_r_r (int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +static void i_move_x_r (int offset,int register_1,int register_2,int register_3) +{ + register struct instruction *instruction; + register struct index_registers *index_registers; + + instruction=i_new_instruction + (IMOVE,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + instruction->instruction_parameters[0].parameter_type=P_INDEXED; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_1; + index_registers->d_reg.r=register_2; + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_data.i=register_3; +} + +static void i_move_x_id (int offset_1,int register_1,int register_2,int offset_2,int register_3) +{ + register struct instruction *instruction; + register struct index_registers *index_registers; + + instruction=i_new_instruction + (IMOVE,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + instruction->instruction_parameters[0].parameter_type=P_INDEXED; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_1; + index_registers->d_reg.r=register_2; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset_2; + instruction->instruction_parameters[1].parameter_data.i=register_3; +} + +#if defined (M68000) +static void i_move_x_pi (int offset,int register_1,int register_2,int register_3) +{ + register struct instruction *instruction; + register struct index_registers *index_registers; + + instruction=i_new_instruction + (IMOVE,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + instruction->instruction_parameters[0].parameter_type=P_INDEXED; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_1; + index_registers->d_reg.r=register_2; + + instruction->instruction_parameters[1].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_3; +} + +static void i_move_x_x (int offset_1,int register_1,int register_2,int offset_2,int register_3,int register_4) +{ + register struct instruction *instruction; + register struct index_registers *index_registers_1,*index_registers_2; + + instruction=i_new_instruction + (IMOVE,2,2*sizeof (struct parameter)+2*sizeof (struct index_registers)); + index_registers_1=(struct index_registers *)&instruction->instruction_parameters[2]; + index_registers_2=&index_registers_1[1]; + + instruction->instruction_parameters[0].parameter_type=P_INDEXED; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.ir=index_registers_1; + + index_registers_1->a_reg.r=register_1; + index_registers_1->d_reg.r=register_2; + + instruction->instruction_parameters[1].parameter_type=P_INDEXED; + instruction->instruction_parameters[1].parameter_offset=offset_2; + instruction->instruction_parameters[1].parameter_data.ir=index_registers_2; + + index_registers_2->a_reg.r=register_3; + index_registers_2->d_reg.r=register_4; +} + +void i_movew_id_pd (int offset_1,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVEW); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} + +void i_movew_pi_id (int register_1,int offset_2,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVEW); + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset_2; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} + +void i_movew_pi_r (int register_1,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVEW); + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +void i_movew_r_pd (int register_1,int register_2) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVEW); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + instruction->instruction_parameters[1].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_2; +} +#endif + +#ifdef G_POWER +void i_or_i_r (LONG value,int register_1) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (IOR); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=value); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +void i_mtctr (int register_1) +{ + struct instruction *instruction; + + instruction=i_new_instruction (IMTCTR,1,1*sizeof (struct parameter)); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} +#endif + +#if ! (defined (sparc) || defined (G_POWER)) + void i_rts (void) + { + i_new_instruction (IRTS,0,0); + } + +# ifdef I486 + void i_rts_i (int offset) + { + struct instruction *instruction; + + instruction=i_new_instruction (IRTSI,1,1*sizeof (struct parameter)); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=offset); + } + + void i_rts_profile (void) + { + i_new_instruction (IRTSP,0,0); + } +# endif +#else + void i_rts (int offset_1,int offset_2) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IRTS); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=B_STACK_POINTER; + + instruction->instruction_parameters[1].parameter_type=P_IMMEDIATE; + instruction->instruction_parameters[1].parameter_data.i=offset_2; + } +#endif + +#ifdef G_POWER + void i_rts_c (void) + { + i_new_instruction (IRTS,0,0); + } + + void i_rts_profile (int offset_1,int offset_2) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IRTSP); + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset_1; + instruction->instruction_parameters[0].parameter_data.i=B_STACK_POINTER; + + instruction->instruction_parameters[1].parameter_type=P_IMMEDIATE; + instruction->instruction_parameters[1].parameter_data.i=offset_2; + } + + void i_rts_r (int register1,int offset_1) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IRTS); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[0].parameter_data.i=register1; + + instruction->instruction_parameters[1].parameter_type=P_IMMEDIATE; + instruction->instruction_parameters[1].parameter_data.i=offset_1; + } + + void i_rts_r_profile (int register1,int offset_1) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IRTSP); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[0].parameter_data.i=register1; + + instruction->instruction_parameters[1].parameter_type=P_IMMEDIATE; + instruction->instruction_parameters[1].parameter_data.i=offset_1; + } +#endif + +void i_schedule_i (int value) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (ISCHEDULE); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=value); +} + +void i_sub_i_r (LONG value,int register_1) +{ + + register struct instruction *instruction; + + instruction=i_new_instruction2 (ISUB); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=value); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +#ifdef M68000 +static void i_tstb_pi (int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (ITSTB); + + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; +} +#endif + +void i_tst_r (int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (ITST); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +void i_word_i (int value) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (IWORD); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=value); +} + +#define N_VECTOR_BITS 32 + +struct register_list { + ULONG r_l_vector; + struct register_list *r_l_next; +}; + +struct register_set { + struct register_list r_s_list; + UWORD r_s_first_free; + UWORD r_s_highest; +}; + +static struct register_set free_dregisters,free_aregisters,free_fregisters; + +void get_n_virtual_registers + (int *n_virtual_a_regs_p,int *n_virtual_d_regs_p,int *n_virtual_f_regs_p) +{ + *n_virtual_a_regs_p=free_aregisters.r_s_highest; + *n_virtual_d_regs_p=free_dregisters.r_s_highest; + *n_virtual_f_regs_p=free_fregisters.r_s_highest; +} + +static int get_free_register_number (register struct register_set *r_s_p) +{ + struct register_list *r_list; + register unsigned int bit_n,reg_n; + ULONG vector; + + reg_n=r_s_p->r_s_first_free; + + bit_n=reg_n; + r_list=&r_s_p->r_s_list; + + while (bit_n>=N_VECTOR_BITS){ + struct register_list *n_r_list; + + bit_n-=N_VECTOR_BITS; + n_r_list=r_list->r_l_next; + if (n_r_list==NULL){ + n_r_list=(struct register_list*)fast_memory_allocate (sizeof (struct register_list)); + n_r_list->r_l_next=NULL; + + r_list->r_l_next=n_r_list; + } + r_list=n_r_list; + } + vector=r_list->r_l_vector; + + while (reg_n<r_s_p->r_s_highest){ + if (bit_n==N_VECTOR_BITS){ + bit_n=0; + r_list=r_list->r_l_next; + vector=r_list->r_l_vector; + } + if (vector & (1<<bit_n)){ + r_list->r_l_vector &= ~(1<<bit_n); + r_s_p->r_s_first_free=reg_n+1; + return reg_n; + } + ++reg_n; + ++bit_n; + } + + if (bit_n==N_VECTOR_BITS){ + r_list=r_list->r_l_next=(struct register_list*)fast_memory_allocate (sizeof (struct register_list)); + r_list->r_l_next=NULL; + bit_n=0; + } + + r_s_p->r_s_highest=reg_n+1; + r_s_p->r_s_first_free=reg_n+1; + r_list->r_l_vector &= ~(1<<bit_n); + return reg_n; +} + +static void free_register_number (struct register_set *r_s_p,unsigned int reg_n) +{ + struct register_list *r_list; + register unsigned int bit_n; + + if (reg_n<r_s_p->r_s_first_free) + r_s_p->r_s_first_free=reg_n; + + bit_n=reg_n; + r_list=&r_s_p->r_s_list; + + while (bit_n>=N_VECTOR_BITS){ + bit_n-=N_VECTOR_BITS; + r_list=r_list->r_l_next; + } + + r_list->r_l_vector |= (1<<bit_n); +} + +static void allocate_register_number (struct register_set *r_s_p,unsigned int reg_n) +{ + struct register_list *r_list; + register unsigned int bit_n; + + bit_n=reg_n; + r_list=&r_s_p->r_s_list; + + while (bit_n>=N_VECTOR_BITS){ + bit_n-=N_VECTOR_BITS; + r_list=r_list->r_l_next; + } + + r_list->r_l_vector &= ~(1<<bit_n); +} + +static int try_allocate_register_number (int reg_n) +{ + struct register_list *r_list; + register unsigned int bit_n; + + if (is_d_register (reg_n)){ + r_list=&free_dregisters.r_s_list; + bit_n=d_reg_num (reg_n); + } else { + r_list=&free_aregisters.r_s_list; + bit_n=a_reg_num (reg_n); + } + + while (bit_n>=N_VECTOR_BITS){ + bit_n-=N_VECTOR_BITS; + r_list=r_list->r_l_next; + } + + if (r_list->r_l_vector & (1<<bit_n)){ + r_list->r_l_vector &= ~(1<<bit_n); + return 1; + } else + return 0; +} + +static int try_get_real_dregister_number (VOID) +{ + register struct register_list *r_list; + register unsigned int reg_n; + ULONG vector; + + reg_n=free_dregisters.r_s_first_free; + r_list=&free_dregisters.r_s_list; + vector=r_list->r_l_vector; + + while (reg_n<N_DATA_PARAMETER_REGISTERS && reg_n<free_dregisters.r_s_highest){ + if (vector & (1<<reg_n)){ + r_list->r_l_vector &= ~(1<<reg_n); + free_dregisters.r_s_first_free=reg_n+1; + return reg_n; + } + ++reg_n; + } + + if (reg_n>=N_DATA_PARAMETER_REGISTERS) + return -1; + + free_dregisters.r_s_highest=reg_n+1; + r_list->r_l_vector &= ~(1<<reg_n); + return reg_n; +} + +static int get_dregister (VOID) +{ + return num_to_d_reg (get_free_register_number (&free_dregisters)); +} + +static void free_dregister (int dregister) +{ + free_register_number (&free_dregisters,d_reg_num (dregister)); +} + +void allocate_dregister (int dregister) +{ + allocate_register_number (&free_dregisters,d_reg_num (dregister)); +} + +void free_all_dregisters (VOID) +{ + free_dregisters.r_s_first_free=d_reg_num (REGISTER_D0); + free_dregisters.r_s_highest=8; +#ifdef I486 + free_dregisters.r_s_list.r_l_vector= + (1<<d_reg_num (REGISTER_D0)) | (1<<d_reg_num (REGISTER_D1)); +#else + if (parallel_flag) + free_dregisters.r_s_list.r_l_vector= + (1<<d_reg_num (REGISTER_D0)) | (1<<d_reg_num (REGISTER_D1)) + | (1<<d_reg_num (REGISTER_D2)) | (1<<d_reg_num (REGISTER_D3)) + | (1<<d_reg_num (REGISTER_D4)) | (1<<d_reg_num (REGISTER_D5)); + else + free_dregisters.r_s_list.r_l_vector= + (1<<d_reg_num (REGISTER_D0)) | (1<<d_reg_num (REGISTER_D1)) + | (1<<d_reg_num (REGISTER_D2)) | (1<<d_reg_num (REGISTER_D3)) + | (1<<d_reg_num (REGISTER_D4)) | (1<<d_reg_num (REGISTER_D5)) + | (1<<d_reg_num (REGISTER_D6)); +#endif + free_dregisters.r_s_list.r_l_next=NULL; +} + +static int get_aregister (VOID) +{ + return num_to_a_reg (get_free_register_number (&free_aregisters)); +} + +static void free_aregister (int aregister) +{ + free_register_number (&free_aregisters,a_reg_num (aregister)); +} + +void allocate_aregister (int aregister) +{ + allocate_register_number (&free_aregisters,a_reg_num (aregister)); +} + +void free_all_aregisters (VOID) +{ + free_aregisters.r_s_first_free=a_reg_num (REGISTER_A0); + free_aregisters.r_s_highest=N_REAL_A_REGISTERS; + free_aregisters.r_s_list.r_l_vector= (1<<a_reg_num (REGISTER_A0)) + | (1<<a_reg_num (REGISTER_A1)) +#ifndef I486 + | (1<<a_reg_num (REGISTER_A2)) +#endif + ; + free_aregisters.r_s_list.r_l_next=NULL; +} + +static int get_fregister (VOID) +{ + return get_free_register_number (&free_fregisters); +} + +static void free_fregister (int fregister) +{ + free_register_number (&free_fregisters,fregister); +} + +void allocate_fregister (int fregister) +{ + allocate_register_number (&free_fregisters,fregister); +} + +void free_all_fregisters (VOID) +{ + free_fregisters.r_s_first_free=REGISTER_FP0; + free_fregisters.r_s_highest=8; + free_fregisters.r_s_list.r_l_vector= (1<<REGISTER_FP0) | (1<<REGISTER_FP1) | + (1<<REGISTER_FP2) | (1<<REGISTER_FP3) | + (1<<REGISTER_FP4) | (1<<REGISTER_FP5) | + (1<<REGISTER_FP6) +#ifndef I486 + | (1<<REGISTER_FP7) +#endif + ; + free_fregisters.r_s_list.r_l_next=NULL; +} + +static void free_register (int reg) +{ + if (is_d_register (reg)) + free_dregister (reg); + else + free_aregister (reg); +} + +typedef struct address { + int ad_mode; + union { + struct { + union { + LONG ad_register; + LABEL *ad_label; + struct { + WORD ad_areg; + WORD ad_dreg; + } s; + } u; + LONG ad_offset; + } s; + DOUBLE ad_real; + } u; + WORD *ad_count_p; + WORD *ad_count_p2; + WORD ad_count; + WORD ad_count2; +} ADDRESS; + +#define ad_register u.s.u.ad_register +#define ad_label u.s.u.ad_label +#define ad_areg u.s.u.s.ad_areg +#define ad_dreg u.s.u.s.ad_dreg +#define ad_offset u.s.ad_offset +#define ad_real u.ad_real + +static void ad_to_parameter (ADDRESS *ad_p,struct parameter *parameter_p) +{ + switch (ad_p->ad_mode){ + case P_REGISTER: + parameter_p->parameter_type=P_REGISTER; + parameter_p->parameter_data.i=ad_p->ad_register; + if (--*ad_p->ad_count_p==0) + free_register (ad_p->ad_register); + break; + case P_IMMEDIATE: + parameter_p->parameter_type=P_IMMEDIATE; + parameter_p->parameter_data.i=ad_p->ad_offset; + break; + case P_INDIRECT: + parameter_p->parameter_type=P_INDIRECT; + parameter_p->parameter_offset=ad_p->ad_offset; + parameter_p->parameter_data.i=ad_p->ad_register; + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + break; + case P_DESCRIPTOR_NUMBER: + parameter_p->parameter_type=P_DESCRIPTOR_NUMBER; + parameter_p->parameter_offset=ad_p->ad_offset; + parameter_p->parameter_data.l=ad_p->ad_label; + break; + case P_INDEXED: + { + struct index_registers *index_registers; + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + index_registers=(struct index_registers*)fast_memory_allocate (sizeof (struct index_registers)); + + U3(parameter_p, parameter_type=P_INDEXED, + parameter_offset=i_ad_p->ad_offset, + parameter_data.ir=index_registers); + + index_registers->a_reg.r=i_ad_p->ad_areg; + index_registers->d_reg.r=i_ad_p->ad_dreg; + + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + } else { + U3(parameter_p, parameter_type=P_INDIRECT, + parameter_offset=i_ad_p->ad_offset, + parameter_data.i=i_ad_p->ad_register); + + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + } + } else { + U2(parameter_p,parameter_type=P_REGISTER,parameter_data.i=i_ad_p->ad_register); + + if (--*i_ad_p->ad_count_p==0) + free_register (i_ad_p->ad_register); + } + break; + } + default: + internal_error_in_function ("ad_to_parameter"); + } +} + +static int fad_to_parameter (ADDRESS *ad_p,struct parameter *parameter_p) +{ + switch (ad_p->ad_mode){ + case P_F_REGISTER: + set_float_register_parameter (*parameter_p,ad_p->ad_register); + if (--*ad_p->ad_count_p==0) + /* free_fregister (ad_p->ad_register); */ + return 1; + break; + case P_F_IMMEDIATE: + { + DOUBLE *rp; + + parameter_p->parameter_type=P_F_IMMEDIATE; + rp=(DOUBLE*)fast_memory_allocate (sizeof (DOUBLE)); + parameter_p->parameter_data.r=rp; + *rp=ad_p->ad_real; + break; + } + case P_INDIRECT: + parameter_p->parameter_type=P_INDIRECT; + parameter_p->parameter_offset=ad_p->ad_offset; + parameter_p->parameter_data.i=ad_p->ad_register; + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + break; + case P_DESCRIPTOR_NUMBER: + parameter_p->parameter_type=P_DESCRIPTOR_NUMBER; + parameter_p->parameter_offset=ad_p->ad_offset; + parameter_p->parameter_data.l=ad_p->ad_label; + break; + case P_INDEXED: + { + struct index_registers *index_registers; + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + index_registers=(struct index_registers*)fast_memory_allocate (sizeof (struct index_registers)); + + U3(parameter_p, parameter_type=P_INDEXED, + parameter_offset=i_ad_p->ad_offset, + parameter_data.ir=index_registers); + + index_registers->a_reg.r=i_ad_p->ad_areg; + index_registers->d_reg.r=i_ad_p->ad_dreg; + + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + } else { + U3(parameter_p, parameter_type=P_INDIRECT, + parameter_offset=i_ad_p->ad_offset, + parameter_data.i=i_ad_p->ad_register); + + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + } + } else { + U2(parameter_p,parameter_type=P_REGISTER,parameter_data.i=i_ad_p->ad_register); + + if (--*i_ad_p->ad_count_p==0) + free_register (i_ad_p->ad_register); + } + break; + } + default: + internal_error_in_function ("ad_to_parameter"); + } + return 0; +} + +static void instruction_ad (int instruction_code,ADDRESS *ad_p) +{ + struct instruction *instruction; + + instruction=i_new_instruction1 (instruction_code); + + ad_to_parameter (ad_p,&instruction->instruction_parameters[0]); +} + +static void instruction_ad_id (int instruction_code,ADDRESS *ad_p,int offset,int register_1) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (instruction_code); + + ad_to_parameter (ad_p,&instruction->instruction_parameters[0]); + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.i=register_1; +} + +#ifdef G_POWER + static void i_move_ad_idu (ADDRESS *ad_p,int offset,int register_1) + { + struct instruction *instruction; + + instruction=i_new_instruction2 (IMOVE); + + ad_to_parameter (ad_p,&instruction->instruction_parameters[0]); + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.i=register_1; + } +#endif + +#ifdef M68000 +static void instruction_ad_pd (int instruction_code,ADDRESS *ad_p,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (instruction_code); + + ad_to_parameter (ad_p,&instruction->instruction_parameters[0]); + + instruction->instruction_parameters[1].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_1; +} + +static void instruction_ad_pi (int instruction_code,ADDRESS *ad_p,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (instruction_code); + + ad_to_parameter (ad_p,&instruction->instruction_parameters[0]); + + instruction->instruction_parameters[1].parameter_type=P_POST_INCREMENT; + instruction->instruction_parameters[1].parameter_data.i=register_1; +} +#endif + +static void instruction_ad_r (int instruction_code,ADDRESS *ad_p,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (instruction_code); + + ad_to_parameter (ad_p,&instruction->instruction_parameters[0]); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +static void instruction_i_ad (int instruction_code,LONG value,ADDRESS *ad_p) +{ + struct instruction *instruction; + + instruction=i_new_instruction2 (instruction_code); + + S2 (instruction->instruction_parameters[0], parameter_type=P_IMMEDIATE, + parameter_data.i=value); + + ad_to_parameter (ad_p,&instruction->instruction_parameters[1]); +} + +static void instruction_d_ad (int instruction_code,LABEL *label,int arity,ADDRESS *ad_p) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (instruction_code); + + instruction->instruction_parameters[0].parameter_type=P_DESCRIPTOR_NUMBER; + instruction->instruction_parameters[0].parameter_data.l=label; + instruction->instruction_parameters[0].parameter_offset=arity; + + ad_to_parameter (ad_p,&instruction->instruction_parameters[1]); +} + +static void instruction_fr_fr (int instruction_code,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (instruction_code); + + set_float_register_parameter (instruction->instruction_parameters[0],register_1); + + set_float_register_parameter (instruction->instruction_parameters[1],register_2); +} + +static void instruction_l (int instruction_code,LABEL *label) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (instruction_code); + + instruction->instruction_parameters[0].parameter_type=P_LABEL; + instruction->instruction_parameters[0].parameter_data.l=label; +} + +static void instruction_ad_r_r (int instruction_code,ADDRESS *ad_p,int register_1,int register_2) +{ + register struct instruction *instruction; + + instruction=i_new_instruction (instruction_code,3,3*sizeof (struct parameter)); + + ad_to_parameter (ad_p,&instruction->instruction_parameters[0]); + + S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER, + parameter_data.i=register_1); + + S2 (instruction->instruction_parameters[2], parameter_type=P_REGISTER, + parameter_data.i=register_2); +} + +static void instruction_r (int instruction_code,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (instruction_code); + + S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER, + parameter_data.i=register_1); +} + +#ifdef M68000 +void instruction_pd (int instruction_code,int register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction1 (instruction_code); + + instruction->instruction_parameters[0].parameter_type=P_PRE_DECREMENT; + instruction->instruction_parameters[0].parameter_data.i=register_1; +} +#endif + +static void instruction_ad_x (int instruction_code,ADDRESS *ad_p,int offset,int register_1,int register_2) +{ + register struct instruction *instruction; + register struct index_registers *index_registers; + + instruction=i_new_instruction + (instruction_code,2,2*sizeof (struct parameter)+sizeof (struct index_registers)); + index_registers=(struct index_registers *)&instruction->instruction_parameters[2]; + + ad_to_parameter (ad_p,&instruction->instruction_parameters[0]); + + instruction->instruction_parameters[1].parameter_type=P_INDEXED; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.ir=index_registers; + + index_registers->a_reg.r=register_1; + index_registers->d_reg.r=register_2; +} + +static void to_data_addressing_mode (register ADDRESS *ad_p) +{ + if (ad_p->ad_mode==P_REGISTER && is_a_register (ad_p->ad_register)){ + int dreg; + + dreg=get_dregister(); + i_move_r_r (ad_p->ad_register,dreg); + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=dreg; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1; + } +} + +static void in_register (register ADDRESS *ad_p) +{ + int dreg; + + switch (ad_p->ad_mode){ + case P_REGISTER: + return; + case P_IMMEDIATE: + dreg=get_dregister(); + i_move_i_r (ad_p->ad_offset,dreg); + break; + case P_INDIRECT: + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + dreg=get_dregister(); + i_move_id_r (ad_p->ad_offset,ad_p->ad_register,dreg); + break; + case P_DESCRIPTOR_NUMBER: + dreg=get_dregister(); + i_move_d_r (ad_p->ad_label,ad_p->ad_offset,dreg); + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + dreg=get_dregister(); + i_move_x_r (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,dreg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + + dreg=get_dregister(); + i_move_id_r (i_ad_p->ad_offset,i_ad_p->ad_register,dreg); + } + i_ad_p->ad_register=dreg; + } else { + dreg=i_ad_p->ad_register; + } + break; + } + default: + internal_error_in_function ("in_register"); + return; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=dreg; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1; +} + +static void in_data_register (register ADDRESS *ad_p) +{ + int dreg; + + switch (ad_p->ad_mode){ + case P_REGISTER: + if (is_d_register (ad_p->ad_register)) + return; + dreg=get_dregister(); + i_move_r_r (ad_p->ad_register,dreg); + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + break; + case P_IMMEDIATE: + dreg=get_dregister(); + i_move_i_r (ad_p->ad_offset,dreg); + break; + case P_INDIRECT: + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + dreg=get_dregister(); + i_move_id_r (ad_p->ad_offset,ad_p->ad_register,dreg); + break; + case P_DESCRIPTOR_NUMBER: + dreg=get_dregister(); + i_move_d_r (ad_p->ad_label,ad_p->ad_offset,dreg); + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + dreg=get_dregister(); + i_move_x_r (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,dreg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + dreg=get_dregister(); + i_move_id_r (i_ad_p->ad_offset,i_ad_p->ad_register,dreg); + } + i_ad_p->ad_register=dreg; + } else { + dreg=i_ad_p->ad_register; + if (!is_d_register (dreg)){ + int areg; + + areg=dreg; + dreg=get_dregister(); + i_move_r_r (areg,dreg); + if (--*i_ad_p->ad_count_p==0) + free_aregister (areg); + } + } + break; + } + default: + internal_error_in_function ("in_data_register"); + return; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=dreg; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1; +} + +static void in_alterable_data_register (register ADDRESS *ad_p) +{ + int dreg; + + switch (ad_p->ad_mode){ + case P_REGISTER: + if (is_d_register (ad_p->ad_register)){ + if (*ad_p->ad_count_p==1) + return; + dreg=get_dregister(); + i_move_r_r (ad_p->ad_register,dreg); + --*ad_p->ad_count_p; + } else { + dreg=get_dregister(); + i_move_r_r (ad_p->ad_register,dreg); + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + } + break; + case P_IMMEDIATE: + dreg=get_dregister(); + i_move_i_r (ad_p->ad_offset,dreg); + break; + case P_INDIRECT: + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + dreg=get_dregister(); + i_move_id_r (ad_p->ad_offset,ad_p->ad_register,dreg); + break; + case P_DESCRIPTOR_NUMBER: + dreg=get_dregister(); + i_move_d_r (ad_p->ad_label,ad_p->ad_offset,dreg); + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + + dreg=get_dregister(); + i_move_x_r (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,dreg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + dreg=get_dregister(); + i_move_id_r (i_ad_p->ad_offset,i_ad_p->ad_register,dreg); + } + i_ad_p->ad_register=dreg; + } else { + dreg=i_ad_p->ad_register; + + if (is_d_register (dreg)){ + if (*i_ad_p->ad_count_p>1){ + int old_dreg; + + old_dreg=dreg; + dreg=get_dregister(); + i_move_r_r (old_dreg,dreg); + --*i_ad_p->ad_count_p; + } + } else { + int areg; + + areg=dreg; + dreg=get_dregister(); + i_move_r_r (areg,dreg); + if (--*i_ad_p->ad_count_p==0) + free_aregister (areg); + } + } + break; + } + default: + internal_error_in_function ("in_alterable_data register"); + return; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=dreg; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1; +} + +static void in_address_register (register ADDRESS *ad_p) +{ + int areg; + + switch (ad_p->ad_mode){ + case P_REGISTER: + if (is_a_register (ad_p->ad_register)) + return; + areg=get_aregister(); + i_move_r_r (ad_p->ad_register,areg); + if (--*ad_p->ad_count_p==0) + free_dregister (ad_p->ad_register); + break; + case P_IMMEDIATE: + areg=get_aregister(); + i_move_i_r (ad_p->ad_offset,areg); + break; + case P_INDIRECT: + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + areg=get_aregister(); + i_move_id_r (ad_p->ad_offset,ad_p->ad_register,areg); + break; + case P_DESCRIPTOR_NUMBER: + areg=get_aregister(); + i_move_d_r (ad_p->ad_label,ad_p->ad_offset,areg); + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + areg=get_aregister(); + i_move_x_r (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,areg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + areg=get_aregister(); + i_move_id_r (i_ad_p->ad_offset,i_ad_p->ad_register,areg); + } + i_ad_p->ad_register=areg; + } else { + areg=i_ad_p->ad_register; + if (!is_a_register (areg)){ + int dreg; + + dreg=areg; + areg=get_aregister(); + i_move_r_r (dreg,areg); + if (--*i_ad_p->ad_count_p==0) + free_dregister (dreg); + } + } + break; + } + default: + internal_error_in_function ("in_address_register"); + return; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=areg; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1; +} + +static void in_alterable_address_register (register ADDRESS *ad_p) +{ + int areg; + + switch (ad_p->ad_mode){ + case P_REGISTER: + if (is_a_register (ad_p->ad_register)){ + if (*ad_p->ad_count_p==1) + return; + areg=get_aregister(); + i_move_r_r (ad_p->ad_register,areg); + --*ad_p->ad_count_p; + } else { + areg=get_aregister(); + i_move_r_r (ad_p->ad_register,areg); + if (--*ad_p->ad_count_p==0) + free_dregister (ad_p->ad_register); + } + break; + case P_IMMEDIATE: + areg=get_aregister(); + i_move_i_r (ad_p->ad_offset,areg); + break; + case P_INDIRECT: + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + areg=get_aregister(); + i_move_id_r (ad_p->ad_offset,ad_p->ad_register,areg); + break; + case P_DESCRIPTOR_NUMBER: + areg=get_aregister(); + i_move_d_r (ad_p->ad_label,ad_p->ad_offset,areg); + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + areg=get_aregister(); + i_move_x_r (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,areg); + } else + { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + areg=get_aregister(); + i_move_id_r (i_ad_p->ad_offset,i_ad_p->ad_register,areg); + } + i_ad_p->ad_register=areg; + } else { + areg=i_ad_p->ad_register; + + if (is_a_register (areg)){ + if (*i_ad_p->ad_count_p>1){ + int old_areg; + + old_areg=areg; + areg=get_aregister(); + i_move_r_r (old_areg,areg); + --*i_ad_p->ad_count_p; + } + } else { + int dreg; + + dreg=areg; + areg=get_aregister(); + i_move_r_r (dreg,areg); + if (--*i_ad_p->ad_count_p==0) + free_dregister (dreg); + } + } + break; + } + default: + internal_error_in_function ("in_alterable_address_register"); + return; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=areg; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1; +} + +static void register_node (INSTRUCTION_GRAPH graph,int reg) +{ + graph->instruction_code=GREGISTER; + graph->instruction_parameters[0].i=reg; + + if ((unsigned)a_reg_num (reg)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + global_block.block_graph_a_register_parameter_node[a_reg_num (reg)]=graph; + + if ((unsigned)d_reg_num (reg)<(unsigned)N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ) + global_block.block_graph_d_register_parameter_node[d_reg_num (reg)]=graph; +} + +static void float_register_node (register INSTRUCTION_GRAPH graph,int reg) +{ + graph->instruction_code=GFREGISTER; + graph->instruction_parameters[0].i=reg; + + if ((unsigned)reg<(unsigned)N_FLOAT_PARAMETER_REGISTERS) + global_block.block_graph_f_register_parameter_node [reg]=graph; +} + +static void linearize_graph (INSTRUCTION_GRAPH,ADDRESS *); + +#if defined (G_POWER) +# define SMALL_IMMEDIATE(i) (((short int)i)==((int)i)) +#endif +#if defined (sparc) +# define SMALL_IMMEDIATE(i) ((int)i<4096 && (int)i>=-4095) +#endif + +static void linearize_dyadic_commutative_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1,ad_2; + int reg_1; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + } else { + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_1,&ad_1); + } + + if (graph->instruction_d_min_a_cost<=0){ + if (ad_1.ad_mode==P_REGISTER && is_d_register (ad_1.ad_register) && *ad_1.ad_count_p<=1 && + !(ad_2.ad_mode==P_REGISTER && is_d_register (ad_2.ad_register) && *ad_2.ad_count_p<=1)) + { + instruction_ad_r (i_instruction_code,&ad_2,ad_1.ad_register); + --*ad_1.ad_count_p; + reg_1=ad_1.ad_register; + } else { +#ifndef M68000 /* optimization added 18-8-1998 */ + if (ad_2.ad_mode==P_IMMEDIATE){ +# if defined (G_POWER) || defined (sparc) + if (ad_1.ad_mode==P_REGISTER && SMALL_IMMEDIATE (ad_2.ad_offset) && i_instruction_code==IADD){ + if (--*ad_1.ad_count_p==0) + free_register (ad_1.ad_register); + reg_1=get_dregister(); + i_addi_r_r (ad_2.ad_offset,ad_1.ad_register,reg_1); + } else +# endif + { + in_alterable_data_register (&ad_1); + instruction_ad_r (i_instruction_code,&ad_2,ad_1.ad_register); + --*ad_1.ad_count_p; + reg_1=ad_1.ad_register; + } + } else { +#endif +#if defined (G_POWER) || defined (sparc) + if (ad_1.ad_mode==P_IMMEDIATE && ad_2.ad_mode==P_REGISTER && SMALL_IMMEDIATE (ad_1.ad_offset) && i_instruction_code==IADD){ + if (--*ad_2.ad_count_p==0) + free_register (ad_2.ad_register); + reg_1=get_dregister(); + i_addi_r_r (ad_1.ad_offset,ad_2.ad_register,reg_1); + } else +#endif + + { +#if 1 /* optimization added 9-1-2000 */ + if (! (ad_1.ad_mode==P_REGISTER && ad_2.ad_mode==P_REGISTER && ad_1.ad_register==ad_2.ad_register && + is_d_register (ad_1.ad_register) && *ad_1.ad_count_p==2 && ad_1.ad_count_p==ad_2.ad_count_p)) +#endif + in_alterable_data_register (&ad_2); + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + --*ad_2.ad_count_p; + reg_1=ad_2.ad_register; + } +#ifndef M68000 + } +#endif + } + } else { +# if defined (G_POWER) || defined (sparc) + if (ad_1.ad_mode==P_IMMEDIATE && ad_2.ad_mode==P_REGISTER && SMALL_IMMEDIATE (ad_1.ad_offset) && i_instruction_code==IADD){ + if (--*ad_2.ad_count_p==0) + free_register (ad_2.ad_register); + reg_1=get_aregister(); + i_addi_r_r (ad_1.ad_offset,ad_2.ad_register,reg_1); + } else if (ad_2.ad_mode==P_IMMEDIATE && ad_1.ad_mode==P_REGISTER && SMALL_IMMEDIATE (ad_2.ad_offset) && i_instruction_code==IADD){ + if (--*ad_1.ad_count_p==0) + free_register (ad_1.ad_register); + reg_1=get_aregister(); + i_addi_r_r (ad_2.ad_offset,ad_1.ad_register,reg_1); + } else +# endif + + if ((ad_1.ad_mode==P_REGISTER || ad_1.ad_mode==P_INDIRECT) + && is_a_register (ad_1.ad_register) && *ad_1.ad_count_p<=1) + { + in_alterable_address_register (&ad_1); + instruction_ad_r (i_instruction_code,&ad_2,ad_1.ad_register); + --*ad_1.ad_count_p; + reg_1=ad_1.ad_register; + } else { + in_alterable_address_register (&ad_2); + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + --*ad_2.ad_count_p; + reg_1=ad_2.ad_register; + } + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); +} + +static void linearize_dyadic_commutative_data_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1,ad_2; + int reg_1; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + } else { + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_1,&ad_1); + } + + if (ad_1.ad_mode==P_REGISTER && (is_a_register (ad_1.ad_register) || *ad_1.ad_count_p<=1) && + !(ad_2.ad_mode==P_REGISTER && is_d_register (ad_2.ad_register) && *ad_2.ad_count_p<=1)) + { + in_alterable_data_register (&ad_1); + to_data_addressing_mode (&ad_2); + instruction_ad_r (i_instruction_code,&ad_2,ad_1.ad_register); + --*ad_1.ad_count_p; + reg_1=ad_1.ad_register; + } else { + in_alterable_data_register (&ad_2); + to_data_addressing_mode (&ad_1); + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + --*ad_2.ad_count_p; + reg_1=ad_2.ad_register; + } + + if (graph->instruction_d_min_a_cost>0){ + int areg; + + areg=get_aregister(); + i_move_r_r (reg_1,areg); + free_dregister (reg_1); + reg_1=areg; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); +} + +static void linearize_eor_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1,ad_2; + int reg_1; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + } else { + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_1,&ad_1); + } + + in_alterable_data_register (&ad_2); + if (ad_1.ad_mode!=P_IMMEDIATE) + in_data_register (&ad_1); + instruction_ad_r (IEOR,&ad_1,ad_2.ad_register); + --*ad_2.ad_count_p; + reg_1=ad_2.ad_register; + + if (graph->instruction_d_min_a_cost>0){ + int areg; + + areg=get_aregister(); + i_move_r_r (reg_1,areg); + free_dregister (reg_1); + reg_1=areg; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); +} + +static int compare_node (INSTRUCTION_GRAPH graph,int i_test_1,int i_test_2) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1,ad_2; + int mode_1,mode_2; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph_1->instruction_code==GLOAD_DES_ID && graph_1->node_count==1 + && graph_2->instruction_code==GLOAD_DES_I && graph_2->node_count==1) + { + linearize_graph (graph_1->instruction_parameters[1].p,&ad_1); + in_address_register (&ad_1); + if (--*ad_1.ad_count_p==0) + free_aregister (ad_1.ad_register); + i_cmpw_d_id (graph_2->instruction_parameters[0].l,graph_2->instruction_parameters[1].i, + graph_1->instruction_parameters[0].i,ad_1.ad_register); + return i_test_2; + } else + if (graph_2->instruction_code==GLOAD_DES_ID && graph_2->node_count==1 + && graph_1->instruction_code==GLOAD_DES_I && graph_1->node_count==1) + { + linearize_graph (graph_2->instruction_parameters[1].p,&ad_1); + in_address_register (&ad_1); + if (--*ad_1.ad_count_p==0) + free_aregister (ad_1.ad_register); + i_cmpw_d_id (graph_1->instruction_parameters[0].l, + graph_1->instruction_parameters[1].i, + graph_2->instruction_parameters[0].i,ad_1.ad_register); + return i_test_1; + } else { + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + } else { + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_1,&ad_1); + } + + mode_1=ad_1.ad_mode; + mode_2=ad_2.ad_mode; + + if (mode_1==P_IMMEDIATE && ! (mode_2==P_IMMEDIATE || mode_2==P_DESCRIPTOR_NUMBER)){ + LONG i; +#ifdef M68000 + int real_dreg_number; +#endif + i=ad_1.ad_offset; +#ifdef M68000 + if (i<128 && i>=-128 && i!=0 && (real_dreg_number=try_get_real_dregister_number())>=0){ + int dreg; + + dreg=num_to_d_reg (real_dreg_number); + i_move_i_r (i,dreg); + instruction_ad_r (ICMP,&ad_2,dreg); + free_dregister (dreg); + return i_test_2; + } else { +#endif + instruction_i_ad (ICMP,i,&ad_2); + return i_test_1; +#ifdef M68000 + } +#endif + } else if (mode_1==P_DESCRIPTOR_NUMBER + && ! (mode_2==P_IMMEDIATE || mode_2==P_DESCRIPTOR_NUMBER)){ + instruction_d_ad (ICMP,ad_1.ad_label,ad_1.ad_offset,&ad_2); + return i_test_1; + } else if (mode_2==P_IMMEDIATE + && ! (mode_1==P_IMMEDIATE || mode_1==P_DESCRIPTOR_NUMBER)) + { + LONG i; +#ifdef M68000 + int real_dreg_number; +#endif + + i=ad_2.ad_offset; +#ifdef M68000 + if (i<128 && i>=-128 && i!=0 && (real_dreg_number=try_get_real_dregister_number())>=0){ + int dreg; + + dreg=num_to_d_reg (real_dreg_number); + i_move_i_r (i,dreg); + instruction_ad_r (ICMP,&ad_1,dreg); + free_dregister (dreg); + return i_test_1; + } else { +#endif + instruction_i_ad (ICMP,i,&ad_1); + return i_test_2; +#ifdef M68000 + } +#endif + } else if (mode_2==P_DESCRIPTOR_NUMBER + && ! (mode_1==P_IMMEDIATE || mode_1==P_DESCRIPTOR_NUMBER)){ + instruction_d_ad (ICMP,ad_2.ad_label,ad_2.ad_offset,&ad_1); + return i_test_2; + } else if (mode_2==P_REGISTER + || (mode_1!=P_REGISTER && mode_2==P_INDIRECT && *ad_2.ad_count_p==1)){ + in_register (&ad_2); + instruction_ad_r (ICMP,&ad_1,ad_2.ad_register); + if (--*ad_2.ad_count_p==0) + free_register (ad_2.ad_register); + return i_test_1; + } else { + in_register (&ad_1); + instruction_ad_r (ICMP,&ad_2,ad_1.ad_register); + if (--*ad_1.ad_count_p==0) + free_register (ad_1.ad_register); + return i_test_2; + } + } +} + +enum { + CEQ, CNE, CGT, CLT, CGE, CLE, CO, CNO, + CFEQ, CFNE, CFGT, CFLT, CFGE, CFLE +}; + +#define is_float_condition(c) ((c)>=CFEQ) + +int condition_to_set_instruction[]= +{ + ISEQ, ISNE, ISGT, ISLT, ISGE, ISLE, ISO, ISNO, + IFSEQ, IFSNE, IFSGT, IFSLT, IFSGE, IFSLE +}; + +static int condition_to_branch_false_instruction[]= +{ + IBNE, IBEQ, IBLE, IBGE, IBLT, IBGT, IBNO, IBO, + IFBNE, IFBEQ, IFBLE, IFBGE, IFBLT, IFBGT +}; + +static int condition_to_branch_true_instruction[]= +{ + IBEQ, IBNE, IBGT, IBLT, IBGE, IBLE, IBO, IBNO, + IFBEQ, IFBNE, IFBGT, IFBLT, IFBGE, IFBLE +}; + +static void save_condition (INSTRUCTION_GRAPH graph,int condition) +{ + int reg_1; + + reg_1=get_dregister(); + instruction_r (condition_to_set_instruction[condition],reg_1); + + if (graph->instruction_d_min_a_cost>0){ + int areg; + + areg=get_aregister(); + i_move_r_r (reg_1,areg); + reg_1=areg; + } + + register_node (graph,reg_1); + --graph->node_count; +} + +static int float_compare_node (INSTRUCTION_GRAPH graph,int condition_1,int condition_2); +static int linearize_not_condition (INSTRUCTION_GRAPH graph); + +static int linearize_condition (INSTRUCTION_GRAPH graph) +{ + int condition; + + switch (graph->instruction_code){ + case GCMP_EQ: + condition=compare_node (graph,CEQ,CEQ); + break; + case GCMP_LT: + condition=compare_node (graph,CLT,CGT); + break; + case GCMP_GT: + condition=compare_node (graph,CGT,CLT); + break; + case GFCMP_EQ: + condition=float_compare_node (graph,CFEQ,CFEQ); + break; + case GFCMP_LT: + condition=float_compare_node (graph,CFLT,CFGT); + break; + case GFCMP_GT: + condition=float_compare_node (graph,CFGT,CFLT); + break; + case GCNOT: + condition=linearize_not_condition (graph->instruction_parameters[0].p); + break; + case GTEST_O: + if (graph->node_count==0){ +#ifdef sparc + if (graph->inode_arity==0) + return CNE; + else +#endif + return CO; + } /* else default */ + default: + { + ADDRESS ad_1; + + linearize_graph (graph,&ad_1); + + if (ad_1.ad_mode==P_REGISTER && is_a_register (ad_1.ad_register)){ + /* TST.L An is an illegal instruction, use CMP.L #0,An */ + i_cmp_i_r (0,ad_1.ad_register); + if (--*ad_1.ad_count_p==0) + free_aregister (ad_1.ad_register); + } else { + if (ad_1.ad_mode==P_IMMEDIATE) /* TST #d is an illegal instruction */ + in_data_register (&ad_1); + instruction_ad (ITST,&ad_1); + } + return CNE; + } + } + if (graph->node_count>1){ + save_condition (graph,condition); + condition=CNE; + } + return condition; +} + +static int linearize_not_condition (INSTRUCTION_GRAPH graph) +{ + int condition; + + switch (graph->instruction_code){ + case GCMP_EQ: + condition=compare_node (graph,CNE,CNE); + break; + case GCMP_LT: + condition=compare_node (graph,CGE,CLE); + break; + case GCMP_GT: + condition=compare_node (graph,CLE,CGE); + break; + case GFCMP_EQ: + condition=float_compare_node (graph,CFNE,CFNE); + break; + case GFCMP_LT: + condition=float_compare_node (graph,CFGE,CFLE); + break; + case GFCMP_GT: + condition=float_compare_node (graph,CFLE,CFGE); + break; + case GCNOT: + condition=linearize_condition (graph->instruction_parameters[0].p); + break; + case GTEST_O: + if (graph->node_count==0){ +#ifdef sparc + if (graph->inode_arity==0) + return CEQ; + else +#endif + return CNO; + } /* else default */ + default: + { + ADDRESS ad_1; + + linearize_graph (graph,&ad_1); + + if (ad_1.ad_mode==P_REGISTER && is_a_register (ad_1.ad_register)){ + /* TST.L An is an illegal instruction, use CMP.L #0,An */ + /* (MOVE.L An,Dn would be faster */ + i_cmp_i_r (0,ad_1.ad_register); + if (--*ad_1.ad_count_p==0) + free_aregister (ad_1.ad_register); + } else { + if (ad_1.ad_mode==P_IMMEDIATE) /* TST #d is an illegal instruction */ + in_data_register (&ad_1); + instruction_ad (ITST,&ad_1); + } + return CEQ; + } + } + if (graph->node_count>1){ + save_condition (graph,condition); + condition=CEQ; + } + return condition; +} + +static void condition_to_register (INSTRUCTION_GRAPH graph,int condition,ADDRESS *ad_p) +{ + int reg_1; + + reg_1=get_dregister(); + instruction_r (condition_to_set_instruction[condition],reg_1); + + if (graph->instruction_d_min_a_cost>0){ + int areg; + + areg=get_aregister(); + i_move_r_r (reg_1,areg); + reg_1=areg; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); +} + +static void linearize_compare_operator (int i_test_1,int i_test_2,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + int condition; + + condition=compare_node (graph,i_test_1,i_test_2); + condition_to_register (graph,condition,ad_p); +} + +static void linearize_dyadic_non_commutative_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1,ad_2; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + } else { + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_1,&ad_1); + } + +# if defined (G_POWER) || defined (sparc) + if (ad_1.ad_mode==P_IMMEDIATE && ad_2.ad_mode==P_REGISTER && SMALL_IMMEDIATE (-ad_1.ad_offset) && i_instruction_code==ISUB){ + int reg_1; + + if (--*ad_2.ad_count_p==0) + free_register (ad_2.ad_register); + + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + + i_addi_r_r (-ad_1.ad_offset,ad_2.ad_register,reg_1); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); + + return; + } +# endif + + if (graph->instruction_d_min_a_cost<=0) + in_alterable_data_register (&ad_2); + else + in_alterable_address_register (&ad_2); + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + --*ad_2.ad_count_p; + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=ad_2.ad_register; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,ad_p->ad_register); +} + +static void linearize_dyadic_non_commutative_data_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1,ad_2; + int reg_1; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + } else { + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_1,&ad_1); + } + + in_alterable_data_register (&ad_2); + to_data_addressing_mode (&ad_1); + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + --*ad_2.ad_count_p; + reg_1=ad_2.ad_register; + + if (graph->instruction_d_min_a_cost>0){ + int areg; + + areg=get_aregister(); + i_move_r_r (reg_1,areg); + free_dregister (reg_1); + reg_1=areg; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); +} + +#if defined (I486) || defined (G_POWER) +static void linearize_div_mod_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1,ad_2; + int reg_1; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + } else { + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_1,&ad_1); + } + + in_alterable_data_register (&ad_2); + to_data_addressing_mode (&ad_1); + +# ifdef I486 + if ((ad_1.ad_mode==P_IMMEDIATE && !((ad_1.ad_offset & (ad_1.ad_offset-1))==0 && ad_1.ad_offset>0)) || ad_1.ad_mode==P_INDEXED) + in_data_register (&ad_1); +# endif + + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + --*ad_2.ad_count_p; + reg_1=ad_2.ad_register; + + if (graph->instruction_d_min_a_cost>0){ + int areg; + + areg=get_aregister(); + i_move_r_r (reg_1,areg); + free_dregister (reg_1); + reg_1=areg; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); +} +#else +static void linearize_mod_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1,ad_2; + int reg_1; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + } else { + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_1,&ad_1); + } + + in_alterable_data_register (&ad_2); + to_data_addressing_mode (&ad_1); + + if (ad_1.ad_mode==P_INDEXED) + in_data_register (&ad_1); + + if (ad_1.ad_mode==P_REGISTER && is_d_register (ad_1.ad_register)){ + if (*ad_1.ad_count_p>1) + in_alterable_data_register (&ad_1); + ++*ad_1.ad_count_p; + reg_1=ad_1.ad_register; + } else + reg_1=get_dregister(); + instruction_ad_r_r (IMOD,&ad_1,reg_1,ad_2.ad_register); + free_dregister (ad_2.ad_register); + + if (graph->instruction_d_min_a_cost>0){ + int areg; + + areg=get_aregister(); + i_move_r_r (reg_1,areg); + free_dregister (reg_1); + reg_1=areg; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); +} +#endif + +static void linearize_shift_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1,ad_2; + int reg_1; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,&ad_2); + } else { + linearize_graph (graph_2,&ad_2); + linearize_graph (graph_1,&ad_1); + } + +#if defined (G_POWER) || defined (sparc) + if (i_instruction_code==ILSL && ad_1.ad_mode==P_IMMEDIATE && (unsigned)ad_1.ad_offset<(unsigned)32){ + in_register (&ad_2); + if (--*ad_2.ad_count_p==0) + free_register (ad_2.ad_register); + + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + + i_lsli_r_r (ad_1.ad_offset,ad_2.ad_register,reg_1); + } else { +#endif + + in_alterable_data_register (&ad_2); + +#ifdef M68000 + if (ad_1.ad_mode!=P_IMMEDIATE || ad_1.ad_offset<=0 || ad_1.ad_offset>8) +#else + if (ad_1.ad_mode!=P_IMMEDIATE || ad_1.ad_offset<0 || ad_1.ad_offset>=32) +#endif + in_data_register (&ad_1); + + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + --*ad_2.ad_count_p; + + reg_1=ad_2.ad_register; + + if (graph->instruction_d_min_a_cost>0){ + int areg; + + areg=get_aregister(); + i_move_r_r (reg_1,areg); + free_dregister (reg_1); + reg_1=areg; + } + +#if defined (G_POWER) || defined (sparc) + } +#endif + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + + ad_p->ad_count_p=&graph->node_count; + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); +} + +static void linearize_integer_o_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_r_p,ADDRESS *ad_f_p, + void linearize_operator (int,INSTRUCTION_GRAPH,ADDRESS *),int i_instruction_code) +{ + INSTRUCTION_GRAPH test_o_graph; + int reg_1; + + test_o_graph=graph->instruction_parameters[2].p; + + if (ad_r_p!=NULL){ + linearize_operator (i_instruction_code,graph,ad_r_p); + } else { + ADDRESS ad_r; + + linearize_operator (i_instruction_code,graph,&ad_r); + + if (graph->node_count>0){ + register_node (graph,ad_r.ad_register); + } else + free_register (ad_r.ad_register); + } + + if (test_o_graph->node_count!=0){ + reg_1=get_dregister(); +#ifdef sparc + instruction_r (condition_to_set_instruction[test_o_graph->inode_arity==0 ? CNE : CO],reg_1); +#else + instruction_r (condition_to_set_instruction[CO],reg_1); +#endif + if (ad_f_p==NULL){ + register_node (test_o_graph,reg_1); + } else { + ad_f_p->ad_mode=P_REGISTER; + ad_f_p->ad_register=reg_1; + ad_f_p->ad_count_p=&test_o_graph->node_count; + + if (test_o_graph->node_count>1) + register_node (test_o_graph,reg_1); + } + } +} + +static void linearize_add_o_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_r_p,ADDRESS *ad_f_p) +{ + linearize_integer_o_operator (graph,ad_r_p,ad_f_p,linearize_dyadic_commutative_operator, +#if defined (sparc) || defined (G_POWER) + IADDO +#else + IADD +#endif + ); +} + +static void linearize_sub_o_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_r_p,ADDRESS *ad_f_p) +{ + linearize_integer_o_operator (graph,ad_r_p,ad_f_p,linearize_dyadic_non_commutative_operator, +#if defined (sparc) || defined (G_POWER) + ISUBO +#else + ISUB +#endif + ); +} + +static void linearize_mul_o_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_r_p,ADDRESS *ad_f_p) +{ + linearize_integer_o_operator (graph,ad_r_p,ad_f_p,linearize_dyadic_commutative_data_operator, +#ifdef G_POWER + IMULO +#else + IMUL +#endif + ); +} + +static void linearize_test_o_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH operator_graph; + + operator_graph=graph->instruction_parameters[0].p; + + switch (operator_graph->instruction_code){ + case GADD_O: + linearize_add_o_operator (operator_graph,NULL,ad_p); + break; + case GMUL_O: + linearize_mul_o_operator (operator_graph,NULL,ad_p); + break; + case GSUB_O: + linearize_sub_o_operator (operator_graph,NULL,ad_p); + break; + default: + internal_error_in_function ("linearize_test_o_operator"); + } +} + +static void linearize_conditional_not_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + int condition; + + condition=linearize_not_condition (graph->instruction_parameters[0].p); + condition_to_register (graph,condition,ad_p); +} + +static void linearize_float_graph (INSTRUCTION_GRAPH graph,ADDRESS *ad_p); + +#define MAX(a,b) ((a)>(b)?(a):(b)) + +static ADDRESS *evaluate_arguments (union instruction_parameter arguments[],int n_arguments) +{ + int argument_number; + char *argument_evaluated; + ADDRESS *ad_a; + char small_argument_evaluated[32]; + + ad_a=(ADDRESS*)memory_allocate (sizeof (ADDRESS) * n_arguments); + + if (n_arguments<32) + argument_evaluated=small_argument_evaluated; + else + argument_evaluated=(char*)memory_allocate (sizeof (char) * n_arguments); + + for (argument_number=0; argument_number<n_arguments; ++argument_number) + argument_evaluated[argument_number]=(arguments[argument_number].p==NULL); + + for (;;){ + int first_argument_number; + INSTRUCTION_GRAPH a_graph_1; + + first_argument_number=0; + while (first_argument_number<n_arguments && argument_evaluated[first_argument_number]) + ++first_argument_number; + + if (first_argument_number>=n_arguments) + break; + + a_graph_1=arguments[first_argument_number].p; + + for (argument_number=first_argument_number+1; argument_number<n_arguments; ++argument_number){ + if (!argument_evaluated[argument_number]){ + INSTRUCTION_GRAPH a_graph_2; + int i1,i2,u1,u2; + int a,d; + + a_graph_2=arguments[argument_number].p; + + a=a_graph_1->i_aregs; d=a_graph_1->i_dregs; i1=AD_REG_WEIGHT (a,d); + a=a_graph_2->i_aregs; d=a_graph_2->i_dregs; i2=AD_REG_WEIGHT (a,d); + + a=a_graph_1->u_aregs; d=a_graph_1->u_dregs; u1=AD_REG_WEIGHT (a,d); + a=a_graph_2->u_aregs; d=a_graph_2->u_dregs; u2=AD_REG_WEIGHT (a,d); + + if (i1<0){ + if (i2<0 && (u2<u1 || (u1==u2 && i2<i1))){ + first_argument_number=argument_number; + a_graph_1=a_graph_2; + } + } else if (i1==0){ + if (i2<0 || (i2==0 && u2<u1)){ + first_argument_number=argument_number; + a_graph_1=a_graph_2; + } + } else { + if (i2<=0 || (u2-i2>u1-i1 || (u2-i2==u1-i1 && i2<i1))){ + first_argument_number=argument_number; + a_graph_1=a_graph_2; + } + } + } + } + + if (a_graph_1->instruction_code==GFHIGH && + first_argument_number+1<n_arguments && + !argument_evaluated[first_argument_number+1]) + { + INSTRUCTION_GRAPH next_graph; + + next_graph=arguments[first_argument_number+1].p; + if (next_graph!=NULL && next_graph->instruction_code==GFLOW && + a_graph_1->instruction_parameters[0].p==next_graph->instruction_parameters[0].p) + { + INSTRUCTION_GRAPH f_graph; + + f_graph=a_graph_1->instruction_parameters[0].p; + arguments[first_argument_number].p=f_graph; + arguments[first_argument_number+1].p=f_graph; + + /* CHANGED 22-10-1999 */ + { + int f_graph_count; + + f_graph_count=f_graph->node_count; + if (--a_graph_1->node_count==0) + --f_graph_count; + if (--next_graph->node_count==0) + --f_graph_count; + f_graph->node_count=f_graph_count+1; + } + /* + --f_graph->node_count; + */ + + linearize_float_graph (f_graph,&ad_a[first_argument_number]); + argument_evaluated[first_argument_number]=1; + argument_evaluated[first_argument_number+1]=1; + + ad_a[first_argument_number].ad_mode+=100; + continue; + } + } + + linearize_graph (a_graph_1,&ad_a[first_argument_number]); + argument_evaluated[first_argument_number]=1; + } + + if (argument_evaluated!=small_argument_evaluated) + memory_free (argument_evaluated); + + return ad_a; +} + +#ifdef M68000 +static void move_float_ad_pi (ADDRESS *ad_p,int areg) +{ + switch (ad_p->ad_mode){ + case P_F_REGISTER: + i_fmove_fr_pi (ad_p->ad_register,areg); + if (--*ad_p->ad_count_p==0) + free_fregister (ad_p->ad_register); + return; + case P_INDIRECT: + if (ad_p->ad_offset==0 && *ad_p->ad_count_p==1){ + i_move_pi_pi (ad_p->ad_register,areg); + i_move_id_pi (0,ad_p->ad_register,areg); + *ad_p->ad_count_p=0; + free_aregister (ad_p->ad_register); + } else { + i_move_id_pi (ad_p->ad_offset,ad_p->ad_register,areg); + i_move_id_pi (ad_p->ad_offset+4,ad_p->ad_register,areg); + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + } + return; + case P_F_IMMEDIATE: + i_move_i_pi (((LONG*)&ad_p->ad_register)[0],areg); + i_move_i_pi (((LONG*)&ad_p->ad_register)[1],areg); + return; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + i_move_x_pi (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,areg); + i_move_x_pi (i_ad_p->ad_offset+(4<<2),i_ad_p->ad_areg,i_ad_p->ad_dreg,areg); + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + } else { + i_move_id_pi (i_ad_p->ad_offset,i_ad_p->ad_register,areg); + i_move_id_pi (i_ad_p->ad_offset+4,i_ad_p->ad_register,areg); + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + } + } else { + i_fmove_fr_pi (i_ad_p->ad_register,areg); + if (--*i_ad_p->ad_count_p==0) + free_fregister (i_ad_p->ad_register); + } + return; + } + default: + internal_error_in_function ("move_float_ad_pi"); + } +} +#endif + +#ifndef M68000 +LONG offset_from_heap_register; +#endif +#ifdef G_POWER +LONG heap_pointer_offset_in_basic_block; +#endif + +void evaluate_arguments_and_free_addresses (union instruction_parameter arguments[],int n_arguments) +{ + ADDRESS *ad_a; + + ad_a=evaluate_arguments (arguments,n_arguments); + memory_free (ad_a); +} + +#if defined (FP_STACK_OPTIMIZATIONS) || defined (FMADD) +#define FP_REG_LAST_USE 4 +#endif + +static void move_float_ad_id (ADDRESS *ad_p,int offset,int areg) +{ + switch (ad_p->ad_mode){ + case P_F_REGISTER: + i_fmove_fr_id (ad_p->ad_register,offset,areg); + if (--*ad_p->ad_count_p==0){ +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_p->ad_register); + } + return; + case P_INDIRECT: +#ifdef M68000 + if (ad_p->ad_offset==0 && *ad_p->ad_count_p==1){ + i_move_pi_id (ad_p->ad_register,offset,areg); + i_move_id_id (0,ad_p->ad_register,offset+4,areg); + *ad_p->ad_count_p=0; + free_aregister (ad_p->ad_register); + } else { +#endif + i_move_id_id (ad_p->ad_offset,ad_p->ad_register,offset,areg); + i_move_id_id (ad_p->ad_offset+4,ad_p->ad_register,offset+4,areg); + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); +#ifdef M68000 + } +#endif + return; + case P_F_IMMEDIATE: + i_move_i_id (((LONG*)&ad_p->ad_register)[0],offset,areg); + i_move_i_id (((LONG*)&ad_p->ad_register)[1],offset+4,areg); + return; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ +#ifdef sparc + if (i_ad_p->ad_offset!=0){ + int a_reg,offset1; + + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + a_reg=get_aregister(); + + offset1=i_ad_p->ad_offset>>2; + + i_lea_x_r (i_ad_p->ad_areg,i_ad_p->ad_dreg,a_reg); + i_move_id_id (offset1,a_reg,offset,areg); + i_move_id_id (offset1+4,a_reg,offset+4,areg); + free_aregister (a_reg); + + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + return; + } +#endif + i_move_x_id (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,offset,areg); + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); +#if defined (M68000) || defined (I486) + i_move_x_id (i_ad_p->ad_offset+(4<<2),i_ad_p->ad_areg,i_ad_p->ad_dreg,offset+4,areg); +#else + { + int a_reg; + + a_reg=get_aregister(); + i_lea_x_r (i_ad_p->ad_areg,i_ad_p->ad_dreg,a_reg); + i_move_id_id (4,a_reg,offset+4,areg); + free_aregister (a_reg); + } +#endif + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + } else { + i_move_id_id (i_ad_p->ad_offset,i_ad_p->ad_register,offset,areg); + i_move_id_id (i_ad_p->ad_offset+4,i_ad_p->ad_register,offset+4,areg); + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + } + } else { + i_fmove_fr_id (i_ad_p->ad_register,offset,areg); + if (--*i_ad_p->ad_count_p==0){ +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (i_ad_p->ad_register); + } + } + return; + } + default: + internal_error_in_function ("move_float_ad_id"); + } +} + +static void linearize_load_graph (register INSTRUCTION_GRAPH load_graph) +{ + if (load_graph!=NULL){ + if (load_graph->node_count>0){ + switch (load_graph->instruction_code){ + case GLOAD: + { + int reg; + + if (load_graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + + i_move_id_r (load_graph->instruction_parameters[0].i,load_graph->instruction_parameters[1].i,reg); + + register_node (load_graph,reg); + break; + } + case GFLOAD: + { + int reg; + + reg=get_fregister(); + + i_fmove_id_fr (load_graph->instruction_parameters[0].i,load_graph->instruction_parameters[1].i,reg); + + float_register_node (load_graph,reg); + + break; + } + case GREGISTER: + case GGREGISTER: + case GFREGISTER: + case GGFREGISTER: + break; + default: + internal_error_in_function ("linearize_load_graph"); + } + } + /* added 24-8-1999 */ + else if (load_graph->instruction_code==GFHIGH || load_graph->instruction_code==GFLOW){ + load_graph=load_graph->instruction_parameters[0].p; + if (load_graph->node_count>0 && load_graph->instruction_code==GFLOAD){ + int reg; + + reg=get_fregister(); + + i_fmove_id_fr (load_graph->instruction_parameters[0].i,load_graph->instruction_parameters[1].i,reg); + + float_register_node (load_graph,reg); + } + } + /* */ + } +} + +static void linearize_create_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p,int result_register) +{ + int argument_number,arity; + ADDRESS *ad_a; + int reg_1,heap_offset; +#ifndef M68000 + int reg_1_allocated; + + reg_1_allocated=0; +#endif + + arity=graph->inode_arity; + + last_block->block_n_new_heap_cells+=arity; + +#ifdef G_POWER + for (argument_number=0; argument_number<arity; ++argument_number){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[argument_number].p; + + if (a_graph!=NULL && a_graph->instruction_code==GCREATE && a_graph->node_count==1) + a_graph->instruction_code=GCREATE_S; + } +#endif + + ad_a=evaluate_arguments (graph->instruction_parameters,arity); + +#ifndef M68000 +# ifdef I486 + if (offset_from_heap_register+(arity<<2) >= 127){ +# else +# ifdef G_POWER + if (offset_from_heap_register+(arity<<2) >= 32767){ + heap_pointer_offset_in_basic_block+=offset_from_heap_register; +# else + if (offset_from_heap_register+(arity<<2) >= 4096){ +# endif +# endif + i_add_i_r (offset_from_heap_register,HEAP_POINTER); + IF_G_POWER(last_heap_pointer_update=last_instruction;) + offset_from_heap_register=0; + } + + heap_offset=offset_from_heap_register; +#else + if (result_register!=0 && try_allocate_register_number (result_register>>1)) + reg_1=result_register>>1; + else + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + + i_move_r_r (HEAP_POINTER,reg_1); + heap_offset=0; +#endif + + for (argument_number=0; argument_number<arity; ++argument_number){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[argument_number].p; + + if (a_graph!=NULL){ +#ifdef M68000 + if (heap_offset>0){ + i_add_i_r (heap_offset,HEAP_POINTER); + heap_offset=0; + } +#endif + if (ad_a[argument_number].ad_mode>=100){ + ad_a[argument_number].ad_mode-=100; +#ifdef M68000 + move_float_ad_pi (&ad_a[argument_number],HEAP_POINTER); +#else +# ifdef G_POWER + move_float_ad_id (&ad_a[argument_number],heap_offset+4,HEAP_POINTER); +# else + move_float_ad_id (&ad_a[argument_number],heap_offset,HEAP_POINTER); +# endif + heap_offset+=8; +#endif + ++argument_number; + } else { +#ifdef M68000 + instruction_ad_pi (IMOVE,&ad_a[argument_number],HEAP_POINTER); +#else +# ifdef G_POWER + if (ad_a[argument_number].ad_mode==P_STORE_HP_INSTRUCTION){ + struct instruction *instruction; + + instruction = (struct instruction*)ad_a[argument_number].ad_offset; + + instruction->instruction_parameters[1].parameter_data.i= + heap_pointer_offset_in_basic_block+heap_offset+4 + -instruction->instruction_parameters[1].parameter_data.i; + } else + instruction_ad_id (IMOVE,&ad_a[argument_number],heap_offset+4,HEAP_POINTER); +# else + instruction_ad_id (IMOVE,&ad_a[argument_number],heap_offset,HEAP_POINTER); +# endif + heap_offset+=4; +#endif + } + } else { + if (arity>3 && graph->instruction_parameters[0].p!=NULL){ +#ifdef M68000 + if (heap_offset>0){ + i_add_i_r (heap_offset,HEAP_POINTER); + heap_offset=0; + } + i_move_r_pi (reg_1,HEAP_POINTER); +#else + if (!reg_1_allocated){ + if (result_register!=0 && try_allocate_register_number (result_register>>1)) + reg_1=result_register>>1; + else + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + +# ifdef G_POWER + i_lea_id_r (offset_from_heap_register+4+NODE_POINTER_OFFSET,HEAP_POINTER,reg_1); +# else + if (offset_from_heap_register==0) + i_move_r_r (HEAP_POINTER,reg_1); + else + i_lea_id_r (offset_from_heap_register,HEAP_POINTER,reg_1); +# endif + + reg_1_allocated=1; + } + +# ifdef G_POWER + i_move_r_id (reg_1,heap_offset+4,HEAP_POINTER); +# else + i_move_r_id (reg_1,heap_offset,HEAP_POINTER); +# endif + heap_offset+=4; +#endif + } else + heap_offset+=4; + } + } + +#ifndef M68000 + if (!reg_1_allocated){ + if (result_register!=0 && try_allocate_register_number (result_register>>1)) + reg_1=result_register>>1; + else + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + +# ifdef G_POWER + i_lea_id_r (offset_from_heap_register+4+NODE_POINTER_OFFSET,HEAP_POINTER,reg_1); +# else + if (offset_from_heap_register==0) + i_move_r_r (HEAP_POINTER,reg_1); + else + i_lea_id_r (offset_from_heap_register,HEAP_POINTER,reg_1); +# endif + } + + offset_from_heap_register=heap_offset; +#else + if (heap_offset>0) + i_add_i_r (heap_offset,HEAP_POINTER); +#endif + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); + + memory_free (ad_a); +} + +#ifdef G_POWER +static struct instruction * +#else +static void +#endif +linearize_store_create_operator (int offset,int stack_pointer,INSTRUCTION_GRAPH graph) +{ + int argument_number; + int arity,heap_offset; + ADDRESS *ad_a; +#ifdef G_POWER + struct instruction *instruction; +#endif + + arity=graph->inode_arity; + + last_block->block_n_new_heap_cells+=arity; + +#ifdef G_POWER + for (argument_number=1; argument_number<arity; ++argument_number){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[argument_number].p; + + if (a_graph!=NULL && a_graph->instruction_code==GCREATE && a_graph->node_count==1) + a_graph->instruction_code=GCREATE_S; + } +#endif + + ad_a=evaluate_arguments (graph->instruction_parameters,arity); + + heap_offset=0-NODE_POINTER_OFFSET; + argument_number=0; + +#ifdef G_POWER +# if NODE_POINTER_OFFSET==0 + if (arity>=1 && graph->instruction_parameters[0].p!=NULL && ad_a[0].ad_mode<100){ + i_move_ad_idu (&ad_a[0],offset_from_heap_register+4,HEAP_POINTER); + heap_pointer_offset_in_basic_block+=offset_from_heap_register+4; + offset_from_heap_register=-4; + heap_offset=4; + ++argument_number; + } else { +#endif + if (offset_from_heap_register!=-(4+NODE_POINTER_OFFSET)){ + i_add_i_r (offset_from_heap_register+(4+NODE_POINTER_OFFSET),HEAP_POINTER); + heap_pointer_offset_in_basic_block+=offset_from_heap_register+(4+NODE_POINTER_OFFSET); + offset_from_heap_register=-(4+NODE_POINTER_OFFSET); + } +# if NODE_POINTER_OFFSET==0 + } +#endif + if (stack_pointer==HEAP_POINTER) + instruction=instruction_move_r_idhp (HEAP_POINTER,heap_pointer_offset_in_basic_block); + else { + i_move_r_id (HEAP_POINTER,offset,stack_pointer); + instruction=NULL; + } + IF_G_POWER (last_heap_pointer_update=last_instruction;) +#else +# ifndef M68000 + if (offset_from_heap_register>0){ + i_add_i_r (offset_from_heap_register,HEAP_POINTER); + IF_G_POWER (last_heap_pointer_update=last_instruction;) + offset_from_heap_register=0; + } +# endif + i_move_r_id (HEAP_POINTER,offset,stack_pointer); +#endif + + for (; argument_number<arity; ++argument_number){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[argument_number].p; + + if (a_graph!=NULL){ +#ifdef M68000 + if (heap_offset>0){ + i_add_i_r (heap_offset,HEAP_POINTER); + heap_offset=0; + } +#endif + if (ad_a[argument_number].ad_mode>=100){ + ad_a[argument_number].ad_mode-=100; +#ifdef M68000 + move_float_ad_pi (&ad_a[argument_number],HEAP_POINTER); +#else + move_float_ad_id (&ad_a[argument_number],heap_offset,HEAP_POINTER); + heap_offset+=8; +#endif + ++argument_number; + } else { +#ifdef M68000 + instruction_ad_pi (IMOVE,&ad_a[argument_number],HEAP_POINTER); +#else +# ifdef G_POWER + if (ad_a[argument_number].ad_mode==P_STORE_HP_INSTRUCTION){ + struct instruction *instruction; + + instruction = (struct instruction*)ad_a[argument_number].ad_offset; + + instruction->instruction_parameters[1].parameter_data.i= + heap_pointer_offset_in_basic_block+heap_offset + -instruction->instruction_parameters[1].parameter_data.i; + } else +# endif + instruction_ad_id (IMOVE,&ad_a[argument_number],heap_offset,HEAP_POINTER); + heap_offset+=4; +#endif + } + } else + heap_offset+=4; + } + +#ifndef M68000 +# ifdef G_POWER + offset_from_heap_register=heap_offset-4; +# else + offset_from_heap_register=heap_offset; +# endif +#else + if (heap_offset>0) + i_add_i_r (heap_offset,HEAP_POINTER); +#endif + + memory_free (ad_a); + +#ifdef G_POWER + return instruction; +#endif +} + +static void linearize_fill_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + int argument_number; + ADDRESS *ad_a; + int reg_1,reg_2,n_arguments; + + n_arguments=graph->inode_arity; + while (n_arguments>1 && graph->instruction_parameters[n_arguments-1].p==NULL) + --n_arguments; + + ad_a=evaluate_arguments (graph->instruction_parameters,n_arguments); + + if (n_arguments==2 && graph->instruction_parameters[1].p!=NULL){ + in_address_register (&ad_a[0]); + reg_1=reg_2=ad_a[0].ad_register; + instruction_ad_id (IMOVE,&ad_a[1],0-NODE_POINTER_OFFSET,reg_2); + if (--*ad_a[0].ad_count_p==0 && graph->node_count==0) + free_aregister (reg_2); + } else if ( n_arguments==3 && graph->instruction_parameters[1].p!=NULL + && graph->instruction_parameters[2].p!=NULL) + { + in_address_register (&ad_a[0]); + reg_1=reg_2=ad_a[0].ad_register; + + if (ad_a[1].ad_mode>=100){ + ad_a[1].ad_mode-=100; + move_float_ad_id (&ad_a[1],0-NODE_POINTER_OFFSET,reg_2); + } else { + instruction_ad_id (IMOVE,&ad_a[1],0-NODE_POINTER_OFFSET,reg_2); + instruction_ad_id (IMOVE,&ad_a[2],4-NODE_POINTER_OFFSET,reg_2); + } + if (--*ad_a[0].ad_count_p==0 && graph->node_count==0) + free_aregister (reg_2); + } else { +#ifndef M68000 + int offset; + + offset=0-NODE_POINTER_OFFSET; +#endif + if (ad_a[0].ad_mode==P_REGISTER && is_d_register (ad_a[0].ad_register) + && graph->instruction_d_min_a_cost<=0 && graph->node_count>0 + && *ad_a[0].ad_count_p<=1) + { + reg_2=ad_a[0].ad_register; + reg_1=get_aregister(); + i_move_r_r (reg_2,reg_1); + } else { +#ifdef M68000 + in_alterable_address_register (&ad_a[0]); +#else + in_address_register (&ad_a[0]); +#endif + + reg_1=ad_a[0].ad_register; + reg_2=reg_1; + +#ifdef M68000 + if (graph->node_count>0){ + if (graph->instruction_d_min_a_cost<=0) + reg_2=get_dregister(); + else + reg_2=get_aregister(); + i_move_r_r (reg_1,reg_2); + } +#endif + } + + for (argument_number=1; argument_number<n_arguments; ++argument_number){ + register INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[argument_number].p; + + if (a_graph!=NULL){ + if (ad_a[argument_number].ad_mode>=100){ + ad_a[argument_number].ad_mode-=100; +#ifdef M68000 + move_float_ad_pi (&ad_a[argument_number],reg_1); +#else + move_float_ad_id (&ad_a[argument_number],offset,reg_1); + offset+=8; +#endif + ++argument_number; + } else { +#ifdef M68000 + if (argument_number!=n_arguments-1) + instruction_ad_pi (IMOVE,&ad_a[argument_number],reg_1); + else + instruction_ad_id (IMOVE,&ad_a[argument_number],0,reg_1); +#else + instruction_ad_id (IMOVE,&ad_a[argument_number],offset,reg_1); + offset+=4; +#endif + } + } else +#ifdef M68000 + i_add_i_r (4,reg_1); +#else + offset+=4; +#endif + } + +#ifndef M68000 + if (reg_1!=reg_2) +#endif + free_aregister (reg_1); + + --*ad_a[0].ad_count_p; + } + + ad_p->ad_mode=P_REGISTER; + + if (reg_1==reg_2 && *ad_a[0].ad_count_p>0 && graph->node_count>1){ + int result_reg; + + if (graph->instruction_d_min_a_cost<=0) + result_reg=get_aregister(); + else + result_reg=get_dregister(); + + i_move_r_r (reg_1,result_reg); + --*ad_a[0].ad_count_p; + + ad_p->ad_register=result_reg; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,result_reg); + } else { + ad_p->ad_register=reg_2; + ad_p->ad_count_p=&graph->node_count; + + if (*ad_p->ad_count_p>1) + register_node (graph,reg_2); + + if (reg_1==reg_2 && *ad_a[0].ad_count_p>0){ + ad_p->ad_count_p=ad_a[0].ad_count_p; + *ad_p->ad_count_p+=graph->node_count; + } + } + + memory_free (ad_a); +} + +static void move_float_ad_x (ADDRESS *ad_p,int offset,int areg,int dreg) +{ + switch (ad_p->ad_mode){ + case P_F_REGISTER: + i_fmove_fr_x (ad_p->ad_register,offset,areg,dreg); + if (--*ad_p->ad_count_p==0){ +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_p->ad_register); + } + return; +#if defined (M68000) || defined (I486) + case P_INDIRECT: +# ifdef M68000 + if (ad_p->ad_offset==0 && *ad_p->ad_count_p==1){ + i_move_pi_x (ad_p->ad_register,offset,areg,dreg); + i_move_id_x (0,ad_p->ad_register,offset+(4<<2),areg,dreg); + *ad_p->ad_count_p=0; + free_aregister (ad_p->ad_register); + } else { +# endif + i_move_id_x (ad_p->ad_offset,ad_p->ad_register,offset,areg,dreg); + i_move_id_x (ad_p->ad_offset+4,ad_p->ad_register,offset+(4<<2),areg,dreg); + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); +# ifdef M68000 + } +# endif + return; + case P_F_IMMEDIATE: + i_move_i_x (((LONG*)&ad_p->ad_register)[0],offset,areg,dreg); + i_move_i_x (((LONG*)&ad_p->ad_register)[1],offset+(4<<2),areg,dreg); + return; +#endif +#ifdef M68000 + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + i_move_x_x (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,offset,areg,dreg); + i_move_x_x (i_ad_p->ad_offset+(4<<2),i_ad_p->ad_areg,i_ad_p->ad_dreg,offset+(4<<2),areg,dreg); + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + } else { + i_move_id_x (i_ad_p->ad_offset,i_ad_p->ad_register,offset,areg,dreg); + i_move_id_x (i_ad_p->ad_offset+4,i_ad_p->ad_register,offset+(4<<2),areg,dreg); + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + } + } else { + i_fmove_fr_x (i_ad_p->ad_register,offset,areg,dreg); + if (--*i_ad_p->ad_count_p==0) + free_fregister (i_ad_p->ad_register); + } + return; + } +#endif + default: + internal_error_in_function ("move_float_ad_x"); + } +} + +static void linearize_fill_r_operator (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + ADDRESS ad_a[3]; + int reg_2; + + linearize_float_graph (graph->instruction_parameters[2].p,&ad_a[2]); + linearize_graph (graph->instruction_parameters[0].p,&ad_a[0]); + linearize_graph (graph->instruction_parameters[1].p,&ad_a[1]); + + in_address_register (&ad_a[0]); + reg_2=ad_a[0].ad_register; + + instruction_ad_id (IMOVE,&ad_a[1],0,reg_2); + move_float_ad_id (&ad_a[2],4,reg_2); + + if (graph->node_count==0) + if (--*ad_a[0].ad_count_p==0) + free_aregister (reg_2); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_2; + ad_p->ad_count_p=&graph->node_count; + + if (*ad_p->ad_count_p>1) + register_node (graph,reg_2); +} + +static void in_float_register (ADDRESS *ad_p); + +static void linearize_store_fill_operator (INSTRUCTION_GRAPH s_graph,INSTRUCTION_GRAPH graph) +{ + int argument_number,stack_offset,stack_pointer,n_arguments; + ADDRESS *ad_a; + int reg_1; +#ifndef M68000 + int offset; +#endif + + n_arguments=graph->inode_arity; + while (n_arguments>1 && graph->instruction_parameters[n_arguments-1].p==NULL) + --n_arguments; + + ad_a=evaluate_arguments (graph->instruction_parameters,n_arguments); + +#ifdef M68000 + if (n_arguments!=2 || graph->instruction_parameters[1].p==NULL) + in_alterable_address_register (&ad_a[0]); + else +#endif + in_address_register (&ad_a[0]); + + reg_1=ad_a[0].ad_register; + + stack_offset=s_graph->instruction_parameters[0].i; + stack_pointer=s_graph->instruction_parameters[1].i; + + if (s_graph->instruction_parameters[3].p!=NULL){ + for (argument_number=1; argument_number<n_arguments; ++argument_number){ + if (graph->instruction_parameters[argument_number].p!=NULL){ + ADDRESS *ad_p; + + ad_p=&ad_a[argument_number]; + if (ad_p->ad_mode==100 + P_INDIRECT){ + if (ad_p->ad_register==stack_pointer && (ad_p->ad_offset==stack_offset || ad_p->ad_offset-4==stack_offset)){ + ad_p->ad_mode=P_INDIRECT; + in_float_register (ad_p); + ad_p->ad_mode+=100; + } + } else if (ad_p->ad_mode==P_INDIRECT){ + if (ad_p->ad_register==stack_pointer && ad_p->ad_offset==stack_offset){ + in_register (ad_p); + } + } + } + } + linearize_load_graph (s_graph->instruction_parameters[3].p); + } + + i_move_r_id (reg_1,stack_offset,stack_pointer); + +#ifndef M68000 + offset=0-NODE_POINTER_OFFSET; +#endif + + for (argument_number=1; argument_number<n_arguments; ++argument_number){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[argument_number].p; + + if (a_graph!=NULL){ + if (ad_a[argument_number].ad_mode>=100){ + ad_a[argument_number].ad_mode-=100; +#ifdef M68000 + move_float_ad_pi (&ad_a[argument_number],reg_1); +#else + move_float_ad_id (&ad_a[argument_number],offset,reg_1); + offset+=8; +#endif + ++argument_number; + } else { +#ifdef M68000 + if (argument_number!=n_arguments-1) + instruction_ad_pi (IMOVE,&ad_a[argument_number],reg_1); + else + instruction_ad_id (IMOVE,&ad_a[argument_number],0,reg_1); +#else + instruction_ad_id (IMOVE,&ad_a[argument_number],offset,reg_1); + offset+=4; +#endif + } + } else +#ifdef M68000 + i_add_i_r (4,reg_1); +#else + offset+=4; +#endif + } + + if (--*ad_a[0].ad_count_p==0) + free_aregister (reg_1); + + memory_free (ad_a); +} + +static int movem_registers (int a_reg,register int n_registers,int registers[],int offset,int update_a_reg) +{ +#ifdef M68000 + if (n_registers>=5){ + i_movem_id (offset,a_reg,n_registers,registers); + return offset+(n_registers<<2); + } else { + register int i; + + for (i=0; i<n_registers; ++i) + if (i==n_registers-1 && !update_a_reg) + i_move_id_r (offset,a_reg,registers[i]); + else { + if (offset!=0){ + i_add_i_r (offset,a_reg); + offset=0; + } + i_move_pi_r (a_reg,registers[i]); + } + return offset; + } +#else + int i; + + for (i=0; i<n_registers; ++i){ + i_move_id_r (offset,a_reg,registers[i]); + offset+=4; + } + return offset; +#endif +} + +static void linearize_movem_operator (INSTRUCTION_GRAPH graph) +{ + ADDRESS ad_1; + int registers[16],offset,n_registers,a_reg,arity,address_register_used; + register int argument_number; + + linearize_graph (graph->instruction_parameters[1].p,&ad_1); + +#ifdef M68000 + in_alterable_address_register (&ad_1); +#else + in_address_register (&ad_1); +#endif + a_reg=ad_1.ad_register; + + arity=graph->inode_arity; + + offset=graph->instruction_parameters[0].i; + address_register_used=0; + n_registers=0; + + for (argument_number=0; argument_number<arity; ++argument_number){ + register INSTRUCTION_GRAPH a_graph; + + a_graph=graph->instruction_parameters[2+argument_number].p; + if (a_graph==NULL || a_graph->node_count<=0){ + if (n_registers>0){ + offset=movem_registers (a_reg,n_registers,registers,offset,1); + address_register_used=0; + n_registers=0; + } + offset+=4; + } else { + if (a_graph->instruction_code==GFMOVEMI){ + int l_f_reg; + + l_f_reg=get_fregister(); + float_register_node (a_graph,l_f_reg); + + if (n_registers>0){ + offset=movem_registers (a_reg,n_registers,registers,offset,1); + address_register_used=0; + n_registers=0; + } + + if (argument_number<arity-2){ +#ifdef M68000 + if (offset){ + i_add_i_r (offset,a_reg); + offset=0; + } + i_fmove_pi_fr (a_reg,l_f_reg); +#else + i_fmove_id_fr (offset,a_reg,l_f_reg); + offset+=8; +#endif + } else + i_fmove_id_fr (offset,a_reg,l_f_reg); + + ++argument_number; + } else { + if (a_graph->instruction_parameters[1].i!=0){ + int reg_n; + + reg_n=a_graph->instruction_parameters[1].i>>1; + if (try_allocate_register_number (reg_n)){ + register_node (a_graph,reg_n); + + offset=movem_registers (a_reg,n_registers,registers,offset,1); + address_register_used=0; + n_registers=0; + + if (argument_number<arity-1){ +#ifdef M68000 + if (offset){ + i_add_i_r (offset,a_reg); + offset=0; + } + i_move_pi_r (a_reg,reg_n); +#else + i_move_id_r (offset,a_reg,reg_n); + offset+=4; +#endif + } else + i_move_id_r (offset,a_reg,reg_n); + continue; + } else + if (reg_n==ad_1.ad_register && *ad_1.ad_count_p==1 + && argument_number==arity-1) + { + register_node (a_graph,reg_n); + + offset=movem_registers (a_reg,n_registers,registers,offset,1); + address_register_used=0; + n_registers=0; + + if (argument_number<arity-1){ +#ifdef M68000 + if (offset){ + i_add_i_r (offset,a_reg); + offset=0; + } + i_move_pi_r (a_reg,reg_n); +#else + i_move_id_r (offset,a_reg,reg_n); + offset+=4; +#endif + } else + i_move_id_r (offset,a_reg,reg_n); + + return; + } + } + + if (a_graph->instruction_d_min_a_cost<=0){ + int l_d_reg; + + l_d_reg=get_dregister(); + register_node (a_graph,l_d_reg); + + if (d_reg_num (l_d_reg)>=N_DATA_PARAMETER_REGISTERS){ + offset=movem_registers (a_reg,n_registers,registers,offset,1); + n_registers=0; + address_register_used=0; + if (argument_number<arity-1){ +#ifdef M68000 + if (offset){ + i_add_i_r (offset,a_reg); + offset=0; + } + i_move_pi_r (a_reg,l_d_reg); +#else + i_move_id_r (offset,a_reg,l_d_reg); + offset+=4; +#endif + } else + i_move_id_r (offset,a_reg,l_d_reg); + } else { + if (address_register_used){ + offset=movem_registers (a_reg,n_registers,registers,offset,1); + n_registers=0; + address_register_used=0; + } + registers[n_registers++]=l_d_reg; + } + } else { + int l_a_reg; + + l_a_reg=get_aregister(); + register_node (a_graph,l_a_reg); + + if (a_reg_num (l_a_reg)>=N_ADDRESS_PARAMETER_REGISTERS){ + offset=movem_registers (a_reg,n_registers,registers,offset,1); + n_registers=0; + address_register_used=0; + if (argument_number<arity-1){ +#ifdef M68000 + if (offset){ + i_add_i_r (offset,a_reg); + offset=0; + } + i_move_pi_r (a_reg,l_a_reg); +#else + i_move_id_r (offset,a_reg,l_a_reg); + offset+=4; +#endif + } else + i_move_id_r (offset,a_reg,l_a_reg); + } else { + registers[n_registers++]=l_a_reg; + address_register_used=1; + } + } + } + } + } + + offset=movem_registers (a_reg,n_registers,registers,offset,0); + + if (--*ad_1.ad_count_p==0) + free_aregister (ad_1.ad_register); +} + +static void linearize_movemi_operator (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + linearize_movem_operator (graph->instruction_parameters[0].p); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=graph->instruction_parameters[0].i; + ad_p->ad_count_p=&graph->node_count; +} + +static void linearize_fmovemi_operator (INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + linearize_movem_operator (graph->instruction_parameters[0].p); + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=graph->instruction_parameters[0].i; + ad_p->ad_count_p=&graph->node_count; +} + +static void linearize_copy_operator (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + ADDRESS ad; + int areg_1,areg_2; + + linearize_graph (graph->instruction_parameters[0].p,&ad); + linearize_graph (graph->instruction_parameters[1].p,ad_p); + +#ifdef M68000 + in_alterable_address_register (&ad); +#else + in_address_register (&ad); +#endif + in_alterable_address_register (ad_p); + + areg_1=ad.ad_register; + areg_2=ad_p->ad_register; + +#ifdef M68000 + i_move_pi_id (areg_1,0,areg_2); + i_move_pi_id (areg_1,4,areg_2); + i_move_pi_id (areg_1,8,areg_2); +#else + i_move_id_id (0,areg_1,0,areg_2); + i_move_id_id (4,areg_1,4,areg_2); + i_move_id_id (8,areg_1,8,areg_2); +#endif + + if (--*ad.ad_count_p==0) + free_aregister (ad.ad_register); + + if (*ad_p->ad_count_p>1) + *ad_p->ad_count_p += graph->node_count-1; + else { + ad_p->ad_count_p=&graph->node_count; + register_node (graph,areg_2); + } +} + +#define FLOAT_SIZE 8 + +static void in_alterable_float_register (ADDRESS *ad_p) +{ + int freg; + + switch (ad_p->ad_mode){ + case P_F_REGISTER: + if (*ad_p->ad_count_p==1) + return; + freg=get_fregister(); + i_fmove_fr_fr (ad_p->ad_register,freg); + --*ad_p->ad_count_p; + break; + case P_INDIRECT: + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + freg=get_fregister(); + i_fmove_id_fr (ad_p->ad_offset,ad_p->ad_register,freg); + break; + case P_F_IMMEDIATE: + freg=get_fregister(); + i_fmove_if_fr (ad_p->ad_real,freg); + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + freg=get_fregister(); + i_fmove_x_fr (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,freg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + freg=get_fregister(); + i_fmove_id_fr (i_ad_p->ad_offset,i_ad_p->ad_register,freg); + } + i_ad_p->ad_register=freg; + } else { + freg=i_ad_p->ad_register; + } + break; + } + default: + internal_error_in_function ("in_alterable_float_register"); + return; + } + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=freg; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1; +} + +static void in_float_register (ADDRESS *ad_p) +{ + int freg; + + switch (ad_p->ad_mode){ + case P_F_REGISTER: + return; + case P_INDIRECT: + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + freg=get_fregister(); + i_fmove_id_fr (ad_p->ad_offset,ad_p->ad_register,freg); + break; + case P_F_IMMEDIATE: + freg=get_fregister(); + i_fmove_if_fr (ad_p->ad_real,freg); + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + freg=get_fregister(); + i_fmove_x_fr (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,freg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + freg=get_fregister(); + i_fmove_id_fr (i_ad_p->ad_offset,i_ad_p->ad_register,freg); + } + i_ad_p->ad_register=freg; + } else { + freg=i_ad_p->ad_register; + } + break; + } + default: + internal_error_in_function ("in_float_register"); + return; + } + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=freg; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1; +} + +static void instruction_ad_fr (int instruction_code,ADDRESS *ad_p,int register_1) +{ + struct instruction *instruction; + struct parameter *parameter_p; + + instruction=i_new_instruction2 (instruction_code); + + parameter_p=&instruction->instruction_parameters[0]; + + switch (ad_p->ad_mode){ + case P_F_REGISTER: + set_float_register_parameter (*parameter_p,ad_p->ad_register); +#if defined (FMADD) + parameter_p->parameter_flags=0; +#endif + if (--*ad_p->ad_count_p==0){ +#if defined (FP_STACK_OPTIMIZATIONS) || defined (FMADD) + parameter_p->parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_p->ad_register); + } + break; + case P_INDIRECT: + parameter_p->parameter_type=P_INDIRECT; + parameter_p->parameter_offset=ad_p->ad_offset; + parameter_p->parameter_data.i=ad_p->ad_register; + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + break; + case P_F_IMMEDIATE: + { + DOUBLE *rp; + + parameter_p->parameter_type=P_F_IMMEDIATE; + rp=(DOUBLE*)fast_memory_allocate (sizeof (DOUBLE)); + parameter_p->parameter_data.r=rp; + *rp=ad_p->ad_real; + break; + } + case P_INDEXED: + { + struct index_registers *index_registers; + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + index_registers=(struct index_registers*)fast_memory_allocate (sizeof (struct index_registers)); + + parameter_p->parameter_type=P_INDEXED; + parameter_p->parameter_offset=i_ad_p->ad_offset; + parameter_p->parameter_data.ir=index_registers; + + index_registers->a_reg.r=i_ad_p->ad_areg; + index_registers->d_reg.r=i_ad_p->ad_dreg; + + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + } else { + parameter_p->parameter_type=P_INDIRECT; + parameter_p->parameter_offset=i_ad_p->ad_offset; + parameter_p->parameter_data.i=i_ad_p->ad_register; + + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + } + } else { + set_float_register_parameter (*parameter_p,i_ad_p->ad_register); + if (--*i_ad_p->ad_count_p==0){ +#ifdef FP_STACK_OPTIMIZATIONS + parameter_p->parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (i_ad_p->ad_register); + } + } + break; + } + default: + internal_error_in_function ("instruction_ad_fr"); + } + + set_float_register_parameter (instruction->instruction_parameters[1],register_1); +} + +static void instruction_p_fr (int instruction_code,struct parameter *parameter1_p,int register_1) +{ + struct instruction *instruction; + + instruction=i_new_instruction (instruction_code,2,2*sizeof (struct parameter)); + + instruction->instruction_parameters[0]=*parameter1_p; + + set_float_register_parameter (instruction->instruction_parameters[1],register_1); +} + +static void instruction_lad_fr (int instruction_code,ADDRESS *ad_p,int f_register_1) +{ + register struct instruction *instruction; + + instruction=i_new_instruction2 (instruction_code); + + ad_to_parameter (ad_p,&instruction->instruction_parameters[0]); + + set_float_register_parameter (instruction->instruction_parameters[1],f_register_1); +} + +static void linearize_fhigh_operator (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + linearize_float_graph (graph->instruction_parameters[0].p,ad_p); + + switch (ad_p->ad_mode){ + case P_INDIRECT: + if (graph->node_count>1){ + int reg; + + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + i_move_id_r (ad_p->ad_offset,ad_p->ad_register,reg); + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg; + ad_p->ad_count_p=&graph->node_count; + + graph->instruction_code=P_REGISTER; + graph->instruction_parameters[0].i=reg; + } + return; + case P_F_REGISTER: + local_data_offset-=FLOAT_SIZE; + + i_fmove_fr_id (ad_p->ad_register,local_data_offset,B_STACK_POINTER); + if (--*ad_p->ad_count_p==0){ +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_p->ad_register); + } + + if (graph->node_count>1){ + int reg; + + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + i_move_id_r (local_data_offset,B_STACK_POINTER,reg); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,reg); + } else { + ad_p->ad_mode=P_INDIRECT; + ad_p->ad_offset=local_data_offset; + ad_p->ad_register=B_STACK_POINTER; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=graph->node_count+1; + } +#ifdef g_fhighlow + { + INSTRUCTION_GRAPH low_graph; + + low_graph=graph->instruction_parameters[1].p; + + if (low_graph!=NULL){ + low_graph->instruction_code=GLOAD; + low_graph->instruction_parameters[0].i=local_data_offset+4; + low_graph->instruction_parameters[1].i=B_STACK_POINTER; + } + } +#endif + return; + case P_F_IMMEDIATE: + { + DOUBLE r; + + r=ad_p->ad_real; + + if (graph->node_count>1){ + int reg; + + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + + i_move_i_r (((LONG*)&r)[0],reg); + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,reg); + } else { + ad_p->ad_mode=P_IMMEDIATE; + ad_p->ad_offset=((LONG*)&r)[0]; + } + return; + } + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (graph->node_count>1){ + int reg; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + i_move_x_r (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,reg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + i_move_id_r (i_ad_p->ad_offset,i_ad_p->ad_register,reg); + } + i_ad_p->ad_register=reg; + } else { + int reg; + + local_data_offset-=FLOAT_SIZE; + + i_fmove_fr_id (i_ad_p->ad_register,local_data_offset,B_STACK_POINTER); +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (i_ad_p->ad_register); + + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + i_move_id_r (local_data_offset,B_STACK_POINTER,reg); + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg; + ad_p->ad_count_p=&graph->node_count; + + graph->instruction_code=P_REGISTER; + graph->instruction_parameters[0].i=reg; + + register_node (graph,reg); + } else { + if (load_x_graph->inode_arity==1){ + } else { + local_data_offset-=FLOAT_SIZE; + + i_fmove_fr_id (i_ad_p->ad_register,local_data_offset,B_STACK_POINTER); +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (i_ad_p->ad_register); + + ad_p->ad_mode=P_INDIRECT; + ad_p->ad_offset=local_data_offset; + ad_p->ad_register=B_STACK_POINTER; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=graph->node_count+1; + } + } + return; + } + + default: + internal_error_in_function ("linearize_fhigh_operator"); + } +} + +static void linearize_flow_operator (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + linearize_float_graph (graph->instruction_parameters[0].p,ad_p); + + switch (ad_p->ad_mode){ + case P_INDIRECT: + if (graph->node_count>1){ + register int reg; + + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + i_move_id_r (ad_p->ad_offset+4,ad_p->ad_register,reg); + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,reg); + } else + ad_p->ad_offset+=4; + return; + case P_F_REGISTER: + local_data_offset-=FLOAT_SIZE; + + i_fmove_fr_id (ad_p->ad_register,local_data_offset,B_STACK_POINTER); + if (--*ad_p->ad_count_p==0) +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_p->ad_register); + + if (graph->node_count>1){ + int reg; + + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + i_move_id_r (local_data_offset+4,B_STACK_POINTER,reg); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg; + ad_p->ad_count_p=&graph->node_count; + + graph->instruction_code=P_REGISTER; + graph->instruction_parameters[0].i=reg; + } else { + ad_p->ad_mode=P_INDIRECT; + ad_p->ad_offset=local_data_offset+4; + ad_p->ad_register=B_STACK_POINTER; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=graph->node_count+1; + } +#ifdef g_fhighlow + { + INSTRUCTION_GRAPH high_graph; + + high_graph=graph->instruction_parameters[1].p; + + if (high_graph!=NULL){ + high_graph->instruction_code=GLOAD; + high_graph->instruction_parameters[0].i=local_data_offset; + high_graph->instruction_parameters[1].i=B_STACK_POINTER; + } + } +#endif + return; + case P_F_IMMEDIATE: + { + DOUBLE r; + + r=ad_p->ad_real; + + if (graph->node_count>1){ + int reg; + + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + + i_move_i_r (((LONG*)&r)[1],reg); + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,reg); + } else { + ad_p->ad_mode=P_IMMEDIATE; + ad_p->ad_offset=((LONG*)&r)[1]; + } + return; + } + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_p->ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; + + if (graph->node_count>1){ + int reg; + + if (load_x_graph->inode_arity==1){ + load_x_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + i_move_x_r (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,reg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + if (graph->instruction_d_min_a_cost<=0) + reg=get_dregister(); + else + reg=get_aregister(); + i_move_id_r (i_ad_p->ad_offset,i_ad_p->ad_register,reg); + } + i_ad_p->ad_register=reg; + } else + reg=i_ad_p->ad_register; + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg; + ad_p->ad_count_p=&graph->node_count; + + graph->instruction_code=P_REGISTER; + graph->instruction_parameters[0].i=reg; + } else { + if (load_x_graph->inode_arity==1){ + if (i_ad_p->ad_mode==P_INDEXED) + i_ad_p->ad_offset+=4<<2; + else + i_ad_p->ad_offset+=4; + } else { + local_data_offset-=FLOAT_SIZE; + + i_fmove_fr_id (i_ad_p->ad_register,local_data_offset,B_STACK_POINTER); +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (i_ad_p->ad_register); + + ad_p->ad_mode=P_INDIRECT; + ad_p->ad_offset=local_data_offset+4; + ad_p->ad_register=B_STACK_POINTER; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=graph->node_count+1; + } + } + return; + } + default: + internal_error_in_function ("linearize_flow_operator"); + } +} + +static void linearize_fjoin_operator (INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH high_graph,low_graph; + ADDRESS ad_1,ad_2; + + high_graph=graph->instruction_parameters[0].p; + low_graph=graph->instruction_parameters[1].p; + +#ifdef g_fhighlow + linearize_graph (low_graph,&ad_2); + linearize_graph (high_graph,&ad_1); +#else + linearize_graph (high_graph,&ad_1); + linearize_graph (low_graph,&ad_2); +#endif + +#ifdef sparc + if (ad_1.ad_mode==P_INDIRECT && ad_2.ad_mode==P_INDIRECT){ + int freg; + + freg=get_fregister(); + instruction_ad_fr (IFMOVEHI,&ad_1,freg); + instruction_ad_fr (IFMOVELO,&ad_2,freg); + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=freg; + ad_p->ad_count_p=&graph->node_count; + + if (graph->node_count>1) + float_register_node (graph,freg); + + return; + } +#endif + + local_data_offset-=FLOAT_SIZE; + +#ifdef g_fhighlow + instruction_ad_id (IMOVE,&ad_2,local_data_offset+4,B_STACK_POINTER); + instruction_ad_id (IMOVE,&ad_1,local_data_offset,B_STACK_POINTER); +#else + instruction_ad_id (IMOVE,&ad_1,local_data_offset,B_STACK_POINTER); + instruction_ad_id (IMOVE,&ad_2,local_data_offset+4,B_STACK_POINTER); +#endif + + if (graph->node_count>1){ + int freg; + + freg=get_fregister(); + i_fmove_id_fr (local_data_offset,B_STACK_POINTER,freg); + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=freg; + ad_p->ad_count_p=&graph->node_count; + + float_register_node (graph,freg); + } else { + ad_p->ad_mode=P_INDIRECT; + ad_p->ad_offset=local_data_offset; + ad_p->ad_register=B_STACK_POINTER; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1+1; + } +} + +static int float_compare_node (INSTRUCTION_GRAPH graph,int i_test_1,int i_test_2) +{ + ADDRESS ad_1,ad_2; + + linearize_float_graph (graph->instruction_parameters[0].p,&ad_1); + linearize_float_graph (graph->instruction_parameters[1].p,&ad_2); + + if (ad_1.ad_mode==P_F_REGISTER){ + instruction_ad_fr (IFCMP,&ad_2,ad_1.ad_register); + if (--*ad_1.ad_count_p==0){ +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[1].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_1.ad_register); + } + return i_test_2; + } else { + in_float_register (&ad_2); + instruction_ad_fr (IFCMP,&ad_1,ad_2.ad_register); + if (--*ad_2.ad_count_p==0){ +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[1].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_2.ad_register); + } + return i_test_1; + } +} + +static void linearize_float_compare_operator (int i_test_1,int i_test_2,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + int condition; + + condition=float_compare_node (graph,i_test_1,i_test_2); + condition_to_register (graph,condition,ad_p); +} + +static void linearize_dyadic_commutative_float_operator (int instruction_code,register INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + ADDRESS ad_1,ad_2; + int reg_1; + + if (graph->order_left){ + linearize_float_graph (graph->instruction_parameters[0].p,&ad_1); + linearize_float_graph (graph->instruction_parameters[1].p,&ad_2); + } else { + linearize_float_graph (graph->instruction_parameters[1].p,&ad_2); + linearize_float_graph (graph->instruction_parameters[0].p,&ad_1); + } + + if (ad_1.ad_mode==P_F_REGISTER && *ad_1.ad_count_p==1 + /* added 17-3-1999: prefer result in lowest register number */ + && !(ad_2.ad_mode==P_F_REGISTER && *ad_2.ad_count_p==1 && ad_2.ad_register<ad_1.ad_register) + /* */ + ){ + reg_1=ad_1.ad_register; + instruction_ad_fr (instruction_code,&ad_2,reg_1); + + *ad_1.ad_count_p=0; + } else { +#if 1 + struct parameter parameter1; + int free_f_register; + +#if defined (FMADD) + parameter1.parameter_flags=0; +#endif + free_f_register=fad_to_parameter (&ad_1,¶meter1); + in_alterable_float_register (&ad_2); + if (free_f_register){ +#if defined (FP_STACK_OPTIMIZATIONS) || defined (FMADD) + parameter1.parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_1.ad_register); + } + reg_1=ad_2.ad_register; + instruction_p_fr (instruction_code,¶meter1,reg_1); +#else + in_alterable_float_register (&ad_2); + reg_1=ad_2.ad_register; + instruction_ad_fr (instruction_code,&ad_1,reg_1); +#endif + --*ad_2.ad_count_p; + } + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + if (*ad_p->ad_count_p>1) + float_register_node (graph,reg_1); +} + +static void linearize_dyadic_non_commutative_float_operator (int instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + ADDRESS ad_1,ad_2; + int reg_1; + + if (graph->order_left){ + linearize_float_graph (graph->instruction_parameters[0].p,&ad_1); + linearize_float_graph (graph->instruction_parameters[1].p,&ad_2); + } else { + linearize_float_graph (graph->instruction_parameters[1].p,&ad_2); + linearize_float_graph (graph->instruction_parameters[0].p,&ad_1); + } + +#if 1 +# if defined (I486) || defined (G_POWER) + /* added 15-12-1998 */ + if (ad_1.ad_mode==P_F_REGISTER && *ad_1.ad_count_p==1 + && !(ad_2.ad_mode==P_F_REGISTER && ad_2.ad_register<ad_1.ad_register && *ad_2.ad_count_p==1) + ){ + reg_1=ad_1.ad_register; + instruction_ad_fr (instruction_code,&ad_2,reg_1); + last_instruction->instruction_parameters[1].parameter_flags=1; + + *ad_1.ad_count_p=0; + } else +# endif + { + struct parameter parameter1; + int free_f_register; + +# if defined (FMADD) + parameter1.parameter_flags=0; +# endif + + free_f_register=fad_to_parameter (&ad_1,¶meter1); + in_alterable_float_register (&ad_2); + if (free_f_register){ +#if defined (FP_STACK_OPTIMIZATIONS) || defined (FMADD) + parameter1.parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_1.ad_register); + } + reg_1=ad_2.ad_register; + instruction_p_fr (instruction_code,¶meter1,reg_1); +# if defined (I486) || defined (G_POWER) + last_instruction->instruction_parameters[1].parameter_flags=0; +# endif + } +#else + in_alterable_float_register (&ad_2); + reg_1=ad_2.ad_register; + instruction_ad_fr (instruction_code,&ad_1,reg_1); +# if defined (I486) || defined (G_POWER) + last_instruction->instruction_parameters[1].parameter_flags=0; +# endif +#endif + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + if (*ad_p->ad_count_p>1) + float_register_node (graph,reg_1); +} + +static void linearize_itor_operator (INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + int reg_1; + + linearize_graph (graph->instruction_parameters[0].p,ad_p); + to_data_addressing_mode (ad_p); + + reg_1=get_fregister(); + instruction_lad_fr (IFMOVEL,ad_p,reg_1); + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + if (*ad_p->ad_count_p>1) + float_register_node (graph,reg_1); +} + +static void linearize_monadic_float_operator (INSTRUCTION_GRAPH graph,register ADDRESS *ad_p,int i_code) +{ + int freg; + + linearize_float_graph (graph->instruction_parameters[0].p,ad_p); + + if (ad_p->ad_mode==P_F_REGISTER && *ad_p->ad_count_p==1){ + free_fregister (ad_p->ad_register); + freg=get_fregister(); + instruction_fr_fr (i_code,ad_p->ad_register,freg); +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + } else { + freg=get_fregister(); + instruction_ad_fr (i_code,ad_p,freg); + } + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=freg; + ad_p->ad_count_p=&graph->node_count; + + if (*ad_p->ad_count_p>1) + float_register_node (graph,freg); +} + +static void linearize_float_keep_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + linearize_graph (graph_1,&ad_1); + + switch (ad_1.ad_mode){ + case P_REGISTER: + case P_INDIRECT: + if (--*ad_1.ad_count_p==0) + free_register (ad_1.ad_register); + } + + linearize_float_graph (graph_2,ad_p); + + if (graph->node_count>1){ + in_float_register (ad_p); +/* changed 10-12-97 + float_register_node (graph,ad_p->ad_register); + ad_p->ad_count_p=&graph->node_count; +*/ + float_register_node (graph_2,ad_p->ad_register); + graph_2->node_count += graph->node_count; + ad_p->ad_count_p=&graph_2->node_count; + + graph->instruction_parameters[0].p=graph_2; + graph->instruction_code=GINDIRECTION; +/* */ + } +} + +static void linearize_fload_x_operator (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int offset; + + graph_1=graph->instruction_parameters[0].p; + offset=graph->instruction_parameters[1].i; + graph_2=graph->instruction_parameters[2].p; + + if (graph_2!=NULL){ + ADDRESS ad_1; + + if (graph->order_left){ + linearize_graph (graph_1,ad_p); + linearize_graph (graph_2,&ad_1); + } else { + linearize_graph (graph_2,&ad_1); + linearize_graph (graph_1,ad_p); + } + + in_data_register (&ad_1); + in_address_register (ad_p); + + if (graph->node_count<=1){ + ADDRESS *i_ad_p; + + ad_p->ad_mode=P_INDEXED; + ad_p->ad_offset=(LONG)graph; + + i_ad_p=(ADDRESS*)fast_memory_allocate (sizeof (ADDRESS)); + graph->instruction_parameters[1].p=(INSTRUCTION_GRAPH)i_ad_p; + + i_ad_p->ad_mode=P_INDEXED; + i_ad_p->ad_offset=offset; + i_ad_p->ad_areg=ad_p->ad_register; + i_ad_p->ad_dreg=ad_1.ad_register; + + i_ad_p->ad_count_p=ad_p->ad_count_p; + if (ad_1.ad_count_p!=&ad_1.ad_count) + /* it points to a counter in a graph node */ + i_ad_p->ad_count_p2=ad_1.ad_count_p; + else { + /* prevent a scope problem */ + i_ad_p->ad_count_p2=&ad_p->ad_count2; + ad_p->ad_count2=ad_1.ad_count; + } + graph->node_count=0; + graph->inode_arity=1; + } else { + int reg_1; + + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + if (--*ad_1.ad_count_p==0) + free_dregister (ad_1.ad_register); + + reg_1=get_fregister(); + i_fmove_x_fr (offset,ad_p->ad_register,ad_1.ad_register,reg_1); + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + float_register_node (graph,reg_1); + } + } else { + linearize_graph (graph_1,ad_p); + in_address_register (ad_p); + + if (graph->node_count<=1){ + ADDRESS *i_ad_p; + + ad_p->ad_mode=P_INDEXED; + ad_p->ad_offset=(LONG)graph; + + i_ad_p=(ADDRESS*)fast_memory_allocate (sizeof (ADDRESS)); + graph->instruction_parameters[1].p=(INSTRUCTION_GRAPH)i_ad_p; + + i_ad_p->ad_mode=P_INDIRECT; + i_ad_p->ad_offset=offset>>2; + i_ad_p->ad_register=ad_p->ad_register; + i_ad_p->ad_count_p=ad_p->ad_count_p; + + graph->node_count=0; + graph->inode_arity=1; + } else { + int reg_1; + + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + + reg_1=get_fregister(); + i_fmove_id_fr (offset>>2,ad_p->ad_register,reg_1); + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + float_register_node (graph,reg_1); + } + } +} + +static void linearize_float_graph (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + switch (graph->instruction_code){ + case GFREGISTER: + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=graph->instruction_parameters[0].i; + ad_p->ad_count_p=&graph->node_count; + break; + case GGFREGISTER: + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=graph->instruction_parameters[0].i; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1+1; + break; + case GFLOAD: + { + if (graph->node_count<=1){ + ad_p->ad_mode=P_INDIRECT; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1+1; + ad_p->ad_offset=graph->instruction_parameters[0].i; + ad_p->ad_register=graph->instruction_parameters[1].i; + graph->node_count=0; + } else { + int reg_1; + + reg_1=get_fregister(); + + i_fmove_id_fr (graph->instruction_parameters[0].i, + graph->instruction_parameters[1].i,reg_1); + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + float_register_node (graph,reg_1); + } + return; + } + case GFLOAD_I: + if (graph->node_count<=1){ + ad_p->ad_mode=P_F_IMMEDIATE; + ad_p->ad_real=*(DOUBLE*)&graph->instruction_parameters[0]; + } else { + int reg_1; + + reg_1=get_fregister(); + i_fmove_if_fr (*(DOUBLE*)&graph->instruction_parameters[0],reg_1); + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + float_register_node (graph,reg_1); + } + return; + case GFLOAD_ID: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=graph->instruction_parameters[1].p; + linearize_graph (graph_1,ad_p); + in_address_register (ad_p); + + if (graph->node_count<=1){ + ad_p->ad_mode=P_INDIRECT; + ad_p->ad_offset=graph->instruction_parameters[0].i; + /* added 26-7-97 */ + --graph->node_count; + /* */ + } else { + int reg_1; + + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + + reg_1=get_fregister(); + i_fmove_id_fr (graph->instruction_parameters[0].i,ad_p->ad_register,reg_1); + + ad_p->ad_mode=P_F_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + float_register_node (graph,reg_1); + } + return; + } + case GFMOVEMI: + linearize_fmovemi_operator (graph,ad_p); + return; + case GFLOAD_X: + linearize_fload_x_operator (graph,ad_p); + return; + case GFADD: + linearize_dyadic_commutative_float_operator (IFADD,graph,ad_p); + return; + case GFDIV: + linearize_dyadic_non_commutative_float_operator (IFDIV,graph,ad_p); + return; + case GFMUL: + linearize_dyadic_commutative_float_operator (IFMUL,graph,ad_p); + return; + case GFREM: + linearize_dyadic_non_commutative_float_operator (IFREM,graph,ad_p); + return; + case GFSUB: + linearize_dyadic_non_commutative_float_operator (IFSUB,graph,ad_p); + return; + case GFJOIN: + linearize_fjoin_operator (graph,ad_p); + return; + case GFITOR: + linearize_itor_operator (graph,ad_p); + return; + case GFCOS: + linearize_monadic_float_operator (graph,ad_p,IFCOS); + break; + case GFNEG: + linearize_monadic_float_operator (graph,ad_p,IFNEG); + break; + case GFSIN: + linearize_monadic_float_operator (graph,ad_p,IFSIN); + break; + case GFTAN: + linearize_monadic_float_operator (graph,ad_p,IFTAN); + break; +#ifdef M68000 + case GFASIN: + linearize_monadic_float_operator (graph,ad_p,IFASIN); + break; + case GFACOS: + linearize_monadic_float_operator (graph,ad_p,IFACOS); + break; + case GFATAN: + linearize_monadic_float_operator (graph,ad_p,IFATAN); + break; + case GFLN: + linearize_monadic_float_operator (graph,ad_p,IFLN); + break; + case GFLOG10: + linearize_monadic_float_operator (graph,ad_p,IFLOG10); + break; + case GFEXP: + linearize_monadic_float_operator (graph,ad_p,IFEXP); + break; +#endif + case GFKEEP: + linearize_float_keep_operator (graph,ad_p); + break; +/* added 10-12-97 */ + case GINDIRECTION: + linearize_float_graph (graph->instruction_parameters[0].p,ad_p); + break; +/* */ +#if !defined (G_POWER) + case GFSQRT: + linearize_monadic_float_operator (graph,ad_p,IFSQRT); + break; +#endif + default: + /* printf ("%d %d\n",(int)graph,graph->instruction_code); */ + internal_error_in_function ("linearize_float_graph"); + } +} + +static void linearize_fstore_operator (register INSTRUCTION_GRAPH graph) +{ + int offset,stack_pointer; + ADDRESS ad_1; + + linearize_float_graph (graph->instruction_parameters[2].p,&ad_1); + + offset=graph->instruction_parameters[0].i; + stack_pointer=graph->instruction_parameters[1].i; + + linearize_load_graph (graph->instruction_parameters[3].p); + linearize_load_graph (graph->instruction_parameters[4].p); + + move_float_ad_id (&ad_1,offset,stack_pointer); +} + +static void linearize_fstore_x_operator (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p); + +static void linearize_fstore_r_operator (register INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH *register_graph_1_p,*register_graph_2_p; + register int reg_1; + ADDRESS ad_1; + + linearize_float_graph (graph->instruction_parameters[1].p,&ad_1); + + reg_1=graph->instruction_parameters[0].i; + + if ((unsigned)reg_1<(unsigned)N_FLOAT_PARAMETER_REGISTERS) + register_graph_1_p=&global_block.block_graph_f_register_parameter_node[reg_1]; + else + register_graph_1_p=NULL; + + if (ad_1.ad_mode==P_F_REGISTER && ad_1.ad_register==reg_1){ + if (register_graph_1_p!=NULL && *register_graph_1_p!=NULL) + (*register_graph_1_p)->instruction_code=GGFREGISTER; + return; + } + + if (ad_1.ad_mode==P_F_REGISTER){ + register int reg_2; + + reg_2=ad_1.ad_register; + + if ((unsigned)reg_2<(unsigned)N_FLOAT_PARAMETER_REGISTERS) + register_graph_2_p=&global_block.block_graph_f_register_parameter_node[reg_2]; + else + register_graph_2_p=NULL; + + if (register_graph_1_p!=NULL && *register_graph_1_p!=NULL && (*register_graph_1_p)->node_count>0){ +#ifdef FP_STACK_OPTIMIZATIONS + if (register_graph_2_p!=NULL && (*register_graph_2_p==NULL || (*register_graph_2_p)->instruction_code!=GGFREGISTER)){ + INSTRUCTION_GRAPH graph; + + i_fexg_fr_fr (reg_2,reg_1); + + (*register_graph_1_p)->instruction_parameters[0].i=reg_2; + + if (*register_graph_2_p!=NULL){ + (*register_graph_2_p)->instruction_code=GGFREGISTER; + (*register_graph_2_p)->instruction_parameters[0].i=reg_1; + } + + graph=*register_graph_1_p; + *register_graph_1_p=*register_graph_2_p; + *register_graph_2_p=graph; + } else { +#endif + register int reg_2; + + reg_2=get_fregister(); + if ((unsigned)reg_2<(unsigned)N_FLOAT_PARAMETER_REGISTERS) + register_graph_2_p=&global_block.block_graph_f_register_parameter_node [reg_2]; + else + register_graph_2_p=NULL; + + i_fmove_fr_fr (reg_1,reg_2); + instruction_ad_fr (IFMOVE,&ad_1,reg_1); + + (*register_graph_1_p)->instruction_parameters[0].i=reg_2; + + if (register_graph_2_p!=NULL) + *register_graph_2_p=*register_graph_1_p; + + *register_graph_1_p=NULL; +#ifdef FP_STACK_OPTIMIZATIONS + } +#endif + } else { + i_fmove_fr_fr (reg_2,reg_1); + if (--*ad_1.ad_count_p==0){ +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (reg_2); + } + } + } else { + if (ad_1.ad_mode==P_INDIRECT) + --*ad_1.ad_count_p; + if (register_graph_1_p!=NULL && *register_graph_1_p!=NULL + && (*register_graph_1_p)->node_count>0) + { + register int reg_2; + + reg_2=get_fregister(); + if ((unsigned)reg_2<(unsigned)N_FLOAT_PARAMETER_REGISTERS) + register_graph_2_p= + &global_block.block_graph_f_register_parameter_node [reg_2]; + else + register_graph_2_p=NULL; + + i_fmove_fr_fr (reg_1,reg_2); + + (*register_graph_1_p)->instruction_parameters[0].i=reg_2; + + if (register_graph_2_p!=NULL) + *register_graph_2_p=*register_graph_1_p; + + *register_graph_1_p=NULL; + } + if (ad_1.ad_mode==P_INDIRECT) + ++*ad_1.ad_count_p; + instruction_ad_fr (IFMOVE,&ad_1,reg_1); + } + + allocate_fregister (reg_1); +} + +static void linearize_create_r_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p,int result_register) +{ + ADDRESS ad_1,ad_2; + int reg_1; + + last_block->block_n_new_heap_cells+=3; + +#ifndef M68000 +# ifdef I486 + if (offset_from_heap_register+(3<<2) >= 127){ +# else +# ifdef G_POWER + if (offset_from_heap_register+(3<<2) >= 32767){ + heap_pointer_offset_in_basic_block+=offset_from_heap_register; +# else + if (offset_from_heap_register+(3<<2) >= 4096){ +# endif +# endif + i_add_i_r (offset_from_heap_register,HEAP_POINTER); + IF_G_POWER (last_heap_pointer_update=last_instruction;) + offset_from_heap_register=0; + } +#endif + + linearize_float_graph (graph->instruction_parameters[1].p,&ad_2); + linearize_graph (graph->instruction_parameters[0].p,&ad_1); + + if (result_register!=0 && try_allocate_register_number (result_register>>1)) + reg_1=result_register>>1; + else + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + +#ifdef G_POWER + i_lea_id_r (offset_from_heap_register+4+NODE_POINTER_OFFSET,HEAP_POINTER,reg_1); +#else +# ifndef M68000 + if (offset_from_heap_register!=0) + i_lea_id_r (offset_from_heap_register,HEAP_POINTER,reg_1); + else +# endif + i_move_r_r (HEAP_POINTER,reg_1); +#endif + +#ifdef M68000 + instruction_ad_pi (IMOVE,&ad_1,HEAP_POINTER); + move_float_ad_pi (&ad_2,HEAP_POINTER); +#else +# ifdef G_POWER + instruction_ad_id (IMOVE,&ad_1,offset_from_heap_register+4,HEAP_POINTER); + move_float_ad_id (&ad_2,offset_from_heap_register+8,HEAP_POINTER); +# else + instruction_ad_id (IMOVE,&ad_1,offset_from_heap_register,HEAP_POINTER); + move_float_ad_id (&ad_2,offset_from_heap_register+4,HEAP_POINTER); +# endif + offset_from_heap_register+=12; +#endif + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + if (*ad_p->ad_count_p>1) + register_node (graph,reg_1); +} + +static void linearize_rtoi_operator (INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + int reg; + + linearize_float_graph (graph->instruction_parameters[0].p,ad_p); + in_float_register (ad_p); + + reg=get_dregister(); + i_fmovel_fr_r (ad_p->ad_register,reg); + if (--*ad_p->ad_count_p==0){ +#ifdef FP_STACK_OPTIMIZATIONS + last_instruction->instruction_parameters[0].parameter_flags |= FP_REG_LAST_USE; +#endif + free_fregister (ad_p->ad_register); + } + + if (graph->instruction_d_min_a_cost>0){ + int areg; + + areg=get_aregister(); + i_move_r_r (reg,areg); + free_dregister (reg); + reg=areg; + } + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg; + ad_p->ad_count_p=&graph->node_count; + + if (*ad_p->ad_count_p>1) + register_node (graph,reg); +} + +static void linearize_load_x_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p +#ifdef LOAD_X_PARAMETER_REGISTER + ,int result_register +#endif + ) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int offset; + + graph_1=graph->instruction_parameters[0].p; + offset=graph->instruction_parameters[1].i; + graph_2=graph->instruction_parameters[2].p; + + if (graph_2!=NULL){ + ADDRESS ad_1; + + if (graph->order_left){ + linearize_graph (graph_1,ad_p); + linearize_graph (graph_2,&ad_1); + } else { + linearize_graph (graph_2,&ad_1); + linearize_graph (graph_1,ad_p); + } + + in_data_register (&ad_1); + in_address_register (ad_p); + + if (graph->node_count<=1){ + ADDRESS *i_ad_p; + + ad_p->ad_mode=P_INDEXED; + ad_p->ad_offset=(LONG)graph; + + i_ad_p=(ADDRESS*)fast_memory_allocate (sizeof (ADDRESS)); + graph->instruction_parameters[1].p=(INSTRUCTION_GRAPH)i_ad_p; + + i_ad_p->ad_mode=P_INDEXED; + i_ad_p->ad_offset=offset; + i_ad_p->ad_areg=ad_p->ad_register; + i_ad_p->ad_dreg=ad_1.ad_register; + + i_ad_p->ad_count_p=ad_p->ad_count_p; + if (ad_1.ad_count_p!=&ad_1.ad_count) + /* it points to a counter in a graph node */ + i_ad_p->ad_count_p2=ad_1.ad_count_p; + else { + /* prevent a scope problem */ + i_ad_p->ad_count_p2=&ad_p->ad_count2; + ad_p->ad_count2=ad_1.ad_count; + } + + graph->node_count=0; + graph->inode_arity=1; + } else { + int reg_1; + + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + + if (--*ad_1.ad_count_p==0) + free_dregister (ad_1.ad_register); + +#ifdef LOAD_X_PARAMETER_REGISTER + if (result_register!=0 && try_allocate_register_number (result_register>>1)) + reg_1=result_register>>1; + else +#endif + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + + i_move_x_r (offset,ad_p->ad_register,ad_1.ad_register,reg_1); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,reg_1); + } + } else { + linearize_graph (graph_1,ad_p); + in_address_register (ad_p); + + if (graph->node_count<=1){ + ADDRESS *i_ad_p; + + ad_p->ad_mode=P_INDEXED; + ad_p->ad_offset=(LONG)graph; + + i_ad_p=(ADDRESS*)fast_memory_allocate (sizeof (ADDRESS)); + graph->instruction_parameters[1].p=(INSTRUCTION_GRAPH)i_ad_p; + + i_ad_p->ad_mode=P_INDIRECT; + i_ad_p->ad_offset=offset>>2; + i_ad_p->ad_register=ad_p->ad_register; + i_ad_p->ad_count_p=ad_p->ad_count_p; + + graph->node_count=0; + graph->inode_arity=1; + } else { + int reg_1; + + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + +#ifdef LOAD_X_PARAMETER_REGISTER + if (result_register!=0 && try_allocate_register_number (result_register>>1)) + reg_1=result_register>>1; + else +#endif + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + i_move_id_r (offset>>2,ad_p->ad_register,reg_1); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,reg_1); + } + } +} + +static void linearize_store_r_node (INSTRUCTION_GRAPH graph) +{ + INSTRUCTION_GRAPH *register_graph_1_p,*register_graph_2_p; + int reg_1; + ADDRESS ad_1; + + switch (graph->instruction_parameters[1].p->instruction_code){ + case GCREATE: + linearize_create_operator (graph->instruction_parameters[1].p,&ad_1,(graph->instruction_parameters[0].i<<1)+1); + break; + case GCREATE_R: + linearize_create_r_operator (graph->instruction_parameters[1].p,&ad_1,(graph->instruction_parameters[0].i<<1)+1); + break; +#ifdef LOAD_X_PARAMETER_REGISTER + case GLOAD_X: + linearize_load_x_operator (graph->instruction_parameters[1].p,&ad_1,(graph->instruction_parameters[0].i<<1)+1); + break; +#endif + default: + linearize_graph (graph->instruction_parameters[1].p,&ad_1); + } + + reg_1=graph->instruction_parameters[0].i; + + register_graph_1_p=NULL; + + if (is_d_register (reg_1)){ + if ((unsigned)d_reg_num (reg_1)<(unsigned)N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ) + register_graph_1_p=&global_block.block_graph_d_register_parameter_node[d_reg_num (reg_1)]; + } else + if ((unsigned)a_reg_num (reg_1)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + register_graph_1_p=&global_block.block_graph_a_register_parameter_node[a_reg_num (reg_1)]; + + if (ad_1.ad_mode==P_REGISTER && ad_1.ad_register==reg_1){ + if (register_graph_1_p!=NULL && *register_graph_1_p!=NULL) + (*register_graph_1_p)->instruction_code=GGREGISTER; + return; + } + + if (ad_1.ad_mode==P_REGISTER){ + int reg_2; + + reg_2=ad_1.ad_register; + + register_graph_2_p=NULL; + + if ((unsigned)d_reg_num (reg_2)<(unsigned)N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ) + register_graph_2_p=&global_block.block_graph_d_register_parameter_node[d_reg_num (reg_2)]; + + if ((unsigned)a_reg_num (reg_2)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + register_graph_2_p=&global_block.block_graph_a_register_parameter_node[a_reg_num (reg_2)]; + + if (register_graph_1_p!=NULL && *register_graph_1_p!=NULL && (*register_graph_1_p)->node_count>0){ +#if defined (M68000) || defined (I486) + if (register_graph_2_p!=NULL && (*register_graph_2_p==NULL || (*register_graph_2_p)->instruction_code!=GGREGISTER)){ + INSTRUCTION_GRAPH graph; + + i_exg_r_r (reg_2,reg_1); + + (*register_graph_1_p)->instruction_parameters[0].i=reg_2; + + if (*register_graph_2_p!=NULL){ + (*register_graph_2_p)->instruction_code=GGREGISTER; + (*register_graph_2_p)->instruction_parameters[0].i=reg_1; + } + + graph=*register_graph_1_p; + *register_graph_1_p=*register_graph_2_p; + *register_graph_2_p=graph; + } else { +#endif + register int reg_2; + + register_graph_2_p=NULL; + + if ((*register_graph_1_p)->instruction_d_min_a_cost<=0){ + reg_2=get_dregister(); + if ((unsigned)d_reg_num (reg_2)<(unsigned)N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ) + register_graph_2_p=&global_block.block_graph_d_register_parameter_node[d_reg_num (reg_2)]; + } else { + reg_2=get_aregister(); + if ((unsigned)a_reg_num (reg_2)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + register_graph_2_p=&global_block.block_graph_a_register_parameter_node[a_reg_num (reg_2)]; + } + + i_move_r_r (reg_1,reg_2); + instruction_ad_r (IMOVE,&ad_1,reg_1); + + (*register_graph_1_p)->instruction_parameters[0].i=reg_2; + + if (register_graph_2_p!=NULL) + *register_graph_2_p=*register_graph_1_p; + + *register_graph_1_p=NULL; +#if defined (M68000) || defined (I486) + } +#endif + } else { + i_move_r_r (reg_2,reg_1); + if (--*ad_1.ad_count_p==0) + free_register (reg_2); + } + } else { + switch (ad_1.ad_mode){ + case P_INDIRECT: + --*ad_1.ad_count_p; + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_1.ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; +#ifdef M68000 + if (load_x_graph->inode_arity==1 && i_ad_p->ad_mode==P_INDEXED) + --*i_ad_p->ad_count_p2; +#endif + --*i_ad_p->ad_count_p; + break; + } + } + + if (register_graph_1_p!=NULL && *register_graph_1_p!=NULL && (*register_graph_1_p)->node_count>0){ + int reg_2; + + register_graph_2_p=NULL; + + if ((*register_graph_1_p)->instruction_d_min_a_cost<=0){ + reg_2=get_dregister(); + if ((unsigned)d_reg_num (reg_2)<(unsigned)N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ) + register_graph_2_p=&global_block.block_graph_d_register_parameter_node[d_reg_num (reg_2)]; + } else { + reg_2=get_aregister(); + if ((unsigned)a_reg_num (reg_2)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + register_graph_2_p=&global_block.block_graph_a_register_parameter_node[a_reg_num (reg_2)]; + } + + i_move_r_r (reg_1,reg_2); + + (*register_graph_1_p)->instruction_parameters[0].i=reg_2; + + if (register_graph_2_p!=NULL) + *register_graph_2_p=*register_graph_1_p; + + *register_graph_1_p=NULL; + } + + switch (ad_1.ad_mode){ + case P_INDIRECT: + ++*ad_1.ad_count_p; + break; + case P_INDEXED: + { + INSTRUCTION_GRAPH load_x_graph; + ADDRESS *i_ad_p; + + load_x_graph=(INSTRUCTION_GRAPH)ad_1.ad_offset; + i_ad_p=(ADDRESS *)load_x_graph->instruction_parameters[1].p; +#ifdef M68000 + if (load_x_graph->inode_arity==1 && i_ad_p->ad_mode==P_INDEXED) + ++*i_ad_p->ad_count_p2; +#endif + ++*i_ad_p->ad_count_p; + break; + } + } + + instruction_ad_r (IMOVE,&ad_1,reg_1); + } + + if (is_a_register (reg_1)) + allocate_aregister (reg_1); + else + allocate_dregister (reg_1); +} + +static void linearize_load_b_x_operator (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + register INSTRUCTION_GRAPH graph_1,graph_2; + register int offset; + + graph_1=graph->instruction_parameters[0].p; + offset=graph->instruction_parameters[1].i; + graph_2=graph->instruction_parameters[2].p; + + if (graph_2!=NULL){ + ADDRESS ad_1; + + if (graph->order_left){ + linearize_graph (graph_1,ad_p); + linearize_graph (graph_2,&ad_1); + } else { + linearize_graph (graph_2,&ad_1); + linearize_graph (graph_1,ad_p); + } + +#if defined (sparc) || defined (G_POWER) + { + int reg_1,reg_2; + + in_register (&ad_1); + in_register (ad_p); + + if (--*ad_1.ad_count_p==0) + free_register (ad_1.ad_register); + if (--*ad_p->ad_count_p==0) + free_register (ad_p->ad_register); + + if (offset>>2==0){ + if (graph->instruction_d_min_a_cost<=0) + reg_2=get_dregister(); + else + reg_2=get_aregister(); + i_moveb_x_r (ad_p->ad_register,ad_1.ad_register,reg_2); + } else { + reg_1=get_aregister(); + + i_lea_x_r (ad_p->ad_register,ad_1.ad_register,reg_1); + + free_aregister (reg_1); + + if (graph->instruction_d_min_a_cost<=0) + reg_2=get_dregister(); + else + reg_2=get_aregister(); + i_moveb_id_r (offset>>2,reg_1,reg_2); + } + +# ifdef G_POWER + if (offset & 1) + i_extb_r (reg_2); +# endif + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_2; + ad_p->ad_count_p=&graph->node_count; + + if (graph->node_count<=1) + graph->inode_arity=2; + else + register_node (graph,reg_2); + } +#else + { + int reg_1; + + in_data_register (&ad_1); + in_address_register (ad_p); + + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + + if (--*ad_1.ad_count_p==0) + free_dregister (ad_1.ad_register); + + reg_1=get_dregister(); +# ifdef I486 + i_moveb_x_r (offset & ~3,ad_p->ad_register,ad_1.ad_register,reg_1); +# else + if (offset & 1){ + i_moveb_x_r (offset & ~3,ad_p->ad_register,ad_1.ad_register,reg_1); + i_extb_r (reg_1); + } else { + if (ad_1.ad_register==reg_1){ + i_moveb_x_r (offset,ad_p->ad_register,ad_1.ad_register,reg_1); + i_and_i_r (255,reg_1); + } else { + i_move_i_r (0,reg_1); + i_moveb_x_r (offset,ad_p->ad_register,ad_1.ad_register,reg_1); + } + } +# endif + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + if (graph->node_count<=1) + graph->inode_arity=2; + else + register_node (graph,reg_1); + } +#endif + } else { + int reg_1; + + linearize_graph (graph_1,ad_p); + in_address_register (ad_p); + + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + +#ifdef M68000 + if (!(offset & 1)) + i_move_i_r (0,reg_1); +#endif + i_moveb_id_r (offset>>2,ad_p->ad_register,reg_1); +#if defined (M68000) || defined (G_POWER) + if (offset & 1) + i_extb_r (reg_1); +#endif + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + if (graph->node_count<=1) + graph->inode_arity=2; + else + register_node (graph,reg_1); + } +} + +#if 0 +static int selects_from_array (INSTRUCTION_GRAPH select_graph,INSTRUCTION_GRAPH graph) +{ + if (select_graph==graph) + return 1; + + switch (select_graph->instruction_code){ + case GLOAD_X: + case GFLOAD_X: + case GLOAD_B_X: + return selects_from_array (select_graph->instruction_parameters[0].p,graph); + case GLOAD_ID: + return selects_from_array (select_graph->instruction_parameters[1].p,graph); + default: + return 0; + } +} +#endif + +static void do_array_selects_before_update (INSTRUCTION_GRAPH select_graph,INSTRUCTION_GRAPH graph_1,INSTRUCTION_GRAPH graph_2) +{ + for (; select_graph!=NULL; select_graph=select_graph->instruction_parameters[3].p){ + switch (select_graph->instruction_code){ + case GLOAD_X: +#if 1 + if (graph_2==select_graph->instruction_parameters[0].p){ +#else + if (selects_from_array (select_graph->instruction_parameters[0].p,graph_2)){ +#endif + if (select_graph->node_count>0){ + ADDRESS s_ad; + + ++select_graph->node_count; + linearize_load_x_operator (select_graph,&s_ad +#ifdef LOAD_X_PARAMETER_REGISTER + ,0 +#endif + ); + --select_graph->node_count; + } else if (select_graph->inode_arity==1 && select_graph!=graph_1){ + ADDRESS *i_ad_p; + int dreg; + + i_ad_p=(ADDRESS *)select_graph->instruction_parameters[1].p; + + select_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + dreg=get_dregister(); + i_move_x_r (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,dreg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + dreg=get_dregister(); + i_move_id_r (i_ad_p->ad_offset,i_ad_p->ad_register,dreg); + } + i_ad_p->ad_register=dreg; + } + } + break; + case GLOAD_B_X: +#if 1 + if (graph_2==select_graph->instruction_parameters[0].p){ +#else + if (selects_from_array (select_graph->instruction_parameters[0].p,graph_2)){ +#endif + if (select_graph->node_count>0 /* added 29-2-2000: */ && select_graph->inode_arity!=2 /**/){ + ADDRESS s_ad; + + ++select_graph->node_count; + linearize_load_b_x_operator (select_graph,&s_ad); + --select_graph->node_count; + } + } + break; + case GFLOAD_X: +#if 1 + if (graph_2==select_graph->instruction_parameters[0].p){ +#else + if (selects_from_array (select_graph->instruction_parameters[0].p,graph_2)){ +#endif + if (select_graph->node_count>0){ + ADDRESS s_ad; + + ++select_graph->node_count; + linearize_fload_x_operator (select_graph,&s_ad); + --select_graph->node_count; + } else if (select_graph->inode_arity==1 && select_graph!=graph_1){ + ADDRESS *i_ad_p; + int freg; + + i_ad_p=(ADDRESS *)select_graph->instruction_parameters[1].p; + + select_graph->inode_arity=2; + + if (i_ad_p->ad_mode==P_INDEXED){ + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_areg); + if (--*i_ad_p->ad_count_p2==0) + free_dregister (i_ad_p->ad_dreg); + freg=get_fregister(); + i_fmove_x_fr (i_ad_p->ad_offset,i_ad_p->ad_areg,i_ad_p->ad_dreg,freg); + } else { + if (--*i_ad_p->ad_count_p==0) + free_aregister (i_ad_p->ad_register); + freg=get_fregister(); + i_fmove_id_fr (i_ad_p->ad_offset,i_ad_p->ad_register,freg); + } + i_ad_p->ad_register=freg; + } + } + break; + case GREGISTER: + case GFREGISTER: + case GFHIGH: + case GFLOW: + case GGREGISTER: + break; + default: + internal_error_in_function ("do_array_selects_before_update"); + } + } +} + +static void linearize_store_x_operator (int i_instruction_code,register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH graph_1,graph_2,graph_3; + int offset; + ADDRESS ad_1,ad_3; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + offset=graph->instruction_parameters[2].i; + graph_3=graph->instruction_parameters[3].p; + + if (graph_3==NULL){ + if (graph->order_left){ + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,ad_p); + } else { + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,ad_p); + } + } else { + switch (graph->order_left){ + case 0: + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,ad_p); + linearize_graph (graph_3,&ad_3); + break; + case 1: + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_3,&ad_3); + linearize_graph (graph_2,ad_p); + break; + case 2: + linearize_graph (graph_2,ad_p); + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_3,&ad_3); + break; + case 3: + linearize_graph (graph_2,ad_p); + linearize_graph (graph_3,&ad_3); + linearize_graph (graph_1,&ad_1); + break; + case 4: + linearize_graph (graph_3,&ad_3); + linearize_graph (graph_2,ad_p); + linearize_graph (graph_1,&ad_1); + break; + case 5: + linearize_graph (graph_3,&ad_3); + linearize_graph (graph_1,&ad_1); + linearize_graph (graph_2,ad_p); + break; + default: + internal_error_in_function ("linearize_store_x_operator"); + } + } + + do_array_selects_before_update (graph->instruction_parameters[4].p,graph_1,graph_2); + + in_address_register (ad_p); + + if (graph_3==NULL){ + if (i_instruction_code==IMOVEB && ad_1.ad_mode!=P_IMMEDIATE) + in_data_register (&ad_1); + + instruction_ad_id (i_instruction_code,&ad_1,offset>>2,ad_p->ad_register); + } else { + in_data_register (&ad_3); + +#ifndef M68000 + if (ad_1.ad_mode==P_INDEXED) + in_register (&ad_1); +#endif + + if (i_instruction_code==IMOVEB && ad_1.ad_mode!=P_IMMEDIATE +#ifdef M68000 + && ad_1.ad_mode!=P_INDEXED +#endif + ) + in_data_register (&ad_1); + + if (--*ad_3.ad_count_p==0) + free_dregister (ad_3.ad_register); + + instruction_ad_x (i_instruction_code,&ad_1,offset,ad_p->ad_register,ad_3.ad_register); + } + + if (graph->node_count>1){ +/* added 10-12-97 */ + /* changed 27-6-2001 */ + + while (graph_2->instruction_code==GINDIRECTION) + graph_2=graph_2->instruction_parameters[0].p; + + if (graph_2->instruction_code==GREGISTER){ + /* if (graph_2->instruction_code==GREGISTER || graph_2->instruction_code==GINDIRECTION){ */ + + register_node (graph_2,ad_p->ad_register); + graph_2->node_count += graph->node_count; + ad_p->ad_count_p=&graph_2->node_count; + + graph->instruction_parameters[0].p=graph_2; + graph->instruction_code=GINDIRECTION; + } else +/* */ + { + register_node (graph,ad_p->ad_register); + ad_p->ad_count_p=&graph->node_count; + } + } +/* added 27-6-2001 */ + else { + if (graph_2->instruction_code==GREGISTER){ + graph->instruction_parameters[0].p=graph_2; + graph->instruction_code=GINDIRECTION; + } else if (graph_2->instruction_code==GINDIRECTION){ + graph->instruction_parameters[0].p=graph_2->instruction_parameters[0].p; + graph->instruction_code=GINDIRECTION; + } + } +/**/ +} + +static void linearize_bounds_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + ADDRESS ad_1; + + if (graph->order_left){ + linearize_graph (graph->instruction_parameters[0].p,&ad_1); + linearize_graph (graph->instruction_parameters[1].p,ad_p); + } else { + linearize_graph (graph->instruction_parameters[1].p,ad_p); + linearize_graph (graph->instruction_parameters[0].p,&ad_1); + } + + in_address_register (&ad_1); + + if (graph->node_count>1) + in_alterable_data_register (ad_p); + else + in_data_register (ad_p); + + i_cmp_id_r (4,ad_1.ad_register,ad_p->ad_register); + instruction_l (IBHS,index_error_label); + + if (--*ad_1.ad_count_p==0) + free_aregister (ad_1.ad_register); + + if (graph->node_count>1){ + register_node (graph,ad_p->ad_register); + ad_p->ad_count_p=&graph->node_count; + } +} + +static void linearize_exit_if_operator (INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + INSTRUCTION_GRAPH graph_1,graph_2; + int condition; + + graph_1=graph->instruction_parameters[1].p; + graph_2=graph->instruction_parameters[2].p; + + condition=linearize_condition (graph_1); + + instruction_l (condition_to_branch_false_instruction[condition],graph->instruction_parameters[0].l); + + linearize_graph (graph_2,ad_p); + + if (graph->node_count>1){ + in_address_register (ad_p); + register_node (graph_2,ad_p->ad_register); + graph_2->node_count += graph->node_count; + ad_p->ad_count_p=&graph_2->node_count; + + graph->instruction_parameters[0].p=graph_2; + graph->instruction_code=GINDIRECTION; + } +} + +static void linearize_graph (INSTRUCTION_GRAPH graph,ADDRESS *ad_p) +{ + switch (graph->instruction_code){ + case GLOAD: + { + if (graph->node_count<=1){ + ad_p->ad_mode=P_INDIRECT; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1+1; + ad_p->ad_offset=graph->instruction_parameters[0].i; + ad_p->ad_register=graph->instruction_parameters[1].i; + graph->node_count=0; + } else { + int reg_1; + + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + + i_move_id_r (graph->instruction_parameters[0].i,graph->instruction_parameters[1].i,reg_1); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,reg_1); + } + return; + } + case GREGISTER: + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=graph->instruction_parameters[0].i; + ad_p->ad_count_p=&graph->node_count; + return; + case GGREGISTER: + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=graph->instruction_parameters[0].i; + ad_p->ad_count_p=&ad_p->ad_count; + ad_p->ad_count=1+1; + return; + case GLOAD_I: + if (graph->node_count<=1){ + ad_p->ad_mode=P_IMMEDIATE; + ad_p->ad_offset=graph->instruction_parameters[0].i; + } else { + register int reg_1; + + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + i_move_i_r (graph->instruction_parameters[0].i,reg_1); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,reg_1); + } + return; + case GLOAD_DES_I: + if (graph->node_count<=1){ + ad_p->ad_mode=P_DESCRIPTOR_NUMBER; + ad_p->ad_label=graph->instruction_parameters[0].l; + ad_p->ad_offset=graph->instruction_parameters[1].i; + } else { + int reg_1; + + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + + i_move_d_r (graph->instruction_parameters[0].l,graph->instruction_parameters[1].i,reg_1); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + register_node (graph,reg_1); + } + return; + case GLEA: + { + register int reg_1; + +#ifdef I486 + if (graph->node_count==1){ + ad_p->ad_mode=P_DESCRIPTOR_NUMBER; + if (graph->inode_arity==1) + ad_p->ad_offset=graph->instruction_parameters[1].i; + else + ad_p->ad_offset=0; + ad_p->ad_label=graph->instruction_parameters[0].l; + ad_p->ad_count_p=&graph->node_count; + return; + } else { +#endif + +#ifndef M68000 + if (graph->instruction_d_min_a_cost<0) + reg_1=get_dregister(); + else +#endif + reg_1=get_aregister(); + + if (graph->inode_arity==1) + i_lea_l_i_r (graph->instruction_parameters[0].l,graph->instruction_parameters[1].i,reg_1); + else + i_lea_l_i_r (graph->instruction_parameters[0].l,0,reg_1); +#ifdef M68000 + if (graph->instruction_d_min_a_cost<0){ + int reg_2; + + reg_2=get_dregister(); + i_move_r_r (reg_1,reg_2); + free_aregister (reg_1); + reg_1=reg_2; + } +#endif + if (graph->node_count>1) + register_node (graph,reg_1); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + return; +#ifdef I486 + } +#endif + } + case GLOAD_ID: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=graph->instruction_parameters[1].p; + linearize_graph (graph_1,ad_p); + in_address_register (ad_p); + + if (graph->node_count<=1){ + ad_p->ad_mode=P_INDIRECT; + ad_p->ad_offset=graph->instruction_parameters[0].i; + --graph->node_count; + } else { + int reg_1; + + if (--*ad_p->ad_count_p==0) + free_aregister (ad_p->ad_register); + + if (graph->instruction_d_min_a_cost<=0) + reg_1=get_dregister(); + else + reg_1=get_aregister(); + i_move_id_r (graph->instruction_parameters[0].i,ad_p->ad_register,reg_1); + + U3( ad_p, ad_mode=P_REGISTER, ad_register=reg_1, ad_count_p=&graph->node_count); + + register_node (graph,reg_1); + } + return; + } + case GLOAD_B_ID: + { + register INSTRUCTION_GRAPH graph_1; + ADDRESS ad_1; + register int reg_1; + + graph_1=graph->instruction_parameters[1].p; + linearize_graph (graph_1,&ad_1); + in_address_register (&ad_1); + + if (--*ad_1.ad_count_p==0) + free_aregister (ad_1.ad_register); + + reg_1=get_dregister(); +#ifdef M68000 + i_move_i_r (0,reg_1); +#endif + i_moveb_id_r (graph->instruction_parameters[0].i,ad_1.ad_register,reg_1); + + if (graph->instruction_d_min_a_cost>0){ + int reg_2; + + reg_2=get_aregister(); + i_move_r_r (reg_1,reg_2); + free_dregister (reg_1); + reg_1=reg_2; + } + + if (graph->node_count>1) + register_node (graph,reg_1); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + return; + } + case GLOAD_DES_ID: + { + register INSTRUCTION_GRAPH graph_1; + ADDRESS ad_1; + register int reg_1; + + graph_1=graph->instruction_parameters[1].p; + linearize_graph (graph_1,&ad_1); + in_address_register (&ad_1); + + if (--*ad_1.ad_count_p==0) + free_aregister (ad_1.ad_register); + + if (graph->instruction_d_min_a_cost<0){ + reg_1=get_dregister(); + i_movew_id_r (graph->instruction_parameters[0].i,ad_1.ad_register,reg_1); +#ifdef M68000 + i_ext_r (reg_1); +#endif + } else { + reg_1=get_aregister(); + i_movew_id_r (graph->instruction_parameters[0].i,ad_1.ad_register,reg_1); + } + + if (graph->node_count>1) + register_node (graph,reg_1); + + ad_p->ad_mode=P_REGISTER; + ad_p->ad_register=reg_1; + ad_p->ad_count_p=&graph->node_count; + + return; + } + case GSTORE: + { + INSTRUCTION_GRAPH a_graph; + int offset,stack_pointer; + + a_graph=graph->instruction_parameters[2].p; + + if (a_graph->node_count==1) + switch (a_graph->instruction_code){ + case GFILL: + linearize_store_fill_operator (graph,a_graph); + return; + case GCREATE: + if (a_graph->inode_arity>3 && a_graph->instruction_parameters[0].p!=NULL){ + int arity; + + arity=a_graph->inode_arity; + while (--arity>0 && a_graph->instruction_parameters[arity].p!=NULL) + ; + + if (arity>0) + break; + } + + offset=graph->instruction_parameters[0].i; + stack_pointer=graph->instruction_parameters[1].i; + + linearize_load_graph (graph->instruction_parameters[3].p); + + linearize_store_create_operator (offset,stack_pointer,a_graph); + return; + } + + linearize_graph (a_graph,ad_p); + + offset=graph->instruction_parameters[0].i; + stack_pointer=graph->instruction_parameters[1].i; + + linearize_load_graph (graph->instruction_parameters[3].p); + + instruction_ad_id (IMOVE,ad_p,offset,stack_pointer); + return; + } + case GBEFORE0: + case GBEFORE: + { + INSTRUCTION_GRAPH graph_1; + int i; + + graph_1=graph->instruction_parameters[0].p; + linearize_graph (graph_1,ad_p); + + if (graph->instruction_code==GBEFORE){ + /* added 16-5-2000 */ + for (i=1; i<graph->inode_arity; ++i){ + INSTRUCTION_GRAPH graph_2; + + graph_2=graph->instruction_parameters[i].p; + if (graph_2->node_count==1 && graph_2->instruction_code==GMOVEMI) + graph_2->node_count=0; + } + /**/ + for (i=1; i<graph->inode_arity; ++i){ + INSTRUCTION_GRAPH graph_2; + ADDRESS ad_1; + + graph_2=graph->instruction_parameters[i].p; + if (graph_2->node_count>1){ + linearize_graph (graph_2,&ad_1); + in_register (&ad_1); + register_node (graph_2,ad_1.ad_register); + } + } + } + + if (graph->node_count>1){ + in_address_register (ad_p); +/* changed 27-12-2000 + register_node (graph,ad_p->ad_register); + ad_p->ad_count_p=&graph->node_count; +*/ + register_node (graph_1,ad_p->ad_register); + graph_1->node_count += graph->node_count; + ad_p->ad_count_p=&graph_1->node_count; + + /* graph->instruction_parameters[0].p=graph_1; */ + graph->instruction_code=GINDIRECTION; +/* */ + } + + return; + } + case GKEEP: + { + INSTRUCTION_GRAPH graph_1,graph_2; + ADDRESS ad_1; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + + linearize_graph (graph_1,&ad_1); + + switch (ad_1.ad_mode){ + case P_REGISTER: + case P_INDIRECT: + if (--*ad_1.ad_count_p==0) + free_register (ad_1.ad_register); + } + + linearize_graph (graph_2,ad_p); + + if (graph->node_count>1){ + in_address_register (ad_p); +/* changed 10-12-97 + register_node (graph,ad_p->ad_register); + ad_p->ad_count_p=&graph->node_count; +*/ + register_node (graph_2,ad_p->ad_register); + graph_2->node_count += graph->node_count; + ad_p->ad_count_p=&graph_2->node_count; + + graph->instruction_parameters[0].p=graph_2; + graph->instruction_code=GINDIRECTION; +/**/ + } + + return; + } +/* added 10-12-97 */ + case GINDIRECTION: + linearize_graph (graph->instruction_parameters[0].p,ad_p); + return; +/* */ + case GLOAD_X: + linearize_load_x_operator (graph,ad_p +#ifdef LOAD_X_PARAMETER_REGISTER + ,0 +#endif + ); + return; + case GLOAD_B_X: + linearize_load_b_x_operator (graph,ad_p); + return; + case GSTORE_X: + linearize_store_x_operator (IMOVE,graph,ad_p); + return; + case GSTORE_B_X: + linearize_store_x_operator (IMOVEB,graph,ad_p); + return; + case GSTORE_R: + linearize_store_r_node (graph); + break; + case GFSTORE: + linearize_fstore_operator (graph); + return; + case GFSTORE_X: + linearize_fstore_x_operator (graph,ad_p); + return; + case GFSTORE_R: + linearize_fstore_r_operator (graph); + return; + case GADD: + linearize_dyadic_commutative_operator (IADD,graph,ad_p); + return; + case GAND: + linearize_dyadic_commutative_data_operator (IAND,graph,ad_p); + return; + case GMUL: + linearize_dyadic_commutative_data_operator (IMUL,graph,ad_p); + return; + case GOR: + linearize_dyadic_commutative_data_operator (IOR,graph,ad_p); + return; + case GEOR: + linearize_eor_operator (graph,ad_p); + return; + case GSUB: + linearize_dyadic_non_commutative_operator (ISUB,graph,ad_p); + return; +#if defined (I486) || defined (G_POWER) + case GDIV: + linearize_div_mod_operator (IDIV,graph,ad_p); + return; + case GMOD: + linearize_div_mod_operator (IMOD,graph,ad_p); + return; +#else + case GDIV: + linearize_dyadic_non_commutative_data_operator (IDIV,graph,ad_p); + return; + case GMOD: + linearize_mod_operator (IMOD,graph,ad_p); + return; +#endif + case GCMP_EQ: + linearize_compare_operator (CEQ,CEQ,graph,ad_p); + return; + case GCMP_LT: + linearize_compare_operator (CLT,CGT,graph,ad_p); + return; + case GCMP_GT: + linearize_compare_operator (CGT,CLT,graph,ad_p); + return; + case GCNOT: + linearize_conditional_not_operator (graph,ad_p); + return; + case GLSR: + linearize_shift_operator (ILSR,graph,ad_p); + return; + case GLSL: + linearize_shift_operator (ILSL,graph,ad_p); + return; + case GASR: + linearize_shift_operator (IASR,graph,ad_p); + return; + case GCREATE: + linearize_create_operator (graph,ad_p,0); + return; +#ifdef G_POWER + case GCREATE_S: + ad_p->ad_mode=P_STORE_HP_INSTRUCTION; + ad_p->ad_offset=(LONG) linearize_store_create_operator (0,HEAP_POINTER,graph); + return; +#endif + case GCREATE_R: + linearize_create_r_operator (graph,ad_p,0); + return; + case GFILL: + linearize_fill_operator (graph,ad_p); + return; + case GFILL_R: + linearize_fill_r_operator (graph,ad_p); + return; + case GMOVEMI: + linearize_movemi_operator (graph,ad_p); + return; + case GCOPY: + linearize_copy_operator (graph,ad_p); + return; + case GFHIGH: + linearize_fhigh_operator (graph,ad_p); + return; + case GFLOW: + linearize_flow_operator (graph,ad_p); + return; + case GFCMP_EQ: + linearize_float_compare_operator (CFEQ,CFEQ,graph,ad_p); + return; + case GFCMP_LT: + linearize_float_compare_operator (CFLT,CFGT,graph,ad_p); + return; + case GFCMP_GT: + linearize_float_compare_operator (CFGT,CFLT,graph,ad_p); + return; + case GFRTOI: + linearize_rtoi_operator (graph,ad_p); + return; + case GBOUNDS: + linearize_bounds_operator (graph,ad_p); + return; + case GEXIT_IF: + linearize_exit_if_operator (graph,ad_p); + return; + case GADD_O: + linearize_add_o_operator (graph,ad_p,NULL); + return; + case GMUL_O: + linearize_mul_o_operator (graph,ad_p,NULL); + break; + case GSUB_O: + linearize_sub_o_operator (graph,ad_p,NULL); + return; + case GTEST_O: + linearize_test_o_operator (graph,ad_p); + return; + default: + /* printf ("%d %d\n",(int)graph,graph->instruction_code); */ + internal_error_in_function ("linearize_graph"); + } +} + +#pragma segment Code30 + +static void linearize_fstore_x_operator (register INSTRUCTION_GRAPH graph,register ADDRESS *ad_p) +{ + register INSTRUCTION_GRAPH graph_1,graph_2,graph_3; + register int offset; + ADDRESS ad_1,ad_3; + + graph_1=graph->instruction_parameters[0].p; + graph_2=graph->instruction_parameters[1].p; + offset=graph->instruction_parameters[2].i; + graph_3=graph->instruction_parameters[3].p; + + if (graph_3==NULL){ + if (graph->order_left){ + linearize_float_graph (graph_1,&ad_1); + linearize_graph (graph_2,ad_p); + } else { + linearize_graph (graph_2,ad_p); + linearize_float_graph (graph_1,&ad_1); + } + } else { + switch (graph->order_left){ + case 0: + linearize_float_graph (graph_1,&ad_1); + linearize_graph (graph_2,ad_p); + linearize_graph (graph_3,&ad_3); + break; + case 1: + linearize_float_graph (graph_1,&ad_1); + linearize_graph (graph_3,&ad_3); + linearize_graph (graph_2,ad_p); + break; + case 2: + linearize_graph (graph_2,ad_p); + linearize_float_graph (graph_1,&ad_1); + linearize_graph (graph_3,&ad_3); + break; + case 3: + linearize_graph (graph_2,ad_p); + linearize_graph (graph_3,&ad_3); + linearize_float_graph (graph_1,&ad_1); + break; + case 4: + linearize_graph (graph_3,&ad_3); + linearize_graph (graph_2,ad_p); + linearize_float_graph (graph_1,&ad_1); + break; + case 5: + linearize_graph (graph_3,&ad_3); + linearize_float_graph (graph_1,&ad_1); + linearize_graph (graph_2,ad_p); + break; + default: + internal_error_in_function ("linearize_fstore_x_operator"); + } + } + + do_array_selects_before_update (graph->instruction_parameters[4].p,graph_1,graph_2); + + in_address_register (ad_p); + + if (graph_3==NULL) + move_float_ad_id (&ad_1,offset>>2,ad_p->ad_register); + else { + in_data_register (&ad_3); + + if (--*ad_3.ad_count_p==0) + free_dregister (ad_3.ad_register); + +#ifndef M68000 +# ifdef I486 + if (ad_1.ad_mode==P_INDEXED) +# else + if (ad_1.ad_mode!=P_F_REGISTER) +# endif + in_float_register (&ad_1); +#endif + move_float_ad_x (&ad_1,offset,ad_p->ad_register,ad_3.ad_register); + } + + if (graph->node_count>1){ + register_node (graph,ad_p->ad_register); + ad_p->ad_count_p=&graph->node_count; + } +} + +void calculate_and_linearize_branch_false (LABEL *label,INSTRUCTION_GRAPH graph) +{ + int condition,condition_on_stack; + + calculate_graph_register_uses (graph); + condition=linearize_condition (graph); + + condition_on_stack=adjust_stack_pointers_without_altering_condition_codes (is_float_condition (condition),condition); + +#ifdef M68000 + if (condition_on_stack){ + i_tstb_pi (REGISTER_A7); + instruction_l (IBEQ,label); + } else +#endif + instruction_l (condition_to_branch_false_instruction[condition],label); +} + +void calculate_and_linearize_branch_true (LABEL *label,INSTRUCTION_GRAPH graph) +{ + int condition,condition_on_stack; + + calculate_graph_register_uses (graph); + condition=linearize_condition (graph); + + condition_on_stack=adjust_stack_pointers_without_altering_condition_codes (is_float_condition (condition),condition); + +#ifdef M68000 + if (condition_on_stack){ + i_tstb_pi (REGISTER_A7); + instruction_l (IBNE,label); + } else +#endif + instruction_l (condition_to_branch_true_instruction[condition],label); +} + +void calculate_and_linearize_graph (INSTRUCTION_GRAPH graph) +{ + ADDRESS ad; + + calculate_graph_register_uses (graph); + linearize_graph (graph,&ad); +} + +void initialize_linearization (VOID) +{ + free_dregisters.r_s_list.r_l_next=NULL; + free_aregisters.r_s_list.r_l_next=NULL; + free_fregisters.r_s_list.r_l_next=NULL; + + free_all_aregisters(); + free_all_dregisters(); + free_all_fregisters(); + + IF_G_POWER (last_heap_pointer_update=NULL;) +} + +#if 0 +static char *i_instruction_names[] = { + "ADD", "AND", "ASR", "BEQ", "BGE", "BGT", "BHS", + "BLE", "BLT", "BMI", "BMOVE", "BNE", "CMP", "CMPW", + "DIV", "EOR", "EXG", "EXT", "FACOS", "FADD", "FASIN", + "FATAN", "FBEQ", "FBGE", "FBGT", "FBLE", "FBLT", "FBNE", + "FCMP", "FCOS", "FDIV", "FEXP", "FLN", "FLOG10", "FMUL", + "FREM", "FSEQ", "FSGE", "FSGT", "FSIN", "FSLE", "FSLT", + "FSNE", "FSQRT", "FSUB", "FTAN", "FTST", "FMOVE", "FMOVEL", + "JMP", "JSR", "LEA", "LSL", "LSR", "MOD", "MOVE", + "MOVEB", "MOVEM", "MOVEW", "MUL", "OR", "RTS", "SEQ", + "SGE", "SGT", "SLE", "SLT", "SNE", "SUB", "TST", + "TSTB", "WORD" +}; + +static void show_parameter (register struct parameter *parameter) +{ + switch (parameter->parameter_type){ + case P_REGISTER: + { + int reg=parameter->parameter_data.reg.r; + if (is_d_register (reg)) + printf ("D%d",d_reg_num (reg)); + else + printf ("A%d",a_reg_num (reg)); + break; + } + case P_LABEL: + if (parameter->parameter_data.l->label_number!=0) + printf ("L%d",parameter->parameter_data.l->label_number); + else + printf ("%s",parameter->parameter_data.l->label_name); + break; + case P_DESCRIPTOR_NUMBER: + printf ("#!%s+%d",parameter->parameter_data.l->label_name,parameter->parameter_offset); + break; + case P_INDIRECT: + if (parameter->parameter_offset==0) + printf ("(A%d)",a_reg_num (parameter->parameter_data.reg.r)); + else + printf ("%d(A%d)",parameter->parameter_offset, + a_reg_num (parameter->parameter_data.reg.r)); + break; + case P_IMMEDIATE: + printf ("#%ld",parameter->parameter_data.i); + break; +#ifdef M68000 + case P_POST_INCREMENT: + printf ("(A%d)+",a_reg_num (parameter->parameter_data.reg.r)); + break; + case P_PRE_DECREMENT: + printf ("-(A%d)",a_reg_num (parameter->parameter_data.reg.r)); + break; +#endif + case P_F_REGISTER: + printf ("FP%d",parameter->parameter_data.reg.r); + break; + case P_F_IMMEDIATE: + printf ("#%g",*parameter->parameter_data.r); + break; + case P_INDEXED: + { + struct index_registers *index_registers; + int offset; + + index_registers=parameter->parameter_data.ir; + offset=parameter->parameter_offset; + + printf ("%d(a%d,d%d*%d)",offset>>2,a_reg_num (index_registers->a_reg.r), + d_reg_num (index_registers->d_reg.r),1<<(offset & 3)); + } + } +} + +void show_instructions (register struct instruction *instructions) +{ + while (instructions!=NULL){ + register struct parameter *parameter; + register int n_parameters; + + printf ("%s ",i_instruction_names[instructions->instruction_icode]); + + n_parameters=instructions->instruction_arity; + parameter=instructions->instruction_parameters; + while (n_parameters>1){ + show_parameter (parameter); + printf (","); + ++parameter; + --n_parameters; + } + if (n_parameters==1) + show_parameter (parameter); + printf ("\n"); + + instructions=instructions->instruction_next; + } +} +#endif |