summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn van Groningen2004-07-12 14:26:40 +0000
committerJohn van Groningen2004-07-12 14:26:40 +0000
commit5fd3638b200ddd7c901449347ae3b003bb31683b (patch)
treef7ea535d8601c15d5e3ba52290226f4bab849200
parentuse transition vector for calling functions with ccall "F" (diff)
add absR, negI, unsigned compare, divU, remU and faster not
instructions for IA32 add loop optimization code (speeds up jmp to a cmp and branch instruction), not yet enabled
-rw-r--r--cg.tgt260
-rw-r--r--cg.wpj10
-rw-r--r--cgcalc.c60
-rw-r--r--cgcode.c96
-rw-r--r--cgcodep.h18
-rw-r--r--cgconst.h30
-rw-r--r--cgias.c177
-rw-r--r--cgiconst.h23
-rw-r--r--cginput.c18
-rw-r--r--cgiwas.c174
-rw-r--r--cglin.c127
-rw-r--r--cgopt.c287
-rw-r--r--cgstack.c34
-rw-r--r--cgtypes.h5
14 files changed, 982 insertions, 337 deletions
diff --git a/cg.tgt b/cg.tgt
index 97afdfc..37d402c 100644
--- a/cg.tgt
+++ b/cg.tgt
@@ -12,7 +12,7 @@ NEXE
3
WString
5
-nc2e9
+nc2en
1
0
0
@@ -32,7 +32,7 @@ WString
NEXE
8
WVList
-11
+9
9
MVState
10
@@ -70,9 +70,9 @@ WINLINK
18
WString
24
-?????Case sensitive link
-1
+?????Produce symbol file
1
+0
19
MCState
20
@@ -82,9 +82,9 @@ WINLINK
21
WString
24
-?????Produce symbol file
+?????Eliminate dead code
+1
1
-0
22
MCState
23
@@ -94,9 +94,9 @@ WINLINK
24
WString
24
-?????Eliminate dead code
-1
-1
+?????Incremental Linking
+0
+0
25
MVState
26
@@ -134,9 +134,9 @@ WINLINK
34
WString
24
-?????Case sensitive link
+?????Produce symbol file
+0
0
-1
35
MCState
36
@@ -146,433 +146,409 @@ WINLINK
37
WString
24
-?????Produce symbol file
-0
-0
-38
-MRState
-39
-WString
-7
-WINLINK
-40
-WString
-19
-nc???Character mode
-0
-1
-41
-MCState
-42
-WString
-7
-WINLINK
-43
-WString
-24
?????Eliminate dead code
0
1
-44
+38
WVList
3
-45
+39
ActionStates
-46
+40
WString
6
&Debug
-47
+41
WVList
0
-48
+42
ActionStates
-49
+43
WString
7
Sam&ple
-50
+44
WVList
0
-51
+45
ActionStates
-52
+46
WString
4
&Run
-53
+47
WVList
0
-1
1
1
0
-54
+48
WPickList
11
-55
+49
MItem
3
*.c
-56
+50
WString
4
COBJ
-57
+51
WVList
13
-58
+52
MVState
-59
+53
WString
3
WCC
-60
+54
WString
23
?????Macro definitions:
1
-61
+55
WString
14
_WINDOWS_ I486
0
-62
+56
MCState
-63
+57
WString
3
WCC
-64
+58
WString
33
?????Disable stack depth checking
0
1
-65
+59
MVState
-66
+60
WString
3
WCC
-67
+61
WString
23
?????Macro definitions:
0
-68
+62
WString
14
_WINDOWS_ I486
0
-69
+63
MRState
-70
+64
WString
3
WCC
-71
+65
WString
20
?????Pack structures
0
0
-72
+66
MRState
-73
+67
WString
3
WCC
-74
+68
WString
21
?????4 byte alignment
0
1
-75
+69
MRState
-76
+70
WString
3
WCC
-77
+71
WString
23
?????Time optimizations
0
1
-78
+72
MRState
-79
+73
WString
3
WCC
-80
+74
WString
26
?????Fastest possible code
0
0
-81
+75
MCState
-82
+76
WString
3
WCC
-83
+77
WString
23
?????Loop optimizations
0
1
-84
+78
MCState
-85
+79
WString
3
WCC
-86
+80
WString
30
?????Call/return optimizations
0
1
-87
+81
MCState
-88
+82
WString
3
WCC
-89
+83
WString
32
?????In-line intrinsic functions
0
1
-90
+84
MCState
-91
+85
WString
3
WCC
-92
+86
WString
27
?????Instruction scheduling
0
1
-93
+87
MVState
-94
+88
WString
3
WCC
-95
+89
WString
29
?????Expand function in-line:
0
-96
+90
WString
2
20
1
-97
+91
MCState
-98
+92
WString
3
WCC
-99
+93
WString
35
?????Put functions in separate segs
0
1
-100
+94
WVList
0
-1
1
1
0
-101
+95
MItem
4
cg.c
-102
+96
WString
4
COBJ
-103
+97
WVList
0
-104
+98
WVList
0
-55
+49
1
1
0
-105
+99
MItem
8
cgcalc.c
-106
+100
WString
4
COBJ
-107
+101
WVList
0
-108
+102
WVList
0
-55
+49
1
1
0
-109
+103
MItem
8
cgcode.c
-110
+104
WString
4
COBJ
-111
+105
WVList
0
-112
+106
WVList
0
-55
+49
1
1
0
-113
+107
MItem
7
cgias.c
-114
+108
WString
4
COBJ
-115
+109
WVList
0
-116
+110
WVList
0
-55
+49
1
1
0
-117
+111
MItem
9
cginput.c
-118
+112
WString
4
COBJ
-119
+113
WVList
0
-120
+114
WVList
0
-55
+49
1
1
0
-121
+115
MItem
16
cginstructions.c
-122
+116
WString
4
COBJ
-123
+117
WVList
0
-124
+118
WVList
0
-55
+49
1
1
0
-125
+119
MItem
8
cgiwas.c
-126
+120
WString
4
COBJ
-127
+121
WVList
0
-128
+122
WVList
0
-55
+49
1
1
0
-129
+123
MItem
7
cglin.c
-130
+124
WString
4
COBJ
-131
+125
WVList
0
-132
+126
WVList
0
-55
+49
1
1
0
-133
+127
MItem
7
cgopt.c
-134
+128
WString
4
COBJ
-135
+129
WVList
0
-136
+130
WVList
0
-55
+49
1
1
0
-137
+131
MItem
9
cgstack.c
-138
+132
WString
4
COBJ
-139
+133
WVList
0
-140
+134
WVList
0
-55
+49
1
1
0
diff --git a/cg.wpj b/cg.wpj
index 7375ef3..eac38c7 100644
--- a/cg.wpj
+++ b/cg.wpj
@@ -4,10 +4,10 @@ projectIdent
VpeMain
1
WRect
-560
-1054
+1475
+1410
7680
-6411
+6400
2
MProject
3
@@ -38,6 +38,6 @@ WRect
WFileName
6
cg.tgt
-1
-1
+0
+9
7
diff --git a/cgcalc.c b/cgcalc.c
index 771457b..73b0504 100644
--- a/cgcalc.c
+++ b/cgcalc.c
@@ -571,7 +571,7 @@ static void calculate_dyadic_non_commutative_data_operator (INSTRUCTION_GRAPH gr
return;
}
-static void calculate_mod_operator (INSTRUCTION_GRAPH graph)
+static void calculate_rem_operator (INSTRUCTION_GRAPH graph)
{
register INSTRUCTION_GRAPH graph_1,graph_2;
int i_aregs,i_dregs;
@@ -2264,8 +2264,10 @@ void calculate_graph_register_uses (INSTRUCTION_GRAPH graph)
calculate_dyadic_commutative_data_operator (graph);
return;
case GCMP_EQ:
- case GCMP_LT:
case GCMP_GT:
+ case GCMP_GTU:
+ case GCMP_LT:
+ case GCMP_LTU:
calculate_compare_operator (graph);
return;
case GSUB:
@@ -2273,10 +2275,16 @@ void calculate_graph_register_uses (INSTRUCTION_GRAPH graph)
calculate_dyadic_non_commutative_operator (graph);
return;
case GDIV:
+#ifdef I486
+ case GDIVU:
+#endif
calculate_dyadic_non_commutative_data_operator (graph);
return;
case GMOD:
- calculate_mod_operator (graph);
+#ifdef I486
+ case GREMU:
+#endif
+ calculate_rem_operator (graph);
return;
case GLSL:
case GLSR:
@@ -2299,6 +2307,10 @@ void calculate_graph_register_uses (INSTRUCTION_GRAPH graph)
calculate_eor_operator (graph);
return;
case GCNOT:
+#ifdef I486
+ case GNEG:
+ case GNOT:
+#endif
calculate_cnot_operator (graph);
return;
case GMOVEMI:
@@ -2330,6 +2342,9 @@ void calculate_graph_register_uses (INSTRUCTION_GRAPH graph)
case GFEXP:
case GFSQRT:
case GFNEG:
+#ifdef I486
+ case GFABS:
+#endif
calculate_monadic_float_operator (graph);
return;
case GFLOAD_ID:
@@ -2468,8 +2483,13 @@ void count_graph (INSTRUCTION_GRAPH graph)
case GAND:
case GCMP_EQ:
case GCMP_GT:
+ case GCMP_GTU:
case GCMP_LT:
+ case GCMP_LTU:
case GDIV:
+#ifdef I486
+ case GDIVU:
+#endif
case GFADD:
case GFCMP_EQ:
case GFCMP_GT:
@@ -2482,6 +2502,9 @@ void count_graph (INSTRUCTION_GRAPH graph)
case GLSL:
case GLSR:
case GMOD:
+#ifdef I486
+ case GREMU:
+#endif
case GMUL:
case GMUL_O:
case GOR:
@@ -2515,6 +2538,11 @@ void count_graph (INSTRUCTION_GRAPH graph)
case GFEXP:
case GFSQRT:
case GFNEG:
+#ifdef I486
+ case GFABS:
+ case GNEG:
+ case GNOT:
+#endif
case GBEFORE0:
case GTEST_O:
if (++graph->node_count==1)
@@ -2620,8 +2648,13 @@ void mark_graph_2 (register INSTRUCTION_GRAPH graph)
case GAND:
case GCMP_EQ:
case GCMP_GT:
+ case GCMP_GTU:
case GCMP_LT:
+ case GCMP_LTU:
case GDIV:
+#ifdef I486
+ case GDIVU:
+#endif
case GFADD:
case GFCMP_EQ:
case GFCMP_GT:
@@ -2634,6 +2667,9 @@ void mark_graph_2 (register INSTRUCTION_GRAPH graph)
case GLSL:
case GLSR:
case GMOD:
+#ifdef I486
+ case GREMU:
+#endif
case GMUL:
case GMUL_O:
case GOR:
@@ -2668,6 +2704,11 @@ void mark_graph_2 (register INSTRUCTION_GRAPH graph)
case GFEXP:
case GFSQRT:
case GFNEG:
+#ifdef I486
+ case GFABS:
+ case GNEG:
+ case GNOT:
+#endif
case GBEFORE0:
case GTEST_O:
if (graph->node_mark<2){
@@ -2787,8 +2828,13 @@ void mark_graph_1 (register INSTRUCTION_GRAPH graph)
case GAND:
case GCMP_EQ:
case GCMP_GT:
+ case GCMP_GTU:
case GCMP_LT:
+ case GCMP_LTU:
case GDIV:
+#ifdef I486
+ case GDIVU:
+#endif
case GFADD:
case GFCMP_EQ:
case GFCMP_GT:
@@ -2801,6 +2847,9 @@ void mark_graph_1 (register INSTRUCTION_GRAPH graph)
case GLSL:
case GLSR:
case GMOD:
+#ifdef I486
+ case GREMU:
+#endif
case GMUL:
case GMUL_O:
case GOR:
@@ -2833,6 +2882,11 @@ void mark_graph_1 (register INSTRUCTION_GRAPH graph)
case GFEXP:
case GFSQRT:
case GFNEG:
+#ifdef I486
+ case GFABS:
+ case GNEG:
+ case GNOT:
+#endif
case GBEFORE0:
case GTEST_O:
if (!graph->node_mark){
diff --git a/cgcode.c b/cgcode.c
index 4e6dd24..80844fc 100644
--- a/cgcode.c
+++ b/cgcode.c
@@ -158,9 +158,18 @@ int no_time_profiling;
#define g_bounds(g1,g2) g_instruction_2(GBOUNDS,(g1),(g2))
#define g_cmp_eq(g1,g2) g_instruction_2(GCMP_EQ,(g1),(g2))
#define g_cmp_gt(g1,g2) g_instruction_2(GCMP_GT,(g1),(g2))
+#ifdef I486
+# define g_cmp_gtu(g1,g2) g_instruction_2(GCMP_GTU,(g1),(g2))
+#endif
#define g_cmp_lt(g1,g2) g_instruction_2(GCMP_LT,(g1),(g2))
+#ifdef I486
+# define g_cmp_ltu(g1,g2) g_instruction_2(GCMP_LTU,(g1),(g2))
+#endif
#define g_cnot(g1) g_instruction_1(GCNOT,(g1))
#define g_div(g1,g2) g_instruction_2(GDIV,(g1),(g2))
+#ifdef I486
+# define g_divu(g1,g2) g_instruction_2(GDIVU,(g1),(g2))
+#endif
#define g_eor(g1,g2) g_instruction_2(GEOR,(g1),(g2))
#define g_fadd(g1,g2) g_instruction_2(GFADD,(g1),(g2))
#define g_fcmp_eq(g1,g2) g_instruction_2(GFCMP_EQ,(g1),(g2))
@@ -179,7 +188,14 @@ int no_time_profiling;
#define g_lsl(g1,g2) g_instruction_2(GLSL,(g1),(g2))
#define g_lsr(g1,g2) g_instruction_2(GLSR,(g1),(g2))
#define g_mod(g1,g2) g_instruction_2(GMOD,(g1),(g2))
+#ifdef I486
+# define g_remu(g1,g2) g_instruction_2(GREMU,(g1),(g2))
+#endif
#define g_mul(g1,g2) g_instruction_2(GMUL,(g1),(g2))
+#ifdef I486
+# define g_neg(g1) g_instruction_1(GNEG,(g1))
+# define g_not(g1) g_instruction_1(GNOT,(g1))
+#endif
#define g_or(g1,g2) g_instruction_2(GOR,(g1),(g2))
#define g_keep(g1,g2) g_instruction_2(GKEEP,(g1),(g2))
#define g_fkeep(g1,g2) g_instruction_2(GFKEEP,(g1),(g2))
@@ -243,7 +259,7 @@ LABEL *eval_fill_label,*eval_upd_labels[33];
static LABEL *print_r_arg_label,*push_t_r_args_label,*push_a_r_args_label;
LABEL *index_error_label;
-#ifdef G_POWER
+#if defined (G_POWER) || defined (I486)
LABEL *r_to_i_buffer_label;
#endif
@@ -435,6 +451,13 @@ static void code_dyadic_sane_operator (LABEL *label)
#endif
}
+#ifdef I486
+void code_absR (void)
+{
+ code_monadic_real_operator (GFABS);
+}
+#endif
+
void code_acosR (VOID)
{
#ifdef M68000
@@ -1770,6 +1793,18 @@ void code_divR (VOID)
#endif
}
+#ifdef I486
+void code_divU (VOID)
+{
+ INSTRUCTION_GRAPH graph_1,graph_2,graph_3;
+
+ graph_1=s_pop_b();
+ graph_2=s_get_b (0);
+ graph_3=g_divu (graph_2,graph_1);
+ s_put_b (0,graph_3);
+}
+#endif
+
void code_entierR (VOID)
{
if (entier_real_label==NULL)
@@ -3237,6 +3272,19 @@ void code_gtR (VOID)
#endif
}
+#ifdef I486
+void code_gtU (VOID)
+{
+ INSTRUCTION_GRAPH graph_1,graph_2,graph_3;
+
+ graph_1=s_pop_b();
+ graph_2=s_get_b (0);
+ graph_3=g_cmp_gtu (graph_2,graph_1);
+
+ s_put_b (0,graph_3);
+}
+#endif
+
void code_halt (VOID)
{
if (halt_label==NULL)
@@ -4021,6 +4069,19 @@ void code_ltR (VOID)
#endif
}
+#ifdef I486
+void code_ltU (VOID)
+{
+ INSTRUCTION_GRAPH graph_1,graph_2,graph_3;
+
+ graph_1=s_pop_b();
+ graph_2=s_get_b (0);
+ graph_3=g_cmp_ltu (graph_2,graph_1);
+
+ s_put_b (0,graph_3);
+}
+#endif
+
void code_remI (VOID)
{
#ifdef M68000
@@ -4052,6 +4113,18 @@ void code_remI (VOID)
#endif
}
+#ifdef I486
+void code_remU (VOID)
+{
+ INSTRUCTION_GRAPH graph_1,graph_2,graph_3;
+
+ graph_1=s_pop_b();
+ graph_2=s_get_b (0);
+ graph_3=g_remu (graph_2,graph_1);
+ s_put_b (0,graph_3);
+}
+#endif
+
static INSTRUCTION_GRAPH multiply_by_constant (unsigned int n,INSTRUCTION_GRAPH graph_1)
{
INSTRUCTION_GRAPH graph_2;
@@ -4264,6 +4337,18 @@ void code_nu (int a_size,int b_size,char *descriptor_name,char *ea_label_name)
last_block->block_ea_label=NULL;
}
+#ifdef I486
+void code_negI (void)
+{
+ INSTRUCTION_GRAPH graph_1,graph_2;
+
+ graph_1=s_get_b (0);
+ graph_2=g_neg (graph_1);
+
+ s_put_b (0,graph_2);
+}
+#endif
+
void code_negR (void)
{
#ifdef M68000
@@ -4296,9 +4381,12 @@ void code_not (VOID)
INSTRUCTION_GRAPH graph_1,graph_2,graph_3;
graph_1=s_get_b (0);
+#ifdef I486
+ graph_3=g_not (graph_1);
+#else
graph_2=g_load_i (-1);
graph_3=g_eor (graph_2,graph_1);
-
+#endif
s_put_b (0,graph_3);
}
@@ -6200,7 +6288,7 @@ void code_RtoI (VOID)
{
INSTRUCTION_GRAPH graph_1,graph_2,graph_3,graph_4;
-#ifdef G_POWER
+#if defined (G_POWER) || defined (I486)
if (r_to_i_buffer_label==NULL)
r_to_i_buffer_label=enter_label ("r_to_i_buffer",IMPORT_LABEL);
@@ -8435,7 +8523,7 @@ void initialize_coding (VOID)
sqrt_real=NULL;
#endif
-#ifdef G_POWER
+#if defined (G_POWER) || defined (I486)
r_to_i_buffer_label=NULL;
#endif
diff --git a/cgcodep.h b/cgcodep.h
index ad18364..a54569e 100644
--- a/cgcodep.h
+++ b/cgcodep.h
@@ -15,6 +15,9 @@
# define ULONG unsigned long
#endif
+#ifdef I486
+void code_absR (void);
+#endif
void code_acosR (VOID);
void code_add_args (int source_offset,int n_arguments,int destination_offset);
void code_addI (VOID);
@@ -62,6 +65,9 @@ void code_decI (VOID);
void code_del_args (int source_offset,int n_arguments,int destination_offset);
void code_divI (VOID);
void code_divR (VOID);
+#ifdef I486
+ void code_divU (VOID);
+#endif
void code_entierR (VOID);
void code_eqB (VOID);
void code_eqB_a (int value,int a_offset);
@@ -112,6 +118,9 @@ void code_get_node_arity (int a_offset);
void code_gtC (VOID);
void code_gtI (VOID);
void code_gtR (VOID);
+#ifdef I486
+void code_gtU (VOID);
+#endif
void code_halt (VOID);
void code_in (char parameters[]);
void code_incI (VOID);
@@ -132,12 +141,21 @@ void code_log10R (VOID);
void code_ltC (VOID);
void code_ltI (VOID);
void code_ltR (VOID);
+#ifdef I486
+void code_ltU (VOID);
+#endif
void code_remI (VOID);
+#ifdef I486
+ void code_remU (VOID);
+#endif
void code_mulI (VOID);
#ifndef M68000
void code_mulIo (VOID);
#endif
void code_mulR (VOID);
+#ifdef I486
+void code_negI (void);
+#endif
void code_negR (VOID);
void code_new_ext_reducer (char descriptor_name[],int a_offset);
void code_new_int_reducer (char label_name[],int a_offset);
diff --git a/cgconst.h b/cgconst.h
index 2553b8c..35644e6 100644
--- a/cgconst.h
+++ b/cgconst.h
@@ -1,22 +1,26 @@
enum {
GADD, GADD_O, GAND, GALLOCATE, GASR, GBEFORE,
- GBEFORE0, GBOUNDS, GCMP_EQ, GCMP_GT, GCMP_LT, GCNOT,
- GCOPY, GCREATE, GCREATE_R, GDIV, GEOR,
- GFACOS, GFADD, GFASIN, GFCMP_EQ, GFCMP_GT, GFATAN,
- GFCMP_LT, GFCOS, GFDIV, GFEXP, GFHIGH, GFITOR,
- GFJOIN, GFKEEP, GFLN, GFLOAD, GFLOAD_I, GFLOAD_ID,
- GFLOAD_X, GFLOG10, GFLOW, GFMOVEMI, GFMUL, GFNEG,
- GFREM, GFRTOI, GFSIN, GFSUB, GFILL, GFILL_R,
- GFREGISTER, GFSQRT, GFSTORE, GFSTORE_R, GFSTORE_X, GFTAN,
- GGFREGISTER, GGREGISTER, GKEEP, GINDIRECTION, GLEA, GLOAD,
- GLOAD_I, GLOAD_ID, GLOAD_X, GLOAD_B_ID, GLOAD_B_X, GLOAD_DES_ID,
- GLOAD_DES_I, GLSL, GLSR, GMOD, GMOVEM, GMOVEMI,
- GMUL, GMUL_O, GOR, GREGISTER, GSTORE, GSTORE_R,
- GSTORE_B_X, GSTORE_X, GSUB, GSUB_O, GTEST_O, GEXIT_IF
+ GBEFORE0, GBOUNDS, GCMP_EQ, GCMP_GT, GCMP_GTU, GCMP_LT,
+ GCMP_LTU, GCNOT, GCOPY, GCREATE, GCREATE_R, GDIV,
+ GEOR, GFACOS, GFADD, GFASIN, GFCMP_EQ, GFCMP_GT,
+ GFATAN, GFCMP_LT, GFCOS, GFDIV, GFEXP, GFHIGH,
+ GFITOR, GFJOIN, GFKEEP, GFLN, GFLOAD, GFLOAD_I,
+ GFLOAD_ID, GFLOAD_X, GFLOG10, GFLOW, GFMOVEMI, GFMUL,
+ GFNEG, GFREM, GFRTOI, GFSIN, GFSUB, GFILL,
+ GFILL_R, GFREGISTER, GFSQRT, GFSTORE, GFSTORE_R, GFSTORE_X,
+ GFTAN, GGFREGISTER, GGREGISTER, GKEEP, GINDIRECTION, GLEA,
+ GLOAD, GLOAD_I, GLOAD_ID, GLOAD_X, GLOAD_B_ID, GLOAD_B_X,
+ GLOAD_DES_ID, GLOAD_DES_I, GLSL, GLSR, GMOD, GMOVEM,
+ GMOVEMI, GMUL, GMUL_O, GOR, GREGISTER, GSTORE,
+ GSTORE_R, GSTORE_B_X, GSTORE_X, GSUB, GSUB_O, GTEST_O,
+ GEXIT_IF
#ifdef G_POWER
,GCREATE_S, GUMULH
#endif
+#ifdef I486
+ ,GDIVU, GREMU, GFABS, GNEG, GNOT
+#endif
};
enum {
diff --git a/cgias.c b/cgias.c
index 760273a..aa0942c 100644
--- a/cgias.c
+++ b/cgias.c
@@ -2149,13 +2149,13 @@ static void as_div_rem_i_instruction (struct instruction *instruction,int comput
}
}
-static void as_div_instruction (struct instruction *instruction)
+static void as_div_instruction (struct instruction *instruction,int unsigned_div)
{
- int d_reg;
+ int d_reg,opcode2;
d_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
- if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE && unsigned_div==0){
int i,log2i;
i=instruction->instruction_parameters[0].parameter_data.i;
@@ -2198,24 +2198,28 @@ static void as_div_instruction (struct instruction *instruction)
return;
}
+ opcode2=unsigned_div ? 0060 : 0070;
+
switch (d_reg){
case REGISTER_D0:
as_move_r_r (REGISTER_A1,REGISTER_O0);
- /*cdq*/
- store_c (0231);
+ if (unsigned_div)
+ as_r_r (0063,REGISTER_A1,REGISTER_A1); /* xor */
+ else
+ store_c (0231); /* cdq */
/* idivl */
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER
&& instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
{
- as_r (0367,0070,REGISTER_O0);
+ as_r (0367,opcode2,REGISTER_O0);
} else if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT
&& instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
{
- as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,REGISTER_O0);
+ as_id (0367,opcode2,instruction->instruction_parameters[0].parameter_offset,REGISTER_O0);
} else
- as_parameter (0367,0070,&instruction->instruction_parameters[0]);
+ as_parameter (0367,opcode2,&instruction->instruction_parameters[0]);
as_move_r_r (REGISTER_O0,REGISTER_A1);
break;
@@ -2223,8 +2227,10 @@ static void as_div_instruction (struct instruction *instruction)
as_move_r_r (REGISTER_D0,REGISTER_O0);
as_move_r_r (REGISTER_A1,REGISTER_D0);
- /*cdq*/
- store_c (0231);
+ if (unsigned_div)
+ as_r_r (0063,REGISTER_A1,REGISTER_A1); /* xor */
+ else
+ store_c (0231); /* cdq */
/* idivl */
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
@@ -2236,7 +2242,7 @@ static void as_div_instruction (struct instruction *instruction)
else if (r==REGISTER_A1)
r=REGISTER_D0;
- as_r (0367,0070,r);
+ as_r (0367,opcode2,r);
} else if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
int r;
@@ -2246,9 +2252,9 @@ static void as_div_instruction (struct instruction *instruction)
else if (r==REGISTER_A1)
r=REGISTER_D0;
- as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,r);
+ as_id (0367,opcode2,instruction->instruction_parameters[0].parameter_offset,r);
} else
- as_parameter (00367,0070,&instruction->instruction_parameters[0]);
+ as_parameter (00367,opcode2,&instruction->instruction_parameters[0]);
as_move_r_r (REGISTER_D0,REGISTER_A1);
as_move_r_r (REGISTER_O0,REGISTER_D0);
@@ -2257,8 +2263,10 @@ static void as_div_instruction (struct instruction *instruction)
as_move_r_r (REGISTER_A1,REGISTER_O0);
store_c (0x90+reg_num (d_reg)); /* xchg d_reg,D0 */
- /*cdq*/
- store_c (0231);
+ if (unsigned_div)
+ as_r_r (0063,REGISTER_A1,REGISTER_A1); /* xor */
+ else
+ store_c (0231); /* cdq */
/* idivl */
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
@@ -2272,7 +2280,7 @@ static void as_div_instruction (struct instruction *instruction)
else if (r==d_reg)
r=REGISTER_D0;
- as_r (0367,0070,r);
+ as_r (0367,opcode2,r);
} else if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
int r;
@@ -2284,7 +2292,7 @@ static void as_div_instruction (struct instruction *instruction)
else if (r==d_reg)
r=REGISTER_D0;
- as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,r);
+ as_id (0367,opcode2,instruction->instruction_parameters[0].parameter_offset,r);
} else
as_parameter (0367,0070,&instruction->instruction_parameters[0]);
@@ -2293,13 +2301,13 @@ static void as_div_instruction (struct instruction *instruction)
}
}
-static void as_rem_instruction (struct instruction *instruction)
+static void as_rem_instruction (struct instruction *instruction,int unsigned_rem)
{
- int d_reg;
+ int d_reg,opcode2;
d_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
- if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE && unsigned_rem==0){
int i,log2i;
i=instruction->instruction_parameters[0].parameter_data.i;
@@ -2356,24 +2364,28 @@ static void as_rem_instruction (struct instruction *instruction)
return;
}
+ opcode2=unsigned_rem ? 0060 : 0070;
+
switch (d_reg){
case REGISTER_D0:
as_move_r_r (REGISTER_A1,REGISTER_O0);
- /*cdq*/
- store_c (0231);
+ if (unsigned_rem)
+ as_r_r (0063,REGISTER_A1,REGISTER_A1); /* xor */
+ else
+ store_c (0231); /* cdq */
/* idivl */
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER
&& instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
{
- as_r (0367,0070,REGISTER_O0);
+ as_r (0367,opcode2,REGISTER_O0);
} else if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT
&& instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
{
- as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,REGISTER_O0);
+ as_id (0367,opcode2,instruction->instruction_parameters[0].parameter_offset,REGISTER_O0);
} else
- as_parameter (0367,0070,&instruction->instruction_parameters[0]);
+ as_parameter (0367,opcode2,&instruction->instruction_parameters[0]);
as_move_r_r (REGISTER_A1,REGISTER_D0);
as_move_r_r (REGISTER_O0,REGISTER_A1);
@@ -2382,8 +2394,11 @@ static void as_rem_instruction (struct instruction *instruction)
as_move_r_r (REGISTER_D0,REGISTER_O0);
as_move_r_r (REGISTER_A1,REGISTER_D0);
- /*cdq*/
- store_c (0231);
+ if (unsigned_rem)
+ as_r_r (0063,REGISTER_A1,REGISTER_A1); /* xor */
+ else
+ store_c (0231); /* cdq */
+
/* idivl */
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
int r;
@@ -2394,7 +2409,7 @@ static void as_rem_instruction (struct instruction *instruction)
else if (r==REGISTER_A1)
r=REGISTER_D0;
- as_r (0367,0070,r);
+ as_r (0367,opcode2,r);
} else if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
int r;
@@ -2404,9 +2419,9 @@ static void as_rem_instruction (struct instruction *instruction)
else if (r==REGISTER_A1)
r=REGISTER_D0;
- as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,r);
+ as_id (0367,opcode2,instruction->instruction_parameters[0].parameter_offset,r);
} else
- as_parameter (0367,0070,&instruction->instruction_parameters[0]);
+ as_parameter (0367,opcode2,&instruction->instruction_parameters[0]);
as_move_r_r (REGISTER_O0,REGISTER_D0);
break;
@@ -2414,8 +2429,10 @@ static void as_rem_instruction (struct instruction *instruction)
as_move_r_r (REGISTER_A1,REGISTER_O0);
store_c (0x90+reg_num (d_reg)); /* xchg d_reg,D0 */
- /*cdq*/
- store_c (0231);
+ if (unsigned_rem)
+ as_r_r (0063,REGISTER_A1,REGISTER_A1); /* xor */
+ else
+ store_c (0231); /* cdq */
/* idivl */
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
int r;
@@ -2428,7 +2445,7 @@ static void as_rem_instruction (struct instruction *instruction)
else if (r==d_reg)
r=REGISTER_D0;
- as_r (0367,0070,r);
+ as_r (0367,opcode2,r);
} else if (instruction->instruction_parameters[0].parameter_type==P_INDIRECT){
int r;
@@ -2440,9 +2457,9 @@ static void as_rem_instruction (struct instruction *instruction)
else if (r==d_reg)
r=REGISTER_D0;
- as_id (0367,0070,instruction->instruction_parameters[0].parameter_offset,r);
+ as_id (0367,opcode2,instruction->instruction_parameters[0].parameter_offset,r);
} else
- as_parameter (0367,0070,&instruction->instruction_parameters[0]);
+ as_parameter (0367,opcode2,&instruction->instruction_parameters[0]);
as_move_r_r (d_reg,REGISTER_D0);
as_move_r_r (REGISTER_A1,d_reg);
@@ -2600,6 +2617,16 @@ static void as_exg_instruction (struct instruction *instruction)
as_r_r (0207,r1,r2);
}
+static void as_neg_instruction (struct instruction *instruction)
+{
+ as_r (0367,0030,instruction->instruction_parameters[0].parameter_data.reg.r);
+}
+
+static void as_not_instruction (struct instruction *instruction)
+{
+ as_r (0367,0020,instruction->instruction_parameters[0].parameter_data.reg.r);
+}
+
static void as_rtsi_instruction (struct instruction *instruction)
{
store_c (0xc2);
@@ -2685,6 +2712,9 @@ static void as_f_i (int code1,int code2,DOUBLE *r_p)
new_label->label_flags=DATA_LABEL;
+ if (data_object_label==NULL)
+ as_new_data_module();
+
data_object_label->object_section_align8=1;
if ((data_buffer_p-current_data_buffer->data-data_object_label->object_label_offset) & 4)
store_long_word_in_data_section (0);
@@ -2706,7 +2736,7 @@ struct instruction *find_next_fp_instruction (struct instruction *instruction)
while (instruction!=NULL){
switch (instruction->instruction_icode){
case IFADD: case IFSUB: case IFMUL: case IFDIV:
- case IFMOVEL: case IFCMP: case IFNEG: case IFTST: case IFREM:
+ case IFMOVEL: case IFCMP: case IFNEG: case IFABS: case IFTST: case IFREM:
case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE:
case IFSEQ: case IFSGE: case IFSGT: case IFSLE: case IFSLT: case IFSNE:
case IFCOS: case IFSIN: case IFSQRT: case IFTAN:
@@ -2734,7 +2764,7 @@ int next_instruction_is_fld_reg (int reg0,struct instruction *instruction)
if (next_fp_instruction!=NULL){
switch (next_fp_instruction->instruction_icode){
case IFADD: case IFSUB: case IFMUL: case IFDIV:
- case IFSQRT: case IFNEG: case IFSIN: case IFCOS:
+ case IFSQRT: case IFNEG: case IFABS: case IFSIN: case IFCOS:
if (next_fp_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER
&& next_fp_instruction->instruction_parameters[0].parameter_data.reg.r==reg0)
{
@@ -2846,7 +2876,7 @@ static void fstpl_instruction (int reg0,struct instruction *instruction)
return;
} /* else */
- case IFSQRT: case IFNEG: case IFSIN: case IFCOS:
+ case IFSQRT: case IFNEG: case IFABS: case IFSIN: case IFCOS:
if (next_fp_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER
&& next_fp_instruction->instruction_parameters[0].parameter_data.reg.r==reg0)
{
@@ -3651,9 +3681,28 @@ void store_descriptor_string_in_data_section (char *string,int length,LABEL *str
static void as_fmovel_instruction (struct instruction *instruction)
{
- if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER)
- internal_error_in_function ("as_fmovel_instruction");
- else {
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ LABEL *new_label;
+ int s_freg;
+
+ new_label=allocate_memory_from_heap (sizeof (struct label));
+
+ new_label->label_flags=DATA_LABEL;
+
+ define_data_label (new_label);
+ store_long_word_in_data_section (0);
+
+ s_freg=instruction->instruction_parameters[0].parameter_data.reg.r;
+ if (s_freg!=0){
+ as_f_r (0xd9,0xc0,s_freg); /* fld s_freg */
+ as_f_a (0xdb,3,new_label); /* fistp */
+ } else
+ as_f_a (0xdb,2,new_label); /* fist */
+ as_r_a (0x8b,instruction->instruction_parameters[1].parameter_data.reg.r,new_label);
+ } else
+ internal_error_in_function ("as_fmovel_instruction");
+ } else {
switch (instruction->instruction_parameters[0].parameter_type){
case P_REGISTER:
{
@@ -3792,21 +3841,30 @@ static void as_instructions (struct instruction *instruction)
case IBGE:
as_branch_instruction (instruction,015);
break;
+ case IBGEU:
+ as_branch_instruction (instruction,003);
+ break;
case IBGT:
as_branch_instruction (instruction,017);
break;
+ case IBGTU:
+ as_branch_instruction (instruction,007);
+ break;
case IBLE:
as_branch_instruction (instruction,016);
break;
+ case IBLEU:
+ as_branch_instruction (instruction,006);
+ break;
case IBLT:
as_branch_instruction (instruction,014);
break;
+ case IBLTU:
+ as_branch_instruction (instruction,002);
+ break;
case IBNE:
as_branch_instruction (instruction,005);
break;
- case IBHS:
- as_branch_instruction (instruction,003);
- break;
case IBO:
as_branch_instruction (instruction,0);
break;
@@ -3826,17 +3884,23 @@ static void as_instructions (struct instruction *instruction)
as_mul_instruction (instruction);
break;
case IDIV:
- as_div_instruction (instruction);
+ as_div_instruction (instruction,0);
break;
case IDIVI:
as_div_rem_i_instruction (instruction,0);
break;
+ case IDIVU:
+ as_div_instruction (instruction,1);
+ break;
case IMOD:
- as_rem_instruction (instruction);
+ as_rem_instruction (instruction,0);
break;
case IREMI:
as_div_rem_i_instruction (instruction,1);
break;
+ case IREMU:
+ as_rem_instruction (instruction,1);
+ break;
case IAND:
as_logic_instruction (instruction,0043,040,045);
break;
@@ -3852,15 +3916,27 @@ static void as_instructions (struct instruction *instruction)
case ISGE:
as_set_condition_instruction (instruction,015);
break;
+ case ISGEU:
+ as_set_condition_instruction (instruction,003);
+ break;
case ISGT:
as_set_condition_instruction (instruction,017);
break;
+ case ISGTU:
+ as_set_condition_instruction (instruction,007);
+ break;
case ISLE:
as_set_condition_instruction (instruction,016);
break;
+ case ISLEU:
+ as_set_condition_instruction (instruction,006);
+ break;
case ISLT:
as_set_condition_instruction (instruction,014);
break;
+ case ISLTU:
+ as_set_condition_instruction (instruction,002);
+ break;
case ISNE:
as_set_condition_instruction (instruction,005);
break;
@@ -3888,6 +3964,12 @@ static void as_instructions (struct instruction *instruction)
case IEXG:
as_exg_instruction (instruction);
break;
+ case INEG:
+ as_neg_instruction (instruction);
+ break;
+ case INOT:
+ as_not_instruction (instruction);
+ break;
case IWORD:
store_c (instruction->instruction_parameters[0].parameter_data.i);
break;
@@ -3946,6 +4028,9 @@ static void as_instructions (struct instruction *instruction)
case IFNEG:
as_monadic_float_instruction (instruction,0xe0);
break;
+ case IFABS:
+ as_monadic_float_instruction (instruction,0xe1);
+ break;
case IFSIN:
as_monadic_float_instruction (instruction,0xfe);
break;
diff --git a/cgiconst.h b/cgiconst.h
index 0c06775..02ca0ac 100644
--- a/cgiconst.h
+++ b/cgiconst.h
@@ -7,16 +7,19 @@
# define FP_STACK_OPTIMIZATIONS
#endif
+#define IBHS IBGEU
+
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,
+ IADD, IAND, IASR, IBEQ, IBGE, IBGEU, IBGT,
+ IBGTU, IBLE, IBLEU, IBLT, IBLTU, 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, ISGEU, ISGT,
+ ISGTU, ISLE, ISLEU, ISLT, ISLTU, ISNE, ISNO,
ISO, ISUB, ITST, IWORD
#if !defined (G_POWER)
,IFSQRT
@@ -52,7 +55,7 @@ enum {
,IFEXG
#endif
#if defined (I486)
- ,IRTSI, IDIVI, IREMI
+ ,IRTSI, IDIVI, IREMI, IDIVU, IREMU, IFABS, INEG, INOT
#endif
#ifdef G_POWER
,IUMULH
diff --git a/cginput.c b/cginput.c
index ee6bab6..d26a8bf 100644
--- a/cginput.c
+++ b/cginput.c
@@ -1717,6 +1717,9 @@ static void put_instruction_name
static void put_instructions_in_table (void)
{
+#ifdef I486
+ put_instruction_name ("absR", parse_instruction, code_absR );
+#endif
put_instruction_name ("acosR", parse_instruction, code_acosR );
put_instruction_name ("add_args", parse_instruction_n_n_n, code_add_args );
put_instruction_name ("addI", parse_instruction, code_addI );
@@ -1760,6 +1763,9 @@ static void put_instructions_in_table (void)
put_instruction_name ("del_args", parse_instruction_n_n_n, code_del_args );
put_instruction_name ("divI", parse_instruction, code_divI );
put_instruction_name ("divR", parse_instruction, code_divR );
+#ifdef I486
+ put_instruction_name ("divU", parse_instruction, code_divU );
+#endif
put_instruction_name ("entierR", parse_instruction, code_entierR );
put_instruction_name ("eqB", parse_instruction, code_eqB );
put_instruction_name ("eqB_a", parse_instruction_b_n, code_eqB_a );
@@ -1810,6 +1816,9 @@ static void put_instructions_in_table (void)
put_instruction_name ("gtC", parse_instruction, code_gtC );
put_instruction_name ("gtI", parse_instruction, code_gtI );
put_instruction_name ("gtR", parse_instruction, code_gtR );
+#ifdef I486
+ put_instruction_name ("gtU", parse_instruction, code_gtU );
+#endif
put_instruction_name ("halt", parse_instruction, code_halt );
put_instruction_name ("in", parse_instruction_in_or_out, code_in );
put_instruction_name ("incI", parse_instruction, code_incI );
@@ -1834,9 +1843,15 @@ static void put_instructions_in_table (void)
put_instruction_name ("ltC", parse_instruction, code_ltC );
put_instruction_name ("ltI", parse_instruction, code_ltI );
put_instruction_name ("ltR", parse_instruction, code_ltR );
+#ifdef I486
+ put_instruction_name ("ltU", parse_instruction, code_ltU );
+#endif
put_instruction_name ("modI", parse_instruction, code_remI );
put_instruction_name ("mulI", parse_instruction, code_mulI );
put_instruction_name ("mulR", parse_instruction, code_mulR );
+#ifdef I486
+ put_instruction_name ("negI", parse_instruction, code_negI );
+#endif
put_instruction_name ("negR", parse_instruction, code_negR );
put_instruction_name ("new_ext_reducer",parse_instruction_a_n, code_new_ext_reducer );
put_instruction_name ("new_int_reducer",parse_instruction_a_n, code_new_int_reducer );
@@ -1911,6 +1926,9 @@ static void put_instructions_in_table2 (void)
put_instruction_name ("randomP", parse_instruction, code_randomP );
put_instruction_name ("release", parse_instruction, code_release );
put_instruction_name ("remI", parse_instruction, code_remI );
+#ifdef I486
+ put_instruction_name ("remU", parse_instruction, code_remU );
+#endif
put_instruction_name ("replace", parse_instruction_a_n_n, code_replace );
put_instruction_name ("repl_arg", parse_instruction_n_n, code_repl_arg );
put_instruction_name ("repl_args", parse_instruction_n_n, code_repl_args );
diff --git a/cgiwas.c b/cgiwas.c
index a31d06e..4064d9c 100644
--- a/cgiwas.c
+++ b/cgiwas.c
@@ -1270,6 +1270,13 @@ static void w_as_tst_instruction (struct instruction *instruction,int size_flag)
}
}
+static void w_as_monadic_instruction (struct instruction *instruction,char *opcode)
+{
+ w_as_opcode (opcode);
+ w_as_register (instruction->instruction_parameters[0].parameter_data.reg.r);
+ w_as_newline();
+}
+
static void w_as_btst_instruction (struct instruction *instruction)
{
if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
@@ -1378,7 +1385,7 @@ static void as_test_floating_point_condition_code (int n)
fprintf (assembly_file,intel_asm ? "\tand\tah,69\n\tdec\tah\n\tcmp\tah,64\n" : "\tandb\t$69,%%ah\n\tdecb\t%%ah\n\tcmpb\t$64,%%ah\n");
break;
case 5:
- fprintf (assembly_file,intel_asm ? "\tand\tah,5\n" : "\tand\t5,%%ah\n");
+ fprintf (assembly_file,intel_asm ? "\tand\tah,5\n" : "\tand\t$5,%%ah\n");
break;
}
}
@@ -1687,7 +1694,7 @@ static void w_as_div_rem_i_instruction (struct instruction *instruction,int comp
}
}
-static void w_as_div_instruction (struct instruction *instruction)
+static void w_as_div_instruction (struct instruction *instruction,int unsigned_div)
{
int d_reg;
@@ -1697,8 +1704,8 @@ static void w_as_div_instruction (struct instruction *instruction)
int i,log2i;
i=instruction->instruction_parameters[0].parameter_data.i;
-
- if ((i & (i-1))==0 && i>0){
+
+ if (unsigned_div==0 && (i & (i-1))==0 && i>0){
if (i==1)
return;
@@ -1729,19 +1736,24 @@ static void w_as_div_instruction (struct instruction *instruction)
w_as_immediate_register_newline (log2i,d_reg);
return;
- } else {
- internal_error_in_function ("w_as_div_instruction");
- return;
}
+
+ internal_error_in_function ("w_as_div_instruction");
+ return;
}
switch (d_reg){
case REGISTER_D0:
w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0);
-
- w_as_instruction_without_parameters ("cdq");
-
- w_as_opcode (intel_asm ? "idiv" : "idivl");
+
+ if (unsigned_div){
+ w_as_opcode_register_register_newline ("xor",REGISTER_A1,REGISTER_A1);
+ w_as_opcode (intel_asm ? "div" : "divl");
+ } else {
+ w_as_instruction_without_parameters ("cdq");
+ w_as_opcode (intel_asm ? "idiv" : "idivl");
+ }
+
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER
&& instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
{
@@ -1765,9 +1777,13 @@ static void w_as_div_instruction (struct instruction *instruction)
w_as_movl_register_register_newline (REGISTER_A1,REGISTER_D0);
- w_as_instruction_without_parameters ("cdq");
-
- w_as_opcode (intel_asm ? "idiv" : "idivl");
+ if (unsigned_div){
+ w_as_opcode_register_register_newline ("xor",REGISTER_A1,REGISTER_A1);
+ w_as_opcode (intel_asm ? "div" : "divl");
+ } else {
+ w_as_instruction_without_parameters ("cdq");
+ w_as_opcode (intel_asm ? "idiv" : "idivl");
+ }
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
int r;
@@ -1805,9 +1821,13 @@ static void w_as_div_instruction (struct instruction *instruction)
w_as_opcode_register_register_newline ("xchg",REGISTER_D0,d_reg);
- w_as_instruction_without_parameters ("cdq");
-
- w_as_opcode (intel_asm ? "idiv" : "idivl");
+ if (unsigned_div){
+ w_as_opcode_register_register_newline ("xor",REGISTER_A1,REGISTER_A1);
+ w_as_opcode (intel_asm ? "div" : "divl");
+ } else {
+ w_as_instruction_without_parameters ("cdq");
+ w_as_opcode (intel_asm ? "idiv" : "idivl");
+ }
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
int r;
@@ -1846,13 +1866,13 @@ static void w_as_div_instruction (struct instruction *instruction)
}
}
-static void w_as_rem_instruction (struct instruction *instruction)
+static void w_as_rem_instruction (struct instruction *instruction,int unsigned_rem)
{
int d_reg;
d_reg=instruction->instruction_parameters[1].parameter_data.reg.r;
- if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE){
+ if (instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE && unsigned_rem==0){
int i,log2i;
i=instruction->instruction_parameters[0].parameter_data.i;
@@ -1903,9 +1923,14 @@ static void w_as_rem_instruction (struct instruction *instruction)
case REGISTER_D0:
w_as_movl_register_register_newline (REGISTER_A1,REGISTER_O0);
- w_as_instruction_without_parameters ("cdq");
+ if (unsigned_rem){
+ w_as_opcode_register_register_newline ("xor",REGISTER_A1,REGISTER_A1);
+ w_as_opcode (intel_asm ? "div" : "divl");
+ } else {
+ w_as_instruction_without_parameters ("cdq");
+ w_as_opcode (intel_asm ? "idiv" : "idivl");
+ }
- w_as_opcode ("idivl");
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER
&& instruction->instruction_parameters[0].parameter_data.reg.r==REGISTER_A1)
{
@@ -1932,9 +1957,13 @@ static void w_as_rem_instruction (struct instruction *instruction)
w_as_movl_register_register_newline (REGISTER_A1,REGISTER_D0);
- w_as_instruction_without_parameters ("cdq");
-
- w_as_opcode ("idivl");
+ if (unsigned_rem){
+ w_as_opcode_register_register_newline ("xor",REGISTER_A1,REGISTER_A1);
+ w_as_opcode (intel_asm ? "div" : "divl");
+ } else {
+ w_as_instruction_without_parameters ("cdq");
+ w_as_opcode (intel_asm ? "idiv" : "idivl");
+ }
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
int r;
@@ -1970,9 +1999,13 @@ static void w_as_rem_instruction (struct instruction *instruction)
w_as_opcode_register_register_newline ("xchg",REGISTER_D0,d_reg);
- w_as_instruction_without_parameters ("cdq");
-
- w_as_opcode (intel_asm ? "idiv" : "idivl");
+ if (unsigned_rem){
+ w_as_opcode_register_register_newline ("xor",REGISTER_A1,REGISTER_A1);
+ w_as_opcode (intel_asm ? "div" : "divl");
+ } else {
+ w_as_instruction_without_parameters ("cdq");
+ w_as_opcode (intel_asm ? "idiv" : "idivl");
+ }
if (instruction->instruction_parameters[0].parameter_type==P_REGISTER){
int r;
@@ -2174,7 +2207,7 @@ static void fstpl_instruction (int reg0,struct instruction *instruction)
return;
} /* else */
- case IFSQRT: case IFNEG: case IFSIN: case IFCOS:
+ case IFSQRT: case IFNEG: case IFABS: case IFSIN: case IFCOS:
if (next_fp_instruction->instruction_parameters[0].parameter_type==P_F_REGISTER
&& next_fp_instruction->instruction_parameters[0].parameter_data.reg.r==reg0)
{
@@ -2691,9 +2724,42 @@ static int int_to_real_scratch_imported=0;
static void w_as_fmovel_instruction (struct instruction *instruction)
{
- if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER)
- internal_error_in_function ("w_as_fmovel_instruction");
- else {
+ if (instruction->instruction_parameters[0].parameter_type==P_F_REGISTER){
+ if (instruction->instruction_parameters[1].parameter_type==P_REGISTER){
+ int s_freg;
+
+ if (intel_asm && !int_to_real_scratch_imported){
+ w_as_opcode ("extrn");
+ fprintf (assembly_file,"%s:near\n","int_to_real_scratch");
+ int_to_real_scratch_imported=1;
+ }
+
+ s_freg=instruction->instruction_parameters[0].parameter_data.reg.r;
+ if (s_freg!=0){
+ w_as_opcode ("fld");
+ w_as_fp_register (s_freg);
+ w_as_newline();
+
+ w_as_opcode (!intel_asm ? "fistpl" : "fistp");
+ } else
+ w_as_opcode (!intel_asm ? "fistl" : "fist");
+ if (intel_asm)
+ fprintf (assembly_file,"dword ptr ");
+ w_as_label ("int_to_real_scratch");
+ w_as_newline();
+
+ w_as_opcode_movl();
+ if (intel_asm){
+ w_as_register_comma (instruction->instruction_parameters[1].parameter_data.reg.r);
+ fprintf (assembly_file,"dword ptr ");
+ }
+ w_as_label ("int_to_real_scratch");
+ if (!intel_asm)
+ w_as_comma_register (instruction->instruction_parameters[1].parameter_data.reg.r);
+ w_as_newline();
+ } else
+ internal_error_in_function ("w_as_fmovel_instruction");
+ } else {
switch (instruction->instruction_parameters[0].parameter_type){
case P_REGISTER:
if (intel_asm && !int_to_real_scratch_imported){
@@ -2877,21 +2943,30 @@ static void w_as_instructions (register struct instruction *instruction)
case IBGE:
w_as_branch_instruction (instruction,"jge");
break;
+ case IBGEU:
+ w_as_branch_instruction (instruction,"jae");
+ break;
case IBGT:
w_as_branch_instruction (instruction,"jg");
break;
+ case IBGTU:
+ w_as_branch_instruction (instruction,"ja");
+ break;
case IBLE:
w_as_branch_instruction (instruction,"jle");
break;
+ case IBLEU:
+ w_as_branch_instruction (instruction,"jbe");
+ break;
case IBLT:
w_as_branch_instruction (instruction,"jl");
break;
+ case IBLTU:
+ w_as_branch_instruction (instruction,"jb");
+ break;
case IBNE:
w_as_branch_instruction (instruction,"jne");
break;
- case IBHS:
- w_as_branch_instruction (instruction,"jae");
- break;
case IBO:
w_as_branch_instruction (instruction,"jo");
break;
@@ -2911,17 +2986,23 @@ static void w_as_instructions (register struct instruction *instruction)
w_as_dyadic_instruction (instruction,intel_asm ? "imul" : "imull");
break;
case IDIV:
- w_as_div_instruction (instruction);
+ w_as_div_instruction (instruction,0);
break;
case IDIVI:
w_as_div_rem_i_instruction (instruction,0);
break;
+ case IDIVU:
+ w_as_div_instruction (instruction,1);
+ break;
case IMOD:
- w_as_rem_instruction (instruction);
+ w_as_rem_instruction (instruction,0);
break;
case IREMI:
w_as_div_rem_i_instruction (instruction,1);
break;
+ case IREMU:
+ w_as_rem_instruction (instruction,1);
+ break;
case IAND:
w_as_dyadic_instruction (instruction,intel_asm ? "and" : "andl");
break;
@@ -2937,15 +3018,27 @@ static void w_as_instructions (register struct instruction *instruction)
case ISGE:
w_as_set_condition_instruction (instruction,"setge");
break;
+ case ISGEU:
+ w_as_set_condition_instruction (instruction,"setae");
+ break;
case ISGT:
w_as_set_condition_instruction (instruction,"setg");
break;
+ case ISGTU:
+ w_as_set_condition_instruction (instruction,"seta");
+ break;
case ISLE:
w_as_set_condition_instruction (instruction,"setle");
break;
+ case ISLEU:
+ w_as_set_condition_instruction (instruction,"setbe");
+ break;
case ISLT:
w_as_set_condition_instruction (instruction,"setl");
break;
+ case ISLTU:
+ w_as_set_condition_instruction (instruction,"setb");
+ break;
case ISNE:
w_as_set_condition_instruction (instruction,"setne");
break;
@@ -2973,6 +3066,12 @@ static void w_as_instructions (register struct instruction *instruction)
case IEXG:
w_as_dyadic_instruction (instruction,"xchg");
break;
+ case INEG:
+ w_as_monadic_instruction (instruction,intel_asm ? "neg" : "negl");
+ break;
+ case INOT:
+ w_as_monadic_instruction (instruction,intel_asm ? "not" : "notl");
+ break;
case IFMOVE:
instruction=w_as_fmove_instruction (instruction);
break;
@@ -3028,6 +3127,9 @@ static void w_as_instructions (register struct instruction *instruction)
case IFNEG:
w_as_monadic_float_instruction (instruction,"fchs");
break;
+ case IFABS:
+ w_as_monadic_float_instruction (instruction,"fabs");
+ break;
case IFSIN:
w_as_monadic_float_instruction (instruction,"fsin");
break;
diff --git a/cglin.c b/cglin.c
index b9b9f32..b293c9a 100644
--- a/cglin.c
+++ b/cglin.c
@@ -3068,7 +3068,8 @@ static int compare_node (INSTRUCTION_GRAPH graph,int i_test_1,int i_test_2)
}
enum {
- CEQ, CNE, CGT, CLT, CGE, CLE, CO, CNO,
+ CEQ, CNE, CGT, CLT, CGE, CLE,
+ CO, CNO, CGTU, CLTU, CGEU, CLEU,
CFEQ, CFNE, CFGT, CFLT, CFGE, CFLE
};
@@ -3076,19 +3077,22 @@ enum {
int condition_to_set_instruction[]=
{
- ISEQ, ISNE, ISGT, ISLT, ISGE, ISLE, ISO, ISNO,
+ ISEQ, ISNE, ISGT, ISLT, ISGE, ISLE,
+ ISO, ISNO, ISGTU, ISLTU, ISGEU, ISLEU,
IFSEQ, IFSNE, IFSGT, IFSLT, IFSGE, IFSLE
};
static int condition_to_branch_false_instruction[]=
{
- IBNE, IBEQ, IBLE, IBGE, IBLT, IBGT, IBNO, IBO,
+ IBNE, IBEQ, IBLE, IBGE, IBLT, IBGT,
+ IBNO, IBO, IBLEU, IBGEU, IBLTU, IBGTU,
IFBNE, IFBEQ, IFBLE, IFBGE, IFBLT, IFBGT
};
static int condition_to_branch_true_instruction[]=
{
- IBEQ, IBNE, IBGT, IBLT, IBGE, IBLE, IBO, IBNO,
+ IBEQ, IBNE, IBGT, IBLT, IBGE, IBLE,
+ IBO, IBNO, IBGTU, IBLTU, IBGEU, IBLEU,
IFBEQ, IFBNE, IFBGT, IFBLT, IFBGE, IFBLE
};
@@ -3125,9 +3129,15 @@ static int linearize_condition (INSTRUCTION_GRAPH graph)
case GCMP_LT:
condition=compare_node (graph,CLT,CGT);
break;
+ case GCMP_LTU:
+ condition=compare_node (graph,CLTU,CGTU);
+ break;
case GCMP_GT:
condition=compare_node (graph,CGT,CLT);
break;
+ case GCMP_GTU:
+ condition=compare_node (graph,CGTU,CLTU);
+ break;
case GFCMP_EQ:
condition=float_compare_node (graph,CFEQ,CFEQ);
break;
@@ -3186,9 +3196,15 @@ static int linearize_not_condition (INSTRUCTION_GRAPH graph)
case GCMP_LT:
condition=compare_node (graph,CGE,CLE);
break;
+ case GCMP_LTU:
+ condition=compare_node (graph,CGEU,CLEU);
+ break;
case GCMP_GT:
condition=compare_node (graph,CLE,CGE);
break;
+ case GCMP_GTU:
+ condition=compare_node (graph,CLEU,CGEU);
+ break;
case GFCMP_EQ:
condition=float_compare_node (graph,CFNE,CFNE);
break;
@@ -3364,8 +3380,41 @@ static void linearize_dyadic_non_commutative_data_operator (int i_instruction_co
register_node (graph,reg_1);
}
+#ifdef I486
+static void linearize_monadic_data_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p)
+{
+ INSTRUCTION_GRAPH graph_1;
+ ADDRESS ad_1;
+ int reg_1;
+
+ graph_1=graph->instruction_parameters[0].p;
+
+ linearize_graph (graph_1,&ad_1);
+
+ in_alterable_data_register (&ad_1);
+ reg_1=ad_1.ad_register;
+ instruction_r (i_instruction_code,reg_1);
+
+ if (graph->instruction_d_min_a_cost>0){
+ int areg;
+
+ areg=get_aregister();
+ i_move_r_r (reg_1,areg);
+ free_dregister (reg_1);
+ reg_1=areg;
+ }
+
+ ad_p->ad_mode=P_REGISTER;
+ ad_p->ad_register=reg_1;
+
+ ad_p->ad_count_p=&graph->node_count;
+ if (*ad_p->ad_count_p>1)
+ register_node (graph,reg_1);
+}
+#endif
+
#if defined (I486) || defined (G_POWER)
-static void linearize_div_mod_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p)
+static void linearize_div_rem_operator (int i_instruction_code,INSTRUCTION_GRAPH graph,ADDRESS *ad_p)
{
INSTRUCTION_GRAPH graph_1,graph_2;
ADDRESS ad_1,ad_2;
@@ -3387,23 +3436,28 @@ static void linearize_div_mod_operator (int i_instruction_code,INSTRUCTION_GRAPH
# ifdef I486
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 {
+ if (i_instruction_code==IDIVU || i_instruction_code==IREMU){
in_data_register (&ad_1);
- instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register);
+ instruction_ad_r (i_instruction_code,&ad_1,ad_2.ad_register);
+ } else {
+ 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)
@@ -6053,6 +6107,11 @@ static void linearize_float_graph (register INSTRUCTION_GRAPH graph,register ADD
case GFNEG:
linearize_monadic_float_operator (graph,ad_p,IFNEG);
break;
+#ifdef I486
+ case GFABS:
+ linearize_monadic_float_operator (graph,ad_p,IFABS);
+ break;
+#endif
case GFSIN:
linearize_monadic_float_operator (graph,ad_p,IFSIN);
break;
@@ -7512,11 +7571,19 @@ static void linearize_graph (INSTRUCTION_GRAPH graph,ADDRESS *ad_p)
return;
#if defined (I486) || defined (G_POWER)
case GDIV:
- linearize_div_mod_operator (IDIV,graph,ad_p);
+ linearize_div_rem_operator (IDIV,graph,ad_p);
return;
case GMOD:
- linearize_div_mod_operator (IMOD,graph,ad_p);
+ linearize_div_rem_operator (IMOD,graph,ad_p);
+ return;
+# ifdef I486
+ case GDIVU:
+ linearize_div_rem_operator (IDIVU,graph,ad_p);
+ return;
+ case GREMU:
+ linearize_div_rem_operator (IREMU,graph,ad_p);
return;
+# endif
#else
case GDIV:
linearize_dyadic_non_commutative_data_operator (IDIV,graph,ad_p);
@@ -7531,9 +7598,15 @@ static void linearize_graph (INSTRUCTION_GRAPH graph,ADDRESS *ad_p)
case GCMP_LT:
linearize_compare_operator (CLT,CGT,graph,ad_p);
return;
+ case GCMP_LTU:
+ linearize_compare_operator (CLTU,CGTU,graph,ad_p);
+ return;
case GCMP_GT:
linearize_compare_operator (CGT,CLT,graph,ad_p);
return;
+ case GCMP_GTU:
+ linearize_compare_operator (CGTU,CLTU,graph,ad_p);
+ return;
case GCNOT:
linearize_conditional_not_operator (graph,ad_p);
return;
@@ -7564,6 +7637,14 @@ static void linearize_graph (INSTRUCTION_GRAPH graph,ADDRESS *ad_p)
case GFILL_R:
linearize_fill_r_operator (graph,ad_p);
return;
+#ifdef I486
+ case GNEG:
+ linearize_monadic_data_operator (INEG,graph,ad_p);
+ return;
+ case GNOT:
+ linearize_monadic_data_operator (INOT,graph,ad_p);
+ return;
+#endif
case GMOVEMI:
linearize_movemi_operator (graph,ad_p);
return;
diff --git a/cgopt.c b/cgopt.c
index f9dee23..292258e 100644
--- a/cgopt.c
+++ b/cgopt.c
@@ -40,9 +40,10 @@
# define IF_G_RISC(a)
#endif
-#define POWER_PC_A_STACK_OPTIMIZE
+#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n)
-#define for_all(v,l,n) for(v=(l);v!=NULL;v=v->n)
+#define POWER_PC_A_STACK_OPTIMIZE
+#undef OPTIMIZE_LOOPS
#pragma segment Code4
@@ -50,12 +51,14 @@
extern struct basic_block *first_block;
-static void optimize_branch_jump
- (struct instruction *branch,struct instruction *jump,struct basic_block *jump_block)
+#ifdef OPTIMIZE_LOOPS
+extern LABEL *new_local_label (int label_flags);
+#endif
+
+static void optimize_branch_jump (struct instruction *branch,LABEL *new_branch_label)
{
- branch->instruction_parameters[0].parameter_data.l=
- jump->instruction_parameters[0].parameter_data.l;
-
+ branch->instruction_parameters[0].parameter_data.l=new_branch_label;
+
switch (branch->instruction_icode){
case IBEQ: branch->instruction_icode=IBNE; break;
case IBGE: branch->instruction_icode=IBLT; break;
@@ -63,6 +66,10 @@ static void optimize_branch_jump
case IBLE: branch->instruction_icode=IBGT; break;
case IBLT: branch->instruction_icode=IBGE; break;
case IBNE: branch->instruction_icode=IBEQ; break;
+ case IBGEU: branch->instruction_icode=IBLTU; break;
+ case IBGTU: branch->instruction_icode=IBLEU; break;
+ case IBLEU: branch->instruction_icode=IBGTU; break;
+ case IBLTU: branch->instruction_icode=IBGEU; break;
case IFBEQ: branch->instruction_icode=IFBNE; break;
case IFBGE: branch->instruction_icode=IFBLT; break;
case IFBGT: branch->instruction_icode=IFBLE; break;
@@ -70,20 +77,41 @@ static void optimize_branch_jump
case IFBLT: branch->instruction_icode=IFBGE; break;
case IFBNE: branch->instruction_icode=IFBEQ;
}
-
- jump_block->block_instructions=NULL;
}
-void optimize_jumps()
+#ifdef OPTIMIZE_LOOPS
+static LABEL *get_label_of_block (struct basic_block *block)
+{
+ if (block->block_labels!=NULL)
+ return block->block_labels->block_label_label;
+ else {
+ struct block_label *new_block_label;
+ LABEL *new_jmp_label;
+
+ new_jmp_label=new_local_label (0);
+
+ new_block_label=fast_memory_allocate_type (struct block_label);
+ new_block_label->block_label_label=new_jmp_label;
+ new_block_label->block_label_next=NULL;
+
+ block->block_labels=new_block_label;
+
+ return new_jmp_label;
+ }
+}
+#endif
+
+void optimize_jumps (void)
{
struct basic_block *block;
- for_all (block,first_block,block_next){
+ for_l (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 IBEQ: case IBGE: case IBGT: case IBLE: case IBLT:
+ case IBNE: case IBGEU: case IBGTU: case IBLEU: case IBLTU:
case IFBEQ: case IFBGE: case IFBGT: case IFBLE: case IFBLT: case IFBNE:
{
struct basic_block *next_block;
@@ -110,25 +138,54 @@ void optimize_jumps()
#endif
)
{
- for ( block_labels=next_next_block->block_labels;
- block_labels!=NULL;
- block_labels=block_labels->block_label_next
- )
+ for_l (block_labels,next_next_block->block_labels,block_label_next)
if (block_labels->block_label_label==branch_label){
- optimize_branch_jump (branch,jump,next_block);
+ optimize_branch_jump (branch,jump->instruction_parameters[0].parameter_data.l);
+ next_block->block_instructions=NULL;
+#ifdef OPTIMIZE_LOOPS
+ next_block->block_last_instruction=NULL;
+#endif
break;
}
}
}
}
}
+
+#ifdef OPTIMIZE_LOOPS
+ {
+ struct instruction *cmp_instruction;
+
+ cmp_instruction=block->block_instructions;
+ if (cmp_instruction->instruction_icode==ICMP && cmp_instruction->instruction_next==branch
+ && (cmp_instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE ||
+ cmp_instruction->instruction_parameters[0].parameter_type==P_REGISTER ||
+ (cmp_instruction->instruction_parameters[0].parameter_type==P_INDIRECT &&
+ cmp_instruction->instruction_parameters[1].parameter_type==P_REGISTER))
+ && (cmp_instruction->instruction_parameters[1].parameter_type==P_REGISTER ||
+ cmp_instruction->instruction_parameters[1].parameter_type==P_INDIRECT)
+ ){
+ struct block_label *block_label;
+
+ for_l (block_label,block->block_labels,block_label_next){
+ LABEL *label;
+
+ label=block_label->block_label_label;
+ label->label_flags |= CMP_BRANCH_BLOCK_LABEL;
+ label->label_block = block;
+ }
+ }
+ }
+#endif
break;
}
case IJMP:
{
struct basic_block *next_block;
-
- if ((next_block=block->block_next)!=NULL){
+
+ if (branch->instruction_parameters[0].parameter_type==P_LABEL
+ && (next_block=block->block_next)!=NULL)
+ {
struct block_label *labels;
LABEL *jmp_label;
@@ -144,7 +201,14 @@ void optimize_jumps()
if (branch->instruction_prev!=NULL)
branch->instruction_prev->instruction_next=NULL;
else
+#ifdef OPTIMIZE_LOOPS
+ {
+ block->block_instructions=NULL;
+ block->block_last_instruction=NULL;
+ }
+#else
block->block_instructions=NULL;
+#endif
break;
}
}
@@ -187,6 +251,140 @@ void optimize_jumps()
}
}
}
+
+#ifdef OPTIMIZE_LOOPS
+ for_l (block,first_block,block_next){
+ struct instruction *branch;
+
+ if ((branch=block->block_last_instruction)!=NULL &&
+ branch->instruction_icode==IJMP && branch->instruction_parameters[0].parameter_type==P_LABEL)
+ {
+ LABEL *jmp_label;
+
+ jmp_label=branch->instruction_parameters[0].parameter_data.l;
+ if (jmp_label->label_flags & CMP_BRANCH_BLOCK_LABEL){
+ struct basic_block *jmp_block,*jmp_next_block;
+ struct block_label *branch_block_label,*branch_next_block_label;
+ struct instruction *old_cmp_instruction,*old_branch_instruction,*new_branch_instruction;
+ LABEL *branch_label,*new_jmp_label;
+# ifdef I486
+ struct instruction *previous_instruction;
+# endif
+
+ jmp_block=jmp_label->label_block;
+ old_cmp_instruction=jmp_block->block_instructions;
+ jmp_next_block=jmp_block->block_next;
+ old_branch_instruction=old_cmp_instruction->instruction_next;
+
+ branch_label=old_branch_instruction->instruction_parameters[0].parameter_data.l;
+
+ branch_next_block_label=NULL;
+ if (block->block_next!=NULL)
+ for_l (branch_next_block_label,block->block_next->block_labels,block_label_next)
+ if (branch_next_block_label->block_label_label==branch_label)
+ break;
+
+ branch_block_label=NULL;
+ if (branch_next_block_label==NULL)
+ for_l (branch_block_label,block->block_labels,block_label_next)
+ if (branch_block_label->block_label_label==branch_label)
+ break;
+
+# ifdef I486
+ if (old_cmp_instruction->instruction_parameters[0].parameter_type==P_IMMEDIATE &&
+ old_cmp_instruction->instruction_parameters[0].parameter_data.i==0 &&
+ old_cmp_instruction->instruction_parameters[1].parameter_type==P_REGISTER &&
+ (previous_instruction=branch->instruction_prev)!=NULL &&
+ (previous_instruction->instruction_icode==ISUB || previous_instruction->instruction_icode==IADD) &&
+ previous_instruction->instruction_parameters[1].parameter_type==P_REGISTER &&
+ old_cmp_instruction->instruction_parameters[1].parameter_data.reg.r==previous_instruction->instruction_parameters[1].parameter_data.reg.r)
+ {
+ new_jmp_label = get_label_of_block (jmp_next_block);
+
+ if (branch_next_block_label!=NULL){
+ branch->instruction_icode=old_branch_instruction->instruction_icode;
+ branch->instruction_parameters[0]=old_branch_instruction->instruction_parameters[0];
+
+ optimize_branch_jump (branch,new_jmp_label);
+ } else {
+ new_branch_instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+sizeof (struct parameter));
+
+ new_branch_instruction->instruction_icode=old_branch_instruction->instruction_icode;
+ new_branch_instruction->instruction_arity=1;
+ new_branch_instruction->instruction_parameters[0]=old_branch_instruction->instruction_parameters[0];
+
+ if (block->block_instructions==branch){
+ block->block_instructions=new_branch_instruction;
+ new_branch_instruction->instruction_prev=NULL;
+ } else {
+ struct instruction *previous_instruction;
+
+ previous_instruction=branch->instruction_prev;
+ previous_instruction->instruction_next=new_branch_instruction;
+ new_branch_instruction->instruction_prev=previous_instruction;
+ }
+ new_branch_instruction->instruction_next=branch;
+
+ branch->instruction_prev=new_branch_instruction;
+
+ branch->instruction_parameters[0].parameter_data.l=new_jmp_label;
+ }
+ } else
+# endif
+
+ if (branch_next_block_label!=NULL || branch_block_label!=NULL){
+ struct instruction *new_cmp_instruction;
+
+ new_cmp_instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+2*sizeof (struct parameter));
+
+ new_cmp_instruction->instruction_icode=ICMP;
+ new_cmp_instruction->instruction_arity=2;
+ new_cmp_instruction->instruction_parameters[0]=old_cmp_instruction->instruction_parameters[0];
+ new_cmp_instruction->instruction_parameters[1]=old_cmp_instruction->instruction_parameters[1];
+
+ if (block->block_instructions==branch){
+ block->block_instructions=new_cmp_instruction;
+ new_cmp_instruction->instruction_prev=NULL;
+ } else {
+ struct instruction *previous_instruction;
+
+ previous_instruction=branch->instruction_prev;
+ previous_instruction->instruction_next=new_cmp_instruction;
+ new_cmp_instruction->instruction_prev=previous_instruction;
+ }
+
+ new_jmp_label = get_label_of_block (jmp_next_block);
+
+ if (branch_next_block_label!=NULL){
+ branch->instruction_icode=old_branch_instruction->instruction_icode;
+ branch->instruction_parameters[0]=old_branch_instruction->instruction_parameters[0];
+
+ optimize_branch_jump (branch,new_jmp_label);
+
+ new_cmp_instruction->instruction_next=branch;
+
+ branch->instruction_prev=new_cmp_instruction;
+ } else {
+ new_branch_instruction=(struct instruction*)fast_memory_allocate (sizeof (struct instruction)+sizeof (struct parameter));
+
+ new_branch_instruction->instruction_icode=old_branch_instruction->instruction_icode;
+ new_branch_instruction->instruction_arity=1;
+ new_branch_instruction->instruction_parameters[0]=old_branch_instruction->instruction_parameters[0];
+
+ new_cmp_instruction->instruction_next=new_branch_instruction;
+
+ new_branch_instruction->instruction_prev=new_cmp_instruction;
+ new_branch_instruction->instruction_next=branch;
+
+ branch->instruction_prev=new_branch_instruction;
+
+ branch->instruction_parameters[0].parameter_data.l=new_jmp_label;
+ }
+ }
+ }
+ }
+ }
+#endif
}
#if defined (M68000) || defined (I486)
@@ -209,7 +407,7 @@ 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 REMI:
+ case IDIVI: case IREMI: case IDIVU: case IREMU:
#endif
IF_G_POWER ( case IUMULH: )
return 4;
@@ -221,6 +419,9 @@ IF_G_POWER ( case IUMULH: )
#if !defined (G_POWER)
case IFSQRT:
#endif
+#ifdef I486
+ case IFABS:
+#endif
return 8;
default:
return 0;
@@ -449,7 +650,7 @@ static void compute_maximum_b_stack_offsets (register int b_offset)
{
struct instruction *instruction;
- for_all (instruction,last_instruction,instruction_prev){
+ for_l (instruction,last_instruction,instruction_prev){
switch (instruction->instruction_arity){
default:
if (
@@ -459,6 +660,7 @@ static void compute_maximum_b_stack_offsets (register int b_offset)
#ifdef I486
instruction->instruction_icode!=IDIVI &&
instruction->instruction_icode!=IREMI &&
+ instruction->instruction_icode!=IREMU &&
#endif
instruction->instruction_icode!=IMOD)
#ifdef M68000
@@ -511,7 +713,7 @@ void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_off
compute_maximum_b_stack_offsets (*b_offset_p);
# ifdef M68000
- for_all (instruction,block->block_instructions,instruction_next){
+ for_l (instruction,block->block_instructions,instruction_next){
switch (instruction->instruction_arity){
default:
if (
@@ -594,7 +796,7 @@ void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_off
# endif
# ifdef I486
- for_all (instruction,block->block_instructions,instruction_next){
+ for_l (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)
@@ -692,6 +894,7 @@ void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_off
default:
if (instruction->instruction_icode!=IDIVI &&
instruction->instruction_icode!=IREMI &&
+ instruction->instruction_icode!=IREMU &&
instruction->instruction_icode!=IMOD)
internal_error_in_function ("optimize_stack_access");
/* only first argument of mod might be register indirect */
@@ -722,7 +925,7 @@ void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_off
# endif
# ifdef OLDI486
- for_all (instruction,block->block_instructions,instruction_next){
+ for_l (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 &&
@@ -799,8 +1002,8 @@ void optimize_stack_access (struct basic_block *block,int *a_offset_p,int *b_off
if (a_offset==0)
return;
-
- for_all (instruction,block->block_instructions,instruction_next){
+
+ for_l (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 &&
@@ -1302,6 +1505,9 @@ static void store_next_uses (struct instruction *instruction)
#ifndef I486_USE_SCRATCH_REGISTER
case IASR: case ILSL: case ILSR:
case IDIV:
+# ifdef I486
+ case IDIVU:
+# endif
case ICMPW:
#endif
case IEOR: case IFADD:
@@ -1331,7 +1537,7 @@ IF_G_POWER ( case IUMULH: )
use_parameter (&instruction->instruction_parameters[1]);
use_parameter (&instruction->instruction_parameters[0]);
break;
- case IDIV: case IMOD:
+ case IDIV: case IMOD: case IDIVU: case IREMU:
define_scratch_register();
use_parameter (&instruction->instruction_parameters[1]);
use_parameter (&instruction->instruction_parameters[0]);
@@ -1368,6 +1574,9 @@ IF_G_POWER ( case IUMULH: )
#if !defined (G_POWER)
case IFSQRT:
#endif
+#ifdef I486
+ case IFABS:
+#endif
IF_G_SPARC (case IFMOVEHI: case IFMOVELO:)
IF_G_RISC (case IADDI: case ILSLI:)
define_parameter (&instruction->instruction_parameters[1]);
@@ -1382,7 +1591,7 @@ IF_G_RISC (case IADDI: case ILSLI:)
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:
+ case ISO: case ISGEU: case ISGTU: case ISLEU: case ISLTU: case ISNO:
#ifdef I486_USE_SCRATCH_REGISTER
define_scratch_register();
#endif
@@ -1392,6 +1601,9 @@ IF_G_RISC (case IADDI: case ILSLI:)
case IMOD:
# if defined (I486) || defined (G_POWER)
use_parameter (&instruction->instruction_parameters[1]);
+# ifdef I486
+ case IREMU:
+# endif
use_parameter (&instruction->instruction_parameters[0]);
break;
# else
@@ -1429,8 +1641,7 @@ IF_G_RISC (case IADDI: case ILSLI:)
break;
*/
case IBEQ: case IBGE: case IBGT: case IBLE: case IBLT: case IBNE:
- case IBHS:
- case IBO: case IBNO:
+ case IBO: case IBGEU: case IBGTU: case IBLEU: case IBLTU: case IBNO:
break;
default:
internal_error_in_function ("store_next_uses");
@@ -3578,6 +3789,9 @@ static void allocate_registers (struct basic_block *basic_block)
#ifndef I486_USE_SCRATCH_REGISTER
case IASR: case ILSL: case ILSR:
case IDIV:
+# ifdef I486
+ case IDIVU:
+# endif
#endif
case IEOR:
case IFADD: case IFCMP: case IFDIV: case IFMUL: case IFREM: case IFSUB:
@@ -3593,7 +3807,7 @@ IF_G_POWER ( case IUMULH: )
instruction_use_2 (instruction,USE_DEF);
allocate_scratch_register=1;
break;
- case IDIV: case IMOD:
+ case IDIV: case IMOD: case IDIVU: case IREMU:
use_scratch_register();
instruction_use_2 (instruction,USE_DEF);
allocate_scratch_register=1;
@@ -3643,6 +3857,9 @@ IF_G_POWER (case ICMPLW:)
#if !defined (G_POWER)
case IFSQRT:
#endif
+#ifdef I486
+ case IFABS:
+#endif
IF_G_SPARC (case IFMOVEHI: case IFMOVELO:)
IF_G_RISC (case IADDI: case ILSLI:)
@@ -3675,7 +3892,7 @@ IF_G_RISC (case IADDI: case ILSLI:)
break;
}
case ISEQ: case ISGE: case ISGT: case ISLE: case ISLT: case ISNE:
- case ISO: case ISNO:
+ case ISO: case ISGEU: case ISGTU: case ISLEU: case ISLTU: case ISNO:
#ifdef I486_USE_SCRATCH_REGISTER
use_scratch_register();
#endif
@@ -3697,6 +3914,9 @@ IF_G_RISC (case IADDI: case ILSLI:)
#ifndef I486_USE_SCRATCH_REGISTER
case IMOD:
# if defined (I486) || defined (G_POWER)
+# ifdef I486
+ case IREMU:
+# endif
instruction_use_2 (instruction,USE_DEF);
# else
instruction_mod_use_def_use (instruction);
@@ -3736,8 +3956,7 @@ IF_G_RISC (case IADDI: case ILSLI:)
break;
*/
case IBEQ: case IBGE: case IBGT: case IBLE: case IBLT: case IBNE:
- case IBO: case IBNO:
- case IBHS:
+ case IBO: case IBGEU: case IBGTU: case IBLEU: case IBLTU: case IBNO:
break;
default:
internal_error_in_function ("allocate_registers");
diff --git a/cgstack.c b/cgstack.c
index 73163e5..d5284d4 100644
--- a/cgstack.c
+++ b/cgstack.c
@@ -3194,7 +3194,7 @@ int block_stack_displacement;
static WORD *check_size_p;
#endif
-static int stack_access_and_adjust_a_stack_pointer (int extra_b_offset)
+static int stack_access_and_adjust_a_stack_pointer (int extra_b_offset,int do_not_alter_condition_codes)
{
int a_offset,b_offset,minimum_b_offset;
@@ -3270,32 +3270,34 @@ static int stack_access_and_adjust_a_stack_pointer (int extra_b_offset)
if (a_offset!=0)
#ifdef I486
- i_lea_id_r (a_offset,A_STACK_POINTER,A_STACK_POINTER);
-#else
+ if (do_not_alter_condition_codes)
+ i_lea_id_r (a_offset,A_STACK_POINTER,A_STACK_POINTER);
+ else
+#endif
if (a_offset>0)
i_add_i_r (a_offset,A_STACK_POINTER);
else
i_sub_i_r (-a_offset,A_STACK_POINTER);
-#endif
return b_offset;
}
-static void stack_access (void)
+static void stack_access (int do_not_alter_condition_codes)
{
register int b_offset;
- b_offset=stack_access_and_adjust_a_stack_pointer (0);
+ b_offset=stack_access_and_adjust_a_stack_pointer (0,do_not_alter_condition_codes);
if (b_offset!=0)
#ifdef I486
- i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER);
-#else
+ if (do_not_alter_condition_codes)
+ i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER);
+ else
+#endif
if (b_offset>0)
i_add_i_r (b_offset,B_STACK_POINTER);
else
i_sub_i_r (-b_offset,B_STACK_POINTER);
-#endif
}
static int local_register_allocation_and_adjust_a_stack_pointer (int extra_b_offset)
@@ -3304,7 +3306,7 @@ static int local_register_allocation_and_adjust_a_stack_pointer (int extra_b_off
get_n_virtual_registers (&n_virtual_a_regs,&n_virtual_d_regs,&n_virtual_f_regs);
do_register_allocation (last_instruction,last_block,n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,0,0);
- return stack_access_and_adjust_a_stack_pointer (extra_b_offset);
+ return stack_access_and_adjust_a_stack_pointer (extra_b_offset,0);
}
void adjust_stack_pointers (void)
@@ -3313,7 +3315,7 @@ void adjust_stack_pointers (void)
get_n_virtual_registers (&n_virtual_a_regs,&n_virtual_d_regs,&n_virtual_f_regs);
do_register_allocation (last_instruction,last_block,n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,0,0);
- stack_access();
+ stack_access (0);
}
int adjust_stack_pointers_without_altering_condition_codes (int float_condition,int condition)
@@ -3322,7 +3324,7 @@ int adjust_stack_pointers_without_altering_condition_codes (int float_condition,
get_n_virtual_registers (&n_virtual_a_regs,&n_virtual_d_regs,&n_virtual_f_regs);
condition_on_stack=do_register_allocation (last_instruction,last_block,n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,1+float_condition,condition);
- stack_access();
+ stack_access (1);
return condition_on_stack;
}
@@ -3755,14 +3757,10 @@ static void generate_code_for_basic_block (struct block_graph *next_block_graph)
}
#else
if (b_offset!=0)
-# ifdef I486
- i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER);
-# else
if (b_offset<0)
i_sub_i_r (-b_offset,B_STACK_POINTER);
else
i_add_i_r (b_offset,B_STACK_POINTER);
-# endif
# if ! defined (sparc)
{
@@ -4187,14 +4185,10 @@ void end_basic_block_with_registers (int n_a_parameters,int n_b_parameters,ULONG
b_offset=end_basic_block_with_registers_and_return_b_stack_offset (n_a_parameters,n_b_parameters,vector,N_ADDRESS_PARAMETER_REGISTERS);
if (b_offset!=0)
-#ifdef I486
- i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER);
-#else
if (b_offset>0)
i_add_i_r (b_offset,B_STACK_POINTER);
else
i_sub_i_r (-b_offset,B_STACK_POINTER);
-#endif
}
void end_stack_elements (int n_a_parameters,int n_b_parameters,ULONG vector[])
diff --git a/cgtypes.h b/cgtypes.h
index 927330f..50f2229 100644
--- a/cgtypes.h
+++ b/cgtypes.h
@@ -36,6 +36,7 @@ typedef struct label {
} label_u1;
union {
struct basic_block * u_last_lea_block; /* cgcode.c */
+ struct basic_block * u_block; /* cgopt.c */
#ifdef G_POWER
struct toc_label * u_toc_labels; /* cgpwas.c */
#endif
@@ -43,7 +44,8 @@ typedef struct label {
WORD label_last_lea_arity;
} LABEL;
-#define label_last_lea_block label_u2.u_last_lea_block
+#define label_last_lea_block label_u2.u_last_lea_block
+#define label_block label_u2.u_block
#ifdef G_POWER
# define label_toc_labels label_u2.u_toc_labels
#endif
@@ -66,6 +68,7 @@ typedef struct label {
# define DOT_O_BEFORE_LABEL 2048
# define STUB_GENERATED 4096
#endif
+#define CMP_BRANCH_BLOCK_LABEL 8192
struct label_node {
struct label_node * label_node_left;