RPA Toolkit
6964659e6bc432ac0f2418bf3121bcd7dc8cbe24
[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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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, *((ruword*)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         ruword 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         *((ruword*)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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
578
579         res = ((rword)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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         rword res;
797         rword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
798
799         res = (rword)(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         ruword 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         ruword 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         rword 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         rword res;
871         rword 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 = (rword)(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         ruword 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         ruword 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         ruword 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         ruword n, i = 0;
915         ruword bits = RVM_CPUREG_GETU(cpu, ins->op1);
916         ruword 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 = ((ruword)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         ruword bits = RVM_CPUREG_GETU(cpu, ins->op1);
939         ruword savedbits = bits;
940         ruword 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 (!(((ruword)(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         ruword 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         ruword 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         ruword *dst = (ruword*) RVM_CPUREG_GETU(cpu, ins->op1);
984         ruword bits = RVM_CPUREG_GETU(cpu, ins->op2);
985         
986         for (n = 0; bits && n < RLST; n++) {
987                 if (((ruword)(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         ruword *src = (ruword*)RVM_CPUREG_GETU(cpu, ins->op1);
1000         ruword bits = RVM_CPUREG_GETU(cpu, ins->op2);
1001
1002         for (n = 0; bits && n < RLST; n++) {
1003                 if (((ruword)(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         ruword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
1016         ruword res = (ruword)(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         ruword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
1029         ruword res = (ruword)(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 int 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_SINGED)
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_SINGED) {
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         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1505         rstring_t *s = r_string_create_strsize((const char*)RVM_CPUREG_GETP(cpu, ins->op2), (unsigned long)RVM_CPUREG_GETU(cpu, ins->op3));
1506         if (!s) {
1507                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1508         }
1509         r_gc_add(cpu->gc, (robject_t*)s);
1510         rvm_reg_setstring(arg1, s);
1511 }
1512
1513
1514 static void rvm_op_mapalloc(rvmcpu_t *cpu, rvm_asmins_t *ins)
1515 {
1516         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1517         rmap_t *a = r_map_create(sizeof(rvmreg_t), 7);
1518         if (!a) {
1519                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1520         }
1521         r_gc_add(cpu->gc, (robject_t*)a);
1522         rvm_reg_setjsobject(arg1, (robject_t*)a);
1523 }
1524
1525
1526 static void rvm_op_allocarr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1527 {
1528         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1529         ruword size = RVM_CPUREG_GETU(cpu, ins->op2);
1530         rcarray_t *a = r_carray_create_rvmreg();
1531         if (!a) {
1532                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1533         }
1534         r_carray_setlength(a, (unsigned long)size);
1535         r_gc_add(cpu->gc, (robject_t*)a);
1536         rvm_reg_setarray(arg1, (robject_t*)a);
1537 }
1538
1539
1540 static void rvm_op_maplookup(rvmcpu_t *cpu, rvm_asmins_t *ins)
1541 {
1542         long index;
1543         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1544         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1545         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1546         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
1547
1548         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
1549                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1550         }
1551         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SINGED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
1552                 index = r_map_lookup_l(a, -1, (long)RVM_REG_GETL(arg3));
1553         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
1554                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
1555         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
1556                 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);
1557         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
1558                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
1559         } else {
1560                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1561         }
1562
1563         RVM_REG_CLEAR(arg1);
1564         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SINGED);
1565         RVM_REG_SETL(arg1, index);
1566 }
1567
1568
1569 static void rvm_op_mapadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1570 {
1571         long index;
1572         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1573         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1574         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1575         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
1576
1577         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
1578                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1579         }
1580         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SINGED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
1581                 index = r_map_gckey_add_l(a, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
1582         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
1583                 index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
1584         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
1585                 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);
1586         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
1587                 index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
1588         } else {
1589                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1590         }
1591
1592         RVM_REG_CLEAR(arg1);
1593         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SINGED);
1594         RVM_REG_SETL(arg1, index);
1595 }
1596
1597
1598 static void rvm_op_maplookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1599 {
1600         long index;
1601         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1602         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1603         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1604         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
1605
1606         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
1607                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1608         }
1609         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SINGED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
1610                 index = r_map_lookup_l(a, -1, (long)RVM_REG_GETL(arg3));
1611                 if (index < 0)
1612                         index = r_map_gckey_add_l(a, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
1613         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
1614                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
1615                 if (index < 0)
1616                         index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
1617         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
1618                 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);
1619                 if (index < 0)
1620                         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);
1621         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
1622                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
1623                 if (index < 0)
1624                         index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
1625         } else {
1626                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1627         }
1628         RVM_REG_CLEAR(arg1);
1629         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SINGED);
1630         RVM_REG_SETL(arg1, index);
1631 }
1632
1633
1634 static void rvm_op_mapaddr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1635 {
1636         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1637         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1638         rvmreg_t tmp = rvm_reg_create_signed(0);
1639         rmap_t *a;
1640         rpointer value;
1641         long index;
1642
1643         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1644         index = (long)RVM_REG_GETL(&tmp);
1645         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1646                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1647         a = (rmap_t*)RVM_REG_GETP(arg2);
1648         value = r_map_value(a, index);
1649         if (!value)
1650                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1651         RVM_REG_CLEAR(arg1);
1652         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
1653         RVM_REG_SETP(arg1, value);
1654 }
1655
1656
1657 static void rvm_op_mapldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1658 {
1659         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1660         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1661         rvmreg_t tmp = rvm_reg_create_signed(0);
1662         rmap_t *a = NULL;
1663         rpointer value;
1664         long index;
1665
1666         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1667         index = (long)RVM_REG_GETL(&tmp);
1668         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1669                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1670         a = (rmap_t*)RVM_REG_GETP(arg2);
1671         value = r_map_value(a, index);
1672         if (!value) {
1673                 RVM_REG_CLEAR(arg1);
1674                 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
1675         } else {
1676                 *arg1 = *((rvmreg_t*)value);
1677         }
1678 }
1679
1680
1681 static void rvm_op_mapstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1682 {
1683         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1684         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1685         rvmreg_t tmp = rvm_reg_create_signed(0);
1686         rmap_t *a = NULL;
1687         rpointer value;
1688         long index;
1689
1690         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1691         index = (long)RVM_REG_GETL(&tmp);
1692         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1693                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1694         a = (rmap_t*)RVM_REG_GETP(arg2);
1695         value = r_map_value(a, index);
1696         if (!value)
1697                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1698         r_map_setvalue(a, index, arg1);
1699 }
1700
1701
1702 static void rvm_op_addra(rvmcpu_t *cpu, rvm_asmins_t *ins)
1703 {
1704         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1705         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1706         rvmreg_t tmp = rvm_reg_create_signed(0);
1707         rcarray_t *a = RVM_REG_GETP(arg2);
1708         long index;
1709
1710         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1711         index = (long)RVM_REG_GETL(&tmp);
1712
1713         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY || index < 0) {
1714                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1715         }
1716         RVM_REG_CLEAR(arg1);
1717         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
1718         RVM_REG_SETP(arg1, r_carray_slot_expand(a, index));
1719 }
1720
1721
1722 static void rvm_op_lda(rvmcpu_t *cpu, rvm_asmins_t *ins)
1723 {
1724         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1725         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1726         ruword index = RVM_CPUREG_GETU(cpu, ins->op3);
1727         rcarray_t *a = RVM_REG_GETP(arg2);
1728
1729         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1730                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1731         }
1732         *arg1 = *((rvmreg_t*)r_carray_slot_expand(a, (unsigned long)index));
1733 }
1734
1735
1736 static void rvm_op_sta(rvmcpu_t *cpu, rvm_asmins_t *ins)
1737 {
1738         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1739         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1740         ruword index = RVM_CPUREG_GETU(cpu, ins->op3);
1741         rcarray_t *a = RVM_REG_GETP(arg2);
1742
1743         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1744                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1745         }
1746         r_carray_replace(a, (unsigned long)index, arg1);
1747 }
1748
1749
1750 static void rvm_op_abort(rvmcpu_t *cpu, rvm_asmins_t *ins)
1751 {
1752         RVM_ABORT(cpu, RVM_CPUREG_GETU(cpu, ins->op1));
1753 }
1754
1755
1756 static rvm_cpu_op ops[] = {
1757         rvm_op_exit,            // RVM_EXT
1758         rvm_op_abort,           // RVM_ABORT
1759         rvm_op_prn,                     // RVM_PRN
1760         rvm_op_asr,                     // RVM_ASR
1761         rvm_op_swi,                     // RVM_SWI
1762         rvm_op_swiid,           // RVM_SWIID
1763         rvm_op_call,            // RVM_CALL
1764         rvm_op_mov,                     // RVM_MOV
1765         rvm_op_movs,            // RVM_MOVS
1766         rvm_op_swp,                     // RVM_SWP
1767         rvm_op_inc,                     // RVM_INC
1768         rvm_op_dec,                     // RVM_DEC
1769         rvm_op_add,                     // RVM_ADD
1770         rvm_op_adds,            // RVM_ADDS
1771         rvm_op_adc,                     // RVM_ADC
1772         rvm_op_and,                     // RVM_AND
1773         rvm_op_bic,                     // RVM_BIC
1774         rvm_op_clz,                     // RVM_CLZ
1775         rvm_op_cmn,                     // RVM_CMN
1776         rvm_op_xor,                     // RVM_XOR
1777         rvm_op_sub,                     // RVM_SUB
1778         rvm_op_subs,            // RVM_SUBS
1779         rvm_op_sbc,                     // RVM_SBC
1780         rvm_op_mul,                     // RVM_MUL
1781         rvm_op_mls,                     // RVM_MLS
1782         rvm_op_muls,            // RVM_MULS
1783         rvm_op_not,                     // RVM_NOT
1784         rvm_op_div,                     // RVM_DIV
1785         rvm_op_dvs,                     // RVM_DVS
1786         rvm_op_divs,            // RVM_DIVS
1787         rvm_op_mod,                     // RVM_MOD
1788         rvm_op_mods,            // RVM_MODS
1789         rvm_op_bx,                      // RVM_BX
1790         rvm_op_bxeq,            // RVM_BXEQ
1791         rvm_op_bxneq,           // RVM_BXNEQ
1792         rvm_op_bxleq,           // RVM_BXLEQ
1793         rvm_op_bxgeq,           // RVM_BXGEQ
1794         rvm_op_bxles,           // RVM_BXLES
1795         rvm_op_bxgre,           // RVM_BXGRE
1796         rvm_op_bxl,                     // RVM_BXL
1797         rvm_op_bl,                      // RVM_BL
1798         rvm_op_b,                       // RVM_B
1799         rvm_op_str,                     // RVM_STR
1800         rvm_op_strp,            // RVM_STRP
1801         rvm_op_strb,            // RVM_STRB
1802         rvm_op_strh,            // RVM_STRH
1803         rvm_op_strw,            // RVM_STRW
1804         rvm_op_strr,            // RVM_STRR
1805         rvm_op_ldr,                     // RVM_LDR
1806         rvm_op_ldrp,            // RVM_LDRP
1807         rvm_op_ldrb,            // RVM_LDRB
1808         rvm_op_ldrh,            // RVM_LDRH
1809         rvm_op_ldrw,            // RVM_LDRW
1810         rvm_op_ldrr,            // RVM_LDRR
1811         rvm_op_cflag,           // RVM_CFLAG
1812         rvm_op_clr,                     // RVM_CLR
1813         rvm_op_clrr,            // RVM_CLRR
1814         rvm_op_lsl,                     // RVM_LSL
1815         rvm_op_lsr,                     // RVM_LSR
1816         rvm_op_lsrs,            // RVM_LSRS
1817         rvm_op_stm,                     // RVM_STM
1818         rvm_op_ldm,                     // RVM_LDM
1819         rvm_op_sts,                     // RVM_STS
1820         rvm_op_lds,                     // RVM_LDS
1821         rvm_op_orr,                     // RVM_ORR
1822         rvm_op_push,            // RVM_PUSH
1823         rvm_op_pop,                     // RVM_POP
1824         rvm_op_cmp,                     // RVM_CMP
1825         rvm_op_nop,                     // RVM_NOP
1826         rvm_op_beq,                     // RVM_BEQ
1827         rvm_op_bneq,            // RVM_BNEQ
1828         rvm_op_bleq,            // RVM_BLEQ
1829         rvm_op_bgeq,            // RVM_BGEQ
1830         rvm_op_bles,            // RVM_BLES
1831         rvm_op_bgre,            // RVM_BGRE
1832         rvm_op_ret,                     // RVM_RET
1833         rvm_op_ror,                     // RVM_ROR
1834         rvm_op_pushm,           // RVM_PUSHM
1835         rvm_op_popm,            // RVM_POPM
1836         rvm_op_tst,             // RVM_TST
1837         rvm_op_teq,             // RVM_TEQ
1838         rvm_op_addrs,           // RVM_ADDRS
1839
1840 /* Extended VM instructions */
1841         rvm_op_cast,            // RVM_CAST
1842         rvm_op_type,            // RVM_TYPE
1843         rvm_op_settype,         // RVM_SETTYPE
1844         rvm_op_emov,            // RVM_EMOV
1845         rvm_op_eneg,            // RVM_ENEG
1846         rvm_op_eadd,            // RVM_EADD
1847         rvm_op_esub,            // RVM_ESUB
1848         rvm_op_emul,            // RVM_EMUL
1849         rvm_op_ediv,            // RVM_EDIV
1850         rvm_op_emod,            // RVM_MOD
1851         rvm_op_elsl,            // RVM_ELSL
1852         rvm_op_elsr,            // RVM_ELSR
1853         rvm_op_elsru,           // RVM_ELSRU
1854         rvm_op_eand,            // RVM_EAND
1855         rvm_op_eorr,            // RVM_EORR
1856         rvm_op_exor,            // RVM_EXOR
1857         rvm_op_enot,            // RVM_ENOT
1858
1859         rvm_op_eland,           // RVM_ELAND
1860         rvm_op_elor,            // RVM_ELOR
1861         rvm_op_elnot,           // RVM_ELNOT
1862         rvm_op_eeq,                     // RVM_EEQ
1863         rvm_op_enoteq,          // RVM_ENOTEQ
1864         rvm_op_egreat,          // RVM_EGREAT
1865         rvm_op_egreateq,        // RVM_EGREATEQ
1866         rvm_op_eless,           // RVM_ELESS
1867         rvm_op_elesseq,         // RVM_ELESSEQ
1868         rvm_op_ecmp,            // RVM_ECMP
1869         rvm_op_ecmn,            // RVM_ECMN
1870         rvm_op_allocstr,        // RVM_ALLOCSTR
1871         rvm_op_allocarr,        // RVM_ALLOCARR
1872         rvm_op_addra,           // RVM_ADDRA
1873         rvm_op_lda,                     // RVM_LDA
1874         rvm_op_sta,                     // RVM_STA
1875         rvm_op_mapalloc,        // RVM_MAPALLOC
1876         rvm_op_mapaddr,         // RVM_MAPADDR,
1877         rvm_op_mapldr,          // RVM_MAPLDR,
1878         rvm_op_mapstr,          // RVM_MAPSTR,
1879         rvm_op_maplookup,       // RVM_MAPLKUP,
1880         rvm_op_mapadd,          // RVM_MAPADD,
1881         rvm_op_maplookupadd,// RVM_MAPLKUPADD,
1882         (void*) 0,
1883         (void*) 0,
1884         (void*) 0,
1885         (void*) 0,
1886         (void*) 0,
1887         (void*) 0,
1888         (void*) 0,
1889         (void*) 0,
1890         
1891 };
1892
1893
1894 rvmcpu_t *rvm_cpu_create(unsigned long stacksize)
1895 {
1896         rvmcpu_t *cpu;
1897
1898         cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
1899         if (!cpu)
1900                 return ((void*)0);
1901         r_memset(cpu, 0, sizeof(*cpu));
1902         cpu->stacksize = stacksize;
1903         cpu->switables = r_harray_create(sizeof(rvm_switable_t*));
1904         cpu->stack = r_malloc(stacksize * sizeof(rvmreg_t));
1905         cpu->data = r_carray_create(sizeof(rvmreg_t));
1906         cpu->opmap = rvm_opmap_create();
1907         cpu->gc = r_gc_create();
1908         rvm_op_binary_init(cpu->opmap);
1909         rvm_op_cast_init(cpu->opmap);
1910         rvm_op_not_init(cpu->opmap);
1911         rvm_op_logicnot_init(cpu->opmap);
1912
1913         return cpu;
1914 }
1915
1916
1917 rvmcpu_t *rvm_cpu_create_default()
1918 {
1919         return rvm_cpu_create(RVM_DEFAULT_STACKSIZE);
1920 }
1921
1922
1923 void rvm_cpu_destroy(rvmcpu_t *cpu)
1924 {
1925         r_gc_deallocateall(cpu->gc);
1926         r_gc_destroy(cpu->gc);
1927         r_object_destroy((robject_t*)cpu->switables);
1928         r_free(cpu->stack);
1929         r_object_destroy((robject_t*)cpu->data);
1930         rvm_opmap_destroy(cpu->opmap);
1931         r_free(cpu);
1932 }
1933
1934
1935 int rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off)
1936 {
1937         rvm_asmins_t *pi;
1938         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1939         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1940
1941         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1942         cpu->abort = 0;
1943         cpu->error = 0;
1944         do {
1945                 pi = RVM_REG_GETIP(regpc);
1946                 if (pi->da) {
1947                         *regda = pi->data;
1948                 }
1949 #if RVM_CONDITIONAL_INSTRUCTIONS
1950                 if (pi->cond) {
1951                         switch (pi->cond) {
1952                         case RVM_CEXEC_GRE:
1953                                 if (!((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0))
1954                                         goto skipexec;
1955                                 break;
1956                         case RVM_CEXEC_GEQ:
1957                                 if (!((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1))
1958                                         goto skipexec;
1959                                 break;
1960                         case RVM_CEXEC_EQ:
1961                                 if (!((cpu->status & RVM_STATUS_Z)))
1962                                         goto skipexec;
1963                                 break;
1964                         case RVM_CEXEC_NEQ:
1965                                 if (!((cpu->status & RVM_STATUS_Z) == 0))
1966                                         goto skipexec;
1967                                 break;
1968                         case RVM_CEXEC_LEQ:
1969                                 if (!((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)))
1970                                         goto skipexec;
1971                                 break;
1972                         case RVM_CEXEC_LES:
1973                                 if (!((cpu->status & RVM_STATUS_N)))
1974                                         goto skipexec;
1975                                 break;
1976                         default:
1977                                 goto skipexec;
1978                         };
1979                 }
1980 #endif
1981                 ops[pi->opcode](cpu, pi);
1982 #if RVM_CONDITIONAL_INSTRUCTIONS
1983 skipexec:
1984 #endif
1985                 RVM_REG_INCIP(regpc, 1);
1986         } while (!cpu->abort);
1987         if (cpu->error)
1988                 return -1;
1989         return 0;
1990 }
1991
1992
1993 int rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off)
1994 {
1995         long line = 0;
1996         rvm_asmins_t *pi;
1997         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1998         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1999
2000         RVM_CPUREG_SETIP(cpu, PC, prog + off);
2001         cpu->abort = 0;
2002         cpu->error = 0;
2003         do {
2004                 pi = RVM_REG_GETIP(regpc);
2005                 if (pi->da) {
2006                         *regda = pi->data;
2007                 }
2008 #if RVM_CONDITIONAL_INSTRUCTIONS
2009                 if (pi->cond) {
2010                         switch (pi->cond) {
2011                         case RVM_CEXEC_GRE:
2012                                 if (!((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0))
2013                                         goto skipexec;
2014                                 break;
2015                         case RVM_CEXEC_GEQ:
2016                                 if (!((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1))
2017                                         goto skipexec;
2018                                 break;
2019                         case RVM_CEXEC_EQ:
2020                                 if (!((cpu->status & RVM_STATUS_Z)))
2021                                         goto skipexec;
2022                                 break;
2023                         case RVM_CEXEC_NEQ:
2024                                 if (!((cpu->status & RVM_STATUS_Z) == 0))
2025                                         goto skipexec;
2026                                 break;
2027                         case RVM_CEXEC_LEQ:
2028                                 if (!((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)))
2029                                         goto skipexec;
2030                                 break;
2031                         case RVM_CEXEC_LES:
2032                                 if (!((cpu->status & RVM_STATUS_N)))
2033                                         goto skipexec;
2034                                 break;
2035                         default:
2036                                 goto skipexec;
2037                         };
2038                 }
2039 #endif
2040                 ops[pi->opcode](cpu, pi);
2041                 r_printf("%7ld :", ++line);
2042                 rvm_cpu_dumpregs(cpu, pi);
2043 #if RVM_CONDITIONAL_INSTRUCTIONS
2044 skipexec:
2045 #endif
2046                 RVM_REG_INCIP(regpc, 1);
2047         } while (!cpu->abort);
2048         if (cpu->error)
2049                 return -1;
2050         return 0;
2051 }
2052
2053
2054 int rvm_cpu_global_swilookup(rvmcpu_t *cpu, const char *swiname, unsigned long size)
2055 {
2056         int nswi;
2057         rvm_switable_t *swientry;
2058         unsigned long ntable;
2059
2060         for (ntable = 0; ntable < r_harray_length(cpu->switables); ntable++) {
2061                 swientry = r_harray_index(cpu->switables, ntable, rvm_switable_t*);
2062                 if (!swientry)
2063                         return -1;
2064                 for (nswi = 0; swientry[nswi].name; nswi++) {
2065                         if (r_strncmp(swientry[nswi].name, swiname, size) == 0 && r_strlen(swientry[nswi].name) == size)
2066                                 return (int)RVM_SWI_ID(ntable, nswi);
2067                 }
2068         }
2069         return -1;
2070 }
2071
2072
2073 int rvm_cpu_table_swilookup(rvmcpu_t *cpu, const char *tabname, const char *swiname, unsigned long size)
2074 {
2075         int nswi;
2076         rvm_switable_t *swientry;
2077         long ntable = r_harray_lookup_s(cpu->switables, tabname);
2078
2079         if (ntable < 0)
2080                 return -1;
2081         swientry = r_harray_index(cpu->switables, ntable, rvm_switable_t*);
2082         if (!swientry)
2083                 return -1;
2084         for (nswi = 0; swientry[nswi].name; nswi++) {
2085                 if (r_strncmp(swientry[nswi].name, swiname, size) == 0 && r_strlen(swientry[nswi].name) == size)
2086                         return (int)RVM_SWI_ID(ntable, nswi);
2087         }
2088         return -1;
2089 }
2090
2091
2092 int rvm_cpu_swilookup(rvmcpu_t *cpu, const char *tabname, const char *swiname, unsigned long size)
2093 {
2094         return tabname ? rvm_cpu_table_swilookup(cpu, tabname, swiname, size) : rvm_cpu_global_swilookup(cpu, swiname, size);
2095 }
2096
2097
2098 int rvm_cpu_swilookup_s(rvmcpu_t *cpu, const char *tabname, const char *swiname)
2099 {
2100         return rvm_cpu_swilookup(cpu, tabname, swiname, r_strlen(swiname));
2101 }
2102
2103
2104 int rvm_cpu_addswitable(rvmcpu_t *cpu, const char *tabname, rvm_switable_t *switable)
2105 {
2106         return r_harray_replace_s(cpu->switables, tabname, &switable);
2107 }
2108
2109
2110 int rvm_cpu_abort(rvmcpu_t *cpu)
2111 {
2112         if (!cpu)
2113                 return -1;
2114         cpu->error = RVM_E_USERABORT;
2115         cpu->abort = 1;
2116         return 0;
2117 }
2118
2119
2120 rvm_asmins_t rvm_cond_asma(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size)
2121 {
2122         rvm_asmins_t a;
2123
2124         r_memset(&a, 0, sizeof(a));
2125         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2126         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2127         a.op1 = (ruint8)op1;
2128         a.op2 = (ruint8)op2;
2129         a.op3 = (ruint8)op3;
2130         a.cond = (ruint8)cond;
2131         rvm_reg_setstrptr(&a.data, data, size);
2132         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2133                 a.da = 1;
2134         return a;
2135 }
2136
2137
2138 rvm_asmins_t rvm_asma(ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size)
2139 {
2140         return rvm_cond_asma(0, opcode, op1, op2, op3, data, size);
2141 }
2142
2143
2144 rvm_asmins_t rvm_cond_asmp(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, rpointer data)
2145 {
2146         rvm_asmins_t a;
2147
2148         r_memset(&a, 0, sizeof(a));
2149         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2150         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2151         a.op1 = (ruint8)op1;
2152         a.op2 = (ruint8)op2;
2153         a.op3 = (ruint8)op3;
2154         a.cond = (ruint8)cond;
2155         rvm_reg_setpointer(&a.data, data);
2156         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2157                 a.da = 1;
2158         return a;
2159 }
2160
2161
2162 rvm_asmins_t rvm_asmp(ruword opcode, ruword op1, ruword op2, ruword op3, rpointer data)
2163 {
2164         return rvm_cond_asmp(0, opcode, op1, op2, op3, data);
2165 }
2166
2167
2168 rvm_asmins_t rvm_cond_asms(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2169 {
2170         rvm_asmins_t a;
2171
2172         r_memset(&a, 0, sizeof(a));
2173         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2174         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2175         a.op1 = (ruint8)op1;
2176         a.op2 = (ruint8)op2;
2177         a.op3 = (ruint8)op3;
2178         a.cond = (ruint8)cond;
2179         rvm_reg_setunsigned(&a.data, data);
2180         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_SWIID)
2181         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2182                 a.da = 1;
2183         return a;
2184 }
2185
2186
2187 rvm_asmins_t rvm_asms(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2188 {
2189         return rvm_cond_asms(0, opcode, op1, op2, op3, data);
2190 }
2191
2192
2193 rvm_asmins_t rvm_cond_asmf(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2194 {
2195         rvm_asmins_t a;
2196
2197         r_memset(&a, 0, sizeof(a));
2198         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2199         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2200         a.op1 = (ruint8)op1;
2201         a.op2 = (ruint8)op2;
2202         a.op3 = (ruint8)op3;
2203         a.cond = (ruint8)cond;
2204         rvm_reg_setunsigned(&a.data, data);
2205         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_FUNCTION)
2206         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2207                 a.da = 1;
2208         return a;
2209 }
2210
2211 rvm_asmins_t rvm_asmf(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2212 {
2213         return rvm_cond_asmf(0, opcode, op1, op2, op3, data);
2214 }
2215
2216
2217 rvm_asmins_t rvm_cond_asm(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2218 {
2219         rvm_asmins_t a;
2220
2221         r_memset(&a, 0, sizeof(a));
2222         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2223         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2224         a.op1 = (ruint8)op1;
2225         a.op2 = (ruint8)op2;
2226         a.op3 = (ruint8)op3;
2227         a.cond = (ruint8)cond;
2228         rvm_reg_setunsigned(&a.data, data);
2229         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2230                 a.da = 1;
2231         return a;
2232 }
2233
2234
2235 rvm_asmins_t rvm_asm(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2236 {
2237         return rvm_cond_asm(0, opcode, op1, op2, op3, data);
2238 }
2239
2240
2241
2242 rvm_asmins_t rvm_cond_asml(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, long data)
2243 {
2244         rvm_asmins_t a;
2245
2246         r_memset(&a, 0, sizeof(a));
2247         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2248         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2249         a.op1 = (ruint8)op1;
2250         a.op2 = (ruint8)op2;
2251         a.op3 = (ruint8)op3;
2252         a.cond = (ruint8)cond;
2253         rvm_reg_setsigned(&a.data, data);
2254         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2255                 a.da = 1;
2256         return a;
2257 }
2258
2259
2260 rvm_asmins_t rvm_asml(ruword opcode, ruword op1, ruword op2, ruword op3, long data)
2261 {
2262         return rvm_cond_asml(0, opcode, op1, op2, op3, data);
2263 }
2264
2265
2266 rvm_asmins_t rvm_cond_asmb(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data)
2267 {
2268         rvm_asmins_t a;
2269
2270         r_memset(&a, 0, sizeof(a));
2271         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2272         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2273         a.op1 = (ruint8)op1;
2274         a.op2 = (ruint8)op2;
2275         a.op3 = (ruint8)op3;
2276         a.cond = (ruint8)cond;
2277         rvm_reg_setboolean(&a.data, data);
2278         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2279                 a.da = 1;
2280         return a;
2281 }
2282
2283
2284 rvm_asmins_t rvm_asmb(ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data)
2285 {
2286         return rvm_cond_asmb(0, opcode, op1, op2, op3, data);
2287 }
2288
2289
2290 rvm_asmins_t rvm_cond_asmd(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, double data)
2291 {
2292         rvm_asmins_t a;
2293
2294         r_memset(&a, 0, sizeof(a));
2295         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2296         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2297         a.op1 = (ruint8)op1;
2298         a.op2 = (ruint8)op2;
2299         a.op3 = (ruint8)op3;
2300         a.cond = (ruint8)cond;
2301         rvm_reg_setdouble(&a.data, data);
2302         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2303                 a.da = 1;
2304         return a;
2305 }
2306
2307 rvm_asmins_t rvm_asmd(ruword opcode, ruword op1, ruword op2, ruword op3, double data)
2308 {
2309         return rvm_cond_asmd(0, opcode, op1, op2, op3, data);
2310 }
2311
2312
2313 rvm_asmins_t rvm_cond_asm2(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2)
2314 {
2315         rvm_asmins_t a;
2316
2317         r_memset(&a, 0, sizeof(a));
2318         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2319         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2320         a.op1 = (ruint8)op1;
2321         a.op2 = (ruint8)op2;
2322         a.op3 = (ruint8)op3;
2323         a.cond = (ruint8)cond;
2324         rvm_reg_setpair(&a.data, p1, p2);
2325         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2326                 a.da = 1;
2327         return a;
2328 }
2329
2330
2331 rvm_asmins_t rvm_asm2(ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2)
2332 {
2333         return rvm_cond_asm2(0, opcode, op1, op2, op3, p1, p2);
2334 }
2335
2336 rvmreg_t *rvm_cpu_alloc_global(rvmcpu_t *cpu)
2337 {
2338         rvmreg_t *global;
2339         int index = r_carray_add(cpu->data, NULL);
2340
2341         global = (rvmreg_t*)r_carray_slot(cpu->data, index);
2342         RVM_REG_CLEAR(global);
2343         RVM_REG_SETTYPE(global, RVM_DTYPE_UNDEF);
2344         return global;
2345 }
2346
2347
2348 int rvm_cpu_setreg(rvmcpu_t *cpu, ruword regnum, const rvmreg_t *src)
2349 {
2350         if (regnum >= RLST)
2351                 return -1;
2352         RVM_CPUREG_SET(cpu, regnum, *src);
2353         return 0;
2354 }
2355
2356
2357 rvmreg_t *rvm_cpu_getreg(rvmcpu_t *cpu, ruword regnum)
2358 {
2359         if (regnum >= RLST)
2360                 return NULL;
2361         return RVM_CPUREG_PTR(cpu, regnum);
2362 }