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