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