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