RPA Toolkit
work on RJS object introspection.
[rpatk.git] / rvm / rvmcpu.h
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 #ifndef _RVMCPU_H_
22 #define _RVMCPU_H_
23
24 #include "rtypes.h"
25 #include "rlib/rarray.h"
26 #include "rlib/rcarray.h"
27 #include "rvm/rvmreg.h"
28 #include "rlib/rgc.h"
29
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35
36 enum {
37         RVM_EXT = 0,
38         RVM_ABORT,              /* Abort: set the error code, op1: error code */
39         RVM_PRN,
40         RVM_ASR,                /* Arithmetic shift right: op1 = op2 >> op3, preserve the signed bit */
41         RVM_SWI,
42         RVM_SWIID,
43         RVM_CALL,               /* if op1 is of type RVM_DTYPE_SWIID, then invoke RVM_SWIID, otherwise invoke RVM_BL */
44         RVM_MOV,
45         RVM_MOVS,               /* op1 <-- op2, compare to 0 and set the status accordingly */
46         RVM_SWP,                /* op1 <--> op2 */
47         RVM_INC,                /* INC: op1 = op1 + 1 */
48         RVM_DEC,                /* DEC: op1 = op1 - 1 */
49         RVM_ADD,                /* Add: op1 = op2 + op3 */
50         RVM_ADDS,               /* Add: op1 = op2 + op3, update the status register */
51         RVM_ADC,                /* Add: op1 = op2 + op3 + C, update the status register */
52         RVM_AND,                /* Bitwise AND: op1 = op2 & op3, update status register */
53         RVM_BIC,                /* Bit Clear: op1 = op2 & ~op3, update status register */
54         RVM_CLZ,                /* Count rvm_reg_settypeLeading Zeros: op1 = leading_zeros(op2) */
55         RVM_CMN,                /* Compare Negative: status register is updated based on the result: op1 + op2 */
56         RVM_XOR,                /* XOR: op1 = op2 ^ op3, update the status register */
57         RVM_SUB,
58         RVM_SUBS,
59         RVM_SBC,
60         RVM_MUL,
61         RVM_MLS,                /* Signed multiplication: op1 = op2 * op3 */
62         RVM_MULS,
63         RVM_NOT,                /* Bitwise NOT: op1 = ~op2, Update the status register */
64         RVM_DIV,                /* Divide: op1 = op2 / op3 */
65         RVM_DVS,                /* Signed division: op1 = op2 / op3 */  
66         RVM_DIVS,               /* Divide: op1 = op2 / op3, Update the status register */
67         RVM_MOD,                /* Modulo: op1 = op2 % op3 */
68         RVM_MODS,               /* Modulo: op1 = op2 % op3, Update the status register */
69         RVM_BX,                 /* Jump to op1 */
70         RVM_BXEQ,               /* Jump to op1, if equal */
71         RVM_BXNEQ,              /* Jump to op1, if not equal */
72
73         RVM_BXLEQ,              /* Branch if less or equal */
74         RVM_BXGEQ,              /* Branch if greater or equal */
75         RVM_BXLES,              /* Branch if less */
76         RVM_BXGRE,              /* Branch if greater */
77
78
79         RVM_BXL,                /* Jump to op1, link */
80         RVM_BL,                 /* Branch Link */
81         RVM_B,                  /* Branch */
82         RVM_STR,                /* Save: val_at_location(op2) = op1 */
83         RVM_STRP,               /* Save pointer: pointer_at_location(op2) = op1 */
84         RVM_STRB,               /* Save: byte_at_location(op2) = op1 */
85         RVM_STRH,               /* Save: u16_at_location(op2) = op1 */
86         RVM_STRW,               /* Save: u32_at_location(op2) = op1 */
87         RVM_STRR,               /* Save: rvmreg_t_at_location(op2) = op1 */
88         RVM_LDR,                /* Load: op1 = val_at_location(op2) */
89         RVM_LDRP,               /* Load pointer: op1 = pointer_at_location(op2) */
90         RVM_LDRB,               /* Load Byte: op1 = byte_at_location(op2) */
91         RVM_LDRH,               /* Load Half Word: op1 = u16_at_location(op2) */
92         RVM_LDRW,               /* Load Word: op1 = u32_at_location(op2) */
93         RVM_LDRR,               /* Load rvmreg_t: op1 = rvmreg_t_at_location(op2) */
94         RVM_CFLAG,              /* Clear flag */
95         RVM_CLR,                /* Clear op1 */
96         RVM_CLRR,               /* Clear: rvmreg_t at memory location op1 */
97         RVM_LSL,                /* Logical Shift Left: op1 = op2 << op3, update the status register */
98         RVM_LSR,                /* Logical Shift Right: op1 = op2 >> op3, update the status register */
99         RVM_LSRS,               /* Signed Logical Shift Right: op1 = op2 >> op3, update the status register */
100         RVM_STM,                /* Store multiple */
101         RVM_LDM,                /* Load multiple */
102         RVM_STS,                /* Store op1 on the stack at position op2 + op3, i.e. stack[op2 + op3] = op1 */
103         RVM_LDS,                /* Load op1 from thes stack at position op2 + op3, i.e. op1 = stack[op2 + op3] */
104         RVM_ORR,                /* ORR: op1 = op2 | op3, update the status register */
105         RVM_PUSH,
106         RVM_POP,
107         RVM_CMP,
108         RVM_NOP,
109         RVM_BEQ,                /* Branch if equal */
110         RVM_BNEQ,               /* Branch if not equal */
111         RVM_BLEQ,               /* Branch if less or equal */
112         RVM_BGEQ,               /* Branch if greater or equal */
113         RVM_BLES,               /* Branch if less */
114         RVM_BGRE,               /* Branch if greater */
115         RVM_RET,
116         RVM_ROR,                /* Rotate right, the last bit rotated out updates the Carry flag */
117         RVM_PUSHM,
118         RVM_POPM,
119         RVM_TST,
120         RVM_TEQ,
121         RVM_ADDRS,              /* Memory location of the stack at offset op2 + op3 */
122
123 /* Extended VM opcodes, */
124         RVM_CAST,               /* Cast: op1 = (op3)op2 */
125         RVM_TYPE,               /* Type: op1 = typeof(op2) */
126         RVM_SETTYPE,    /* Type: op1.type = op2 */
127         RVM_EMOV,
128         RVM_ENEG,               /* Negative: op1 = -op2, Update the status register */
129         RVM_EADD,               /* Add: op1 = op2 + op3, update the status register */
130         RVM_ESUB,               /* Subtract: op1 = op2 - op3, update the status register */
131         RVM_EMUL,               /* Multiply: op1 = op2 * op3, update the status register */
132         RVM_EDIV,               /* Divide: op1 = op2 / op3, update the status register */
133         RVM_EMOD,               /* Modulo: op1 = op2 % op3, update the status register */
134         RVM_ELSL,               /* Logical Shift Left: op1 = op2 << op3, update the status register */
135         RVM_ELSR,               /* Logical Shift Right: op1 = op2 >> op3, update the status register */
136         RVM_ELSRU,              /* Logical Unsigned Shift Right: op1 = op2 >>> op3, update the status register */
137         RVM_EAND,               /* Bitwise AND: op1 = op2 & op3, update status register */
138         RVM_EORR,               /* Bitwise OR: op1 = op2 | op3, update the status register */
139         RVM_EXOR,               /* Bitwise XOR: op1 = op2 ^ op3, update the status register */
140         RVM_ENOT,               /* Bitwise NOT: op1 = ~op2, Update the status register */
141         RVM_ELAND,              /* Logical AND: op1 = op2 && op3, update status register */
142         RVM_ELOR,               /* Logical OR: op1 = op2 || op3, update the status register */
143         RVM_ELNOT,              /* Logical NOT: op1 = !op2, update the status register */
144         RVM_EEQ,                /* op1 = op2 == op3 ? 1 : 0, update the status register */
145         RVM_ENOTEQ,             /* op1 = op2 != op3 ? 1 : 0, update the status register */
146         RVM_EGREAT,             /* op1 = op2 > op3 ? 1 : 0, update the status register */
147         RVM_EGREATEQ,   /* op1 = op2 >= op3 ? 1 : 0, update the status register */
148         RVM_ELESS,              /* op1 = op2 < op3 ? 1 : 0, update the status register */
149         RVM_ELESSEQ,    /* op1 = op2 <= op3 ? 1 : 0, update the status register */
150
151         RVM_ECMP,               /* Compare: status register is updated based on the result: op1 - op2 */
152         RVM_ECMN,               /* Compare Negative: status register is updated based on the result: op1 + op2 */
153         RVM_ALLOCSTR,   /* Allocate string in op1, op2 is pointer (char*) to string, op3 is the size */
154         RVM_ALLOCARR,   /* Allocate array in op1, op2 is the size */
155         RVM_ADDRA,              /* op1 is the destination memory, op2 is the array, op3 is the offset */
156         RVM_LDA,                /* op1 is the destination, op2 is the array, op3 is the offset */
157         RVM_STA,                /* op1 is the source, op2 is the array, op3 is the offset */
158         RVM_MAPALLOC,
159         RVM_MAPADDR,
160         RVM_MAPKEYLDR,
161         RVM_MAPLDR,
162         RVM_MAPSTR,
163         RVM_MAPDEL,
164         RVM_MAPLKUP,
165         RVM_MAPADD,
166         RVM_MAPLKUPADD,
167         RVM_MAPNEXT,
168         RVM_MAPPREV,
169 };
170
171
172 #define RVM_REGISTER_BITS (8 * sizeof(ruword))
173 #define RVM_SIGN_BIT (((ruword)1) << (RVM_REGISTER_BITS - 1))
174 #define RVM_STATUS_Z (1 << 0)
175 #define RVM_STATUS_N (1 << 1)
176 #define RVM_STATUS_C (1 << 2)
177 #define RVM_STATUS_V (1 << 3)
178 #define RVM_STATUS_E (1 << 4)
179 #define RVM_STATUS_ALL (RVM_STATUS_Z | RVM_STATUS_N | RVM_STATUS_C | RVM_STATUS_V | RVM_STATUS_E)
180 #define RVM_STATUS_GETBIT(cpu, bit) ((cpu)->status & (bit))
181 #define RVM_STATUS_SETBIT(cpu, bit) do { (cpu)->status |= (bit); } while (0)
182 #define RVM_STATUS_CLRBIT(cpu, bit) do { (cpu)->status &= ~(bit); } while (0)
183 #define RVM_STATUS_CLRALL(cpu) RVM_STATUS_CLRBIT(cpu, RVM_STATUS_ALL)
184
185 #define RVM_STATUS_UPDATE(cpu, b, c) \
186 do { \
187     if (c) \
188         RVM_STATUS_SETBIT(cpu, b); \
189     else \
190         RVM_STATUS_CLRBIT(cpu, b); \
191 } while (0)
192
193 #define RVM_OPERAND_BITS 4
194 #define RVM_REGS_NUM (1 << RVM_OPERAND_BITS)
195 #define R0 0
196 #define R1 1
197 #define R2 2
198 #define R3 3
199 #define R4 4
200 #define R5 5
201 #define R6 6
202 #define R7 7
203 #define R8 8
204 #define R9 9
205 #define R10 10
206 #define R11 11
207 #define R12 12
208 #define R13 13
209 #define R14 14
210 #define R15 15
211 #define R16 16
212 #define R17 17
213 #define R18 18
214 #define R19 19
215 #define R20 20
216 #define R21 21
217 #define R22 22
218 #define R23 23
219 #define R24 24
220 #define R25 25
221 #define R26 26
222 #define R27 27
223 #define R28 28
224 #define R29 29
225 #define R30 30
226 #define R31 31
227
228 #define RLST (RVM_REGS_NUM - 1)
229 #define IP (RLST - 7)
230 #define TP (RLST - 6)
231 #define FP (RLST - 5)
232 #define SP (RLST - 4)
233 #define LR (RLST - 3)
234 #define PC (RLST - 2)
235 #define DA (RLST - 1)                           /* The DA register should never be modified manually, otherwise the result is undefined */
236 #define XX (RLST)
237
238
239 #define RVM_STACK_CHUNK 256
240 #define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; R_ASSERT(0); return; } while (0)
241 #define BIT(__shiftby__) (1 << (__shiftby__))
242 #define BITR(__f__, __l__, __r__) (((__r__) >= (__f__) && (__r__) <= (__l__)) ? BIT(__r__) : 0)
243 #define BITS(__f__, __l__)  (BITR(__f__, __l__, R0)) | (BITR(__f__, __l__, R1)) | (BITR(__f__, __l__, R2)) | (BITR(__f__, __l__, R3)) | \
244                                                         (BITR(__f__, __l__, R4)) | (BITR(__f__, __l__, R5)) | (BITR(__f__, __l__, R6)) | (BITR(__f__, __l__, R7)) | \
245                                                         (BITR(__f__, __l__, R8)) | (BITR(__f__, __l__, R9)) | (BITR(__f__, __l__, R10)) | (BITR(__f__, __l__, R11)) | \
246                                                         (BITR(__f__, __l__, R12)) | (BITR(__f__, __l__, R13)) | (BITR(__f__, __l__, R14)) | (BITR(__f__, __l__, R15)) | \
247                                                         (BITR(__f__, __l__, R16)) | (BITR(__f__, __l__, R17)) | (BITR(__f__, __l__, R18)) | (BITR(__f__, __l__, R19)) | \
248                                                         (BITR(__f__, __l__, R20)) | (BITR(__f__, __l__, R21)) | (BITR(__f__, __l__, R22)) | (BITR(__f__, __l__, R23)) | \
249                                                         (BITR(__f__, __l__, R24)) | (BITR(__f__, __l__, R25)) | (BITR(__f__, __l__, R26)) | (BITR(__f__, __l__, R27)) | \
250                                                         (BITR(__f__, __l__, R28)) | (BITR(__f__, __l__, R29)) | (BITR(__f__, __l__, R30)) | (BITR(__f__, __l__, R31))
251
252 #define RVM_OPCODE_BITS 8
253 #define RVM_SWI_TABLE_BITS 8
254 #define RVM_SWI_NUM_BITS 8
255 #define RVM_SWI_TABLE(__op__) ((__op__) >> RVM_SWI_NUM_BITS)
256 #define RVM_SWI_NUM(__op__) ((__op__) & ((1 << RVM_SWI_NUM_BITS) - 1))
257 #define RVM_SWI_ID(__t__, __o__) ((((__t__) & ((1 << RVM_SWI_TABLE_BITS) - 1))  << RVM_SWI_NUM_BITS) | ((__o__) & ((1 << RVM_SWI_NUM_BITS) - 1)))
258 #define RVM_ASMINS_OPCODE(__opcode__) ((__opcode__) & ((1 << RVM_OPCODE_BITS) - 1))
259 #define RVM_ASMINS_SWI(__opcode__) ((__opcode__) >> RVM_OPCODE_BITS)
260 #define RVM_OPSWI(__id__) (((__id__) << RVM_OPCODE_BITS) | RVM_SWI)
261
262 //#define RVM_STACK_WRITE(__s__, __sp__, __p__) r_carray_replace((__s__), (__sp__), (rconstpointer)(__p__));
263 //#define RVM_STACK_READ(__s__, __sp__) r_carray_index((__s__), (__sp__), rvmreg_t)
264 //#define RVM_STACK_ADDR(__s__, __sp__) r_carray_slot_expand((__s__), (__sp__))
265
266
267 #define RVM_STACK_WRITE(__s__, __sp__, __p__) do { r_memcpy(((rvmreg_t*)(__s__)) + (__sp__), (__p__), sizeof(rvmreg_t)); } while(0)
268 #define RVM_STACK_READ(__s__, __sp__) *RVM_STACK_ADDR(__s__, __sp__)
269 #define RVM_STACK_ADDR(__s__, __sp__) (((rvmreg_t*)(__s__)) + (__sp__))
270 #define RVM_STACK_CHECKSIZE(__cpu__, __s__, __sp__)  ((__sp__) < (__cpu__)->stacksize ? 1 : 0)
271 #define RVM_CODE2BYTE_OFFSET(__codeoff__) ((ruword)(((rword)(__codeoff__)) * ((rword)sizeof(rvm_asmins_t))))
272 #define RVM_BYTE2CODE_OFFSET(__byteoff__) ((ruword)(((rword)(__byteoff__)) / ((rword)sizeof(rvm_asmins_t))))
273
274 #define RVM_E_DIVZERO           (1)
275 #define RVM_E_ILLEGAL           (2)
276 #define RVM_E_CAST                      (3)
277 #define RVM_E_SWINUM            (4)
278 #define RVM_E_SWITABLE          (5)
279 #define RVM_E_LVALUE            (6)
280 #define RVM_E_NOMEM                     (7)
281 #define RVM_E_NOTFUNCTION       (8)
282 #define RVM_E_NOTOBJECT         (9)
283 #define RVM_E_USERABORT         (10)
284
285 typedef struct rvm_asmins_s rvm_asmins_t;
286 typedef struct rvmcpu_s rvmcpu_t;
287 typedef void (*rvmcpu_swi)(rvmcpu_t *cpu, rvm_asmins_t *ins);
288 typedef void (*rvm_cpu_op)(rvmcpu_t *cpu, rvm_asmins_t *ins);
289
290 typedef struct rvm_switable_s {
291         const char *name;
292         rvmcpu_swi op;
293 } rvm_switable_t;
294
295 #define RVM_CEXEC_NAN 0
296 #define RVM_CEXEC_GRE 1
297 #define RVM_CEXEC_GEQ 2
298 #define RVM_CEXEC_EQ  3
299 #define RVM_CEXEC_NEQ 4
300 #define RVM_CEXEC_LEQ 5
301 #define RVM_CEXEC_LES 6
302
303 struct rvm_asmins_s {
304         rvmreg_t data;
305         ruint16 op1:RVM_OPERAND_BITS;
306         ruint16 op2:RVM_OPERAND_BITS;
307         ruint16 op3:RVM_OPERAND_BITS;
308         ruint16 da:1;
309         ruint16 swi;
310         ruint8 cond;
311         ruint8 opcode;
312 };
313
314
315 struct rvm_opmap_s;
316
317 struct rvmcpu_s {
318         rvmreg_t r[RVM_REGS_NUM];
319         ruword status;
320         ruword error;
321         ruword abort;
322         rharray_t *switables;
323         unsigned long stacksize;
324         void *stack;
325         rcarray_t *data;
326         struct rvm_opmap_s *opmap;
327         rvmreg_t *thisptr;
328         rgc_t *gc;
329         void *userdata1;
330         void *userdata2;
331         void *userdata3;
332         void *userdata4;
333         void *userdata5;
334         void *userdata6;
335         void *userdata7;
336 };
337
338
339 rvmcpu_t *rvm_cpu_create_default();
340 rvmcpu_t *rvm_cpu_create(unsigned long stacksize);
341 void rvm_cpu_destroy(rvmcpu_t * vm);
342 int rvm_cpu_abort(rvmcpu_t *cpu);
343 int rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off);
344 int rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off);
345 int rvm_cpu_swilookup(rvmcpu_t *cpu, const char *tabname, const char *swiname, unsigned long size);
346 int rvm_cpu_swilookup_s(rvmcpu_t *cpu, const char *tabname, const char *swiname);
347 int rvm_cpu_addswitable(rvmcpu_t * cpu, const char *tabname, rvm_switable_t *switalbe);
348 rvmreg_t *rvm_cpu_alloc_global(rvmcpu_t *cpu);
349 int rvm_cpu_setreg(rvmcpu_t *cpu, ruword regnum, const rvmreg_t *src);
350 rvmreg_t *rvm_cpu_getreg(rvmcpu_t *cpu, ruword regnum);
351 void rvm_cpu_dumpregs( rvmcpu_t *cpu, rvm_asmins_t *pi);
352 rvm_asmins_t rvm_asm(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
353 rvm_asmins_t rvm_asma(ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size);
354 rvm_asmins_t rvm_asml(ruword opcode, ruword op1, ruword op2, ruword op3, long data);
355 rvm_asmins_t rvm_asmb(ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data);
356 rvm_asmins_t rvm_asmd(ruword opcode, ruword op1, ruword op2, ruword op3, double data);
357 rvm_asmins_t rvm_asmp(ruword opcode, ruword op1, ruword op2, ruword op3, rpointer data);
358 rvm_asmins_t rvm_asms(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
359 rvm_asmins_t rvm_asmf(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
360 rvm_asmins_t rvm_asm2(ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2);
361
362 rvm_asmins_t rvm_cond_asm(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
363 rvm_asmins_t rvm_cond_asma(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size);
364 rvm_asmins_t rvm_cond_asml(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, long data);
365 rvm_asmins_t rvm_cond_asmb(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data);
366 rvm_asmins_t rvm_cond_asmp(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, rpointer data);
367 rvm_asmins_t rvm_cond_asms(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
368 rvm_asmins_t rvm_cond_asmd(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, double data);
369 rvm_asmins_t rvm_cond_asmf(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
370 rvm_asmins_t rvm_cond_asm2(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2);
371
372
373 void rvm_asm_dump(rvm_asmins_t *pi, unsigned int count);
374
375
376 #ifdef __cplusplus
377 }
378 #endif
379
380
381 #endif