summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgias.c46
-rw-r--r--cgiconst.h4
-rw-r--r--cgiwas.c77
-rw-r--r--cglin.c37
-rw-r--r--cgopt.c40
5 files changed, 173 insertions, 31 deletions
diff --git a/cgias.c b/cgias.c
index 1985533..031a372 100644
--- a/cgias.c
+++ b/cgias.c
@@ -3260,15 +3260,17 @@ static void as_3move_registers (int reg1,int reg2,int reg3,int reg4)
as_move_r_r (reg1,reg2);
}
-#ifndef THREAD32
static void as_mulud_instruction (struct instruction *instruction)
{
int reg_1,reg_2;
-
+#ifdef THREAD32
+ int reg_3;
+#endif
+
reg_1=instruction->instruction_parameters[0].parameter_data.reg.r;
reg_2=instruction->instruction_parameters[1].parameter_data.reg.r;
-#if 0
+#ifdef THREAD32
reg_3=instruction->instruction_parameters[2].parameter_data.reg.r;
if (reg_3==REGISTER_D0){
@@ -3303,12 +3305,44 @@ static void as_mulud_instruction (struct instruction *instruction)
}
return;
}
-#endif
if (reg_2==REGISTER_D0){
if (reg_1==REGISTER_A1)
as_r (0367,040,reg_1); /* mul */
else {
+ as_move_r_r (REGISTER_A1,reg_3);
+ as_r (0367,040,reg_1); /* mul */
+ as_2move_registers (reg_3,REGISTER_A1,reg_1);
+ }
+ } else if (reg_1==REGISTER_A1){
+ as_2move_registers (reg_2,REGISTER_D0,reg_3);
+ as_r (0367,040,reg_1); /* mul */
+ as_2move_registers (reg_3,REGISTER_D0,reg_2);
+ } else if (reg_1==REGISTER_D0){
+ if (reg_2==REGISTER_A1){
+ as_r (0367,040,REGISTER_A1); /* mul */
+ store_c (0x90+reg_num (REGISTER_A1)); /* xchg A1,D0 */
+ } else {
+ as_move_r_r (REGISTER_A1,reg_3);
+ as_r (0367,040,reg_2); /* mul */
+ as_3move_registers (reg_3,REGISTER_A1,REGISTER_D0,reg_2);
+ }
+ } else if (reg_2==REGISTER_A1){
+ as_2move_registers (reg_2,REGISTER_D0,reg_3);
+ as_r (0367,040,reg_1); /* mul */
+ as_3move_registers (reg_3,REGISTER_D0,REGISTER_A1,reg_1);
+ } else {
+ store_c (0x90+reg_num (reg_2)); /* xchg reg_2,D0 */
+ as_move_r_r (REGISTER_A1,reg_3);
+ as_r (0367,040,reg_1); /* mul */
+ store_c (0x90+reg_num (reg_2)); /* xchg reg_2,D0 */
+ as_2move_registers (reg_3,REGISTER_A1,reg_1);
+ }
+#else
+ if (reg_2==REGISTER_D0){
+ if (reg_1==REGISTER_A1)
+ as_r (0367,040,reg_1); /* mul */
+ else {
as_move_r_r (REGISTER_A1,REGISTER_O0);
as_r (0367,040,reg_1); /* mul */
as_2move_registers (REGISTER_O0,REGISTER_A1,reg_1);
@@ -3337,8 +3371,8 @@ static void as_mulud_instruction (struct instruction *instruction)
store_c (0x90+reg_num (reg_2)); /* xchg reg_2,D0 */
as_2move_registers (REGISTER_O0,REGISTER_A1,reg_1);
}
-}
#endif
+}
static void as_xchg_eax_r (int reg_1)
{
@@ -5559,10 +5593,10 @@ static void as_instructions (struct instruction *instruction)
case ISBB:
as_sbb_instruction (instruction);
break;
-#ifndef THREAD32
case IMULUD:
as_mulud_instruction (instruction);
break;
+#ifndef THREAD32
case IDIVDU:
as_divdu_instruction (instruction);
break;
diff --git a/cgiconst.h b/cgiconst.h
index 0370853..a4e2ad2 100644
--- a/cgiconst.h
+++ b/cgiconst.h
@@ -68,9 +68,9 @@ enum {
#endif
#if defined (I486)
,IADC ,ISBB, IRTSI
- ,IDIVI, IREMI, IREMU, IFLOORDIV, IMOD
+ ,IDIVI, IREMI, IREMU, IFLOORDIV, IMOD, IMULUD
# ifndef THREAD32
- ,IMULUD, IDIVDU
+ ,IDIVDU
# endif
,IFLOADS, IFMOVES
#endif
diff --git a/cgiwas.c b/cgiwas.c
index 3248c76..a021ed8 100644
--- a/cgiwas.c
+++ b/cgiwas.c
@@ -2901,14 +2901,85 @@ static void w_as_3movl_registers (int reg1,int reg2,int reg3,int reg4)
w_as_movl_register_register_newline (reg1,reg2);
}
-#ifndef THREAD32
static void w_as_mulud_instruction (struct instruction *instruction)
{
int reg_1,reg_2;
+#ifdef THREAD32
+ int reg_3;
+#endif
reg_1=instruction->instruction_parameters[0].parameter_data.reg.r;
reg_2=instruction->instruction_parameters[1].parameter_data.reg.r;
+#ifdef THREAD32
+ reg_3=instruction->instruction_parameters[2].parameter_data.reg.r;
+
+ if (reg_3==REGISTER_D0){
+ if (reg_1==REGISTER_A1){
+ w_as_movl_register_register_newline (reg_2,REGISTER_D0);
+ w_as_opcode_register_newline ("mul",reg_1);
+ w_as_movl_register_register_newline (REGISTER_D0,reg_2);
+ } else if (reg_2==REGISTER_A1){
+ w_as_movl_register_register_newline (reg_2,REGISTER_D0);
+ w_as_opcode_register_newline ("mul",reg_1);
+ w_as_2movl_registers (REGISTER_D0,REGISTER_A1,reg_1);
+ } else {
+ w_as_2movl_registers (REGISTER_A1,reg_2,REGISTER_D0);
+ w_as_opcode_register_newline ("mul",reg_1);
+ w_as_3movl_registers (REGISTER_D0,reg_2,REGISTER_A1,reg_1);
+ }
+ return;
+ }
+
+ if (reg_3==REGISTER_A1){
+ if (reg_2==REGISTER_D0){
+ w_as_opcode_register_newline ("mul",reg_1);
+ w_as_movl_register_register_newline (REGISTER_A1,reg_1);
+ } else if (reg_1==REGISTER_D0){
+ w_as_opcode_register_newline ("mul",reg_2);
+ w_as_2movl_registers (REGISTER_A1,REGISTER_D0,reg_2);
+ } else {
+ w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_D0);
+ w_as_opcode_register_newline ("mul",reg_1);
+ w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_D0);
+ w_as_movl_register_register_newline (REGISTER_A1,reg_1);
+ }
+ return;
+ }
+
+ if (reg_2==REGISTER_D0){
+ if (reg_1==REGISTER_A1){
+ w_as_opcode_register_newline ("mul",reg_1);
+ } else {
+ w_as_movl_register_register_newline (REGISTER_A1,reg_3);
+ w_as_opcode_register_newline ("mul",reg_1);
+ w_as_2movl_registers (reg_3,REGISTER_A1,reg_1);
+ }
+ } else if (reg_1==REGISTER_A1){
+ w_as_2movl_registers (reg_2,REGISTER_D0,reg_3);
+ w_as_opcode_register_newline ("mul",reg_1);
+ w_as_2movl_registers (reg_3,REGISTER_D0,reg_2);
+ } else if (reg_1==REGISTER_D0){
+ if (reg_2==REGISTER_A1){
+ w_as_opcode_register_newline ("mul",REGISTER_A1);
+ w_as_opcode_register_register_newline ("xchg",REGISTER_A1,REGISTER_D0);
+ } else {
+ w_as_movl_register_register_newline (REGISTER_A1,reg_3);
+ w_as_opcode_register_newline ("mul",reg_2);
+ w_as_3movl_registers (reg_3,REGISTER_A1,REGISTER_D0,reg_2);
+ }
+ } else if (reg_2==REGISTER_A1){
+ w_as_2movl_registers (reg_2,REGISTER_D0,reg_3);
+ w_as_opcode_register_newline ("mul",reg_1);
+ w_as_3movl_registers (reg_3,REGISTER_D0,REGISTER_A1,reg_1);
+ } else {
+ w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_D0);
+ w_as_movl_register_register_newline (REGISTER_A1,reg_3);
+ w_as_opcode_register_newline ("mul",reg_1);
+ w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_D0);
+ w_as_2movl_registers (reg_3,REGISTER_A1,reg_1);
+ }
+#else
if (reg_2==REGISTER_D0){
if (reg_1==REGISTER_A1){
w_as_opcode_register_newline ("mul",reg_1);
@@ -2941,8 +3012,10 @@ static void w_as_mulud_instruction (struct instruction *instruction)
w_as_opcode_register_register_newline ("xchg",reg_2,REGISTER_D0);
w_as_2movl_registers (REGISTER_O0,REGISTER_A1,reg_1);
}
+#endif
}
+#ifndef THREAD32
static void w_as_divdu_instruction (struct instruction *instruction)
{
int reg_1,reg_2,reg_3;
@@ -4762,10 +4835,10 @@ static void w_as_instructions (register struct instruction *instruction)
case ISBB:
w_as_dyadic_instruction (instruction,intel_asm ? "sbb" : "sbbl");
break;
-#ifndef THREAD32
case IMULUD:
w_as_mulud_instruction (instruction);
break;
+#ifndef THREAD32
case IDIVDU:
w_as_divdu_instruction (instruction);
break;
diff --git a/cglin.c b/cglin.c
index 0ca5605..ab9f7c2 100644
--- a/cglin.c
+++ b/cglin.c
@@ -1807,18 +1807,31 @@ void i_movew_r_pd (int register_1,int register_2)
}
#endif
-#if defined (I486) && !defined (THREAD32)
+#ifdef I486
+# ifdef THREAD32
+void i_mulud_r_r_r (int register_1,int register_2,int register_3)
+# else
void i_mulud_r_r (int register_1,int register_2)
+#endif
{
struct instruction *instruction;
+# ifdef THREAD32
+ instruction=i_new_instruction3 (IMULUD);
+# else
instruction=i_new_instruction2 (IMULUD);
+# endif
S2 (instruction->instruction_parameters[0], parameter_type=P_REGISTER,
parameter_data.i=register_1);
-
+
S2 (instruction->instruction_parameters[1], parameter_type=P_REGISTER,
parameter_data.i=register_2);
+
+# ifdef THREAD32
+ S2 (instruction->instruction_parameters[2], parameter_type=P_REGISTER,
+ parameter_data.i=register_3);
+# endif
}
#endif
@@ -4381,7 +4394,6 @@ static void linearize_two_results_operator (INSTRUCTION_GRAPH result_graph,ADDRE
graph=result_graph->instruction_parameters[0].p;
-#ifndef THREAD32
if (graph->instruction_code==GMULUD){
INSTRUCTION_GRAPH graph_1,graph_2;
@@ -4401,8 +4413,25 @@ static void linearize_two_results_operator (INSTRUCTION_GRAPH result_graph,ADDRE
reg_1=ad_1.ad_register;
reg_2=ad_2.ad_register;
+# ifdef THREAD32
+ {
+ int tmp_reg;
+
+ if (try_allocate_register_number (REGISTER_D0))
+ tmp_reg=REGISTER_D0;
+ else if (try_allocate_register_number (REGISTER_A1))
+ tmp_reg=REGISTER_A1;
+ else
+ tmp_reg=get_dregister();
+ i_mulud_r_r_r (reg_1,reg_2,tmp_reg);
+ free_register (tmp_reg);
+ }
+# else
i_mulud_r_r (reg_1,reg_2);
- } else if (graph->instruction_code==GDIVDU){
+# endif
+ } else
+#ifndef THREAD32
+ if (graph->instruction_code==GDIVDU){
ADDRESS ad_3;
linearize_3_graphs (graph->instruction_parameters[0].p,&ad_1,
diff --git a/cgopt.c b/cgopt.c
index d343bc4..fe784ed 100644
--- a/cgopt.c
+++ b/cgopt.c
@@ -421,9 +421,9 @@ static int get_argument_size (int instruction_code)
IF_G_RISC (case IADDI: case ILSLI:)
IF_G_SPARC (case IADDO: case ISUBO: )
#ifdef I486
- case IDIVI: case IREMI: case IREMU:
+ case IDIVI: case IREMI: case IREMU: case IMULUD:
# ifndef THREAD32
- case IMULUD: case IDIVDU:
+ case IDIVDU:
# endif
case IFLOORDIV: case IMOD:
#endif
@@ -497,18 +497,18 @@ static void insert_decrement_b_stack_pointer (struct instruction *next_instructi
instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+2*sizeof (struct parameter));
instruction->instruction_arity=2;
-#ifdef M68000
+# ifdef M68000
instruction->instruction_icode=ISUB;
instruction->instruction_parameters[0].parameter_type=P_IMMEDIATE;
instruction->instruction_parameters[0].parameter_data.i=offset;
-#else
+# 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
+# endif
instruction->instruction_parameters[1].parameter_type=P_REGISTER;
instruction->instruction_parameters[1].parameter_data.i=B_STACK_POINTER;
@@ -680,6 +680,7 @@ static void compute_maximum_b_stack_offsets (register int b_offset)
# ifdef THREAD32
instruction->instruction_icode!=IDIV &&
instruction->instruction_icode!=IDIVU &&
+ instruction->instruction_icode!=IMULUD &&
# endif
instruction->instruction_icode!=IDIVI &&
instruction->instruction_icode!=IREMI &&
@@ -929,6 +930,7 @@ void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_off
# ifdef THREAD32
instruction->instruction_icode!=IDIV &&
instruction->instruction_icode!=IDIVU &&
+ instruction->instruction_icode!=IMULUD &&
# endif
instruction->instruction_icode!=IDIVI &&
instruction->instruction_icode!=IREMI &&
@@ -1561,7 +1563,7 @@ static void store_next_uses (struct instruction *instruction)
case IROTL: case IROTR:
# endif
#endif
-#if defined (I486) && !defined (I486_USE_SCRATCH_REGISTER)
+#if defined (I486) && !defined (I486_USE_SCRATCH_REGISTER) && !defined (THREAD32)
case IMULUD:
#endif
#if (defined (I486) && !defined (I486_USE_SCRATCH_REGISTER)) || defined (G_POWER)
@@ -1593,20 +1595,17 @@ IF_G_POWER ( case IUMULH: )
use_parameter (&instruction->instruction_parameters[1]);
use_parameter (&instruction->instruction_parameters[0]);
break;
- case IDIV: case IREM: case IDIVU: case IREMU:
-# ifdef THREAD32
+ case IDIV: case IREM: case IDIVU: case IREMU: case IMULUD:
+# ifdef THREAD32
use_parameter (&instruction->instruction_parameters[1]);
use_parameter (&instruction->instruction_parameters[0]);
define_parameter (&instruction->instruction_parameters[2]);
- break;
-# endif
-# ifndef THREAD32
- case IMULUD:
+# else
define_scratch_register();
use_parameter (&instruction->instruction_parameters[1]);
use_parameter (&instruction->instruction_parameters[0]);
- break;
# endif
+ break;
case IMOVE:
if ((instruction->instruction_parameters[0].parameter_type==P_INDIRECT ||
instruction->instruction_parameters[0].parameter_type==P_INDEXED) &&
@@ -4041,14 +4040,21 @@ IF_G_RISC (case IADDI: case ILSLI:)
case IEXG:
instruction_usedef_usedef (instruction);
break;
-#if defined (I486) && !defined (THREAD32)
+#if defined (I486)
case IMULUD:
-# ifdef I486_USE_SCRATCH_REGISTER
+# ifdef THREAD32
+ use_3_same_type_registers
+ (&instruction->instruction_parameters[0].parameter_data.reg,USE_DEF,
+ &instruction->instruction_parameters[1].parameter_data.reg,USE_DEF,
+ &instruction->instruction_parameters[2].parameter_data.reg,DEF,D_REGISTER);
+# else
+# ifdef I486_USE_SCRATCH_REGISTER
use_scratch_register();
-# endif
+# endif
instruction_usedef_usedef (instruction);
-# ifdef I486_USE_SCRATCH_REGISTER
+# ifdef I486_USE_SCRATCH_REGISTER
allocate_scratch_register=1;
+# endif
# endif
break;
#endif