RPA Toolkit
e9e22d85ff9489b92a5d2f63933917d1e0d9c122
[rpatk.git] / rvm / rvmoperatorbin.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 Martin Stoilov
4  *
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.
9  *
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.
14  *
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/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
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"
48
49 static rvm_binopmap_t binary_operations[RVM_OPID_LAST+1];
50
51 static void rvm_op_abort_unsigned(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, ruword op1, ruword op2)
52 {
53         RVM_ABORT(cpu, RVM_E_ILLEGAL);
54 }
55
56
57 static void rvm_op_abort_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, rword op1, rword op2)
58 {
59         RVM_ABORT(cpu, RVM_E_ILLEGAL);
60 }
61
62
63 static void rvm_op_abort_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, double op1, double op2)
64 {
65         RVM_ABORT(cpu, RVM_E_ILLEGAL);
66 }
67
68
69 static void rvm_op_binary_unsigned(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, ruword op1, ruword op2)
70 {
71         binary_operations[opid].unsigned_binop_fun(cpu, opid, res, op1, op2);
72 }
73
74
75 static void rvm_op_binary_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, rword op1, rword op2)
76 {
77         binary_operations[opid].long_binop_fun(cpu, opid, res, op1, op2);
78 }
79
80
81 static void rvm_op_binary_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, double op1, double op2)
82 {
83         binary_operations[opid].double_binop_fun(cpu, opid, res, op1, op2);
84 }
85
86
87 static void rvm_op_binary_unsigned_unsigned(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
88 {
89         rvm_op_binary_unsigned(cpu, opid, res, RVM_REG_GETU(arg1), RVM_REG_GETU(arg2));
90 }
91
92
93 static void rvm_op_binary_signed_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
94 {
95         rvm_op_binary_signed(cpu, opid, res, RVM_REG_GETL(arg1), RVM_REG_GETL(arg2));
96 }
97
98
99 static void rvm_op_binary_double_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
100 {
101         rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(arg1), (double)RVM_REG_GETL(arg2));
102 }
103
104
105 void rvm_op_binary_signed_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
106 {
107         rvm_op_binary_double(cpu, opid, res, (double)RVM_REG_GETL(arg1), RVM_REG_GETD(arg2));
108 }
109
110
111 static void rvm_op_binary_double_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
112 {
113         rvm_op_binary_double(cpu, opid, res, RVM_REG_GETD(arg1), RVM_REG_GETD(arg2));
114 }
115
116
117 static void rvm_op_binary_string_double(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
118 {
119         rvmreg_t s;
120
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));
124 }
125
126
127 static void rvm_op_binary_string_signed(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
128 {
129         rvmreg_t s;
130
131         if (rvm_reg_str2num(&s, arg1) < 0)
132                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
133
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));
136         } else {
137                 rvm_op_binary_signed(cpu, opid, res, RVM_REG_GETL(&s), RVM_REG_GETL(arg2));
138         }
139 }
140
141
142 static void rvm_op_binary_double_string(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
143 {
144         rvmreg_t s;
145
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));
149 }
150
151
152 static void rvm_op_binary_signed_string(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
153 {
154         rvmreg_t s;
155
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));
160         } else {
161                 rvm_op_binary_signed(cpu, opid, res, RVM_REG_GETL(arg1), RVM_REG_GETL(&s));
162         }
163 }
164
165
166 static void rvm_op_binary_nan(rvmcpu_t *cpu, ruint16 opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
167 {
168         rvm_reg_cleanup(res);
169         RVM_REG_SETTYPE(res, RVM_DTYPE_NAN);
170 }
171
172
173 void rvm_op_binary_insert(rvm_opmap_t *opmap, ruint16 opid, rvm_binop_unsigned u, rvm_binop_signed l, rvm_binop_double d)
174 {
175         int i;
176
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);
182
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);
188         }
189
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);
214 }
215
216
217 void rvm_op_binary_init(rvm_opmap_t *opmap)
218 {
219         int i;
220
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;
226         }
227
228         rvm_op_binary_insert(opmap, RVM_OPID_ADD, rvm_op_add_unsigned, rvm_op_add_signed, rvm_op_add_double);
229         /*
230          * Overwrite RVM_OPID_ADD for string concatenation
231          */
232
233         rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_string, RVM_DTYPE_STRING, RVM_DTYPE_STRING);
234         rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_signed, RVM_DTYPE_STRING, RVM_DTYPE_SINGED);
235         rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_signed, RVM_DTYPE_STRING, RVM_DTYPE_UNSIGNED);
236         rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_signed_string, RVM_DTYPE_SINGED, RVM_DTYPE_STRING);
237         rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_signed_string, RVM_DTYPE_UNSIGNED, RVM_DTYPE_STRING);
238         rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_double, RVM_DTYPE_STRING, RVM_DTYPE_DOUBLE);
239         rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_double_string, RVM_DTYPE_DOUBLE, RVM_DTYPE_STRING);
240
241
242         rvm_op_binary_insert(opmap, RVM_OPID_SUB, rvm_op_sub_unsigned, rvm_op_sub_signed, rvm_op_sub_double);
243         rvm_op_binary_insert(opmap, RVM_OPID_MUL, rvm_op_mul_unsigned, rvm_op_mul_signed, rvm_op_mul_double);
244         rvm_op_binary_insert(opmap, RVM_OPID_DIV, rvm_op_div_unsigned, rvm_op_div_signed, rvm_op_div_double);
245         rvm_op_binary_insert(opmap, RVM_OPID_LSL, rvm_op_lsl_unsigned, rvm_op_lsl_signed, rvm_op_lsl_double);
246         rvm_op_binary_insert(opmap, RVM_OPID_LSR, rvm_op_lsr_unsigned, rvm_op_lsr_signed, rvm_op_lsr_double);
247         rvm_op_binary_insert(opmap, RVM_OPID_LSRU, rvm_op_lsru_unsigned, rvm_op_lsru_signed, rvm_op_lsru_double);
248         rvm_op_binary_insert(opmap, RVM_OPID_AND, rvm_op_and_unsigned, rvm_op_and_signed, rvm_op_and_double);
249         rvm_op_binary_insert(opmap, RVM_OPID_XOR, rvm_op_xor_unsigned, rvm_op_xor_signed, rvm_op_xor_double);
250         rvm_op_binary_insert(opmap, RVM_OPID_OR, rvm_op_or_unsigned, rvm_op_or_signed, rvm_op_or_double);
251         rvm_op_binary_insert(opmap, RVM_OPID_CMP, rvm_op_cmp_unsigned, rvm_op_cmp_signed, rvm_op_cmp_double);
252         rvm_op_binary_insert(opmap, RVM_OPID_CMN, rvm_op_cmn_unsigned, rvm_op_cmn_signed, rvm_op_cmn_double);
253         rvm_op_binary_insert(opmap, RVM_OPID_MOD, rvm_op_mod_unsigned, rvm_op_mod_signed, rvm_op_mod_double);
254         rvm_op_binary_insert(opmap, RVM_OPID_LOGICOR, rvm_op_logicor_unsigned, rvm_op_logicor_signed, rvm_op_logicor_double);
255         rvm_op_binary_insert(opmap, RVM_OPID_LOGICAND, rvm_op_logicand_unsigned, rvm_op_logicand_signed, rvm_op_logicand_double);
256         rvm_op_binary_insert(opmap, RVM_OPID_EQ, rvm_op_eq_unsigned, rvm_op_eq_signed, rvm_op_eq_double);
257         rvm_op_binary_insert(opmap, RVM_OPID_NOTEQ, rvm_op_noteq_unsigned, rvm_op_noteq_signed, rvm_op_noteq_double);
258         rvm_op_binary_insert(opmap, RVM_OPID_LESS, rvm_op_less_unsigned, rvm_op_less_signed, rvm_op_less_double);
259         rvm_op_binary_insert(opmap, RVM_OPID_LESSEQ, rvm_op_lesseq_unsigned, rvm_op_lesseq_signed, rvm_op_lesseq_double);
260         rvm_op_binary_insert(opmap, RVM_OPID_GREATER, rvm_op_greater_unsigned, rvm_op_greater_signed, rvm_op_greater_double);
261         rvm_op_binary_insert(opmap, RVM_OPID_GREATEREQ, rvm_op_greatereq_unsigned, rvm_op_greatereq_signed, rvm_op_greatereq_double);
262 }