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