RPA Toolkit
9b1bcddf2084880bc24dac4f06e0d3643ff686d8
[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 "rmem.h"
30 #include "rstring.h"
31 #include "rvmreg.h"
32
33
34 static const char *stropcalls[] = {
35         "RVM_EXT",
36         "RVM_ABORT",
37         "RVM_PRN",
38         "RVM_ASR",
39         "RVM_SWI",
40         "RVM_SWIID",
41         "RVM_CALL",
42         "RVM_MOV",
43         "RVM_INC",
44         "RVM_DEC",
45         "RVM_ADD",
46         "RVM_ADDS",
47         "RVM_ADC",
48         "RVM_AND",
49         "RVM_BIC",
50         "RVM_CLZ",
51         "RVM_CMN",
52         "RVM_XOR",
53         "RVM_SUB",
54         "RVM_SUBS",
55         "RVM_SBC",
56         "RVM_MUL",
57         "RVM_MLS",
58         "RVM_MULS",
59         "RVM_NOT",
60         "RVM_DIV",
61         "RVM_DVS",
62         "RVM_DIVS",
63         "RVM_MOD",
64         "RVM_MODS",
65         "RVM_BX",
66         "RVM_BL",
67         "RVM_B",
68         "RVM_STR",
69         "RVM_STRP",
70         "RVM_STRB",
71         "RVM_STRH",
72         "RVM_STRW",
73         "RVM_STRR",
74         "RVM_LDR",
75         "RVM_LDRP",
76         "RVM_LDRB",
77         "RVM_LDRH",
78         "RVM_LDRW",
79         "RVM_LDRR",
80         "RVM_CLRR",
81         "RVM_LSL",
82         "RVM_LSR",
83         "RVM_LSRS",
84         "RVM_STM",
85         "RVM_LDM",
86         "RVM_STS",
87         "RVM_LDS",
88         "RVM_ORR",
89         "RVM_PUSH",
90         "RVM_POP",
91         "RVM_CMP",
92         "RVM_NOP",
93         "RVM_BEQ",
94         "RVM_BNEQ",
95         "RVM_BLEQ",
96         "RVM_BGEQ",
97         "RVM_BLES",
98         "RVM_BGRE",
99         "RVM_RET",
100         "RVM_ROR",
101         "RVM_PUSHM",
102         "RVM_POPM",     
103         "RVM_TST",
104         "RVM_TEQ",
105         "RVM_CLR",
106         "RVM_ADDRS",
107
108         "RVM_CAST",             /* Cast: op1 = (op3)op2 */
109         "RVM_TYPE",             /* Type: op1 = typeof(op2) */
110         "RVM_SETTYPE",  /* Type: op1.type = op2 */
111         "RVM_EMOV",
112         "RVM_EADD",
113         "RVM_ESUB",
114         "RVM_EMUL",
115         "RVM_EDIV",
116         "RVM_EMOD",
117         "RVM_ELSL",
118         "RVM_ELSR",
119         "RVM_ELSRU",
120         "RVM_EAND",
121         "RVM_EORR",
122         "RVM_EXOR",
123         "RVM_ENOT",
124         "RVM_ELAND",
125         "RVM_ELOR",
126         "RVM_ELNOT",
127         "RVM_EEQ",
128         "RVM_ENOTEQ",
129         "RVM_EGREAT",
130         "RVM_EGREATEQ",
131         "RVM_ELESS",
132         "RVM_ELESSEQ",
133         "RVM_ECMP",
134         "RVM_ECMN",
135         "RVM_ALLOCSTR",
136         "RVM_ALLOCARR",
137         "RVM_ADDRA",
138         "RVM_ELDA",
139         "RVM_ESTA",
140         "UNKNOWN",
141         "UNKNOWN",
142         "UNKNOWN",
143         "UNKNOWN",
144         "UNKNOWN",
145         "UNKNOWN",
146         "UNKNOWN",
147         "UNKNOWN",
148         "UNKNOWN",
149         "UNKNOWN",
150         "UNKNOWN",
151 };
152
153
154 static void rvm_op_b(rvmcpu_t *cpu, rvm_asmins_t *ins)
155 {
156         rword pc = 0;
157
158         if (ins->op1 != XX)
159                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
160         if (ins->op2 != XX)
161                 pc += RVM_CPUREG_GETU(cpu, ins->op2);
162         if (ins->op3 != XX)
163                 pc += RVM_CPUREG_GETU(cpu, ins->op3);
164         RVM_CPUREG_INCIP(cpu, PC, pc - 1);
165 }
166
167
168 static void rvm_op_beq(rvmcpu_t *cpu, rvm_asmins_t *ins)
169 {
170         rword pc = 0;
171
172         if ((cpu->status & RVM_STATUS_Z)) {
173                 if (ins->op1 != XX)
174                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
175                 if (ins->op2 != XX)
176                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
177                 if (ins->op3 != XX)
178                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
179                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
180         }
181 }
182
183
184 static void rvm_op_bneq(rvmcpu_t *cpu, rvm_asmins_t *ins)
185 {
186         rword pc = 0;
187
188         if ((cpu->status & RVM_STATUS_Z) == 0) {
189                 if (ins->op1 != XX)
190                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
191                 if (ins->op2 != XX)
192                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
193                 if (ins->op3 != XX)
194                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
195                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
196         }
197 }
198
199
200 static void rvm_op_bleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
201 {
202         rword pc = 0;
203
204         if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)) {
205                 if (ins->op1 != XX)
206                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
207                 if (ins->op2 != XX)
208                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
209                 if (ins->op3 != XX)
210                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
211                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
212         }
213 }
214
215 static void rvm_op_bgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
216 {
217         rword pc = 0;
218
219         if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1){
220                 if (ins->op1 != XX)
221                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
222                 if (ins->op2 != XX)
223                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
224                 if (ins->op3 != XX)
225                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
226                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
227         }
228 }
229
230
231 static void rvm_op_bles(rvmcpu_t *cpu, rvm_asmins_t *ins)
232 {
233         rword pc = 0;
234
235
236         if ((cpu->status & RVM_STATUS_N)){
237                 if (ins->op1 != XX)
238                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
239                 if (ins->op2 != XX)
240                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
241                 if (ins->op3 != XX)
242                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
243                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
244         }
245 }
246
247
248 static void rvm_op_bgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
249 {
250         rword pc = 0;
251
252         if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0) {
253                 if (ins->op1 != XX)
254                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
255                 if (ins->op2 != XX)
256                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
257                 if (ins->op3 != XX)
258                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
259                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
260         }
261 }
262
263
264 static void rvm_op_bx(rvmcpu_t *cpu, rvm_asmins_t *ins)
265 {
266         RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
267 }
268
269
270 static void rvm_op_bl(rvmcpu_t *cpu, rvm_asmins_t *ins)
271 {
272         rword pc = 0;
273         if (ins->op1 != XX)
274                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
275         if (ins->op2 != XX)
276                 pc += RVM_CPUREG_GETU(cpu, ins->op2);
277         if (ins->op3 != XX)
278                 pc += RVM_CPUREG_GETU(cpu, ins->op3);
279
280         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
281         RVM_CPUREG_INCIP(cpu, PC, pc - 1);
282 }
283
284
285 static void rvm_op_exit(rvmcpu_t *cpu, rvm_asmins_t *ins)
286 {
287         cpu->abort = 1;
288 }
289
290
291 static void rvm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
292 {
293         RVM_CPUREG_SET(cpu, ins->op1, RVM_CPUREG_GET(cpu, ins->op2));
294 }
295
296
297 static void rvm_op_ldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
298 {
299         RVM_CPUREG_SETU(cpu, ins->op1, *((rword*)RVM_CPUREG_GETU(cpu, ins->op2)));
300         
301 }
302
303
304 static void rvm_op_ldrp(rvmcpu_t *cpu, rvm_asmins_t *ins)
305 {
306         RVM_CPUREG_SETU(cpu, ins->op1, *((rpointer*)RVM_CPUREG_GETU(cpu, ins->op2)));
307 }
308
309
310 static void rvm_op_ldrb(rvmcpu_t *cpu, rvm_asmins_t *ins)
311 {
312         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint8*)RVM_CPUREG_GETU(cpu, ins->op2)));
313 }
314
315
316 static void rvm_op_ldrh(rvmcpu_t *cpu, rvm_asmins_t *ins)
317 {
318         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint16*)RVM_CPUREG_GETU(cpu, ins->op2)));
319 }
320
321
322 static void rvm_op_ldrw(rvmcpu_t *cpu, rvm_asmins_t *ins)
323 {
324         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint32*)RVM_CPUREG_GETU(cpu, ins->op2)));
325 }
326
327
328 static void rvm_op_ldrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
329 {
330         RVM_CPUREG_SET(cpu, ins->op1, *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)));
331 }
332
333
334 static void rvm_op_clrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
335 {
336         rvm_reg_cleanup(((rvmreg_t*)RVM_CPUREG_GETP(cpu, ins->op1)));
337 }
338
339
340 static void rvm_op_str(rvmcpu_t *cpu, rvm_asmins_t *ins)
341 {
342         *((rword*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GETU(cpu, ins->op1);
343 }
344
345
346 static void rvm_op_strp(rvmcpu_t *cpu, rvm_asmins_t *ins)
347 {
348         *((rpointer*)RVM_CPUREG_GETP(cpu, ins->op2)) = (rpointer)RVM_CPUREG_GETP(cpu, ins->op1);
349 }
350
351
352 static void rvm_op_strb(rvmcpu_t *cpu, rvm_asmins_t *ins)
353 {
354         *((ruint8*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint8)RVM_CPUREG_GETU(cpu, ins->op1);
355 }
356
357
358 static void rvm_op_strh(rvmcpu_t *cpu, rvm_asmins_t *ins)
359 {
360         *((ruint16*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint16)RVM_CPUREG_GETU(cpu, ins->op1);
361         
362 }
363
364
365 static void rvm_op_strw(rvmcpu_t *cpu, rvm_asmins_t *ins)
366 {
367         *((ruint32*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint32)RVM_CPUREG_GETU(cpu, ins->op1);
368
369 }
370
371
372 static void rvm_op_strr(rvmcpu_t *cpu, rvm_asmins_t *ins)
373 {
374         *((rvmreg_t*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GET(cpu, ins->op1);
375 }
376
377
378 static void rvm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
379 {
380         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
381
382         res = op2 + op3;
383         RVM_CPUREG_SETU(cpu, ins->op1, res);
384         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
385         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
386         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
387         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
388                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
389 }
390
391
392 static void rvm_op_adc(rvmcpu_t *cpu, rvm_asmins_t *ins)
393 {
394         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
395         
396         res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
397         RVM_CPUREG_SETU(cpu, ins->op1, res);
398         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
399         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
400         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
401         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
402                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
403 }
404
405
406 static void rvm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
407 {
408         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
409         
410         res = op2 & op3;
411         RVM_CPUREG_SETU(cpu, ins->op1, res);
412         RVM_STATUS_CLRALL(cpu);
413         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
414         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
415 }
416
417
418 static void rvm_op_orr(rvmcpu_t *cpu, rvm_asmins_t *ins)
419 {
420         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
421         
422         res = op2 | op3;
423         RVM_CPUREG_SETU(cpu, ins->op1, res);
424         RVM_STATUS_CLRALL(cpu);
425         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
426         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
427 }
428
429
430 static void rvm_op_lsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
431 {
432         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
433         
434         res = op2 << op3;
435         RVM_CPUREG_SETU(cpu, ins->op1, res);
436         RVM_STATUS_CLRALL(cpu);
437         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
438         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
439 }
440
441
442 static void rvm_op_lsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
443 {
444         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
445         
446         res = op2 >> op3;
447         RVM_CPUREG_SETU(cpu, ins->op1, res);
448         RVM_STATUS_CLRALL(cpu);
449         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
450 }
451
452
453 static void rvm_op_lsrs(rvmcpu_t *cpu, rvm_asmins_t *ins)
454 {
455         rsword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
456
457         res = ((rsword)op2) >> op3;
458         RVM_CPUREG_SETU(cpu, ins->op1, res);
459         RVM_STATUS_CLRALL(cpu);
460         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
461 }
462
463
464 static void rvm_op_asr(rvmcpu_t *cpu, rvm_asmins_t *ins)
465 {
466         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
467         
468         res = op2 >> op3;
469         res |= op2 & RVM_SIGN_BIT;
470         RVM_CPUREG_SETU(cpu, ins->op1, res);
471         RVM_STATUS_CLRALL(cpu);
472         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
473         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
474 }
475
476
477 static void rvm_op_ror(rvmcpu_t *cpu, rvm_asmins_t *ins)
478 {
479         ruint i;
480         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
481         
482         res = op2;
483         for (i = 0; i < op3; i++) {
484                 if (res & 1) {
485                         res >>= 1;
486                         res |= RVM_SIGN_BIT;
487                 } else {
488                         res >>= 1;
489                 }
490         }
491         RVM_CPUREG_SETU(cpu, ins->op1, res);
492         RVM_STATUS_CLRALL(cpu);
493         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
494         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
495         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res & RVM_SIGN_BIT);
496 }
497
498
499 static void rvm_op_tst(rvmcpu_t *cpu, rvm_asmins_t *ins)
500 {
501         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
502         
503         res = op2 & op3;
504         RVM_STATUS_CLRALL(cpu);
505         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
506         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
507 }
508
509
510 static void rvm_op_xor(rvmcpu_t *cpu, rvm_asmins_t *ins)
511 {
512         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
513         
514         res = op2 ^ op3;
515         RVM_CPUREG_SETU(cpu, ins->op1, res);
516         RVM_STATUS_CLRALL(cpu);
517         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
518         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
519 }
520
521
522 static void rvm_op_not(rvmcpu_t *cpu, rvm_asmins_t *ins)
523 {
524         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
525         
526         res = ~op2;
527         RVM_CPUREG_SETU(cpu, ins->op1, res);
528         RVM_STATUS_CLRALL(cpu);
529         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
530         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
531 }
532
533
534 static void rvm_op_teq(rvmcpu_t *cpu, rvm_asmins_t *ins)
535 {
536         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
537         
538         res = op2 ^ op3;
539         RVM_STATUS_CLRALL(cpu);
540         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
541         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
542 }
543
544
545 static void rvm_op_clr(rvmcpu_t *cpu, rvm_asmins_t *ins)
546 {
547         rvmreg_t *reg = RVM_CPUREG_PTR(cpu, ins->op1);
548         rvm_reg_cleanup(reg);
549 }
550
551
552 static void rvm_op_bic(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_clz(rvmcpu_t *cpu, rvm_asmins_t *ins)
565 {
566         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
567         
568         for (res = RVM_REGISTER_BITS; op2; ) {
569                 op2 >>= 1;
570                 res -= 1;
571         }
572         RVM_CPUREG_SETU(cpu, ins->op1, res);
573 }
574
575
576 static void rvm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
577 {
578         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3));
579 }
580
581
582 static void rvm_op_inc(rvmcpu_t *cpu, rvm_asmins_t *ins)
583 {
584         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op1) + 1);
585 }
586
587
588 static void rvm_op_dec(rvmcpu_t *cpu, rvm_asmins_t *ins)
589 {
590         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
591 }
592
593
594 static void rvm_op_swi(rvmcpu_t *cpu, rvm_asmins_t *ins)
595 {
596         rvmcpu_swi swi;
597         rvm_switable_t *switable;
598         ruint ntable = (ruint) RVM_SWI_TABLE(ins->swi);
599         ruint nswi = (ruint) RVM_SWI_NUM(ins->swi);
600
601         if (r_array_length(cpu->switables) <= ntable)
602                 RVM_ABORT(cpu, RVM_E_SWITABLE);
603         switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
604         swi = switable[nswi].op;
605         swi(cpu, ins);
606 }
607
608
609 static void rvm_op_swiid(rvmcpu_t *cpu, rvm_asmins_t *ins)
610 {
611         rvmcpu_swi swi;
612         rvm_switable_t *switable;
613         ruint ntable = (ruint) RVM_SWI_TABLE(RVM_CPUREG_GETU(cpu, ins->op1));
614         ruint nswi = (ruint) RVM_SWI_NUM(RVM_CPUREG_GETU(cpu, ins->op1));
615
616         if (r_array_length(cpu->switables) <= ntable)
617                 RVM_ABORT(cpu, RVM_E_SWITABLE);
618         switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
619         swi = switable[nswi].op;
620         swi(cpu, ins);
621 }
622
623
624 static void rvm_op_call(rvmcpu_t *cpu, rvm_asmins_t *ins)
625 {
626         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
627
628         if (RVM_REG_GETTYPE(arg1) == RVM_DTYPE_SWIID) {
629                 RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
630                 rvm_op_swiid(cpu, ins);
631         } else {
632                 rvm_op_bl(cpu, ins);
633         }
634 }
635
636
637 static void rvm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
638 {
639         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
640 }
641
642
643 static void rvm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
644 {
645         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
646         
647         res = op2 - op3;
648         RVM_CPUREG_SETU(cpu, ins->op1, res);
649         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
650         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
651         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
652         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
653                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
654 }
655
656
657 static void rvm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
658 {
659         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
660
661         res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
662         RVM_CPUREG_SETU(cpu, ins->op1, res);
663         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
664         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
665         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
666         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
667                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
668 }
669
670
671 static void rvm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
672 {
673         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
674 }
675
676
677 static void rvm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
678 {
679         rsword res;
680         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
681
682         res = (rsword)(op2 * op3);
683         RVM_CPUREG_SETU(cpu, ins->op1, res);
684         /* TBD: Not sure how to update the RVM_STATUS_C */
685         RVM_STATUS_CLRALL(cpu);
686         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
687         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
688 }
689
690
691 static void rvm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
692 {
693         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
694         
695         res = op2 * op3;
696         RVM_CPUREG_SETU(cpu, ins->op1, res);
697         RVM_STATUS_CLRALL(cpu);
698         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
699         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
700         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
701 }
702
703
704 static void rvm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
705 {
706         if (!RVM_CPUREG_GETU(cpu, ins->op3))
707                 RVM_ABORT(cpu, RVM_E_DIVZERO);
708
709         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
710 }
711
712
713 static void rvm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
714 {
715         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
716
717         if (!op3)
718                 RVM_ABORT(cpu, RVM_E_DIVZERO);
719         res = op2 / op3;
720         RVM_CPUREG_SETU(cpu, ins->op1, res);
721         RVM_STATUS_CLRALL(cpu);
722         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
723         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
724 }
725
726
727 static void rvm_op_mod(rvmcpu_t *cpu, rvm_asmins_t *ins)
728 {
729         if (!RVM_CPUREG_GETU(cpu, ins->op3))
730                 RVM_ABORT(cpu, RVM_E_DIVZERO);
731
732         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) % RVM_CPUREG_GETU(cpu, ins->op3));
733 }
734
735
736 static void rvm_op_mods(rvmcpu_t *cpu, rvm_asmins_t *ins)
737 {
738         rsword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
739
740         if (!op3)
741                 RVM_ABORT(cpu, RVM_E_DIVZERO);
742         res = op2 % op3;
743         r_printf("mod RES: %ld\n", res);
744         RVM_CPUREG_SETU(cpu, ins->op1, res);
745         RVM_STATUS_CLRALL(cpu);
746         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
747         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
748 }
749
750
751 static void rvm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
752 {
753         rsword res;
754         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
755
756         if (!op3)
757                 RVM_ABORT(cpu, RVM_E_DIVZERO);
758         res = (rsword)(op2 / op3);
759         RVM_CPUREG_SETU(cpu, ins->op1, res);
760         RVM_STATUS_CLRALL(cpu);
761         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
762         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
763 }
764
765
766 static void rvm_op_push(rvmcpu_t *cpu, rvm_asmins_t *ins)
767 {
768         rword sp = RVM_CPUREG_GETU(cpu, SP) + 1;
769
770         RVM_STACK_WRITE(cpu->stack, sp, &RVM_CPUREG_GET(cpu, ins->op1));
771         RVM_CPUREG_SETU(cpu, SP, sp);
772 }
773
774
775 static void rvm_op_lds(rvmcpu_t *cpu, rvm_asmins_t *ins)
776 {
777         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
778
779         RVM_CPUREG_SET(cpu, ins->op1, RVM_STACK_READ(cpu->stack, sp));
780 }
781
782
783 static void rvm_op_sts(rvmcpu_t *cpu, rvm_asmins_t *ins)
784 {
785         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
786
787         RVM_STACK_WRITE(cpu->stack, sp, &RVM_CPUREG_GET(cpu, ins->op1));
788 }
789
790
791 static void rvm_op_pushm(rvmcpu_t *cpu, rvm_asmins_t *ins)
792 {
793         rword n, i = 0;
794         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
795         rword sp = RVM_CPUREG_GETU(cpu, SP);
796
797         if (!(bits & ((1<<(RVM_REGS_NUM / 2)) - 1)))
798                 i = RVM_REGS_NUM / 2;
799         for (;bits && i < RLST; i++) {
800                 n = 1 << i;
801                 if (n & bits) {
802                         sp += 1;
803                         RVM_STACK_WRITE(cpu->stack, sp, &RVM_CPUREG_GET(cpu, i));
804                         bits &= ~n;
805                 }
806         }
807         RVM_CPUREG_SETU(cpu, SP, sp);
808 }
809
810
811 static void rvm_op_popm(rvmcpu_t *cpu, rvm_asmins_t *ins)
812 {
813         int n, i = RLST - 1;
814         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
815         rword savedbits = bits;
816         rword sp = RVM_CPUREG_GETU(cpu, SP);
817
818         if (!(bits & ~((1 << (RVM_REGS_NUM / 2)) - 1)))
819                 i = RVM_REGS_NUM / 2 - 1;
820         for (; bits && i >= 0; i--) {
821                 n = 1 << i;
822                 if (n & bits) {
823                         RVM_CPUREG_SET(cpu, i, RVM_STACK_READ(cpu->stack, sp));
824                         sp -= 1;
825                         bits &= ~n;
826                 }
827         }
828         if (!(((rword)(1 << SP)) & savedbits))
829                 RVM_CPUREG_SETU(cpu, SP, sp);
830 }
831
832
833 static void rvm_op_pop(rvmcpu_t *cpu, rvm_asmins_t *ins)
834 {
835         rword sp = RVM_CPUREG_GETU(cpu, SP);
836
837         RVM_CPUREG_SET(cpu, ins->op1, RVM_STACK_READ(cpu->stack, sp));
838         if (ins->op1 != SP)
839                 RVM_CPUREG_SETU(cpu, SP, sp - 1);
840 }
841
842
843 static void rvm_op_addrs(rvmcpu_t *cpu, rvm_asmins_t *ins)
844 {
845         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
846
847         RVM_CPUREG_CLEAR(cpu, ins->op1);
848         RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_POINTER);
849         RVM_CPUREG_SETP(cpu, ins->op1, RVM_STACK_ADDR(cpu->stack, sp));
850 }
851
852
853 static void rvm_op_stm(rvmcpu_t *cpu, rvm_asmins_t *ins)
854 {
855         int n;
856         rword *dst = (rword*)   RVM_CPUREG_GETU(cpu, ins->op1);
857         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
858         
859         for (n = 0; bits && n < RLST; n++) {
860                 if (((rword)(1 << n)) & bits) {
861                         *dst = RVM_CPUREG_GETU(cpu, n);
862                         dst += 1;
863                         bits &= ~(1<<n);
864                 }
865         }
866 }
867
868
869 static void rvm_op_ldm(rvmcpu_t *cpu, rvm_asmins_t *ins)
870 {
871         int n;
872         rword *src = (rword*)RVM_CPUREG_GETU(cpu, ins->op1);
873         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
874
875         for (n = 0; bits && n < RLST; n++) {
876                 if (((rword)(1 << n)) & bits) {
877                         RVM_CPUREG_CLEAR(cpu, n);
878                         RVM_CPUREG_SETU(cpu, n, *src);
879                         src += 1;
880                         bits &= ~(1<<n);
881                 }
882         }
883 }
884
885
886 static void rvm_op_cmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
887 {
888         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
889         rword res = (rword)(op1 - op2);
890         
891         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op1 < op2);
892         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
893         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
894         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT) &&
895                                                         (res & RVM_SIGN_BIT) == (op1 & RVM_SIGN_BIT));
896 }
897
898
899 static void rvm_op_cmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
900 {
901         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
902         rword res = (rword)(op1 + op2);
903         
904         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op1 || res < op2);
905         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
906         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
907         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT) &&
908                                                         (res & RVM_SIGN_BIT) != (op1 & RVM_SIGN_BIT));
909
910 }
911
912
913 static void rvm_op_nop(rvmcpu_t *cpu, rvm_asmins_t *ins)
914 {
915 //      fprintf(stdout, "nop\n");
916 }
917
918
919 static void rvm_op_ret(rvmcpu_t *cpu, rvm_asmins_t *ins)
920 {
921         RVM_CPUREG_SETU(cpu, PC, RVM_CPUREG_GETU(cpu, LR));     
922 }
923
924
925 static int rvm_vsnprintf(char *str, ruint size, const char *format, va_list ap)
926 {
927         return vsnprintf(str, size, format, ap);
928 }
929
930
931 static int rvm_snprintf(char *str, ruint size, const char *format, ...)
932 {
933         va_list ap;
934         int ret;
935
936         va_start(ap, format);
937         ret = rvm_vsnprintf(str, size, format, ap);
938         va_end(ap);
939         return ret;
940 }
941
942
943 static int rvm_printf(const char *format, ...)
944 {
945         va_list ap;
946         int ret;
947
948         va_start(ap, format);
949         ret = vfprintf(stdout, format, ap);
950         va_end(ap);
951         return ret;
952 }
953
954
955 int rvm_asm_dump_reg_to_str(unsigned char reg, char *str, ruint size)
956 {
957         int ret = 0;
958
959         if (reg == XX)
960                 ret = rvm_snprintf(str, size, "XX ");
961         else if (reg == FP)
962                 ret = rvm_snprintf(str, size, "FP ");
963         else if (reg == SP)
964                 ret = rvm_snprintf(str, size, "SP ");
965         else if (reg == LR)
966                 ret = rvm_snprintf(str, size, "LR ");
967         else if (reg == PC)
968                 ret = rvm_snprintf(str, size, "PC ");
969         else if (reg == DA)
970                 ret = rvm_snprintf(str, size, "DA ");
971         else if (reg >= 0 && reg < RVM_REGS_NUM/2)
972                 ret = rvm_snprintf(str, size, "R%d ",  reg);
973         else if (reg >= RVM_REGS_NUM/2)
974                 ret = rvm_snprintf(str, size, "S%d ",  reg & ((1 << (RVM_OPERAND_BITS-1))-1));
975
976         return ret;
977 }
978
979
980 static void rvm_op_prn(rvmcpu_t *cpu, rvm_asmins_t *ins)
981 {
982         rvmreg_t *r = RVM_CPUREG_PTR(cpu, ins->op1);
983
984         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
985                 rvm_printf("(UNSIGNED) R%d = %lu(0x%lx)\n", ins->op1, RVM_REG_GETU(r), RVM_REG_GETU(r));
986         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
987                 rvm_printf("(UNSIGNED) R%d = %lu(0x%lx)\n", ins->op1, RVM_REG_GETU(r), RVM_REG_GETU(r));
988         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
989                 rvm_printf("(POINTER) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
990         else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
991                 rvm_printf("(LONG) R%d = %ld\n", ins->op1, RVM_REG_GETL(r));
992         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
993                 rvm_printf("(DOUBLE) R%d = %0.2f\n", ins->op1, RVM_REG_GETD(r));
994         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
995                 rvm_printf("(STRING) R%d = %s\n", ins->op1, ((rstring_t*) RVM_REG_GETP(r))->s.str);
996         else if (rvm_reg_gettype(r) == RVM_DTYPE_ARRAY)
997                 rvm_printf("(ARRAY) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
998         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
999                 rvm_printf("(SWI) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
1000         else
1001                 rvm_printf("(UNKNOWN) R%d = ?\n", ins->op1);
1002 }
1003
1004
1005 int rvm_asm_dump_pi_to_str(rvmcpu_t *vm, rvm_asmins_t *pi, char *str, ruint size)
1006 {
1007         int ret = 0, sz = size;
1008
1009         if (pi->opcode == RVM_SWI) {
1010                 rchar szSwi[64];
1011                 r_memset(szSwi, 0, sizeof(szSwi));
1012                 if (!vm) {
1013                         rvm_snprintf(szSwi, sizeof(szSwi) - 1, "%s(%x)", stropcalls[pi->opcode], (ruint32)pi->swi);
1014                 } else {
1015                         rvm_switable_t *switable;
1016                         ruint ntable = (ruint) RVM_SWI_TABLE(pi->swi);
1017                         ruint nswi = (ruint) RVM_SWI_NUM(pi->swi);
1018
1019                         if (ntable < r_array_length(vm->switables)) {
1020                                 switable = r_array_index(vm->switables, ntable, rvm_switable_t*);
1021                                 rvm_snprintf(szSwi, sizeof(szSwi) - 1, "(%s)",  switable[nswi].name ? switable[nswi].name : "unknown");
1022                         }
1023                 }
1024                 if ((ret = rvm_snprintf(str, sz, "%16s   ", szSwi)) < 0)
1025                         return ret;
1026         } else {
1027                 if ((ret = rvm_snprintf(str, sz, "%16s   ", stropcalls[pi->opcode])) < 0)
1028                         return ret;
1029         }
1030         str += ret;
1031         sz -= ret;
1032         
1033         if ((ret = rvm_asm_dump_reg_to_str(pi->op1, str, sz)) < 0)
1034                 return ret;
1035         str += ret;
1036         sz -= ret;
1037                 
1038         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1039                 return ret;
1040         str += ret;
1041         sz -= ret;
1042
1043         if ((ret = rvm_asm_dump_reg_to_str(pi->op2, str, sz)) < 0)
1044                 return ret;
1045         str += ret;
1046         sz -= ret;
1047                 
1048         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1049                 return ret;
1050         str += ret;
1051         sz -= ret;
1052
1053         if ((ret = rvm_asm_dump_reg_to_str(pi->op3, str, sz)) < 0)
1054                 return ret;
1055         str += ret;
1056         sz -= ret;
1057                 
1058         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1059                 return ret;
1060         str += ret;
1061         sz -= ret;
1062
1063         if (pi->type == RVM_DTYPE_DOUBLE) {
1064                 if ((ret = rvm_snprintf(str, sz, "%f  ", pi->data.d)) < 0)
1065                         return ret;
1066         } else if (pi->type == RVM_DTYPE_LONG) {
1067                 if ((ret = rvm_snprintf(str, sz, "%ld  ", (long)pi->data.u)) < 0)
1068                         return ret;
1069         } else {
1070                 if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)pi->data.u)) < 0)
1071                         return ret;
1072         }
1073
1074         str += ret;
1075         sz -= ret;
1076
1077         return size - sz;
1078 }
1079
1080
1081 void rvm_asm_dump(rvm_asmins_t *pi, ruint count)
1082 {
1083         char buffer[256];
1084         while (count) {
1085                 rvm_asm_dump_pi_to_str(NULL, pi, buffer, sizeof(buffer));
1086                 rvm_printf("%s\n", buffer);
1087                 ++pi;
1088                 --count;
1089         }
1090 }
1091
1092
1093 static void rvm_cpu_dumpregs(rvm_asmins_t *pi, rvmcpu_t *vm)
1094 {
1095     int ret;
1096         char buffer[1024];
1097         
1098         ret = rvm_asm_dump_pi_to_str(vm, pi, buffer, sizeof(buffer));
1099         if (ret < 0)
1100                 return;
1101     ret = rvm_snprintf(buffer + ret, sizeof(buffer) - ret, "                                                                                        ");
1102         buffer[50] = '\0';
1103         rvm_printf("%s", buffer);
1104
1105         rvm_printf("0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, FP=%ld, SP=%ld, LR=%ld, PC=%ld, DA=0x%lx, S( %c%c%c%c )",
1106                 RVM_CPUREG_GETU(vm, 0), RVM_CPUREG_GETU(vm, 1), RVM_CPUREG_GETU(vm, 2), RVM_CPUREG_GETU(vm, 3),
1107                 RVM_CPUREG_GETU(vm, 4), RVM_CPUREG_GETU(vm, 5), RVM_CPUREG_GETU(vm, 6), RVM_CPUREG_GETU(vm, 7),
1108                 RVM_CPUREG_GETU(vm, 8), (long int)RVM_CPUREG_GETU(vm, FP), (long int)RVM_CPUREG_GETU(vm, SP),
1109                 (long int)RVM_CPUREG_GETU(vm, LR), (long int)RVM_CPUREG_GETU(vm, PC), RVM_CPUREG_GETU(vm, DA),
1110                 vm->status & RVM_STATUS_V ? 'V' : '_',
1111                 vm->status & RVM_STATUS_C ? 'C' : '_',
1112                 vm->status & RVM_STATUS_N ? 'N' : '_',
1113                 vm->status & RVM_STATUS_Z ? 'Z' : '_');
1114         rvm_printf("\n");
1115 }
1116
1117
1118 static void rvm_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
1119 {
1120         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
1121         rvmreg_t tmp;
1122
1123         RVM_REG_CLEAR(&tmp);
1124         RVM_REG_SETTYPE(&tmp, type);
1125         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, RVM_CPUREG_PTR(cpu, ins->op1), RVM_CPUREG_PTR(cpu, ins->op2), &tmp);
1126 }
1127
1128
1129 static void rvm_op_type(rvmcpu_t *cpu, rvm_asmins_t *ins)
1130 {
1131         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETTYPE(cpu, ins->op2);
1132
1133         RVM_CPUREG_SETU(cpu, ins->op1, type);
1134 }
1135
1136
1137 static void rvm_op_settype(rvmcpu_t *cpu, rvm_asmins_t *ins)
1138 {
1139         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op2);
1140
1141         RVM_CPUREG_SETTYPE(cpu, ins->op1, type);
1142 }
1143
1144
1145 static void rvm_op_emov(rvmcpu_t *cpu, rvm_asmins_t *ins)
1146 {
1147         rvm_op_mov(cpu, ins);
1148 }
1149
1150
1151 static void rvm_op_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1152 {
1153         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1154         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1155
1156         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_ADD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1157 }
1158
1159
1160 static void rvm_op_esub(rvmcpu_t *cpu, rvm_asmins_t *ins)
1161 {
1162         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1163         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1164
1165         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1166 }
1167
1168
1169 static void rvm_op_emul(rvmcpu_t *cpu, rvm_asmins_t *ins)
1170 {
1171         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1172         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1173
1174         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_MUL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1175 }
1176
1177
1178 static void rvm_op_ediv(rvmcpu_t *cpu, rvm_asmins_t *ins)
1179 {
1180         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1181         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1182
1183         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_DIV, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1184 }
1185
1186
1187 static void rvm_op_emod(rvmcpu_t *cpu, rvm_asmins_t *ins)
1188 {
1189         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1190         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1191
1192         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_MOD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1193 }
1194
1195
1196 static void rvm_op_elsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
1197 {
1198         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1199         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1200
1201         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1202 }
1203
1204
1205 static void rvm_op_elsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1206 {
1207         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1208         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1209
1210         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1211 }
1212
1213
1214 static void rvm_op_elsru(rvmcpu_t *cpu, rvm_asmins_t *ins)
1215 {
1216         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1217         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1218
1219         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSRU, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1220 }
1221
1222
1223 static void rvm_op_eand(rvmcpu_t *cpu, rvm_asmins_t *ins)
1224 {
1225         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1226         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1227
1228         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_AND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1229 }
1230
1231
1232 static void rvm_op_eorr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1233 {
1234         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1235         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1236
1237         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_OR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1238 }
1239
1240
1241 static void rvm_op_exor(rvmcpu_t *cpu, rvm_asmins_t *ins)
1242 {
1243         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1244         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1245
1246         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_XOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1247 }
1248
1249
1250 static void rvm_op_enot(rvmcpu_t *cpu, rvm_asmins_t *ins)
1251 {
1252         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1253
1254         rvm_opmap_invoke_unary_handler(cpu->opmap, RVM_OPID_NOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
1255 }
1256
1257
1258 static void rvm_op_eland(rvmcpu_t *cpu, rvm_asmins_t *ins)
1259 {
1260         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1261         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1262
1263         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LOGICAND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1264 }
1265
1266
1267 static void rvm_op_elor(rvmcpu_t *cpu, rvm_asmins_t *ins)
1268 {
1269         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1270         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1271
1272         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LOGICOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1273 }
1274
1275
1276 static void rvm_op_elnot(rvmcpu_t *cpu, rvm_asmins_t *ins)
1277 {
1278         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1279
1280         rvm_opmap_invoke_unary_handler(cpu->opmap, RVM_OPID_LOGICNOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
1281 }
1282
1283
1284 static void rvm_op_eeq(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_EQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1290 }
1291
1292
1293 static void rvm_op_enoteq(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_NOTEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1299 }
1300
1301
1302 static void rvm_op_egreat(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_GREATER, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1308 }
1309
1310
1311 static void rvm_op_egreateq(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_GREATEREQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1317 }
1318
1319
1320 static void rvm_op_elesseq(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_LESSEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1326 }
1327
1328
1329 static void rvm_op_eless(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_LESS, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1335 }
1336
1337
1338 static void rvm_op_ecmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
1339 {
1340         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1341         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1342
1343         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMP, cpu, NULL, arg1, arg2);
1344 }
1345
1346
1347 static void rvm_op_ecmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
1348 {
1349         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1350         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1351
1352         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMN, cpu, NULL, arg1, arg2);
1353 }
1354
1355
1356 static void rvm_op_allocstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1357 {
1358
1359         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1360         rstring_t *s = r_string_create_strsize((const rchar*)RVM_CPUREG_GETP(cpu, ins->op2), RVM_CPUREG_GETU(cpu, ins->op3));
1361         if (!s) {
1362                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1363         }
1364         rvm_gc_add(cpu->gc, (robject_t*)s);
1365         rvm_reg_setstring(arg1, s);
1366 }
1367
1368
1369 static void rvm_op_allocarr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1370 {
1371         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1372         ruint size = RVM_CPUREG_GETU(cpu, ins->op2);
1373         rcarray_t *a = r_carray_create_rvmreg();
1374         if (!a) {
1375                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1376         }
1377         r_carray_setlength(a, size);
1378         rvm_gc_add(cpu->gc, (robject_t*)a);
1379         rvm_reg_setarray(arg1, (robject_t*)a);
1380 }
1381
1382
1383 static void rvm_op_addra(rvmcpu_t *cpu, rvm_asmins_t *ins)
1384 {
1385         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1386         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1387         rvmreg_t tmp = rvm_reg_create_long(0);
1388         rcarray_t *a = RVM_REG_GETP(arg2);
1389         rlong index;
1390
1391         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1392         index = RVM_REG_GETL(&tmp);
1393
1394         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY || index < 0) {
1395                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1396         }
1397         RVM_REG_CLEAR(arg1);
1398         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
1399         RVM_REG_SETP(arg1, r_carray_slot_expand(a, index));
1400 }
1401
1402
1403 static void rvm_op_elda(rvmcpu_t *cpu, rvm_asmins_t *ins)
1404 {
1405         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1406         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1407         ruint index = RVM_CPUREG_GETU(cpu, ins->op3);
1408         rcarray_t *a = RVM_REG_GETP(arg2);
1409
1410         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1411                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1412         }
1413         *arg1 = *((rvmreg_t*)r_carray_slot_expand(a, index));
1414 }
1415
1416
1417 static void rvm_op_esta(rvmcpu_t *cpu, rvm_asmins_t *ins)
1418 {
1419         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1420         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1421         ruint index = RVM_CPUREG_GETU(cpu, ins->op3);
1422         rcarray_t *a = RVM_REG_GETP(arg2);
1423
1424         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1425                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1426         }
1427         r_carray_replace(a, index, arg1);
1428 }
1429
1430
1431 static void rvm_op_abort(rvmcpu_t *cpu, rvm_asmins_t *ins)
1432 {
1433         RVM_ABORT(cpu, RVM_CPUREG_GETU(cpu, ins->op1));
1434 }
1435
1436 #if 0
1437 static void rvm_op_elds(rvmcpu_t *cpu, rvm_asmins_t *ins)
1438 {
1439         ruint index = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
1440         RVM_CPUREG_SET(cpu, ins->op1, *RVM_STACK_ADDR(cpu, index));
1441 }
1442
1443
1444 static void rvm_op_ests(rvmcpu_t *cpu, rvm_asmins_t *ins)
1445 {
1446         ruint index = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
1447         *RVM_STACK_ADDR(cpu, index) = RVM_CPUREG_GET(cpu, ins->op1);
1448 }
1449 #endif
1450
1451 static rvm_cpu_op ops[] = {
1452         rvm_op_exit,            // RVM_EXT
1453         rvm_op_abort,           // RVM_ABORT
1454         rvm_op_prn,                     // RVM_PRN
1455         rvm_op_asr,                     // RVM_ASR
1456         rvm_op_swi,                     // RVM_SWI
1457         rvm_op_swiid,           // RVM_SWIID
1458         rvm_op_call,            // RVM_CALL
1459         rvm_op_mov,                     // RVM_MOV
1460         rvm_op_inc,                     // RVM_INC
1461         rvm_op_dec,                     // RVM_DEC
1462         rvm_op_add,                     // RVM_ADD
1463         rvm_op_adds,            // RVM_ADDS
1464         rvm_op_adc,                     // RVM_ADC
1465         rvm_op_and,                     // RVM_AND
1466         rvm_op_bic,                     // RVM_BIC
1467         rvm_op_clz,                     // RVM_CLZ
1468         rvm_op_cmn,                     // RVM_CMN
1469         rvm_op_xor,                     // RVM_XOR
1470         rvm_op_sub,                     // RVM_SUB
1471         rvm_op_subs,            // RVM_SUBS
1472         rvm_op_sbc,                     // RVM_SBC
1473         rvm_op_mul,                     // RVM_MUL
1474         rvm_op_mls,                     // RVM_MLS
1475         rvm_op_muls,            // RVM_MULS
1476         rvm_op_not,                     // RVM_NOT
1477         rvm_op_div,                     // RVM_DIV
1478         rvm_op_dvs,                     // RVM_DVS
1479         rvm_op_divs,            // RVM_DIVS
1480         rvm_op_mod,                     // RVM_MOD
1481         rvm_op_mods,            // RVM_MODS
1482         rvm_op_bx,                      // RVM_BX
1483         rvm_op_bl,                      // RVM_BL
1484         rvm_op_b,                       // RVM_B
1485         rvm_op_str,                     // RVM_STR
1486         rvm_op_strp,            // RVM_STRP
1487         rvm_op_strb,            // RVM_STRB
1488         rvm_op_strh,            // RVM_STRH
1489         rvm_op_strw,            // RVM_STRW
1490         rvm_op_strr,            // RVM_STRR
1491         rvm_op_ldr,                     // RVM_LDR
1492         rvm_op_ldrp,            // RVM_LDRP
1493         rvm_op_ldrb,            // RVM_LDRB
1494         rvm_op_ldrh,            // RVM_LDRH
1495         rvm_op_ldrw,            // RVM_LDRW
1496         rvm_op_ldrr,            // RVM_LDRR
1497         rvm_op_clrr,            // RVM_CLRR
1498         rvm_op_lsl,                     // RVM_LSL
1499         rvm_op_lsr,                     // RVM_LSR
1500         rvm_op_lsrs,            // RVM_LSRS
1501         rvm_op_stm,                     // RVM_STM
1502         rvm_op_ldm,                     // RVM_LDM
1503         rvm_op_sts,                     // RVM_STS
1504         rvm_op_lds,                     // RVM_LDS
1505         rvm_op_orr,                     // RVM_ORR
1506         rvm_op_push,            // RVM_PUSH
1507         rvm_op_pop,                     // RVM_POP
1508         rvm_op_cmp,                     // RVM_CMP
1509         rvm_op_nop,                     // RVM_NOP
1510         rvm_op_beq,                     // RVM_BEQ
1511         rvm_op_bneq,            // RVM_BNEQ
1512         rvm_op_bleq,            // RVM_BLEQ
1513         rvm_op_bgeq,            // RVM_BGEQ
1514         rvm_op_bles,            // RVM_BLES
1515         rvm_op_bgre,            // RVM_BGRE
1516         rvm_op_ret,                     // RVM_RET
1517         rvm_op_ror,                     // RVM_ROR
1518         rvm_op_pushm,           // RVM_PUSHM
1519         rvm_op_popm,            // RVM_POPM
1520         rvm_op_tst,             // RVM_TST
1521         rvm_op_teq,             // RVM_TEQ
1522         rvm_op_clr,             // RVM_CLR
1523         rvm_op_addrs,           // RVM_ADDRS
1524
1525 /* Extended VM instructions */
1526         rvm_op_cast,            // RVM_CAST
1527         rvm_op_type,            // RVM_TYPE
1528         rvm_op_settype,         // RVM_SETTYPE
1529         rvm_op_emov,            // RVM_EMOV
1530         rvm_op_eadd,            // RVM_EADD
1531         rvm_op_esub,            // RVM_ESUB
1532         rvm_op_emul,            // RVM_EMUL
1533         rvm_op_ediv,            // RVM_EDIV
1534         rvm_op_emod,            // RVM_MOD
1535         rvm_op_elsl,            // RVM_ELSL
1536         rvm_op_elsr,            // RVM_ELSR
1537         rvm_op_elsru,           // RVM_ELSRU
1538         rvm_op_eand,            // RVM_EAND
1539         rvm_op_eorr,            // RVM_EORR
1540         rvm_op_exor,            // RVM_EXOR
1541         rvm_op_enot,            // RVM_ENOT
1542
1543         rvm_op_eland,           // RVM_ELAND
1544         rvm_op_elor,            // RVM_ELOR
1545         rvm_op_elnot,           // RVM_ELNOT
1546         rvm_op_eeq,                     // RVM_EEQ
1547         rvm_op_enoteq,          // RVM_ENOTEQ
1548         rvm_op_egreat,          // RVM_EGREAT
1549         rvm_op_egreateq,        // RVM_EGREATEQ
1550         rvm_op_eless,           // RVM_ELESS
1551         rvm_op_elesseq,         // RVM_ELESSEQ
1552         rvm_op_ecmp,            // RVM_ECMP
1553         rvm_op_ecmn,            // RVM_ECMN
1554         rvm_op_allocstr,        // RVM_ALLOCSTR
1555         rvm_op_allocarr,        // RVM_ALLOCARR
1556         rvm_op_addra,           // RVM_ADDRA
1557         rvm_op_elda,            // RVM_ELDA
1558         rvm_op_esta,            // RVM_ESTA
1559         (void*) 0,
1560         (void*) 0,
1561         (void*) 0,
1562         (void*) 0,
1563         (void*) 0,
1564         (void*) 0,
1565         (void*) 0,
1566         (void*) 0,
1567         
1568 };
1569
1570
1571 rvmcpu_t *rvm_cpu_create()
1572 {
1573         rvmcpu_t *cpu;
1574
1575         cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
1576         if (!cpu)
1577                 return ((void*)0);
1578         r_memset(cpu, 0, sizeof(*cpu));
1579         cpu->switables = r_array_create(sizeof(rvm_switable_t*));
1580 //      cpu->stack = r_carray_create(sizeof(rvmreg_t));
1581         cpu->stack = r_malloc(4 * 1024 *sizeof(rvmreg_t));
1582         cpu->data = r_carray_create(sizeof(rvmreg_t));
1583         cpu->opmap = rvm_opmap_create();
1584         cpu->gc = rvm_gc_create();
1585         rvm_op_binary_init(cpu->opmap);
1586         rvm_op_cast_init(cpu->opmap);
1587         rvm_op_not_init(cpu->opmap);
1588         rvm_op_logicnot_init(cpu->opmap);
1589
1590         return cpu;
1591 }
1592
1593
1594 void rvm_cpu_destroy(rvmcpu_t *cpu)
1595 {
1596         rvm_gc_deallocate_all(cpu->gc);
1597         rvm_gc_destroy(cpu->gc);
1598         r_object_destroy((robject_t*)cpu->switables);
1599 //      r_object_destroy((robject_t*)cpu->stack);
1600         r_free(cpu->stack);
1601         r_object_destroy((robject_t*)cpu->data);
1602         rvm_opmap_destroy(cpu->opmap);
1603         r_free(cpu);
1604 }
1605
1606
1607 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1608 {
1609         rvm_asmins_t *pi;
1610         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1611         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1612
1613         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1614         cpu->abort = 0;
1615         cpu->error = 0;
1616         do {
1617                 pi = RVM_REG_GETIP(regpc);
1618                 if (pi->da) {
1619                         if (pi->type == RVM_DTYPE_DOUBLE) {
1620                                 RVM_REG_SETD(regda, pi->data.d);
1621                         } else {
1622                                 RVM_REG_SETU(regda, pi->data.u);
1623                         }
1624                         RVM_REG_SETTYPE(regda, pi->type);
1625                         RVM_REG_ASSIGNFLAGS(regda, (pi->type >= RVM_DTYPE_STRING) ? RVM_INFOBIT_ROBJECT : 0);
1626                 }
1627                 ops[pi->opcode](cpu, pi);
1628                 RVM_REG_INCIP(regpc, 1);
1629         } while (!cpu->abort);
1630         if (cpu->error)
1631                 return -1;
1632         return 0;
1633 }
1634
1635
1636 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1637 {
1638         rvm_asmins_t *pi;
1639         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1640         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1641
1642         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1643         cpu->abort = 0;
1644         cpu->error = 0;
1645         do {
1646                 pi = RVM_REG_GETIP(regpc);
1647                 if (pi->da) {
1648                         if (pi->type == RVM_DTYPE_DOUBLE) {
1649                                 RVM_REG_SETD(regda, pi->data.d);
1650                         } else {
1651                                 RVM_REG_SETU(regda, pi->data.u);
1652                         }
1653                         RVM_REG_SETTYPE(regda, pi->type);
1654                         RVM_REG_ASSIGNFLAGS(regda, (pi->type >= RVM_DTYPE_STRING) ? RVM_INFOBIT_ROBJECT : 0);
1655                 }
1656                 ops[pi->opcode](cpu, pi);
1657                 rvm_cpu_dumpregs(pi, cpu);
1658                 RVM_REG_INCIP(regpc, 1);
1659         } while (!cpu->abort);
1660         if (cpu->error)
1661                 return -1;
1662         return 0;
1663 }
1664
1665
1666 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname, rsize_t size)
1667 {
1668         rint ntable, nswi;
1669         rvm_switable_t *swientry;
1670
1671         for (ntable = 0; ntable < r_array_length(cpu->switables); ntable++) {
1672                 swientry = r_array_index(cpu->switables, ntable, rvm_switable_t*);
1673                 for (nswi = 0; swientry[nswi].name; nswi++) {
1674                         if (r_strncmp(swientry[nswi].name, swiname, size) == 0 && r_strlen(swientry[nswi].name) == size)
1675                                 return (rint)RVM_SWI_ID(ntable, nswi);
1676                 }
1677         }
1678
1679         return -1;
1680 }
1681
1682
1683 rint rvm_cpu_getswi_s(rvmcpu_t *cpu, const rchar *swiname)
1684 {
1685         return rvm_cpu_getswi(cpu, swiname, r_strlen(swiname));
1686 }
1687
1688
1689 rint rvm_cpu_addswitable(rvmcpu_t *cpu, rvm_switable_t *switable)
1690 {
1691         rint nswi;
1692
1693         for (nswi = 0; switable[nswi].name; nswi++) {
1694                 if (rvm_cpu_getswi_s(cpu, switable[nswi].name) >= 0)
1695                         return -1;
1696         }
1697
1698         return r_array_add(cpu->switables, &switable);
1699 }
1700
1701
1702 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
1703 {
1704         rvm_asmins_t a;
1705
1706         r_memset(&a, 0, sizeof(a));
1707         a.opcode = (ruint8) opcode;
1708         a.op1 = (ruint8)op1;
1709         a.op2 = (ruint8)op2;
1710         a.op3 = (ruint8)op3;
1711         a.data.u = (rword)data;
1712         a.type = RVM_DTYPE_POINTER;
1713         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1714                 a.da = 1;
1715         return a;
1716 }
1717
1718
1719 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
1720 {
1721         rvm_asmins_t a;
1722
1723         r_memset(&a, 0, sizeof(a));
1724         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1725         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1726         a.op1 = (ruint8)op1;
1727         a.op2 = (ruint8)op2;
1728         a.op3 = (ruint8)op3;
1729         a.data.u = (rword)data;
1730         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1731                 a.da = 1;
1732         return a;
1733 }
1734
1735
1736 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data)
1737 {
1738         rvm_asmins_t a;
1739
1740         r_memset(&a, 0, sizeof(a));
1741         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1742         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1743         a.op1 = (ruint8)op1;
1744         a.op2 = (ruint8)op2;
1745         a.op3 = (ruint8)op3;
1746         a.data.u = (rword)data;
1747         a.type = RVM_DTYPE_LONG;
1748         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1749                 a.da = 1;
1750         return a;
1751 }
1752
1753
1754 rvm_asmins_t rvm_asmb(rword opcode, rword op1, rword op2, rword op3, rword data)
1755 {
1756         rvm_asmins_t a;
1757
1758         r_memset(&a, 0, sizeof(a));
1759         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1760         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1761         a.op1 = (ruint8)op1;
1762         a.op2 = (ruint8)op2;
1763         a.op3 = (ruint8)op3;
1764         a.data.u = (rword)(data ? 1 : 0);
1765         a.type = RVM_DTYPE_BOOLEAN;
1766         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1767                 a.da = 1;
1768         return a;
1769 }
1770
1771
1772 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data)
1773 {
1774         rvm_asmins_t a;
1775
1776         r_memset(&a, 0, sizeof(a));
1777         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1778         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1779         a.op1 = (ruint8)op1;
1780         a.op2 = (ruint8)op2;
1781         a.op3 = (ruint8)op3;
1782         a.data.d = data;
1783         a.type = RVM_DTYPE_DOUBLE;
1784         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1785                 a.da = 1;
1786
1787         return a;
1788 }
1789
1790
1791 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1792 {
1793         rvm_asmins_t a;
1794
1795         r_memset(&a, 0, sizeof(a));
1796         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1797         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1798         a.op1 = (ruint8)op1;
1799         a.op2 = (ruint8)op2;
1800         a.op3 = (ruint8)op3;
1801         a.data.u = (rword)pReloc;
1802         a.flags = RVM_ASMINS_RELOC | RVM_ASMINS_RELOCPTR;
1803         a.da = 1;
1804
1805         return a;
1806 }
1807
1808
1809 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1810 {
1811         rvm_asmins_t a;
1812
1813         r_memset(&a, 0, sizeof(a));
1814         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1815         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1816         a.op1 = (ruint8)op1;
1817         a.op2 = (ruint8)op2;
1818         a.op3 = (ruint8)op3;
1819         a.data.u = (rword)pReloc;
1820         a.flags = RVM_ASMINS_RELOC;
1821         a.da = 1;
1822
1823         return a;
1824 }
1825
1826
1827 void rvm_relocate(rvm_asmins_t *code, rsize_t size)
1828 {
1829         rvm_asmins_t *reloc;
1830         rulong relocindex;
1831         rulong off;
1832
1833         for (off = 0; off < size; off++, code++) {
1834                 if (code->flags & RVM_ASMINS_RELOC) {
1835                         if (code->flags & RVM_ASMINS_RELOCPTR) {
1836                                 reloc = *((rvm_asmins_t **)code->data.u);
1837                                 code->data.u = reloc - code;
1838                         } else {
1839                                 relocindex = *((rulong *)code->data.u);
1840                                 code->data.u = relocindex - off;
1841                         }
1842                         code->flags &= ~(RVM_ASMINS_RELOCPTR | RVM_ASMINS_RELOC);
1843                 }
1844         }
1845 }
1846