RPA Toolkit
work on RJS object introspection.
[rpatk.git] / rvm / rvmcpu.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 Martin Stoilov
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include "rvm/rvmcpu.h"
24 #include "rvm/rvmoperator.h"
25 #include "rvm/rvmoperatorbin.h"
26 #include "rvm/rvmoperatorcast.h"
27 #include "rvm/rvmoperatornot.h"
28 #include "rvm/rvmoperatorlogicnot.h"
29 #include "rvm/rvmcodemap.h"
30 #include "rlib/rmem.h"
31 #include "rlib/rstring.h"
32 #include "rvm/rvmreg.h"
33 #include "rlib/rmap.h"
34
35 #define RVM_DEFAULT_STACKSIZE (4 * 1024)
36
37 static const char *stropcalls[] = {
38         "EXT",
39         "ABORT",
40         "PRN",
41         "ASR",
42         "SWI",
43         "SWIID",
44         "CALL",
45         "MOV",
46         "MOVS",
47         "SWP",
48         "INC",
49         "DEC",
50         "ADD",
51         "ADDS",
52         "ADC",
53         "AND",
54         "BIC",
55         "CLZ",
56         "CMN",
57         "XOR",
58         "SUB",
59         "SUBS",
60         "SBC",
61         "MUL",
62         "MLS",
63         "MULS",
64         "NOT",
65         "DIV",
66         "DVS",
67         "DIVS",
68         "MOD",
69         "MODS",
70         "BX",
71         "BXEQ",
72         "BXNEQ",
73         "BXLEQ",
74         "BXGEQ",
75         "BXLES",
76         "BXGRE",
77         "BXL",
78         "BL",
79         "B",
80         "STR",
81         "STRP",
82         "STRB",
83         "STRH",
84         "STRW",
85         "STRR",
86         "LDR",
87         "LDRP",
88         "LDRB",
89         "LDRH",
90         "LDRW",
91         "LDRR",
92         "CFLAG",
93         "CLR",
94         "CLRR",
95         "LSL",
96         "LSR",
97         "LSRS",
98         "STM",
99         "LDM",
100         "STS",
101         "LDS",
102         "ORR",
103         "PUSH",
104         "POP",
105         "CMP",
106         "NOP",
107         "BEQ",
108         "BNEQ",
109         "BLEQ",
110         "BGEQ",
111         "BLES",
112         "BGRE",
113         "RET",
114         "ROR",
115         "PUSHM",
116         "POPM",
117         "TST",
118         "TEQ",
119         "ADDRS",
120
121         "CAST",         /* Cast: op1 = (op3)op2 */
122         "TYPE",         /* Type: op1 = typeof(op2) */
123         "SETTYPE",      /* Type: op1.type = op2 */
124         "EMOV",
125         "ENEG",
126         "EADD",
127         "ESUB",
128         "EMUL",
129         "EDIV",
130         "EMOD",
131         "ELSL",
132         "ELSR",
133         "ELSRU",
134         "EAND",
135         "EORR",
136         "EXOR",
137         "ENOT",
138         "ELAND",
139         "ELOR",
140         "ELNOT",
141         "EEQ",
142         "ENOTEQ",
143         "EGREAT",
144         "EGREATEQ",
145         "ELESS",
146         "ELESSEQ",
147         "ECMP",
148         "ECMN",
149         "ALLOCSTR",
150         "ALLOCARR",
151         "ADDRA",
152         "LDA",
153         "STA",
154         "MAPALLOC",
155         "MAPADDR",
156         "MAPKEYLDR",
157         "MAPLDR",
158         "MAPSTR",
159         "MAPDEL",
160         "MAPLKUP",
161         "MAPADD",
162         "MAPLKUPADD",
163         "MAPNEXT",
164         "MAPPREV",
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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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, *((ruword*)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         ruword 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         *((ruword*)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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
581
582         res = ((rword)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         ruword 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         unsigned int i;
605         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         ruword 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         unsigned int ntable = (unsigned int) RVM_SWI_TABLE(ins->swi);
717         unsigned int nswi = (unsigned int) 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         unsigned int ntable = (unsigned int) RVM_SWI_TABLE(RVM_CPUREG_GETU(cpu, ins->op1));
732         unsigned int nswi = (unsigned int) 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         ruword 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         ruword 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         rword res;
800         rword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
801
802         res = (rword)(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         ruword 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         ruword 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         rword 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         rword res;
874         rword 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 = (rword)(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         ruword 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         ruword 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         ruword 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         ruword n, i = 0;
918         ruword bits = RVM_CPUREG_GETU(cpu, ins->op1);
919         ruword 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 = ((ruword)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         ruword bits = RVM_CPUREG_GETU(cpu, ins->op1);
942         ruword savedbits = bits;
943         ruword 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 (!(((ruword)(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         ruword 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         ruword 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         ruword *dst = (ruword*) RVM_CPUREG_GETU(cpu, ins->op1);
987         ruword bits = RVM_CPUREG_GETU(cpu, ins->op2);
988         
989         for (n = 0; bits && n < RLST; n++) {
990                 if (((ruword)(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         ruword *src = (ruword*)RVM_CPUREG_GETU(cpu, ins->op1);
1003         ruword bits = RVM_CPUREG_GETU(cpu, ins->op2);
1004
1005         for (n = 0; bits && n < RLST; n++) {
1006                 if (((ruword)(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         ruword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
1019         ruword res = (ruword)(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         ruword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
1032         ruword res = (ruword)(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, unsigned int 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, unsigned int 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 int reg, char *str, unsigned int 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_SINGED)
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, unsigned int size)
1142 {
1143         int ret = 0, sz = size;
1144
1145         if (pi->opcode == RVM_SWI) {
1146                 char 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                         unsigned int ntable = (unsigned int) RVM_SWI_TABLE(pi->swi);
1153                         unsigned int nswi = (unsigned int) 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_SINGED) {
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, unsigned int 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         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1508         rstring_t *s = r_string_create_strsize((const char*)RVM_CPUREG_GETP(cpu, ins->op2), (unsigned long)RVM_CPUREG_GETU(cpu, ins->op3));
1509         if (!s) {
1510                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1511         }
1512         r_gc_add(cpu->gc, (robject_t*)s);
1513         rvm_reg_setstring(arg1, s);
1514 }
1515
1516
1517 static void rvm_op_mapalloc(rvmcpu_t *cpu, rvm_asmins_t *ins)
1518 {
1519         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1520         rmap_t *a = r_map_create(sizeof(rvmreg_t), 7);
1521         if (!a) {
1522                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1523         }
1524         r_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         ruword 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, (unsigned long)size);
1538         r_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         long index;
1546         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1547         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1548         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1549         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
1550
1551         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
1552                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1553         }
1554         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SINGED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
1555                 index = r_map_lookup_l(a, -1, (long)RVM_REG_GETL(arg3));
1556         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
1557                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
1558         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
1559                 index = r_map_lookup(a, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
1560         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
1561                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
1562         } else {
1563                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1564         }
1565
1566         RVM_REG_CLEAR(arg1);
1567         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SINGED);
1568         RVM_REG_SETL(arg1, index);
1569 }
1570
1571
1572 static void rvm_op_mapadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1573 {
1574         long index;
1575         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1576         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1577         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1578         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
1579
1580         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
1581                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1582         }
1583         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SINGED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
1584                 index = r_map_gckey_add_l(a, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
1585         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
1586                 index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
1587         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
1588                 index = r_map_gckey_add(a, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
1589         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
1590                 index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
1591         } else {
1592                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1593         }
1594
1595         RVM_REG_CLEAR(arg1);
1596         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SINGED);
1597         RVM_REG_SETL(arg1, index);
1598 }
1599
1600
1601 static void rvm_op_maplookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1602 {
1603         long index;
1604         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1605         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1606         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1607         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
1608
1609         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
1610                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1611         }
1612         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SINGED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
1613                 index = r_map_lookup_l(a, -1, (long)RVM_REG_GETL(arg3));
1614                 if (index < 0)
1615                         index = r_map_gckey_add_l(a, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
1616         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
1617                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
1618                 if (index < 0)
1619                         index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
1620         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
1621                 index = r_map_lookup(a, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
1622                 if (index < 0)
1623                         index = r_map_gckey_add(a, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
1624         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
1625                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
1626                 if (index < 0)
1627                         index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
1628         } else {
1629                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1630         }
1631         RVM_REG_CLEAR(arg1);
1632         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SINGED);
1633         RVM_REG_SETL(arg1, index);
1634 }
1635
1636
1637 static void rvm_op_mapdel(rvmcpu_t *cpu, rvm_asmins_t *ins)
1638 {
1639         int ret;
1640         long index;
1641         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1642         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1643         rvmreg_t tmp = rvm_reg_create_signed(0);
1644         rmap_t *a = NULL;
1645
1646         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1647         index = (long)RVM_REG_GETL(&tmp);
1648         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1649                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1650         a = (rmap_t*)RVM_REG_GETP(arg2);
1651         ret = r_map_delete(a, index);
1652         rvm_reg_setboolean(arg1, ret == 0 ? 1 : 0);
1653 }
1654
1655
1656 static void rvm_op_mapaddr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1657 {
1658         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1659         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1660         rvmreg_t tmp = rvm_reg_create_signed(0);
1661         rmap_t *a;
1662         rpointer value;
1663         long index;
1664
1665         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1666         index = (long)RVM_REG_GETL(&tmp);
1667         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1668                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1669         a = (rmap_t*)RVM_REG_GETP(arg2);
1670         value = r_map_value(a, index);
1671         if (!value)
1672                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1673         RVM_REG_CLEAR(arg1);
1674         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
1675         RVM_REG_SETP(arg1, value);
1676 }
1677
1678
1679 static void rvm_op_mapldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1680 {
1681         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1682         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1683         rvmreg_t tmp = rvm_reg_create_signed(0);
1684         rmap_t *a = NULL;
1685         rpointer value;
1686         long index;
1687
1688         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1689         index = (long)RVM_REG_GETL(&tmp);
1690         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1691                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1692         a = (rmap_t*)RVM_REG_GETP(arg2);
1693         value = r_map_value(a, index);
1694         if (!value) {
1695                 RVM_REG_CLEAR(arg1);
1696                 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
1697         } else {
1698                 *arg1 = *((rvmreg_t*)value);
1699         }
1700 }
1701
1702
1703 static void rvm_op_mapkeyldr(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_signed(0);
1708         rmap_t *a = NULL;
1709         rstring_t *key;
1710         long index;
1711
1712         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1713         index = (long)RVM_REG_GETL(&tmp);
1714         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1715                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1716         a = (rmap_t*)RVM_REG_GETP(arg2);
1717         key = r_map_key(a, index);
1718         if (!key) {
1719                 RVM_REG_CLEAR(arg1);
1720                 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
1721         } else {
1722                 rvm_reg_setstring(arg1, key);
1723         }
1724 }
1725
1726
1727 static void rvm_op_mapnext(rvmcpu_t *cpu, rvm_asmins_t *ins)
1728 {
1729         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1730         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1731         rvmreg_t tmp = rvm_reg_create_signed(0);
1732         rmap_t *a = NULL;
1733         long index;
1734
1735         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1736         index = (long)RVM_REG_GETL(&tmp);
1737         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1738                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1739         a = (rmap_t*)RVM_REG_GETP(arg2);
1740         if (index < 0)
1741                 index = r_map_first(a);
1742         else
1743                 index = r_map_next(a, index);
1744         RVM_REG_CLEAR(arg1);
1745         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SINGED);
1746         RVM_REG_SETL(arg1, index);
1747 }
1748
1749
1750 static void rvm_op_mapprev(rvmcpu_t *cpu, rvm_asmins_t *ins)
1751 {
1752         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1753         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1754         rvmreg_t tmp = rvm_reg_create_signed(0);
1755         rmap_t *a = NULL;
1756         long index;
1757
1758         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1759         index = (long)RVM_REG_GETL(&tmp);
1760         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1761                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1762         a = (rmap_t*)RVM_REG_GETP(arg2);
1763         if (index < 0)
1764                 index = r_map_last(a);
1765         else
1766                 index = r_map_prev(a, index);
1767         RVM_REG_CLEAR(arg1);
1768         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SINGED);
1769         RVM_REG_SETL(arg1, index);
1770 }
1771
1772
1773 static void rvm_op_mapstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1774 {
1775         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1776         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1777         rvmreg_t tmp = rvm_reg_create_signed(0);
1778         rmap_t *a = NULL;
1779         rpointer value;
1780         long index;
1781
1782         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1783         index = (long)RVM_REG_GETL(&tmp);
1784         if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
1785                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
1786         a = (rmap_t*)RVM_REG_GETP(arg2);
1787         value = r_map_value(a, index);
1788         if (!value)
1789                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1790         r_map_setvalue(a, index, arg1);
1791 }
1792
1793
1794 static void rvm_op_addra(rvmcpu_t *cpu, rvm_asmins_t *ins)
1795 {
1796         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1797         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1798         rvmreg_t tmp = rvm_reg_create_signed(0);
1799         rcarray_t *a = RVM_REG_GETP(arg2);
1800         long index;
1801
1802         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1803         index = (long)RVM_REG_GETL(&tmp);
1804
1805         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY || index < 0) {
1806                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1807         }
1808         RVM_REG_CLEAR(arg1);
1809         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
1810         RVM_REG_SETP(arg1, r_carray_slot_expand(a, index));
1811 }
1812
1813
1814 static void rvm_op_lda(rvmcpu_t *cpu, rvm_asmins_t *ins)
1815 {
1816         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1817         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1818         ruword index = RVM_CPUREG_GETU(cpu, ins->op3);
1819         rcarray_t *a = RVM_REG_GETP(arg2);
1820
1821         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1822                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1823         }
1824         *arg1 = *((rvmreg_t*)r_carray_slot_expand(a, (unsigned long)index));
1825 }
1826
1827
1828 static void rvm_op_sta(rvmcpu_t *cpu, rvm_asmins_t *ins)
1829 {
1830         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1831         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1832         ruword index = RVM_CPUREG_GETU(cpu, ins->op3);
1833         rcarray_t *a = RVM_REG_GETP(arg2);
1834
1835         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1836                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1837         }
1838         r_carray_replace(a, (unsigned long)index, arg1);
1839 }
1840
1841
1842 static void rvm_op_abort(rvmcpu_t *cpu, rvm_asmins_t *ins)
1843 {
1844         RVM_ABORT(cpu, RVM_CPUREG_GETU(cpu, ins->op1));
1845 }
1846
1847
1848 static rvm_cpu_op ops[] = {
1849         rvm_op_exit,            // RVM_EXT
1850         rvm_op_abort,           // RVM_ABORT
1851         rvm_op_prn,                     // RVM_PRN
1852         rvm_op_asr,                     // RVM_ASR
1853         rvm_op_swi,                     // RVM_SWI
1854         rvm_op_swiid,           // RVM_SWIID
1855         rvm_op_call,            // RVM_CALL
1856         rvm_op_mov,                     // RVM_MOV
1857         rvm_op_movs,            // RVM_MOVS
1858         rvm_op_swp,                     // RVM_SWP
1859         rvm_op_inc,                     // RVM_INC
1860         rvm_op_dec,                     // RVM_DEC
1861         rvm_op_add,                     // RVM_ADD
1862         rvm_op_adds,            // RVM_ADDS
1863         rvm_op_adc,                     // RVM_ADC
1864         rvm_op_and,                     // RVM_AND
1865         rvm_op_bic,                     // RVM_BIC
1866         rvm_op_clz,                     // RVM_CLZ
1867         rvm_op_cmn,                     // RVM_CMN
1868         rvm_op_xor,                     // RVM_XOR
1869         rvm_op_sub,                     // RVM_SUB
1870         rvm_op_subs,            // RVM_SUBS
1871         rvm_op_sbc,                     // RVM_SBC
1872         rvm_op_mul,                     // RVM_MUL
1873         rvm_op_mls,                     // RVM_MLS
1874         rvm_op_muls,            // RVM_MULS
1875         rvm_op_not,                     // RVM_NOT
1876         rvm_op_div,                     // RVM_DIV
1877         rvm_op_dvs,                     // RVM_DVS
1878         rvm_op_divs,            // RVM_DIVS
1879         rvm_op_mod,                     // RVM_MOD
1880         rvm_op_mods,            // RVM_MODS
1881         rvm_op_bx,                      // RVM_BX
1882         rvm_op_bxeq,            // RVM_BXEQ
1883         rvm_op_bxneq,           // RVM_BXNEQ
1884         rvm_op_bxleq,           // RVM_BXLEQ
1885         rvm_op_bxgeq,           // RVM_BXGEQ
1886         rvm_op_bxles,           // RVM_BXLES
1887         rvm_op_bxgre,           // RVM_BXGRE
1888         rvm_op_bxl,                     // RVM_BXL
1889         rvm_op_bl,                      // RVM_BL
1890         rvm_op_b,                       // RVM_B
1891         rvm_op_str,                     // RVM_STR
1892         rvm_op_strp,            // RVM_STRP
1893         rvm_op_strb,            // RVM_STRB
1894         rvm_op_strh,            // RVM_STRH
1895         rvm_op_strw,            // RVM_STRW
1896         rvm_op_strr,            // RVM_STRR
1897         rvm_op_ldr,                     // RVM_LDR
1898         rvm_op_ldrp,            // RVM_LDRP
1899         rvm_op_ldrb,            // RVM_LDRB
1900         rvm_op_ldrh,            // RVM_LDRH
1901         rvm_op_ldrw,            // RVM_LDRW
1902         rvm_op_ldrr,            // RVM_LDRR
1903         rvm_op_cflag,           // RVM_CFLAG
1904         rvm_op_clr,                     // RVM_CLR
1905         rvm_op_clrr,            // RVM_CLRR
1906         rvm_op_lsl,                     // RVM_LSL
1907         rvm_op_lsr,                     // RVM_LSR
1908         rvm_op_lsrs,            // RVM_LSRS
1909         rvm_op_stm,                     // RVM_STM
1910         rvm_op_ldm,                     // RVM_LDM
1911         rvm_op_sts,                     // RVM_STS
1912         rvm_op_lds,                     // RVM_LDS
1913         rvm_op_orr,                     // RVM_ORR
1914         rvm_op_push,            // RVM_PUSH
1915         rvm_op_pop,                     // RVM_POP
1916         rvm_op_cmp,                     // RVM_CMP
1917         rvm_op_nop,                     // RVM_NOP
1918         rvm_op_beq,                     // RVM_BEQ
1919         rvm_op_bneq,            // RVM_BNEQ
1920         rvm_op_bleq,            // RVM_BLEQ
1921         rvm_op_bgeq,            // RVM_BGEQ
1922         rvm_op_bles,            // RVM_BLES
1923         rvm_op_bgre,            // RVM_BGRE
1924         rvm_op_ret,                     // RVM_RET
1925         rvm_op_ror,                     // RVM_ROR
1926         rvm_op_pushm,           // RVM_PUSHM
1927         rvm_op_popm,            // RVM_POPM
1928         rvm_op_tst,             // RVM_TST
1929         rvm_op_teq,             // RVM_TEQ
1930         rvm_op_addrs,           // RVM_ADDRS
1931
1932 /* Extended VM instructions */
1933         rvm_op_cast,            // RVM_CAST
1934         rvm_op_type,            // RVM_TYPE
1935         rvm_op_settype,         // RVM_SETTYPE
1936         rvm_op_emov,            // RVM_EMOV
1937         rvm_op_eneg,            // RVM_ENEG
1938         rvm_op_eadd,            // RVM_EADD
1939         rvm_op_esub,            // RVM_ESUB
1940         rvm_op_emul,            // RVM_EMUL
1941         rvm_op_ediv,            // RVM_EDIV
1942         rvm_op_emod,            // RVM_MOD
1943         rvm_op_elsl,            // RVM_ELSL
1944         rvm_op_elsr,            // RVM_ELSR
1945         rvm_op_elsru,           // RVM_ELSRU
1946         rvm_op_eand,            // RVM_EAND
1947         rvm_op_eorr,            // RVM_EORR
1948         rvm_op_exor,            // RVM_EXOR
1949         rvm_op_enot,            // RVM_ENOT
1950
1951         rvm_op_eland,           // RVM_ELAND
1952         rvm_op_elor,            // RVM_ELOR
1953         rvm_op_elnot,           // RVM_ELNOT
1954         rvm_op_eeq,                     // RVM_EEQ
1955         rvm_op_enoteq,          // RVM_ENOTEQ
1956         rvm_op_egreat,          // RVM_EGREAT
1957         rvm_op_egreateq,        // RVM_EGREATEQ
1958         rvm_op_eless,           // RVM_ELESS
1959         rvm_op_elesseq,         // RVM_ELESSEQ
1960         rvm_op_ecmp,            // RVM_ECMP
1961         rvm_op_ecmn,            // RVM_ECMN
1962         rvm_op_allocstr,        // RVM_ALLOCSTR
1963         rvm_op_allocarr,        // RVM_ALLOCARR
1964         rvm_op_addra,           // RVM_ADDRA
1965         rvm_op_lda,                     // RVM_LDA
1966         rvm_op_sta,                     // RVM_STA
1967         rvm_op_mapalloc,        // RVM_MAPALLOC
1968         rvm_op_mapaddr,         // RVM_MAPADDR,
1969         rvm_op_mapkeyldr,       // RVM_MAPKEYLDR,
1970         rvm_op_mapldr,          // RVM_MAPLDR,
1971         rvm_op_mapstr,          // RVM_MAPSTR,
1972         rvm_op_mapdel,          // RVM_MAPDEL,
1973         rvm_op_maplookup,       // RVM_MAPLKUP,
1974         rvm_op_mapadd,          // RVM_MAPADD,
1975         rvm_op_maplookupadd,// RVM_MAPLKUPADD,
1976         rvm_op_mapnext,         // RVM_MAPNEXT,
1977         rvm_op_mapprev,         // RVM_MAPPREV,
1978         (void*) 0,
1979         (void*) 0,
1980         (void*) 0,
1981         (void*) 0,
1982         (void*) 0,
1983         (void*) 0,
1984         (void*) 0,
1985         (void*) 0,
1986         
1987 };
1988
1989
1990 rvmcpu_t *rvm_cpu_create(unsigned long stacksize)
1991 {
1992         rvmcpu_t *cpu;
1993
1994         cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
1995         if (!cpu)
1996                 return ((void*)0);
1997         r_memset(cpu, 0, sizeof(*cpu));
1998         cpu->stacksize = stacksize;
1999         cpu->switables = r_harray_create(sizeof(rvm_switable_t*));
2000         cpu->stack = r_malloc(stacksize * sizeof(rvmreg_t));
2001         cpu->data = r_carray_create(sizeof(rvmreg_t));
2002         cpu->opmap = rvm_opmap_create();
2003         cpu->gc = r_gc_create();
2004         rvm_op_binary_init(cpu->opmap);
2005         rvm_op_cast_init(cpu->opmap);
2006         rvm_op_not_init(cpu->opmap);
2007         rvm_op_logicnot_init(cpu->opmap);
2008
2009         return cpu;
2010 }
2011
2012
2013 rvmcpu_t *rvm_cpu_create_default()
2014 {
2015         return rvm_cpu_create(RVM_DEFAULT_STACKSIZE);
2016 }
2017
2018
2019 void rvm_cpu_destroy(rvmcpu_t *cpu)
2020 {
2021         r_gc_deallocateall(cpu->gc);
2022         r_gc_destroy(cpu->gc);
2023         r_object_destroy((robject_t*)cpu->switables);
2024         r_free(cpu->stack);
2025         r_object_destroy((robject_t*)cpu->data);
2026         rvm_opmap_destroy(cpu->opmap);
2027         r_free(cpu);
2028 }
2029
2030
2031 int rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off)
2032 {
2033         rvm_asmins_t *pi;
2034         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
2035         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
2036
2037         RVM_CPUREG_SETIP(cpu, PC, prog + off);
2038         cpu->abort = 0;
2039         cpu->error = 0;
2040         do {
2041                 pi = RVM_REG_GETIP(regpc);
2042                 if (pi->da) {
2043                         *regda = pi->data;
2044                 }
2045 #if RVM_CONDITIONAL_INSTRUCTIONS
2046                 if (pi->cond) {
2047                         switch (pi->cond) {
2048                         case RVM_CEXEC_GRE:
2049                                 if (!((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0))
2050                                         goto skipexec;
2051                                 break;
2052                         case RVM_CEXEC_GEQ:
2053                                 if (!((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1))
2054                                         goto skipexec;
2055                                 break;
2056                         case RVM_CEXEC_EQ:
2057                                 if (!((cpu->status & RVM_STATUS_Z)))
2058                                         goto skipexec;
2059                                 break;
2060                         case RVM_CEXEC_NEQ:
2061                                 if (!((cpu->status & RVM_STATUS_Z) == 0))
2062                                         goto skipexec;
2063                                 break;
2064                         case RVM_CEXEC_LEQ:
2065                                 if (!((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)))
2066                                         goto skipexec;
2067                                 break;
2068                         case RVM_CEXEC_LES:
2069                                 if (!((cpu->status & RVM_STATUS_N)))
2070                                         goto skipexec;
2071                                 break;
2072                         default:
2073                                 goto skipexec;
2074                         };
2075                 }
2076 #endif
2077                 ops[pi->opcode](cpu, pi);
2078 #if RVM_CONDITIONAL_INSTRUCTIONS
2079 skipexec:
2080 #endif
2081                 RVM_REG_INCIP(regpc, 1);
2082         } while (!cpu->abort);
2083         if (cpu->error)
2084                 return -1;
2085         return 0;
2086 }
2087
2088
2089 int rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off)
2090 {
2091         long line = 0;
2092         rvm_asmins_t *pi;
2093         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
2094         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
2095
2096         RVM_CPUREG_SETIP(cpu, PC, prog + off);
2097         cpu->abort = 0;
2098         cpu->error = 0;
2099         do {
2100                 pi = RVM_REG_GETIP(regpc);
2101                 if (pi->da) {
2102                         *regda = pi->data;
2103                 }
2104 #if RVM_CONDITIONAL_INSTRUCTIONS
2105                 if (pi->cond) {
2106                         switch (pi->cond) {
2107                         case RVM_CEXEC_GRE:
2108                                 if (!((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0))
2109                                         goto skipexec;
2110                                 break;
2111                         case RVM_CEXEC_GEQ:
2112                                 if (!((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1))
2113                                         goto skipexec;
2114                                 break;
2115                         case RVM_CEXEC_EQ:
2116                                 if (!((cpu->status & RVM_STATUS_Z)))
2117                                         goto skipexec;
2118                                 break;
2119                         case RVM_CEXEC_NEQ:
2120                                 if (!((cpu->status & RVM_STATUS_Z) == 0))
2121                                         goto skipexec;
2122                                 break;
2123                         case RVM_CEXEC_LEQ:
2124                                 if (!((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)))
2125                                         goto skipexec;
2126                                 break;
2127                         case RVM_CEXEC_LES:
2128                                 if (!((cpu->status & RVM_STATUS_N)))
2129                                         goto skipexec;
2130                                 break;
2131                         default:
2132                                 goto skipexec;
2133                         };
2134                 }
2135 #endif
2136                 ops[pi->opcode](cpu, pi);
2137                 r_printf("%7ld :", ++line);
2138                 rvm_cpu_dumpregs(cpu, pi);
2139 #if RVM_CONDITIONAL_INSTRUCTIONS
2140 skipexec:
2141 #endif
2142                 RVM_REG_INCIP(regpc, 1);
2143         } while (!cpu->abort);
2144         if (cpu->error)
2145                 return -1;
2146         return 0;
2147 }
2148
2149
2150 int rvm_cpu_global_swilookup(rvmcpu_t *cpu, const char *swiname, unsigned long size)
2151 {
2152         int nswi;
2153         rvm_switable_t *swientry;
2154         unsigned long ntable;
2155
2156         for (ntable = 0; ntable < r_harray_length(cpu->switables); ntable++) {
2157                 swientry = r_harray_index(cpu->switables, ntable, rvm_switable_t*);
2158                 if (!swientry)
2159                         return -1;
2160                 for (nswi = 0; swientry[nswi].name; nswi++) {
2161                         if (r_strncmp(swientry[nswi].name, swiname, size) == 0 && r_strlen(swientry[nswi].name) == size)
2162                                 return (int)RVM_SWI_ID(ntable, nswi);
2163                 }
2164         }
2165         return -1;
2166 }
2167
2168
2169 int rvm_cpu_table_swilookup(rvmcpu_t *cpu, const char *tabname, const char *swiname, unsigned long size)
2170 {
2171         int nswi;
2172         rvm_switable_t *swientry;
2173         long ntable = r_harray_lookup_s(cpu->switables, tabname);
2174
2175         if (ntable < 0)
2176                 return -1;
2177         swientry = r_harray_index(cpu->switables, ntable, rvm_switable_t*);
2178         if (!swientry)
2179                 return -1;
2180         for (nswi = 0; swientry[nswi].name; nswi++) {
2181                 if (r_strncmp(swientry[nswi].name, swiname, size) == 0 && r_strlen(swientry[nswi].name) == size)
2182                         return (int)RVM_SWI_ID(ntable, nswi);
2183         }
2184         return -1;
2185 }
2186
2187
2188 int rvm_cpu_swilookup(rvmcpu_t *cpu, const char *tabname, const char *swiname, unsigned long size)
2189 {
2190         return tabname ? rvm_cpu_table_swilookup(cpu, tabname, swiname, size) : rvm_cpu_global_swilookup(cpu, swiname, size);
2191 }
2192
2193
2194 int rvm_cpu_swilookup_s(rvmcpu_t *cpu, const char *tabname, const char *swiname)
2195 {
2196         return rvm_cpu_swilookup(cpu, tabname, swiname, r_strlen(swiname));
2197 }
2198
2199
2200 int rvm_cpu_addswitable(rvmcpu_t *cpu, const char *tabname, rvm_switable_t *switable)
2201 {
2202         return r_harray_replace_s(cpu->switables, tabname, &switable);
2203 }
2204
2205
2206 int rvm_cpu_abort(rvmcpu_t *cpu)
2207 {
2208         if (!cpu)
2209                 return -1;
2210         cpu->error = RVM_E_USERABORT;
2211         cpu->abort = 1;
2212         return 0;
2213 }
2214
2215
2216 rvm_asmins_t rvm_cond_asma(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size)
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 = (ruint8)cond;
2227         rvm_reg_setstrptr(&a.data, data, size);
2228         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2229                 a.da = 1;
2230         return a;
2231 }
2232
2233
2234 rvm_asmins_t rvm_asma(ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size)
2235 {
2236         return rvm_cond_asma(0, opcode, op1, op2, op3, data, size);
2237 }
2238
2239
2240 rvm_asmins_t rvm_cond_asmp(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, rpointer 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 = (ruint8)cond;
2251         rvm_reg_setpointer(&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_asmp(ruword opcode, ruword op1, ruword op2, ruword op3, rpointer data)
2259 {
2260         return rvm_cond_asmp(0, opcode, op1, op2, op3, data);
2261 }
2262
2263
2264 rvm_asmins_t rvm_cond_asms(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2265 {
2266         rvm_asmins_t a;
2267
2268         r_memset(&a, 0, sizeof(a));
2269         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2270         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2271         a.op1 = (ruint8)op1;
2272         a.op2 = (ruint8)op2;
2273         a.op3 = (ruint8)op3;
2274         a.cond = (ruint8)cond;
2275         rvm_reg_setunsigned(&a.data, data);
2276         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_SWIID)
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_asms(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2284 {
2285         return rvm_cond_asms(0, opcode, op1, op2, op3, data);
2286 }
2287
2288
2289 rvm_asmins_t rvm_cond_asmf(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword 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 = (ruint8)cond;
2300         rvm_reg_setunsigned(&a.data, data);
2301         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_FUNCTION)
2302         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2303                 a.da = 1;
2304         return a;
2305 }
2306
2307 rvm_asmins_t rvm_asmf(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2308 {
2309         return rvm_cond_asmf(0, opcode, op1, op2, op3, data);
2310 }
2311
2312
2313 rvm_asmins_t rvm_cond_asm(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword 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 = (ruint8)cond;
2324         rvm_reg_setunsigned(&a.data, data);
2325         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2326                 a.da = 1;
2327         return a;
2328 }
2329
2330
2331 rvm_asmins_t rvm_asm(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data)
2332 {
2333         return rvm_cond_asm(0, opcode, op1, op2, op3, data);
2334 }
2335
2336
2337
2338 rvm_asmins_t rvm_cond_asml(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, long data)
2339 {
2340         rvm_asmins_t a;
2341
2342         r_memset(&a, 0, sizeof(a));
2343         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2344         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2345         a.op1 = (ruint8)op1;
2346         a.op2 = (ruint8)op2;
2347         a.op3 = (ruint8)op3;
2348         a.cond = (ruint8)cond;
2349         rvm_reg_setsigned(&a.data, data);
2350         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2351                 a.da = 1;
2352         return a;
2353 }
2354
2355
2356 rvm_asmins_t rvm_asml(ruword opcode, ruword op1, ruword op2, ruword op3, long data)
2357 {
2358         return rvm_cond_asml(0, opcode, op1, op2, op3, data);
2359 }
2360
2361
2362 rvm_asmins_t rvm_cond_asmb(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data)
2363 {
2364         rvm_asmins_t a;
2365
2366         r_memset(&a, 0, sizeof(a));
2367         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2368         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2369         a.op1 = (ruint8)op1;
2370         a.op2 = (ruint8)op2;
2371         a.op3 = (ruint8)op3;
2372         a.cond = (ruint8)cond;
2373         rvm_reg_setboolean(&a.data, data);
2374         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2375                 a.da = 1;
2376         return a;
2377 }
2378
2379
2380 rvm_asmins_t rvm_asmb(ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data)
2381 {
2382         return rvm_cond_asmb(0, opcode, op1, op2, op3, data);
2383 }
2384
2385
2386 rvm_asmins_t rvm_cond_asmd(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, double data)
2387 {
2388         rvm_asmins_t a;
2389
2390         r_memset(&a, 0, sizeof(a));
2391         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2392         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2393         a.op1 = (ruint8)op1;
2394         a.op2 = (ruint8)op2;
2395         a.op3 = (ruint8)op3;
2396         a.cond = (ruint8)cond;
2397         rvm_reg_setdouble(&a.data, data);
2398         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2399                 a.da = 1;
2400         return a;
2401 }
2402
2403 rvm_asmins_t rvm_asmd(ruword opcode, ruword op1, ruword op2, ruword op3, double data)
2404 {
2405         return rvm_cond_asmd(0, opcode, op1, op2, op3, data);
2406 }
2407
2408
2409 rvm_asmins_t rvm_cond_asm2(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2)
2410 {
2411         rvm_asmins_t a;
2412
2413         r_memset(&a, 0, sizeof(a));
2414         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
2415         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
2416         a.op1 = (ruint8)op1;
2417         a.op2 = (ruint8)op2;
2418         a.op3 = (ruint8)op3;
2419         a.cond = (ruint8)cond;
2420         rvm_reg_setpair(&a.data, p1, p2);
2421         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
2422                 a.da = 1;
2423         return a;
2424 }
2425
2426
2427 rvm_asmins_t rvm_asm2(ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2)
2428 {
2429         return rvm_cond_asm2(0, opcode, op1, op2, op3, p1, p2);
2430 }
2431
2432 rvmreg_t *rvm_cpu_alloc_global(rvmcpu_t *cpu)
2433 {
2434         rvmreg_t *global;
2435         int index = r_carray_add(cpu->data, NULL);
2436
2437         global = (rvmreg_t*)r_carray_slot(cpu->data, index);
2438         RVM_REG_CLEAR(global);
2439         RVM_REG_SETTYPE(global, RVM_DTYPE_UNDEF);
2440         return global;
2441 }
2442
2443
2444 int rvm_cpu_setreg(rvmcpu_t *cpu, ruword regnum, const rvmreg_t *src)
2445 {
2446         if (regnum >= RLST)
2447                 return -1;
2448         RVM_CPUREG_SET(cpu, regnum, *src);
2449         return 0;
2450 }
2451
2452
2453 rvmreg_t *rvm_cpu_getreg(rvmcpu_t *cpu, ruword regnum)
2454 {
2455         if (regnum >= RLST)
2456                 return NULL;
2457         return RVM_CPUREG_PTR(cpu, regnum);
2458 }