RPA Toolkit
adding rvm_compiler_t to the rpagen test
[rpatk.git] / rvm / rvmcpu.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 <stdio.h>
22 #include <stdarg.h>
23 #include "rvmcpu.h"
24 #include "rvmoperator.h"
25 #include "rvmoperatorcast.h"
26 #include "rvmoperatoradd.h"
27 #include "rvmoperatorsub.h"
28 #include "rvmoperatormul.h"
29 #include "rvmoperatordiv.h"
30 #include "rmem.h"
31 #include "rstring.h"
32 #include "rvmreg.h"
33
34
35 static const char *stropcalls[] = {
36         "RVM_EXT",
37         "RVM_PRN",
38         "RVM_ASR",
39         "RVM_SWI",
40         "RVM_MOV",
41         "RVM_ADD",
42         "RVM_ADDS",
43         "RVM_ADC",
44         "RVM_AND",
45         "RVM_BIC",
46         "RVM_CLZ",
47         "RVM_CMN",
48         "RVM_XOR",
49         "RVM_SUB",
50         "RVM_SUBS",
51         "RVM_SBC",
52         "RVM_MUL",
53         "RVM_MLS",
54         "RVM_MULS",
55         "RVM_NOT",
56         "RVM_DIV",
57         "RVM_DVS",
58         "RVM_DIVS",
59         "RVM_BL",
60         "RVM_B",
61         "RVM_STR",
62         "RVM_STRP",
63         "RVM_STRB",
64         "RVM_STRH",
65         "RVM_STRW",
66         "RVM_STRR",
67         "RVM_LDR",
68         "RVM_LDRP",
69         "RVM_LDRB",
70         "RVM_LDRH",
71         "RVM_LDRW",
72         "RVM_LDRR",
73         "RVM_LSL",
74         "RVM_LSR",
75         "RVM_LSRS",
76         "RVM_STM",
77         "RVM_LDM",
78         "RVM_STS",
79         "RVM_LDS",
80         "RVM_ORR",
81         "RVM_PUSH",
82         "RVM_POP",
83         "RVM_CMP",
84         "RVM_NOP",
85         "RVM_BEQ",
86         "RVM_BNEQ",
87         "RVM_BLEQ",
88         "RVM_BGEQ",
89         "RVM_BLES",
90         "RVM_BGRE",
91         "RVM_RET",
92         "RVM_ROR",
93         "RVM_PUSHM",
94         "RVM_POPM",     
95         "RVM_TST",      
96         "RVM_TEQ",
97         "RVM_CAST",             /* Cast: op1 = (op3)op2 */
98         "RVM_TYPE",             /* Type: op1 = typeof(op2) */
99         "RVM_EMOV",
100         "RVM_EADD",
101         "RVM_ESUB",
102         "RVM_EMUL",
103         "RVM_EDIV",
104         "RVM_ELSL",
105         "RVM_ELSR",
106         "RVM_EAND",
107         "RVM_EORR",
108         "RVM_EXOR",
109         "RVM_ENOT",
110         "RVM_ECMP",
111         "RVM_ECMN",
112         "UNKNOWN",
113         "UNKNOWN",
114         "UNKNOWN",
115         "UNKNOWN",
116         "UNKNOWN",
117         "UNKNOWN",
118         "UNKNOWN",
119         "UNKNOWN",
120         "UNKNOWN",
121         "UNKNOWN",
122 };
123
124
125 static void rvm_op_b(rvmcpu_t *cpu, rvm_asmins_t *ins)
126 {
127         RVM_CPUREG_INCIP(cpu, PC, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
128 }
129
130
131 static void rvm_op_beq(rvmcpu_t *cpu, rvm_asmins_t *ins)
132 {
133         if ((cpu->status & RVM_STATUS_Z))
134                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
135 }
136
137
138 static void rvm_op_bneq(rvmcpu_t *cpu, rvm_asmins_t *ins)
139 {
140         if ((cpu->status & RVM_STATUS_Z) == 0)
141                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
142 }
143
144
145 static void rvm_op_bleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
146 {
147         if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z))
148                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
149 }
150
151 static void rvm_op_bgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
152 {
153         if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1)
154                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
155 }
156
157
158 static void rvm_op_bles(rvmcpu_t *cpu, rvm_asmins_t *ins)
159 {
160         if ((cpu->status & RVM_STATUS_N))
161                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
162 }
163
164
165 static void rvm_op_bgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
166 {
167         if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0)
168                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETU(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
169 }
170
171
172 static void rvm_op_bl(rvmcpu_t *cpu, rvm_asmins_t *ins)
173 {
174         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
175         RVM_CPUREG_INCIP(cpu, PC, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
176 }
177
178
179 static void rvm_op_exit(rvmcpu_t *cpu, rvm_asmins_t *ins)
180 {
181
182 }
183
184
185 static void rvm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
186 {
187         RVM_CPUREG_SET(cpu, ins->op1, RVM_CPUREG_GET(cpu, ins->op2));
188 }
189
190
191 static void rvm_op_ldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
192 {
193         RVM_CPUREG_SETU(cpu, ins->op1, *((rword*)RVM_CPUREG_GETU(cpu, ins->op2)));
194         
195 }
196
197
198 static void rvm_op_ldrp(rvmcpu_t *cpu, rvm_asmins_t *ins)
199 {
200         RVM_CPUREG_SETU(cpu, ins->op1, *((rpointer*)RVM_CPUREG_GETU(cpu, ins->op2)));
201 }
202
203
204 static void rvm_op_ldrb(rvmcpu_t *cpu, rvm_asmins_t *ins)
205 {
206         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint8*)RVM_CPUREG_GETU(cpu, ins->op2)));
207 }
208
209
210 static void rvm_op_ldrh(rvmcpu_t *cpu, rvm_asmins_t *ins)
211 {
212         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint16*)RVM_CPUREG_GETU(cpu, ins->op2)));
213 }
214
215
216 static void rvm_op_ldrw(rvmcpu_t *cpu, rvm_asmins_t *ins)
217 {
218         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint32*)RVM_CPUREG_GETU(cpu, ins->op2)));
219 }
220
221
222 static void rvm_op_ldrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
223 {
224         RVM_CPUREG_SET(cpu, ins->op1, *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)));
225 }
226
227
228 static void rvm_op_str(rvmcpu_t *cpu, rvm_asmins_t *ins)
229 {
230         *((rword*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GETU(cpu, ins->op1);
231 }
232
233
234 static void rvm_op_strp(rvmcpu_t *cpu, rvm_asmins_t *ins)
235 {
236         *((rpointer*)RVM_CPUREG_GETP(cpu, ins->op2)) = (rpointer)RVM_CPUREG_GETP(cpu, ins->op1);
237 }
238
239
240 static void rvm_op_strb(rvmcpu_t *cpu, rvm_asmins_t *ins)
241 {
242         *((ruint8*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint8)RVM_CPUREG_GETU(cpu, ins->op1);
243 }
244
245
246 static void rvm_op_strh(rvmcpu_t *cpu, rvm_asmins_t *ins)
247 {
248         *((ruint16*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint16)RVM_CPUREG_GETU(cpu, ins->op1);
249         
250 }
251
252
253 static void rvm_op_strw(rvmcpu_t *cpu, rvm_asmins_t *ins)
254 {
255         *((ruint32*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint32)RVM_CPUREG_GETU(cpu, ins->op1);
256
257 }
258
259
260 static void rvm_op_strr(rvmcpu_t *cpu, rvm_asmins_t *ins)
261 {
262         *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)) = RVM_CPUREG_GET(cpu, ins->op1);
263 }
264
265
266 static void rvm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
267 {
268         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
269
270         res = op2 + op3;
271         RVM_CPUREG_SETU(cpu, ins->op1, res);
272         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
273         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
274         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
275         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
276                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
277 }
278
279
280 static void rvm_op_adc(rvmcpu_t *cpu, rvm_asmins_t *ins)
281 {
282         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
283         
284         res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
285         RVM_CPUREG_SETU(cpu, ins->op1, res);
286         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
287         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
288         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
289         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
290                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
291 }
292
293
294 static void rvm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
295 {
296         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
297         
298         res = op2 & op3;
299         RVM_CPUREG_SETU(cpu, ins->op1, res);
300         RVM_STATUS_CLRALL(cpu);
301         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
302         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
303 }
304
305
306 static void rvm_op_orr(rvmcpu_t *cpu, rvm_asmins_t *ins)
307 {
308         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
309         
310         res = op2 | op3;
311         RVM_CPUREG_SETU(cpu, ins->op1, res);
312         RVM_STATUS_CLRALL(cpu);
313         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
314         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
315 }
316
317
318 static void rvm_op_lsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
319 {
320         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
321         
322         res = op2 << op3;
323         RVM_CPUREG_SETU(cpu, ins->op1, res);
324         RVM_STATUS_CLRALL(cpu);
325         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
326         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
327 }
328
329
330 static void rvm_op_lsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
331 {
332         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
333         
334         res = op2 >> op3;
335         RVM_CPUREG_SETU(cpu, ins->op1, res);
336         RVM_STATUS_CLRALL(cpu);
337         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
338 }
339
340
341 static void rvm_op_lsrs(rvmcpu_t *cpu, rvm_asmins_t *ins)
342 {
343         rsword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
344
345         res = ((rsword)op2) >> op3;
346         RVM_CPUREG_SETU(cpu, ins->op1, res);
347         RVM_STATUS_CLRALL(cpu);
348         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
349 }
350
351
352 static void rvm_op_asr(rvmcpu_t *cpu, rvm_asmins_t *ins)
353 {
354         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
355         
356         res = op2 >> op3;
357         res |= op2 & RVM_SIGN_BIT;
358         RVM_CPUREG_SETU(cpu, ins->op1, res);
359         RVM_STATUS_CLRALL(cpu);
360         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
361         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
362 }
363
364
365 static void rvm_op_ror(rvmcpu_t *cpu, rvm_asmins_t *ins)
366 {
367         ruint i;
368         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
369         
370         res = op2;
371         for (i = 0; i < op3; i++) {
372                 if (res & 1) {
373                         res >>= 1;
374                         res |= RVM_SIGN_BIT;
375                 } else {
376                         res >>= 1;
377                 }
378         }
379         RVM_CPUREG_SETU(cpu, ins->op1, res);
380         RVM_STATUS_CLRALL(cpu);
381         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
382         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
383         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res & RVM_SIGN_BIT);
384 }
385
386
387 static void rvm_op_tst(rvmcpu_t *cpu, rvm_asmins_t *ins)
388 {
389         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
390         
391         res = op2 & op3;
392         RVM_STATUS_CLRALL(cpu);
393         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
394         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
395 }
396
397
398 static void rvm_op_xor(rvmcpu_t *cpu, rvm_asmins_t *ins)
399 {
400         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
401         
402         res = op2 ^ op3;
403         RVM_CPUREG_SETU(cpu, ins->op1, res);
404         RVM_STATUS_CLRALL(cpu);
405         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
406         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
407 }
408
409
410 static void rvm_op_not(rvmcpu_t *cpu, rvm_asmins_t *ins)
411 {
412         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
413         
414         res = ~op2;
415         RVM_CPUREG_SETU(cpu, ins->op1, res);
416         RVM_STATUS_CLRALL(cpu);
417         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
418         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
419 }
420
421
422 static void rvm_op_teq(rvmcpu_t *cpu, rvm_asmins_t *ins)
423 {
424         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
425         
426         res = op2 ^ op3;
427         RVM_STATUS_CLRALL(cpu);
428         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
429         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
430 }
431
432
433 static void rvm_op_bic(rvmcpu_t *cpu, rvm_asmins_t *ins)
434 {
435         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
436         
437         res = op2 & ~op3;
438         RVM_CPUREG_SETU(cpu, ins->op1, res);
439         RVM_STATUS_CLRALL(cpu);
440         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
441         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
442 }
443
444
445 static void rvm_op_clz(rvmcpu_t *cpu, rvm_asmins_t *ins)
446 {
447         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
448         
449         for (res = RVM_REGISTER_BITS; op2; ) {
450                 op2 >>= 1;
451                 res -= 1;
452         }
453         RVM_CPUREG_SETU(cpu, ins->op1, res);
454 }
455
456
457 static void rvm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
458 {
459         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3));
460 }
461
462
463 static void rvm_op_swi(rvmcpu_t *cpu, rvm_asmins_t *ins)
464 {
465         rvmcpu_swi swi;
466         rvm_switable_t *switable;
467         ruint ntable = (ruint) RVM_SWI_TABLE(ins->swi);
468         ruint nswi = (ruint) RVM_SWI_NUM(ins->swi);
469
470         if (r_array_size(cpu->switables) <= ntable)
471                 RVM_ABORT(cpu, RVM_E_SWITABLE);
472         switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
473         swi = switable[nswi].op;
474         swi(cpu, ins);
475 }
476
477
478 static void rvm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
479 {
480         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
481 }
482
483
484 static void rvm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
485 {
486         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
487         
488         res = op2 - op3;
489         RVM_CPUREG_SETU(cpu, ins->op1, res);
490         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
491         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
492         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
493         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
494                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
495 }
496
497
498 static void rvm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
499 {
500         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
501
502         res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
503         RVM_CPUREG_SETU(cpu, ins->op1, res);
504         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
505         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
506         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
507         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
508                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
509 }
510
511
512 static void rvm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
513 {
514         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
515 }
516
517
518 static void rvm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
519 {
520         rsword res;
521         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
522
523         res = (rsword)(op2 * op3);
524         RVM_CPUREG_SETU(cpu, ins->op1, res);
525         /* TBD: Not sure how to update the RVM_STATUS_C */
526         RVM_STATUS_CLRALL(cpu);
527         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
528         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
529 }
530
531
532 static void rvm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
533 {
534         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
535         
536         res = op2 * op3;
537         RVM_CPUREG_SETU(cpu, ins->op1, res);
538         RVM_STATUS_CLRALL(cpu);
539         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
540         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
541         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
542 }
543
544
545 static void rvm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
546 {
547         if (!RVM_CPUREG_GETU(cpu, ins->op3))
548                 RVM_ABORT(cpu, RVM_E_DIVZERO);
549
550         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
551 }
552
553
554 static void rvm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
555 {
556         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
557
558         if (!op3)
559                 RVM_ABORT(cpu, RVM_E_DIVZERO);
560         res = op2 / op3;
561         RVM_CPUREG_SETU(cpu, ins->op1, res);
562         RVM_STATUS_CLRALL(cpu);
563         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
564         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
565 }
566
567
568 static void rvm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
569 {
570         rsword res;
571         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
572
573         if (!op3)
574                 RVM_ABORT(cpu, RVM_E_DIVZERO);
575         res = (rsword)(op2 / op3);
576         RVM_CPUREG_SETU(cpu, ins->op1, res);
577         RVM_STATUS_CLRALL(cpu);
578         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
579         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
580 }
581
582
583 static void rvm_op_push(rvmcpu_t *cpu, rvm_asmins_t *ins)
584 {
585         rword sp = RVM_CPUREG_GETU(cpu, SP) + 1;
586
587         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
588         RVM_CPUREG_SETU(cpu, SP, sp);
589 }
590
591
592 static void rvm_op_sts(rvmcpu_t *cpu, rvm_asmins_t *ins)
593 {
594         rword sp = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
595
596         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
597 }
598
599
600 static void rvm_op_pushm(rvmcpu_t *cpu, rvm_asmins_t *ins)
601 {
602         int n, i;
603         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
604         rword sp = RVM_CPUREG_GETU(cpu, SP);
605
606         for (i = 0, n = 0; bits && n < RLST; n++) {
607                 if (((rword)(1 << n)) & bits) {
608                         i += 1;
609                         sp += 1;
610                         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, n));
611                         bits &= ~(1<<n);
612                 }
613         }
614         RVM_CPUREG_SETU(cpu, SP, RVM_CPUREG_GETU(cpu, SP) + i);
615 }
616
617
618 static void rvm_op_pop(rvmcpu_t *cpu, rvm_asmins_t *ins)
619 {
620         rword sp = RVM_CPUREG_GETU(cpu, SP);
621
622         RVM_CPUREG_SET(cpu, ins->op1, r_array_index(cpu->stack, sp, rvmreg_t));
623         if (ins->op1 != SP)
624                 RVM_CPUREG_SETU(cpu, SP, sp - 1);
625 }
626
627
628 static void rvm_op_popm(rvmcpu_t *cpu, rvm_asmins_t *ins)
629 {
630         int n;
631         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
632         rword sp = RVM_CPUREG_GETU(cpu, SP);
633
634         for (n = RLST - 1; bits && n >= 0; n--) {
635                 if (((rword)(1 << n)) & bits) {
636                         RVM_CPUREG_SET(cpu, n, r_array_index(cpu->stack, sp, rvmreg_t));
637                         sp -= 1;
638                         bits &= ~(1<<n);
639                 }
640         }
641         if (!(((rword)(1 << SP)) & bits))
642                 RVM_CPUREG_SETU(cpu, SP, sp);
643 }
644
645
646 static void rvm_op_lds(rvmcpu_t *cpu, rvm_asmins_t *ins)
647 {
648         rword sp = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
649
650         RVM_CPUREG_SET(cpu, ins->op1, r_array_index(cpu->stack, sp, rvmreg_t));
651 }
652
653
654 static void rvm_op_stm(rvmcpu_t *cpu, rvm_asmins_t *ins)
655 {
656         int n;
657         rword *dst = (rword*)   RVM_CPUREG_GETU(cpu, ins->op1);
658         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
659         
660         for (n = 0; bits && n < RLST; n++) {
661                 if (((rword)(1 << n)) & bits) {
662                         *dst = RVM_CPUREG_GETU(cpu, n);
663                         dst += 1;
664                         bits &= ~(1<<n);
665                 }
666         }
667 }
668
669
670 static void rvm_op_ldm(rvmcpu_t *cpu, rvm_asmins_t *ins)
671 {
672         int n;
673         rword *src = (rword*)RVM_CPUREG_GETU(cpu, ins->op1);
674         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
675
676         for (n = 0; bits && n < RLST; n++) {
677                 if (((rword)(1 << n)) & bits) {
678                         RVM_CPUREG_SETU(cpu, n, *src);
679                         src += 1;
680                         bits &= ~(1<<n);
681                 }
682         }
683 }
684
685
686 static void rvm_op_cmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
687 {
688         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
689         rword res = (rword)(op1 - op2);
690         
691         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op1 < op2);
692         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
693         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
694         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT) &&
695                                                         (res & RVM_SIGN_BIT) == (op1 & RVM_SIGN_BIT));
696 }
697
698
699 static void rvm_op_cmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
700 {
701         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
702         rword res = (rword)(op1 + op2);
703         
704         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op1 || res < op2);
705         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
706         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
707         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT) &&
708                                                         (res & RVM_SIGN_BIT) != (op1 & RVM_SIGN_BIT));
709
710 }
711
712
713 static void rvm_op_nop(rvmcpu_t *cpu, rvm_asmins_t *ins)
714 {
715 //      fprintf(stdout, "nop\n");
716 }
717
718
719 static void rvm_op_ret(rvmcpu_t *cpu, rvm_asmins_t *ins)
720 {
721         RVM_CPUREG_SETU(cpu, PC, RVM_CPUREG_GETU(cpu, LR));     
722 }
723
724
725
726 static int rvm_vsnprintf(char *str, ruint size, const char *format, va_list ap)
727 {
728         return vsnprintf(str, size, format, ap);
729 }
730
731
732 static int rvm_snprintf(char *str, ruint size, const char *format, ...)
733 {
734         va_list ap;
735         int ret;
736
737         va_start(ap, format);
738         ret = rvm_vsnprintf(str, size, format, ap);
739         va_end(ap);
740         return ret;
741 }
742
743
744 static int rvm_printf(const char *format, ...)
745 {
746         va_list ap;
747         int ret;
748
749         va_start(ap, format);
750         ret = vfprintf(stdout, format, ap);
751         va_end(ap);
752         return ret;
753 }
754
755
756 int rvm_asm_dump_reg_to_str(unsigned char reg, char *str, ruint size)
757 {
758         int ret = 0;
759
760         if (reg == XX)
761                 ret = rvm_snprintf(str, size, "XX ");
762         else if (reg == FP)
763                 ret = rvm_snprintf(str, size, "FP ");
764         else if (reg == SP)
765                 ret = rvm_snprintf(str, size, "SP ");
766         else if (reg == LR)
767                 ret = rvm_snprintf(str, size, "LR ");
768         else if (reg == PC)
769                 ret = rvm_snprintf(str, size, "PC ");
770         else if (reg == DA)
771                 ret = rvm_snprintf(str, size, "DA ");
772         else if (reg >= 0 && reg < 10)
773                 ret = rvm_snprintf(str, size, "R%d ",  reg);
774         else if (reg >= 10)
775                 ret = rvm_snprintf(str, size, "R%d",  reg);
776
777         return ret;
778 }
779
780
781 static void rvm_op_prn(rvmcpu_t *cpu, rvm_asmins_t *ins)
782 {
783         rvmreg_t *r = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op1));
784
785         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
786                 rvm_printf("(UNSIGNED) R%d = %lu(%lx)\n", ins->op1, RVM_REG_GETU(r), RVM_REG_GETU(r));
787         else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
788                 rvm_printf("(LONG) R%d = %ld\n", ins->op1, RVM_REG_GETL(r));
789         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
790                 rvm_printf("(DOUBLE) R%d = %0.2f\n", ins->op1, RVM_REG_GETD(r));
791         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
792                 rvm_printf("(STRING) R%d = %s\n", ins->op1, ((rstring_t*) RVM_REG_GETP(r))->s.str);
793         else
794                 rvm_printf("(UNKNOWN) R%d = ?\n", ins->op1);
795 }
796
797
798 int rvm_asm_dump_pi_to_str(rvm_asmins_t *pi, char *str, ruint size)
799 {
800         int ret = 0, sz = size;
801
802         if (pi->opcode == RVM_SWI) {
803                 rchar szSwi[64];
804                 r_memset(szSwi, 0, sizeof(szSwi));
805                 rvm_snprintf(szSwi, sizeof(szSwi) - 1, "%s(%x)", stropcalls[pi->opcode], (ruint32)pi->swi);
806                 if ((ret = rvm_snprintf(str, sz, "%16s   ", szSwi)) < 0)
807                         return ret;
808         } else {
809                 if ((ret = rvm_snprintf(str, sz, "%16s   ", stropcalls[pi->opcode])) < 0)
810                         return ret;
811         }
812         str += ret;
813         sz -= ret;
814         
815         if ((ret = rvm_asm_dump_reg_to_str(pi->op1, str, sz)) < 0)
816                 return ret;
817         str += ret;
818         sz -= ret;
819                 
820         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
821                 return ret;
822         str += ret;
823         sz -= ret;
824
825         if ((ret = rvm_asm_dump_reg_to_str(pi->op2, str, sz)) < 0)
826                 return ret;
827         str += ret;
828         sz -= ret;
829                 
830         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
831                 return ret;
832         str += ret;
833         sz -= ret;
834
835         if ((ret = rvm_asm_dump_reg_to_str(pi->op3, str, sz)) < 0)
836                 return ret;
837         str += ret;
838         sz -= ret;
839                 
840         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
841                 return ret;
842         str += ret;
843         sz -= ret;
844
845         if (pi->type == RVM_DTYPE_DOUBLE) {
846                 if ((ret = rvm_snprintf(str, sz, "%f  ", pi->data.d)) < 0)
847                         return ret;
848         } else if (pi->type == RVM_DTYPE_LONG) {
849                 if ((ret = rvm_snprintf(str, sz, "%ld  ", (long)pi->data.u)) < 0)
850                         return ret;
851         } else {
852                 if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)pi->data.u)) < 0)
853                         return ret;
854         }
855
856         str += ret;
857         sz -= ret;
858
859         return size - sz;
860 }
861
862
863 void rvm_asm_dump(rvm_asmins_t *pi, ruint count)
864 {
865         char buffer[256];
866         while (count) {
867                 rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
868                 rvm_printf("%s\n", buffer);
869                 ++pi;
870                 --count;
871         }
872 }
873
874
875 static void rvm_cpu_dumpregs(rvm_asmins_t *pi, rvmcpu_t *vm)
876 {
877     int ret;
878         char buffer[1024];
879         
880         ret = rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
881         if (ret < 0)
882                 return;
883     ret = rvm_snprintf(buffer + ret, sizeof(buffer) - ret, "                                                                                        ");
884         buffer[50] = '\0';
885         rvm_printf("%s", buffer);
886
887         rvm_printf("0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, FP=%ld, SP=%ld, LR=%ld, PC=%ld, DA=0x%lx, S( %c%c%c%c )",
888                 RVM_CPUREG_GETU(vm, 0), RVM_CPUREG_GETU(vm, 1), RVM_CPUREG_GETU(vm, 2), RVM_CPUREG_GETU(vm, 3),
889                 RVM_CPUREG_GETU(vm, 4), RVM_CPUREG_GETU(vm, 5), RVM_CPUREG_GETU(vm, 6), RVM_CPUREG_GETU(vm, 7),
890                 RVM_CPUREG_GETU(vm, 8), (long int)RVM_CPUREG_GETU(vm, FP), (long int)RVM_CPUREG_GETU(vm, SP),
891                 (long int)RVM_CPUREG_GETU(vm, LR), (long int)RVM_CPUREG_GETU(vm, PC), RVM_CPUREG_GETU(vm, DA),
892                 vm->status & RVM_STATUS_V ? 'V' : '_',
893                 vm->status & RVM_STATUS_C ? 'C' : '_',
894                 vm->status & RVM_STATUS_N ? 'N' : '_',
895                 vm->status & RVM_STATUS_Z ? 'Z' : '_');
896         rvm_printf("\n");
897 }
898
899
900 static void rvm_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
901 {
902         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
903         rvmreg_t tmp;
904
905         RVM_REG_CLEAR(&tmp);
906         RVM_REG_SETTYPE(&tmp, type);
907         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, RVM_CPUREG_PTR(cpu, ins->op1), RVM_CPUREG_PTR(cpu, ins->op2), &tmp);
908 }
909
910
911 static void rvm_op_type(rvmcpu_t *cpu, rvm_asmins_t *ins)
912 {
913         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETTYPE(cpu, ins->op2);
914
915         RVM_CPUREG_CLEAR(cpu, ins->op1);
916         RVM_CPUREG_SETU(cpu, ins->op1, type);
917 }
918
919
920 static void rvm_op_emov(rvmcpu_t *cpu, rvm_asmins_t *ins)
921 {
922         rvm_op_mov(cpu, ins);
923 }
924
925
926 static void rvm_op_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
927 {
928         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
929         rvmreg_t *arg3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
930
931         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_ADD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
932 }
933
934
935 static void rvm_op_esub(rvmcpu_t *cpu, rvm_asmins_t *ins)
936 {
937         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
938         rvmreg_t *arg3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
939
940         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
941 }
942
943
944 static void rvm_op_emul(rvmcpu_t *cpu, rvm_asmins_t *ins)
945 {
946         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
947         rvmreg_t *arg3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
948
949         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_MUL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
950 }
951
952
953 static void rvm_op_ediv(rvmcpu_t *cpu, rvm_asmins_t *ins)
954 {
955         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
956         rvmreg_t *arg3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
957
958         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_DIV, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
959 }
960
961
962 static void rvm_op_elsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
963 {
964         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
965         rvmreg_t *arg3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
966
967         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
968 }
969
970
971 static void rvm_op_elsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
972 {
973         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
974         rvmreg_t *arg3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
975
976         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
977 }
978
979
980 static void rvm_op_eand(rvmcpu_t *cpu, rvm_asmins_t *ins)
981 {
982         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
983         rvmreg_t *arg3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
984
985         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_AND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
986 }
987
988
989 static void rvm_op_eorr(rvmcpu_t *cpu, rvm_asmins_t *ins)
990 {
991         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
992         rvmreg_t *arg3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
993
994         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_OR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
995 }
996
997
998 static void rvm_op_exor(rvmcpu_t *cpu, rvm_asmins_t *ins)
999 {
1000         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
1001         rvmreg_t *arg3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
1002
1003         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_XOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1004 }
1005
1006
1007 static void rvm_op_enot(rvmcpu_t *cpu, rvm_asmins_t *ins)
1008 {
1009         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
1010
1011         rvm_opmap_invoke_unary_handler(cpu->opmap, RVM_OPID_NOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
1012 }
1013
1014
1015 static void rvm_op_ecmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
1016 {
1017         rvmreg_t *arg1 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op1));
1018         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
1019
1020         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMP, cpu, NULL, arg1, arg2);
1021 }
1022
1023
1024 static void rvm_op_ecmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
1025 {
1026         rvmreg_t *arg1 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op1));
1027         rvmreg_t *arg2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
1028
1029         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMN, cpu, NULL, arg1, arg2);
1030 }
1031
1032
1033 static rvm_cpu_op ops[] = {
1034         rvm_op_exit,            // RVM_EXT
1035         rvm_op_prn,                     // RVM_PRN
1036         rvm_op_asr,                     // RVM_ASR
1037         rvm_op_swi,                     // RVM_swi
1038         rvm_op_mov,                     // RVM_MOV
1039         rvm_op_add,                     // RVM_ADD
1040         rvm_op_adds,            // RVM_ADDS
1041         rvm_op_adc,                     // RVM_ADC
1042         rvm_op_and,                     // RVM_AND
1043         rvm_op_bic,                     // RVM_BIC
1044         rvm_op_clz,                     // RVM_CLZ
1045         rvm_op_cmn,                     // RVM_CMN
1046         rvm_op_xor,                     // RVM_XOR
1047         rvm_op_sub,                     // RVM_SUB
1048         rvm_op_subs,            // RVM_SUBS
1049         rvm_op_sbc,                     // RVM_SBC
1050         rvm_op_mul,                     // RVM_MUL
1051         rvm_op_mls,                     // RVM_MLS
1052         rvm_op_muls,            // RVM_MULS
1053         rvm_op_not,                     // RVM_NOT
1054         rvm_op_div,                     // RVM_DIV
1055         rvm_op_dvs,                     // RVM_DVS
1056         rvm_op_divs,            // RVM_DIVS
1057         rvm_op_bl,                      // RVM_BL
1058         rvm_op_b,                       // RVM_B
1059         rvm_op_str,                     // RVM_STR
1060         rvm_op_strp,            // RVM_STRP
1061         rvm_op_strb,            // RVM_STRB
1062         rvm_op_strh,            // RVM_STRH
1063         rvm_op_strw,            // RVM_STRW
1064         rvm_op_strr,            // RVM_STRR
1065         rvm_op_ldr,                     // RVM_LDR
1066         rvm_op_ldrp,            // RVM_LDRP
1067         rvm_op_ldrb,            // RVM_LDRB
1068         rvm_op_ldrh,            // RVM_LDRH
1069         rvm_op_ldrw,            // RVM_LDRW
1070         rvm_op_ldrr,            // RVM_LDRR
1071         rvm_op_lsl,                     // RVM_LSL
1072         rvm_op_lsr,                     // RVM_LSR
1073         rvm_op_lsrs,            // RVM_LSRS
1074         rvm_op_stm,                     // RVM_STM
1075         rvm_op_ldm,                     // RVM_LDS
1076         rvm_op_sts,                     // RVM_STS
1077         rvm_op_lds,                     // RVM_LDM
1078         rvm_op_orr,                     // RVM_ORR
1079         rvm_op_push,            // RVM_PUSH
1080         rvm_op_pop,                     // RVM_POP
1081         rvm_op_cmp,                     // RVM_CMP
1082         rvm_op_nop,                     // RVM_NOP
1083         rvm_op_beq,                     // RVM_BEQ
1084         rvm_op_bneq,            // RVM_BNEQ
1085         rvm_op_bleq,            // RVM_BLEQ
1086         rvm_op_bgeq,            // RVM_BGEQ
1087         rvm_op_bles,            // RVM_BLES
1088         rvm_op_bgre,            // RVM_BGRE
1089         rvm_op_ret,                     // RVM_RET
1090         rvm_op_ror,                     // RVM_ROR
1091         rvm_op_pushm,           // RVM_PUSHM
1092         rvm_op_popm,            // RVM_POPM
1093         rvm_op_tst,             // RVM_TST
1094         rvm_op_teq,             // RVM_TEQ
1095
1096 /* Extended VM instructions */
1097         rvm_op_cast,            // RVM_CAST
1098         rvm_op_type,            // RVM_TYPE
1099         rvm_op_emov,            // RVM_EMOV
1100         rvm_op_eadd,            // RVM_EADD
1101         rvm_op_esub,            // RVM_ESUB
1102         rvm_op_emul,            // RVM_EMUL
1103         rvm_op_ediv,            // RVM_EDIV
1104         rvm_op_elsl,            // RVM_ELSL
1105         rvm_op_elsr,            // RVM_ELSR
1106         rvm_op_eand,            // RVM_EAND
1107         rvm_op_eorr,            // RVM_EORR
1108         rvm_op_exor,            // RVM_EXOR
1109         rvm_op_enot,            // RVM_ENOT
1110         rvm_op_ecmp,            // RVM_ECMP
1111         rvm_op_ecmn,            // RVM_ECMN
1112         (void*) 0,
1113         (void*) 0,
1114         (void*) 0,
1115         (void*) 0,
1116         (void*) 0,
1117         (void*) 0,
1118         (void*) 0,
1119         (void*) 0,
1120         
1121 };
1122         
1123
1124 rvmcpu_t *rvm_cpu_create()
1125 {
1126         rvmcpu_t *cpu;
1127
1128         cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
1129         if (!cpu)
1130                 return ((void*)0);
1131         r_memset(cpu, 0, sizeof(*cpu));
1132         cpu->switables = r_array_create(sizeof(rvm_switable_t*));
1133         cpu->stack = r_array_create(sizeof(rvmreg_t));
1134         cpu->opmap = rvm_opmap_create();
1135         rvm_op_cast_init(cpu->opmap);
1136         rvm_op_add_init(cpu->opmap);
1137         rvm_op_sub_init(cpu->opmap);
1138         rvm_op_mul_init(cpu->opmap);
1139         rvm_op_div_init(cpu->opmap);
1140         rvm_op_lsl_init(cpu->opmap);
1141         rvm_op_lsr_init(cpu->opmap);
1142         rvm_op_or_init(cpu->opmap);
1143         rvm_op_xor_init(cpu->opmap);
1144         rvm_op_and_init(cpu->opmap);
1145         rvm_op_not_init(cpu->opmap);
1146         rvm_op_cmp_init(cpu->opmap);
1147         rvm_op_cmn_init(cpu->opmap);
1148
1149         return cpu;
1150 }
1151
1152
1153 void rvm_cpu_destroy(rvmcpu_t *cpu)
1154 {
1155         r_array_destroy(cpu->switables);
1156         r_array_destroy(cpu->stack);
1157         rvm_opmap_destroy(cpu->opmap);
1158         r_free(cpu);
1159 }
1160
1161
1162 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1163 {
1164         rvm_asmins_t *pi;
1165         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1166         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1167
1168         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1169         cpu->abort = 0;
1170         cpu->error = 0;
1171         do {
1172                 pi = RVM_REG_GETIP(regpc);
1173                 if (pi->type == RVM_DTYPE_DOUBLE) {
1174                         RVM_REG_SETD(regda, pi->data.d);
1175                 } else {
1176                         RVM_REG_SETU(regda, pi->data.u);
1177                 }
1178                 RVM_REG_SETTYPE(regda, pi->type);
1179                 RVM_REG_CLRFLAG(regda, RVM_INFOBIT_ALL);
1180                 ops[pi->opcode](cpu, pi);
1181                 if (cpu->abort)
1182                         return -1;
1183                 RVM_REG_INCIP(regpc, 1);
1184         } while (pi->opcode);
1185         return 0;
1186 }
1187
1188
1189 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1190 {
1191         rvm_asmins_t *pi;
1192         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1193         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1194
1195         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1196         cpu->abort = 0;
1197         cpu->error = 0;
1198         do {
1199                 pi = RVM_REG_GETIP(regpc);
1200                 if (pi->type == RVM_DTYPE_DOUBLE) {
1201                         RVM_REG_SETD(regda, pi->data.d);
1202                 } else {
1203                         RVM_REG_SETU(regda, pi->data.u);
1204                 }
1205                 RVM_REG_SETTYPE(regda, pi->type);
1206                 RVM_REG_CLRFLAG(regda, RVM_INFOBIT_ALL);
1207                 ops[pi->opcode](cpu, pi);
1208                 if (cpu->abort)
1209                         return -1;
1210                 rvm_cpu_dumpregs(pi, cpu);              
1211                 RVM_REG_INCIP(regpc, 1);
1212         } while (pi->opcode);
1213         return 0;
1214 }
1215
1216
1217 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname)
1218 {
1219         rint ntable, nswi;
1220         rvm_switable_t *swientry;
1221
1222         for (ntable = 0; ntable < cpu->switables->len; ntable++) {
1223                 swientry = r_array_index(cpu->switables, ntable, rvm_switable_t*);
1224                 for (nswi = 0; swientry[nswi].name; nswi++) {
1225                         if (r_strcmp(swientry[nswi].name, swiname) == 0)
1226                                 return (rint)RVM_SWI_ID(ntable, nswi);
1227                 }
1228         }
1229
1230         return -1;
1231 }
1232
1233
1234 rint rvmcpu_switable_add(rvmcpu_t *cpu, rvm_switable_t *switable)
1235 {
1236         rint nswi;
1237
1238         for (nswi = 0; switable[nswi].name; nswi++) {
1239                 if (rvm_cpu_getswi(cpu, switable[nswi].name) >= 0)
1240                         return -1;
1241         }
1242
1243         return r_array_add(cpu->switables, &switable);
1244 }
1245
1246
1247 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
1248 {
1249         rvm_asmins_t a;
1250
1251         r_memset(&a, 0, sizeof(a));
1252         a.opcode = (ruint8) opcode;
1253         a.op1 = (ruint8)op1;
1254         a.op2 = (ruint8)op2;
1255         a.op3 = (ruint8)op3;
1256         a.data.u = (rword)data;
1257
1258         return a;
1259 }
1260
1261
1262 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
1263 {
1264         rvm_asmins_t a;
1265
1266         r_memset(&a, 0, sizeof(a));
1267         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1268         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1269         a.op1 = (ruint8)op1;
1270         a.op2 = (ruint8)op2;
1271         a.op3 = (ruint8)op3;
1272         a.data.u = (rword)data;
1273
1274         return a;
1275 }
1276
1277
1278 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data)
1279 {
1280         rvm_asmins_t a;
1281
1282         r_memset(&a, 0, sizeof(a));
1283         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1284         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1285         a.op1 = (ruint8)op1;
1286         a.op2 = (ruint8)op2;
1287         a.op3 = (ruint8)op3;
1288         a.data.u = (rword)data;
1289         a.type = RVM_DTYPE_LONG;
1290         return a;
1291 }
1292
1293
1294 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data)
1295 {
1296         rvm_asmins_t a;
1297
1298         r_memset(&a, 0, sizeof(a));
1299         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1300         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1301         a.op1 = (ruint8)op1;
1302         a.op2 = (ruint8)op2;
1303         a.op3 = (ruint8)op3;
1304         a.data.d = data;
1305         a.type = RVM_DTYPE_DOUBLE;
1306         return a;
1307 }
1308
1309
1310 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1311 {
1312         rvm_asmins_t a;
1313
1314         r_memset(&a, 0, sizeof(a));
1315         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1316         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1317         a.op1 = (ruint8)op1;
1318         a.op2 = (ruint8)op2;
1319         a.op3 = (ruint8)op3;
1320         a.data.u = (rword)pReloc;
1321         a.flags = RVM_ASMINS_RELOC | RVM_ASMINS_RELOCPTR;
1322
1323         return a;
1324 }
1325
1326
1327 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1328 {
1329         rvm_asmins_t a;
1330
1331         r_memset(&a, 0, sizeof(a));
1332         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1333         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1334         a.op1 = (ruint8)op1;
1335         a.op2 = (ruint8)op2;
1336         a.op3 = (ruint8)op3;
1337         a.data.u = (rword)pReloc;
1338         a.flags = RVM_ASMINS_RELOC;
1339
1340         return a;
1341 }
1342
1343
1344 void rvm_relocate(rvm_asmins_t *code, rsize_t size)
1345 {
1346         rvm_asmins_t *reloc;
1347         rulong relocindex;
1348         rulong off;
1349
1350         for (off = 0; off < size; off++, code++) {
1351                 if (code->flags & RVM_ASMINS_RELOC) {
1352                         if (code->flags & RVM_ASMINS_RELOCPTR) {
1353                                 reloc = *((rvm_asmins_t **)code->data.u);
1354                                 code->data.u = reloc - code;
1355                         } else {
1356                                 relocindex = *((rulong *)code->data.u);
1357                                 code->data.u = relocindex - off;
1358                         }
1359                         code->flags &= ~(RVM_ASMINS_RELOCPTR | RVM_ASMINS_RELOC);
1360                 }
1361         }
1362 }
1363