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