2 * Regular Pattern Analyzer (RPA)
3 * Copyright (c) 2009-2010 Martin Stoilov
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * Martin Stoilov <martin@rpasearch.com>
21 #include "rvm/rvmoperator.h"
22 #include "rvm/rvmreg.h"
23 #include "rvm/rvmoperatornot.h"
24 #include "rvm/rvmoperatorbin.h"
25 #include "rvm/rvmoperatorlsr.h"
26 #include "rvm/rvmoperatorlsru.h"
27 #include "rvm/rvmoperatoreq.h"
28 #include "rvm/rvmoperatornoteq.h"
29 #include "rvm/rvmoperatorlogicor.h"
30 #include "rvm/rvmoperatorlogicand.h"
31 #include "rvm/rvmoperatorless.h"
32 #include "rvm/rvmoperatorlesseq.h"
33 #include "rvm/rvmoperatorgreater.h"
34 #include "rvm/rvmoperatorgreatereq.h"
35 #include "rvm/rvmoperatoror.h"
36 #include "rvm/rvmoperatorxor.h"
37 #include "rvm/rvmoperatorcast.h"
38 #include "rvm/rvmoperatorsub.h"
39 #include "rvm/rvmoperatoradd.h"
40 #include "rvm/rvmoperatormod.h"
41 #include "rvm/rvmoperatormul.h"
42 #include "rvm/rvmoperatorlsl.h"
43 #include "rvm/rvmoperatorcmn.h"
44 #include "rvm/rvmoperatorcmp.h"
45 #include "rvm/rvmoperatorand.h"
46 #include "rvm/rvmoperatorcat.h"
47 #include "rvm/rvmoperatordiv.h"
49 static rvm_binopmap_t binary_operations[RVM_OPID_LAST+1];
51 static void rvm_op_abort_unsigned(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, ruword op1, ruword op2)
53 RVM_ABORT(cpu, RVM_E_ILLEGAL);
57 static void rvm_op_abort_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, rword op1, rword op2)
59 RVM_ABORT(cpu, RVM_E_ILLEGAL);
63 static void rvm_op_abort_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, double op1, double op2)
65 RVM_ABORT(cpu, RVM_E_ILLEGAL);
69 static void rvm_op_binary_unsigned(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, ruword op1, ruword op2)
71 binary_operations[opid].unsigned_binop_fun(cpu, opid, res, op1, op2);
75 static void rvm_op_binary_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, rword op1, rword op2)
77 binary_operations[opid].long_binop_fun(cpu, opid, res, op1, op2);
81 static void rvm_op_binary_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, double op1, double op2)
83 binary_operations[opid].double_binop_fun(cpu, opid, res, op1, op2);
87 static void rvm_op_binary_unsigned_unsigned(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
89 rvm_op_binary_unsigned(cpu, opid, res, RVM_REG_GETU(arg1), RVM_REG_GETU(arg2));
93 static void rvm_op_binary_signed_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
95 rvm_op_binary_signed(cpu, opid, res, RVM_REG_GETL(arg1), RVM_REG_GETL(arg2));
99 static void rvm_op_binary_double_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
101 rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(arg1), (double)RVM_REG_GETL(arg2));
105 void rvm_op_binary_signed_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
107 rvm_op_binary_double(cpu, opid, res, (double)RVM_REG_GETL(arg1), RVM_REG_GETD(arg2));
111 static void rvm_op_binary_double_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
113 rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(arg1), RVM_REG_GETD(arg2));
117 static void rvm_op_binary_string_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
121 if (rvm_reg_str2double(&s, arg1) < 0)
122 RVM_ABORT(cpu, RVM_E_ILLEGAL);
123 rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(&s), RVM_REG_GETD(arg2));
127 static void rvm_op_binary_string_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
131 if (rvm_reg_str2num(&s, arg1) < 0)
132 RVM_ABORT(cpu, RVM_E_ILLEGAL);
134 if (rvm_reg_gettype(&s) == RVM_DTYPE_DOUBLE) {
135 rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(&s), (double)RVM_REG_GETL(arg2));
137 rvm_op_binary_signed(cpu, opid, res, RVM_REG_GETL(&s), RVM_REG_GETL(arg2));
142 static void rvm_op_binary_double_string(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
146 if (rvm_reg_str2double(&s, arg2) < 0)
147 RVM_ABORT(cpu, RVM_E_ILLEGAL);
148 rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(arg1), RVM_REG_GETD(&s));
152 static void rvm_op_binary_signed_string(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
156 if (rvm_reg_str2num(&s, arg2) < 0)
157 RVM_ABORT(cpu, RVM_E_ILLEGAL);
158 if (rvm_reg_gettype(&s) == RVM_DTYPE_DOUBLE) {
159 rvm_op_binary_double(cpu, opid, res, (double)RVM_REG_GETL(arg1), RVM_REG_GETD(&s));
161 rvm_op_binary_signed(cpu, opid, res, RVM_REG_GETL(arg1), RVM_REG_GETL(&s));
166 static void rvm_op_binary_nan(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
168 rvm_reg_cleanup(res);
169 RVM_REG_SETTYPE(res, RVM_DTYPE_NAN);
173 void rvm_op_binary_insert(rvm_opmap_t *opmap, ruint16 opid, rvm_binop_unsigned u, rvm_binop_signed l, rvm_binop_double d)
177 binary_operations[opid].opid = opid;
178 binary_operations[opid].unsigned_binop_fun = u;
179 binary_operations[opid].long_binop_fun = l;
180 binary_operations[opid].double_binop_fun = d;
181 rvm_opmap_add_binary_operator(opmap, opid);
183 for (i = 0; i < RVM_DTYPE_USER; i++) {
184 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_nan, RVM_DTYPE_NAN, i);
185 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_nan, RVM_DTYPE_UNDEF, i);
186 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_nan, i, RVM_DTYPE_NAN);
187 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_nan, i, RVM_DTYPE_UNDEF);
190 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_BOOLEAN, RVM_DTYPE_BOOLEAN);
191 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_BOOLEAN, RVM_DTYPE_UNSIGNED);
192 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_signed, RVM_DTYPE_BOOLEAN, RVM_DTYPE_SINGED);
193 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_double, RVM_DTYPE_BOOLEAN, RVM_DTYPE_DOUBLE);
194 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_string, RVM_DTYPE_BOOLEAN, RVM_DTYPE_STRING);
195 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_UNSIGNED, RVM_DTYPE_BOOLEAN);
196 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_SINGED, RVM_DTYPE_BOOLEAN);
197 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_signed, RVM_DTYPE_DOUBLE, RVM_DTYPE_BOOLEAN);
198 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_string_signed, RVM_DTYPE_STRING, RVM_DTYPE_BOOLEAN);
199 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_unsigned_unsigned, RVM_DTYPE_UNSIGNED, RVM_DTYPE_UNSIGNED);
200 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_double, RVM_DTYPE_DOUBLE, RVM_DTYPE_DOUBLE);
201 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_signed, RVM_DTYPE_SINGED, RVM_DTYPE_SINGED);
202 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_signed, RVM_DTYPE_UNSIGNED, RVM_DTYPE_SINGED);
203 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_signed, RVM_DTYPE_SINGED, RVM_DTYPE_UNSIGNED);
204 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_double, RVM_DTYPE_SINGED, RVM_DTYPE_DOUBLE);
205 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_double, RVM_DTYPE_UNSIGNED, RVM_DTYPE_DOUBLE);
206 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_signed, RVM_DTYPE_DOUBLE, RVM_DTYPE_SINGED);
207 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_signed, RVM_DTYPE_DOUBLE, RVM_DTYPE_UNSIGNED);
208 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_string_signed, RVM_DTYPE_STRING, RVM_DTYPE_UNSIGNED);
209 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_string_signed, RVM_DTYPE_STRING, RVM_DTYPE_SINGED);
210 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_string_double, RVM_DTYPE_STRING, RVM_DTYPE_DOUBLE);
211 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_string, RVM_DTYPE_UNSIGNED, RVM_DTYPE_STRING);
212 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_signed_string, RVM_DTYPE_SINGED, RVM_DTYPE_STRING);
213 rvm_opmap_set_binary_handler(opmap, opid, rvm_op_binary_double_string, RVM_DTYPE_DOUBLE, RVM_DTYPE_STRING);
217 void rvm_op_binary_init(rvm_opmap_t *opmap)
221 for (i = 0; i < sizeof(binary_operations)/sizeof(binary_operations[0]); i++) {
222 binary_operations[i].opid = RVM_OPID_NONE;
223 binary_operations[i].unsigned_binop_fun = rvm_op_abort_unsigned;
224 binary_operations[i].long_binop_fun = rvm_op_abort_signed;
225 binary_operations[i].double_binop_fun = rvm_op_abort_double;
228 rvm_op_binary_insert(opmap, RVM_OPID_SUB, rvm_op_sub_unsigned, rvm_op_sub_signed, rvm_op_sub_double);
229 rvm_op_binary_insert(opmap, RVM_OPID_MUL, rvm_op_mul_unsigned, rvm_op_mul_signed, rvm_op_mul_double);
230 rvm_op_binary_insert(opmap, RVM_OPID_DIV, rvm_op_div_unsigned, rvm_op_div_signed, rvm_op_div_double);
231 rvm_op_binary_insert(opmap, RVM_OPID_LSL, rvm_op_lsl_unsigned, rvm_op_lsl_signed, rvm_op_lsl_double);
232 rvm_op_binary_insert(opmap, RVM_OPID_LSR, rvm_op_lsr_unsigned, rvm_op_lsr_signed, rvm_op_lsr_double);
233 rvm_op_binary_insert(opmap, RVM_OPID_LSRU, rvm_op_lsru_unsigned, rvm_op_lsru_signed, rvm_op_lsru_double);
234 rvm_op_binary_insert(opmap, RVM_OPID_AND, rvm_op_and_unsigned, rvm_op_and_signed, rvm_op_and_double);
235 rvm_op_binary_insert(opmap, RVM_OPID_XOR, rvm_op_xor_unsigned, rvm_op_xor_signed, rvm_op_xor_double);
236 rvm_op_binary_insert(opmap, RVM_OPID_OR, rvm_op_or_unsigned, rvm_op_or_signed, rvm_op_or_double);
237 rvm_op_binary_insert(opmap, RVM_OPID_CMP, rvm_op_cmp_unsigned, rvm_op_cmp_signed, rvm_op_cmp_double);
238 rvm_op_binary_insert(opmap, RVM_OPID_CMN, rvm_op_cmn_unsigned, rvm_op_cmn_signed, rvm_op_cmn_double);
239 rvm_op_binary_insert(opmap, RVM_OPID_MOD, rvm_op_mod_unsigned, rvm_op_mod_signed, rvm_op_mod_double);
240 rvm_op_binary_insert(opmap, RVM_OPID_LOGICOR, rvm_op_logicor_unsigned, rvm_op_logicor_signed, rvm_op_logicor_double);
241 rvm_op_binary_insert(opmap, RVM_OPID_LOGICAND, rvm_op_logicand_unsigned, rvm_op_logicand_signed, rvm_op_logicand_double);
242 rvm_op_binary_insert(opmap, RVM_OPID_NOTEQ, rvm_op_noteq_unsigned, rvm_op_noteq_signed, rvm_op_noteq_double);
243 rvm_op_binary_insert(opmap, RVM_OPID_LESS, rvm_op_less_unsigned, rvm_op_less_signed, rvm_op_less_double);
244 rvm_op_binary_insert(opmap, RVM_OPID_LESSEQ, rvm_op_lesseq_unsigned, rvm_op_lesseq_signed, rvm_op_lesseq_double);
245 rvm_op_binary_insert(opmap, RVM_OPID_GREATER, rvm_op_greater_unsigned, rvm_op_greater_signed, rvm_op_greater_double);
246 rvm_op_binary_insert(opmap, RVM_OPID_GREATEREQ, rvm_op_greatereq_unsigned, rvm_op_greatereq_signed, rvm_op_greatereq_double);
248 rvm_op_binary_insert(opmap, RVM_OPID_ADD, rvm_op_add_unsigned, rvm_op_add_signed, rvm_op_add_double);
250 * Overwrite RVM_OPID_ADD for string concatenation
252 rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_string, RVM_DTYPE_STRING, RVM_DTYPE_STRING);
253 rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_signed, RVM_DTYPE_STRING, RVM_DTYPE_SINGED);
254 rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_signed, RVM_DTYPE_STRING, RVM_DTYPE_UNSIGNED);
255 rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_signed_string, RVM_DTYPE_SINGED, RVM_DTYPE_STRING);
256 rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_signed_string, RVM_DTYPE_UNSIGNED, RVM_DTYPE_STRING);
257 rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_double, RVM_DTYPE_STRING, RVM_DTYPE_DOUBLE);
258 rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_double_string, RVM_DTYPE_DOUBLE, RVM_DTYPE_STRING);
260 rvm_op_binary_insert(opmap, RVM_OPID_EQ, rvm_op_eq_unsigned, rvm_op_eq_signed, rvm_op_eq_double);
261 rvm_opmap_set_binary_handler(opmap, RVM_OPID_EQ, rvm_op_eq_string_string, RVM_DTYPE_STRING, RVM_DTYPE_STRING);
263 rvm_op_binary_insert(opmap, RVM_OPID_NOTEQ, rvm_op_noteq_unsigned, rvm_op_noteq_signed, rvm_op_noteq_double);
264 rvm_opmap_set_binary_handler(opmap, RVM_OPID_NOTEQ, rvm_op_noteq_string_string, RVM_DTYPE_STRING, RVM_DTYPE_STRING);