RPA Toolkit
Removed RMV_ prefix from the opcode display names.
[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 "rvm/rvmcpu.h"
24 #include "rvm/rvmoperator.h"
25 #include "rvm/rvmoperatorbin.h"
26 #include "rvm/rvmoperatorcast.h"
27 #include "rvm/rvmoperatornot.h"
28 #include "rvm/rvmoperatorlogicnot.h"
29 #include "rvm/rvmcodemap.h"
30 #include "rlib/rmem.h"
31 #include "rlib/rstring.h"
32 #include "rvm/rvmreg.h"
33 #include "rlib/rmap.h"
34
35 #define RVM_DEFAULT_STACKSIZE (4 * 1024)
36
37 static const char *stropcalls[] = {
38         "EXT",
39         "ABORT",
40         "PRN",
41         "ASR",
42         "SWI",
43         "SWIID",
44         "CALL",
45         "MOV",
46         "MOVS",
47         "SWP",
48         "INC",
49         "DEC",
50         "ADD",
51         "ADDS",
52         "ADC",
53         "AND",
54         "BIC",
55         "CLZ",
56         "CMN",
57         "XOR",
58         "SUB",
59         "SUBS",
60         "SBC",
61         "MUL",
62         "MLS",
63         "MULS",
64         "NOT",
65         "DIV",
66         "DVS",
67         "DIVS",
68         "MOD",
69         "MODS",
70         "BX",
71         "BXEQ",
72         "BXNEQ",
73         "BXLEQ",
74         "BXGEQ",
75         "BXLES",
76         "BXGRE",
77         "BXL",
78         "BL",
79         "B",
80         "STR",
81         "STRP",
82         "STRB",
83         "STRH",
84         "STRW",
85         "STRR",
86         "LDR",
87         "LDRP",
88         "LDRB",
89         "LDRH",
90         "LDRW",
91         "LDRR",
92         "CFLAG",
93         "CLR",
94         "CLRR",
95         "LSL",
96         "LSR",
97         "LSRS",
98         "STM",
99         "LDM",
100         "STS",
101         "LDS",
102         "ORR",
103         "PUSH",
104         "POP",
105         "CMP",
106         "NOP",
107         "BEQ",
108         "BNEQ",
109         "BLEQ",
110         "BGEQ",
111         "BLES",
112         "BGRE",
113         "RET",
114         "ROR",
115         "PUSHM",
116         "POPM",
117         "TST",
118         "TEQ",
119         "ADDRS",
120
121         "CAST",         /* Cast: op1 = (op3)op2 */
122         "TYPE",         /* Type: op1 = typeof(op2) */
123         "SETTYPE",      /* Type: op1.type = op2 */
124         "EMOV",
125         "ENEG",
126         "EADD",
127         "ESUB",
128         "EMUL",
129         "EDIV",
130         "EMOD",
131         "ELSL",
132         "ELSR",
133         "ELSRU",
134         "EAND",
135         "EORR",
136         "EXOR",
137         "ENOT",
138         "ELAND",
139         "ELOR",
140         "ELNOT",
141         "EEQ",
142         "ENOTEQ",
143         "EGREAT",
144         "EGREATEQ",
145         "ELESS",
146         "ELESSEQ",
147         "ECMP",
148         "ECMN",
149         "ALLOCSTR",
150         "ALLOCARR",
151         "ADDRA",
152         "LDA",
153         "STA",
154         "MAPALLOC",
155         "MAPADDR",
156         "MAPLDR",
157         "MAPSTR",
158         "MAPLKUP",
159         "MAPADD",
160         "MAPLKUPADD",
161         "UNKNOWN",
162         "UNKNOWN",
163         "UNKNOWN",
164         "UNKNOWN",
165         "UNKNOWN",
166         "UNKNOWN",
167         "UNKNOWN",
168         "UNKNOWN",
169         "UNKNOWN",
170         "UNKNOWN",
171         "UNKNOWN",
172 };
173
174
175 static void rvm_op_b(rvmcpu_t *cpu, rvm_asmins_t *ins)
176 {
177         rword pc = 0;
178
179 //      if (ins->op1 != XX)
180 //              pc += RVM_CPUREG_GETU(cpu, ins->op1);
181 //      if (ins->op2 != XX)
182 //              pc += RVM_CPUREG_GETU(cpu, ins->op2);
183 //      if (ins->op3 != XX)
184 //              pc += RVM_CPUREG_GETU(cpu, ins->op3);
185         pc += RVM_CPUREG_GETU(cpu, ins->op1);
186         RVM_CPUREG_INCIP(cpu, PC, pc - 1);
187 }
188
189
190 static void rvm_op_beq(rvmcpu_t *cpu, rvm_asmins_t *ins)
191 {
192         rword pc = 0;
193
194         if ((cpu->status & RVM_STATUS_Z)) {
195 //              if (ins->op1 != XX)
196 //                      pc += RVM_CPUREG_GETU(cpu, ins->op1);
197 //              if (ins->op2 != XX)
198 //                      pc += RVM_CPUREG_GETU(cpu, ins->op2);
199 //              if (ins->op3 != XX)
200 //                      pc += RVM_CPUREG_GETU(cpu, ins->op3);
201                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
202                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
203         }
204 }
205
206
207 static void rvm_op_bneq(rvmcpu_t *cpu, rvm_asmins_t *ins)
208 {
209         rword pc = 0;
210
211         if ((cpu->status & RVM_STATUS_Z) == 0) {
212 //              if (ins->op1 != XX)
213 //                      pc += RVM_CPUREG_GETU(cpu, ins->op1);
214 //              if (ins->op2 != XX)
215 //                      pc += RVM_CPUREG_GETU(cpu, ins->op2);
216 //              if (ins->op3 != XX)
217 //                      pc += RVM_CPUREG_GETU(cpu, ins->op3);
218                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
219                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
220         }
221 }
222
223
224 static void rvm_op_bleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
225 {
226         rword pc = 0;
227
228         if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)) {
229 //              if (ins->op1 != XX)
230 //                      pc += RVM_CPUREG_GETU(cpu, ins->op1);
231 //              if (ins->op2 != XX)
232 //                      pc += RVM_CPUREG_GETU(cpu, ins->op2);
233 //              if (ins->op3 != XX)
234 //                      pc += RVM_CPUREG_GETU(cpu, ins->op3);
235                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
236                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
237         }
238 }
239
240 static void rvm_op_bgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
241 {
242         rword pc = 0;
243
244         if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1) {
245 //              if (ins->op1 != XX)
246 //                      pc += RVM_CPUREG_GETU(cpu, ins->op1);
247 //              if (ins->op2 != XX)
248 //                      pc += RVM_CPUREG_GETU(cpu, ins->op2);
249 //              if (ins->op3 != XX)
250 //                      pc += RVM_CPUREG_GETU(cpu, ins->op3);
251                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
252                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
253         }
254 }
255
256
257 static void rvm_op_bles(rvmcpu_t *cpu, rvm_asmins_t *ins)
258 {
259         rword pc = 0;
260
261
262         if ((cpu->status & RVM_STATUS_N)) {
263 //              if (ins->op1 != XX)
264 //                      pc += RVM_CPUREG_GETU(cpu, ins->op1);
265 //              if (ins->op2 != XX)
266 //                      pc += RVM_CPUREG_GETU(cpu, ins->op2);
267 //              if (ins->op3 != XX)
268 //                      pc += RVM_CPUREG_GETU(cpu, ins->op3);
269                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
270                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
271         }
272 }
273
274
275 static void rvm_op_bgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
276 {
277         rword pc = 0;
278
279         if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 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                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
287                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
288         }
289 }
290
291
292 static void rvm_op_bx(rvmcpu_t *cpu, rvm_asmins_t *ins)
293 {
294         RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
295 }
296
297
298 static void rvm_op_bxleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
299 {
300         if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)) {
301                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
302         }
303 }
304
305
306 static void rvm_op_bxgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
307 {
308         if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1){
309                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
310         }
311 }
312
313
314 static void rvm_op_bxles(rvmcpu_t *cpu, rvm_asmins_t *ins)
315 {
316         if ((cpu->status & RVM_STATUS_N)) {
317                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
318         }
319 }
320
321
322 static void rvm_op_bxgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
323 {
324         if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0) {
325                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
326         }
327 }
328
329
330 static void rvm_op_bxeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
331 {
332         if ((cpu->status & RVM_STATUS_Z)) {
333                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
334         }
335 }
336
337
338 static void rvm_op_bxneq(rvmcpu_t *cpu, rvm_asmins_t *ins)
339 {
340         if (!(cpu->status & RVM_STATUS_Z)) {
341                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
342         }
343 }
344
345
346 static void rvm_op_bxl(rvmcpu_t *cpu, rvm_asmins_t *ins)
347 {
348         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
349         RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
350 }
351
352
353 static void rvm_op_bl(rvmcpu_t *cpu, rvm_asmins_t *ins)
354 {
355         rword pc = 0;
356
357 //      if (ins->op1 != XX)
358 //              pc += RVM_CPUREG_GETU(cpu, ins->op1);
359 //      if (ins->op2 != XX)
360 //              pc += RVM_CPUREG_GETU(cpu, ins->op2);
361 //      if (ins->op3 != XX)
362 //              pc += RVM_CPUREG_GETU(cpu, ins->op3);
363         pc += RVM_CPUREG_GETU(cpu, ins->op1);
364         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
365         RVM_CPUREG_INCIP(cpu, PC, pc - 1);
366 }
367
368
369 static void rvm_op_exit(rvmcpu_t *cpu, rvm_asmins_t *ins)
370 {
371         cpu->abort = 1;
372 }
373
374
375 static void rvm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
376 {
377         RVM_CPUREG_SET(cpu, ins->op1, RVM_CPUREG_GET(cpu, ins->op2));
378 }
379
380
381 static void rvm_op_movs(rvmcpu_t *cpu, rvm_asmins_t *ins)
382 {
383         rword op2 = RVM_CPUREG_GETU(cpu, ins->op2);;
384
385         RVM_CPUREG_SETU(cpu, ins->op1, op2);
386         RVM_STATUS_CLRALL(cpu);
387         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !op2);
388         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, op2 & RVM_SIGN_BIT);
389 }
390
391
392 static void rvm_op_swp(rvmcpu_t *cpu, rvm_asmins_t *ins)
393 {
394         rvmreg_t tmp = RVM_CPUREG_GET(cpu, ins->op1);
395         RVM_CPUREG_SET(cpu, ins->op1, RVM_CPUREG_GET(cpu, ins->op2));
396         RVM_CPUREG_SET(cpu, ins->op2, tmp);
397 }
398
399
400 static void rvm_op_ldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
401 {
402         RVM_CPUREG_SETU(cpu, ins->op1, *((rword*)RVM_CPUREG_GETU(cpu, ins->op2)));
403         
404 }
405
406
407 static void rvm_op_ldrp(rvmcpu_t *cpu, rvm_asmins_t *ins)
408 {
409         RVM_CPUREG_SETU(cpu, ins->op1, *((rpointer*)RVM_CPUREG_GETU(cpu, ins->op2)));
410 }
411
412
413 static void rvm_op_ldrb(rvmcpu_t *cpu, rvm_asmins_t *ins)
414 {
415         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint8*)RVM_CPUREG_GETU(cpu, ins->op2)));
416 }
417
418
419 static void rvm_op_ldrh(rvmcpu_t *cpu, rvm_asmins_t *ins)
420 {
421         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint16*)RVM_CPUREG_GETU(cpu, ins->op2)));
422 }
423
424
425 static void rvm_op_ldrw(rvmcpu_t *cpu, rvm_asmins_t *ins)
426 {
427         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint32*)RVM_CPUREG_GETU(cpu, ins->op2)));
428 }
429
430
431 static void rvm_op_ldrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
432 {
433         RVM_CPUREG_SET(cpu, ins->op1, *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)));
434 }
435
436
437 static void rvm_op_clr(rvmcpu_t *cpu, rvm_asmins_t *ins)
438 {
439         RVM_REG_CLEAR(((rvmreg_t*)RVM_CPUREG_PTR(cpu, ins->op1)));
440         RVM_REG_SETTYPE(((rvmreg_t*)RVM_CPUREG_PTR(cpu, ins->op1)), RVM_DTYPE_UNDEF);
441 }
442
443
444 static void rvm_op_cflag(rvmcpu_t *cpu, rvm_asmins_t *ins)
445 {
446         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1);
447         RVM_STATUS_CLRBIT(cpu, op1);
448 }
449
450
451 static void rvm_op_clrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
452 {
453         RVM_REG_CLEAR(((rvmreg_t*)RVM_CPUREG_GETP(cpu, ins->op1)));
454         RVM_REG_SETTYPE(((rvmreg_t*)RVM_CPUREG_GETP(cpu, ins->op1)), RVM_DTYPE_UNDEF);
455 }
456
457
458 static void rvm_op_str(rvmcpu_t *cpu, rvm_asmins_t *ins)
459 {
460         *((rword*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GETU(cpu, ins->op1);
461 }
462
463
464 static void rvm_op_strp(rvmcpu_t *cpu, rvm_asmins_t *ins)
465 {
466         *((rpointer*)RVM_CPUREG_GETP(cpu, ins->op2)) = (rpointer)RVM_CPUREG_GETP(cpu, ins->op1);
467 }
468
469
470 static void rvm_op_strb(rvmcpu_t *cpu, rvm_asmins_t *ins)
471 {
472         *((ruint8*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint8)RVM_CPUREG_GETU(cpu, ins->op1);
473 }
474
475
476 static void rvm_op_strh(rvmcpu_t *cpu, rvm_asmins_t *ins)
477 {
478         *((ruint16*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint16)RVM_CPUREG_GETU(cpu, ins->op1);
479         
480 }
481
482
483 static void rvm_op_strw(rvmcpu_t *cpu, rvm_asmins_t *ins)
484 {
485         *((ruint32*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint32)RVM_CPUREG_GETU(cpu, ins->op1);
486
487 }
488
489
490 static void rvm_op_strr(rvmcpu_t *cpu, rvm_asmins_t *ins)
491 {
492         rvmreg_t *dest = RVM_CPUREG_PTR(cpu, ins->op2);
493         if (RVM_REG_GETTYPE(dest) != RVM_DTYPE_POINTER)
494                 RVM_ABORT(cpu, RVM_E_LVALUE);
495         else
496                 *((rvmreg_t*)RVM_REG_GETP(dest)) = RVM_CPUREG_GET(cpu, ins->op1);
497 }
498
499
500 static void rvm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
501 {
502         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
503
504         res = op2 + op3;
505         RVM_CPUREG_SETU(cpu, ins->op1, res);
506         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
507         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
508         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
509         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
510                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
511 }
512
513
514 static void rvm_op_adc(rvmcpu_t *cpu, rvm_asmins_t *ins)
515 {
516         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
517         
518         res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
519         RVM_CPUREG_SETU(cpu, ins->op1, res);
520         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
521         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
522         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
523         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
524                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
525 }
526
527
528 static void rvm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
529 {
530         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
531         
532         res = op2 & op3;
533         RVM_CPUREG_SETU(cpu, ins->op1, res);
534         RVM_STATUS_CLRALL(cpu);
535         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
536         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
537 }
538
539
540 static void rvm_op_orr(rvmcpu_t *cpu, rvm_asmins_t *ins)
541 {
542         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
543         
544         res = op2 | op3;
545         RVM_CPUREG_SETU(cpu, ins->op1, res);
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_lsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
553 {
554         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
555         
556         res = op2 << op3;
557         RVM_CPUREG_SETU(cpu, ins->op1, res);
558         RVM_STATUS_CLRALL(cpu);
559         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
560         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
561 }
562
563
564 static void rvm_op_lsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
565 {
566         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
567         
568         res = op2 >> op3;
569         RVM_CPUREG_SETU(cpu, ins->op1, res);
570         RVM_STATUS_CLRALL(cpu);
571         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
572 }
573
574
575 static void rvm_op_lsrs(rvmcpu_t *cpu, rvm_asmins_t *ins)
576 {
577         rsword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
578
579         res = ((rsword)op2) >> op3;
580         RVM_CPUREG_SETU(cpu, ins->op1, res);
581         RVM_STATUS_CLRALL(cpu);
582         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
583 }
584
585
586 static void rvm_op_asr(rvmcpu_t *cpu, rvm_asmins_t *ins)
587 {
588         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
589         
590         res = op2 >> op3;
591         res |= op2 & RVM_SIGN_BIT;
592         RVM_CPUREG_SETU(cpu, ins->op1, res);
593         RVM_STATUS_CLRALL(cpu);
594         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
595         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
596 }
597
598
599 static void rvm_op_ror(rvmcpu_t *cpu, rvm_asmins_t *ins)
600 {
601         unsigned int i;
602         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
603         
604         res = op2;
605         for (i = 0; i < op3; i++) {
606                 if (res & 1) {
607                         res >>= 1;
608                         res |= RVM_SIGN_BIT;
609                 } else {
610                         res >>= 1;
611                 }
612         }
613         RVM_CPUREG_SETU(cpu, ins->op1, res);
614         RVM_STATUS_CLRALL(cpu);
615         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
616         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
617         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res & RVM_SIGN_BIT);
618 }
619
620
621 static void rvm_op_tst(rvmcpu_t *cpu, rvm_asmins_t *ins)
622 {
623         rword res, op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
624         
625         res = op1 & op2;
626         RVM_STATUS_CLRALL(cpu);
627         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
628         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
629 }
630
631
632 static void rvm_op_xor(rvmcpu_t *cpu, rvm_asmins_t *ins)
633 {
634         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
635         
636         res = op2 ^ op3;
637         RVM_CPUREG_SETU(cpu, ins->op1, res);
638         RVM_STATUS_CLRALL(cpu);
639         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
640         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
641 }
642
643
644 static void rvm_op_not(rvmcpu_t *cpu, rvm_asmins_t *ins)
645 {
646         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
647         
648         res = ~op2;
649         RVM_CPUREG_SETU(cpu, ins->op1, res);
650         RVM_STATUS_CLRALL(cpu);
651         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
652         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
653 }
654
655
656 static void rvm_op_teq(rvmcpu_t *cpu, rvm_asmins_t *ins)
657 {
658         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
659         
660         res = op2 ^ op3;
661         RVM_STATUS_CLRALL(cpu);
662         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
663         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
664 }
665
666
667 static void rvm_op_bic(rvmcpu_t *cpu, rvm_asmins_t *ins)
668 {
669         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
670         
671         res = op2 & ~op3;
672         RVM_CPUREG_SETU(cpu, ins->op1, res);
673         RVM_STATUS_CLRALL(cpu);
674         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
675         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
676 }
677
678
679 static void rvm_op_clz(rvmcpu_t *cpu, rvm_asmins_t *ins)
680 {
681         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
682         
683         for (res = RVM_REGISTER_BITS; op2; ) {
684                 op2 >>= 1;
685                 res -= 1;
686         }
687         RVM_CPUREG_SETU(cpu, ins->op1, res);
688 }
689
690
691 static void rvm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
692 {
693         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3));
694 }
695
696
697 static void rvm_op_inc(rvmcpu_t *cpu, rvm_asmins_t *ins)
698 {
699         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op1) + 1);
700 }
701
702
703 static void rvm_op_dec(rvmcpu_t *cpu, rvm_asmins_t *ins)
704 {
705         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
706 }
707
708
709 static void rvm_op_swi(rvmcpu_t *cpu, rvm_asmins_t *ins)
710 {
711         rvmcpu_swi swi;
712         rvm_switable_t *switable;
713         unsigned int ntable = (unsigned int) RVM_SWI_TABLE(ins->swi);
714         unsigned int nswi = (unsigned int) RVM_SWI_NUM(ins->swi);
715
716         if (r_harray_length(cpu->switables) <= ntable)
717                 RVM_ABORT(cpu, RVM_E_SWITABLE);
718         switable = r_harray_index(cpu->switables, ntable, rvm_switable_t*);
719         swi = switable[nswi].op;
720         swi(cpu, ins);
721 }
722
723
724 static void rvm_op_swiid(rvmcpu_t *cpu, rvm_asmins_t *ins)
725 {
726         rvmcpu_swi swi;
727         rvm_switable_t *switable;
728         unsigned int ntable = (unsigned int) RVM_SWI_TABLE(RVM_CPUREG_GETU(cpu, ins->op1));
729         unsigned int nswi = (unsigned int) RVM_SWI_NUM(RVM_CPUREG_GETU(cpu, ins->op1));
730
731         if (r_harray_length(cpu->switables) <= ntable)
732                 RVM_ABORT(cpu, RVM_E_SWITABLE);
733         switable = r_harray_index(cpu->switables, ntable, rvm_switable_t*);
734         swi = switable[nswi].op;
735         swi(cpu, ins);
736 }
737
738
739 static void rvm_op_call(rvmcpu_t *cpu, rvm_asmins_t *ins)
740 {
741         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
742
743         if (RVM_REG_GETTYPE(arg1) == RVM_DTYPE_SWIID) {
744                 RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
745                 rvm_op_swiid(cpu, ins);
746         } else if (RVM_REG_GETTYPE(arg1) == RVM_DTYPE_FUNCTION) {
747                 rvm_op_bxl(cpu, ins);
748         } else {
749                 RVM_ABORT(cpu, RVM_E_NOTFUNCTION);
750         }
751 }
752
753
754 static void rvm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
755 {
756         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
757 }
758
759
760 static void rvm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
761 {
762         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
763         
764         res = op2 - op3;
765         RVM_CPUREG_SETU(cpu, ins->op1, res);
766         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
767         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
768         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
769         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
770                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
771 }
772
773
774 static void rvm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
775 {
776         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
777
778         res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
779         RVM_CPUREG_SETU(cpu, ins->op1, res);
780         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
781         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
782         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
783         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
784                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
785 }
786
787
788 static void rvm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
789 {
790         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
791 }
792
793
794 static void rvm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
795 {
796         rsword res;
797         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
798
799         res = (rsword)(op2 * op3);
800         RVM_CPUREG_SETU(cpu, ins->op1, res);
801         /* TBD: Not sure how to update the RVM_STATUS_C */
802         RVM_STATUS_CLRALL(cpu);
803         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
804         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
805 }
806
807
808 static void rvm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
809 {
810         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
811         
812         res = op2 * op3;
813         RVM_CPUREG_SETU(cpu, ins->op1, res);
814         RVM_STATUS_CLRALL(cpu);
815         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
816         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
817         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
818 }
819
820
821 static void rvm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
822 {
823         if (!RVM_CPUREG_GETU(cpu, ins->op3))
824                 RVM_ABORT(cpu, RVM_E_DIVZERO);
825
826         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
827 }
828
829
830 static void rvm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
831 {
832         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
833
834         if (!op3)
835                 RVM_ABORT(cpu, RVM_E_DIVZERO);
836         res = op2 / op3;
837         RVM_CPUREG_SETU(cpu, ins->op1, res);
838         RVM_STATUS_CLRALL(cpu);
839         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
840         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
841 }
842
843
844 static void rvm_op_mod(rvmcpu_t *cpu, rvm_asmins_t *ins)
845 {
846         if (!RVM_CPUREG_GETU(cpu, ins->op3))
847                 RVM_ABORT(cpu, RVM_E_DIVZERO);
848
849         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) % RVM_CPUREG_GETU(cpu, ins->op3));
850 }
851
852
853 static void rvm_op_mods(rvmcpu_t *cpu, rvm_asmins_t *ins)
854 {
855         rsword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
856
857         if (!op3)
858                 RVM_ABORT(cpu, RVM_E_DIVZERO);
859         res = op2 % op3;
860         r_printf("mod RES: %ld\n", res);
861         RVM_CPUREG_SETU(cpu, ins->op1, res);
862         RVM_STATUS_CLRALL(cpu);
863         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
864         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
865 }
866
867
868 static void rvm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
869 {
870         rsword res;
871         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
872
873         if (!op3)
874                 RVM_ABORT(cpu, RVM_E_DIVZERO);
875         res = (rsword)(op2 / op3);
876         RVM_CPUREG_SETU(cpu, ins->op1, res);
877         RVM_STATUS_CLRALL(cpu);
878         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
879         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
880 }
881
882
883 static void rvm_op_push(rvmcpu_t *cpu, rvm_asmins_t *ins)
884 {
885         rword sp = RVM_CPUREG_GETU(cpu, SP) + 1;
886
887         if (!RVM_STACK_CHECKSIZE(cpu, cpu->stack, sp))
888                 RVM_ABORT(cpu, RVM_E_NOMEM);
889         RVM_STACK_WRITE(cpu->stack, sp, &RVM_CPUREG_GET(cpu, ins->op1));
890         RVM_CPUREG_SETU(cpu, SP, sp);
891 }
892
893
894 static void rvm_op_lds(rvmcpu_t *cpu, rvm_asmins_t *ins)
895 {
896         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
897
898         RVM_CPUREG_SET(cpu, ins->op1, RVM_STACK_READ(cpu->stack, sp));
899 }
900
901
902 static void rvm_op_sts(rvmcpu_t *cpu, rvm_asmins_t *ins)
903 {
904         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
905
906         if (!RVM_STACK_CHECKSIZE(cpu, cpu->stack, sp))
907                 RVM_ABORT(cpu, RVM_E_NOMEM);
908         RVM_STACK_WRITE(cpu->stack, sp, &RVM_CPUREG_GET(cpu, ins->op1));
909 }
910
911
912 static void rvm_op_pushm(rvmcpu_t *cpu, rvm_asmins_t *ins)
913 {
914         rword n, i = 0;
915         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
916         rword sp = RVM_CPUREG_GETU(cpu, SP);
917
918         if (!RVM_STACK_CHECKSIZE(cpu, cpu->stack, sp + RVM_REGS_NUM))
919                 RVM_ABORT(cpu, RVM_E_NOMEM);
920
921         if (!(bits & ((1<<(RVM_REGS_NUM / 2)) - 1)))
922                 i = RVM_REGS_NUM / 2;
923         for (;bits && i < RLST; i++) {
924                 n = 1 << i;
925                 if (n & bits) {
926                         sp += 1;
927                         RVM_STACK_WRITE(cpu->stack, sp, &RVM_CPUREG_GET(cpu, i));
928                         bits &= ~n;
929                 }
930         }
931         RVM_CPUREG_SETU(cpu, SP, sp);
932 }
933
934
935 static void rvm_op_popm(rvmcpu_t *cpu, rvm_asmins_t *ins)
936 {
937         int n, i = RLST - 1;
938         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
939         rword savedbits = bits;
940         rword sp = RVM_CPUREG_GETU(cpu, SP);
941
942         if (!(bits & ~((1 << (RVM_REGS_NUM / 2)) - 1)))
943                 i = RVM_REGS_NUM / 2 - 1;
944         for (; bits && i >= 0; i--) {
945                 n = 1 << i;
946                 if (n & bits) {
947                         RVM_CPUREG_SET(cpu, i, RVM_STACK_READ(cpu->stack, sp));
948                         sp -= 1;
949                         bits &= ~n;
950                 }
951         }
952         if (!(((rword)(1 << SP)) & savedbits))
953                 RVM_CPUREG_SETU(cpu, SP, sp);
954 }
955
956
957 static void rvm_op_pop(rvmcpu_t *cpu, rvm_asmins_t *ins)
958 {
959         rword sp = RVM_CPUREG_GETU(cpu, SP);
960
961         RVM_CPUREG_SET(cpu, ins->op1, RVM_STACK_READ(cpu->stack, sp));
962         if (ins->op1 != SP)
963                 RVM_CPUREG_SETU(cpu, SP, sp - 1);
964 }
965
966
967 static void rvm_op_addrs(rvmcpu_t *cpu, rvm_asmins_t *ins)
968 {
969         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
970
971         if (!RVM_STACK_CHECKSIZE(cpu, cpu->stack, sp))
972                 RVM_ABORT(cpu, RVM_E_NOMEM);
973
974         RVM_CPUREG_CLEAR(cpu, ins->op1);
975         RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_POINTER);
976         RVM_CPUREG_SETP(cpu, ins->op1, RVM_STACK_ADDR(cpu->stack, sp));
977 }
978
979
980 static void rvm_op_stm(rvmcpu_t *cpu, rvm_asmins_t *ins)
981 {
982         int n;
983         rword *dst = (rword*)   RVM_CPUREG_GETU(cpu, ins->op1);
984         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
985         
986         for (n = 0; bits && n < RLST; n++) {
987                 if (((rword)(1 << n)) & bits) {
988                         *dst = RVM_CPUREG_GETU(cpu, n);
989                         dst += 1;
990                         bits &= ~(1<<n);
991                 }
992         }
993 }
994
995
996 static void rvm_op_ldm(rvmcpu_t *cpu, rvm_asmins_t *ins)
997 {
998         int n;
999         rword *src = (rword*)RVM_CPUREG_GETU(cpu, ins->op1);
1000         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
1001
1002         for (n = 0; bits && n < RLST; n++) {
1003                 if (((rword)(1 << n)) & bits) {
1004                         RVM_CPUREG_CLEAR(cpu, n);
1005                         RVM_CPUREG_SETU(cpu, n, *src);
1006                         src += 1;
1007                         bits &= ~(1<<n);
1008                 }
1009         }
1010 }
1011
1012
1013 static void rvm_op_cmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
1014 {
1015         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
1016         rword res = (rword)(op1 - op2);
1017         
1018         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op1 < op2);
1019         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
1020         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
1021         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT) &&
1022                                                         (res & RVM_SIGN_BIT) == (op1 & RVM_SIGN_BIT));
1023 }
1024
1025
1026 static void rvm_op_cmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
1027 {
1028         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
1029         rword res = (rword)(op1 + op2);
1030         
1031         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op1 || res < op2);
1032         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
1033         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
1034         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT) &&
1035                                                         (res & RVM_SIGN_BIT) != (op1 & RVM_SIGN_BIT));
1036
1037 }
1038
1039
1040 static void rvm_op_nop(rvmcpu_t *cpu, rvm_asmins_t *ins)
1041 {
1042 //      fprintf(stdout, "nop\n");
1043 }
1044
1045
1046 static void rvm_op_ret(rvmcpu_t *cpu, rvm_asmins_t *ins)
1047 {
1048         RVM_CPUREG_SETU(cpu, PC, RVM_CPUREG_GETU(cpu, LR));
1049 }
1050
1051
1052 static int rvm_vsnprintf(char *str, unsigned int size, const char *format, va_list ap)
1053 {
1054         return vsnprintf(str, size, format, ap);
1055 }
1056
1057
1058 static int rvm_snprintf(char *str, unsigned int size, const char *format, ...)
1059 {
1060         va_list ap;
1061         int ret;
1062
1063         va_start(ap, format);
1064         ret = rvm_vsnprintf(str, size, format, ap);
1065         va_end(ap);
1066         return ret;
1067 }
1068
1069
1070 static int rvm_printf(const char *format, ...)
1071 {
1072         va_list ap;
1073         int ret;
1074
1075         va_start(ap, format);
1076         ret = vfprintf(stdout, format, ap);
1077         va_end(ap);
1078         return ret;
1079 }
1080
1081
1082 int rvm_asm_dump_reg_to_str(unsigned char reg, char *str, unsigned int size)
1083 {
1084         int ret = 0;
1085
1086         if (reg == XX)
1087                 ret = rvm_snprintf(str, size, "XX ");
1088         else if (reg == IP)
1089                 ret = rvm_snprintf(str, size, "IP ");
1090         else if (reg == TP)
1091                 ret = rvm_snprintf(str, size, "TP ");
1092         else if (reg == FP)
1093                 ret = rvm_snprintf(str, size, "FP ");
1094         else if (reg == SP)
1095                 ret = rvm_snprintf(str, size, "SP ");
1096         else if (reg == LR)
1097                 ret = rvm_snprintf(str, size, "LR ");
1098         else if (reg == PC)
1099                 ret = rvm_snprintf(str, size, "PC ");
1100         else if (reg == DA)
1101                 ret = rvm_snprintf(str, size, "DA ");
1102         else
1103                 ret = rvm_snprintf(str, size, "R%d ",  reg);
1104
1105         return ret;
1106 }
1107
1108
1109 static void rvm_op_prn(rvmcpu_t *cpu, rvm_asmins_t *ins)
1110 {
1111         rvmreg_t *r = RVM_CPUREG_PTR(cpu, ins->op1);
1112
1113         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
1114                 rvm_printf("(UNSIGNED) R%d = %lu(0x%lx)\n", ins->op1, RVM_REG_GETU(r), RVM_REG_GETU(r));
1115         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
1116                 rvm_printf("(UNSIGNED) R%d = %lu(0x%lx)\n", ins->op1, RVM_REG_GETU(r), RVM_REG_GETU(r));
1117         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
1118                 rvm_printf("(POINTER) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
1119         else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
1120                 rvm_printf("(LONG) R%d = %ld\n", ins->op1, RVM_REG_GETL(r));
1121         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
1122                 rvm_printf("(DOUBLE) R%d = %0.2f\n", ins->op1, RVM_REG_GETD(r));
1123         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
1124                 rvm_printf("(STRING) R%d = %s\n", ins->op1, ((rstring_t*) RVM_REG_GETP(r))->s.str);
1125         else if (rvm_reg_gettype(r) == RVM_DTYPE_ARRAY)
1126                 rvm_printf("(ARRAY) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
1127         else if (rvm_reg_gettype(r) == RVM_DTYPE_JSOBJECT)
1128                 rvm_printf("(Object) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
1129         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
1130                 rvm_printf("(SWI) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
1131         else if (rvm_reg_gettype(r) == RVM_DTYPE_FUNCTION)
1132                 rvm_printf("(FUNCTION) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
1133         else
1134                 rvm_printf("(UNKNOWN) R%d = ?\n", ins->op1);
1135 }
1136
1137
1138 int rvm_asm_dump_pi_to_str(rvmcpu_t *vm, rvm_asmins_t *pi, char *str, unsigned int size)
1139 {
1140         int ret = 0, sz = size;
1141
1142         if (pi->opcode == RVM_SWI) {
1143                 char szSwi[64];
1144                 r_memset(szSwi, 0, sizeof(szSwi));
1145                 if (!vm) {
1146                         rvm_snprintf(szSwi, sizeof(szSwi) - 1, "%s(%x)", stropcalls[pi->opcode], (ruint32)pi->swi);
1147                 } else {
1148                         rvm_switable_t *switable;
1149                         unsigned int ntable = (unsigned int) RVM_SWI_TABLE(pi->swi);
1150                         unsigned int nswi = (unsigned int) RVM_SWI_NUM(pi->swi);
1151
1152                         if (ntable < r_harray_length(vm->switables)) {
1153                                 switable = r_harray_index(vm->switables, ntable, rvm_switable_t*);
1154                                 rvm_snprintf(szSwi, sizeof(szSwi) - 1, "(%s)",  switable[nswi].name ? switable[nswi].name : "unknown");
1155                         }
1156                 }
1157                 if ((ret = rvm_snprintf(str, sz, "%16s   ", szSwi)) < 0)
1158                         return ret;
1159         } else {
1160                 if ((ret = rvm_snprintf(str, sz, "%16s   ", stropcalls[pi->opcode])) < 0)
1161                         return ret;
1162         }
1163         str += ret;
1164         sz -= ret;
1165         
1166         if ((ret = rvm_asm_dump_reg_to_str(pi->op1, str, sz)) < 0)
1167                 return ret;
1168         str += ret;
1169         sz -= ret;
1170                 
1171         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1172                 return ret;
1173         str += ret;
1174         sz -= ret;
1175
1176         if ((ret = rvm_asm_dump_reg_to_str(pi->op2, str, sz)) < 0)
1177                 return ret;
1178         str += ret;
1179         sz -= ret;
1180                 
1181         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1182                 return ret;
1183         str += ret;
1184         sz -= ret;
1185
1186         if ((ret = rvm_asm_dump_reg_to_str(pi->op3, str, sz)) < 0)
1187                 return ret;
1188         str += ret;
1189         sz -= ret;
1190                 
1191         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1192                 return ret;
1193         str += ret;
1194         sz -= ret;
1195
1196
1197         if (RVM_REG_GETTYPE(&pi->data) == RVM_DTYPE_DOUBLE) {
1198                 if ((ret = rvm_snprintf(str, sz, "%f  ", RVM_REG_GETD(&pi->data))) < 0)
1199                         return ret;
1200         } else if (RVM_REG_GETTYPE(&pi->data) == RVM_DTYPE_LONG) {
1201                 if ((ret = rvm_snprintf(str, sz, "%ld  ", RVM_REG_GETL(&pi->data))) < 0)
1202                         return ret;
1203         } else {
1204                 if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)RVM_REG_GETU(&pi->data))) < 0)
1205                         return ret;
1206         }
1207
1208         str += ret;
1209         sz -= ret;
1210
1211         return size - sz;
1212 }
1213
1214
1215 void rvm_asm_dump(rvm_asmins_t *pi, unsigned int count)
1216 {
1217         char buffer[256];
1218         while (count) {
1219                 rvm_asm_dump_pi_to_str(NULL, pi, buffer, sizeof(buffer));
1220                 rvm_printf("%s\n", buffer);
1221                 ++pi;
1222                 --count;
1223         }
1224 }
1225
1226
1227 void rvm_cpu_dumpregs(rvmcpu_t *vm, rvm_asmins_t *pi)
1228 {
1229     int ret;
1230         char buffer[1024];
1231         
1232         ret = rvm_asm_dump_pi_to_str(vm, pi, buffer, sizeof(buffer));
1233         if (ret < 0)
1234                 return;
1235     ret = rvm_snprintf(buffer + ret, sizeof(buffer) - ret, "                                                                                        ");
1236         buffer[50] = '\0';
1237         rvm_printf("%s", buffer);
1238
1239         rvm_printf("0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, TP=%p, FP=%ld, SP=%ld, LR=0x%lx, PC=0x%lx, DA=0x%lx, S( %c%c%c%c%c )",
1240                 RVM_CPUREG_GETU(vm, 0), RVM_CPUREG_GETU(vm, 1), RVM_CPUREG_GETU(vm, 2), RVM_CPUREG_GETU(vm, 3),
1241                 RVM_CPUREG_GETU(vm, 4), RVM_CPUREG_GETU(vm, 5), RVM_CPUREG_GETU(vm, 6), RVM_CPUREG_GETU(vm, 7),
1242                 RVM_CPUREG_GETU(vm, 8), RVM_CPUREG_GETP(vm, TP), (long int)RVM_CPUREG_GETU(vm, FP), (long int)RVM_CPUREG_GETU(vm, SP),
1243                 (long int)RVM_CPUREG_GETU(vm, LR), (long int)RVM_CPUREG_GETU(vm, PC), RVM_CPUREG_GETU(vm, DA),
1244                 vm->status & RVM_STATUS_E ? 'E' : '_',
1245                 vm->status & RVM_STATUS_V ? 'V' : '_',
1246                 vm->status & RVM_STATUS_C ? 'C' : '_',
1247                 vm->status & RVM_STATUS_N ? 'N' : '_',
1248                 vm->status & RVM_STATUS_Z ? 'Z' : '_');
1249         rvm_printf("\n");
1250 }
1251
1252
1253 static void rvm_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
1254 {
1255         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
1256         rvmreg_t tmp;
1257
1258         RVM_REG_CLEAR(&tmp);
1259         RVM_REG_SETTYPE(&tmp, type);
1260         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, RVM_CPUREG_PTR(cpu, ins->op1), RVM_CPUREG_PTR(cpu, ins->op2), &tmp);
1261 }
1262
1263
1264 static void rvm_op_type(rvmcpu_t *cpu, rvm_asmins_t *ins)
1265 {
1266         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETTYPE(cpu, ins->op2);
1267
1268         RVM_CPUREG_SETU(cpu, ins->op1, type);
1269 }
1270
1271
1272 static void rvm_op_settype(rvmcpu_t *cpu, rvm_asmins_t *ins)
1273 {
1274         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op2);
1275
1276         RVM_CPUREG_SETTYPE(cpu, ins->op1, type);
1277 }
1278
1279
1280 static void rvm_op_emov(rvmcpu_t *cpu, rvm_asmins_t *ins)
1281 {
1282         rvm_op_mov(cpu, ins);
1283 }
1284
1285
1286 static void rvm_op_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1287 {
1288         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1289         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1290
1291         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_ADD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1292 }
1293
1294
1295 static void rvm_op_esub(rvmcpu_t *cpu, rvm_asmins_t *ins)
1296 {
1297         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1298         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1299
1300         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1301 }
1302
1303
1304 static void rvm_op_eneg(rvmcpu_t *cpu, rvm_asmins_t *ins)
1305 {
1306         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1307         rvmreg_t zero;
1308
1309         rvm_reg_setunsigned(&zero, 0);
1310         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), &zero, arg2);
1311 }
1312
1313
1314
1315 static void rvm_op_emul(rvmcpu_t *cpu, rvm_asmins_t *ins)
1316 {
1317         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1318         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1319
1320         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_MUL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1321 }
1322
1323
1324 static void rvm_op_ediv(rvmcpu_t *cpu, rvm_asmins_t *ins)
1325 {
1326         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1327         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1328
1329         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_DIV, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1330 }
1331
1332
1333 static void rvm_op_emod(rvmcpu_t *cpu, rvm_asmins_t *ins)
1334 {
1335         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1336         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1337
1338         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_MOD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1339 }
1340
1341
1342 static void rvm_op_elsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
1343 {
1344         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1345         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1346
1347         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1348 }
1349
1350
1351 static void rvm_op_elsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1352 {
1353         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1354         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1355
1356         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1357 }
1358
1359
1360 static void rvm_op_elsru(rvmcpu_t *cpu, rvm_asmins_t *ins)
1361 {
1362         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1363         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1364
1365         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSRU, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1366 }
1367
1368
1369 static void rvm_op_eand(rvmcpu_t *cpu, rvm_asmins_t *ins)
1370 {
1371         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1372         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1373
1374         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_AND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1375 }
1376
1377
1378 static void rvm_op_eorr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1379 {
1380         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1381         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1382
1383         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_OR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1384 }
1385
1386
1387 static void rvm_op_exor(rvmcpu_t *cpu, rvm_asmins_t *ins)
1388 {
1389         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1390         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1391
1392         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_XOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1393 }
1394
1395
1396 static void rvm_op_enot(rvmcpu_t *cpu, rvm_asmins_t *ins)
1397 {
1398         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1399
1400         rvm_opmap_invoke_unary_handler(cpu->opmap, RVM_OPID_NOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
1401 }
1402
1403
1404 static void rvm_op_eland(rvmcpu_t *cpu, rvm_asmins_t *ins)
1405 {
1406         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1407         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1408
1409         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LOGICAND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1410 }
1411
1412
1413 static void rvm_op_elor(rvmcpu_t *cpu, rvm_asmins_t *ins)
1414 {
1415         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1416         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1417
1418         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LOGICOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1419 }
1420
1421
1422 static void rvm_op_elnot(rvmcpu_t *cpu, rvm_asmins_t *ins)
1423 {
1424         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1425
1426         rvm_opmap_invoke_unary_handler(cpu->opmap, RVM_OPID_LOGICNOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
1427 }
1428
1429
1430 static void rvm_op_eeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1431 {
1432         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1433         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1434
1435         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_EQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1436 }
1437
1438
1439 static void rvm_op_enoteq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1440 {
1441         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1442         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1443
1444         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_NOTEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1445 }
1446
1447
1448 static void rvm_op_egreat(rvmcpu_t *cpu, rvm_asmins_t *ins)
1449 {
1450         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1451         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1452
1453         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_GREATER, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1454 }
1455
1456
1457 static void rvm_op_egreateq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1458 {
1459         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1460         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1461
1462         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_GREATEREQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1463 }
1464
1465
1466 static void rvm_op_elesseq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1467 {
1468         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1469         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1470
1471         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LESSEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1472 }
1473
1474
1475 static void rvm_op_eless(rvmcpu_t *cpu, rvm_asmins_t *ins)
1476 {
1477         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1478         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1479
1480         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LESS, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1481 }
1482
1483
1484 static void rvm_op_ecmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
1485 {
1486         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1487         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1488
1489         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMP, cpu, NULL, arg1, arg2);
1490 }
1491
1492
1493 static void rvm_op_ecmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
1494 {
1495         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1496         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1497
1498         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMN, cpu, NULL, arg1, arg2);
1499 }
1500
1501
1502 static void rvm_op_allocstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1503 {
1504
1505         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1506         rstring_t *s = r_string_create_strsize((const char*)RVM_CPUREG_GETP(cpu, ins->op2), RVM_CPUREG_GETU(cpu, ins->op3));
1507         if (!s) {
1508                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1509         }
1510         r_gc_add(cpu->gc, (robject_t*)s);
1511         rvm_reg_setstring(arg1, s);
1512 }
1513
1514
1515 static void rvm_op_mapalloc(rvmcpu_t *cpu, rvm_asmins_t *ins)
1516 {
1517         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1518         rmap_t *a = r_map_create(sizeof(rvmreg_t), 7);
1519         if (!a) {
1520                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1521         }
1522         r_gc_add(cpu->gc, (robject_t*)a);
1523         rvm_reg_setjsobject(arg1, (robject_t*)a);
1524 }
1525
1526
1527 static void rvm_op_allocarr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1528 {
1529         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1530         unsigned int size = RVM_CPUREG_GETU(cpu, ins->op2);
1531         rcarray_t *a = r_carray_create_rvmreg();
1532         if (!a) {
1533                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1534         }
1535         r_carray_setlength(a, size);
1536         r_gc_add(cpu->gc, (robject_t*)a);
1537         rvm_reg_setarray(arg1, (robject_t*)a);
1538 }
1539
1540
1541 static void rvm_op_maplookup(rvmcpu_t *cpu, rvm_asmins_t *ins)
1542 {
1543         long index;
1544         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1545         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1546         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1547         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
1548
1549         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
1550                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1551         }
1552         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_LONG || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
1553                 index = r_map_lookup_l(a, -1, RVM_REG_GETL(arg3));
1554         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
1555                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
1556         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
1557                 index = r_map_lookup(a, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
1558         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
1559                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1));
1560         } else {
1561                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1562         }
1563
1564         RVM_REG_CLEAR(arg1);
1565         RVM_REG_SETTYPE(arg1, RVM_DTYPE_LONG);
1566         RVM_REG_SETL(arg1, index);
1567 }
1568
1569
1570 static void rvm_op_mapadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1571 {
1572         long index;
1573         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1574         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1575         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1576         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
1577
1578         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
1579                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1580         }
1581         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_LONG || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
1582                 index = r_map_gckey_add_l(a, cpu->gc, RVM_REG_GETL(arg3), NULL);
1583         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
1584                 index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
1585         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
1586                 index = r_map_gckey_add(a, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
1587         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
1588                 index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1), NULL);
1589         } else {
1590                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1591         }
1592
1593         RVM_REG_CLEAR(arg1);
1594         RVM_REG_SETTYPE(arg1, RVM_DTYPE_LONG);
1595         RVM_REG_SETL(arg1, index);
1596 }
1597
1598
1599 static void rvm_op_maplookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1600 {
1601         long index;
1602         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1603         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1604         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1605         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
1606
1607         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
1608                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1609         }
1610         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_LONG || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
1611                 index = r_map_lookup_l(a, -1, RVM_REG_GETL(arg3));
1612                 if (index < 0)
1613                         index = r_map_gckey_add_l(a, cpu->gc, RVM_REG_GETL(arg3), NULL);
1614         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
1615                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
1616                 if (index < 0)
1617                         index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
1618         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
1619                 index = r_map_lookup(a, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
1620                 if (index < 0)
1621                         index = r_map_gckey_add(a, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
1622         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
1623                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1));
1624                 if (index < 0)
1625                         index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1), NULL);
1626         } else {
1627                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1628         }
1629         RVM_REG_CLEAR(arg1);
1630         RVM_REG_SETTYPE(arg1, RVM_DTYPE_LONG);
1631         RVM_REG_SETL(arg1, index);
1632 }
1633
1634
1635 static void rvm_op_mapaddr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1636 {
1637         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1638         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1639         rvmreg_t tmp = rvm_reg_create_long(0);
1640         rmap_t *a;
1641         rpointer value;
1642         long index;
1643
1644         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1645         index = RVM_REG_GETL(&tmp);
1646         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1647                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1648         a = (rmap_t*)RVM_REG_GETP(arg2);
1649         value = r_map_value(a, index);
1650         if (!value)
1651                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1652         RVM_REG_CLEAR(arg1);
1653         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
1654         RVM_REG_SETP(arg1, value);
1655 }
1656
1657
1658 static void rvm_op_mapldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1659 {
1660         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1661         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1662         rvmreg_t tmp = rvm_reg_create_long(0);
1663         rmap_t *a = NULL;
1664         rpointer value;
1665         long index;
1666
1667         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1668         index = RVM_REG_GETL(&tmp);
1669         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1670                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1671         a = (rmap_t*)RVM_REG_GETP(arg2);
1672         value = r_map_value(a, index);
1673         if (!value) {
1674                 RVM_REG_CLEAR(arg1);
1675                 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
1676         } else {
1677                 *arg1 = *((rvmreg_t*)value);
1678         }
1679 }
1680
1681
1682 static void rvm_op_mapstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1683 {
1684         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1685         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1686         rvmreg_t tmp = rvm_reg_create_long(0);
1687         rmap_t *a = NULL;
1688         rpointer value;
1689         long index;
1690
1691         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1692         index = RVM_REG_GETL(&tmp);
1693         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1694                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1695         a = (rmap_t*)RVM_REG_GETP(arg2);
1696         value = r_map_value(a, index);
1697         if (!value)
1698                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1699         r_map_setvalue(a, index, arg1);
1700 }
1701
1702
1703 static void rvm_op_addra(rvmcpu_t *cpu, rvm_asmins_t *ins)
1704 {
1705         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1706         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1707         rvmreg_t tmp = rvm_reg_create_long(0);
1708         rcarray_t *a = RVM_REG_GETP(arg2);
1709         long index;
1710
1711         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1712         index = RVM_REG_GETL(&tmp);
1713
1714         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY || index < 0) {
1715                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1716         }
1717         RVM_REG_CLEAR(arg1);
1718         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
1719         RVM_REG_SETP(arg1, r_carray_slot_expand(a, index));
1720 }
1721
1722
1723 static void rvm_op_lda(rvmcpu_t *cpu, rvm_asmins_t *ins)
1724 {
1725         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1726         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1727         unsigned int index = RVM_CPUREG_GETU(cpu, ins->op3);
1728         rcarray_t *a = RVM_REG_GETP(arg2);
1729
1730         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1731                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1732         }
1733         *arg1 = *((rvmreg_t*)r_carray_slot_expand(a, index));
1734 }
1735
1736
1737 static void rvm_op_sta(rvmcpu_t *cpu, rvm_asmins_t *ins)
1738 {
1739         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1740         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1741         unsigned int index = RVM_CPUREG_GETU(cpu, ins->op3);
1742         rcarray_t *a = RVM_REG_GETP(arg2);
1743
1744         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1745                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1746         }
1747         r_carray_replace(a, index, arg1);
1748 }
1749
1750
1751 static void rvm_op_abort(rvmcpu_t *cpu, rvm_asmins_t *ins)
1752 {
1753         RVM_ABORT(cpu, RVM_CPUREG_GETU(cpu, ins->op1));
1754 }
1755
1756
1757 static rvm_cpu_op ops[] = {
1758         rvm_op_exit,            // RVM_EXT
1759         rvm_op_abort,           // RVM_ABORT
1760         rvm_op_prn,                     // RVM_PRN
1761         rvm_op_asr,                     // RVM_ASR
1762         rvm_op_swi,                     // RVM_SWI
1763         rvm_op_swiid,           // RVM_SWIID
1764         rvm_op_call,            // RVM_CALL
1765         rvm_op_mov,                     // RVM_MOV
1766         rvm_op_movs,            // RVM_MOVS
1767         rvm_op_swp,                     // RVM_SWP
1768         rvm_op_inc,                     // RVM_INC
1769         rvm_op_dec,                     // RVM_DEC
1770         rvm_op_add,                     // RVM_ADD
1771         rvm_op_adds,            // RVM_ADDS
1772         rvm_op_adc,                     // RVM_ADC
1773         rvm_op_and,                     // RVM_AND
1774         rvm_op_bic,                     // RVM_BIC
1775         rvm_op_clz,                     // RVM_CLZ
1776         rvm_op_cmn,                     // RVM_CMN
1777         rvm_op_xor,                     // RVM_XOR
1778         rvm_op_sub,                     // RVM_SUB
1779         rvm_op_subs,            // RVM_SUBS
1780         rvm_op_sbc,                     // RVM_SBC
1781         rvm_op_mul,                     // RVM_MUL
1782         rvm_op_mls,                     // RVM_MLS
1783         rvm_op_muls,            // RVM_MULS
1784         rvm_op_not,                     // RVM_NOT
1785         rvm_op_div,                     // RVM_DIV
1786         rvm_op_dvs,                     // RVM_DVS
1787         rvm_op_divs,            // RVM_DIVS
1788         rvm_op_mod,                     // RVM_MOD
1789         rvm_op_mods,            // RVM_MODS
1790         rvm_op_bx,                      // RVM_BX
1791         rvm_op_bxeq,            // RVM_BXEQ
1792         rvm_op_bxneq,           // RVM_BXNEQ
1793         rvm_op_bxleq,           // RVM_BXLEQ
1794         rvm_op_bxgeq,           // RVM_BXGEQ
1795         rvm_op_bxles,           // RVM_BXLES
1796         rvm_op_bxgre,           // RVM_BXGRE
1797         rvm_op_bxl,                     // RVM_BXL
1798         rvm_op_bl,                      // RVM_BL
1799         rvm_op_b,                       // RVM_B
1800         rvm_op_str,                     // RVM_STR
1801         rvm_op_strp,            // RVM_STRP
1802         rvm_op_strb,            // RVM_STRB
1803         rvm_op_strh,            // RVM_STRH
1804         rvm_op_strw,            // RVM_STRW
1805         rvm_op_strr,            // RVM_STRR
1806         rvm_op_ldr,                     // RVM_LDR
1807         rvm_op_ldrp,            // RVM_LDRP
1808         rvm_op_ldrb,            // RVM_LDRB
1809         rvm_op_ldrh,            // RVM_LDRH
1810         rvm_op_ldrw,            // RVM_LDRW
1811         rvm_op_ldrr,            // RVM_LDRR
1812         rvm_op_cflag,           // RVM_CFLAG
1813         rvm_op_clr,                     // RVM_CLR
1814         rvm_op_clrr,            // RVM_CLRR
1815         rvm_op_lsl,                     // RVM_LSL
1816         rvm_op_lsr,                     // RVM_LSR
1817         rvm_op_lsrs,            // RVM_LSRS
1818         rvm_op_stm,                     // RVM_STM
1819         rvm_op_ldm,                     // RVM_LDM
1820         rvm_op_sts,                     // RVM_STS
1821         rvm_op_lds,                     // RVM_LDS
1822         rvm_op_orr,                     // RVM_ORR
1823         rvm_op_push,            // RVM_PUSH
1824         rvm_op_pop,                     // RVM_POP
1825         rvm_op_cmp,                     // RVM_CMP
1826         rvm_op_nop,                     // RVM_NOP
1827         rvm_op_beq,                     // RVM_BEQ
1828         rvm_op_bneq,            // RVM_BNEQ
1829         rvm_op_bleq,            // RVM_BLEQ
1830         rvm_op_bgeq,            // RVM_BGEQ
1831         rvm_op_bles,            // RVM_BLES
1832         rvm_op_bgre,            // RVM_BGRE
1833         rvm_op_ret,                     // RVM_RET
1834         rvm_op_ror,                     // RVM_ROR
1835         rvm_op_pushm,           // RVM_PUSHM
1836         rvm_op_popm,            // RVM_POPM
1837         rvm_op_tst,             // RVM_TST
1838         rvm_op_teq,             // RVM_TEQ
1839         rvm_op_addrs,           // RVM_ADDRS
1840
1841 /* Extended VM instructions */
1842         rvm_op_cast,            // RVM_CAST
1843         rvm_op_type,            // RVM_TYPE
1844         rvm_op_settype,         // RVM_SETTYPE
1845         rvm_op_emov,            // RVM_EMOV
1846         rvm_op_eneg,            // RVM_ENEG
1847         rvm_op_eadd,            // RVM_EADD
1848         rvm_op_esub,            // RVM_ESUB
1849         rvm_op_emul,            // RVM_EMUL
1850         rvm_op_ediv,            // RVM_EDIV
1851         rvm_op_emod,            // RVM_MOD
1852         rvm_op_elsl,            // RVM_ELSL
1853         rvm_op_elsr,            // RVM_ELSR
1854         rvm_op_elsru,           // RVM_ELSRU
1855         rvm_op_eand,            // RVM_EAND
1856         rvm_op_eorr,            // RVM_EORR
1857         rvm_op_exor,            // RVM_EXOR
1858         rvm_op_enot,            // RVM_ENOT
1859
1860         rvm_op_eland,           // RVM_ELAND
1861         rvm_op_elor,            // RVM_ELOR
1862         rvm_op_elnot,           // RVM_ELNOT
1863         rvm_op_eeq,                     // RVM_EEQ
1864         rvm_op_enoteq,          // RVM_ENOTEQ
1865         rvm_op_egreat,          // RVM_EGREAT
1866         rvm_op_egreateq,        // RVM_EGREATEQ
1867         rvm_op_eless,           // RVM_ELESS
1868         rvm_op_elesseq,         // RVM_ELESSEQ
1869         rvm_op_ecmp,            // RVM_ECMP
1870         rvm_op_ecmn,            // RVM_ECMN
1871         rvm_op_allocstr,        // RVM_ALLOCSTR
1872         rvm_op_allocarr,        // RVM_ALLOCARR
1873         rvm_op_addra,           // RVM_ADDRA
1874         rvm_op_lda,                     // RVM_LDA
1875         rvm_op_sta,                     // RVM_STA
1876         rvm_op_mapalloc,        // RVM_MAPALLOC
1877         rvm_op_mapaddr,         // RVM_MAPADDR,
1878         rvm_op_mapldr,          // RVM_MAPLDR,
1879         rvm_op_mapstr,          // RVM_MAPSTR,
1880         rvm_op_maplookup,       // RVM_MAPLKUP,
1881         rvm_op_mapadd,          // RVM_MAPADD,
1882         rvm_op_maplookupadd,// RVM_MAPLKUPADD,
1883         (void*) 0,
1884         (void*) 0,
1885         (void*) 0,
1886         (void*) 0,
1887         (void*) 0,
1888         (void*) 0,
1889         (void*) 0,
1890         (void*) 0,
1891         
1892 };
1893
1894
1895 rvmcpu_t *rvm_cpu_create(unsigned long stacksize)
1896 {
1897         rvmcpu_t *cpu;
1898
1899         cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
1900         if (!cpu)
1901                 return ((void*)0);
1902         r_memset(cpu, 0, sizeof(*cpu));
1903         cpu->stacksize = stacksize;
1904         cpu->switables = r_harray_create(sizeof(rvm_switable_t*));
1905         cpu->stack = r_malloc(stacksize * sizeof(rvmreg_t));
1906         cpu->data = r_carray_create(sizeof(rvmreg_t));
1907         cpu->opmap = rvm_opmap_create();
1908         cpu->gc = r_gc_create();
1909         rvm_op_binary_init(cpu->opmap);
1910         rvm_op_cast_init(cpu->opmap);
1911         rvm_op_not_init(cpu->opmap);
1912         rvm_op_logicnot_init(cpu->opmap);
1913
1914         return cpu;
1915 }
1916
1917
1918 rvmcpu_t *rvm_cpu_create_default()
1919 {
1920         return rvm_cpu_create(RVM_DEFAULT_STACKSIZE);
1921 }
1922
1923
1924 void rvm_cpu_destroy(rvmcpu_t *cpu)
1925 {
1926         r_gc_deallocateall(cpu->gc);
1927         r_gc_destroy(cpu->gc);
1928         r_object_destroy((robject_t*)cpu->switables);
1929         r_free(cpu->stack);
1930         r_object_destroy((robject_t*)cpu->data);
1931         rvm_opmap_destroy(cpu->opmap);
1932         r_free(cpu);
1933 }
1934
1935
1936 int rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1937 {
1938         rvm_asmins_t *pi;
1939         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1940         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1941
1942         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1943         cpu->abort = 0;
1944         cpu->error = 0;
1945         do {
1946                 pi = RVM_REG_GETIP(regpc);
1947                 if (pi->da) {
1948                         *regda = pi->data;
1949                 }
1950 #if RVM_CONDITIONAL_INSTRUCTIONS
1951                 if (pi->cond) {
1952                         switch (pi->cond) {
1953                         case RVM_CEXEC_GRE:
1954                                 if (!((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0))
1955                                         goto skipexec;
1956                                 break;
1957                         case RVM_CEXEC_GEQ:
1958                                 if (!((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1))
1959                                         goto skipexec;
1960                                 break;
1961                         case RVM_CEXEC_EQ:
1962                                 if (!((cpu->status & RVM_STATUS_Z)))
1963                                         goto skipexec;
1964                                 break;
1965                         case RVM_CEXEC_NEQ:
1966                                 if (!((cpu->status & RVM_STATUS_Z) == 0))
1967                                         goto skipexec;
1968                                 break;
1969                         case RVM_CEXEC_LEQ:
1970                                 if (!((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)))
1971                                         goto skipexec;
1972                                 break;
1973                         case RVM_CEXEC_LES:
1974                                 if (!((cpu->status & RVM_STATUS_N)))
1975                                         goto skipexec;
1976                                 break;
1977                         default:
1978                                 goto skipexec;
1979                         };
1980                 }
1981 #endif
1982                 ops[pi->opcode](cpu, pi);
1983 #if RVM_CONDITIONAL_INSTRUCTIONS
1984 skipexec:
1985 #endif
1986                 RVM_REG_INCIP(regpc, 1);
1987         } while (!cpu->abort);
1988         if (cpu->error)
1989                 return -1;
1990         return 0;
1991 }
1992
1993
1994 int rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1995 {
1996         long line = 0;
1997         rvm_asmins_t *pi;
1998         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1999         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
2000
2001         RVM_CPUREG_SETIP(cpu, PC, prog + off);
2002         cpu->abort = 0;
2003         cpu->error = 0;
2004         do {
2005                 pi = RVM_REG_GETIP(regpc);
2006                 if (pi->da) {
2007                         *regda = pi->data;
2008                 }
2009 #if RVM_CONDITIONAL_INSTRUCTIONS
2010                 if (pi->cond) {
2011                         switch (pi->cond) {
2012                         case RVM_CEXEC_GRE:
2013                                 if (!((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0))
2014                                         goto skipexec;
2015                                 break;
2016                         case RVM_CEXEC_GEQ:
2017                                 if (!((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1))
2018                                         goto skipexec;
2019                                 break;
2020                         case RVM_CEXEC_EQ:
2021                                 if (!((cpu->status & RVM_STATUS_Z)))
2022                                         goto skipexec;
2023                                 break;
2024                         case RVM_CEXEC_NEQ:
2025                                 if (!((cpu->status & RVM_STATUS_Z) == 0))
2026                                         goto skipexec;
2027                                 break;
2028                         case RVM_CEXEC_LEQ:
2029                                 if (!((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)))
2030                                         goto skipexec;
2031                                 break;
2032                         case RVM_CEXEC_LES:
2033                                 if (!((cpu->status & RVM_STATUS_N)))
2034                                         goto skipexec;
2035                                 break;
2036                         default:
2037                                 goto skipexec;
2038                         };
2039                 }
2040 #endif
2041                 ops[pi->opcode](cpu, pi);
2042                 r_printf("%7ld :", ++line);
2043                 rvm_cpu_dumpregs(cpu, pi);
2044 #if RVM_CONDITIONAL_INSTRUCTIONS
2045 skipexec:
2046 #endif
2047                 RVM_REG_INCIP(regpc, 1);
2048         } while (!cpu->abort);
2049         if (cpu->error)
2050                 return -1;
2051         return 0;
2052 }
2053
2054
2055 int rvm_cpu_global_swilookup(rvmcpu_t *cpu, const char *swiname, rsize_t size)
2056 {
2057         int nswi;
2058         rvm_switable_t *swientry;
2059         long ntable;
2060
2061         for (ntable = 0; ntable < r_harray_length(cpu->switables); ntable++) {
2062                 swientry = r_harray_index(cpu->switables, ntable, rvm_switable_t*);
2063                 if (!swientry)
2064                         return -1;
2065                 for (nswi = 0; swientry[nswi].name; nswi++) {
2066                         if (r_strncmp(swientry[nswi].name, swiname, size) == 0 && r_strlen(swientry[nswi].name) == size)
2067                                 return (int)RVM_SWI_ID(ntable, nswi);
2068                 }
2069         }
2070         return -1;
2071 }
2072
2073
2074 int rvm_cpu_table_swilookup(rvmcpu_t *cpu, const char *tabname, const char *swiname, rsize_t size)
2075 {
2076         int nswi;
2077         rvm_switable_t *swientry;
2078         long ntable = r_harray_lookup_s(cpu->switables, tabname);
2079
2080         if (ntable < 0)
2081                 return -1;
2082         swientry = r_harray_index(cpu->switables, ntable, rvm_switable_t*);
2083         if (!swientry)
2084                 return -1;
2085         for (nswi = 0; swientry[nswi].name; nswi++) {
2086                 if (r_strncmp(swientry[nswi].name, swiname, size) == 0 && r_strlen(swientry[nswi].name) == size)
2087                         return (int)RVM_SWI_ID(ntable, nswi);
2088         }
2089         return -1;
2090 }
2091
2092
2093 int rvm_cpu_swilookup(rvmcpu_t *cpu, const char *tabname, const char *swiname, rsize_t size)
2094 {
2095         return tabname ? rvm_cpu_table_swilookup(cpu, tabname, swiname, size) : rvm_cpu_global_swilookup(cpu, swiname, size);
2096 }
2097
2098
2099 int rvm_cpu_swilookup_s(rvmcpu_t *cpu, const char *tabname, const char *swiname)
2100 {
2101         return rvm_cpu_swilookup(cpu, tabname, swiname, r_strlen(swiname));
2102 }
2103
2104
2105 int rvm_cpu_addswitable(rvmcpu_t *cpu, const char *tabname, rvm_switable_t *switable)
2106 {
2107         return r_harray_replace_s(cpu->switables, tabname, &switable);
2108 }
2109
2110
2111 int rvm_cpu_abort(rvmcpu_t *cpu)
2112 {
2113         if (!cpu)
2114                 return -1;
2115         cpu->error = RVM_E_USERABORT;
2116         cpu->abort = 1;
2117         return 0;
2118 }
2119
2120
2121 rvm_asmins_t rvm_cond_asma(rword cond, rword opcode, rword op1, rword op2, rword op3, char *data, unsigned long size)
2122 {
2123         rvm_asmins_t a;
2124
2125         r_memset(&a, 0, sizeof(a));
2126         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2127         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2128         a.op1 = (ruint8)op1;
2129         a.op2 = (ruint8)op2;
2130         a.op3 = (ruint8)op3;
2131         a.cond = cond;
2132         rvm_reg_setstrptr(&a.data, data, size);
2133         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2134                 a.da = 1;
2135         return a;
2136 }
2137
2138
2139 rvm_asmins_t rvm_asma(rword opcode, rword op1, rword op2, rword op3, char *data, unsigned long size)
2140 {
2141         return rvm_cond_asma(0, opcode, op1, op2, op3, data, size);
2142 }
2143
2144
2145 rvm_asmins_t rvm_cond_asmp(rword cond, rword opcode, rword op1, rword op2, rword op3, rpointer data)
2146 {
2147         rvm_asmins_t a;
2148
2149         r_memset(&a, 0, sizeof(a));
2150         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2151         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2152         a.op1 = (ruint8)op1;
2153         a.op2 = (ruint8)op2;
2154         a.op3 = (ruint8)op3;
2155         a.cond = cond;
2156         rvm_reg_setpointer(&a.data, data);
2157         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2158                 a.da = 1;
2159         return a;
2160 }
2161
2162
2163 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
2164 {
2165         return rvm_cond_asmp(0, opcode, op1, op2, op3, data);
2166 }
2167
2168
2169 rvm_asmins_t rvm_cond_asms(rword cond, rword opcode, rword op1, rword op2, rword op3, rword data)
2170 {
2171         rvm_asmins_t a;
2172
2173         r_memset(&a, 0, sizeof(a));
2174         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2175         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2176         a.op1 = (ruint8)op1;
2177         a.op2 = (ruint8)op2;
2178         a.op3 = (ruint8)op3;
2179         a.cond = cond;
2180         rvm_reg_setunsigned(&a.data, data);
2181         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_SWIID)
2182         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2183                 a.da = 1;
2184         return a;
2185 }
2186
2187
2188 rvm_asmins_t rvm_asms(rword opcode, rword op1, rword op2, rword op3, rword data)
2189 {
2190         return rvm_cond_asms(0, opcode, op1, op2, op3, data);
2191 }
2192
2193
2194 rvm_asmins_t rvm_cond_asmf(rword cond, rword opcode, rword op1, rword op2, rword op3, rword data)
2195 {
2196         rvm_asmins_t a;
2197
2198         r_memset(&a, 0, sizeof(a));
2199         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2200         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2201         a.op1 = (ruint8)op1;
2202         a.op2 = (ruint8)op2;
2203         a.op3 = (ruint8)op3;
2204         a.cond = cond;
2205         rvm_reg_setunsigned(&a.data, data);
2206         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_FUNCTION)
2207         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2208                 a.da = 1;
2209         return a;
2210 }
2211
2212 rvm_asmins_t rvm_asmf(rword opcode, rword op1, rword op2, rword op3, rword data)
2213 {
2214         return rvm_cond_asmf(0, opcode, op1, op2, op3, data);
2215 }
2216
2217
2218 rvm_asmins_t rvm_cond_asm(rword cond, rword opcode, rword op1, rword op2, rword op3, rword data)
2219 {
2220         rvm_asmins_t a;
2221
2222         r_memset(&a, 0, sizeof(a));
2223         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2224         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2225         a.op1 = (ruint8)op1;
2226         a.op2 = (ruint8)op2;
2227         a.op3 = (ruint8)op3;
2228         a.cond = cond;
2229         rvm_reg_setunsigned(&a.data, data);
2230         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2231                 a.da = 1;
2232         return a;
2233 }
2234
2235
2236 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
2237 {
2238         return rvm_cond_asm(0, opcode, op1, op2, op3, data);
2239 }
2240
2241
2242
2243 rvm_asmins_t rvm_cond_asml(rword cond, rword opcode, rword op1, rword op2, rword op3, long data)
2244 {
2245         rvm_asmins_t a;
2246
2247         r_memset(&a, 0, sizeof(a));
2248         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2249         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2250         a.op1 = (ruint8)op1;
2251         a.op2 = (ruint8)op2;
2252         a.op3 = (ruint8)op3;
2253         a.cond = cond;
2254         rvm_reg_setlong(&a.data, data);
2255         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2256                 a.da = 1;
2257         return a;
2258 }
2259
2260
2261 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, long data)
2262 {
2263         return rvm_cond_asml(0, opcode, op1, op2, op3, data);
2264 }
2265
2266
2267 rvm_asmins_t rvm_cond_asmb(rword cond, rword opcode, rword op1, rword op2, rword op3, unsigned int data)
2268 {
2269         rvm_asmins_t a;
2270
2271         r_memset(&a, 0, sizeof(a));
2272         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2273         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2274         a.op1 = (ruint8)op1;
2275         a.op2 = (ruint8)op2;
2276         a.op3 = (ruint8)op3;
2277         a.cond = cond;
2278         rvm_reg_setboolean(&a.data, data);
2279         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2280                 a.da = 1;
2281         return a;
2282 }
2283
2284
2285 rvm_asmins_t rvm_asmb(rword opcode, rword op1, rword op2, rword op3, unsigned int data)
2286 {
2287         return rvm_cond_asmb(0, opcode, op1, op2, op3, data);
2288 }
2289
2290
2291 rvm_asmins_t rvm_cond_asmd(rword cond, rword opcode, rword op1, rword op2, rword op3, double data)
2292 {
2293         rvm_asmins_t a;
2294
2295         r_memset(&a, 0, sizeof(a));
2296         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2297         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2298         a.op1 = (ruint8)op1;
2299         a.op2 = (ruint8)op2;
2300         a.op3 = (ruint8)op3;
2301         a.cond = cond;
2302         rvm_reg_setdouble(&a.data, data);
2303         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2304                 a.da = 1;
2305         return a;
2306 }
2307
2308 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, double data)
2309 {
2310         return rvm_cond_asmd(0, opcode, op1, op2, op3, data);
2311 }
2312
2313
2314 rvm_asmins_t rvm_cond_asm2(rword cond, rword opcode, rword op1, rword op2, rword op3, ruint32 p1, ruint32 p2)
2315 {
2316         rvm_asmins_t a;
2317
2318         r_memset(&a, 0, sizeof(a));
2319         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2320         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2321         a.op1 = (ruint8)op1;
2322         a.op2 = (ruint8)op2;
2323         a.op3 = (ruint8)op3;
2324         a.cond = cond;
2325         rvm_reg_setpair(&a.data, p1, p2);
2326         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2327                 a.da = 1;
2328         return a;
2329 }
2330
2331
2332 rvm_asmins_t rvm_asm2(rword opcode, rword op1, rword op2, rword op3, ruint32 p1, ruint32 p2)
2333 {
2334         return rvm_cond_asm2(0, opcode, op1, op2, op3, p1, p2);
2335 }
2336
2337 rvmreg_t *rvm_cpu_alloc_global(rvmcpu_t *cpu)
2338 {
2339         rvmreg_t *global;
2340         int index = r_carray_add(cpu->data, NULL);
2341
2342         global = (rvmreg_t*)r_carray_slot(cpu->data, index);
2343         RVM_REG_CLEAR(global);
2344         RVM_REG_SETTYPE(global, RVM_DTYPE_UNDEF);
2345         return global;
2346 }
2347
2348
2349 int rvm_cpu_setreg(rvmcpu_t *cpu, rword regnum, const rvmreg_t *src)
2350 {
2351         if (regnum >= RLST)
2352                 return -1;
2353         RVM_CPUREG_SET(cpu, regnum, *src);
2354         return 0;
2355 }
2356
2357
2358 rvmreg_t *rvm_cpu_getreg(rvmcpu_t *cpu, rword regnum)
2359 {
2360         if (regnum >= RLST)
2361                 return NULL;
2362         return RVM_CPUREG_PTR(cpu, regnum);
2363 }