RPA Toolkit
merge the BNF branch to trunk.
[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 "rvmoperatorbin.h"
26 #include "rvmoperatorcast.h"
27 #include "rvmoperatornot.h"
28 #include "rvmoperatorlogicnot.h"
29 #include "rmem.h"
30 #include "rstring.h"
31 #include "rvmreg.h"
32
33
34 static const char *stropcalls[] = {
35         "RVM_EXT",
36         "RVM_ABORT",
37         "RVM_PRN",
38         "RVM_ASR",
39         "RVM_SWI",
40         "RVM_MOV",
41         "RVM_INC",
42         "RVM_DEC",
43         "RVM_ADD",
44         "RVM_ADDS",
45         "RVM_ADC",
46         "RVM_AND",
47         "RVM_BIC",
48         "RVM_CLZ",
49         "RVM_CMN",
50         "RVM_XOR",
51         "RVM_SUB",
52         "RVM_SUBS",
53         "RVM_SBC",
54         "RVM_MUL",
55         "RVM_MLS",
56         "RVM_MULS",
57         "RVM_NOT",
58         "RVM_DIV",
59         "RVM_DVS",
60         "RVM_DIVS",
61         "RVM_MOD",
62         "RVM_MODS",
63         "RVM_BX",
64         "RVM_BL",
65         "RVM_B",
66         "RVM_STR",
67         "RVM_STRP",
68         "RVM_STRB",
69         "RVM_STRH",
70         "RVM_STRW",
71         "RVM_STRR",
72         "RVM_LDR",
73         "RVM_LDRP",
74         "RVM_LDRB",
75         "RVM_LDRH",
76         "RVM_LDRW",
77         "RVM_LDRR",
78         "RVM_CLRR",
79         "RVM_LSL",
80         "RVM_LSR",
81         "RVM_LSRS",
82         "RVM_STM",
83         "RVM_LDM",
84         "RVM_STS",
85         "RVM_LDS",
86         "RVM_ORR",
87         "RVM_PUSH",
88         "RVM_POP",
89         "RVM_CMP",
90         "RVM_NOP",
91         "RVM_BEQ",
92         "RVM_BNEQ",
93         "RVM_BLEQ",
94         "RVM_BGEQ",
95         "RVM_BLES",
96         "RVM_BGRE",
97         "RVM_RET",
98         "RVM_ROR",
99         "RVM_PUSHM",
100         "RVM_POPM",     
101         "RVM_TST",
102         "RVM_TEQ",
103         "RVM_CLR",
104         "RVM_ADDRS",
105
106         "RVM_CAST",             /* Cast: op1 = (op3)op2 */
107         "RVM_TYPE",             /* Type: op1 = typeof(op2) */
108         "RVM_SETTYPE",  /* Type: op1.type = op2 */
109         "RVM_EMOV",
110         "RVM_EADD",
111         "RVM_ESUB",
112         "RVM_EMUL",
113         "RVM_EDIV",
114         "RVM_EMOD",
115         "RVM_ELSL",
116         "RVM_ELSR",
117         "RVM_ELSRU",
118         "RVM_EAND",
119         "RVM_EORR",
120         "RVM_EXOR",
121         "RVM_ENOT",
122         "RVM_ELAND",
123         "RVM_ELOR",
124         "RVM_ELNOT",
125         "RVM_EEQ",
126         "RVM_ENOTEQ",
127         "RVM_EGREAT",
128         "RVM_EGREATEQ",
129         "RVM_ELESS",
130         "RVM_ELESSEQ",
131         "RVM_ECMP",
132         "RVM_ECMN",
133         "RVM_ALLOCSTR",
134         "RVM_ALLOCARR",
135         "RVM_ADDRA",
136         "RVM_ELDA",
137         "RVM_ESTA",
138         "RVM_ELDS",
139         "RVM_ESTS",
140         "UNKNOWN",
141         "UNKNOWN",
142         "UNKNOWN",
143         "UNKNOWN",
144         "UNKNOWN",
145         "UNKNOWN",
146         "UNKNOWN",
147         "UNKNOWN",
148         "UNKNOWN",
149         "UNKNOWN",
150         "UNKNOWN",
151 };
152
153
154 static void rvm_op_b(rvmcpu_t *cpu, rvm_asmins_t *ins)
155 {
156         rword pc = 0;
157
158         if (ins->op1 != XX)
159                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
160         if (ins->op2 != XX)
161                 pc += RVM_CPUREG_GETU(cpu, ins->op2);
162         if (ins->op3 != XX)
163                 pc += RVM_CPUREG_GETU(cpu, ins->op3);
164 //      RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
165         RVM_CPUREG_INCIP(cpu, PC, pc - 1);
166 }
167
168
169 static void rvm_op_beq(rvmcpu_t *cpu, rvm_asmins_t *ins)
170 {
171         rword pc = 0;
172
173         if ((cpu->status & RVM_STATUS_Z)) {
174                 if (ins->op1 != XX)
175                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
176                 if (ins->op2 != XX)
177                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
178                 if (ins->op3 != XX)
179                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
180 //              RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
181                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
182         }
183 }
184
185
186 static void rvm_op_bneq(rvmcpu_t *cpu, rvm_asmins_t *ins)
187 {
188         rword pc = 0;
189
190         if ((cpu->status & RVM_STATUS_Z) == 0) {
191                 if (ins->op1 != XX)
192                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
193                 if (ins->op2 != XX)
194                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
195                 if (ins->op3 != XX)
196                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
197 //              RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
198                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
199         }
200 }
201
202
203 static void rvm_op_bleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
204 {
205         rword pc = 0;
206
207         if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)) {
208                 if (ins->op1 != XX)
209                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
210                 if (ins->op2 != XX)
211                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
212                 if (ins->op3 != XX)
213                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
214 //              RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
215                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
216         }
217 }
218
219 static void rvm_op_bgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
220 {
221         rword pc = 0;
222
223         if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1){
224                 if (ins->op1 != XX)
225                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
226                 if (ins->op2 != XX)
227                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
228                 if (ins->op3 != XX)
229                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
230 //              RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
231                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
232         }
233 }
234
235
236 static void rvm_op_bles(rvmcpu_t *cpu, rvm_asmins_t *ins)
237 {
238         rword pc = 0;
239
240
241         if ((cpu->status & RVM_STATUS_N)){
242                 if (ins->op1 != XX)
243                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
244                 if (ins->op2 != XX)
245                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
246                 if (ins->op3 != XX)
247                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
248 //              RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
249                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
250         }
251 }
252
253
254 static void rvm_op_bgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
255 {
256         rword pc = 0;
257
258         if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0) {
259                 if (ins->op1 != XX)
260                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
261                 if (ins->op2 != XX)
262                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
263                 if (ins->op3 != XX)
264                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
265 //              RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
266                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
267         }
268 }
269
270
271 static void rvm_op_bx(rvmcpu_t *cpu, rvm_asmins_t *ins)
272 {
273         RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
274 }
275
276
277 static void rvm_op_bl(rvmcpu_t *cpu, rvm_asmins_t *ins)
278 {
279         rword pc = 0;
280         if (ins->op1 != XX)
281                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
282         if (ins->op2 != XX)
283                 pc += RVM_CPUREG_GETU(cpu, ins->op2);
284         if (ins->op3 != XX)
285                 pc += RVM_CPUREG_GETU(cpu, ins->op3);
286
287         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
288         RVM_CPUREG_INCIP(cpu, PC, pc - 1);
289 }
290
291
292 static void rvm_op_exit(rvmcpu_t *cpu, rvm_asmins_t *ins)
293 {
294
295 }
296
297
298 static void rvm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
299 {
300         RVM_CPUREG_SET(cpu, ins->op1, RVM_CPUREG_GET(cpu, ins->op2));
301 }
302
303
304 static void rvm_op_ldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
305 {
306         RVM_CPUREG_SETU(cpu, ins->op1, *((rword*)RVM_CPUREG_GETU(cpu, ins->op2)));
307         
308 }
309
310
311 static void rvm_op_ldrp(rvmcpu_t *cpu, rvm_asmins_t *ins)
312 {
313         RVM_CPUREG_SETU(cpu, ins->op1, *((rpointer*)RVM_CPUREG_GETU(cpu, ins->op2)));
314 }
315
316
317 static void rvm_op_ldrb(rvmcpu_t *cpu, rvm_asmins_t *ins)
318 {
319         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint8*)RVM_CPUREG_GETU(cpu, ins->op2)));
320 }
321
322
323 static void rvm_op_ldrh(rvmcpu_t *cpu, rvm_asmins_t *ins)
324 {
325         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint16*)RVM_CPUREG_GETU(cpu, ins->op2)));
326 }
327
328
329 static void rvm_op_ldrw(rvmcpu_t *cpu, rvm_asmins_t *ins)
330 {
331         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint32*)RVM_CPUREG_GETU(cpu, ins->op2)));
332 }
333
334
335 static void rvm_op_ldrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
336 {
337         RVM_CPUREG_SET(cpu, ins->op1, *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)));
338 }
339
340
341 static void rvm_op_clrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
342 {
343         rvm_reg_cleanup(((rvmreg_t*)RVM_CPUREG_GETP(cpu, ins->op1)));
344 }
345
346
347 static void rvm_op_str(rvmcpu_t *cpu, rvm_asmins_t *ins)
348 {
349         *((rword*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GETU(cpu, ins->op1);
350 }
351
352
353 static void rvm_op_strp(rvmcpu_t *cpu, rvm_asmins_t *ins)
354 {
355         *((rpointer*)RVM_CPUREG_GETP(cpu, ins->op2)) = (rpointer)RVM_CPUREG_GETP(cpu, ins->op1);
356 }
357
358
359 static void rvm_op_strb(rvmcpu_t *cpu, rvm_asmins_t *ins)
360 {
361         *((ruint8*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint8)RVM_CPUREG_GETU(cpu, ins->op1);
362 }
363
364
365 static void rvm_op_strh(rvmcpu_t *cpu, rvm_asmins_t *ins)
366 {
367         *((ruint16*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint16)RVM_CPUREG_GETU(cpu, ins->op1);
368         
369 }
370
371
372 static void rvm_op_strw(rvmcpu_t *cpu, rvm_asmins_t *ins)
373 {
374         *((ruint32*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint32)RVM_CPUREG_GETU(cpu, ins->op1);
375
376 }
377
378
379 static void rvm_op_strr(rvmcpu_t *cpu, rvm_asmins_t *ins)
380 {
381         *((rvmreg_t*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GET(cpu, ins->op1);
382 }
383
384
385 static void rvm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
386 {
387         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
388
389         res = op2 + op3;
390         RVM_CPUREG_SETU(cpu, ins->op1, res);
391         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
392         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
393         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
394         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
395                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
396 }
397
398
399 static void rvm_op_adc(rvmcpu_t *cpu, rvm_asmins_t *ins)
400 {
401         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
402         
403         res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
404         RVM_CPUREG_SETU(cpu, ins->op1, res);
405         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
406         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
407         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
408         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
409                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
410 }
411
412
413 static void rvm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
414 {
415         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
416         
417         res = op2 & op3;
418         RVM_CPUREG_SETU(cpu, ins->op1, res);
419         RVM_STATUS_CLRALL(cpu);
420         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
421         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
422 }
423
424
425 static void rvm_op_orr(rvmcpu_t *cpu, rvm_asmins_t *ins)
426 {
427         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
428         
429         res = op2 | op3;
430         RVM_CPUREG_SETU(cpu, ins->op1, res);
431         RVM_STATUS_CLRALL(cpu);
432         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
433         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
434 }
435
436
437 static void rvm_op_lsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
438 {
439         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
440         
441         res = op2 << op3;
442         RVM_CPUREG_SETU(cpu, ins->op1, res);
443         RVM_STATUS_CLRALL(cpu);
444         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
445         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
446 }
447
448
449 static void rvm_op_lsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
450 {
451         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
452         
453         res = op2 >> op3;
454         RVM_CPUREG_SETU(cpu, ins->op1, res);
455         RVM_STATUS_CLRALL(cpu);
456         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
457 }
458
459
460 static void rvm_op_lsrs(rvmcpu_t *cpu, rvm_asmins_t *ins)
461 {
462         rsword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
463
464         res = ((rsword)op2) >> op3;
465         RVM_CPUREG_SETU(cpu, ins->op1, res);
466         RVM_STATUS_CLRALL(cpu);
467         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
468 }
469
470
471 static void rvm_op_asr(rvmcpu_t *cpu, rvm_asmins_t *ins)
472 {
473         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
474         
475         res = op2 >> op3;
476         res |= op2 & RVM_SIGN_BIT;
477         RVM_CPUREG_SETU(cpu, ins->op1, res);
478         RVM_STATUS_CLRALL(cpu);
479         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
480         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
481 }
482
483
484 static void rvm_op_ror(rvmcpu_t *cpu, rvm_asmins_t *ins)
485 {
486         ruint i;
487         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
488         
489         res = op2;
490         for (i = 0; i < op3; i++) {
491                 if (res & 1) {
492                         res >>= 1;
493                         res |= RVM_SIGN_BIT;
494                 } else {
495                         res >>= 1;
496                 }
497         }
498         RVM_CPUREG_SETU(cpu, ins->op1, res);
499         RVM_STATUS_CLRALL(cpu);
500         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
501         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
502         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res & RVM_SIGN_BIT);
503 }
504
505
506 static void rvm_op_tst(rvmcpu_t *cpu, rvm_asmins_t *ins)
507 {
508         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
509         
510         res = op2 & op3;
511         RVM_STATUS_CLRALL(cpu);
512         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
513         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
514 }
515
516
517 static void rvm_op_xor(rvmcpu_t *cpu, rvm_asmins_t *ins)
518 {
519         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
520         
521         res = op2 ^ op3;
522         RVM_CPUREG_SETU(cpu, ins->op1, res);
523         RVM_STATUS_CLRALL(cpu);
524         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
525         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
526 }
527
528
529 static void rvm_op_not(rvmcpu_t *cpu, rvm_asmins_t *ins)
530 {
531         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
532         
533         res = ~op2;
534         RVM_CPUREG_SETU(cpu, ins->op1, res);
535         RVM_STATUS_CLRALL(cpu);
536         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
537         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
538 }
539
540
541 static void rvm_op_teq(rvmcpu_t *cpu, rvm_asmins_t *ins)
542 {
543         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
544         
545         res = op2 ^ op3;
546         RVM_STATUS_CLRALL(cpu);
547         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
548         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
549 }
550
551
552 static void rvm_op_clr(rvmcpu_t *cpu, rvm_asmins_t *ins)
553 {
554         rvmreg_t *reg = RVM_CPUREG_PTR(cpu, ins->op1);
555         rvm_reg_cleanup(reg);
556 }
557
558
559 static void rvm_op_bic(rvmcpu_t *cpu, rvm_asmins_t *ins)
560 {
561         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
562         
563         res = op2 & ~op3;
564         RVM_CPUREG_SETU(cpu, ins->op1, res);
565         RVM_STATUS_CLRALL(cpu);
566         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
567         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
568 }
569
570
571 static void rvm_op_clz(rvmcpu_t *cpu, rvm_asmins_t *ins)
572 {
573         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
574         
575         for (res = RVM_REGISTER_BITS; op2; ) {
576                 op2 >>= 1;
577                 res -= 1;
578         }
579         RVM_CPUREG_SETU(cpu, ins->op1, res);
580 }
581
582
583 static void rvm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
584 {
585         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3));
586 }
587
588
589 static void rvm_op_inc(rvmcpu_t *cpu, rvm_asmins_t *ins)
590 {
591         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op1) + 1);
592 }
593
594
595 static void rvm_op_dec(rvmcpu_t *cpu, rvm_asmins_t *ins)
596 {
597         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
598 }
599
600
601 static void rvm_op_swi(rvmcpu_t *cpu, rvm_asmins_t *ins)
602 {
603         rvmcpu_swi swi;
604         rvm_switable_t *switable;
605         ruint ntable = (ruint) RVM_SWI_TABLE(ins->swi);
606         ruint nswi = (ruint) RVM_SWI_NUM(ins->swi);
607
608         if (r_array_length(cpu->switables) <= ntable)
609                 RVM_ABORT(cpu, RVM_E_SWITABLE);
610         switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
611         swi = switable[nswi].op;
612         swi(cpu, ins);
613 }
614
615
616 static void rvm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
617 {
618         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
619 }
620
621
622 static void rvm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
623 {
624         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
625         
626         res = op2 - op3;
627         RVM_CPUREG_SETU(cpu, ins->op1, res);
628         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
629         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
630         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
631         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
632                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
633 }
634
635
636 static void rvm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
637 {
638         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
639
640         res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
641         RVM_CPUREG_SETU(cpu, ins->op1, res);
642         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
643         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
644         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
645         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
646                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
647 }
648
649
650 static void rvm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
651 {
652         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
653 }
654
655
656 static void rvm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
657 {
658         rsword res;
659         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
660
661         res = (rsword)(op2 * op3);
662         RVM_CPUREG_SETU(cpu, ins->op1, res);
663         /* TBD: Not sure how to update the RVM_STATUS_C */
664         RVM_STATUS_CLRALL(cpu);
665         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
666         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
667 }
668
669
670 static void rvm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
671 {
672         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
673         
674         res = op2 * op3;
675         RVM_CPUREG_SETU(cpu, ins->op1, res);
676         RVM_STATUS_CLRALL(cpu);
677         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
678         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
679         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
680 }
681
682
683 static void rvm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
684 {
685         if (!RVM_CPUREG_GETU(cpu, ins->op3))
686                 RVM_ABORT(cpu, RVM_E_DIVZERO);
687
688         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
689 }
690
691
692 static void rvm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
693 {
694         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
695
696         if (!op3)
697                 RVM_ABORT(cpu, RVM_E_DIVZERO);
698         res = op2 / op3;
699         RVM_CPUREG_SETU(cpu, ins->op1, res);
700         RVM_STATUS_CLRALL(cpu);
701         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
702         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
703 }
704
705
706 static void rvm_op_mod(rvmcpu_t *cpu, rvm_asmins_t *ins)
707 {
708         if (!RVM_CPUREG_GETU(cpu, ins->op3))
709                 RVM_ABORT(cpu, RVM_E_DIVZERO);
710
711         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) % RVM_CPUREG_GETU(cpu, ins->op3));
712 }
713
714
715 static void rvm_op_mods(rvmcpu_t *cpu, rvm_asmins_t *ins)
716 {
717         rsword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
718
719         if (!op3)
720                 RVM_ABORT(cpu, RVM_E_DIVZERO);
721         res = op2 % op3;
722         r_printf("mod RES: %ld\n", res);
723         RVM_CPUREG_SETU(cpu, ins->op1, res);
724         RVM_STATUS_CLRALL(cpu);
725         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
726         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
727 }
728
729
730 static void rvm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
731 {
732         rsword res;
733         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
734
735         if (!op3)
736                 RVM_ABORT(cpu, RVM_E_DIVZERO);
737         res = (rsword)(op2 / op3);
738         RVM_CPUREG_SETU(cpu, ins->op1, res);
739         RVM_STATUS_CLRALL(cpu);
740         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
741         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
742 }
743
744
745 static void rvm_op_push(rvmcpu_t *cpu, rvm_asmins_t *ins)
746 {
747         rword sp = RVM_CPUREG_GETU(cpu, SP) + 1;
748
749         r_carray_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
750         RVM_CPUREG_SETU(cpu, SP, sp);
751 }
752
753
754 static void rvm_op_sts(rvmcpu_t *cpu, rvm_asmins_t *ins)
755 {
756         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
757
758         r_carray_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
759 }
760
761
762 static void rvm_op_pushm(rvmcpu_t *cpu, rvm_asmins_t *ins)
763 {
764         int n, i;
765         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
766         rword sp = RVM_CPUREG_GETU(cpu, SP);
767
768         for (i = 0, n = 0; bits && n < RLST; n++) {
769                 if (((rword)(1 << n)) & bits) {
770                         i += 1;
771                         sp += 1;
772                         r_carray_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, n));
773                         bits &= ~(1<<n);
774                 }
775         }
776         RVM_CPUREG_SETU(cpu, SP, RVM_CPUREG_GETU(cpu, SP) + i);
777 }
778
779
780 static void rvm_op_pop(rvmcpu_t *cpu, rvm_asmins_t *ins)
781 {
782         rword sp = RVM_CPUREG_GETU(cpu, SP);
783
784         RVM_CPUREG_SET(cpu, ins->op1, r_carray_index(cpu->stack, sp, rvmreg_t));
785         if (ins->op1 != SP)
786                 RVM_CPUREG_SETU(cpu, SP, sp - 1);
787 }
788
789
790 static void rvm_op_popm(rvmcpu_t *cpu, rvm_asmins_t *ins)
791 {
792         int n;
793         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
794         rword savedbits = bits;
795         rword sp = RVM_CPUREG_GETU(cpu, SP);
796
797         for (n = RLST - 1; bits && n >= 0; n--) {
798                 if (((rword)(1 << n)) & bits) {
799                         RVM_CPUREG_SET(cpu, n, r_carray_index(cpu->stack, sp, rvmreg_t));
800                         sp -= 1;
801                         bits &= ~(1<<n);
802                 }
803         }
804         if (!(((rword)(1 << SP)) & savedbits))
805                 RVM_CPUREG_SETU(cpu, SP, sp);
806 }
807
808
809 static void rvm_op_lds(rvmcpu_t *cpu, rvm_asmins_t *ins)
810 {
811         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
812
813         RVM_CPUREG_SET(cpu, ins->op1, r_carray_index(cpu->stack, sp, rvmreg_t));
814 }
815
816
817 static void rvm_op_addrs(rvmcpu_t *cpu, rvm_asmins_t *ins)
818 {
819         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
820
821         RVM_CPUREG_CLEAR(cpu, ins->op1);
822         RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_POINTER);
823         RVM_CPUREG_SETP(cpu, ins->op1, r_carray_slot_expand(cpu->stack, sp));
824 }
825
826
827 static void rvm_op_stm(rvmcpu_t *cpu, rvm_asmins_t *ins)
828 {
829         int n;
830         rword *dst = (rword*)   RVM_CPUREG_GETU(cpu, ins->op1);
831         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
832         
833         for (n = 0; bits && n < RLST; n++) {
834                 if (((rword)(1 << n)) & bits) {
835                         *dst = RVM_CPUREG_GETU(cpu, n);
836                         dst += 1;
837                         bits &= ~(1<<n);
838                 }
839         }
840 }
841
842
843 static void rvm_op_ldm(rvmcpu_t *cpu, rvm_asmins_t *ins)
844 {
845         int n;
846         rword *src = (rword*)RVM_CPUREG_GETU(cpu, ins->op1);
847         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
848
849         for (n = 0; bits && n < RLST; n++) {
850                 if (((rword)(1 << n)) & bits) {
851                         RVM_CPUREG_CLEAR(cpu, n);
852                         RVM_CPUREG_SETU(cpu, n, *src);
853                         src += 1;
854                         bits &= ~(1<<n);
855                 }
856         }
857 }
858
859
860 static void rvm_op_cmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
861 {
862         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
863         rword res = (rword)(op1 - op2);
864         
865         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op1 < op2);
866         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
867         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
868         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT) &&
869                                                         (res & RVM_SIGN_BIT) == (op1 & RVM_SIGN_BIT));
870 }
871
872
873 static void rvm_op_cmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
874 {
875         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
876         rword res = (rword)(op1 + op2);
877         
878         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op1 || res < op2);
879         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
880         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
881         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT) &&
882                                                         (res & RVM_SIGN_BIT) != (op1 & RVM_SIGN_BIT));
883
884 }
885
886
887 static void rvm_op_nop(rvmcpu_t *cpu, rvm_asmins_t *ins)
888 {
889 //      fprintf(stdout, "nop\n");
890 }
891
892
893 static void rvm_op_ret(rvmcpu_t *cpu, rvm_asmins_t *ins)
894 {
895         RVM_CPUREG_SETU(cpu, PC, RVM_CPUREG_GETU(cpu, LR));     
896 }
897
898
899 static int rvm_vsnprintf(char *str, ruint size, const char *format, va_list ap)
900 {
901         return vsnprintf(str, size, format, ap);
902 }
903
904
905 static int rvm_snprintf(char *str, ruint size, const char *format, ...)
906 {
907         va_list ap;
908         int ret;
909
910         va_start(ap, format);
911         ret = rvm_vsnprintf(str, size, format, ap);
912         va_end(ap);
913         return ret;
914 }
915
916
917 static int rvm_printf(const char *format, ...)
918 {
919         va_list ap;
920         int ret;
921
922         va_start(ap, format);
923         ret = vfprintf(stdout, format, ap);
924         va_end(ap);
925         return ret;
926 }
927
928
929 int rvm_asm_dump_reg_to_str(unsigned char reg, char *str, ruint size)
930 {
931         int ret = 0;
932
933         if (reg == XX)
934                 ret = rvm_snprintf(str, size, "XX ");
935         else if (reg == FP)
936                 ret = rvm_snprintf(str, size, "FP ");
937         else if (reg == SP)
938                 ret = rvm_snprintf(str, size, "SP ");
939         else if (reg == LR)
940                 ret = rvm_snprintf(str, size, "LR ");
941         else if (reg == PC)
942                 ret = rvm_snprintf(str, size, "PC ");
943         else if (reg == DA)
944                 ret = rvm_snprintf(str, size, "DA ");
945         else if (reg >= 0 && reg < RVM_REGS_NUM/2)
946                 ret = rvm_snprintf(str, size, "R%d ",  reg);
947         else if (reg >= RVM_REGS_NUM/2)
948                 ret = rvm_snprintf(str, size, "S%d ",  reg & ((1 << (RVM_OPERAND_BITS-1))-1));
949
950         return ret;
951 }
952
953
954 static void rvm_op_prn(rvmcpu_t *cpu, rvm_asmins_t *ins)
955 {
956         rvmreg_t *r = RVM_CPUREG_PTR(cpu, ins->op1);
957
958         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
959                 rvm_printf("(UNSIGNED) R%d = %lu(0x%lx)\n", ins->op1, RVM_REG_GETU(r), RVM_REG_GETU(r));
960         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
961                 rvm_printf("(UNSIGNED) R%d = %lu(0x%lx)\n", ins->op1, RVM_REG_GETU(r), RVM_REG_GETU(r));
962         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
963                 rvm_printf("(POINTER) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
964         else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
965                 rvm_printf("(LONG) R%d = %ld\n", ins->op1, RVM_REG_GETL(r));
966         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
967                 rvm_printf("(DOUBLE) R%d = %0.2f\n", ins->op1, RVM_REG_GETD(r));
968         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
969                 rvm_printf("(STRING) R%d = %s\n", ins->op1, ((rstring_t*) RVM_REG_GETP(r))->s.str);
970         else if (rvm_reg_gettype(r) == RVM_DTYPE_ARRAY)
971                 rvm_printf("(ARRAY) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
972         else
973                 rvm_printf("(UNKNOWN) R%d = ?\n", ins->op1);
974 }
975
976
977 int rvm_asm_dump_pi_to_str(rvmcpu_t *vm, rvm_asmins_t *pi, char *str, ruint size)
978 {
979         int ret = 0, sz = size;
980
981         if (pi->opcode == RVM_SWI) {
982                 rchar szSwi[64];
983                 r_memset(szSwi, 0, sizeof(szSwi));
984                 if (!vm) {
985                         rvm_snprintf(szSwi, sizeof(szSwi) - 1, "%s(%x)", stropcalls[pi->opcode], (ruint32)pi->swi);
986                 } else {
987                         rvm_switable_t *switable;
988                         ruint ntable = (ruint) RVM_SWI_TABLE(pi->swi);
989                         ruint nswi = (ruint) RVM_SWI_NUM(pi->swi);
990
991                         if (ntable < r_array_length(vm->switables)) {
992                                 switable = r_array_index(vm->switables, ntable, rvm_switable_t*);
993                                 rvm_snprintf(szSwi, sizeof(szSwi) - 1, "(%s)",  switable[nswi].name ? switable[nswi].name : "unknown");
994                         }
995                 }
996                 if ((ret = rvm_snprintf(str, sz, "%16s   ", szSwi)) < 0)
997                         return ret;
998         } else {
999                 if ((ret = rvm_snprintf(str, sz, "%16s   ", stropcalls[pi->opcode])) < 0)
1000                         return ret;
1001         }
1002         str += ret;
1003         sz -= ret;
1004         
1005         if ((ret = rvm_asm_dump_reg_to_str(pi->op1, str, sz)) < 0)
1006                 return ret;
1007         str += ret;
1008         sz -= ret;
1009                 
1010         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1011                 return ret;
1012         str += ret;
1013         sz -= ret;
1014
1015         if ((ret = rvm_asm_dump_reg_to_str(pi->op2, str, sz)) < 0)
1016                 return ret;
1017         str += ret;
1018         sz -= ret;
1019                 
1020         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1021                 return ret;
1022         str += ret;
1023         sz -= ret;
1024
1025         if ((ret = rvm_asm_dump_reg_to_str(pi->op3, str, sz)) < 0)
1026                 return ret;
1027         str += ret;
1028         sz -= ret;
1029                 
1030         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1031                 return ret;
1032         str += ret;
1033         sz -= ret;
1034
1035         if (pi->type == RVM_DTYPE_DOUBLE) {
1036                 if ((ret = rvm_snprintf(str, sz, "%f  ", pi->data.d)) < 0)
1037                         return ret;
1038         } else if (pi->type == RVM_DTYPE_LONG) {
1039                 if ((ret = rvm_snprintf(str, sz, "%ld  ", (long)pi->data.u)) < 0)
1040                         return ret;
1041         } else {
1042                 if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)pi->data.u)) < 0)
1043                         return ret;
1044         }
1045
1046         str += ret;
1047         sz -= ret;
1048
1049         return size - sz;
1050 }
1051
1052
1053 void rvm_asm_dump(rvm_asmins_t *pi, ruint count)
1054 {
1055         char buffer[256];
1056         while (count) {
1057                 rvm_asm_dump_pi_to_str(NULL, pi, buffer, sizeof(buffer));
1058                 rvm_printf("%s\n", buffer);
1059                 ++pi;
1060                 --count;
1061         }
1062 }
1063
1064
1065 static void rvm_cpu_dumpregs(rvm_asmins_t *pi, rvmcpu_t *vm)
1066 {
1067     int ret;
1068         char buffer[1024];
1069         
1070         ret = rvm_asm_dump_pi_to_str(vm, pi, buffer, sizeof(buffer));
1071         if (ret < 0)
1072                 return;
1073     ret = rvm_snprintf(buffer + ret, sizeof(buffer) - ret, "                                                                                        ");
1074         buffer[50] = '\0';
1075         rvm_printf("%s", buffer);
1076
1077         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 )",
1078                 RVM_CPUREG_GETU(vm, 0), RVM_CPUREG_GETU(vm, 1), RVM_CPUREG_GETU(vm, 2), RVM_CPUREG_GETU(vm, 3),
1079                 RVM_CPUREG_GETU(vm, 4), RVM_CPUREG_GETU(vm, 5), RVM_CPUREG_GETU(vm, 6), RVM_CPUREG_GETU(vm, 7),
1080                 RVM_CPUREG_GETU(vm, 8), (long int)RVM_CPUREG_GETU(vm, FP), (long int)RVM_CPUREG_GETU(vm, SP),
1081                 (long int)RVM_CPUREG_GETU(vm, LR), (long int)RVM_CPUREG_GETU(vm, PC), RVM_CPUREG_GETU(vm, DA),
1082                 vm->status & RVM_STATUS_V ? 'V' : '_',
1083                 vm->status & RVM_STATUS_C ? 'C' : '_',
1084                 vm->status & RVM_STATUS_N ? 'N' : '_',
1085                 vm->status & RVM_STATUS_Z ? 'Z' : '_');
1086         rvm_printf("\n");
1087 }
1088
1089
1090 static void rvm_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
1091 {
1092         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
1093         rvmreg_t tmp;
1094
1095         RVM_REG_CLEAR(&tmp);
1096         RVM_REG_SETTYPE(&tmp, type);
1097         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, RVM_CPUREG_PTR(cpu, ins->op1), RVM_CPUREG_PTR(cpu, ins->op2), &tmp);
1098 }
1099
1100
1101 static void rvm_op_type(rvmcpu_t *cpu, rvm_asmins_t *ins)
1102 {
1103         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETTYPE(cpu, ins->op2);
1104
1105         RVM_CPUREG_SETU(cpu, ins->op1, type);
1106 }
1107
1108
1109 static void rvm_op_settype(rvmcpu_t *cpu, rvm_asmins_t *ins)
1110 {
1111         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op2);
1112
1113         RVM_CPUREG_SETTYPE(cpu, ins->op1, type);
1114 }
1115
1116
1117 static void rvm_op_emov(rvmcpu_t *cpu, rvm_asmins_t *ins)
1118 {
1119         rvm_op_mov(cpu, ins);
1120 }
1121
1122
1123 static void rvm_op_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1124 {
1125         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1126         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1127
1128         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_ADD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1129 }
1130
1131
1132 static void rvm_op_esub(rvmcpu_t *cpu, rvm_asmins_t *ins)
1133 {
1134         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1135         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1136
1137         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1138 }
1139
1140
1141 static void rvm_op_emul(rvmcpu_t *cpu, rvm_asmins_t *ins)
1142 {
1143         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1144         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1145
1146         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_MUL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1147 }
1148
1149
1150 static void rvm_op_ediv(rvmcpu_t *cpu, rvm_asmins_t *ins)
1151 {
1152         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1153         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1154
1155         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_DIV, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1156 }
1157
1158
1159 static void rvm_op_emod(rvmcpu_t *cpu, rvm_asmins_t *ins)
1160 {
1161         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1162         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1163
1164         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_MOD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1165 }
1166
1167
1168 static void rvm_op_elsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
1169 {
1170         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1171         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1172
1173         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1174 }
1175
1176
1177 static void rvm_op_elsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1178 {
1179         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1180         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1181
1182         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1183 }
1184
1185
1186 static void rvm_op_elsru(rvmcpu_t *cpu, rvm_asmins_t *ins)
1187 {
1188         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1189         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1190
1191         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSRU, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1192 }
1193
1194
1195 static void rvm_op_eand(rvmcpu_t *cpu, rvm_asmins_t *ins)
1196 {
1197         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1198         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1199
1200         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_AND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1201 }
1202
1203
1204 static void rvm_op_eorr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1205 {
1206         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1207         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1208
1209         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_OR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1210 }
1211
1212
1213 static void rvm_op_exor(rvmcpu_t *cpu, rvm_asmins_t *ins)
1214 {
1215         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1216         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1217
1218         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_XOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1219 }
1220
1221
1222 static void rvm_op_enot(rvmcpu_t *cpu, rvm_asmins_t *ins)
1223 {
1224         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1225
1226         rvm_opmap_invoke_unary_handler(cpu->opmap, RVM_OPID_NOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
1227 }
1228
1229
1230 static void rvm_op_eland(rvmcpu_t *cpu, rvm_asmins_t *ins)
1231 {
1232         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1233         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1234
1235         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LOGICAND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1236 }
1237
1238
1239 static void rvm_op_elor(rvmcpu_t *cpu, rvm_asmins_t *ins)
1240 {
1241         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1242         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1243
1244         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LOGICOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1245 }
1246
1247
1248 static void rvm_op_elnot(rvmcpu_t *cpu, rvm_asmins_t *ins)
1249 {
1250         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1251
1252         rvm_opmap_invoke_unary_handler(cpu->opmap, RVM_OPID_LOGICNOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
1253 }
1254
1255
1256 static void rvm_op_eeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1257 {
1258         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1259         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1260
1261         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_EQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1262 }
1263
1264
1265 static void rvm_op_enoteq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1266 {
1267         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1268         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1269
1270         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_NOTEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1271 }
1272
1273
1274 static void rvm_op_egreat(rvmcpu_t *cpu, rvm_asmins_t *ins)
1275 {
1276         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1277         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1278
1279         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_GREATER, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1280 }
1281
1282
1283 static void rvm_op_egreateq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1284 {
1285         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1286         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1287
1288         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_GREATEREQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1289 }
1290
1291
1292 static void rvm_op_elesseq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1293 {
1294         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1295         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1296
1297         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LESSEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1298 }
1299
1300
1301 static void rvm_op_eless(rvmcpu_t *cpu, rvm_asmins_t *ins)
1302 {
1303         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1304         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1305
1306         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LESS, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1307 }
1308
1309
1310 static void rvm_op_ecmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
1311 {
1312         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1313         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1314
1315         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMP, cpu, NULL, arg1, arg2);
1316 }
1317
1318
1319 static void rvm_op_ecmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
1320 {
1321         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1322         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1323
1324         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMN, cpu, NULL, arg1, arg2);
1325 }
1326
1327
1328 static void rvm_op_allocstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1329 {
1330
1331         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1332         rstring_t *s = r_string_create_strsize((const rchar*)RVM_CPUREG_GETP(cpu, ins->op2), RVM_CPUREG_GETU(cpu, ins->op3));
1333         if (!s) {
1334                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1335         }
1336         rvm_gc_add(cpu->gc, (robject_t*)s);
1337         rvm_reg_setstring(arg1, s);
1338 }
1339
1340
1341 static void rvm_op_allocarr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1342 {
1343         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1344         ruint size = RVM_CPUREG_GETU(cpu, ins->op2);
1345         rcarray_t *a = r_carray_create_rvmreg();
1346         if (!a) {
1347                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1348         }
1349         r_carray_setlength(a, size);
1350         rvm_gc_add(cpu->gc, (robject_t*)a);
1351         rvm_reg_setarray(arg1, (robject_t*)a);
1352 }
1353
1354
1355 static void rvm_op_addra(rvmcpu_t *cpu, rvm_asmins_t *ins)
1356 {
1357         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1358         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1359         ruint index = RVM_CPUREG_GETU(cpu, ins->op3);
1360         rcarray_t *a = RVM_REG_GETP(arg2);
1361
1362         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1363                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1364         }
1365         RVM_REG_CLEAR(arg1);
1366         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
1367         RVM_REG_SETP(arg1, r_carray_slot_expand(a, index));
1368 }
1369
1370
1371 static void rvm_op_elda(rvmcpu_t *cpu, rvm_asmins_t *ins)
1372 {
1373         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1374         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1375         ruint index = RVM_CPUREG_GETU(cpu, ins->op3);
1376         rcarray_t *a = RVM_REG_GETP(arg2);
1377
1378         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1379                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1380         }
1381         *arg1 = *((rvmreg_t*)r_carray_slot_expand(a, index));
1382 }
1383
1384
1385 static void rvm_op_esta(rvmcpu_t *cpu, rvm_asmins_t *ins)
1386 {
1387         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1388         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1389         ruint index = RVM_CPUREG_GETU(cpu, ins->op3);
1390         rcarray_t *a = RVM_REG_GETP(arg2);
1391
1392         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1393                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1394         }
1395         r_carray_replace(a, index, arg1);
1396 }
1397
1398
1399 static void rvm_op_abort(rvmcpu_t *cpu, rvm_asmins_t *ins)
1400 {
1401         RVM_ABORT(cpu, RVM_CPUREG_GETU(cpu, ins->op1));
1402 }
1403
1404
1405 static void rvm_op_elds(rvmcpu_t *cpu, rvm_asmins_t *ins)
1406 {
1407         ruint index = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
1408         RVM_CPUREG_SET(cpu, ins->op1, *RVM_STACK_ADDR(cpu, index));
1409 }
1410
1411
1412 static void rvm_op_ests(rvmcpu_t *cpu, rvm_asmins_t *ins)
1413 {
1414         ruint index = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
1415         *RVM_STACK_ADDR(cpu, index) = RVM_CPUREG_GET(cpu, ins->op1);
1416 }
1417
1418
1419 static rvm_cpu_op ops[] = {
1420         rvm_op_exit,            // RVM_EXT
1421         rvm_op_abort,           // RVM_ABORT
1422         rvm_op_prn,                     // RVM_PRN
1423         rvm_op_asr,                     // RVM_ASR
1424         rvm_op_swi,                     // RVM_swi
1425         rvm_op_mov,                     // RVM_MOV
1426         rvm_op_inc,                     // RVM_INC
1427         rvm_op_dec,                     // RVM_DEC
1428         rvm_op_add,                     // RVM_ADD
1429         rvm_op_adds,            // RVM_ADDS
1430         rvm_op_adc,                     // RVM_ADC
1431         rvm_op_and,                     // RVM_AND
1432         rvm_op_bic,                     // RVM_BIC
1433         rvm_op_clz,                     // RVM_CLZ
1434         rvm_op_cmn,                     // RVM_CMN
1435         rvm_op_xor,                     // RVM_XOR
1436         rvm_op_sub,                     // RVM_SUB
1437         rvm_op_subs,            // RVM_SUBS
1438         rvm_op_sbc,                     // RVM_SBC
1439         rvm_op_mul,                     // RVM_MUL
1440         rvm_op_mls,                     // RVM_MLS
1441         rvm_op_muls,            // RVM_MULS
1442         rvm_op_not,                     // RVM_NOT
1443         rvm_op_div,                     // RVM_DIV
1444         rvm_op_dvs,                     // RVM_DVS
1445         rvm_op_divs,            // RVM_DIVS
1446         rvm_op_mod,                     // RVM_MOD
1447         rvm_op_mods,            // RVM_MODS
1448         rvm_op_bx,                      // RVM_BX
1449         rvm_op_bl,                      // RVM_BL
1450         rvm_op_b,                       // RVM_B
1451         rvm_op_str,                     // RVM_STR
1452         rvm_op_strp,            // RVM_STRP
1453         rvm_op_strb,            // RVM_STRB
1454         rvm_op_strh,            // RVM_STRH
1455         rvm_op_strw,            // RVM_STRW
1456         rvm_op_strr,            // RVM_STRR
1457         rvm_op_ldr,                     // RVM_LDR
1458         rvm_op_ldrp,            // RVM_LDRP
1459         rvm_op_ldrb,            // RVM_LDRB
1460         rvm_op_ldrh,            // RVM_LDRH
1461         rvm_op_ldrw,            // RVM_LDRW
1462         rvm_op_ldrr,            // RVM_LDRR
1463         rvm_op_clrr,            // RVM_CLRR
1464         rvm_op_lsl,                     // RVM_LSL
1465         rvm_op_lsr,                     // RVM_LSR
1466         rvm_op_lsrs,            // RVM_LSRS
1467         rvm_op_stm,                     // RVM_STM
1468         rvm_op_ldm,                     // RVM_LDM
1469         rvm_op_sts,                     // RVM_STS
1470         rvm_op_lds,                     // RVM_LDS
1471         rvm_op_orr,                     // RVM_ORR
1472         rvm_op_push,            // RVM_PUSH
1473         rvm_op_pop,                     // RVM_POP
1474         rvm_op_cmp,                     // RVM_CMP
1475         rvm_op_nop,                     // RVM_NOP
1476         rvm_op_beq,                     // RVM_BEQ
1477         rvm_op_bneq,            // RVM_BNEQ
1478         rvm_op_bleq,            // RVM_BLEQ
1479         rvm_op_bgeq,            // RVM_BGEQ
1480         rvm_op_bles,            // RVM_BLES
1481         rvm_op_bgre,            // RVM_BGRE
1482         rvm_op_ret,                     // RVM_RET
1483         rvm_op_ror,                     // RVM_ROR
1484         rvm_op_pushm,           // RVM_PUSHM
1485         rvm_op_popm,            // RVM_POPM
1486         rvm_op_tst,             // RVM_TST
1487         rvm_op_teq,             // RVM_TEQ
1488         rvm_op_clr,             // RVM_CLR
1489         rvm_op_addrs,           // RVM_ADDRS
1490
1491 /* Extended VM instructions */
1492         rvm_op_cast,            // RVM_CAST
1493         rvm_op_type,            // RVM_TYPE
1494         rvm_op_settype,         // RVM_SETTYPE
1495         rvm_op_emov,            // RVM_EMOV
1496         rvm_op_eadd,            // RVM_EADD
1497         rvm_op_esub,            // RVM_ESUB
1498         rvm_op_emul,            // RVM_EMUL
1499         rvm_op_ediv,            // RVM_EDIV
1500         rvm_op_emod,            // RVM_MOD
1501         rvm_op_elsl,            // RVM_ELSL
1502         rvm_op_elsr,            // RVM_ELSR
1503         rvm_op_elsru,           // RVM_ELSRU
1504         rvm_op_eand,            // RVM_EAND
1505         rvm_op_eorr,            // RVM_EORR
1506         rvm_op_exor,            // RVM_EXOR
1507         rvm_op_enot,            // RVM_ENOT
1508
1509         rvm_op_eland,           // RVM_ELAND
1510         rvm_op_elor,            // RVM_ELOR
1511         rvm_op_elnot,           // RVM_ELNOT
1512         rvm_op_eeq,                     // RVM_EEQ
1513         rvm_op_enoteq,          // RVM_ENOTEQ
1514         rvm_op_egreat,          // RVM_EGREAT
1515         rvm_op_egreateq,        // RVM_EGREATEQ
1516         rvm_op_eless,           // RVM_ELESS
1517         rvm_op_elesseq,         // RVM_ELESSEQ
1518         rvm_op_ecmp,            // RVM_ECMP
1519         rvm_op_ecmn,            // RVM_ECMN
1520         rvm_op_allocstr,        // RVM_ALLOCSTR
1521         rvm_op_allocarr,        // RVM_ALLOCARR
1522         rvm_op_addra,           // RVM_ADDRA
1523         rvm_op_elda,            // RVM_ELDA
1524         rvm_op_esta,            // RVM_ESTA
1525         rvm_op_elds,            // RVM_ELDS
1526         rvm_op_ests,            // RVM_ESTS
1527         (void*) 0,
1528         (void*) 0,
1529         (void*) 0,
1530         (void*) 0,
1531         (void*) 0,
1532         (void*) 0,
1533         (void*) 0,
1534         (void*) 0,
1535         
1536 };
1537
1538
1539 rvmcpu_t *rvm_cpu_create()
1540 {
1541         rvmcpu_t *cpu;
1542
1543         cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
1544         if (!cpu)
1545                 return ((void*)0);
1546         r_memset(cpu, 0, sizeof(*cpu));
1547         cpu->switables = r_array_create(sizeof(rvm_switable_t*));
1548         cpu->stack = r_carray_create(sizeof(rvmreg_t));
1549         cpu->stack->user = (void*)cpu;
1550         cpu->opmap = rvm_opmap_create();
1551         cpu->gc = rvm_gc_create();
1552         rvm_op_binary_init(cpu->opmap);
1553         rvm_op_cast_init(cpu->opmap);
1554         rvm_op_not_init(cpu->opmap);
1555         rvm_op_logicnot_init(cpu->opmap);
1556
1557         return cpu;
1558 }
1559
1560
1561 void rvm_cpu_destroy(rvmcpu_t *cpu)
1562 {
1563         r_object_destroy((robject_t*)cpu->switables);
1564         r_object_destroy((robject_t*)cpu->stack);
1565         rvm_opmap_destroy(cpu->opmap);
1566         rvm_gc_deallocate_all(cpu->gc);
1567         rvm_gc_destroy(cpu->gc);
1568         r_free(cpu);
1569 }
1570
1571
1572 rint rvm_cpu_dbgarg_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off, rint debug)
1573 {
1574         rvm_asmins_t *pi;
1575         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1576         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1577
1578         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1579         cpu->abort = 0;
1580         cpu->error = 0;
1581         do {
1582                 pi = RVM_REG_GETIP(regpc);
1583                 if (pi->da) {
1584                         if (pi->type == RVM_DTYPE_DOUBLE) {
1585                                 RVM_REG_SETD(regda, pi->data.d);
1586                         } else {
1587                                 RVM_REG_SETU(regda, pi->data.u);
1588                         }
1589                         RVM_REG_SETTYPE(regda, pi->type);
1590                         RVM_REG_ASSIGNFLAGS(regda, (pi->type >= RVM_DTYPE_STRING) ? RVM_INFOBIT_ROBJECT : 0);
1591                 }
1592                 ops[pi->opcode](cpu, pi);
1593                 if (debug)
1594                         rvm_cpu_dumpregs(pi, cpu);
1595                 if (cpu->abort)
1596                         return -1;
1597                 RVM_REG_INCIP(regpc, 1);
1598         } while (pi->opcode);
1599         return 0;
1600 }
1601
1602
1603 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1604 {
1605         return rvm_cpu_dbgarg_exec(cpu, prog, off, 0);
1606 }
1607
1608
1609 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1610 {
1611         return rvm_cpu_dbgarg_exec(cpu, prog, off, 1);
1612 }
1613
1614
1615 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname)
1616 {
1617         rint ntable, nswi;
1618         rvm_switable_t *swientry;
1619
1620         for (ntable = 0; ntable < r_array_length(cpu->switables); ntable++) {
1621                 swientry = r_array_index(cpu->switables, ntable, rvm_switable_t*);
1622                 for (nswi = 0; swientry[nswi].name; nswi++) {
1623                         if (r_strcmp(swientry[nswi].name, swiname) == 0)
1624                                 return (rint)RVM_SWI_ID(ntable, nswi);
1625                 }
1626         }
1627
1628         return -1;
1629 }
1630
1631
1632 rint rvmcpu_switable_add(rvmcpu_t *cpu, rvm_switable_t *switable)
1633 {
1634         rint nswi;
1635
1636         for (nswi = 0; switable[nswi].name; nswi++) {
1637                 if (rvm_cpu_getswi(cpu, switable[nswi].name) >= 0)
1638                         return -1;
1639         }
1640
1641         return r_array_add(cpu->switables, &switable);
1642 }
1643
1644
1645 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
1646 {
1647         rvm_asmins_t a;
1648
1649         r_memset(&a, 0, sizeof(a));
1650         a.opcode = (ruint8) opcode;
1651         a.op1 = (ruint8)op1;
1652         a.op2 = (ruint8)op2;
1653         a.op3 = (ruint8)op3;
1654         a.data.u = (rword)data;
1655         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1656                 a.da = 1;
1657         return a;
1658 }
1659
1660
1661 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
1662 {
1663         rvm_asmins_t a;
1664
1665         r_memset(&a, 0, sizeof(a));
1666         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1667         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1668         a.op1 = (ruint8)op1;
1669         a.op2 = (ruint8)op2;
1670         a.op3 = (ruint8)op3;
1671         a.data.u = (rword)data;
1672         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1673                 a.da = 1;
1674         return a;
1675 }
1676
1677
1678 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data)
1679 {
1680         rvm_asmins_t a;
1681
1682         r_memset(&a, 0, sizeof(a));
1683         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1684         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1685         a.op1 = (ruint8)op1;
1686         a.op2 = (ruint8)op2;
1687         a.op3 = (ruint8)op3;
1688         a.data.u = (rword)data;
1689         a.type = RVM_DTYPE_LONG;
1690         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1691                 a.da = 1;
1692         return a;
1693 }
1694
1695
1696 rvm_asmins_t rvm_asmb(rword opcode, rword op1, rword op2, rword op3, rword data)
1697 {
1698         rvm_asmins_t a;
1699
1700         r_memset(&a, 0, sizeof(a));
1701         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1702         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1703         a.op1 = (ruint8)op1;
1704         a.op2 = (ruint8)op2;
1705         a.op3 = (ruint8)op3;
1706         a.data.u = (rword)(data ? 1 : 0);
1707         a.type = RVM_DTYPE_BOOLEAN;
1708         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1709                 a.da = 1;
1710         return a;
1711 }
1712
1713
1714 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data)
1715 {
1716         rvm_asmins_t a;
1717
1718         r_memset(&a, 0, sizeof(a));
1719         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1720         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1721         a.op1 = (ruint8)op1;
1722         a.op2 = (ruint8)op2;
1723         a.op3 = (ruint8)op3;
1724         a.data.d = data;
1725         a.type = RVM_DTYPE_DOUBLE;
1726         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1727                 a.da = 1;
1728
1729         return a;
1730 }
1731
1732
1733 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1734 {
1735         rvm_asmins_t a;
1736
1737         r_memset(&a, 0, sizeof(a));
1738         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1739         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1740         a.op1 = (ruint8)op1;
1741         a.op2 = (ruint8)op2;
1742         a.op3 = (ruint8)op3;
1743         a.data.u = (rword)pReloc;
1744         a.flags = RVM_ASMINS_RELOC | RVM_ASMINS_RELOCPTR;
1745         a.da = 1;
1746
1747         return a;
1748 }
1749
1750
1751 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1752 {
1753         rvm_asmins_t a;
1754
1755         r_memset(&a, 0, sizeof(a));
1756         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1757         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1758         a.op1 = (ruint8)op1;
1759         a.op2 = (ruint8)op2;
1760         a.op3 = (ruint8)op3;
1761         a.data.u = (rword)pReloc;
1762         a.flags = RVM_ASMINS_RELOC;
1763         a.da = 1;
1764
1765         return a;
1766 }
1767
1768
1769 void rvm_relocate(rvm_asmins_t *code, rsize_t size)
1770 {
1771         rvm_asmins_t *reloc;
1772         rulong relocindex;
1773         rulong off;
1774
1775         for (off = 0; off < size; off++, code++) {
1776                 if (code->flags & RVM_ASMINS_RELOC) {
1777                         if (code->flags & RVM_ASMINS_RELOCPTR) {
1778                                 reloc = *((rvm_asmins_t **)code->data.u);
1779                                 code->data.u = reloc - code;
1780                         } else {
1781                                 relocindex = *((rulong *)code->data.u);
1782                                 code->data.u = relocindex - off;
1783                         }
1784                         code->flags &= ~(RVM_ASMINS_RELOCPTR | RVM_ASMINS_RELOC);
1785                 }
1786         }
1787 }
1788