RPA Toolkit
dev
[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 <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include "rmem.h"
26 #include "rstring.h"
27 #include "rvmcpu.h"
28
29
30 static const char *stropcalls[] = {
31         "RVM_EXT",
32         "RVM_ASR",
33         "RVM_SWI",
34         "RVM_MOV",
35         "RVM_ADD",
36         "RVM_ADDS",
37         "RVM_ADC",
38         "RVM_AND",
39         "RVM_BIC",
40         "RVM_CLZ",
41         "RVM_CMN",
42         "RVM_EOR",
43         "RVM_SUB",
44         "RVM_SUBS",
45         "RVM_SBC",
46         "RVM_MUL",
47         "RVM_MLS",
48         "RVM_MULS",
49         "RVM_NOT",
50         "RVM_DIV",
51         "RVM_DVS",
52         "RVM_DIVS",
53         "RVM_BL",
54         "RVM_B",
55         "RVM_STR",
56         "RVM_STRP",
57         "RVM_STRB",
58         "RVM_STRH",
59         "RVM_LDR",
60         "RVM_LDRP",
61         "RVM_LDRB",
62         "RVM_LDRH",
63         "RVM_LSL",
64         "RVM_LSR",
65         "RVM_STM",
66         "RVM_LDM",
67         "RVM_STS",
68         "RVM_LDS",
69         "RVM_ORR",
70         "RVM_PUSH",
71         "RVM_POP",
72         "RVM_CMP",
73         "RVM_NOP",
74         "RVM_BEQ",
75         "RVM_BNEQ",
76         "RVM_BLEQ",
77         "RVM_BGEQ",
78         "RVM_BLES",
79         "RVM_BGRE",
80         "RVM_RET",
81         "RVM_ROR",
82         "RVM_PUSHM",
83         "RVM_POPM",     
84         "RVM_TST",      
85         "RVM_TEQ",      
86 };
87
88
89 static void rvm_op_b(rvm_cpu_t *cpu, rvm_asmins_t *ins)
90 {
91         RVM_INC_REGM(cpu, PC, RVM_GET_REGU(cpu, ins->op1) - 1);
92 }
93
94
95 static void rvm_op_beq(rvm_cpu_t *cpu, rvm_asmins_t *ins)
96 {
97         if ((cpu->status & RVM_STATUS_Z))
98                 RVM_SET_REGM(cpu, PC, RVM_GET_REGM(cpu, PC) + RVM_GET_REGU(cpu, ins->op1) - 1);
99 }
100
101
102 static void rvm_op_bneq(rvm_cpu_t *cpu, rvm_asmins_t *ins)
103 {
104         if ((cpu->status & RVM_STATUS_Z) == 0)
105                 RVM_SET_REGM(cpu, PC, RVM_GET_REGM(cpu, PC) + RVM_GET_REGU(cpu, ins->op1) - 1);
106 }
107
108
109 static void rvm_op_bleq(rvm_cpu_t *cpu, rvm_asmins_t *ins)
110 {
111         if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z))
112                 RVM_SET_REGM(cpu, PC, RVM_GET_REGM(cpu, PC) + RVM_GET_REGU(cpu, ins->op1) - 1);
113 }
114
115 static void rvm_op_bgeq(rvm_cpu_t *cpu, rvm_asmins_t *ins)
116 {
117         if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1)
118                 RVM_SET_REGM(cpu, PC, RVM_GET_REGM(cpu, PC) + RVM_GET_REGU(cpu, ins->op1) - 1);
119 }
120
121
122 static void rvm_op_bles(rvm_cpu_t *cpu, rvm_asmins_t *ins)
123 {
124         if ((cpu->status & RVM_STATUS_N))
125                 RVM_SET_REGM(cpu, PC, RVM_GET_REGM(cpu, PC) + RVM_GET_REGU(cpu, ins->op1) - 1);
126 }
127
128
129 static void rvm_op_bgre(rvm_cpu_t *cpu, rvm_asmins_t *ins)
130 {
131         if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0)
132                 RVM_SET_REGM(cpu, PC, RVM_GET_REGU(cpu, PC) + RVM_GET_REGU(cpu, ins->op1) - 1);
133 }
134
135
136 static void rvm_op_bl(rvm_cpu_t *cpu, rvm_asmins_t *ins)
137 {
138         RVM_SET_REGM(cpu, LR, RVM_GET_REGM(cpu, PC));
139         RVM_INC_REGM(cpu, PC, RVM_GET_REGU(cpu, ins->op1) - 1);
140 }
141
142
143 static void rvm_op_exit(rvm_cpu_t *cpu, rvm_asmins_t *ins)
144 {
145
146 }
147
148
149 static void rvm_op_mov(rvm_cpu_t *cpu, rvm_asmins_t *ins)
150 {
151         RVM_SET_REG(cpu, ins->op1, RVM_GET_REG(cpu, ins->op2));
152 }
153
154
155 static void rvm_op_ldr(rvm_cpu_t *cpu, rvm_asmins_t *ins)
156 {
157         RVM_SET_REGU(cpu, ins->op1, *((rword*)RVM_GET_REGU(cpu, ins->op2)));
158         
159 }
160
161
162 static void rvm_op_ldrp(rvm_cpu_t *cpu, rvm_asmins_t *ins)
163 {
164         RVM_SET_REGU(cpu, ins->op1, *((rpointer*)RVM_GET_REGU(cpu, ins->op2)));
165 }
166
167
168 static void rvm_op_ldrb(rvm_cpu_t *cpu, rvm_asmins_t *ins)
169 {
170         RVM_SET_REGU(cpu, ins->op1, *((ruint8*)RVM_GET_REGU(cpu, ins->op2)));
171 }
172
173
174 static void rvm_op_ldrh(rvm_cpu_t *cpu, rvm_asmins_t *ins)
175 {
176         RVM_SET_REGU(cpu, ins->op1, *((ruint16*)RVM_GET_REGU(cpu, ins->op2)));
177 }
178
179
180 static void rvm_op_str(rvm_cpu_t *cpu, rvm_asmins_t *ins)
181 {
182         *((rword*)RVM_GET_REGP(cpu, ins->op2)) = RVM_GET_REGU(cpu, ins->op1);
183 }
184
185
186 static void rvm_op_strp(rvm_cpu_t *cpu, rvm_asmins_t *ins)
187 {
188         *((rpointer*)RVM_GET_REGP(cpu, ins->op2)) = (rpointer)RVM_GET_REGP(cpu, ins->op1);
189 }
190
191
192 static void rvm_op_strb(rvm_cpu_t *cpu, rvm_asmins_t *ins)
193 {
194         *((ruint8*)RVM_GET_REGP(cpu, ins->op2)) = (ruint8)RVM_GET_REGU(cpu, ins->op1);
195 }
196
197
198 static void rvm_op_strh(rvm_cpu_t *cpu, rvm_asmins_t *ins)
199 {
200         *((ruint16*)RVM_GET_REGP(cpu, ins->op2)) = (ruint16)RVM_GET_REGU(cpu, ins->op1);
201         
202 }
203
204
205 static void rvm_op_adds(rvm_cpu_t *cpu, rvm_asmins_t *ins)
206 {
207         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
208         
209         res = op2 + op3;
210         RVM_SET_REGU(cpu, ins->op1, res);
211         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
212         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
213         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
214         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
215                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
216 }
217
218
219 static void rvm_op_adc(rvm_cpu_t *cpu, rvm_asmins_t *ins)
220 {
221         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
222         
223         res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
224         RVM_SET_REGU(cpu, ins->op1, res);
225         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
226         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
227         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
228         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
229                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
230 }
231
232
233 static void rvm_op_and(rvm_cpu_t *cpu, rvm_asmins_t *ins)
234 {
235         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
236         
237         res = op2 & op3;
238         RVM_SET_REGU(cpu, ins->op1, res);
239         RVM_STATUS_CLRALL(cpu);
240         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
241         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
242 }
243
244
245 static void rvm_op_orr(rvm_cpu_t *cpu, rvm_asmins_t *ins)
246 {
247         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
248         
249         res = op2 | op3;
250         RVM_SET_REGU(cpu, ins->op1, res);
251         RVM_STATUS_CLRALL(cpu);
252         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
253         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
254 }
255
256
257 static void rvm_op_lsl(rvm_cpu_t *cpu, rvm_asmins_t *ins)
258 {
259         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
260         
261         res = op2 << op3;
262         RVM_SET_REGU(cpu, ins->op1, res);
263         RVM_STATUS_CLRALL(cpu);
264         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
265         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
266 }
267
268
269 static void rvm_op_lsr(rvm_cpu_t *cpu, rvm_asmins_t *ins)
270 {
271         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
272         
273         res = op2 >> op3;
274         RVM_SET_REGU(cpu, ins->op1, res);
275         RVM_STATUS_CLRALL(cpu);
276         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
277 }
278
279
280 static void rvm_op_asr(rvm_cpu_t *cpu, rvm_asmins_t *ins)
281 {
282         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
283         
284         res = op2 >> op3;
285         res |= op2 & RVM_SIGN_BIT;
286         RVM_SET_REGU(cpu, ins->op1, res);
287         RVM_STATUS_CLRALL(cpu);
288         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
289         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
290 }
291
292
293 static void rvm_op_ror(rvm_cpu_t *cpu, rvm_asmins_t *ins)
294 {
295         ruint i;
296         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
297         
298         res = op2;
299         for (i = 0; i < op3; i++) {
300                 if (res & 1) {
301                         res >>= 1;
302                         res |= RVM_SIGN_BIT;
303                 } else {
304                         res >>= 1;
305                 }
306         }
307         RVM_SET_REGU(cpu, ins->op1, res);
308         RVM_STATUS_CLRALL(cpu);
309         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
310         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
311         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res & RVM_SIGN_BIT);
312 }
313
314
315 static void rvm_op_tst(rvm_cpu_t *cpu, rvm_asmins_t *ins)
316 {
317         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
318         
319         res = op2 & op3;
320         RVM_STATUS_CLRALL(cpu);
321         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
322         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
323 }
324
325
326 static void rvm_op_eor(rvm_cpu_t *cpu, rvm_asmins_t *ins)
327 {
328         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
329         
330         res = op2 ^ op3;
331         RVM_SET_REGU(cpu, ins->op1, res);
332         RVM_STATUS_CLRALL(cpu);
333         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
334         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
335 }
336
337
338 static void rvm_op_not(rvm_cpu_t *cpu, rvm_asmins_t *ins)
339 {
340         rword res, op2 = RVM_GET_REGU(cpu, ins->op2);
341         
342         res = ~op2;
343         RVM_SET_REGU(cpu, ins->op1, res);
344         RVM_STATUS_CLRALL(cpu);
345         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
346         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
347 }
348
349
350 static void rvm_op_teq(rvm_cpu_t *cpu, rvm_asmins_t *ins)
351 {
352         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
353         
354         res = op2 ^ op3;
355         RVM_STATUS_CLRALL(cpu);
356         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
357         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
358 }
359
360
361 static void rvm_op_bic(rvm_cpu_t *cpu, rvm_asmins_t *ins)
362 {
363         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
364         
365         res = op2 & ~op3;
366         RVM_SET_REGU(cpu, ins->op1, res);
367         RVM_STATUS_CLRALL(cpu);
368         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
369         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
370 }
371
372
373 static void rvm_op_clz(rvm_cpu_t *cpu, rvm_asmins_t *ins)
374 {
375         rword res, op2 = RVM_GET_REGU(cpu, ins->op2);
376         
377         for (res = RVM_REGISTER_BITS; op2; ) {
378                 op2 >>= 1;
379                 res -= 1;
380         }
381         RVM_SET_REGU(cpu, ins->op1, res);
382 }
383
384
385 static void rvm_op_add(rvm_cpu_t *cpu, rvm_asmins_t *ins)
386 {
387         RVM_SET_REGU(cpu, ins->op1, RVM_GET_REGU(cpu, ins->op2) + RVM_GET_REGU(cpu, ins->op3));
388 }
389
390
391 static void rvm_op_swi(rvm_cpu_t *cpu, rvm_asmins_t *ins)
392 {
393 //      rvm_cpu_swi *cbt = cpu->switable[RVM_CB_TABLE(RVM_GET_REGU(cpu, ins->op1))];
394 //      cbt[RVM_CB_OFFSET(RVM_GET_REGU(cpu, ins->op1))](cpu);
395
396         rvm_cpu_swi swi;
397         rvm_switable_t *switable;
398         ruint ntable = (ruint) RVM_SWI_TABLE(RVM_GET_REGU(cpu, ins->op1));
399         ruint nswi = (ruint) RVM_SWI_NUM(RVM_GET_REGU(cpu, ins->op1));
400
401         if (r_array_size(cpu->switables) <= ntable)
402                 RVM_ABORT(cpu, RVM_E_SWITABLE);
403         switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
404         swi = switable[nswi].op;
405         swi(cpu, ins);
406 }
407
408
409 static void rvm_op_sub(rvm_cpu_t *cpu, rvm_asmins_t *ins)
410 {
411         RVM_SET_REGU(cpu, ins->op1, RVM_GET_REGU(cpu, ins->op2) - RVM_GET_REGU(cpu, ins->op3));
412 }
413
414
415 static void rvm_op_subs(rvm_cpu_t *cpu, rvm_asmins_t *ins)
416 {
417         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
418         
419         res = op2 - op3;
420         RVM_SET_REGU(cpu, ins->op1, res);
421         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
422         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
423         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
424         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
425                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
426 }
427
428
429 static void rvm_op_sbc(rvm_cpu_t *cpu, rvm_asmins_t *ins)
430 {
431         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
432
433         res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
434         RVM_SET_REGU(cpu, ins->op1, res);
435         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
436         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
437         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
438         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
439                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
440 }
441
442
443 static void rvm_op_mul(rvm_cpu_t *cpu, rvm_asmins_t *ins)
444 {
445         RVM_SET_REGU(cpu, ins->op1, RVM_GET_REGU(cpu, ins->op2) * RVM_GET_REGU(cpu, ins->op3));
446 }
447
448
449 static void rvm_op_mls(rvm_cpu_t *cpu, rvm_asmins_t *ins)
450 {
451         rsword res;
452         rsword op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
453
454         res = (rsword)(op2 * op3);
455         RVM_SET_REGU(cpu, ins->op1, res);
456         /* TBD: Not sure how to update the RVM_STATUS_C */
457         RVM_STATUS_CLRALL(cpu);
458         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
459         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
460 }
461
462
463 static void rvm_op_muls(rvm_cpu_t *cpu, rvm_asmins_t *ins)
464 {
465         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
466         
467         res = op2 * op3;
468         RVM_SET_REGU(cpu, ins->op1, res);
469         RVM_STATUS_CLRALL(cpu);
470         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
471         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
472         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
473 }
474
475
476 static void rvm_op_div(rvm_cpu_t *cpu, rvm_asmins_t *ins)
477 {
478         if (!RVM_GET_REGU(cpu, ins->op3))
479                 RVM_ABORT(cpu, RVM_E_DIVZERO);
480
481         RVM_SET_REGU(cpu, ins->op1, RVM_GET_REGU(cpu, ins->op2) / RVM_GET_REGU(cpu, ins->op3));
482 }
483
484
485 static void rvm_op_divs(rvm_cpu_t *cpu, rvm_asmins_t *ins)
486 {
487         rword res, op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
488
489         if (!op3)
490                 RVM_ABORT(cpu, RVM_E_DIVZERO);
491         res = op2 / op3;
492         RVM_SET_REGU(cpu, ins->op1, res);
493         RVM_STATUS_CLRALL(cpu);
494         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
495         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
496 }
497
498
499 static void rvm_op_dvs(rvm_cpu_t *cpu, rvm_asmins_t *ins)
500 {
501         rsword res;
502         rsword op2 = RVM_GET_REGU(cpu, ins->op2), op3 = RVM_GET_REGU(cpu, ins->op3);
503
504         if (!op3)
505                 RVM_ABORT(cpu, RVM_E_DIVZERO);
506         res = (rsword)(op2 / op3);
507         RVM_SET_REGU(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_push(rvm_cpu_t *cpu, rvm_asmins_t *ins)
515 {
516         rword sp = RVM_GET_REGU(cpu, SP) + 1;
517
518         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_GET_REG(cpu, ins->op1));
519         RVM_SET_REGU(cpu, SP, sp);
520 }
521
522
523 static void rvm_op_sts(rvm_cpu_t *cpu, rvm_asmins_t *ins)
524 {
525         rword sp = RVM_GET_REGU(cpu, ins->op2) + RVM_GET_REGU(cpu, ins->op3);
526
527         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_GET_REG(cpu, ins->op1));
528 }
529
530
531 static void rvm_op_pushm(rvm_cpu_t *cpu, rvm_asmins_t *ins)
532 {
533         int n, i;
534         rword bits = RVM_GET_REGU(cpu, ins->op1);
535         rword sp = RVM_GET_REGU(cpu, SP);
536
537         for (i = 0, n = 0; bits && n < RLST; n++) {
538                 if (((rword)(1 << n)) & bits) {
539                         i += 1;
540                         sp += 1;
541                         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_GET_REG(cpu, n));
542                         bits &= ~(1<<n);
543                 }
544         }
545         RVM_SET_REGU(cpu, SP, RVM_GET_REGU(cpu, SP) + i);
546 }
547
548
549 static void rvm_op_pop(rvm_cpu_t *cpu, rvm_asmins_t *ins)
550 {
551         rword sp = RVM_GET_REGU(cpu, SP);
552
553         RVM_SET_REG(cpu, ins->op1, r_array_index(cpu->stack, sp, rvm_reg_t));
554         if (ins->op1 != SP)
555                 RVM_SET_REGU(cpu, SP, sp - 1);
556 }
557
558
559 static void rvm_op_popm(rvm_cpu_t *cpu, rvm_asmins_t *ins)
560 {
561         int n;
562         rword bits = RVM_GET_REGU(cpu, ins->op1);
563         rword sp = RVM_GET_REGU(cpu, SP);
564
565         for (n = RLST - 1; bits && n >= 0; n--) {
566                 if (((rword)(1 << n)) & bits) {
567                         RVM_SET_REG(cpu, n, r_array_index(cpu->stack, sp, rvm_reg_t));
568                         sp -= 1;
569                         bits &= ~(1<<n);
570                 }
571         }
572         if (!(((rword)(1 << SP)) & bits))
573                 RVM_SET_REGU(cpu, SP, sp);
574 }
575
576
577 static void rvm_op_lds(rvm_cpu_t *cpu, rvm_asmins_t *ins)
578 {
579         rword sp = RVM_GET_REGU(cpu, ins->op2) + RVM_GET_REGU(cpu, ins->op3);
580
581         RVM_SET_REG(cpu, ins->op1, r_array_index(cpu->stack, sp, rvm_reg_t));
582 }
583
584
585 static void rvm_op_stm(rvm_cpu_t *cpu, rvm_asmins_t *ins)
586 {
587         int n;
588         rword *dst = (rword*)   RVM_GET_REGU(cpu, ins->op1);
589         rword bits = RVM_GET_REGU(cpu, ins->op2);
590         
591         for (n = 0; bits && n < RLST; n++) {
592                 if (((rword)(1 << n)) & bits) {
593                         *dst = RVM_GET_REGU(cpu, n);
594                         dst += 1;
595                         bits &= ~(1<<n);
596                 }
597         }
598 }
599
600
601 static void rvm_op_ldm(rvm_cpu_t *cpu, rvm_asmins_t *ins)
602 {
603         int n;
604         rword *src = (rword*)RVM_GET_REGU(cpu, ins->op1);
605         rword bits = RVM_GET_REGU(cpu, ins->op2);
606
607         for (n = 0; bits && n < RLST; n++) {
608                 if (((rword)(1 << n)) & bits) {
609                         RVM_SET_REGU(cpu, n, *src);
610                         src += 1;
611                         bits &= ~(1<<n);
612                 }
613         }
614 }
615
616
617 static void rvm_op_cmp(rvm_cpu_t *cpu, rvm_asmins_t *ins)
618 {
619         rword op1 = RVM_GET_REGU(cpu, ins->op1), op2 = RVM_GET_REGU(cpu, ins->op2);
620         rword res = (rword)(op1 - op2);
621         
622         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op1 < op2);
623         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
624         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
625         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT) &&
626                                                         (res & RVM_SIGN_BIT) == (op1 & RVM_SIGN_BIT));
627 }
628
629
630 static void rvm_op_cmn(rvm_cpu_t *cpu, rvm_asmins_t *ins)
631 {
632         rword op1 = RVM_GET_REGU(cpu, ins->op1), op2 = RVM_GET_REGU(cpu, ins->op2);
633         rword res = (rword)(op1 + op2);
634         
635         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op1 || res < op2);
636         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
637         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
638         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT) &&
639                                                         (res & RVM_SIGN_BIT) != (op1 & RVM_SIGN_BIT));
640
641 }
642
643
644 static void rvm_op_nop(rvm_cpu_t *cpu, rvm_asmins_t *ins)
645 {
646 //      fprintf(stdout, "nop\n");
647 }
648
649
650 static void rvm_op_ret(rvm_cpu_t *cpu, rvm_asmins_t *ins)
651 {
652         RVM_SET_REGU(cpu, PC, RVM_GET_REGU(cpu, LR));   
653 }
654
655
656
657 static int rvm_vsnprintf(char *str, ruint size, const char *format, va_list ap)
658 {
659         return vsnprintf(str, size, format, ap);
660 }
661
662
663 static int rvm_snprintf(char *str, ruint size, const char *format, ...)
664 {
665         va_list ap;
666         int ret;
667
668         va_start(ap, format);
669         ret = rvm_vsnprintf(str, size, format, ap);
670         va_end(ap);
671         return ret;
672 }
673
674
675 static int rvm_printf(const char *format, ...)
676 {
677         va_list ap;
678         int ret;
679
680         va_start(ap, format);
681         ret = vfprintf(stdout, format, ap);
682         va_end(ap);
683         return ret;
684 }
685
686
687 int rvm_asm_dump_reg_to_str(unsigned char reg, char *str, ruint size)
688 {
689         int ret = 0;
690
691         if (reg == XX)
692                 ret = rvm_snprintf(str, size, "XX ");
693         else if (reg == FP)
694                 ret = rvm_snprintf(str, size, "FP ");
695         else if (reg == SP)
696                 ret = rvm_snprintf(str, size, "SP ");
697         else if (reg == LR)
698                 ret = rvm_snprintf(str, size, "LR ");
699         else if (reg == PC)
700                 ret = rvm_snprintf(str, size, "PC ");
701         else if (reg == DA)
702                 ret = rvm_snprintf(str, size, "DA ");
703         else if (reg >= 0 && reg < 10)
704                 ret = rvm_snprintf(str, size, "R%d ",  reg);
705         else if (reg >= 10)
706                 ret = rvm_snprintf(str, size, "R%d",  reg);
707
708         return ret;
709 }
710
711
712 int rvm_asm_dump_pi_to_str(rvm_asmins_t *pi, char *str, ruint size)
713 {
714         int ret = 0, sz = size;
715
716         if ((ret = rvm_snprintf(str, sz, "%10s   ", stropcalls[pi->opcode])) < 0)
717                 return ret;
718         str += ret;
719         sz -= ret;
720         
721         if ((ret = rvm_asm_dump_reg_to_str(pi->op1, str, sz)) < 0)
722                 return ret;
723         str += ret;
724         sz -= ret;
725                 
726         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
727                 return ret;
728         str += ret;
729         sz -= ret;
730
731         if ((ret = rvm_asm_dump_reg_to_str(pi->op2, str, sz)) < 0)
732                 return ret;
733         str += ret;
734         sz -= ret;
735                 
736         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
737                 return ret;
738         str += ret;
739         sz -= ret;
740
741         if ((ret = rvm_asm_dump_reg_to_str(pi->op3, str, sz)) < 0)
742                 return ret;
743         str += ret;
744         sz -= ret;
745                 
746         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
747                 return ret;
748         str += ret;
749         sz -= ret;
750
751         if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)RVM_REGU(&pi->data))) < 0)
752                 return ret;
753         str += ret;
754         sz -= ret;
755
756         return size - sz;
757 }
758
759
760 void rvm_asm_dump(rvm_asmins_t *pi, ruint count)
761 {
762         char buffer[256];
763         while (count) {
764                 rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
765                 rvm_printf("%s\n", buffer);
766                 ++pi;
767                 --count;
768         }
769 }
770
771
772 static void rvm_cpu_dumpregs(rvm_asmins_t *pi, rvm_cpu_t *vm)
773 {
774     int ret;
775         char buffer[1024];
776         
777         ret = rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
778         if (ret < 0)
779                 return;
780     ret = rvm_snprintf(buffer + ret, sizeof(buffer) - ret, "                                                                                        ");
781         buffer[50] = '\0';
782         rvm_printf("%s", buffer);
783
784         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 )",
785                 RVM_GET_REGU(vm, 0), RVM_GET_REGU(vm, 1), RVM_GET_REGU(vm, 2), RVM_GET_REGU(vm, 3),
786                 RVM_GET_REGU(vm, 4), RVM_GET_REGU(vm, 5), RVM_GET_REGU(vm, 6), RVM_GET_REGU(vm, 7),
787                 RVM_GET_REGU(vm, 8), (long int)RVM_GET_REGU(vm, FP), (long int)RVM_GET_REGU(vm, SP),
788                 (long int)RVM_GET_REGU(vm, LR), (long int)RVM_GET_REGU(vm, PC), RVM_GET_REGU(vm, DA),
789                 vm->status & RVM_STATUS_V ? 'V' : '_',
790                 vm->status & RVM_STATUS_C ? 'C' : '_',
791                 vm->status & RVM_STATUS_N ? 'N' : '_',
792                 vm->status & RVM_STATUS_Z ? 'Z' : '_');
793         rvm_printf("\n");
794 }
795
796
797 static rvm_cpu_op ops[] = {
798         rvm_op_exit,            // RVM_EXT
799         rvm_op_asr,                     // RVM_ASR
800         rvm_op_swi,                     // RVM_swi
801         rvm_op_mov,                     // RVM_MOV
802         rvm_op_add,                     // RVM_ADD
803         rvm_op_adds,            // RVM_ADDS
804         rvm_op_adc,                     // RVM_ADC
805         rvm_op_and,                     // RVM_AND
806         rvm_op_bic,                     // RVM_BIC
807         rvm_op_clz,                     // RVM_CLZ
808         rvm_op_cmn,                     // RVM_CMN
809         rvm_op_eor,                     // RVM_EOR
810         rvm_op_sub,                     // RVM_SUB
811         rvm_op_subs,            // RVM_SUBS
812         rvm_op_sbc,                     // RVM_SBC
813         rvm_op_mul,                     // RVM_MUL
814         rvm_op_mls,                     // RVM_MLS
815         rvm_op_muls,            // RVM_MULS
816         rvm_op_not,                     // RVM_NOT
817         rvm_op_div,                     // RVM_DIV
818         rvm_op_dvs,                     // RVM_DVS
819         rvm_op_divs,            // RVM_DIVS
820         rvm_op_bl,                      // RVM_BL
821         rvm_op_b,                       // RVM_B
822         rvm_op_str,                     // RVM_STR
823         rvm_op_strp,            // RVM_STRP
824         rvm_op_strb,            // RVM_STRB
825         rvm_op_strh,            // RVM_STRH
826         rvm_op_ldr,                     // RVM_LDR
827         rvm_op_ldrp,            // RVM_LDRP
828         rvm_op_ldrb,            // RVM_LDRB
829         rvm_op_ldrh,            // RVM_LDRH
830         rvm_op_lsl,                     // RVM_LSL
831         rvm_op_lsr,                     // RVM_LSR
832         rvm_op_stm,                     // RVM_STM
833         rvm_op_ldm,                     // RVM_LDS
834         rvm_op_sts,                     // RVM_STS
835         rvm_op_lds,                     // RVM_LDM
836         rvm_op_orr,                     // RVM_ORR
837         rvm_op_push,            // RVM_PUSH
838         rvm_op_pop,                     // RVM_POP
839         rvm_op_cmp,                     // RVM_CMP
840         rvm_op_nop,                     // RVM_NOP
841         rvm_op_beq,                     // RVM_BEQ
842         rvm_op_bneq,            // RVM_BNEQ
843         rvm_op_bleq,            // RVM_BLEQ
844         rvm_op_bgeq,            // RVM_BGEQ
845         rvm_op_bles,            // RVM_BLES
846         rvm_op_bgre,            // RVM_BGRE
847         rvm_op_ret,                     // RVM_RET
848         rvm_op_ror,                     // RVM_ROR
849         rvm_op_pushm,           // RVM_PUSHM
850         rvm_op_popm,            // RVM_POPM
851         rvm_op_tst,             // RVM_TST
852         rvm_op_teq,             // RVM_TEQ
853         (void*) 0,
854         (void*) 0,
855         (void*) 0,
856         (void*) 0,
857         (void*) 0,
858         (void*) 0,
859         (void*) 0,
860         (void*) 0,
861         
862 };
863         
864
865 rvm_cpu_t *rvm_cpu_create()
866 {
867         rvm_cpu_t *cpu;
868
869         cpu = (rvm_cpu_t *)r_malloc(sizeof(*cpu));
870         if (!cpu)
871                 return ((void*)0);
872         r_memset(cpu, 0, sizeof(*cpu));
873         cpu->switables = r_array_create(sizeof(rvm_switable_t*));
874         cpu->stack = r_array_create(sizeof(rvm_reg_t));
875         return cpu;
876 }
877
878
879 void rvm_cpu_destroy(rvm_cpu_t *cpu)
880 {
881 //      rvm_free(cpu->stack);
882         r_array_destroy(cpu->switables);
883         r_array_destroy(cpu->stack);
884         r_free(cpu);
885 }
886
887
888 rint rvm_cpu_exec(rvm_cpu_t *cpu, rvm_asmins_t *prog, rword off)
889 {
890         rvm_asmins_t *pi;
891
892         RVM_SET_REGM(cpu, PC, prog + off);
893         cpu->abort = 0;
894         cpu->error = 0;
895         do {
896                 pi = RVM_GET_REGM(cpu, PC);
897                 cpu->r[DA] = pi->data;
898                 ops[pi->opcode](cpu, pi);
899                 if (cpu->abort)
900                         return -1;
901                 RVM_INC_REGM(cpu, PC, 1);
902         } while (pi->opcode);
903         return 0;
904 }
905
906
907 rint rvm_cpu_exec_debug(rvm_cpu_t *cpu, rvm_asmins_t *prog, rword off)
908 {
909         rvm_asmins_t *pi;
910
911         RVM_SET_REGM(cpu, PC, prog + off);
912         cpu->abort = 0;
913         cpu->error = 0;
914         do {
915                 pi = RVM_GET_REGM(cpu, PC);
916                 cpu->r[DA] = pi->data;
917                 ops[pi->opcode](cpu, pi);
918                 if (cpu->abort)
919                         return -1;
920                 rvm_cpu_dumpregs(pi, cpu);              
921                 RVM_INC_REGM(cpu, PC, 1);
922         } while (pi->opcode);
923         return 0;
924 }
925
926
927 rint rvm_cpu_getswi(rvm_cpu_t *cpu, const rchar *swiname)
928 {
929         rint ntable, nswi;
930         rvm_switable_t *swientry;
931
932         for (ntable = 0; ntable < cpu->switables->len; ntable++) {
933                 swientry = r_array_index(cpu->switables, ntable, rvm_switable_t*);
934                 for (nswi = 0; swientry[nswi].name; nswi++) {
935                         if (r_strcmp(swientry[nswi].name, swiname) == 0)
936                                 return (rint)RVM_SWI_ID(ntable, nswi);
937                 }
938         }
939
940         return -1;
941 }
942
943
944 rint rvm_cpu_switable_add(rvm_cpu_t *cpu, rvm_switable_t *switable)
945 {
946         rint nswi;
947
948         for (nswi = 0; switable[nswi].name; nswi++) {
949                 if (rvm_cpu_getswi(cpu, switable[nswi].name) >= 0)
950                         return -1;
951         }
952
953         return r_array_add(cpu->switables, &switable);
954 }
955
956
957 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data)
958 {
959         rvm_asmins_t a;
960
961         r_memset(&a, 0, sizeof(a));
962         a.opcode = (unsigned char) opcode;
963         a.op1 = (unsigned char)op1;
964         a.op2 = (unsigned char)op2;
965         a.op3 = (unsigned char)op3;
966         RVM_REGD(&a.data) = data;
967         rvm_reg_settype(&a.data, RVM_DTYPE_DOUBLE);
968         return a;
969 }
970
971
972 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
973 {
974         rvm_asmins_t a;
975
976         r_memset(&a, 0, sizeof(a));
977         a.opcode = (unsigned char) opcode;
978         a.op1 = (unsigned char)op1;
979         a.op2 = (unsigned char)op2;
980         a.op3 = (unsigned char)op3;
981         RVM_REGP(&a.data) = data;
982         rvm_reg_settype(&a.data, RVM_DTYPE_POINTER);
983         return a;
984 }
985
986
987 rvm_asmins_t rvm_asmu(rword opcode, rword op1, rword op2, rword op3, rword data)
988 {
989         rvm_asmins_t a;
990
991         r_memset(&a, 0, sizeof(a));
992         a.opcode = (unsigned char) opcode;
993         a.op1 = (unsigned char)op1;
994         a.op2 = (unsigned char)op2;
995         a.op3 = (unsigned char)op3;
996         RVM_REGU(&a.data) = data;
997         rvm_reg_settype(&a.data, RVM_DTYPE_WORD);
998         return a;
999 }
1000
1001
1002 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data)
1003 {
1004         rvm_asmins_t a;
1005
1006         r_memset(&a, 0, sizeof(a));
1007         a.opcode = (unsigned char) opcode;
1008         a.op1 = (unsigned char)op1;
1009         a.op2 = (unsigned char)op2;
1010         a.op3 = (unsigned char)op3;
1011         RVM_REGL(&a.data) = (rword)data;
1012         rvm_reg_settype(&a.data, RVM_DTYPE_LONG);
1013         return a;
1014 }
1015
1016
1017 rvm_asmins_t rvm_asmi(rword opcode, rword op1, rword op2, rword op3, rint data)
1018 {
1019         return rvm_asml(opcode, op1, op2, op3, data);
1020 }
1021
1022
1023 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1024 {
1025         rvm_asmins_t a;
1026
1027         r_memset(&a, 0, sizeof(a));
1028         a.opcode = (unsigned char) opcode;
1029         a.op1 = (unsigned char)op1;
1030         a.op2 = (unsigned char)op2;
1031         a.op3 = (unsigned char)op3;
1032         RVM_REGP(&a.data) = pReloc;
1033         rvm_reg_settype(&a.data, RVM_DTYPE_RELOCPTR);
1034         return a;
1035 }
1036
1037
1038 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1039 {
1040         rvm_asmins_t a;
1041
1042         r_memset(&a, 0, sizeof(a));
1043         a.opcode = (unsigned char) opcode;
1044         a.op1 = (unsigned char)op1;
1045         a.op2 = (unsigned char)op2;
1046         a.op3 = (unsigned char)op3;
1047         RVM_REGP(&a.data) = pReloc;
1048         rvm_reg_settype(&a.data, RVM_DTYPE_RELOCINDEX);
1049         return a;
1050 }
1051
1052
1053 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
1054 {
1055         return rvm_asmu(opcode, op1, op2, op3, data);
1056 }
1057
1058
1059 void rvm_relocate(rvm_asmins_t *code, rsize_t size)
1060 {
1061         rvm_asmins_t *reloc;
1062         rulong relocindex;
1063         rulong off;
1064
1065         for (off = 0; off < size; off++, code++) {
1066                 if (RVM_REG_INFO(&code->data) == RVM_DTYPE_RELOCPTR) {
1067                         RVM_REG_INFO(&code->data) = 0;
1068                         reloc = *((rvm_asmins_t **)RVM_REGP(&code->data));
1069                         RVM_REGU(&code->data) = reloc - code;
1070                 } else if (RVM_REG_INFO(&code->data) == RVM_DTYPE_RELOCINDEX) {
1071                         RVM_REG_INFO(&code->data) = 0;
1072                         relocindex = *((rulong *)RVM_REGP(&code->data));
1073                         RVM_REGU(&code->data) = relocindex - off;
1074                 }
1075         }
1076 }
1077
1078
1079 void rvm_reg_settype(rvm_reg_t *r, ruint type)
1080 {
1081         r->info &= ~RVM_DTYPE_MASK;
1082         r->info |= type & RVM_DTYPE_MASK;
1083 }
1084
1085
1086 ruint rvm_reg_gettype(rvm_reg_t *r)
1087 {
1088         return (r->info & RVM_DTYPE_MASK);
1089 }