summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgias.c224
-rw-r--r--cgias.h34
-rw-r--r--cgiconst.h66
-rw-r--r--cgiwas.c423
-rw-r--r--cglin.c29
-rw-r--r--cgopt.c3949
6 files changed, 4592 insertions, 133 deletions
diff --git a/cgias.c b/cgias.c
index c441505..ac6c7a5 100644
--- a/cgias.c
+++ b/cgias.c
@@ -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;
diff --git a/cgias.h b/cgias.h
new file mode 100644
index 0000000..2124a5f
--- /dev/null
+++ b/cgias.h
@@ -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
+};
diff --git a/cgiwas.c b/cgiwas.c
index 2075c32..16165a5 100644
--- a/cgiwas.c
+++ b/cgiwas.c
@@ -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;
diff --git a/cglin.c b/cglin.c
index 5f7092e..5a6cdf1 100644
--- a/cglin.c
+++ b/cglin.c
@@ -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;
diff --git a/cgopt.c b/cgopt.c
new file mode 100644
index 0000000..8e7b52a
--- /dev/null
+++ b/cgopt.c
@@ -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;
+}