RPA Toolkit
implemented break and continue, also added string concatination
[rpatk.git] / rvm / rvmoperatorbin.c
1 #include "rvmoperator.h"
2 #include "rvmreg.h"
3 #include "rvmoperatornot.h"
4 #include "rvmoperatorbin.h"
5 #include "rvmoperatorlsr.h"
6 #include "rvmoperatorlsru.h"
7 #include "rvmoperatoreq.h"
8 #include "rvmoperatornoteq.h"
9 #include "rvmoperatorlogicor.h"
10 #include "rvmoperatorlogicand.h"
11 #include "rvmoperatorless.h"
12 #include "rvmoperatorlesseq.h"
13 #include "rvmoperatorgreater.h"
14 #include "rvmoperatorgreatereq.h"
15 #include "rvmoperatoror.h"
16 #include "rvmoperatorxor.h"
17 #include "rvmoperatorcast.h"
18 #include "rvmoperatorsub.h"
19 #include "rvmoperatoradd.h"
20 #include "rvmoperatormod.h"
21 #include "rvmoperatormul.h"
22 #include "rvmoperatorlsl.h"
23 #include "rvmoperatorcmn.h"
24 #include "rvmoperatorcmp.h"
25 #include "rvmoperatorand.h"
26 #include "rvmoperatorcat.h"
27 #include "rvmoperatordiv.h"
28
29 static rvm_binopmap_t binary_operations[RVM_OPID_LAST+1];
30
31 static void rvm_op_abort_unsigned(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rword op1, rword op2)
32 {
33         RVM_ABORT(cpu, RVM_E_ILLEGAL);
34 }
35
36
37 static void rvm_op_abort_long(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rlong op1, rlong op2)
38 {
39         RVM_ABORT(cpu, RVM_E_ILLEGAL);
40 }
41
42
43 static void rvm_op_abort_double(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rdouble op1, rdouble op2)
44 {
45         RVM_ABORT(cpu, RVM_E_ILLEGAL);
46 }
47
48
49 inline void rvm_op_binary_unsigned(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rword op1, rword op2)
50 {
51         binary_operations[opid].unsigned_binop_fun(cpu, opid, res, op1, op2);
52 }
53
54
55 inline void rvm_op_binary_long(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rlong op1, rlong op2)
56 {
57         binary_operations[opid].long_binop_fun(cpu, opid, res, op1, op2);
58 }
59
60
61 inline void rvm_op_binary_double(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rdouble op1, rdouble op2)
62 {
63         binary_operations[opid].double_binop_fun(cpu, opid, res, op1, op2);
64 }
65
66
67 static void rvm_op_binary_unsigned_unsigned(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
68 {
69         rvm_op_binary_unsigned(cpu, opid, res, RVM_REG_GETU(arg1), RVM_REG_GETU(arg2));
70 }
71
72
73 static void rvm_op_binary_long_long(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
74 {
75         rvm_op_binary_long(cpu, opid, res, RVM_REG_GETL(arg1), RVM_REG_GETL(arg2));
76 }
77
78
79 static void rvm_op_binary_double_long(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
80 {
81         rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(arg1), RVM_REG_GETL(arg2));
82 }
83
84
85 void rvm_op_binary_long_double(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
86 {
87         rvm_op_binary_double(cpu, opid, res, RVM_REG_GETL(arg1), RVM_REG_GETD(arg2));
88 }
89
90
91 static void rvm_op_binary_double_double(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
92 {
93         rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(arg1), RVM_REG_GETD(arg2));
94 }
95
96
97 static void rvm_op_binary_string_double(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
98 {
99         rvmreg_t s;
100
101         if (rvm_reg_str2double(&s, arg1) < 0)
102                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
103         rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(&s), RVM_REG_GETD(arg2));
104 }
105
106
107 static void rvm_op_binary_string_long(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
108 {
109         rvmreg_t s;
110
111         if (rvm_reg_str2num(&s, arg1) < 0)
112                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
113
114         if (rvm_reg_gettype(&s) == RVM_DTYPE_DOUBLE) {
115                 rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(&s), RVM_REG_GETL(arg2));
116         } else {
117                 rvm_op_binary_long(cpu, opid, res, RVM_REG_GETL(&s), RVM_REG_GETL(arg2));
118         }
119 }
120
121
122 static void rvm_op_binary_double_string(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
123 {
124         rvmreg_t s;
125
126         if (rvm_reg_str2double(&s, arg2) < 0)
127                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
128         rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(arg1), RVM_REG_GETD(&s));
129 }
130
131
132 static void rvm_op_binary_long_string(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
133 {
134         rvmreg_t s;
135
136         if (rvm_reg_str2num(&s, arg2) < 0)
137                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
138         if (rvm_reg_gettype(&s) == RVM_DTYPE_DOUBLE) {
139                 rvm_op_binary_double(cpu, opid, res, RVM_REG_GETL(arg1), RVM_REG_GETD(&s));
140         } else {
141                 rvm_op_binary_long(cpu, opid, res, RVM_REG_GETL(arg1), RVM_REG_GETL(&s));
142         }
143 }
144
145
146 void rvm_op_binary_insert(rvm_opmap_t *opmap, rushort opid, rvm_binop_unsigned u, rvm_binop_long l, rvm_binop_double d)
147 {
148         binary_operations[opid].opid = opid;
149         binary_operations[opid].unsigned_binop_fun = u;
150         binary_operations[opid].long_binop_fun = l;
151         binary_operations[opid].double_binop_fun = d;
152         rvm_opmap_add_binary_operator(opmap, opid);
153         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_BOOLEAN, RVM_DTYPE_BOOLEAN);
154         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_BOOLEAN, RVM_DTYPE_UNSIGNED);
155         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_long, RVM_DTYPE_BOOLEAN, RVM_DTYPE_LONG);
156         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_double, RVM_DTYPE_BOOLEAN, RVM_DTYPE_DOUBLE);
157         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_string, RVM_DTYPE_BOOLEAN, RVM_DTYPE_STRING);
158         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_UNSIGNED, RVM_DTYPE_BOOLEAN);
159         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_LONG, RVM_DTYPE_BOOLEAN);
160         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_long, RVM_DTYPE_DOUBLE, RVM_DTYPE_BOOLEAN);
161         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_string_long, RVM_DTYPE_STRING, RVM_DTYPE_BOOLEAN);
162         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_UNSIGNED, RVM_DTYPE_UNSIGNED);
163         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_double, RVM_DTYPE_DOUBLE, RVM_DTYPE_DOUBLE);
164         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_long, RVM_DTYPE_LONG, RVM_DTYPE_LONG);
165         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_long, RVM_DTYPE_UNSIGNED, RVM_DTYPE_LONG);
166         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_long, RVM_DTYPE_LONG, RVM_DTYPE_UNSIGNED);
167         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_double, RVM_DTYPE_LONG, RVM_DTYPE_DOUBLE);
168         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_double, RVM_DTYPE_UNSIGNED, RVM_DTYPE_DOUBLE);
169         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_long, RVM_DTYPE_DOUBLE, RVM_DTYPE_LONG);
170         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_long, RVM_DTYPE_DOUBLE, RVM_DTYPE_UNSIGNED);
171         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_string_long, RVM_DTYPE_STRING, RVM_DTYPE_UNSIGNED);
172         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_string_long, RVM_DTYPE_STRING, RVM_DTYPE_LONG);
173         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_string_double, RVM_DTYPE_STRING, RVM_DTYPE_DOUBLE);
174         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_string, RVM_DTYPE_UNSIGNED, RVM_DTYPE_STRING);
175         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_long_string, RVM_DTYPE_LONG, RVM_DTYPE_STRING);
176         rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_string, RVM_DTYPE_DOUBLE, RVM_DTYPE_STRING);
177 }
178
179
180 void rvm_op_binary_init(rvm_opmap_t *opmap)
181 {
182         int i;
183
184         for (i = 0; i < sizeof(binary_operations)/sizeof(binary_operations[0]); i++) {
185                 binary_operations[i].opid = RVM_OPID_NONE;
186                 binary_operations[i].unsigned_binop_fun = rvm_op_abort_unsigned;
187                 binary_operations[i].long_binop_fun = rvm_op_abort_long;
188                 binary_operations[i].double_binop_fun = rvm_op_abort_double;
189         }
190
191         rvm_op_binary_insert(opmap, RVM_OPID_ADD, rvm_op_add_unsigned, rvm_op_add_long, rvm_op_add_double);
192         /*
193          * Overwrite RVM_OPID_ADD for string concatenation
194          */
195         rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_string, RVM_DTYPE_STRING, RVM_DTYPE_STRING);
196
197
198         rvm_op_binary_insert(opmap, RVM_OPID_SUB, rvm_op_sub_unsigned, rvm_op_sub_long, rvm_op_sub_double);
199         rvm_op_binary_insert(opmap, RVM_OPID_MUL, rvm_op_mul_unsigned, rvm_op_mul_long, rvm_op_mul_double);
200         rvm_op_binary_insert(opmap, RVM_OPID_DIV, rvm_op_div_unsigned, rvm_op_div_long, rvm_op_div_double);
201         rvm_op_binary_insert(opmap, RVM_OPID_LSL, rvm_op_lsl_unsigned, rvm_op_lsl_long, rvm_op_lsl_double);
202         rvm_op_binary_insert(opmap, RVM_OPID_LSR, rvm_op_lsr_unsigned, rvm_op_lsr_long, rvm_op_lsr_double);
203         rvm_op_binary_insert(opmap, RVM_OPID_LSRU, rvm_op_lsru_unsigned, rvm_op_lsru_long, rvm_op_lsru_double);
204         rvm_op_binary_insert(opmap, RVM_OPID_AND, rvm_op_and_unsigned, rvm_op_and_long, rvm_op_and_double);
205         rvm_op_binary_insert(opmap, RVM_OPID_XOR, rvm_op_xor_unsigned, rvm_op_xor_long, rvm_op_xor_double);
206         rvm_op_binary_insert(opmap, RVM_OPID_OR, rvm_op_or_unsigned, rvm_op_or_long, rvm_op_or_double);
207         rvm_op_binary_insert(opmap, RVM_OPID_CMP, rvm_op_cmp_unsigned, rvm_op_cmp_long, rvm_op_cmp_double);
208         rvm_op_binary_insert(opmap, RVM_OPID_CMN, rvm_op_cmn_unsigned, rvm_op_cmn_long, rvm_op_cmn_double);
209         rvm_op_binary_insert(opmap, RVM_OPID_MOD, rvm_op_mod_unsigned, rvm_op_mod_long, rvm_op_mod_double);
210         rvm_op_binary_insert(opmap, RVM_OPID_LOGICOR, rvm_op_logicor_unsigned, rvm_op_logicor_long, rvm_op_logicor_double);
211         rvm_op_binary_insert(opmap, RVM_OPID_LOGICAND, rvm_op_logicand_unsigned, rvm_op_logicand_long, rvm_op_logicand_double);
212         rvm_op_binary_insert(opmap, RVM_OPID_EQ, rvm_op_eq_unsigned, rvm_op_eq_long, rvm_op_eq_double);
213         rvm_op_binary_insert(opmap, RVM_OPID_NOTEQ, rvm_op_noteq_unsigned, rvm_op_noteq_long, rvm_op_noteq_double);
214         rvm_op_binary_insert(opmap, RVM_OPID_LESS, rvm_op_less_unsigned, rvm_op_less_long, rvm_op_less_double);
215         rvm_op_binary_insert(opmap, RVM_OPID_LESSEQ, rvm_op_lesseq_unsigned, rvm_op_lesseq_long, rvm_op_lesseq_double);
216         rvm_op_binary_insert(opmap, RVM_OPID_GREATER, rvm_op_greater_unsigned, rvm_op_greater_long, rvm_op_greater_double);
217         rvm_op_binary_insert(opmap, RVM_OPID_GREATEREQ, rvm_op_greatereq_unsigned, rvm_op_greatereq_long, rvm_op_greatereq_double);
218 }