diff options
-rw-r--r-- | cgias.c | 224 | ||||
-rw-r--r-- | cgias.h | 34 | ||||
-rw-r--r-- | cgiconst.h | 66 | ||||
-rw-r--r-- | cgiwas.c | 423 | ||||
-rw-r--r-- | cglin.c | 29 | ||||
-rw-r--r-- | cgopt.c | 3949 |
6 files changed, 4592 insertions, 133 deletions
@@ -9,6 +9,7 @@ #include <stdio.h> #include <string.h> +#include <stdlib.h> #ifdef __MWERKS__ # define I486 @@ -1121,6 +1122,13 @@ static void as_r_a (int code,int reg1,LABEL *label) store_label_in_code_section (label); } +static void as_sar_i_r (int i,int reg) +{ + store_c (0301); + store_c (0300 | (7<<3) | reg_num (reg)); + store_c (i); +} + static void as_move_parameter_reg (struct parameter *parameter,int reg) { switch (parameter->parameter_type){ @@ -1904,6 +1912,188 @@ static void as_parameter (int code1,int code2,struct parameter *parameter) } } +static void as_div_rem_i_instruction (struct instruction *instruction,int compute_remainder) +{ + int s_reg1,s_reg2,s_reg3,i,sd_reg,i_reg,tmp_reg,abs_i; + struct ms ms; + + if (instruction->instruction_parameters[0].parameter_type!=P_IMMEDIATE) + internal_error_in_function ("as_div_rem_i_instruction"); + + i=instruction->instruction_parameters[0].parameter_data.i; + + if (! ((i>1 || (i<-1 && i!=0x80000000)))) + internal_error_in_function ("as_div_rem_i_instruction"); + + abs_i=abs (i); + + if (compute_remainder) + i=abs_i; + + ms=magic (abs_i); + + sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r; + tmp_reg=instruction->instruction_parameters[2].parameter_data.reg.r; + + if (sd_reg==tmp_reg) + internal_error_in_function ("as_div_rem_i_instruction"); + + if (sd_reg==REGISTER_A1){ + if (tmp_reg!=REGISTER_D0) + as_move_r_r (REGISTER_D0,tmp_reg); + as_move_r_r (REGISTER_A1,REGISTER_O0); + + s_reg1=sd_reg; + s_reg2=REGISTER_O0; + i_reg=REGISTER_D0; + } else if (sd_reg==REGISTER_D0){ + if (tmp_reg!=REGISTER_A1) + as_move_r_r (REGISTER_A1,tmp_reg); + as_move_r_r (REGISTER_D0,REGISTER_O0); + + s_reg1=REGISTER_A1; + s_reg2=REGISTER_O0; + i_reg=REGISTER_A1; + } else { + if (tmp_reg==REGISTER_D0) + as_move_r_r (REGISTER_A1,REGISTER_O0); + else if (tmp_reg==REGISTER_A1) + as_move_r_r (REGISTER_D0,REGISTER_O0); + else { + as_move_r_r (REGISTER_D0,REGISTER_O0); + as_move_r_r (REGISTER_A1,tmp_reg); + } + + s_reg1=sd_reg; + s_reg2=sd_reg; + i_reg=REGISTER_D0; + } + + as_move_i_r (ms.m,i_reg); + + as_r (0367,0050,s_reg1); /* imul */ + + if (compute_remainder) + as_move_r_r (s_reg2,REGISTER_D0); + + if (ms.m<0) + as_r_r (0003,s_reg2,REGISTER_A1); /* add */ + + if (compute_remainder){ + if (s_reg2==sd_reg && s_reg2!=REGISTER_D0 && s_reg2!=REGISTER_A1){ + s_reg3=s_reg2; + s_reg2=REGISTER_D0; + } else + s_reg3=REGISTER_D0; + } + + if (i>=0){ + /* shr */ + store_c (0301); + store_c (0300 | (5<<3) | reg_num (s_reg2)); + store_c (31); + } else + as_sar_i_r (31,s_reg2); + + if (ms.s>0) + as_sar_i_r (ms.s,REGISTER_A1); + + if (!compute_remainder){ + if (sd_reg==REGISTER_A1){ + if (i>=0) + as_r_r (0003,s_reg2,REGISTER_A1); /* add */ + else { + as_r_r (0053,REGISTER_A1,s_reg2); /* sub */ + as_move_r_r (s_reg2,sd_reg); + } + } else if (sd_reg==REGISTER_D0){ + struct index_registers index_registers; + + if (i>=0){ + index_registers.a_reg.r=REGISTER_A1; + index_registers.d_reg.r=s_reg2; + + /* lea */ + as_x_r (00215,0,&index_registers,sd_reg); + } else { + as_move_r_r (s_reg2,sd_reg); + as_r_r (0053,REGISTER_A1,sd_reg);/* sub */ + } + } else { + if (i>=0) + as_r_r (0003,REGISTER_A1,s_reg2); /* add */ /* s_reg2==sd_reg */ + else + as_r_r (0053,REGISTER_A1,s_reg2); /* sub */ /* s_reg2==sd_reg */ + } + } else { + int r,i2; + + as_r_r (0003,s_reg2,REGISTER_A1); /* add */ + + i2=i & (i-1); + if ((i2 & (i2-1))==0){ + unsigned int n; + int n_shifts; + + n=i; + + n_shifts=0; + while (n>0){ + while ((n & 1)==0){ + n>>=1; + ++n_shifts; + } + + if (n_shifts>0){ + /* shl */ + store_c (0301); + store_c (0300 | (4<<3) | reg_num (REGISTER_A1)); + store_c (n_shifts); + } + + as_r_r (0053,REGISTER_A1,s_reg3); /* sub */ + + n>>=1; + n_shifts=1; + } + } else { + /* imul */ + r=reg_num (REGISTER_A1); + if ((signed char)i==i){ + store_c (0153); + store_c (0300 | (r<<3) | r); + store_c (i); + } else { + store_c (0151); + store_c (0300 | (r<<3) | r); + store_l (i); + } + + as_r_r (0053,REGISTER_A1,s_reg3); /* sub */ + } + + if (sd_reg!=s_reg3) + as_move_r_r (s_reg3,sd_reg); + } + + if (sd_reg==REGISTER_A1){ + if (tmp_reg!=REGISTER_D0) + as_move_r_r (tmp_reg,REGISTER_D0); + } else if (sd_reg==REGISTER_D0){ + if (tmp_reg!=REGISTER_A1) + as_move_r_r (tmp_reg,REGISTER_A1); + } else { + if (tmp_reg==REGISTER_D0) + as_move_r_r (REGISTER_O0,REGISTER_A1); + else if (tmp_reg==REGISTER_A1) + as_move_r_r (REGISTER_O0,REGISTER_D0); + else { + as_move_r_r (REGISTER_O0,REGISTER_D0); + as_move_r_r (tmp_reg,REGISTER_A1); + } + } +} + static void as_div_instruction (struct instruction *instruction) { int d_reg; @@ -1932,17 +2122,11 @@ static void as_div_instruction (struct instruction *instruction) as_move_r_r (d_reg,REGISTER_O0); if (log2i==1){ - /* sar */ - store_c (0301); - store_c (0300 | (7<<3) | reg_num (REGISTER_O0)); - store_c (31); + as_sar_i_r (31,REGISTER_O0); as_r_r (0053,REGISTER_O0,d_reg); /* sub */ } else { - /* sar */ - store_c (0301); - store_c (0300 | (7<<3) | reg_num (d_reg)); - store_c (31); + as_sar_i_r (31,d_reg); /* and */ if (d_reg==EAX) @@ -1954,10 +2138,7 @@ static void as_div_instruction (struct instruction *instruction) as_r_r (0003,REGISTER_O0,d_reg); /* add */ } - /* sar */ - store_c (0301); - store_c (0300 | (7<<3) | reg_num (d_reg)); - store_c (log2i); + as_sar_i_r (log2i,d_reg); return; } @@ -2067,6 +2248,9 @@ static void as_rem_instruction (struct instruction *instruction) int i,log2i; i=instruction->instruction_parameters[0].parameter_data.i; + + if (i<0 && i!=0x80000000) + i=-i; if (! ((i & (i-1))==0 && i>1)){ internal_error_in_function ("as_rem_instruction"); @@ -2089,17 +2273,11 @@ static void as_rem_instruction (struct instruction *instruction) as_r (0201,040,d_reg); store_l (1); - /* sar */ - store_c (0301); - store_c (0300 | (7<<3) | reg_num (REGISTER_O0)); - store_c (31); + as_sar_i_r (31,REGISTER_O0); as_r_r (0063,REGISTER_O0,d_reg); /* xor */ } else { - /* sar */ - store_c (0301); - store_c (0300 | (7<<3) | reg_num (REGISTER_O0)); - store_c (31); + as_sar_i_r (31,REGISTER_O0); /* and */ if (REGISTER_O0==EAX) @@ -3590,9 +3768,15 @@ static void as_instructions (struct instruction *instruction) case IDIV: as_div_instruction (instruction); break; + case IDIVI: + as_div_rem_i_instruction (instruction,0); + break; case IMOD: as_rem_instruction (instruction); break; + case IREMI: + as_div_rem_i_instruction (instruction,1); + break; case IAND: as_logic_instruction (instruction,0043,040,045); break; @@ -0,0 +1,34 @@ + +void assemble_code (VOID); +void initialize_assembler (FILE *file); +void define_local_label (int id,int flag); +void define_external_label (int id,int flag,char label_name[]); +void store_word_in_data_section (UWORD i); +void store_long_word_in_data_section (ULONG i); +void define_data_label (LABEL *label); +void store_label_in_data_section (LABEL *label); +void store_label_offset_in_data_section (int label_id); +void store_descriptor_in_data_section (LABEL *label); +void store_descriptor_in_code_section (int label_id); +void store_c_string_in_data_section (char *string,int length); +void store_abc_string_in_data_section (char *string,int length); +void store_c_string_in_code_section (char *string,int length); +void store_abc_string_in_code_section (char *string,int length); +void store_descriptor_string_in_code_section (char *string,int length,int string_code_label_id,LABEL *string_label); +void store_label_offset_in_code_section (int label_id); +void start_new_module (int flag); +void store_descriptor_string_in_data_section (char *string,int length,LABEL *string_label); +void store_2_words_in_data_section (UWORD w1,UWORD w2); +#ifdef _WINDOWS_ +void as_new_data_module (void); +#endif + +#ifndef GNU_C +void write_version_and_options (int version,int options); +void write_depend (char *module_name); +#endif + +struct ms { int m; int s; }; + +extern struct ms magic (int d); + diff --git a/cgiconst.h b/cgiconst.h new file mode 100644 index 0000000..71b51da --- /dev/null +++ b/cgiconst.h @@ -0,0 +1,66 @@ + +#undef FMADD + +#ifdef I486 +# define FP_STACK_OPTIMIZATIONS +#endif + +enum { + IADD, IAND, IASR, IBEQ, IBGE, IBGT, IBHS, + IBLE, IBLT, IBNE, IBNO, IBO, ICMP, ICMPW, + IDIV, IEOR, IEXG, IEXT, IFADD, IFBEQ, IFBGE, + IFBGT, IFBLE, IFBLT, IFBNE, IFCMP, IFCOS, IFDIV, + IFMUL, IFNEG, IFREM, IFSEQ, IFSGE, IFSGT, IFSIN, + IFSLE, IFSLT, IFSNE, IFSUB, IFTAN, IFTST, IFMOVE, + IFMOVEL, IJMP, IJSR, ILEA, ILSL, ILSR, IMOD, + IMOVE, IMOVEB, IMOVEW, IMUL, IOR, IRTS, ISCHEDULE, + ISEQ, ISGE, ISGT, ISLE, ISLT, ISNE, ISNO, + ISO, ISUB, ITST, IWORD +#if !defined (G_POWER) + ,IFSQRT +#endif +#ifdef M68000 + ,IFACOS, IFASIN, IFATAN, IFEXP, IFLN, IFLOG10, + IBMI, IBMOVE, IMOVEM, ITSTB +#endif +#if defined (M68000) || defined (G_POWER) + ,IEXTB +#endif +#ifndef M68000 + ,IBTST +#endif +#ifdef sparc + ,IFMOVEHI, IFMOVELO +#endif +#ifdef G_POWER + ,IBNEP,IMTCTR +#endif +#if defined (G_POWER) || defined (sparc) + ,IADDI, ILSLI + ,IADDO, ISUBO +#endif +#ifdef G_POWER + ,ICMPLW + ,IMULO +#endif +#if defined (G_POWER) || defined (I486) + ,IJMPP ,IRTSP +#endif +#if defined (I486) && defined (FP_STACK_OPTIMIZATIONS) + ,IFEXG +#endif +#if defined (I486) + ,IRTSI, IDIVI, IREMI +#endif +}; + +enum { + P_REGISTER, P_LABEL, P_DESCRIPTOR_NUMBER, P_INDIRECT, + P_IMMEDIATE, P_F_IMMEDIATE, P_F_REGISTER, P_INDEXED +#if defined (M68000) || defined (I486) + ,P_POST_INCREMENT, P_PRE_DECREMENT +#endif +#if defined (G_POWER) + ,P_INDIRECT_WITH_UPDATE, P_INDIRECT_HP, P_STORE_HP_INSTRUCTION +#endif +}; @@ -7,6 +7,7 @@ #include <stdio.h> #include <string.h> #include <ctype.h> +#include <stdlib.h> #define FSUB_FDIV_REVERSED #undef GENERATIONAL_GC @@ -18,6 +19,7 @@ #include "cgiconst.h" #include "cgcode.h" #include "cginstructions.h" +#include "cgias.h" #include "cgiwas.h" @@ -733,6 +735,18 @@ static void w_as_register_register_newline (int reg1,int reg2) w_as_newline(); } +static void w_as_opcode_register_register_newline (char *opcode,int reg1,int reg2) +{ + w_as_opcode (opcode); + w_as_register_register_newline (reg1,reg2); +} + +static void w_as_movl_register_register_newline (int reg1,int reg2) +{ + w_as_opcode_movl(); + w_as_register_register_newline (reg1,reg2); +} + static void w_as_immediate_register_newline (int i,int reg) { if (!intel_asm){ @@ -885,8 +899,7 @@ static void w_as_move_instruction (struct instruction *instruction,int size_flag reg=parameter.parameter_data.reg.r; - w_as_opcode ("xchg"); - w_as_register_register_newline (reg,REGISTER_D0); + w_as_opcode_register_register_newline ("xchg",reg,REGISTER_D0); reg1=instruction->instruction_parameters[1].parameter_data.reg.r; if (reg1==reg) @@ -905,8 +918,7 @@ static void w_as_move_instruction (struct instruction *instruction,int size_flag } w_as_newline(); - w_as_opcode ("xchg"); - w_as_register_register_newline (reg,REGISTER_D0); + w_as_opcode_register_register_newline ("xchg",reg,REGISTER_D0); return; } @@ -996,8 +1008,7 @@ static void w_as_move_instruction (struct instruction *instruction,int size_flag reg=parameter.parameter_data.reg.r; - w_as_opcode ("xchg"); - w_as_register_register_newline (reg,REGISTER_D0); + w_as_opcode_register_register_newline ("xchg",reg,REGISTER_D0); reg1=instruction->instruction_parameters[1].parameter_data.ir->a_reg.r; reg2=instruction->instruction_parameters[1].parameter_data.ir->d_reg.r; @@ -1026,8 +1037,7 @@ static void w_as_move_instruction (struct instruction *instruction,int size_flag } w_as_newline(); - w_as_opcode ("xchg"); - w_as_register_register_newline (reg,REGISTER_D0); + w_as_opcode_register_register_newline ("xchg",reg,REGISTER_D0); return; } @@ -1135,8 +1145,7 @@ static void w_as_shift_instruction (struct instruction *instruction,char *opcode } else { int r; - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_A0,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_A0,REGISTER_O0); w_as_opcode_movl(); if (intel_asm) @@ -1158,8 +1167,7 @@ static void w_as_shift_instruction (struct instruction *instruction,char *opcode fprintf (assembly_file,",cl"); w_as_newline(); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_O0,REGISTER_A0); + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A0); } } @@ -1381,13 +1389,11 @@ static void w_as_float_branch_instruction (struct instruction *instruction,int n r=instruction->instruction_parameters[0].parameter_data.reg.r; - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_D0,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); as_test_floating_point_condition_code (n); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_O0,REGISTER_D0); + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); switch (n){ case 0: @@ -1421,8 +1427,7 @@ static void w_as_set_condition_instruction (struct instruction *instruction,char r=instruction->instruction_parameters[0].parameter_data.reg.r; if (r==REGISTER_A3 || r==REGISTER_A4){ - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_D0,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); w_as_opcode (opcode); fprintf (assembly_file,intel_asm ? "al" : "%%al"); @@ -1436,8 +1441,7 @@ static void w_as_set_condition_instruction (struct instruction *instruction,char w_as_comma_register (r); w_as_newline(); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_O0,REGISTER_D0); + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); } else { char *reg_s; @@ -1475,10 +1479,8 @@ static void w_as_set_float_condition_instruction (struct instruction *instructio r=instruction->instruction_parameters[0].parameter_data.reg.r; - if (r!=REGISTER_D0){ - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_D0,r); - } + if (r!=REGISTER_D0) + w_as_movl_register_register_newline (REGISTER_D0,r); as_test_floating_point_condition_code (n); @@ -1507,9 +1509,229 @@ static void w_as_set_float_condition_instruction (struct instruction *instructio w_as_comma_register (REGISTER_D0); w_as_newline(); - if (r!=REGISTER_D0){ - w_as_opcode ("xchg"); - w_as_register_register_newline (r,REGISTER_D0); + if (r!=REGISTER_D0) + w_as_opcode_register_register_newline ("xchg",r,REGISTER_D0); +} + +/* + From The PowerPC Compiler WriterÕs Guide, + Warren, Henry S., Jr., IBM Research Report RC 18601 [1992]. Changing Division by a + Constant to Multiplication in TwoÕs Complement Arithmetic, (December 21), + Granlund, Torbjorn and Montgomery, Peter L. [1994]. SIGPLAN Notices, 29 (June), 61. +*/ + +struct ms magic (int d) + /* must have 2 <= d <= 231-1 or -231 <= d <= -2 */ +{ + int p; + unsigned int ad, anc, delta, q1, r1, q2, r2, t; + const unsigned int two31 = 2147483648;/* 231 */ + struct ms mag; + + ad = abs(d); + t = two31 + ((unsigned int)d >> 31); + anc = t - 1 - t%ad; /* absolute value of nc */ + p = 31; /* initialize p */ + q1 = two31/anc; /* initialize q1 = 2p/abs(nc) */ + r1 = two31 - q1*anc;/* initialize r1 = rem(2p,abs(nc)) */ + q2 = two31/ad; /* initialize q2 = 2p/abs(d) */ + r2 = two31 - q2*ad; /* initialize r2 = rem(2p,abs(d)) */ + + do { + p = p + 1; + q1 = 2*q1; /* update q1 = 2p/abs(nc) */ + r1 = 2*r1; /* update r1 = rem(2p/abs(nc)) */ + if (r1 >= anc) {/* must be unsigned comparison */ + q1 = q1 + 1; + r1 = r1 - anc; + } + q2 = 2*q2; /* update q2 = 2p/abs(d) */ + r2 = 2*r2; /* update r2 = rem(2p/abs(d)) */ + if (r2 >= ad) { /* must be unsigned comparison */ + q2 = q2 + 1; + r2 = r2 - ad; + } + delta = ad - r2; + } while (q1 < delta || (q1 == delta && r1 == 0)); + + mag.m = q2 + 1; + if (d < 0) mag.m = -mag.m; /* resulting magic number */ + mag.s = p - 32; /* resulting shift */ + + return mag; +} + +static void w_as_div_rem_i_instruction (struct instruction *instruction,int compute_remainder) +{ + int s_reg1,s_reg2,s_reg3,i,sd_reg,i_reg,tmp_reg,abs_i; + struct ms ms; + + if (instruction->instruction_parameters[0].parameter_type!=P_IMMEDIATE) + internal_error_in_function ("w_as_div_rem_i_instruction"); + + i=instruction->instruction_parameters[0].parameter_data.i; + + if (! ((i>1 || (i<-1 && i!=0x80000000)))) + internal_error_in_function ("w_as_div_rem_i_instruction"); + + abs_i=abs (i); + + if (compute_remainder) + i=abs_i; + + ms=magic (abs_i); + + sd_reg=instruction->instruction_parameters[1].parameter_data.reg.r; + tmp_reg=instruction->instruction_parameters[2].parameter_data.reg.r; + + if (sd_reg==tmp_reg) + internal_error_in_function ("w_as_div_rem_i_instruction"); + + if (sd_reg==REGISTER_A1){ + if (tmp_reg!=REGISTER_D0) + w_as_movl_register_register_newline (REGISTER_D0,tmp_reg); + + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + + s_reg1=sd_reg; + s_reg2=REGISTER_O0; + i_reg=REGISTER_D0; + } else if (sd_reg==REGISTER_D0){ + if (tmp_reg!=REGISTER_A1) + w_as_movl_register_register_newline (REGISTER_A1,tmp_reg); + + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); + + s_reg1=REGISTER_A1; + s_reg2=REGISTER_O0; + i_reg=REGISTER_A1; + } else { + if (tmp_reg==REGISTER_D0) + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); + else if (tmp_reg==REGISTER_A1) + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); + else { + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_A1,tmp_reg); + } + + s_reg1=sd_reg; + s_reg2=sd_reg; + i_reg=REGISTER_D0; + } + + w_as_opcode_movl(); + w_as_immediate_register_newline (ms.m,i_reg); + + w_as_opcode (intel_asm ? "imul" : "imull"); + w_as_register (s_reg1); + w_as_newline(); + + if (compute_remainder) + w_as_movl_register_register_newline (s_reg2,REGISTER_D0); + + if (ms.m<0) + w_as_opcode_register_register_newline ("add",s_reg2,REGISTER_A1); + + if (compute_remainder){ + if (s_reg2==sd_reg && s_reg2!=REGISTER_D0 && s_reg2!=REGISTER_A1){ + s_reg3=s_reg2; + s_reg2=REGISTER_D0; + } else + s_reg3=REGISTER_D0; + } + + w_as_opcode (i>=0 ? "shr" : "sar"); + w_as_immediate_register_newline (31,s_reg2); + + if (ms.s>0){ + w_as_opcode ("sar"); + w_as_immediate_register_newline (ms.s,REGISTER_A1); + } + + if (!compute_remainder){ + if (sd_reg==REGISTER_A1){ + if (i>=0) + w_as_opcode_register_register_newline ("add",s_reg2,REGISTER_A1); + else { + w_as_opcode_register_register_newline ("sub",REGISTER_A1,s_reg2); + w_as_movl_register_register_newline (s_reg2,sd_reg); + } + } else if (sd_reg==REGISTER_D0){ + struct index_registers index_registers; + + if (i>=0){ + index_registers.a_reg.r=REGISTER_A1; + index_registers.d_reg.r=s_reg2; + + w_as_opcode (intel_asm ? "lea" : "leal"); + if (!intel_asm) + w_as_register_comma (sd_reg); + w_as_indexed (0,&index_registers); + if (intel_asm) + w_as_comma_register (sd_reg); + w_as_newline(); + } else { + w_as_movl_register_register_newline (s_reg2,sd_reg); + w_as_opcode_register_register_newline ("sub",REGISTER_A1,sd_reg); + } + } else + w_as_opcode_register_register_newline (i>=0 ? "add" : "sub",REGISTER_A1,s_reg2); /* s_reg2==sd_reg */ + } else { + int i2; + + w_as_opcode_register_register_newline ("add",s_reg2,REGISTER_A1); + + i2=i & (i-1); + if ((i2 & (i2-1))==0){ + unsigned int n; + int n_shifts; + + n=i; + + n_shifts=0; + while (n>0){ + while ((n & 1)==0){ + n>>=1; + ++n_shifts; + } + + if (n_shifts>0){ + w_as_opcode ("shl"); + w_as_immediate_register_newline (n_shifts,REGISTER_A1); + } + + w_as_opcode_register_register_newline ("sub",REGISTER_A1,s_reg3); + + n>>=1; + n_shifts=1; + } + } else { + w_as_opcode (intel_asm ? "imul" : "imull"); + w_as_immediate_register_newline (i,REGISTER_A1); + + w_as_opcode_register_register_newline ("sub",REGISTER_A1,s_reg3); + } + + if (sd_reg!=s_reg3) + w_as_movl_register_register_newline (s_reg3,sd_reg); + } + + if (sd_reg==REGISTER_A1){ + if (tmp_reg!=REGISTER_D0) + w_as_movl_register_register_newline (tmp_reg,REGISTER_D0); + } else if (sd_reg==REGISTER_D0){ + if (tmp_reg!=REGISTER_A1) + w_as_movl_register_register_newline (tmp_reg,REGISTER_A1); + } else { + if (tmp_reg==REGISTER_D0) + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); + else if (tmp_reg==REGISTER_A1) + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); + else { + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); + w_as_movl_register_register_newline (tmp_reg,REGISTER_A1); + } } } @@ -1524,50 +1746,46 @@ static void w_as_div_instruction (struct instruction *instruction) i=instruction->instruction_parameters[0].parameter_data.i; - if (! ((i & (i-1))==0 && i>0)){ - internal_error_in_function ("w_as_div_instruction"); - return; - } - - if (i==1) - return; - - log2i=0; - while (i>1){ - i=i>>1; - ++log2i; - } - - w_as_opcode_movl(); - w_as_register_register_newline (d_reg,REGISTER_O0); + if ((i & (i-1))==0 && i>0){ + if (i==1) + return; + + log2i=0; + while (i>1){ + i=i>>1; + ++log2i; + } + + w_as_movl_register_register_newline (d_reg,REGISTER_O0); - if (log2i==1){ - w_as_opcode ("sar"); - w_as_immediate_register_newline (31,REGISTER_O0); + if (log2i==1){ + w_as_opcode ("sar"); + w_as_immediate_register_newline (31,REGISTER_O0); - w_as_opcode ("sub"); - w_as_register_register_newline (REGISTER_O0,d_reg); - } else { - w_as_opcode ("sar"); - w_as_immediate_register_newline (31,d_reg); + w_as_opcode_register_register_newline ("sub",REGISTER_O0,d_reg); + } else { + w_as_opcode ("sar"); + w_as_immediate_register_newline (31,d_reg); - w_as_opcode ("and"); - w_as_immediate_register_newline ((1<<log2i)-1,d_reg); + w_as_opcode ("and"); + w_as_immediate_register_newline ((1<<log2i)-1,d_reg); - w_as_opcode ("add"); - w_as_register_register_newline (REGISTER_O0,d_reg); - } - - w_as_opcode ("sar"); - w_as_immediate_register_newline (log2i,d_reg); + w_as_opcode_register_register_newline ("add",REGISTER_O0,d_reg); + } + + w_as_opcode ("sar"); + w_as_immediate_register_newline (log2i,d_reg); - return; + return; + } else { + internal_error_in_function ("w_as_div_instruction"); + return; + } } switch (d_reg){ case REGISTER_D0: - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); w_as_instruction_without_parameters ("cdq"); @@ -1588,15 +1806,12 @@ static void w_as_div_instruction (struct instruction *instruction) } w_as_newline(); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_O0,REGISTER_A1); + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); break; case REGISTER_A1: - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_D0,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_A1,REGISTER_D0); + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_D0); w_as_instruction_without_parameters ("cdq"); @@ -1629,18 +1844,14 @@ static void w_as_div_instruction (struct instruction *instruction) } w_as_newline(); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_D0,REGISTER_A1); + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_A1); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_O0,REGISTER_D0); + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); break; default: - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); - w_as_opcode ("xchg"); - w_as_register_register_newline (REGISTER_D0,d_reg); + w_as_opcode_register_register_newline ("xchg",REGISTER_D0,d_reg); w_as_instruction_without_parameters ("cdq"); @@ -1677,11 +1888,9 @@ static void w_as_div_instruction (struct instruction *instruction) } w_as_newline(); - w_as_opcode ("xchg"); - w_as_register_register_newline (REGISTER_D0,d_reg); + w_as_opcode_register_register_newline ("xchg",REGISTER_D0,d_reg); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_O0,REGISTER_A1); + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); } } @@ -1696,6 +1905,9 @@ static void w_as_rem_instruction (struct instruction *instruction) i=instruction->instruction_parameters[0].parameter_data.i; + if (i<0 && i!=0x80000000) + i=-i; + if (! ((i & (i-1))==0 && i>1)){ internal_error_in_function ("w_as_rem_instruction"); return; @@ -1707,8 +1919,7 @@ static void w_as_rem_instruction (struct instruction *instruction) ++log2i; } - w_as_opcode_movl(); - w_as_register_register_newline (d_reg,REGISTER_O0); + w_as_movl_register_register_newline (d_reg,REGISTER_O0); if (log2i==1){ w_as_opcode ("and"); @@ -1717,8 +1928,7 @@ static void w_as_rem_instruction (struct instruction *instruction) w_as_opcode ("sar"); w_as_immediate_register_newline (31,REGISTER_O0); - w_as_opcode ("xor"); - w_as_register_register_newline (REGISTER_O0,d_reg); + w_as_opcode_register_register_newline ("xor",REGISTER_O0,d_reg); } else { w_as_opcode ("sar"); w_as_immediate_register_newline (31,REGISTER_O0); @@ -1726,23 +1936,20 @@ static void w_as_rem_instruction (struct instruction *instruction) w_as_opcode ("and"); w_as_immediate_register_newline ((1<<log2i)-1,REGISTER_O0); - w_as_opcode ("add"); - w_as_register_register_newline (REGISTER_O0,d_reg); + w_as_opcode_register_register_newline ("add",REGISTER_O0,d_reg); w_as_opcode ("and"); w_as_immediate_register_newline ((1<<log2i)-1,d_reg); } - w_as_opcode ("sub"); - w_as_register_register_newline (REGISTER_O0,d_reg); + w_as_opcode_register_register_newline ("sub",REGISTER_O0,d_reg); return; } switch (d_reg){ case REGISTER_D0: - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); w_as_instruction_without_parameters ("cdq"); @@ -1763,19 +1970,15 @@ static void w_as_rem_instruction (struct instruction *instruction) } w_as_newline(); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_A1,REGISTER_D0); + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_D0); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_O0,REGISTER_A1); + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); break; case REGISTER_A1: - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_D0,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_D0,REGISTER_O0); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_A1,REGISTER_D0); + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_D0); w_as_instruction_without_parameters ("cdq"); @@ -1808,15 +2011,12 @@ static void w_as_rem_instruction (struct instruction *instruction) } w_as_newline(); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_O0,REGISTER_D0); + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_D0); break; default: - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_A1,REGISTER_O0); + w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0); - w_as_opcode ("xchg"); - w_as_register_register_newline (REGISTER_D0,d_reg); + w_as_opcode_register_register_newline ("xchg",REGISTER_D0,d_reg); w_as_instruction_without_parameters ("cdq"); @@ -1853,14 +2053,11 @@ static void w_as_rem_instruction (struct instruction *instruction) } w_as_newline(); - w_as_opcode_movl(); - w_as_register_register_newline (d_reg,REGISTER_D0); + w_as_movl_register_register_newline (d_reg,REGISTER_D0); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_A1,d_reg); + w_as_movl_register_register_newline (REGISTER_A1,d_reg); - w_as_opcode_movl(); - w_as_register_register_newline (REGISTER_O0,REGISTER_A1); + w_as_movl_register_register_newline (REGISTER_O0,REGISTER_A1); } } @@ -2763,9 +2960,15 @@ static void w_as_instructions (register struct instruction *instruction) case IDIV: w_as_div_instruction (instruction); break; + case IDIVI: + w_as_div_rem_i_instruction (instruction,0); + break; case IMOD: w_as_rem_instruction (instruction); break; + case IREMI: + w_as_div_rem_i_instruction (instruction,1); + break; case IAND: w_as_dyadic_instruction (instruction,intel_asm ? "and" : "andl"); break; @@ -3384,11 +3384,34 @@ static void linearize_div_mod_operator (int i_instruction_code,INSTRUCTION_GRAPH 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 && (i_instruction_code==IMOD ? ad_1.ad_offset>1 : ad_1.ad_offset>0))) || ad_1.ad_mode==P_INDEXED) - in_data_register (&ad_1); + if (ad_1.ad_mode==P_IMMEDIATE){ + int i; + + i=ad_1.ad_offset; + if (i_instruction_code==IMOD && i<0 && i!=0x80000000) + i=-i; + + if ((i & (i-1))==0 && (i_instruction_code==IMOD ? i>1 : i>0)) + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + else if (i>1 || (i<-1 && i!=0x80000000)){ + int tmp_reg; + + tmp_reg=get_dregister(); + instruction_ad_r_r (i_instruction_code==IDIV ? IDIVI : IREMI,&ad_1,ad_2.ad_register,tmp_reg); + free_dregister (tmp_reg); + } else { + in_data_register (&ad_1); + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + } + } else { + if (ad_1.ad_mode==P_INDEXED) + in_data_register (&ad_1); + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); + } +# else + instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); # endif - instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register); --*ad_2.ad_count_p; reg_1=ad_2.ad_register; @@ -0,0 +1,3949 @@ +/* + File: cgopt.c + Author: John van Groningen + At: University of Nijmegen +*/ + +#define FIX_REG_USES_INDEX + +#include <stdio.h> +#include "cgport.h" +#include "cg.h" +#include "cgrconst.h" +#include "cgtypes.h" +#include "cgiconst.h" +#include "cglin.h" + +#include "cgopt.h" + +#ifdef I486 +# undef I486_USE_SCRATCH_REGISTER +#endif + +#ifndef M68000 +# define NEW_R_ALLOC +#endif + +#ifdef G_POWER +# define IF_G_POWER(a) a +#else +# define IF_G_POWER(a) +#endif + +#ifdef sparc +# define IF_G_SPARC(a) a +#else +# define IF_G_SPARC(a) +#endif + +#if defined (G_POWER) || defined (sparc) +# define IF_G_RISC(a) a +#else +# define IF_G_RISC(a) +#endif + +#define POWER_PC_A_STACK_OPTIMIZE + +#define for_all(v,l,n) for(v=(l);v!=NULL;v=v->n) + +#pragma segment Code4 + +/* from cgcode.c : */ + +extern struct basic_block *first_block; + +static void optimize_branch_jump + (struct instruction *branch,struct instruction *jump,struct basic_block *jump_block) +{ + branch->instruction_parameters[0].parameter_data.l= + jump->instruction_parameters[0].parameter_data.l; + + switch (branch->instruction_icode){ + case IBEQ: branch->instruction_icode=IBNE; break; + case IBGE: branch->instruction_icode=IBLT; break; + case IBGT: branch->instruction_icode=IBLE; break; + case IBLE: branch->instruction_icode=IBGT; break; + case IBLT: branch->instruction_icode=IBGE; break; + case IBNE: branch->instruction_icode=IBEQ; break; + case IFBEQ: branch->instruction_icode=IFBNE; break; + case IFBGE: branch->instruction_icode=IFBLT; break; + case IFBGT: branch->instruction_icode=IFBLE; break; + case IFBLE: branch->instruction_icode=IFBGT; break; + case IFBLT: branch->instruction_icode=IFBGE; break; + case IFBNE: branch->instruction_icode=IFBEQ; + } + + jump_block->block_instructions=NULL; +} + +void optimize_jumps() +{ + struct basic_block *block; + + for_all (block,first_block,block_next){ + struct instruction *branch; + + if ((branch=block->block_last_instruction)!=NULL){ + switch (branch->instruction_icode){ + case IBEQ: case IBGE: case IBGT: case IBLE: case IBLT: case IBNE: + case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE: + { + struct basic_block *next_block; + + if ((next_block=block->block_next)!=NULL && next_block->block_labels==NULL){ + struct instruction *jump; + + if ((jump=next_block->block_instructions)!=NULL + && jump->instruction_icode==IJMP + && jump->instruction_parameters[0].parameter_type==P_LABEL + && jump->instruction_next==NULL ) + { + struct basic_block *next_next_block; + + if ((next_next_block=next_block->block_next)!=NULL){ + struct block_label *block_labels; + LABEL *branch_label; + + branch_label=branch->instruction_parameters[0].parameter_data.l; + if ((branch_label->label_flags & LOCAL_LABEL) && + (jump->instruction_parameters[0].parameter_data.l->label_flags & LOCAL_LABEL) +#ifdef G_POWER + && !(jump->instruction_parameters[0].parameter_data.l->label_flags & DOT_O_BEFORE_LABEL) +#endif + ) + { + for ( block_labels=next_next_block->block_labels; + block_labels!=NULL; + block_labels=block_labels->block_label_next + ) + if (block_labels->block_label_label==branch_label){ + optimize_branch_jump (branch,jump,next_block); + break; + } + } + } + } + } + break; + } + case IJMP: + { + struct basic_block *next_block; + + if ((next_block=block->block_next)!=NULL){ + struct block_label *labels; + LABEL *jmp_label; + + jmp_label=branch->instruction_parameters[0].parameter_data.l; + + labels=next_block->block_labels; + for (; labels!=NULL; labels=labels->block_label_next){ + if (labels->block_label_label==jmp_label){ + if (next_block->block_begin_module) + next_block->block_link_module=1; + + /* remove branch */ + if (branch->instruction_prev!=NULL) + branch->instruction_prev->instruction_next=NULL; + else + block->block_instructions=NULL; + break; + } + } + } + break; + } +#if defined (G_POWER) + case IJSR: + { + struct basic_block *next_block; + struct instruction *next_block_last_instruction; + + if (block->block_n_new_heap_cells!=0 && !(branch->instruction_arity & NO_MFLR)){ + if (block->block_gc_kind==0){ + block->block_gc_kind=2; + branch->instruction_arity |= NO_MFLR; + } else if (block->block_gc_kind==1){ + block->block_gc_kind=3; + branch->instruction_arity |= NO_MFLR; + } + } + + if ((next_block=block->block_next)!=NULL && next_block->block_labels==NULL + && !next_block->block_begin_module && !(next_block->block_n_node_arguments>-100)) + { + if (next_block->block_n_new_heap_cells!=0){ + branch->instruction_arity|=NO_MTLR; + next_block->block_gc_kind=1; + } else { + if ((next_block_last_instruction=next_block->block_last_instruction)!=NULL + && next_block_last_instruction->instruction_icode==IJSR) + { + branch->instruction_arity|=NO_MTLR; + next_block_last_instruction->instruction_arity|=NO_MFLR; + } + } + } + } +#endif + } + } + } +} + +#if defined (M68000) || defined (I486) + +# ifdef M68000 +static struct parameter *previous_a_parameter; +static int previous_a_icode; +static int a_offset; +# endif + +static int b_offset; + +# ifdef M68000 +static int get_argument_size (int instruction_code) +{ + switch (instruction_code){ + case IADD: case IAND: case IASR: case ICMP: case IDIV: + case IEOR: case ILSL: case ILSR: case IMOD: case IMOVE: + case IMUL: case IOR: case ISUB: case ITST: +IF_G_RISC (case IADDI: case ILSLI:) +IF_G_SPARC (case IADDO: case ISUBO: ) +#ifdef I486 + case IDIVI: case REMI: +#endif + return 4; + case IFADD: case IFCMP: case IFDIV: case IFMUL: + case IFREM: case IFSUB: case IFTST: case IFMOVE: + case IFACOS: case IFASIN: case IFATAN: case IFCOS: + case IFEXP: case IFLN: case IFLOG10: case IFSIN: + case IFTAN: case IFNEG: +#if !defined (G_POWER) + case IFSQRT: +#endif + return 8; + default: + return 0; + } +} + +static void optimize_a_stack_access (struct parameter *parameter,int instruction_code) +{ + int previous_argument_size; + + if (previous_a_parameter!=NULL){ + previous_argument_size=get_argument_size (previous_a_icode); + + if (previous_argument_size!=0){ + if (previous_a_parameter->parameter_offset==0){ + if (parameter->parameter_offset-a_offset==previous_argument_size){ + a_offset+=previous_argument_size; + previous_a_parameter->parameter_type=P_POST_INCREMENT; + } else { + int argument_size=get_argument_size (instruction_code); + + if (argument_size!=0 && argument_size!=previous_argument_size + && parameter->parameter_offset-a_offset + ==previous_argument_size-argument_size) + { + a_offset+=previous_argument_size; + previous_a_parameter->parameter_type=P_POST_INCREMENT; + } + } + } else + if (previous_a_parameter->parameter_offset==-previous_argument_size + && parameter->parameter_offset-a_offset!=0) + { + a_offset-=previous_argument_size; + previous_a_parameter->parameter_type=P_PRE_DECREMENT; + } + } + } + + parameter->parameter_offset-=a_offset; + previous_a_parameter=parameter; + previous_a_icode=instruction_code; +} +# endif + +extern struct basic_block *last_block; +extern struct instruction *last_instruction; + +#if defined (M68000) | defined (I486) +static void insert_decrement_b_stack_pointer (struct instruction *next_instruction,int offset) +{ + struct instruction *previous_instruction,*instruction; + + instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+2*sizeof (struct parameter)); + + instruction->instruction_arity=2; +#ifdef M68000 + instruction->instruction_icode=ISUB; + + instruction->instruction_parameters[0].parameter_type=P_IMMEDIATE; + instruction->instruction_parameters[0].parameter_data.i=offset; +#else + instruction->instruction_icode=ILEA; + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=-offset; + instruction->instruction_parameters[0].parameter_data.reg.r=B_STACK_POINTER; +#endif + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_data.i=B_STACK_POINTER; + + previous_instruction=next_instruction->instruction_prev; + if (previous_instruction==NULL) + last_block->block_instructions=instruction; + else + previous_instruction->instruction_next=instruction; + + instruction->instruction_next=next_instruction; + instruction->instruction_prev=previous_instruction; + + if (next_instruction!=NULL) + next_instruction->instruction_prev=instruction; +} +#endif + +#ifdef I486 +static void optimize_b_stack_access (struct parameter *parameter,struct instruction *instruction) +{ + if (parameter->parameter_offset<b_offset){ + insert_decrement_b_stack_pointer (instruction,b_offset-parameter->parameter_offset); + b_offset=parameter->parameter_offset; + } + + parameter->parameter_offset-=b_offset; +} + +static void optimize_b_stack_access2 (struct instruction *instruction) +{ + struct parameter *parameter0,*parameter1; + + parameter0=&instruction->instruction_parameters[0]; + parameter1=&instruction->instruction_parameters[1]; + + if (parameter1->parameter_offset<b_offset && parameter1->parameter_offset < parameter0->parameter_offset){ + insert_decrement_b_stack_pointer (instruction,b_offset-parameter1->parameter_offset); + + b_offset=parameter1->parameter_offset; + parameter0->parameter_offset-=b_offset; + parameter1->parameter_offset=0; + return; + } + + if (parameter0->parameter_offset<b_offset){ + insert_decrement_b_stack_pointer (instruction,b_offset-parameter0->parameter_offset); + b_offset=parameter0->parameter_offset; + parameter0->parameter_offset=0; + } else + parameter0->parameter_offset-=b_offset; + + if (parameter1->parameter_offset<b_offset) + internal_error_in_function ("optimize_b_stack_access2"); + + parameter1->parameter_offset-=b_offset; +} +#endif + +#ifdef M68000 +static void optimize_b_stack_access (struct parameter *parameter,struct instruction *instruction) +{ + int argument_size; + + if (parameter->parameter_offset<b_offset){ + argument_size=get_argument_size (instruction->instruction_icode); + + if (argument_size!=0 && parameter->parameter_offset==b_offset-argument_size){ + b_offset-=argument_size; + parameter->parameter_type=P_PRE_DECREMENT; + return; + } else { + insert_decrement_b_stack_pointer (instruction,b_offset-parameter->parameter_offset); + b_offset=parameter->parameter_offset; + } + } else + if (parameter->parameter_offset==b_offset + && b_offset<((WORD)parameter->parameter_data.reg.u)) + { + argument_size=get_argument_size (instruction->instruction_icode); + + if (argument_size!=0 && b_offset+argument_size<=((WORD)parameter->parameter_data.reg.u)){ + b_offset+=argument_size; + parameter->parameter_type=P_POST_INCREMENT; + return; + } + } + + parameter->parameter_offset-=b_offset; +} + +static void optimize_b_stack_access2 (struct instruction *instruction) +{ + int argument_size; + struct parameter *parameter0,*parameter1; + + parameter0=&instruction->instruction_parameters[0]; + parameter1=&instruction->instruction_parameters[1]; + + argument_size=get_argument_size (instruction->instruction_icode); + + if (parameter1->parameter_offset<b_offset + && !(argument_size!=0 && parameter1->parameter_offset==b_offset-argument_size)) + { + insert_decrement_b_stack_pointer (instruction,b_offset-parameter1->parameter_offset); + + b_offset=parameter1->parameter_offset; + parameter0->parameter_offset-=b_offset; + parameter1->parameter_offset=0; + return; + } + + if (parameter0->parameter_offset<b_offset){ + if (argument_size!=0 && parameter0->parameter_offset==b_offset-argument_size){ + b_offset-=argument_size; + parameter0->parameter_type=P_PRE_DECREMENT; + } else { + insert_decrement_b_stack_pointer (instruction,b_offset-parameter0->parameter_offset); + b_offset=parameter0->parameter_offset; + parameter0->parameter_offset=0; + } + } else { + if (parameter0->parameter_offset==b_offset + && b_offset<((WORD)parameter0->parameter_data.reg.u)) + { + if (argument_size!=0 && b_offset+argument_size<=((WORD)parameter0->parameter_data.reg.u)){ + b_offset+=argument_size; + parameter0->parameter_type=P_POST_INCREMENT; + } else + parameter0->parameter_offset-=b_offset; + } else + parameter0->parameter_offset-=b_offset; + } + + if (parameter1->parameter_offset<b_offset){ + if (argument_size!=0 && parameter1->parameter_offset==b_offset-argument_size){ + b_offset-=argument_size; + parameter1->parameter_type=P_PRE_DECREMENT; + return; + } else + internal_error_in_function ("optimize_b_stack_access2"); + } else + if (parameter1->parameter_offset==b_offset + && b_offset<((WORD)parameter1->parameter_data.reg.u)) + { + if (argument_size!=0 && b_offset+argument_size<=((WORD)parameter1->parameter_data.reg.u)){ + b_offset+=argument_size; + parameter1->parameter_type=P_POST_INCREMENT; + return; + } + } + + parameter1->parameter_offset-=b_offset; +} +# endif + +static void compute_maximum_b_stack_offsets (register int b_offset) +{ + struct instruction *instruction; + + for_all (instruction,last_instruction,instruction_prev){ + switch (instruction->instruction_arity){ + default: + if ( +#ifdef M68000 + instruction->instruction_icode!=IMOVEM && +#endif +#ifdef I486 + instruction->instruction_icode!=IDIVI && + instruction->instruction_icode!=IREMI && +#endif + instruction->instruction_icode!=IMOD) +#ifdef M68000 + if (instruction->instruction_icode==IBMOVE) + break; + else +#endif + internal_error_in_function ("compute_maximum_b_stack_offsets"); + /* only first argument of movem or mod might be register indirect */ + /* no break ! */ + case 1: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT + && instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER) + { + instruction->instruction_parameters[0].parameter_data.reg.u=b_offset; + if (instruction->instruction_parameters[0].parameter_offset<b_offset) + b_offset=instruction->instruction_parameters[0].parameter_offset; + } + break; + case 2: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT + && instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER) + { + instruction->instruction_parameters[0].parameter_data.reg.u=b_offset; + if (instruction->instruction_parameters[0].parameter_offset<b_offset) + b_offset=instruction->instruction_parameters[0].parameter_offset; + } + if (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.reg.u=b_offset; + if (instruction->instruction_parameters[1].parameter_offset<b_offset) + b_offset=instruction->instruction_parameters[1].parameter_offset; + } + } + } +} + +void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_offset_p) +{ + struct instruction *instruction; + +# ifdef M68000 + a_offset=0; + previous_a_parameter=NULL; +# endif + + b_offset=0; + + compute_maximum_b_stack_offsets (*b_offset_p); + +# ifdef M68000 + for_all (instruction,block->block_instructions,instruction_next){ + switch (instruction->instruction_arity){ + default: + if ( +# ifdef M68000 + instruction->instruction_icode!=IMOVEM && +# endif + instruction->instruction_icode!=IMOD) +# ifdef M68000 + if (instruction->instruction_icode==IBMOVE) + break; + else +# endif + internal_error_in_function ("optimize_stack_access"); + /* only first argument of movem or mod might be register indirect */ + /* no break ! */ + case 1: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ + switch (instruction->instruction_parameters[0].parameter_data.reg.r){ + case A_STACK_POINTER: + optimize_a_stack_access (&instruction->instruction_parameters[0], + instruction->instruction_icode); + break; + case B_STACK_POINTER: + optimize_b_stack_access (&instruction->instruction_parameters[0],instruction); + } + } + break; + case 2: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){ + if (instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER + && instruction->instruction_parameters[1].parameter_type==P_INDIRECT + && instruction->instruction_parameters[1].parameter_data.reg.r==B_STACK_POINTER) + { + optimize_b_stack_access2 (instruction); + break; + } + + switch (instruction->instruction_parameters[0].parameter_data.reg.r){ + case A_STACK_POINTER: + optimize_a_stack_access (&instruction->instruction_parameters[0], + instruction->instruction_icode); + break; + case B_STACK_POINTER: + optimize_b_stack_access (&instruction->instruction_parameters[0],instruction); + } + } + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT){ + switch (instruction->instruction_parameters[1].parameter_data.reg.r){ + case A_STACK_POINTER: + optimize_a_stack_access (&instruction->instruction_parameters[1], + instruction->instruction_icode); + break; + case B_STACK_POINTER: + optimize_b_stack_access (&instruction->instruction_parameters[1],instruction); + } + } + } + } + + if (previous_a_parameter!=NULL){ + int previous_argument_size; + + previous_argument_size=get_argument_size (previous_a_icode); + if (previous_argument_size!=0){ + if (previous_a_parameter->parameter_offset==0){ + if (*a_offset_p-a_offset==previous_argument_size){ + a_offset+=previous_argument_size; + previous_a_parameter->parameter_type=P_POST_INCREMENT; + } + } else if (previous_a_parameter->parameter_offset==-previous_argument_size){ + if (*a_offset_p-a_offset!=0){ + a_offset-=previous_argument_size; + previous_a_parameter->parameter_type=P_PRE_DECREMENT; + } + } + } + } + + *a_offset_p-=a_offset; +# endif + +# ifdef I486 + for_all (instruction,block->block_instructions,instruction_next){ + if (instruction->instruction_icode==IMOVE){ + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER) + { + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==B_STACK_POINTER) + { + struct parameter *parameter0,*parameter1; + + parameter0=&instruction->instruction_parameters[0]; + parameter1=&instruction->instruction_parameters[1]; + + if (parameter1->parameter_offset<b_offset && parameter1->parameter_offset!=b_offset-4){ + insert_decrement_b_stack_pointer (instruction,b_offset-parameter1->parameter_offset); + + b_offset=parameter1->parameter_offset; + parameter0->parameter_offset-=b_offset; + parameter1->parameter_offset=0; + continue; + } + + if (parameter0->parameter_offset<b_offset){ + insert_decrement_b_stack_pointer (instruction,b_offset-parameter0->parameter_offset); + b_offset=parameter0->parameter_offset; + parameter0->parameter_offset=0; + } else { + if (parameter0->parameter_offset==b_offset + && b_offset<((WORD)parameter0->parameter_data.reg.u)) + { + if (b_offset+4<=((WORD)parameter0->parameter_data.reg.u)){ + b_offset+=4; + parameter0->parameter_type=P_POST_INCREMENT; + } else + parameter0->parameter_offset-=b_offset; + } else + parameter0->parameter_offset-=b_offset; + } + + if (parameter1->parameter_offset<b_offset){ + if (parameter1->parameter_offset==b_offset-4){ + b_offset-=4; + parameter1->parameter_type=P_PRE_DECREMENT; + continue; + } else + internal_error_in_function ("optimize_stack_access"); + } + + parameter1->parameter_offset-=b_offset; + } else { + struct parameter *parameter; + + parameter=&instruction->instruction_parameters[0]; + + if (parameter->parameter_offset<b_offset){ + insert_decrement_b_stack_pointer (instruction,b_offset-parameter->parameter_offset); + b_offset=parameter->parameter_offset; + } else + if (parameter->parameter_offset==b_offset + && b_offset<((WORD)parameter->parameter_data.reg.u)) + { + if (b_offset+4<=((WORD)parameter->parameter_data.reg.u)){ + b_offset+=4; + parameter->parameter_type=P_POST_INCREMENT; + continue; + } + } + + parameter->parameter_offset-=b_offset; + } + } else { + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==B_STACK_POINTER) + { + struct parameter *parameter; + + parameter=&instruction->instruction_parameters[1]; + + if (parameter->parameter_offset<b_offset){ + if (parameter->parameter_offset==b_offset-4){ + b_offset-=4; + parameter->parameter_type=P_PRE_DECREMENT; + continue; + } else { + insert_decrement_b_stack_pointer (instruction,b_offset-parameter->parameter_offset); + b_offset=parameter->parameter_offset; + } + } + + parameter->parameter_offset-=b_offset; + } + } + } else + + switch (instruction->instruction_arity){ + default: + if (instruction->instruction_icode!=IDIVI && + instruction->instruction_icode!=IREMI && + instruction->instruction_icode!=IMOD) + internal_error_in_function ("optimize_stack_access"); + /* only first argument of mod might be register indirect */ + /* no break ! */ + case 1: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER) + optimize_b_stack_access + (&instruction->instruction_parameters[0],instruction); + break; + case 2: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER) + { + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT + && instruction->instruction_parameters[1].parameter_data.reg.r==B_STACK_POINTER) + { + optimize_b_stack_access2 (instruction); + } else + optimize_b_stack_access (&instruction->instruction_parameters[0],instruction); + } + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==B_STACK_POINTER) + optimize_b_stack_access + (&instruction->instruction_parameters[1],instruction); + } + } +# endif + +# ifdef OLDI486 + for_all (instruction,block->block_instructions,instruction_next){ + if (instruction->instruction_icode==IMOVE){ + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER && + instruction->instruction_parameters[0].parameter_offset==b_offset && + b_offset+4<=((WORD)instruction->instruction_parameters[0].parameter_data.reg.u) + ){ + instruction->instruction_parameters[0].parameter_type=P_POST_INCREMENT; + + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==B_STACK_POINTER + ){ + instruction->instruction_parameters[1].parameter_offset-=b_offset; + } + b_offset+=4; + continue; + } + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==B_STACK_POINTER && + instruction->instruction_parameters[1].parameter_offset==b_offset-4 + ){ + instruction->instruction_parameters[1].parameter_type=P_PRE_DECREMENT; + + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER + ){ + instruction->instruction_parameters[0].parameter_offset-=b_offset; + } + b_offset-=4; + continue; + } + } + + switch (instruction->instruction_arity){ + default: + if (instruction->instruction_icode!=IMOD) + internal_error_in_function ("optimize_stack_access"); + /* only first argument of movem or mod might be register indirect */ + /* no break ! */ + case 1: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER + ){ + instruction->instruction_parameters[0].parameter_offset-=b_offset; + } + break; + case 2: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==B_STACK_POINTER + ){ + instruction->instruction_parameters[0].parameter_offset-=b_offset; + } + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==B_STACK_POINTER + ){ + instruction->instruction_parameters[1].parameter_offset-=b_offset; + } + } + } +# endif + + *b_offset_p-=b_offset; +} +#endif + +#ifdef G_POWER + +# ifdef POWER_PC_A_STACK_OPTIMIZE +void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_offset_p) +{ + struct instruction *instruction; + int a_offset; + + a_offset=*a_offset_p; + + if (a_offset==0) + return; + + for_all (instruction,block->block_instructions,instruction_next){ + if (instruction->instruction_icode==IMOVE){ + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==A_STACK_POINTER && + instruction->instruction_parameters[0].parameter_offset==a_offset) + { + instruction->instruction_parameters[0].parameter_type=P_INDIRECT_WITH_UPDATE; + + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==A_STACK_POINTER) + { + instruction->instruction_parameters[1].parameter_offset -= a_offset; + } + break; + } + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==A_STACK_POINTER && + instruction->instruction_parameters[1].parameter_offset==a_offset) + { + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; + break; + } + } + } + + if (instruction!=NULL){ + while ((instruction=instruction->instruction_next)!=NULL){ + switch (instruction->instruction_arity){ + default: + break; + case 1: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==A_STACK_POINTER) + { + instruction->instruction_parameters[0].parameter_offset -= a_offset; + } + break; + case 2: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==A_STACK_POINTER) + { + instruction->instruction_parameters[0].parameter_offset -= a_offset; + } + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==A_STACK_POINTER) + { + instruction->instruction_parameters[1].parameter_offset -= a_offset; + } + break; + } + } + + *a_offset_p=0; + } +} +# endif + +extern struct instruction *last_heap_pointer_update; + +void optimize_heap_pointer_increment (struct basic_block *block,int offset_from_heap_register) +{ + struct instruction *instruction; + + instruction=last_heap_pointer_update; + + if (instruction!=NULL && instruction->instruction_icode==IMOVE + && instruction->instruction_parameters[1].parameter_type==P_INDIRECT_HP + && instruction->instruction_parameters[1].parameter_data.i==offset_from_heap_register) + { + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; + instruction->instruction_parameters[1].parameter_data.reg.r=HEAP_POINTER; + instruction->instruction_parameters[1].parameter_offset=offset_from_heap_register; + } else { + if (instruction!=NULL){ + instruction=instruction->instruction_next; + } else + instruction=block->block_instructions; + + for (; instruction!=NULL; instruction=instruction->instruction_next){ + switch (instruction->instruction_icode){ + case IADD: + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER && + instruction->instruction_parameters[1].parameter_data.reg.r==HEAP_POINTER) + { + internal_error_in_function ("optimize_heap_pointer_increment"); + } + continue; + case ILEA: + /* can be optimized, not yet implemented + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==HEAP_POINTER && + instruction->instruction_parameters[0].parameter_offset==offset_from_heap_register) + { + break; + } + */ + continue; + case IMOVE: + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER && + instruction->instruction_parameters[0].parameter_data.reg.r==HEAP_POINTER) + { + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER && + instruction->instruction_parameters[1].parameter_data.reg.r!=HEAP_POINTER) + { + } else { + internal_error_in_function ("optimize_heap_pointer_increment"); + } + } else { + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==HEAP_POINTER) + { + if (instruction->instruction_parameters[1].parameter_offset==offset_from_heap_register){ + instruction->instruction_parameters[1].parameter_type=P_INDIRECT_WITH_UPDATE; + break; + } + } else if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT_WITH_UPDATE + || instruction->instruction_parameters[1].parameter_type==P_INDIRECT_HP){ + internal_error_in_function ("optimize_heap_pointer_increment"); + } + } + continue; + case IFMOVE: + /* can be optimized, not yet implemented + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==HEAP_POINTER && + instruction->instruction_parameters[1].parameter_offset==offset_from_heap_register) + { + break; + } + */ + continue; + default: + continue; + } + break; + } + } + + if (instruction!=NULL){ + while ((instruction=instruction->instruction_next)!=NULL){ + switch (instruction->instruction_icode){ + case IADD: + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER && + instruction->instruction_parameters[1].parameter_data.reg.r==HEAP_POINTER) + { + internal_error_in_function ("optimize_heap_pointer_increment"); + } + break; + case ILEA: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT && + instruction->instruction_parameters[0].parameter_data.reg.r==HEAP_POINTER) + { + instruction->instruction_parameters[0].parameter_offset -= offset_from_heap_register; + } + break; + case IMOVE: + if (instruction->instruction_parameters[0].parameter_type==P_REGISTER && + instruction->instruction_parameters[0].parameter_data.reg.r==HEAP_POINTER) + { + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER && + instruction->instruction_parameters[1].parameter_data.reg.r!=HEAP_POINTER) + { + instruction->instruction_icode=ILEA; + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset = -offset_from_heap_register; + } else { + internal_error_in_function ("optimize_heap_pointer_increment"); + } + } else { + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==HEAP_POINTER) + { + instruction->instruction_parameters[1].parameter_offset -= offset_from_heap_register; + } else if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT_WITH_UPDATE + || instruction->instruction_parameters[1].parameter_type==P_INDIRECT_HP){ + internal_error_in_function ("optimize_heap_pointer_increment"); + } + } + break; + case IFMOVE: + if (instruction->instruction_parameters[1].parameter_type==P_INDIRECT && + instruction->instruction_parameters[1].parameter_data.reg.r==HEAP_POINTER) + { + instruction->instruction_parameters[1].parameter_offset -= offset_from_heap_register; + } + } + } + } else + i_add_i_r (offset_from_heap_register,HEAP_POINTER); + + last_heap_pointer_update=NULL; +} +#endif + +struct register_use { + int instruction_n; + int value_used; + int offset; + int reg; +}; + +struct register_allocation { + int instruction_n; + int value_used; + int reg; + int altered; +}; + +#ifdef NEW_R_ALLOC +struct register_use *r_reg_uses; +#else +struct register_use *a_reg_uses,*d_reg_uses; +#endif +struct register_use *f_reg_uses; + +#ifdef NEW_R_ALLOC +#define N_REAL_REGISTERS (N_REAL_A_REGISTERS+8) +struct register_allocation r_reg_alloc[N_REAL_REGISTERS]; +#else +struct register_allocation a_reg_alloc[8],d_reg_alloc[8]; +#endif + +#if defined (NEW_R_ALLOC) && (defined (sparc) || defined (G_POWER)) + struct register_allocation f_reg_alloc[15]; +#else + struct register_allocation f_reg_alloc[8]; +#endif + +static void initialize_register_uses (struct register_use *reg_uses,int highest_register,unsigned end_registers) +{ + int n; + struct register_use *reg_use; + + for (n=0,reg_use=reg_uses; n<highest_register; ++n,++reg_use){ + reg_use->instruction_n=0; + reg_use->value_used=0; + reg_use->reg=-1; + reg_use->offset=0; + } + + for (n=0; n<8; ++n) + if (end_registers & ((unsigned)1<<n)){ + reg_uses[n].instruction_n=1; + reg_uses[n].value_used=1; + } +} + +#ifdef NEW_R_ALLOC +static void initialize_a_register_uses (struct register_use *reg_uses,int highest_register,unsigned end_registers) +{ + int n; + struct register_use *reg_use; + + for (n=0,reg_use=reg_uses; --reg_use,n<highest_register; ++n){ + reg_use->instruction_n=0; + reg_use->value_used=0; + reg_use->reg=-1; + reg_use->offset=0; + } + + for (n=0; n<N_REAL_A_REGISTERS; ++n) + if (end_registers & ((unsigned)1<<n)){ + reg_uses[-(n+1)].instruction_n=1; + reg_uses[-(n+1)].value_used=1; + } +} +#endif + +unsigned int end_a_registers,end_d_registers,end_f_registers; + +static int instruction_number; + +static void use_parameter (struct parameter *parameter) +{ + struct register_use *r_use_p; + int reg; + + switch (parameter->parameter_type){ + case P_REGISTER: + case P_INDIRECT: +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: +#endif + reg=parameter->parameter_data.reg.r; + +#ifdef MORE_PARAMETER_REGISTERS + if ((unsigned)(num_to_d_reg (reg)-N_DATA_PARAMETER_REGISTERS)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS){ + reg = a_reg_num ((N_ADDRESS_PARAMETER_REGISTERS-1)-(num_to_d_reg (reg)-N_DATA_PARAMETER_REGISTERS)); + parameter->parameter_data.reg.r = reg; + } +#endif + +#ifdef NEW_R_ALLOC + r_use_p=&r_reg_uses[reg]; +#else + if (is_d_register (reg)) + r_use_p=&d_reg_uses[d_reg_num (reg)]; + else + r_use_p=&a_reg_uses[a_reg_num (reg)]; +#endif + parameter->parameter_data.reg.u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); + r_use_p->instruction_n=instruction_number; + r_use_p->value_used=1; + break; + case P_F_REGISTER: + reg=parameter->parameter_data.reg.r; + + r_use_p=&f_reg_uses[reg]; + + parameter->parameter_data.reg.u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); + r_use_p->instruction_n=instruction_number; + r_use_p->value_used=1; + break; + case P_INDEXED: + { + struct index_registers *index_registers; + + index_registers=parameter->parameter_data.ir; + +#ifdef MORE_PARAMETER_REGISTERS + if ((unsigned)(num_to_d_reg (index_registers->a_reg.r)-N_DATA_PARAMETER_REGISTERS)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + index_registers->a_reg.r = a_reg_num ((N_ADDRESS_PARAMETER_REGISTERS-1)-(num_to_d_reg (index_registers->a_reg.r)-N_DATA_PARAMETER_REGISTERS)); + + if ((unsigned)(num_to_d_reg (index_registers->d_reg.r)-N_DATA_PARAMETER_REGISTERS)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + index_registers->d_reg.r = a_reg_num ((N_ADDRESS_PARAMETER_REGISTERS-1)-(num_to_d_reg (index_registers->d_reg.r)-N_DATA_PARAMETER_REGISTERS)); +#endif + +#ifdef NEW_R_ALLOC + r_use_p=&r_reg_uses[index_registers->a_reg.r]; +#else + r_use_p=&a_reg_uses[a_reg_num (index_registers->a_reg.r)]; +#endif + index_registers->a_reg.u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); + r_use_p->instruction_n=instruction_number; + r_use_p->value_used=1; + +#ifdef NEW_R_ALLOC + r_use_p=&r_reg_uses[index_registers->d_reg.r]; +#else + r_use_p=&d_reg_uses[d_reg_num (index_registers->d_reg.r)]; +#endif + index_registers->d_reg.u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); + r_use_p->instruction_n=instruction_number; + r_use_p->value_used=1; + } + } +} + +static void define_parameter (struct parameter *parameter) +{ + struct register_use *r_use_p; + int reg,reg_num; + + switch (parameter->parameter_type){ + case P_REGISTER: + reg=parameter->parameter_data.reg.r; + +#ifdef MORE_PARAMETER_REGISTERS + if ((unsigned)(num_to_d_reg (reg)-N_DATA_PARAMETER_REGISTERS)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS){ + reg = a_reg_num ((N_ADDRESS_PARAMETER_REGISTERS-1)-(num_to_d_reg (reg)-N_DATA_PARAMETER_REGISTERS)); + parameter->parameter_data.reg.r = reg; + } +#endif + +#ifdef NEW_R_ALLOC + reg_num=reg; + r_use_p=&r_reg_uses[reg_num]; +#else + if (is_d_register (reg)){ + reg_num=d_reg_num (reg); + r_use_p=&d_reg_uses[reg_num]; + } else { + reg_num=a_reg_num (reg); + r_use_p=&a_reg_uses[reg_num]; + } +#endif + parameter->parameter_data.reg.u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); +#ifdef NEW_R_ALLOC + if ((unsigned)(reg_num+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS) +#else + if (reg_num<8) +#endif + r_use_p->instruction_n=instruction_number; + else + r_use_p->instruction_n=0; + r_use_p->value_used=0; + break; + case P_INDIRECT: +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: +#endif + reg=parameter->parameter_data.reg.r; + +#ifdef MORE_PARAMETER_REGISTERS + if ((unsigned)(num_to_d_reg (reg)-N_DATA_PARAMETER_REGISTERS)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS){ + reg = a_reg_num ((N_ADDRESS_PARAMETER_REGISTERS-1)-(num_to_d_reg (reg)-N_DATA_PARAMETER_REGISTERS)); + parameter->parameter_data.reg.r = reg; + } +#endif + +#ifdef NEW_R_ALLOC + r_use_p=&r_reg_uses[reg]; +#else + if (is_d_register (reg)) + r_use_p=&d_reg_uses[d_reg_num (reg)]; + else + r_use_p=&a_reg_uses[a_reg_num (reg)]; +#endif + parameter->parameter_data.reg.u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); + r_use_p->instruction_n=instruction_number; + r_use_p->value_used=1; + break; + case P_F_REGISTER: + reg_num=parameter->parameter_data.reg.r; + + r_use_p=&f_reg_uses[reg_num]; + + parameter->parameter_data.reg.u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); + if (reg_num<8) + r_use_p->instruction_n=instruction_number; + else + r_use_p->instruction_n=0; + r_use_p->value_used=0; + break; + case P_INDEXED: + { + struct index_registers *index_registers; + + index_registers=parameter->parameter_data.ir; + +#ifdef MORE_PARAMETER_REGISTERS + if ((unsigned)(num_to_d_reg (index_registers->a_reg.r)-N_DATA_PARAMETER_REGISTERS)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + index_registers->a_reg.r = a_reg_num ((N_ADDRESS_PARAMETER_REGISTERS-1)-(num_to_d_reg (index_registers->a_reg.r)-N_DATA_PARAMETER_REGISTERS)); + + if ((unsigned)(num_to_d_reg (index_registers->d_reg.r)-N_DATA_PARAMETER_REGISTERS)<(unsigned)N_ADDRESS_PARAMETER_REGISTERS) + index_registers->d_reg.r = a_reg_num ((N_ADDRESS_PARAMETER_REGISTERS-1)-(num_to_d_reg (index_registers->d_reg.r)-N_DATA_PARAMETER_REGISTERS)); +#endif + +#ifdef NEW_R_ALLOC + r_use_p=&r_reg_uses[index_registers->a_reg.r]; +#else + r_use_p=&a_reg_uses[a_reg_num (index_registers->a_reg.r)]; +#endif + index_registers->a_reg.u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); + r_use_p->instruction_n=instruction_number; + r_use_p->value_used=1; +#ifdef NEW_R_ALLOC + r_use_p=&r_reg_uses[index_registers->d_reg.r]; +#else + r_use_p=&d_reg_uses[d_reg_num (index_registers->d_reg.r)]; +#endif + index_registers->d_reg.u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); + r_use_p->instruction_n=instruction_number; + r_use_p->value_used=1; + } + } +} + +#ifdef I486_USE_SCRATCH_REGISTER +struct scratch_register_next_uses { + unsigned int scratch_register_u; + struct scratch_register_next_uses *scratch_register_next; +}; + +static struct scratch_register_next_uses *scratch_register_next_uses,*scratch_register_free_list=NULL; + +static int allocate_scratch_register=1; + +static void define_scratch_register (void) +{ + struct register_use *r_use_p; + struct scratch_register_next_uses *scratch_register_next_use; + + if (scratch_register_free_list!=NULL){ + scratch_register_next_use=scratch_register_free_list; + scratch_register_free_list=scratch_register_next_use->scratch_register_next; + } else + scratch_register_next_use=(struct scratch_register_next_uses*)fast_memory_allocate (sizeof (struct scratch_register_next_uses)); + + scratch_register_next_use->scratch_register_next=scratch_register_next_uses; + scratch_register_next_uses=scratch_register_next_use; + + r_use_p=&r_reg_uses[-3]; + + scratch_register_next_use->scratch_register_u=(r_use_p->instruction_n<<1)+(r_use_p->value_used & 1); + + r_use_p->instruction_n=instruction_number; + r_use_p->value_used=0; +} +#endif + +static void store_next_uses (struct instruction *instruction) +{ + instruction_number=2; + while (instruction!=NULL){ + switch (instruction->instruction_icode){ + case IADD: case IAND: +#ifndef I486_USE_SCRATCH_REGISTER + case IASR: case ILSL: case ILSR: + case IDIV: + case ICMPW: +#endif + case IEOR: case IFADD: + case IFCMP: case IFDIV: case IFMUL: case IFREM: case IFSUB: + case IMUL: case IOR: case ISUB: case ICMP: + case IEXG: +IF_G_POWER (case ICMPLW:) +IF_G_SPARC (case IADDO: case ISUBO:) +#if defined (I486) && defined (FP_STACK_OPTIMIZATIONS) + case IFEXG: +#endif + use_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[0]); + break; +#ifdef I486_USE_SCRATCH_REGISTER + case IASR: case ILSL: case ILSR: + if (instruction->instruction_parameters[0].parameter_type!=P_IMMEDIATE) + define_scratch_register(); + use_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[0]); + break; + case ICMPW: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT || + instruction->instruction_parameters[1].parameter_type==P_INDIRECT) + define_scratch_register(); + use_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[0]); + break; + case IDIV: case IMOD: + define_scratch_register(); + use_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[0]); + break; + case IMOVE: + if ((instruction->instruction_parameters[0].parameter_type==P_INDIRECT || + instruction->instruction_parameters[0].parameter_type==P_INDEXED) && + (instruction->instruction_parameters[1].parameter_type==P_INDIRECT || + instruction->instruction_parameters[1].parameter_type==P_INDEXED)) + define_scratch_register(); + define_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[0]); + break; +#endif +#ifdef I486 + case IDIVI: case IREMI: +# ifdef I486_USE_SCRATCH_REGISTER + define_scratch_register(); +# endif + use_parameter (&instruction->instruction_parameters[1]); + define_parameter (&instruction->instruction_parameters[2]); + break; +#endif + case IFMOVE: case IFMOVEL: case ILEA: +#ifndef I486_USE_SCRATCH_REGISTER + case IMOVE: +#endif + case IMOVEB: case IMOVEW: + case IFCOS: case IFSIN: case IFTAN: +#ifdef M68000 + case IFACOS: case IFASIN: case IFATAN: case IFEXP: case IFLN: case IFLOG10: +#endif + case IFNEG: +#if !defined (G_POWER) + case IFSQRT: +#endif +IF_G_SPARC (case IFMOVEHI: case IFMOVELO:) +IF_G_RISC (case IADDI: case ILSLI:) + define_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[0]); + break; + case IFTST: case ITST: case IEXT: +#if defined (M68000) || defined (G_POWER) + case IEXTB: +#endif + /* case IJMP: case IJSR: */ + use_parameter (&instruction->instruction_parameters[0]); + break; + case IFSEQ: case IFSGE: case IFSGT: case IFSLE: case IFSLT: case IFSNE: + case ISEQ: case ISGE: case ISGT: case ISLE: case ISLT: case ISNE: + case ISO: case ISNO: +#ifdef I486_USE_SCRATCH_REGISTER + define_scratch_register(); +#endif + define_parameter (&instruction->instruction_parameters[0]); + break; +#ifndef I486_USE_SCRATCH_REGISTER + case IMOD: +# if defined (I486) || defined (G_POWER) + use_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[0]); + break; +# else + define_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[2]); + use_parameter (&instruction->instruction_parameters[0]); + break; +# endif +#endif +#ifdef M68000 + case IMOVEM: + { + int n=instruction->instruction_arity; + while (n>1){ + --n; + define_parameter (&instruction->instruction_parameters[n]); + } + use_parameter (&instruction->instruction_parameters[0]); + break; + } + case IBMOVE: + use_parameter (&instruction->instruction_parameters[2]); + use_parameter (&instruction->instruction_parameters[1]); + use_parameter (&instruction->instruction_parameters[0]); + break; +#endif +#ifdef I486_USE_SCRATCH_REGISTER + case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE: + define_scratch_register(); + break; +#endif + /* + case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE: + case IRTS: + break; + */ + case IBEQ: case IBGE: case IBGT: case IBLE: case IBLT: case IBNE: + case IBHS: + case IBO: case IBNO: + break; + default: + internal_error_in_function ("store_next_uses"); + + } + instruction=instruction->instruction_prev; + ++instruction_number; + } +} + +static void initialize_register_allocation() +{ + int n; + + for (n=0; n<8; ++n){ +#ifdef NEW_R_ALLOC + if (r_reg_uses[n].value_used){ + r_reg_alloc[n+N_REAL_A_REGISTERS].reg=n; + r_reg_uses[n].reg=n+N_REAL_A_REGISTERS; + r_reg_alloc[n+N_REAL_A_REGISTERS].value_used=1; + r_reg_alloc[n+N_REAL_A_REGISTERS].instruction_n=r_reg_uses[n].instruction_n; + } else { + r_reg_alloc[n+N_REAL_A_REGISTERS].reg=-32768; + r_reg_alloc[n+N_REAL_A_REGISTERS].instruction_n=0; + } + + if (r_reg_uses[-(n+1)].value_used){ + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].reg=-(n+1); + r_reg_uses[-(n+1)].reg=(N_REAL_A_REGISTERS-1)-n; + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].value_used=1; + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].instruction_n=r_reg_uses[-(n+1)].instruction_n; + } else { + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].reg=-32768; + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].instruction_n=0; + } +#else + if (a_reg_uses[n].value_used){ + a_reg_alloc[n].reg=n; + a_reg_uses[n].reg=n; + a_reg_alloc[n].value_used=1; + a_reg_alloc[n].instruction_n=a_reg_uses[n].instruction_n; + } else { + a_reg_alloc[n].reg=-1; + a_reg_alloc[n].instruction_n=0; + } + + if (d_reg_uses[n].value_used){ + d_reg_alloc[n].reg=n; + d_reg_uses[n].reg=n; + d_reg_alloc[n].value_used=1; + d_reg_alloc[n].instruction_n=d_reg_uses[n].instruction_n; + } else { + d_reg_alloc[n].reg=-1; + d_reg_alloc[n].instruction_n=0; + } +#endif + if (f_reg_uses[n].value_used){ + f_reg_alloc[n].reg=n; + f_reg_uses[n].reg=n; + f_reg_alloc[n].value_used=1; + f_reg_alloc[n].instruction_n=f_reg_uses[n].instruction_n; + } else { +#ifdef NEW_R_ALLOC + f_reg_alloc[n].reg=-32768; +#else + f_reg_alloc[n].reg=-1; +#endif + f_reg_alloc[n].instruction_n=0; + } + } + +#ifdef NEW_R_ALLOC + for (n=8; n<N_REAL_A_REGISTERS; ++n){ + if (r_reg_uses[-(n+1)].value_used){ + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].reg=-(n+1); + r_reg_uses[-(n+1)].reg=(N_REAL_A_REGISTERS-1)-n; + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].value_used=1; + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].instruction_n=r_reg_uses[-(n+1)].instruction_n; + } else { + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].reg=-32768; + r_reg_alloc[(N_REAL_A_REGISTERS-1)-n].instruction_n=0; + } + } +#endif + +#if defined (NEW_R_ALLOC) && (defined (sparc) || defined (G_POWER)) + for (n=8; n<15; ++n){ + f_reg_alloc[n].reg=-32768; + f_reg_alloc[n].instruction_n=0; + } +#endif +} + +enum { USE, USE_DEF, DEF }; + +enum { A_REGISTER, D_REGISTER, F_REGISTER }; + +int do_not_alter_condition_codes; /* TRUE if it is not allowed to alter condition codes */ + +static struct instruction *previous_instruction; +static struct basic_block *current_block; + +static struct instruction *insert_instruction (int instruction_code,int arity,int arg_size) +{ + struct instruction *instruction,*next_instruction; + + instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+arg_size); + instruction->instruction_icode=instruction_code; + instruction->instruction_arity=arity; + + if (previous_instruction==NULL){ + next_instruction=current_block->block_instructions; + current_block->block_instructions=instruction; + } else { + next_instruction=previous_instruction->instruction_next; + previous_instruction->instruction_next=instruction; + } + instruction->instruction_next=next_instruction; + instruction->instruction_prev=previous_instruction; + if (next_instruction!=NULL) + next_instruction->instruction_prev=instruction; + + previous_instruction=instruction; + + return instruction; +} + +#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 + +static void insert_load (int offset,int register_n,int register_flag) +{ + struct instruction *instruction; + + switch (register_flag){ + case D_REGISTER: +#ifdef M68000 + if (do_not_alter_condition_codes) + instruction=insert_instruction (IMOVEM,2,2*sizeof (struct parameter)); + else +#endif + instruction=insert_instruction (IMOVE,2,2*sizeof (struct parameter)); + instruction->instruction_parameters[1].parameter_type=P_REGISTER; +#ifdef NEW_R_ALLOC + instruction->instruction_parameters[1].parameter_data.i=register_n-N_REAL_A_REGISTERS; +#else + instruction->instruction_parameters[1].parameter_data.i=num_to_d_reg (register_n); +#endif + break; +#ifndef NEW_R_ALLOC + case A_REGISTER: + instruction=insert_instruction (IMOVE,2,2*sizeof (struct parameter)); + + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_data.i=num_to_a_reg (register_n); + break; +#endif + case F_REGISTER: + instruction=insert_instruction (IFMOVE,2,2*sizeof (struct parameter)); + + set_float_register_parameter (instruction->instruction_parameters[1],register_n); + break; + default: + internal_error_in_function ("insert_load"); + return; + } + + instruction->instruction_parameters[0].parameter_type=P_INDIRECT; + instruction->instruction_parameters[0].parameter_offset=offset; + instruction->instruction_parameters[0].parameter_data.i=B_STACK_POINTER; +} + +static void insert_store (int register_n,int offset,int register_flag) +{ + struct instruction *instruction; + + switch (register_flag){ + case D_REGISTER: +#ifdef M68000 + if (do_not_alter_condition_codes) + instruction=insert_instruction (IMOVEM,2,2*sizeof (struct parameter)); + else +#endif + instruction=insert_instruction (IMOVE,2,2*sizeof (struct parameter)); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; +#ifdef NEW_R_ALLOC + instruction->instruction_parameters[0].parameter_data.i=register_n-N_REAL_A_REGISTERS; +#else + instruction->instruction_parameters[0].parameter_data.i=num_to_d_reg (register_n); +#endif + break; +#ifndef NEW_R_ALLOC + case A_REGISTER: +# ifdef M68000 + if (do_not_alter_condition_codes) + instruction=insert_instruction (IMOVEM,2,2*sizeof (struct parameter)); + else +# endif + instruction=insert_instruction (IMOVE,2,2*sizeof (struct parameter)); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[0].parameter_data.i=num_to_a_reg (register_n); + break; +#endif + case F_REGISTER: + instruction=insert_instruction (IFMOVE,2,2*sizeof (struct parameter)); + + set_float_register_parameter (instruction->instruction_parameters[0],register_n); + break; + default: + internal_error_in_function ("insert_store"); + return; + } + + instruction->instruction_parameters[1].parameter_type=P_INDIRECT; + instruction->instruction_parameters[1].parameter_offset=offset; + instruction->instruction_parameters[1].parameter_data.i=B_STACK_POINTER; +} + +static void insert_move (int reg_n_1,int reg_n_2,int register_flag) +{ + struct instruction *instruction; + + switch (register_flag){ + case D_REGISTER: +#ifdef M68000 + if (do_not_alter_condition_codes) + instruction=insert_instruction (IEXG,2,2*sizeof (struct parameter)); + else +#endif + instruction=insert_instruction (IMOVE,2,2*sizeof (struct parameter)); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_type=P_REGISTER; +#ifdef NEW_R_ALLOC + instruction->instruction_parameters[0].parameter_data.i=reg_n_1-N_REAL_A_REGISTERS; + instruction->instruction_parameters[1].parameter_data.i=reg_n_2-N_REAL_A_REGISTERS; +#else + instruction->instruction_parameters[0].parameter_data.i=num_to_d_reg (reg_n_1); + instruction->instruction_parameters[1].parameter_data.i=num_to_d_reg (reg_n_2); +#endif + break; +#ifndef NEW_R_ALLOC + case A_REGISTER: + instruction=insert_instruction (IMOVE,2,2*sizeof (struct parameter)); + + instruction->instruction_parameters[0].parameter_type=P_REGISTER; + instruction->instruction_parameters[1].parameter_type=P_REGISTER; + + instruction->instruction_parameters[0].parameter_data.i=num_to_a_reg (reg_n_1); + instruction->instruction_parameters[1].parameter_data.i=num_to_a_reg (reg_n_2); + break; +#endif + case F_REGISTER: + instruction=insert_instruction (IFMOVE,2,2*sizeof (struct parameter)); + + set_float_register_parameter (instruction->instruction_parameters[0],reg_n_1); + set_float_register_parameter (instruction->instruction_parameters[1],reg_n_2); + } +} + +#ifdef NEW_R_ALLOC +#define REAL_D0 (N_REAL_A_REGISTERS+0) +#define REAL_D1 (N_REAL_A_REGISTERS+1) +#define REAL_D2 (N_REAL_A_REGISTERS+2) +#define REAL_D3 (N_REAL_A_REGISTERS+3) +#define REAL_D4 (N_REAL_A_REGISTERS+4) +#define REAL_D5 (N_REAL_A_REGISTERS+5) +#define REAL_D6 (N_REAL_A_REGISTERS+6) +#define REAL_D7 (N_REAL_A_REGISTERS+7) +#define REAL_A0 (N_REAL_A_REGISTERS-1) +#define REAL_A1 (N_REAL_A_REGISTERS-2) +#define REAL_A2 (N_REAL_A_REGISTERS-3) +#define REAL_A3 (N_REAL_A_REGISTERS-4) +#define REAL_A4 (N_REAL_A_REGISTERS-5) +#define REAL_A5 (N_REAL_A_REGISTERS-6) +#define REAL_A6 (N_REAL_A_REGISTERS-7) +#define REAL_A7 (N_REAL_A_REGISTERS-8) +#endif + +static int find_register (int reg_n,register struct register_allocation *reg_alloc, + int register_flag) +{ + int real_reg_n; +#ifdef NEW_R_ALLOC + if ((unsigned)(reg_n+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS) + if (register_flag==F_REGISTER) + real_reg_n=reg_n; + else + real_reg_n=reg_n+N_REAL_A_REGISTERS; +#else + if (reg_n<8) + real_reg_n=reg_n; +#endif + else { + register int i; + +#ifdef NEW_R_ALLOC + if (register_flag!=F_REGISTER){ + real_reg_n=REAL_D0; + i=reg_alloc[REAL_D0].instruction_n; + + if (reg_alloc[REAL_D1].instruction_n<i){ + real_reg_n=REAL_D1; + i=reg_alloc[REAL_D1].instruction_n; + } +#ifndef I486 + if (reg_alloc[REAL_D2].instruction_n<i){ + real_reg_n=REAL_D2; + i=reg_alloc[REAL_D2].instruction_n; + } + if (reg_alloc[REAL_D3].instruction_n<i){ + real_reg_n=REAL_D3; + i=reg_alloc[REAL_D3].instruction_n; + } + if (reg_alloc[REAL_D4].instruction_n<i){ + real_reg_n=REAL_D4; + i=reg_alloc[REAL_D4].instruction_n; + } + if (reg_alloc[REAL_D5].instruction_n<i){ + real_reg_n=REAL_D5; + i=reg_alloc[REAL_D5].instruction_n; + } + if (reg_alloc[REAL_D6].instruction_n<i){ + real_reg_n=REAL_D6; + i=reg_alloc[REAL_D6].instruction_n; + } + if (reg_alloc[REAL_D7].instruction_n<i){ + real_reg_n=REAL_D7; + i=reg_alloc[REAL_D7].instruction_n; + } +#endif + if (reg_alloc[REAL_A0].instruction_n<i){ + real_reg_n=REAL_A0; + i=reg_alloc[REAL_A0].instruction_n; + } + if (reg_alloc[REAL_A1].instruction_n<i){ + real_reg_n=REAL_A1; + i=reg_alloc[REAL_A1].instruction_n; + } +#if !defined (I486) || defined (I486_USE_SCRATCH_REGISTER) + if (reg_alloc[REAL_A2].instruction_n<i +# if defined (I486_USE_SCRATCH_REGISTER) + && allocate_scratch_register +# endif + ){ + real_reg_n=REAL_A2; + i=reg_alloc[REAL_A2].instruction_n; + } +#endif + if (reg_alloc[REAL_A3].instruction_n<i){ + real_reg_n=REAL_A3; + i=reg_alloc[REAL_A3].instruction_n; + } +#ifndef POWER_PC_A_STACK_OPTIMIZE + if (reg_alloc[REAL_A4].instruction_n<i){ + real_reg_n=REAL_A4; + i=reg_alloc[REAL_A4].instruction_n; + } +#endif +#if ! (defined (I486) || defined (G_POWER)) + if (reg_alloc[REAL_A6].instruction_n<i){ + real_reg_n=REAL_A6; + i=reg_alloc[REAL_A6].instruction_n; + } +#endif + } else { + real_reg_n=0; + i=reg_alloc[0].instruction_n; + + if (reg_alloc[1].instruction_n<i){ + real_reg_n=1; + i=reg_alloc[1].instruction_n; + } + if (reg_alloc[2].instruction_n<i){ + real_reg_n=2; + i=reg_alloc[2].instruction_n; + } + if (reg_alloc[3].instruction_n<i){ + real_reg_n=3; + i=reg_alloc[3].instruction_n; + } + if (reg_alloc[4].instruction_n<i){ + real_reg_n=4; + i=reg_alloc[4].instruction_n; + } + if (reg_alloc[5].instruction_n<i){ + real_reg_n=5; + i=reg_alloc[5].instruction_n; + } + if (reg_alloc[6].instruction_n<i){ + real_reg_n=6; + i=reg_alloc[6].instruction_n; + } +# ifndef I486 + if (reg_alloc[7].instruction_n<i){ + real_reg_n=7; + i=reg_alloc[7].instruction_n; + } +# if defined (sparc) || defined (G_POWER) + if (reg_alloc[8].instruction_n<i){ + real_reg_n=8; + i=reg_alloc[8].instruction_n; + } + if (reg_alloc[9].instruction_n<i){ + real_reg_n=9; + i=reg_alloc[9].instruction_n; + } + if (reg_alloc[10].instruction_n<i){ + real_reg_n=10; + i=reg_alloc[10].instruction_n; + } + if (reg_alloc[11].instruction_n<i){ + real_reg_n=11; + i=reg_alloc[11].instruction_n; + } + if (reg_alloc[12].instruction_n<i){ + real_reg_n=12; + i=reg_alloc[12].instruction_n; + } + if (reg_alloc[13].instruction_n<i){ + real_reg_n=13; + i=reg_alloc[13].instruction_n; + } + if (reg_alloc[14].instruction_n<i){ + real_reg_n=14; + i=reg_alloc[14].instruction_n; + } +# endif +# endif + } +#else + real_reg_n=0; + i=reg_alloc[real_reg_n].instruction_n; + + if (reg_alloc[1].instruction_n<i){ + real_reg_n=1; + i=reg_alloc[1].instruction_n; + } +# ifdef I486 + if (register_flag!=D_REGISTER){ + if (register_flag==F_REGISTER) + if (reg_alloc[2].instruction_n<i){ + real_reg_n=2; + i=reg_alloc[2].instruction_n; + } + if (reg_alloc[3].instruction_n<i){ + real_reg_n=3; + i=reg_alloc[3].instruction_n; + } + if (reg_alloc[4].instruction_n<i){ + real_reg_n=4; + i=reg_alloc[4].instruction_n; + } + if (register_flag==F_REGISTER){ + if (reg_alloc[5].instruction_n<i){ + real_reg_n=5; + i=reg_alloc[5].instruction_n; + } + if (reg_alloc[6].instruction_n<i){ + real_reg_n=6; + i=reg_alloc[6].instruction_n; + } + } + } +# else + if (reg_alloc[2].instruction_n<i){ + real_reg_n=2; + i=reg_alloc[2].instruction_n; + } + if (reg_alloc[3].instruction_n<i){ + real_reg_n=3; + i=reg_alloc[3].instruction_n; + } + if (register_flag!=A_REGISTER){ + if (reg_alloc[4].instruction_n<i){ + real_reg_n=4; + i=reg_alloc[4].instruction_n; + } + if (reg_alloc[5].instruction_n<i){ + real_reg_n=5; + i=reg_alloc[5].instruction_n; + } + } + if (reg_alloc[6].instruction_n<i){ + real_reg_n=6; + i=reg_alloc[6].instruction_n; + } + if (register_flag!=A_REGISTER) + if (reg_alloc[7].instruction_n<i){ + real_reg_n=7; + i=reg_alloc[7].instruction_n; + } +# endif +#endif + } + + return real_reg_n; +} + +static int find_non_reg_2_register (int reg_n,int avoid_reg_n, + struct register_allocation *reg_alloc,int register_flag) +{ + int real_reg_n; + +#ifdef NEW_R_ALLOC + if ((unsigned)(reg_n+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS) + if (register_flag==F_REGISTER) + real_reg_n=reg_n; + else + real_reg_n=reg_n+N_REAL_A_REGISTERS; +#else + if (reg_n<8) + real_reg_n=reg_n; +#endif + else { + register int i; + + real_reg_n=-1; + i=32767; + +#ifdef NEW_R_ALLOC + if (register_flag!=F_REGISTER){ + if (reg_alloc[REAL_D0].instruction_n<i && avoid_reg_n!=REAL_D0){ + real_reg_n=REAL_D0; + i=reg_alloc[REAL_D0].instruction_n; + } + if (reg_alloc[REAL_D1].instruction_n<i && avoid_reg_n!=REAL_D1){ + real_reg_n=REAL_D1; + i=reg_alloc[REAL_D1].instruction_n; + } +#ifndef I486 + if (reg_alloc[REAL_D2].instruction_n<i && avoid_reg_n!=REAL_D2){ + real_reg_n=REAL_D2; + i=reg_alloc[REAL_D2].instruction_n; + } + if (reg_alloc[REAL_D3].instruction_n<i && avoid_reg_n!=REAL_D3){ + real_reg_n=REAL_D3; + i=reg_alloc[REAL_D3].instruction_n; + } + if (reg_alloc[REAL_D4].instruction_n<i && avoid_reg_n!=REAL_D4){ + real_reg_n=REAL_D4; + i=reg_alloc[REAL_D4].instruction_n; + } + if (reg_alloc[REAL_D5].instruction_n<i && avoid_reg_n!=REAL_D5){ + real_reg_n=REAL_D5; + i=reg_alloc[REAL_D5].instruction_n; + } + if (reg_alloc[REAL_D6].instruction_n<i && avoid_reg_n!=REAL_D6){ + real_reg_n=REAL_D6; + i=reg_alloc[REAL_D6].instruction_n; + } + if (reg_alloc[REAL_D7].instruction_n<i && avoid_reg_n!=REAL_D7){ + real_reg_n=REAL_D7; + i=reg_alloc[REAL_D7].instruction_n; + } +#endif + if (reg_alloc[REAL_A0].instruction_n<i && avoid_reg_n!=REAL_A0){ + real_reg_n=REAL_A0; + i=reg_alloc[REAL_A0].instruction_n; + } + if (reg_alloc[REAL_A1].instruction_n<i && avoid_reg_n!=REAL_A1){ + real_reg_n=REAL_A1; + i=reg_alloc[REAL_A1].instruction_n; + } +#if !defined (I486) || defined (I486_USE_SCRATCH_REGISTER) + if (reg_alloc[REAL_A2].instruction_n<i && avoid_reg_n!=REAL_A2 +# if defined (I486_USE_SCRATCH_REGISTER) + && allocate_scratch_register +# endif + ){ + real_reg_n=REAL_A2; + i=reg_alloc[REAL_A2].instruction_n; + } +#endif + if (reg_alloc[REAL_A3].instruction_n<i && avoid_reg_n!=REAL_A3){ + real_reg_n=REAL_A3; + i=reg_alloc[REAL_A3].instruction_n; + } +#ifndef POWER_PC_A_STACK_OPTIMIZE + if (reg_alloc[REAL_A4].instruction_n<i && avoid_reg_n!=REAL_A4){ + real_reg_n=REAL_A4; + i=reg_alloc[REAL_A4].instruction_n; + } +#endif +#if ! (defined (I486) || defined (G_POWER)) + if (reg_alloc[REAL_A6].instruction_n<i && avoid_reg_n!=REAL_A6){ + real_reg_n=REAL_A6; + i=reg_alloc[REAL_A6].instruction_n; + } +#endif + } else { + if (reg_alloc[0].instruction_n<i && avoid_reg_n!=0){ + real_reg_n=0; + i=reg_alloc[0].instruction_n; + } + if (reg_alloc[1].instruction_n<i && avoid_reg_n!=1){ + real_reg_n=1; + i=reg_alloc[1].instruction_n; + } + if (reg_alloc[2].instruction_n<i && avoid_reg_n!=2){ + real_reg_n=2; + i=reg_alloc[2].instruction_n; + } + if (reg_alloc[3].instruction_n<i && avoid_reg_n!=3){ + real_reg_n=3; + i=reg_alloc[3].instruction_n; + } + if (reg_alloc[4].instruction_n<i && avoid_reg_n!=4){ + real_reg_n=4; + i=reg_alloc[4].instruction_n; + } + if (reg_alloc[5].instruction_n<i && avoid_reg_n!=5){ + real_reg_n=5; + i=reg_alloc[5].instruction_n; + } + if (reg_alloc[6].instruction_n<i && avoid_reg_n!=6){ + real_reg_n=6; + i=reg_alloc[6].instruction_n; + } +# ifndef I486 + if (reg_alloc[7].instruction_n<i && avoid_reg_n!=7){ + real_reg_n=7; + i=reg_alloc[7].instruction_n; + } +# if defined (sparc) || defined (G_POWER) + if (reg_alloc[8].instruction_n<i && avoid_reg_n!=8){ + real_reg_n=8; + i=reg_alloc[8].instruction_n; + } + if (reg_alloc[9].instruction_n<i && avoid_reg_n!=9){ + real_reg_n=9; + i=reg_alloc[9].instruction_n; + } + if (reg_alloc[10].instruction_n<i && avoid_reg_n!=10){ + real_reg_n=10; + i=reg_alloc[10].instruction_n; + } + if (reg_alloc[11].instruction_n<i && avoid_reg_n!=11){ + real_reg_n=11; + i=reg_alloc[11].instruction_n; + } + if (reg_alloc[12].instruction_n<i && avoid_reg_n!=12){ + real_reg_n=12; + i=reg_alloc[12].instruction_n; + } + if (reg_alloc[13].instruction_n<i && avoid_reg_n!=13){ + real_reg_n=13; + i=reg_alloc[13].instruction_n; + } + if (reg_alloc[14].instruction_n<i && avoid_reg_n!=14){ + real_reg_n=14; + i=reg_alloc[14].instruction_n; + } +# endif +# endif + } +#else + if (reg_alloc[0].instruction_n<i && avoid_reg_n!=0){ + real_reg_n=0; + i=reg_alloc[0].instruction_n; + } + if (reg_alloc[1].instruction_n<i && avoid_reg_n!=1){ + real_reg_n=1; + i=reg_alloc[1].instruction_n; + } +# ifdef I486 + if (register_flag!=D_REGISTER){ + if (register_flag==F_REGISTER) + if (reg_alloc[2].instruction_n<i && avoid_reg_n!=2){ + real_reg_n=2; + i=reg_alloc[2].instruction_n; + } + if (reg_alloc[3].instruction_n<i && avoid_reg_n!=3){ + real_reg_n=3; + i=reg_alloc[3].instruction_n; + } + if (reg_alloc[4].instruction_n<i && avoid_reg_n!=4){ + real_reg_n=4; + i=reg_alloc[4].instruction_n; + } + if (register_flag==F_REGISTER){ + if (reg_alloc[5].instruction_n<i && avoid_reg_n!=5){ + real_reg_n=5; + i=reg_alloc[5].instruction_n; + } + if (reg_alloc[6].instruction_n<i && avoid_reg_n!=6){ + real_reg_n=6; + i=reg_alloc[6].instruction_n; + } + } + } +# else + if (reg_alloc[2].instruction_n<i && avoid_reg_n!=2){ + real_reg_n=2; + i=reg_alloc[2].instruction_n; + } + if (reg_alloc[3].instruction_n<i && avoid_reg_n!=3){ + real_reg_n=3; + i=reg_alloc[3].instruction_n; + } + if (register_flag!=A_REGISTER){ + if (reg_alloc[4].instruction_n<i && avoid_reg_n!=4){ + real_reg_n=4; + i=reg_alloc[4].instruction_n; + } + if (reg_alloc[5].instruction_n<i && avoid_reg_n!=5){ + real_reg_n=5; + i=reg_alloc[5].instruction_n; + } + } + if (reg_alloc[6].instruction_n<i && avoid_reg_n!=6){ + real_reg_n=6; + i=reg_alloc[6].instruction_n; + } + if (register_flag!=A_REGISTER) + if (reg_alloc[7].instruction_n<i && avoid_reg_n!=7){ + real_reg_n=7; + i=reg_alloc[7].instruction_n; + } +# endif +#endif + if (real_reg_n<0) + internal_error_in_function ("find_non_reg_2_register"); + } + + return real_reg_n; +} + +#if defined (M68000) || defined (NEW_R_ALLOC) +static int find_reg_not_in_set + (int reg_n,unsigned int avoid_reg_set,struct register_allocation *reg_alloc,int register_flag) +{ + int real_reg_n; + +# ifdef NEW_R_ALLOC + if ((unsigned)(reg_n+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS) + if (register_flag==F_REGISTER) + real_reg_n=reg_n; + else + real_reg_n=reg_n+N_REAL_A_REGISTERS; +# else + if (reg_n<8) + real_reg_n=reg_n; +# endif + else { + int i; + + real_reg_n=-1; + i=32767; + +# ifdef NEW_R_ALLOC + if (register_flag!=F_REGISTER){ + if (reg_alloc[REAL_D0].instruction_n<i && !(avoid_reg_set & (1<<REAL_D0))){ + real_reg_n=REAL_D0; + i=reg_alloc[REAL_D0].instruction_n; + } + if (reg_alloc[REAL_D1].instruction_n<i && !(avoid_reg_set & (1<<REAL_D1))){ + real_reg_n=REAL_D1; + i=reg_alloc[REAL_D1].instruction_n; + } +# ifndef I486 + if (reg_alloc[REAL_D2].instruction_n<i && !(avoid_reg_set & (1<<REAL_D2))){ + real_reg_n=REAL_D2; + i=reg_alloc[REAL_D2].instruction_n; + } + if (reg_alloc[REAL_D3].instruction_n<i && !(avoid_reg_set & (1<<REAL_D3))){ + real_reg_n=REAL_D3; + i=reg_alloc[REAL_D3].instruction_n; + } + if (reg_alloc[REAL_D4].instruction_n<i && !(avoid_reg_set & (1<<REAL_D4))){ + real_reg_n=REAL_D4; + i=reg_alloc[REAL_D4].instruction_n; + } + if (reg_alloc[REAL_D5].instruction_n<i && !(avoid_reg_set & (1<<REAL_D5))){ + real_reg_n=REAL_D5; + i=reg_alloc[REAL_D5].instruction_n; + } + if (reg_alloc[REAL_D6].instruction_n<i && !(avoid_reg_set & (1<<REAL_D6))){ + real_reg_n=REAL_D6; + i=reg_alloc[REAL_D6].instruction_n; + } + if (reg_alloc[REAL_D7].instruction_n<i && !(avoid_reg_set & (1<<REAL_D7))){ + real_reg_n=REAL_D7; + i=reg_alloc[REAL_D7].instruction_n; + } +# endif + if (reg_alloc[REAL_A0].instruction_n<i && !(avoid_reg_set & (1<<REAL_A0))){ + real_reg_n=REAL_A0; + i=reg_alloc[REAL_A0].instruction_n; + } + if (reg_alloc[REAL_A1].instruction_n<i && !(avoid_reg_set & (1<<REAL_A1))){ + real_reg_n=REAL_A1; + i=reg_alloc[REAL_A1].instruction_n; + } +# if !defined (I486) || defined (I486_USE_SCRATCH_REGISTER) + if (reg_alloc[REAL_A2].instruction_n<i && !(avoid_reg_set & (1<<REAL_A2)) +# if defined (I486_USE_SCRATCH_REGISTER) + && allocate_scratch_register +# endif + ){ + real_reg_n=REAL_A2; + i=reg_alloc[REAL_A2].instruction_n; + } +# endif + if (reg_alloc[REAL_A3].instruction_n<i && !(avoid_reg_set & (1<<REAL_A3))){ + real_reg_n=REAL_A3; + i=reg_alloc[REAL_A3].instruction_n; + } +#ifndef POWER_PC_A_STACK_OPTIMIZE + if (reg_alloc[REAL_A4].instruction_n<i && !(avoid_reg_set & (1<<REAL_A4))){ + real_reg_n=REAL_A4; + i=reg_alloc[REAL_A4].instruction_n; + } +#endif +#if ! (defined (I486) || defined (G_POWER)) + if (reg_alloc[REAL_A6].instruction_n<i && !(avoid_reg_set & (1<<REAL_A6))){ + real_reg_n=REAL_A6; + i=reg_alloc[REAL_A6].instruction_n; + } +# endif + } else { + if (reg_alloc[0].instruction_n<i && !(avoid_reg_set & 1)){ + real_reg_n=0; + i=reg_alloc[0].instruction_n; + } + if (reg_alloc[1].instruction_n<i && !(avoid_reg_set & 2)){ + real_reg_n=1; + i=reg_alloc[1].instruction_n; + } + if (reg_alloc[2].instruction_n<i && !(avoid_reg_set & 4)){ + real_reg_n=2; + i=reg_alloc[2].instruction_n; + } + if (reg_alloc[3].instruction_n<i && !(avoid_reg_set & 8)){ + real_reg_n=3; + i=reg_alloc[3].instruction_n; + } + if (reg_alloc[4].instruction_n<i && !(avoid_reg_set & 16)){ + real_reg_n=4; + i=reg_alloc[4].instruction_n; + } + if (reg_alloc[5].instruction_n<i && !(avoid_reg_set & 32)){ + real_reg_n=5; + i=reg_alloc[5].instruction_n; + } + if (reg_alloc[6].instruction_n<i && !(avoid_reg_set & 64)){ + real_reg_n=6; + i=reg_alloc[6].instruction_n; + } +# ifndef I486 + if (reg_alloc[7].instruction_n<i && !(avoid_reg_set & 128)){ + real_reg_n=7; + i=reg_alloc[7].instruction_n; + } +# if defined (sparc) || defined (G_POWER) + if (reg_alloc[8].instruction_n<i && !(avoid_reg_set & 256)){ + real_reg_n=8; + i=reg_alloc[8].instruction_n; + } + if (reg_alloc[9].instruction_n<i && !(avoid_reg_set & 512)){ + real_reg_n=9; + i=reg_alloc[9].instruction_n; + } + if (reg_alloc[10].instruction_n<i && !(avoid_reg_set & 1024)){ + real_reg_n=10; + i=reg_alloc[10].instruction_n; + } + if (reg_alloc[11].instruction_n<i && !(avoid_reg_set & 2048)){ + real_reg_n=11; + i=reg_alloc[11].instruction_n; + } + if (reg_alloc[12].instruction_n<i && !(avoid_reg_set & 4096)){ + real_reg_n=12; + i=reg_alloc[12].instruction_n; + } + if (reg_alloc[13].instruction_n<i && !(avoid_reg_set & 8192)){ + real_reg_n=13; + i=reg_alloc[13].instruction_n; + } + if (reg_alloc[14].instruction_n<i && !(avoid_reg_set & 16384)){ + real_reg_n=14; + i=reg_alloc[14].instruction_n; + } +# endif +# endif + } +# else + if (reg_alloc[0].instruction_n<i && !(avoid_reg_set & 1)){ + real_reg_n=0; + i=reg_alloc[0].instruction_n; + } + if (reg_alloc[1].instruction_n<i && !(avoid_reg_set & 2)){ + real_reg_n=1; + i=reg_alloc[1].instruction_n; + } + if (reg_alloc[2].instruction_n<i && !(avoid_reg_set & 4)){ + real_reg_n=2; + i=reg_alloc[2].instruction_n; + } + if (reg_alloc[3].instruction_n<i && !(avoid_reg_set & 8)){ + real_reg_n=3; + i=reg_alloc[3].instruction_n; + } + if (register_flag!=A_REGISTER){ + if (reg_alloc[4].instruction_n<i && !(avoid_reg_set & 16)){ + real_reg_n=4; + i=reg_alloc[4].instruction_n; + } + if (reg_alloc[5].instruction_n<i && !(avoid_reg_set & 32)){ + real_reg_n=5; + i=reg_alloc[5].instruction_n; + } + } + if (reg_alloc[6].instruction_n<i && !(avoid_reg_set & 64)){ + real_reg_n=6; + i=reg_alloc[6].instruction_n; + } + if (register_flag!=A_REGISTER) + if (reg_alloc[7].instruction_n<i && !(avoid_reg_set & 128)){ + real_reg_n=7; + i=reg_alloc[7].instruction_n; + } +# endif + if (real_reg_n<0) + internal_error_in_function ("find_non_reg_2_register"); + } + + return real_reg_n; +} +#endif + +static int free_2_register ( int real_reg_n,struct register_use *reg_uses, + struct register_allocation *reg_alloc,int register_flag) +{ + int old_reg_n; + + old_reg_n=reg_alloc[real_reg_n].reg; +#ifdef NEW_R_ALLOC + if (old_reg_n!=-32768){ +#else + if (old_reg_n>=0){ +#endif + if (reg_alloc[real_reg_n].value_used){ + if (reg_uses[old_reg_n].offset==0){ + if (register_flag!=F_REGISTER) + local_data_offset-=4; + else + local_data_offset-=8; + + reg_uses[old_reg_n].offset=local_data_offset; + + insert_store (real_reg_n,local_data_offset,register_flag); + } else if (reg_alloc[real_reg_n].altered) + insert_store (real_reg_n,reg_uses[old_reg_n].offset,register_flag); + } + reg_uses[old_reg_n].reg=-1; + } +#ifdef NEW_R_ALLOC + reg_alloc[real_reg_n].reg=-32768; +#else + reg_alloc[real_reg_n].reg=-1; +#endif + + return real_reg_n; +} + +static void allocate_2_register ( int reg_n,int real_reg_n,int use_flag, + struct register_use *reg_uses, + struct register_allocation *reg_alloc,int register_flag) +{ + free_2_register (real_reg_n,reg_uses,reg_alloc,register_flag); + + reg_alloc[real_reg_n].reg=reg_n; + reg_uses[reg_n].reg=real_reg_n; + + if (use_flag!=DEF){ + if (reg_uses[reg_n].offset!=0){ + insert_load (reg_uses[reg_n].offset,real_reg_n,register_flag); + reg_alloc[real_reg_n].altered=0; + } + } +} + +static void move_2_register ( int reg_n,int real_reg_n,int use_flag, + struct register_use *reg_uses, + struct register_allocation *reg_alloc,int register_flag) +{ + int old_real_reg_n; + + old_real_reg_n=reg_uses[reg_n].reg; + + free_2_register (real_reg_n,reg_uses,reg_alloc,register_flag); + +#ifdef NEW_R_ALLOC + reg_alloc[old_real_reg_n].reg=-32768; +#else + reg_alloc[old_real_reg_n].reg=-1; +#endif + reg_alloc[old_real_reg_n].instruction_n=0; + + reg_alloc[real_reg_n].reg=reg_n; + reg_uses[reg_n].reg=real_reg_n; + + reg_alloc[real_reg_n].altered=reg_alloc[old_real_reg_n].altered; + + if (use_flag!=DEF) + insert_move (old_real_reg_n,real_reg_n,register_flag); +} + +#ifdef NEW_R_ALLOC +static void register_use (struct reg *reg_p,int use_flag) +{ + int reg,real_reg_n,instruction_n; + + reg=reg_p->r; + + real_reg_n=r_reg_uses[reg].reg; + if (real_reg_n<0){ + real_reg_n=find_register (reg,r_reg_alloc,D_REGISTER); + allocate_2_register (reg,real_reg_n,use_flag,r_reg_uses,r_reg_alloc,D_REGISTER); + } + + instruction_n=reg_p->u>>1; + r_reg_uses[reg].instruction_n=instruction_n; + + r_reg_alloc[real_reg_n].instruction_n = +#ifdef FIX_REG_USES_INDEX + (r_reg_uses[real_reg_n-N_REAL_A_REGISTERS].instruction_n>instruction_n) + ? r_reg_uses[real_reg_n-N_REAL_A_REGISTERS].instruction_n : instruction_n; +#else + (r_reg_uses[real_reg_n].instruction_n>instruction_n) + ? r_reg_uses[real_reg_n].instruction_n : instruction_n; +#endif + + r_reg_alloc[real_reg_n].value_used=reg_p->u & 1; + + if (use_flag!=USE) + r_reg_alloc[real_reg_n].altered=1; + + reg_p->r=real_reg_n-N_REAL_A_REGISTERS; +} +#else +static void register_use (struct reg *reg_p,int use_flag) +{ + int reg,reg_n,real_reg_n,instruction_n; + + reg=reg_p->r; + + if (is_d_register (reg)){ + reg_n=d_reg_num (reg); + + real_reg_n=d_reg_uses[reg_n].reg; + if (real_reg_n<0){ + real_reg_n=find_register (reg_n,d_reg_alloc,D_REGISTER); + allocate_2_register (reg_n,real_reg_n,use_flag,d_reg_uses,d_reg_alloc,D_REGISTER); + } + + instruction_n=reg_p->u>>1; + d_reg_uses[reg_n].instruction_n=instruction_n; + + d_reg_alloc[real_reg_n].instruction_n = + (d_reg_uses[real_reg_n].instruction_n>instruction_n) + ? d_reg_uses[real_reg_n].instruction_n : instruction_n; + + d_reg_alloc[real_reg_n].value_used=reg_p->u & 1; + + if (use_flag!=USE) + d_reg_alloc[real_reg_n].altered=1; + + reg_p->r=num_to_d_reg (real_reg_n); + } else { + reg_n=a_reg_num (reg); + + real_reg_n=a_reg_uses[reg_n].reg; + if (real_reg_n<0){ + real_reg_n=find_register (reg_n,a_reg_alloc,A_REGISTER); + allocate_2_register (reg_n,real_reg_n,use_flag,a_reg_uses,a_reg_alloc,A_REGISTER); + } + + instruction_n=reg_p->u>>1; + a_reg_uses[reg_n].instruction_n=instruction_n; + + a_reg_alloc[real_reg_n].instruction_n = + (a_reg_uses[real_reg_n].instruction_n>instruction_n) + ? a_reg_uses[real_reg_n].instruction_n : instruction_n; + + a_reg_alloc[real_reg_n].value_used=reg_p->u & 1; + + if (use_flag!=USE) + a_reg_alloc[real_reg_n].altered=1; + + reg_p->r=num_to_a_reg (real_reg_n); + } +} +#endif + +static void float_register_use (struct parameter *parameter,int use_flag) +{ + int reg_n,real_reg_n,instruction_n; + + reg_n=parameter->parameter_data.reg.r; + + real_reg_n=f_reg_uses[reg_n].reg; + if (real_reg_n<0){ + real_reg_n=find_register (reg_n,f_reg_alloc,F_REGISTER); + allocate_2_register (reg_n,real_reg_n,use_flag,f_reg_uses,f_reg_alloc,F_REGISTER); + } + + instruction_n=parameter->parameter_data.reg.u>>1; + f_reg_uses[reg_n].instruction_n=instruction_n; + + f_reg_alloc[real_reg_n].instruction_n= + (f_reg_uses[real_reg_n].instruction_n>instruction_n) + ? f_reg_uses[real_reg_n].instruction_n : instruction_n; + + f_reg_alloc[real_reg_n].value_used=parameter->parameter_data.reg.u & 1; + + if (use_flag!=USE) + f_reg_alloc[real_reg_n].altered=1; + + parameter->parameter_data.reg.r=real_reg_n; +} + +#ifdef NEW_R_ALLOC +static void use_2_same_type_registers + (struct reg *reg_p_1,int use_flag_1,struct reg *reg_p_2,int use_flag_2,int register_flag) +{ + int reg_n_1,reg_n_2,real_reg_n_1,real_reg_n_2,instruction_n; + struct register_use *reg_uses; + struct register_allocation *reg_alloc; + + reg_n_1=reg_p_1->r; + reg_n_2=reg_p_2->r; + + switch (register_flag){ + case D_REGISTER: + case A_REGISTER: + reg_uses=r_reg_uses; + reg_alloc=r_reg_alloc; + break; + case F_REGISTER: + reg_uses=f_reg_uses; + reg_alloc=f_reg_alloc; + break; + default: + internal_error_in_function ("use_2_same_type_registers"); + return; + } + + real_reg_n_1=reg_uses[reg_n_1].reg; + if (real_reg_n_1<0){ + int avoid_real_reg_n; + + if (register_flag==F_REGISTER) + avoid_real_reg_n= reg_n_2<8 ? reg_n_2 : reg_uses [reg_n_2].reg; + else + avoid_real_reg_n= (unsigned)(reg_n_2+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS ? reg_n_2+N_REAL_A_REGISTERS : reg_uses [reg_n_2].reg; + + real_reg_n_1=find_non_reg_2_register (reg_n_1,avoid_real_reg_n,reg_alloc,register_flag); + + allocate_2_register (reg_n_1,real_reg_n_1,use_flag_1,reg_uses,reg_alloc,register_flag); + } else if ((unsigned)(reg_n_1+N_REAL_A_REGISTERS)>=(unsigned)N_REAL_REGISTERS && + (register_flag==F_REGISTER ? real_reg_n_1==reg_n_2 : real_reg_n_1==reg_n_2+N_REAL_A_REGISTERS)) + { + int avoid_real_reg_n; + + if (register_flag==F_REGISTER) + avoid_real_reg_n= reg_n_2<8 ? reg_n_2 : reg_uses [reg_n_2].reg; + else + avoid_real_reg_n= (unsigned)(reg_n_2+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS ? reg_n_2+N_REAL_A_REGISTERS : reg_uses [reg_n_2].reg; + + real_reg_n_1=find_non_reg_2_register (reg_n_1,avoid_real_reg_n,reg_alloc,register_flag); + + move_2_register (reg_n_1,real_reg_n_1,use_flag_1,reg_uses,reg_alloc,register_flag); + } + + real_reg_n_2=reg_uses[reg_n_2].reg; + if (real_reg_n_2<0){ + int avoid_real_reg_n; + + if (register_flag==F_REGISTER) + avoid_real_reg_n= reg_n_1<8 ? reg_n_1 : reg_uses [reg_n_1].reg; + else + avoid_real_reg_n= (unsigned)(reg_n_1+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS ? reg_n_1+N_REAL_A_REGISTERS : reg_uses [reg_n_1].reg; + + real_reg_n_2=find_non_reg_2_register (reg_n_2,avoid_real_reg_n,reg_alloc,register_flag); + + allocate_2_register (reg_n_2,real_reg_n_2,use_flag_2,reg_uses,reg_alloc,register_flag); + } else if ((unsigned)(reg_n_2+N_REAL_A_REGISTERS)>=(unsigned)N_REAL_REGISTERS && + (register_flag==F_REGISTER ? real_reg_n_2==reg_n_1 : real_reg_n_2==reg_n_1+N_REAL_A_REGISTERS)) + { + int avoid_real_reg_n; + + if (register_flag==F_REGISTER) + avoid_real_reg_n= reg_n_2<8 ? reg_n_2 : reg_uses [reg_n_2].reg; + else + avoid_real_reg_n= (unsigned)(reg_n_2+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS ? reg_n_2+N_REAL_A_REGISTERS : reg_uses [reg_n_2].reg; + + real_reg_n_2=find_non_reg_2_register (reg_n_2,avoid_real_reg_n,reg_alloc,register_flag); + + move_2_register (reg_n_2,real_reg_n_2,use_flag_2,reg_uses,reg_alloc,register_flag); + } + +#ifdef FIX_REG_USES_INDEX + { + int real_reg_n_1_reg,real_reg_n_2_reg; + + if (register_flag==F_REGISTER){ + real_reg_n_1_reg=real_reg_n_1; + real_reg_n_2_reg=real_reg_n_2; + } else { + real_reg_n_1_reg = real_reg_n_1-N_REAL_A_REGISTERS; + real_reg_n_2_reg = real_reg_n_2-N_REAL_A_REGISTERS; + } +#endif + + instruction_n=reg_p_1->u>>1; + reg_uses[reg_n_1].instruction_n=instruction_n; + + reg_alloc[real_reg_n_1].instruction_n = +#ifdef FIX_REG_USES_INDEX + (reg_uses[real_reg_n_1_reg].instruction_n>instruction_n) + ? reg_uses[real_reg_n_1_reg].instruction_n : instruction_n; +#else + (reg_uses[real_reg_n_1].instruction_n>instruction_n) + ? reg_uses[real_reg_n_1].instruction_n : instruction_n; +#endif + + reg_alloc[real_reg_n_1].value_used=reg_p_1->u & 1; + + instruction_n=reg_p_2->u>>1; + reg_uses[reg_n_2].instruction_n=instruction_n; + + reg_alloc[real_reg_n_2].instruction_n = +#ifdef FIX_REG_USES_INDEX + (reg_uses[real_reg_n_2_reg].instruction_n>instruction_n) + ? reg_uses[real_reg_n_2_reg].instruction_n : instruction_n; +#else + (reg_uses[real_reg_n_2].instruction_n>instruction_n) + ? reg_uses[real_reg_n_2].instruction_n : instruction_n; +#endif + reg_alloc[real_reg_n_2].value_used=reg_p_2->u & 1; + + if (use_flag_1!=USE) + reg_alloc[real_reg_n_1].altered=1; + if (use_flag_2!=USE) + reg_alloc[real_reg_n_2].altered=1; + +#ifdef FIX_REG_USES_INDEX + reg_p_1->r=real_reg_n_1_reg; + reg_p_2->r=real_reg_n_2_reg; + } +#else + if (register_flag==F_REGISTER){ + reg_p_1->r=real_reg_n_1; + reg_p_2->r=real_reg_n_2; + } else { + reg_p_1->r=real_reg_n_1-N_REAL_A_REGISTERS; + reg_p_2->r=real_reg_n_2-N_REAL_A_REGISTERS; + } +#endif +} +#else +static void use_2_same_type_registers + (struct reg *reg_p_1,int use_flag_1,struct reg *reg_p_2,int use_flag_2,int register_flag) +{ + int reg_1,reg_n_1,reg_2,reg_n_2,real_reg_n_1,real_reg_n_2,instruction_n; + struct register_use *reg_uses; + struct register_allocation *reg_alloc; + + reg_1=reg_p_1->r; + reg_2=reg_p_2->r; + + switch (register_flag){ + case D_REGISTER: + reg_n_1=d_reg_num (reg_1); + reg_n_2=d_reg_num (reg_2); + reg_uses=d_reg_uses; + reg_alloc=d_reg_alloc; + break; + case A_REGISTER: + reg_n_1=a_reg_num (reg_1); + reg_n_2=a_reg_num (reg_2); + reg_uses=a_reg_uses; + reg_alloc=a_reg_alloc; + break; + case F_REGISTER: + reg_n_1=reg_1; + reg_n_2=reg_2; + reg_uses=f_reg_uses; + reg_alloc=f_reg_alloc; + break; + default: + internal_error_in_function ("use_2_same_type_registers"); + return; + } + + real_reg_n_1=reg_uses[reg_n_1].reg; + if (real_reg_n_1<0){ + int avoid_real_reg_n; + + avoid_real_reg_n= reg_n_2<8 ? reg_n_2 : reg_uses [reg_n_2].reg; + + real_reg_n_1=find_non_reg_2_register (reg_n_1,avoid_real_reg_n,reg_alloc,register_flag); + + allocate_2_register (reg_n_1,real_reg_n_1,use_flag_1,reg_uses,reg_alloc,register_flag); + } else if (reg_n_1>=8 && real_reg_n_1==reg_n_2){ + int avoid_real_reg_n; + + avoid_real_reg_n= reg_n_2<8 ? reg_n_2 : reg_uses [reg_n_2].reg; + + real_reg_n_1=find_non_reg_2_register (reg_n_1,avoid_real_reg_n,reg_alloc,register_flag); + + move_2_register (reg_n_1,real_reg_n_1,use_flag_1,reg_uses,reg_alloc,register_flag); + } + + real_reg_n_2=reg_uses[reg_n_2].reg; + if (real_reg_n_2<0){ + int avoid_real_reg_n; + + avoid_real_reg_n= reg_n_1<8 ? reg_n_1 : reg_uses [reg_n_1].reg; + + real_reg_n_2=find_non_reg_2_register (reg_n_2,avoid_real_reg_n,reg_alloc,register_flag); + + allocate_2_register (reg_n_2,real_reg_n_2,use_flag_2,reg_uses,reg_alloc, + register_flag); + } else if (reg_n_2>=8 && real_reg_n_2==reg_n_1){ + int avoid_real_reg_n; + + avoid_real_reg_n= reg_n_2<8 ? reg_n_2 : reg_uses [reg_n_2].reg; + + real_reg_n_2=find_non_reg_2_register (reg_n_2,avoid_real_reg_n,reg_alloc,register_flag); + + move_2_register (reg_n_2,real_reg_n_2,use_flag_2,reg_uses,reg_alloc,register_flag); + } + + instruction_n=reg_p_1->u>>1; + reg_uses[reg_n_1].instruction_n=instruction_n; + + reg_alloc[real_reg_n_1].instruction_n = + (reg_uses[real_reg_n_1].instruction_n>instruction_n) + ? reg_uses[real_reg_n_1].instruction_n : instruction_n; + + reg_alloc[real_reg_n_1].value_used=reg_p_1->u & 1; + + instruction_n=reg_p_2->u>>1; + reg_uses[reg_n_2].instruction_n=instruction_n; + + reg_alloc[real_reg_n_2].instruction_n = + (reg_uses[real_reg_n_2].instruction_n>instruction_n) + ? reg_uses[real_reg_n_2].instruction_n : instruction_n; + reg_alloc[real_reg_n_2].value_used=reg_p_2->u & 1; + + if (use_flag_1!=USE) + reg_alloc[real_reg_n_1].altered=1; + if (use_flag_2!=USE) + reg_alloc[real_reg_n_2].altered=1; + + switch (register_flag){ + case D_REGISTER: + reg_p_1->r=num_to_d_reg (real_reg_n_1); + reg_p_2->r=num_to_d_reg (real_reg_n_2); + break; + case A_REGISTER: + reg_p_1->r=num_to_a_reg (real_reg_n_1); + reg_p_2->r=num_to_a_reg (real_reg_n_2); + break; + case F_REGISTER: + reg_p_1->r=real_reg_n_1; + reg_p_2->r=real_reg_n_2; + } +} +#endif + +#ifdef NEW_R_ALLOC +static int find_register_3 + (int reg_n_1,int reg_n_2,int reg_n_3,int register_flag,struct register_use *reg_uses, + struct register_allocation *reg_alloc) +{ + int avoid_real_reg_n2,avoid_real_reg_n3; + unsigned int avoid_register_set; + + if (register_flag==F_REGISTER){ + avoid_real_reg_n2= reg_n_2<8 ? reg_n_2 : reg_uses [reg_n_2].reg; + avoid_real_reg_n3= reg_n_3<8 ? reg_n_3 : reg_uses [reg_n_3].reg; + } else { + avoid_real_reg_n2= (unsigned)(reg_n_2+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS ? reg_n_2+N_REAL_A_REGISTERS : reg_uses [reg_n_2].reg; + avoid_real_reg_n3= (unsigned)(reg_n_3+N_REAL_A_REGISTERS)<(unsigned)N_REAL_REGISTERS ? reg_n_3+N_REAL_A_REGISTERS : reg_uses [reg_n_3].reg; + } + + avoid_register_set=0; + if (avoid_real_reg_n2>=0) + avoid_register_set |= 1<<avoid_real_reg_n2; + if (avoid_real_reg_n3>=0) + avoid_register_set |= 1<<avoid_real_reg_n3; + + return find_reg_not_in_set (reg_n_1,avoid_register_set,reg_alloc,register_flag); +} + +static void use_3_same_type_registers + (struct reg *reg_p_1,int use_flag_1,struct reg *reg_p_2,int use_flag_2, + struct reg *reg_p_3,int use_flag_3,int register_flag) +{ + int reg_n_1,reg_n_2,reg_n_3,real_reg_n_1,real_reg_n_2,real_reg_n_3,instruction_n; + struct register_use *reg_uses; + struct register_allocation *reg_alloc; + + reg_n_1=reg_p_1->r; + reg_n_2=reg_p_2->r; + reg_n_3=reg_p_3->r; + + switch (register_flag){ + case D_REGISTER: + case A_REGISTER: + reg_uses=r_reg_uses; + reg_alloc=r_reg_alloc; + break; + case F_REGISTER: + reg_uses=f_reg_uses; + reg_alloc=f_reg_alloc; + break; + default: + internal_error_in_function ("use_2_same_type_registers"); + return; + } + + real_reg_n_1=reg_uses[reg_n_1].reg; + if (real_reg_n_1<0){ + real_reg_n_1=find_register_3 (reg_n_1,reg_n_2,reg_n_3,register_flag,reg_uses,reg_alloc); + + allocate_2_register (reg_n_1,real_reg_n_1,use_flag_1,reg_uses,reg_alloc,register_flag); + } else if ((unsigned)(reg_n_1+N_REAL_A_REGISTERS)>=(unsigned)N_REAL_REGISTERS && + (register_flag==F_REGISTER ? + (real_reg_n_1==reg_n_2 || real_reg_n_1==reg_n_3) : + (real_reg_n_1==reg_n_2+N_REAL_A_REGISTERS || real_reg_n_1==reg_n_3+N_REAL_A_REGISTERS))) + { + real_reg_n_1=find_register_3 (reg_n_1,reg_n_2,reg_n_3,register_flag,reg_uses,reg_alloc); + + move_2_register (reg_n_1,real_reg_n_1,use_flag_1,reg_uses,reg_alloc,register_flag); + } + + real_reg_n_2=reg_uses[reg_n_2].reg; + if (real_reg_n_2<0){ + real_reg_n_2=find_register_3 (reg_n_2,reg_n_1,reg_n_3,register_flag,reg_uses,reg_alloc); + + allocate_2_register (reg_n_2,real_reg_n_2,use_flag_2,reg_uses,reg_alloc,register_flag); + } else if ((unsigned)(reg_n_2+N_REAL_A_REGISTERS)>=(unsigned)N_REAL_REGISTERS && + (register_flag==F_REGISTER ? + (real_reg_n_2==reg_n_1 || real_reg_n_2==reg_n_3) : + (real_reg_n_2==reg_n_1+N_REAL_A_REGISTERS || real_reg_n_2==reg_n_3+N_REAL_A_REGISTERS))) + { + real_reg_n_2=find_register_3 (reg_n_2,reg_n_1,reg_n_3,register_flag,reg_uses,reg_alloc); + + move_2_register (reg_n_2,real_reg_n_2,use_flag_1,reg_uses,reg_alloc,register_flag); + } + + real_reg_n_3=reg_uses[reg_n_3].reg; + if (real_reg_n_3<0){ + real_reg_n_3=find_register_3 (reg_n_3,reg_n_1,reg_n_2,register_flag,reg_uses,reg_alloc); + + allocate_2_register (reg_n_3,real_reg_n_3,use_flag_3,reg_uses,reg_alloc,register_flag); + } else if ((unsigned)(reg_n_3+N_REAL_A_REGISTERS)>=(unsigned)N_REAL_REGISTERS && + (register_flag==F_REGISTER ? + (real_reg_n_3==reg_n_1 || real_reg_n_3==reg_n_2) : + (real_reg_n_3==reg_n_1+N_REAL_A_REGISTERS || real_reg_n_3==reg_n_2+N_REAL_A_REGISTERS))) + { + real_reg_n_3=find_register_3 (reg_n_3,reg_n_1,reg_n_2,register_flag,reg_uses,reg_alloc); + + move_2_register (reg_n_3,real_reg_n_3,use_flag_1,reg_uses,reg_alloc,register_flag); + } + +#ifdef FIX_REG_USES_INDEX + { + int real_reg_n_1_reg,real_reg_n_2_reg,real_reg_n_3_reg; + + if (register_flag==F_REGISTER){ + real_reg_n_1_reg=real_reg_n_1; + real_reg_n_2_reg=real_reg_n_2; + real_reg_n_3_reg=real_reg_n_3; + } else { + real_reg_n_1_reg = real_reg_n_1-N_REAL_A_REGISTERS; + real_reg_n_2_reg = real_reg_n_2-N_REAL_A_REGISTERS; + real_reg_n_3_reg = real_reg_n_3-N_REAL_A_REGISTERS; + } +#endif + + instruction_n=reg_p_1->u>>1; + reg_uses[reg_n_1].instruction_n=instruction_n; + + reg_alloc[real_reg_n_1].instruction_n = +#ifdef FIX_REG_USES_INDEX + (reg_uses[real_reg_n_1_reg].instruction_n>instruction_n) + ? reg_uses[real_reg_n_1_reg].instruction_n : instruction_n; +#else + (reg_uses[real_reg_n_1].instruction_n>instruction_n) + ? reg_uses[real_reg_n_1].instruction_n : instruction_n; +#endif + + reg_alloc[real_reg_n_1].value_used=reg_p_1->u & 1; + + instruction_n=reg_p_2->u>>1; + reg_uses[reg_n_2].instruction_n=instruction_n; + + reg_alloc[real_reg_n_2].instruction_n = +#ifdef FIX_REG_USES_INDEX + (reg_uses[real_reg_n_2_reg].instruction_n>instruction_n) + ? reg_uses[real_reg_n_2_reg].instruction_n : instruction_n; +#else + (reg_uses[real_reg_n_2].instruction_n>instruction_n) + ? reg_uses[real_reg_n_2].instruction_n : instruction_n; +#endif + reg_alloc[real_reg_n_2].value_used=reg_p_2->u & 1; + + instruction_n=reg_p_3->u>>1; + reg_uses[reg_n_3].instruction_n=instruction_n; + + reg_alloc[real_reg_n_3].instruction_n = +#ifdef FIX_REG_USES_INDEX + (reg_uses[real_reg_n_3_reg].instruction_n>instruction_n) + ? reg_uses[real_reg_n_3_reg].instruction_n : instruction_n; +#else + (reg_uses[real_reg_n_3].instruction_n>instruction_n) + ? reg_uses[real_reg_n_3].instruction_n : instruction_n; +#endif + reg_alloc[real_reg_n_3].value_used=reg_p_3->u & 1; + + if (use_flag_1!=USE) + reg_alloc[real_reg_n_1].altered=1; + if (use_flag_2!=USE) + reg_alloc[real_reg_n_2].altered=1; + if (use_flag_3!=USE) + reg_alloc[real_reg_n_3].altered=1; + +#ifdef FIX_REG_USES_INDEX + reg_p_1->r=real_reg_n_1_reg; + reg_p_2->r=real_reg_n_2_reg; + reg_p_3->r=real_reg_n_3_reg; + } +#else + if (register_flag==F_REGISTER){ + reg_p_1->r=real_reg_n_1; + reg_p_2->r=real_reg_n_2; + reg_p_3->r=real_reg_n_3; + } else { + reg_p_1->r=real_reg_n_1-N_REAL_A_REGISTERS; + reg_p_2->r=real_reg_n_2-N_REAL_A_REGISTERS; + reg_p_3->r=real_reg_n_3-N_REAL_A_REGISTERS; + } +#endif +} +#endif + +#ifdef NEW_R_ALLOC +static void register_use_2 (struct reg *reg_p_1,int use_flag_1,struct reg *reg_p_2,int use_flag_2) +{ + use_2_same_type_registers (reg_p_1,use_flag_1,reg_p_2,use_flag_2,D_REGISTER); +} +#else +static void register_use_2 (struct reg *reg_p_1,int use_flag_1,struct reg *reg_p_2,int use_flag_2) +{ + if (is_d_register (reg_p_1->r)){ + if (is_d_register (reg_p_2->r)) + use_2_same_type_registers (reg_p_1,use_flag_1,reg_p_2,use_flag_2,D_REGISTER); + else { + register_use (reg_p_1,use_flag_1); + register_use (reg_p_2,use_flag_2); + } + } else { + if (is_d_register (reg_p_2->r)){ + register_use (reg_p_1,use_flag_1); + register_use (reg_p_2,use_flag_2); + } else + use_2_same_type_registers (reg_p_1,use_flag_1,reg_p_2,use_flag_2,A_REGISTER); + } +} +#endif + +#ifdef M68000 +static void register_use_3_d_indexed + (struct reg *reg_p,int use_flag,struct reg *a_reg_p,struct reg *d_reg_p) +{ + if (is_d_register (reg_p->r)){ + use_2_same_type_registers (reg_p,use_flag,d_reg_p,USE,D_REGISTER); + register_use (a_reg_p,USE); + } else { + use_2_same_type_registers (reg_p,use_flag,a_reg_p,USE,A_REGISTER); + register_use (d_reg_p,USE); + } +} + +static void register_use_3_s_indexed + (struct reg *a_reg_p,struct reg *d_reg_p,struct reg *reg_p,int use_flag) +{ + if (is_d_register (reg_p->r)){ + use_2_same_type_registers (d_reg_p,USE,reg_p,use_flag,D_REGISTER); + register_use (a_reg_p,USE); + } else { + use_2_same_type_registers (a_reg_p,USE,reg_p,use_flag,A_REGISTER); + register_use (d_reg_p,USE); + } +} +#endif + +#if 1 +static void instruction_use_def_reg (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + case P_INDIRECT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE); + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use (&instruction->instruction_parameters[1].parameter_data.reg,DEF); + break; + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[1],DEF); + } + break; +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF); + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use (&instruction->instruction_parameters[1].parameter_data.reg,DEF); + break; + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[1],DEF); + } + break; +#endif + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[0],USE); + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use (&instruction->instruction_parameters[1].parameter_data.reg,DEF); + break; + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[1],DEF); + } + break; + case P_INDEXED: +#ifdef M68000 + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use_3_s_indexed + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg, + &instruction->instruction_parameters[1].parameter_data.reg,use_flag); + break; + case P_F_REGISTER: + register_use (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE); + register_use (&instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE); + float_register_use (&instruction->instruction_parameters[1],use_flag); + } +#else + use_2_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE,D_REGISTER); + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use (&instruction->instruction_parameters[1].parameter_data.reg,DEF); + break; + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[1],DEF); + } +#endif + break; + default: + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use (&instruction->instruction_parameters[1].parameter_data.reg,DEF); + break; + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[1],DEF); + } + } +} +#endif + +static void instruction_use_2 (struct instruction *instruction,int use_flag) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + case P_INDIRECT: + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use_2 + (&instruction->instruction_parameters[0].parameter_data.reg,USE, + &instruction->instruction_parameters[1].parameter_data.reg,use_flag); + break; + case P_INDIRECT: + register_use_2 + (&instruction->instruction_parameters[0].parameter_data.reg,USE, + &instruction->instruction_parameters[1].parameter_data.reg,USE); + break; +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + register_use_2 + (&instruction->instruction_parameters[0].parameter_data.reg,USE, + &instruction->instruction_parameters[1].parameter_data.reg,USE_DEF); + break; +#endif + case P_F_REGISTER: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE); + float_register_use (&instruction->instruction_parameters[1],use_flag); + break; + case P_INDEXED: +#ifdef M68000 + register_use_3_d_indexed + (&instruction->instruction_parameters[0].parameter_data.reg,USE, + &instruction->instruction_parameters[1].parameter_data.ir->a_reg, + &instruction->instruction_parameters[1].parameter_data.ir->d_reg); +#else + use_3_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.reg,USE, + &instruction->instruction_parameters[1].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[1].parameter_data.ir->d_reg,USE,D_REGISTER); +#endif + break; + default: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE); + } + break; +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use_2 + (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF, + &instruction->instruction_parameters[1].parameter_data.reg,use_flag); + break; + case P_INDIRECT: + register_use_2 + (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF, + &instruction->instruction_parameters[1].parameter_data.reg,USE); + break; + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + register_use_2 + (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF, + &instruction->instruction_parameters[1].parameter_data.reg,USE_DEF); + break; + case P_F_REGISTER: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF); + float_register_use (&instruction->instruction_parameters[1],use_flag); + break; + case P_INDEXED: +#ifdef M68000 + register_use_3_d_indexed + (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF, + &instruction->instruction_parameters[1].parameter_data.ir->a_reg, + &instruction->instruction_parameters[1].parameter_data.ir->d_reg); +#else + use_3_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF, + &instruction->instruction_parameters[1].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[1].parameter_data.ir->d_reg,USE,D_REGISTER); +#endif + break; + default: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF); + } + break; +#endif + case P_F_REGISTER: + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + float_register_use (&instruction->instruction_parameters[0],USE); + register_use (&instruction->instruction_parameters[1].parameter_data.reg,use_flag); + break; + case P_INDIRECT: + float_register_use (&instruction->instruction_parameters[0],USE); + register_use (&instruction->instruction_parameters[1].parameter_data.reg,USE); + break; +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + float_register_use (&instruction->instruction_parameters[0],USE); + register_use (&instruction->instruction_parameters[1].parameter_data.reg,USE_DEF); + break; +#endif + case P_F_REGISTER: + use_2_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.reg,USE, + &instruction->instruction_parameters[1].parameter_data.reg,use_flag, + F_REGISTER); + break; + case P_INDEXED: + float_register_use (&instruction->instruction_parameters[0],USE); +#ifdef M68000 + register_use (&instruction->instruction_parameters[1].parameter_data.ir->a_reg,USE); + register_use (&instruction->instruction_parameters[1].parameter_data.ir->d_reg,USE); +#else + register_use_2 + (&instruction->instruction_parameters[1].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[1].parameter_data.ir->d_reg,USE); +#endif + break; + default: + float_register_use (&instruction->instruction_parameters[0],USE); + } + break; + case P_INDEXED: +#ifdef M68000 + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use_3_s_indexed + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg, + &instruction->instruction_parameters[1].parameter_data.reg,use_flag); + break; + case P_INDIRECT: + register_use_3_s_indexed + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg, + &instruction->instruction_parameters[1].parameter_data.reg,USE); + break; +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + register_use_3_s_indexed + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg, + &instruction->instruction_parameters[1].parameter_data.reg,USE_DEF); + break; +#endif + case P_F_REGISTER: + register_use (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE); + register_use (&instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE); + float_register_use (&instruction->instruction_parameters[1],use_flag); + break; + case P_INDEXED: + use_2_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[1].parameter_data.ir->a_reg,USE, + A_REGISTER); + use_2_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE, + &instruction->instruction_parameters[1].parameter_data.ir->d_reg,USE, + D_REGISTER); + break; + default: + register_use (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE); + register_use (&instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE); + } +#else + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + use_3_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE, + &instruction->instruction_parameters[1].parameter_data.reg,use_flag,D_REGISTER); + break; + case P_F_REGISTER: + use_2_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE,D_REGISTER); + float_register_use (&instruction->instruction_parameters[1],use_flag); + break; + case P_INDIRECT: + use_3_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE, + &instruction->instruction_parameters[1].parameter_data.reg,USE,D_REGISTER); + break; + case P_INDEXED: + internal_error_in_function ("instruction_use_2"); + break; + default: + use_2_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE,D_REGISTER); + } + +#endif + break; + default: + switch (instruction->instruction_parameters[1].parameter_type){ + case P_REGISTER: + register_use (&instruction->instruction_parameters[1].parameter_data.reg,use_flag); + break; + case P_INDIRECT: + register_use (&instruction->instruction_parameters[1].parameter_data.reg,USE); + break; +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + register_use (&instruction->instruction_parameters[1].parameter_data.reg,USE_DEF); + break; +#endif + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[1],use_flag); + break; + case P_INDEXED: +#ifdef M68000 + register_use (&instruction->instruction_parameters[1].parameter_data.ir->a_reg,USE); + register_use (&instruction->instruction_parameters[1].parameter_data.ir->d_reg,USE); +#else + register_use_2 + (&instruction->instruction_parameters[1].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[1].parameter_data.ir->d_reg,USE); +#endif + } + } +} + +static void instruction_use (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + case P_INDIRECT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE); + break; +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF); + break; +#endif + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[0],USE); + break; + case P_INDEXED: +#ifdef M68000 + register_use (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE); + register_use (&instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE); +#else + register_use_2 + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE); +#endif + } +} + +static void instruction_usedef (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF); + break; +#endif + case P_INDIRECT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE); + break; + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[0],USE_DEF); + break; + case P_INDEXED: +#ifdef M68000 + register_use (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE); + register_use (&instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE); +#else + register_use_2 + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE); +#endif + } +} + +static void instruction_def (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,DEF); + break; + case P_INDIRECT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE); + break; +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF); + break; +#endif + case P_F_REGISTER: + float_register_use (&instruction->instruction_parameters[0],DEF); + break; + case P_INDEXED: +#ifdef M68000 + register_use (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE); + register_use (&instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE); +#else + register_use_2 + (&instruction->instruction_parameters[0].parameter_data.ir->a_reg,USE, + &instruction->instruction_parameters[0].parameter_data.ir->d_reg,USE); +#endif + } +} + +static void instruction_exg_usedef_usedef (struct instruction *instruction) +{ + register_use_2 ( &instruction->instruction_parameters[0].parameter_data.reg,USE_DEF, + &instruction->instruction_parameters[1].parameter_data.reg,USE_DEF); +} + +#if defined (I486) && defined (FP_STACK_OPTIMIZATIONS) +static void instruction_fexg_usedef_usedef (struct instruction *instruction) +{ + use_2_same_type_registers ( &instruction->instruction_parameters[0].parameter_data.reg,USE_DEF, + &instruction->instruction_parameters[1].parameter_data.reg,USE_DEF,F_REGISTER); +} +#endif + +#ifndef I486 +static void instruction_mod_use_def_use (struct instruction *instruction) +{ + switch (instruction->instruction_parameters[0].parameter_type){ + case P_REGISTER: + { + int reg=instruction->instruction_parameters[0].parameter_data.reg.r; + if (is_d_register (reg)){ + if (reg!=instruction->instruction_parameters[1].parameter_data.reg.r) + internal_error_in_function ("instruction_mode_use_def_use"); + use_2_same_type_registers + (&instruction->instruction_parameters[1].parameter_data.reg,USE_DEF, + &instruction->instruction_parameters[2].parameter_data.reg,USE, + D_REGISTER); + instruction->instruction_parameters[0].parameter_data.reg.r= + instruction->instruction_parameters[1].parameter_data.reg.r; + } else { + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE); + use_2_same_type_registers + (&instruction->instruction_parameters[1].parameter_data.reg,DEF, + &instruction->instruction_parameters[2].parameter_data.reg,USE, + D_REGISTER); + } + break; + } + case P_INDIRECT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE); + use_2_same_type_registers + (&instruction->instruction_parameters[1].parameter_data.reg,DEF, + &instruction->instruction_parameters[2].parameter_data.reg,USE, + D_REGISTER); + break; +#if defined (M68000) || defined (I486) + case P_POST_INCREMENT: + case P_PRE_DECREMENT: + register_use (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF); + use_2_same_type_registers + (&instruction->instruction_parameters[1].parameter_data.reg,DEF, + &instruction->instruction_parameters[2].parameter_data.reg,USE, + D_REGISTER); + break; +#endif + default: + use_2_same_type_registers + (&instruction->instruction_parameters[1].parameter_data.reg,DEF, + &instruction->instruction_parameters[2].parameter_data.reg,USE, + D_REGISTER); + } +} +#endif + +#ifdef M68000 +static void instruction_movem_use_defs (struct instruction *instruction) +{ + int a_reg,a_reg_n,arity,n,a_real_reg_n,instruction_n; + unsigned int avoid_reg_set; + + if (instruction->instruction_parameters[0].parameter_type!=P_INDIRECT) + internal_error_in_function ("instruction_movem_use_defs"); + + arity=instruction->instruction_arity; + a_reg=instruction->instruction_parameters[0].parameter_data.reg.r; + a_reg_n=a_reg_num (a_reg); + + avoid_reg_set=0; + + for (n=1; n<arity; ++n){ + int reg=instruction->instruction_parameters[n].parameter_data.reg.r; + if (is_a_register (reg)) + avoid_reg_set |= ((unsigned)1 << a_reg_num (reg)); + } + + a_real_reg_n=a_reg_uses[a_reg_n].reg; + if (a_real_reg_n<0){ + a_real_reg_n=find_reg_not_in_set (a_reg_n,avoid_reg_set,a_reg_alloc,A_REGISTER); + allocate_2_register (a_reg_n,a_real_reg_n,USE,a_reg_uses,a_reg_alloc,A_REGISTER); + } + + instruction_n=instruction->instruction_parameters[0].parameter_data.reg.u>>1; + a_reg_uses[a_reg_n].instruction_n=instruction_n; + + a_reg_alloc[a_real_reg_n].instruction_n = + (a_reg_uses[a_real_reg_n].instruction_n>instruction_n) + ? a_reg_uses[a_real_reg_n].instruction_n : instruction_n; + + a_reg_alloc[a_real_reg_n].value_used= + instruction->instruction_parameters[0].parameter_data.reg.u & 1; + + instruction->instruction_parameters[0].parameter_data.reg.r=num_to_a_reg (a_real_reg_n); + + for (n=1; n<arity; ++n){ + int reg=instruction->instruction_parameters[n].parameter_data.reg.r; + + if (is_d_register (reg)) + register_use (&instruction->instruction_parameters[n].parameter_data.reg,DEF); + else { + int reg,reg_n,real_reg_n,instruction_n; + struct parameter *parameter; + + parameter=&instruction->instruction_parameters[n]; + reg=parameter->parameter_data.reg.r; + reg_n=a_reg_num (reg); + + real_reg_n=a_reg_uses[reg_n].reg; + if (real_reg_n<0) { + int avoid_real_reg_n; + + avoid_real_reg_n = a_reg_n<8 ? a_reg_n : a_reg_uses [a_reg_n].reg; + + real_reg_n=find_non_reg_2_register (reg_n,avoid_real_reg_n,a_reg_alloc, + A_REGISTER); + allocate_2_register (reg_n,real_reg_n,DEF,a_reg_uses,a_reg_alloc,A_REGISTER); + } + + instruction_n=parameter->parameter_data.reg.u>>1; + a_reg_uses[reg_n].instruction_n=instruction_n; + + a_reg_alloc[real_reg_n].instruction_n = + (a_reg_uses[real_reg_n].instruction_n>instruction_n) + ? a_reg_uses[real_reg_n].instruction_n : instruction_n; + + a_reg_alloc[real_reg_n].value_used=parameter->parameter_data.reg.u & 1; + a_reg_alloc[real_reg_n].altered=1; + + parameter->parameter_data.reg.r=num_to_a_reg (real_reg_n); + } + } +} + +static void instruction_bmove_use_use_use (struct instruction *instruction) +{ + use_2_same_type_registers + (&instruction->instruction_parameters[0].parameter_data.reg,USE, + &instruction->instruction_parameters[1].parameter_data.reg,USE,A_REGISTER); + register_use (&instruction->instruction_parameters[2].parameter_data.reg,USE); +} +#endif + +# ifdef I486_USE_SCRATCH_REGISTER +static void use_scratch_register (void) +{ + int reg,real_reg_n,instruction_n; + struct scratch_register_next_uses *scratch_register_next_use; + + scratch_register_next_use=scratch_register_next_uses; + scratch_register_next_uses=scratch_register_next_use->scratch_register_next; + + reg=-3; + + real_reg_n=r_reg_uses[reg].reg; + if (real_reg_n<0){ + real_reg_n=find_register (reg,r_reg_alloc,D_REGISTER); + allocate_2_register (reg,real_reg_n,DEF,r_reg_uses,r_reg_alloc,D_REGISTER); + } + + instruction_n=scratch_register_next_use->scratch_register_u>>1; + r_reg_uses[reg].instruction_n=instruction_n; + + r_reg_alloc[real_reg_n].instruction_n = +#ifdef FIX_REG_USES_INDEX + (r_reg_uses[real_reg_n-N_REAL_A_REGISTERS].instruction_n>instruction_n) + ? r_reg_uses[real_reg_n-N_REAL_A_REGISTERS].instruction_n : instruction_n; +#else + (r_reg_uses[real_reg_n].instruction_n>instruction_n) + ? r_reg_uses[real_reg_n].instruction_n : instruction_n; +#endif + + r_reg_alloc[real_reg_n].value_used=scratch_register_next_use->scratch_register_u & 1; + r_reg_alloc[real_reg_n].altered=1; + + scratch_register_next_use->scratch_register_next=scratch_register_free_list; + scratch_register_free_list=scratch_register_next_use; + + allocate_scratch_register=0; +} +#endif + +static void allocate_registers (struct basic_block *basic_block) +{ + struct instruction *instruction; + + current_block=basic_block; + previous_instruction=NULL; + + instruction=basic_block->block_instructions; + while (instruction!=NULL){ + switch (instruction->instruction_icode){ + case IADD: case IAND: +#ifndef I486_USE_SCRATCH_REGISTER + case IASR: case ILSL: case ILSR: + case IDIV: +#endif + case IEOR: + case IFADD: case IFCMP: case IFDIV: case IFMUL: case IFREM: case IFSUB: + case IMUL: case IOR: case ISUB: +IF_G_SPARC (case IADDO: case ISUBO:) + instruction_use_2 (instruction,USE_DEF); + break; +#ifdef I486_USE_SCRATCH_REGISTER + case IASR: case ILSL: case ILSR: + if (instruction->instruction_parameters[0].parameter_type!=P_IMMEDIATE) + use_scratch_register(); + instruction_use_2 (instruction,USE_DEF); + allocate_scratch_register=1; + break; + case IDIV: case IMOD: + use_scratch_register(); + instruction_use_2 (instruction,USE_DEF); + allocate_scratch_register=1; + break; +#endif + case ICMP: +#ifndef I486_USE_SCRATCH_REGISTER + case ICMPW: +#endif +IF_G_POWER (case ICMPLW:) + instruction_use_2 (instruction,USE); + break; +#ifdef I486_USE_SCRATCH_REGISTER + case ICMPW: + if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT || + instruction->instruction_parameters[1].parameter_type==P_INDIRECT) + use_scratch_register(); + instruction_use_2 (instruction,USE); + allocate_scratch_register=1; + break; + case IMOVE: + if ((instruction->instruction_parameters[0].parameter_type==P_INDIRECT || + instruction->instruction_parameters[0].parameter_type==P_INDEXED) && + (instruction->instruction_parameters[1].parameter_type==P_INDIRECT || + instruction->instruction_parameters[1].parameter_type==P_INDEXED)) + use_scratch_register(); +#if 1 + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER || + instruction->instruction_parameters[1].parameter_type==P_F_REGISTER) + instruction_use_def_reg (instruction); + else +#endif + instruction_use_2 (instruction,DEF); + allocate_scratch_register=1; + break; +#endif + case IFMOVE: case IFMOVEL: case ILEA: +#ifndef I486_USE_SCRATCH_REGISTER + case IMOVE: +#endif + case IMOVEB: case IMOVEW: + case IFCOS: case IFSIN: case IFTAN: +#ifdef M68000 + case IFACOS: case IFASIN: case IFATAN: case IFEXP: case IFLN: case IFLOG10: +#endif + case IFNEG: +#if !defined (G_POWER) + case IFSQRT: +#endif +IF_G_SPARC (case IFMOVEHI: case IFMOVELO:) +IF_G_RISC (case IADDI: case ILSLI:) + +#if 1 + if (instruction->instruction_parameters[1].parameter_type==P_REGISTER || + instruction->instruction_parameters[1].parameter_type==P_F_REGISTER) + instruction_use_def_reg (instruction); + else +#endif + instruction_use_2 (instruction,DEF); + break; + case IFTST: case ITST: + instruction_use (instruction); + break; + case IEXT: +#if defined (M68000) || defined (G_POWER) + case IEXTB: +#endif + instruction_usedef (instruction); + break; + case IFSEQ: case IFSGE: case IFSGT: case IFSLE: case IFSLT: case IFSNE: + { +#ifdef I486_USE_SCRATCH_REGISTER + use_scratch_register(); +#endif + instruction_def (instruction); +#ifdef I486_USE_SCRATCH_REGISTER + allocate_scratch_register=1; +#endif + break; + } + case ISEQ: case ISGE: case ISGT: case ISLE: case ISLT: case ISNE: + case ISO: case ISNO: +#ifdef I486_USE_SCRATCH_REGISTER + use_scratch_register(); +#endif + do_not_alter_condition_codes=1; + instruction_def (instruction); + do_not_alter_condition_codes=0; +#ifdef I486_USE_SCRATCH_REGISTER + allocate_scratch_register=1; +#endif + break; + case IEXG: + instruction_exg_usedef_usedef (instruction); + break; +#if defined (I486) && defined (FP_STACK_OPTIMIZATIONS) + case IFEXG: + instruction_fexg_usedef_usedef (instruction); + break; +#endif +#ifndef I486_USE_SCRATCH_REGISTER + case IMOD: +# if defined (I486) || defined (G_POWER) + instruction_use_2 (instruction,USE_DEF); +# else + instruction_mod_use_def_use (instruction); +# endif + break; +#endif +#ifdef I486 + case IDIVI: case IREMI: +# ifdef I486_USE_SCRATCH_REGISTER + use_scratch_register(); +# endif + register_use_2 + (&instruction->instruction_parameters[1].parameter_data.reg,USE_DEF, + &instruction->instruction_parameters[2].parameter_data.reg,DEF); +# ifdef I486_USE_SCRATCH_REGISTER + allocate_scratch_register=1; +# endif + break; +#endif +#ifdef M68000 + case IMOVEM: + instruction_movem_use_defs (instruction); + break; + case IBMOVE: + instruction_bmove_use_use_use (instruction); + break; +#endif +#ifdef I486_USE_SCRATCH_REGISTER + case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE: + use_scratch_register(); + allocate_scratch_register=1; + break; +#endif + /* + case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE: + case IRTS: case IJMP: case IJSR: + break; + */ + case IBEQ: case IBGE: case IBGT: case IBLE: case IBLT: case IBNE: + case IBO: case IBNO: + case IBHS: + break; + default: + internal_error_in_function ("allocate_registers"); + } + previous_instruction=instruction; + instruction=instruction->instruction_next; + } +} + +static int load_parameter_registers (unsigned end_a_registers,unsigned end_d_registers,unsigned end_f_registers, + int not_alter_condition_codes_flag,int condition) +{ + int reg_n,condition_on_stack; + +#ifdef NEW_R_ALLOC + for (reg_n=0; reg_n<N_REAL_A_REGISTERS; ++reg_n) + if (end_a_registers & ((unsigned)1<<reg_n) && r_reg_uses[-(reg_n+1)].reg<0) + i_move_id_r (r_reg_uses[-(reg_n+1)].offset,B_STACK_POINTER,num_to_a_reg (reg_n)); + + for (reg_n=0; reg_n<8; ++reg_n) + if (end_d_registers & ((unsigned)1<<reg_n) && r_reg_uses[reg_n].reg<0) + i_move_id_r (r_reg_uses[reg_n].offset,B_STACK_POINTER,num_to_d_reg (reg_n)); +#else + for (reg_n=0; reg_n<8; ++reg_n) + if (end_a_registers & ((unsigned)1<<reg_n) && a_reg_uses[reg_n].reg<0) + i_move_id_r (a_reg_uses[reg_n].offset,B_STACK_POINTER,num_to_a_reg (reg_n)); + + for (reg_n=0; reg_n<8; ++reg_n) + if (end_d_registers & ((unsigned)1<<reg_n) && d_reg_uses[reg_n].reg<0) +# ifdef M68000 + if (not_alter_condition_codes_flag) + i_movem_id_r (d_reg_uses[reg_n].offset,B_STACK_POINTER,num_to_d_reg (reg_n)); + else +# endif + i_move_id_r (d_reg_uses[reg_n].offset,B_STACK_POINTER,num_to_d_reg (reg_n)); +#endif + + condition_on_stack=0; + for (reg_n=0; reg_n<8; ++reg_n) + if (end_f_registers & ((unsigned)1<<reg_n) && f_reg_uses[reg_n].reg<0){ +#ifdef M68000 + if (not_alter_condition_codes_flag>1 && !condition_on_stack){ + condition_on_stack=1; + instruction_pd (condition_to_set_instruction[condition],REGISTER_A7); + } +#endif + i_fmove_id_fr (f_reg_uses[reg_n].offset,B_STACK_POINTER,reg_n); + } + + return condition_on_stack; +} + +int do_register_allocation + (struct instruction *last_instruction,struct basic_block *basic_block, + int highest_a_register,int highest_d_register,int highest_f_register, + int not_alter_condition_codes_flag,int condition) +{ + int condition_on_stack; +#ifdef NEW_R_ALLOC + struct register_use *r_reg_uses_block; +#endif + +#if defined(NEW_R_ALLOC) && (defined (sparc) || defined (G_POWER)) + if (highest_a_register<=N_REAL_A_REGISTERS && highest_d_register<=8 && highest_f_register<=15) +#else + if (highest_a_register<=8 && highest_d_register<=8 && highest_f_register<=8) +#endif + return 0; + + do_not_alter_condition_codes=0; + +#ifndef I486 + end_d_registers |= ((unsigned)1<<d_reg_num (REGISTER_D7)); +#endif + + if (parallel_flag) + end_d_registers |= ((unsigned)1<<d_reg_num (REGISTER_D6)); + +#ifdef MORE_PARAMETER_REGISTERS + if (end_d_registers & ((unsigned)1<<d_reg_num (REGISTER_D2))){ + if (end_d_registers & ((unsigned)1<<d_reg_num (REGISTER_D3))) + end_a_registers |= ((unsigned)1<<a_reg_num (REGISTER_A0)) | ((unsigned)1<<a_reg_num (REGISTER_A1)); + else + end_a_registers |= ((unsigned)1<<a_reg_num (REGISTER_A1)); + end_d_registers &= ~((unsigned)(2|1)<<d_reg_num (REGISTER_D2)); + } +#endif + + end_a_registers |= ((unsigned)1<<a_reg_num (A_STACK_POINTER)) | + ((unsigned)1<<a_reg_num (B_STACK_POINTER)) | +#ifndef I486 + ((unsigned)1<<a_reg_num (REGISTER_A5)) | +#endif +#ifdef G_POWER + ((unsigned)1<<a_reg_num (REGISTER_A7)) | + ((unsigned)1<<a_reg_num (REGISTER_A8)) | + ((unsigned)1<<a_reg_num (REGISTER_A9)) | + ((unsigned)1<<a_reg_num (REGISTER_A10)) | +#endif + ((unsigned)1<<a_reg_num (HEAP_POINTER)); + +#ifdef NEW_R_ALLOC + r_reg_uses_block=(struct register_use*)memory_allocate ((highest_a_register+highest_d_register) * sizeof (struct register_use)); + r_reg_uses=r_reg_uses_block+highest_a_register; + + initialize_a_register_uses (r_reg_uses,highest_a_register,end_a_registers); + initialize_register_uses (r_reg_uses,highest_d_register,end_d_registers); +#else + a_reg_uses=(struct register_use*)memory_allocate (highest_a_register * sizeof (struct register_use)); + d_reg_uses=(struct register_use*)memory_allocate (highest_d_register * sizeof (struct register_use)); + + initialize_register_uses (a_reg_uses,highest_a_register,end_a_registers); + initialize_register_uses (d_reg_uses,highest_d_register,end_d_registers); +#endif + +#if defined(NEW_R_ALLOC) && (defined(sparc) || defined (G_POWER)) + { + int max_15_and_highest_f_register; + + max_15_and_highest_f_register=highest_f_register>15 ? highest_f_register : 15; + + f_reg_uses=(struct register_use*)memory_allocate (max_15_and_highest_f_register * sizeof (struct register_use)); + initialize_register_uses (f_reg_uses,max_15_and_highest_f_register,end_f_registers); + } +#else + f_reg_uses=(struct register_use*)memory_allocate (highest_f_register * sizeof (struct register_use)); + initialize_register_uses (f_reg_uses,highest_f_register,end_f_registers); +#endif + +#ifdef I486_USE_SCRATCH_REGISTER + scratch_register_next_uses=NULL; + allocate_scratch_register=1; +#endif + + store_next_uses (last_instruction); + + initialize_register_allocation(); + + allocate_registers (basic_block); + + condition_on_stack=load_parameter_registers (end_a_registers,end_d_registers,end_f_registers,not_alter_condition_codes_flag,condition); + + memory_free (f_reg_uses); +#ifdef NEW_R_ALLOC + memory_free (r_reg_uses_block); +#else + memory_free (a_reg_uses); + memory_free (d_reg_uses); +#endif + + return condition_on_stack; +} |