RPA Toolkit
5b223358c7a0e2ede16dee502c66b2f4b0f5ca3f
[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 "rarray.h"
26 #include "rcarray.h"
27 #include "rvmreg.h"
28 #include "rvmgc.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_EADD,               /* Add: op1 = op2 + op3, update the status register */
129         RVM_ESUB,               /* Subtract: op1 = op2 - op3, update the status register */
130         RVM_EMUL,               /* Multiply: op1 = op2 * op3, update the status register */
131         RVM_EDIV,               /* Divide: op1 = op2 / op3, update the status register */
132         RVM_EMOD,               /* Modulo: op1 = op2 % op3, update the status register */
133         RVM_ELSL,               /* Logical Shift Left: op1 = op2 << op3, update the status register */
134         RVM_ELSR,               /* Logical Shift Right: op1 = op2 >> op3, update the status register */
135         RVM_ELSRU,              /* Logical Unsigned Shift Right: op1 = op2 >>> op3, update the status register */
136         RVM_EAND,               /* Bitwise AND: op1 = op2 & op3, update status register */
137         RVM_EORR,               /* Bitwise OR: op1 = op2 | op3, update the status register */
138         RVM_EXOR,               /* Bitwise XOR: op1 = op2 ^ op3, update the status register */
139         RVM_ENOT,               /* Bitwise NOT: op1 = ~op2, Update the status register */
140         RVM_ELAND,              /* Logical AND: op1 = op2 && op3, update status register */
141         RVM_ELOR,               /* Logical OR: op1 = op2 || op3, update the status register */
142         RVM_ELNOT,              /* Logical NOT: op1 = !op2, update the status register */
143         RVM_EEQ,                /* op1 = op2 == op3 ? 1 : 0, update the status register */
144         RVM_ENOTEQ,             /* op1 = op2 != op3 ? 1 : 0, update the status register */
145         RVM_EGREAT,             /* op1 = op2 > op3 ? 1 : 0, update the status register */
146         RVM_EGREATEQ,   /* op1 = op2 >= op3 ? 1 : 0, update the status register */
147         RVM_ELESS,              /* op1 = op2 < op3 ? 1 : 0, update the status register */
148         RVM_ELESSEQ,    /* op1 = op2 <= op3 ? 1 : 0, update the status register */
149
150         RVM_ECMP,               /* Compare: status register is updated based on the result: op1 - op2 */
151         RVM_ECMN,               /* Compare Negative: status register is updated based on the result: op1 + op2 */
152         RVM_ALLOCSTR,   /* Allocate string in op1, op2 is pointer (char*) to string, op3 is the size */
153         RVM_ALLOCARR,   /* Allocate array in op1, op2 is the size */
154         RVM_ADDRA,              /* op1 is the destination memory, op2 is the array, op3 is the offset */
155         RVM_LDA,                /* op1 is the destination, op2 is the array, op3 is the offset */
156         RVM_STA,                /* op1 is the source, op2 is the array, op3 is the offset */
157         RVM_ALLOCOBJ,
158         RVM_ADDROBJN,
159         RVM_ADDROBJH,
160         RVM_LDOBJN,
161         RVM_STOBJN,
162         RVM_LDOBJH,
163         RVM_STOBJH,
164         RVM_OBJLKUP,
165         RVM_OBJADD,
166         RVM_OBJLKUPADD,
167 };
168
169
170 #define RVM_REGISTER_BITS (8 * sizeof(rword))
171 #define RVM_SIGN_BIT (1LU << (RVM_REGISTER_BITS - 1))
172 #define RVM_STATUS_Z (1 << 0)
173 #define RVM_STATUS_N (1 << 1)
174 #define RVM_STATUS_C (1 << 2)
175 #define RVM_STATUS_V (1 << 3)
176 #define RVM_STATUS_E (1 << 4)
177 #define RVM_STATUS_ALL (RVM_STATUS_Z | RVM_STATUS_N | RVM_STATUS_C | RVM_STATUS_V | RVM_STATUS_E)
178 #define RVM_STATUS_GETBIT(cpu, bit) ((cpu)->status & (bit))
179 #define RVM_STATUS_SETBIT(cpu, bit) do { (cpu)->status |= (bit); } while (0)
180 #define RVM_STATUS_CLRBIT(cpu, bit) do { (cpu)->status &= ~(bit); } while (0)
181 #define RVM_STATUS_CLRALL(cpu) RVM_STATUS_CLRBIT(cpu, RVM_STATUS_ALL)
182
183 #define RVM_STATUS_UPDATE(cpu, b, c) \
184 do { \
185     if (c) \
186         RVM_STATUS_SETBIT(cpu, b); \
187     else \
188         RVM_STATUS_CLRBIT(cpu, b); \
189 } while (0)
190
191 #define RVM_OPERAND_BITS 4
192 #define RVM_REGS_NUM (1 << RVM_OPERAND_BITS)
193 #define R0 0
194 #define R1 1
195 #define R2 2
196 #define R3 3
197 #define R4 4
198 #define R5 5
199 #define R6 6
200 #define R7 7
201 #define R8 8
202 #define R9 9
203 #define R10 10
204 #define R11 11
205 #define R12 12
206 #define R13 13
207 #define R14 14
208 #define R15 15
209 #define R16 16
210 #define R17 17
211 #define R18 18
212 #define R19 19
213 #define R20 20
214 #define R21 21
215 #define R22 22
216 #define R23 23
217 #define R24 24
218 #define R25 25
219 #define R26 26
220 #define R27 27
221 #define R28 28
222 #define R29 29
223 #define R30 30
224 #define R31 31
225
226 #define RLST (RVM_REGS_NUM - 1)
227 #define IP (RLST - 7)
228 #define TP (RLST - 6)
229 #define FP (RLST - 5)
230 #define SP (RLST - 4)
231 #define LR (RLST - 3)
232 #define PC (RLST - 2)
233 #define DA (RLST - 1)                           /* The DA register should never be modified manually, otherwise the result is undefined */
234 #define XX (RLST)
235
236
237 #define RVM_STACK_CHUNK 256
238 #define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; R_ASSERT(0); return; } while (0)
239 #define BIT(__shiftby__) (1 << (__shiftby__))
240 #define BITR(__f__, __l__, __r__) (((__r__) >= (__f__) && (__r__) <= (__l__)) ? BIT(__r__) : 0)
241 #define BITS(__f__, __l__)  (BITR(__f__, __l__, R0)) | (BITR(__f__, __l__, R1)) | (BITR(__f__, __l__, R2)) | (BITR(__f__, __l__, R3)) | \
242                                                         (BITR(__f__, __l__, R4)) | (BITR(__f__, __l__, R5)) | (BITR(__f__, __l__, R6)) | (BITR(__f__, __l__, R7)) | \
243                                                         (BITR(__f__, __l__, R8)) | (BITR(__f__, __l__, R9)) | (BITR(__f__, __l__, R10)) | (BITR(__f__, __l__, R11)) | \
244                                                         (BITR(__f__, __l__, R12)) | (BITR(__f__, __l__, R13)) | (BITR(__f__, __l__, R14)) | (BITR(__f__, __l__, R15)) | \
245                                                         (BITR(__f__, __l__, R16)) | (BITR(__f__, __l__, R17)) | (BITR(__f__, __l__, R18)) | (BITR(__f__, __l__, R19)) | \
246                                                         (BITR(__f__, __l__, R20)) | (BITR(__f__, __l__, R21)) | (BITR(__f__, __l__, R22)) | (BITR(__f__, __l__, R23)) | \
247                                                         (BITR(__f__, __l__, R24)) | (BITR(__f__, __l__, R25)) | (BITR(__f__, __l__, R26)) | (BITR(__f__, __l__, R27)) | \
248                                                         (BITR(__f__, __l__, R28)) | (BITR(__f__, __l__, R29)) | (BITR(__f__, __l__, R30)) | (BITR(__f__, __l__, R31))
249
250 #define RVM_OPCODE_BITS 8
251 #define RVM_SWI_TABLE_BITS 8
252 #define RVM_SWI_NUM_BITS 8
253 #define RVM_SWI_TABLE(__op__) ((__op__) >> RVM_SWI_NUM_BITS)
254 #define RVM_SWI_NUM(__op__) ((__op__) & ((1 << RVM_SWI_NUM_BITS) - 1))
255 #define RVM_SWI_ID(__t__, __o__) ((((__t__) & ((1 << RVM_SWI_TABLE_BITS) - 1))  << RVM_SWI_NUM_BITS) | ((__o__) & ((1 << RVM_SWI_NUM_BITS) - 1)))
256 #define RVM_ASMINS_OPCODE(__opcode__) ((__opcode__) & ((1 << RVM_OPCODE_BITS) - 1))
257 #define RVM_ASMINS_SWI(__opcode__) ((__opcode__) >> RVM_OPCODE_BITS)
258 #define RVM_OPSWI(__id__) (((__id__) << RVM_OPCODE_BITS) | RVM_SWI)
259
260 //#define RVM_STACK_WRITE(__s__, __sp__, __p__) r_carray_replace((__s__), (__sp__), (rconstpointer)(__p__));
261 //#define RVM_STACK_READ(__s__, __sp__) r_carray_index((__s__), (__sp__), rvmreg_t)
262 //#define RVM_STACK_ADDR(__s__, __sp__) r_carray_slot_expand((__s__), (__sp__))
263
264
265 #define RVM_STACK_WRITE(__s__, __sp__, __p__) do { r_memcpy(((rvmreg_t*)(__s__)) + (__sp__), (__p__), sizeof(rvmreg_t)); } while(0)
266 #define RVM_STACK_READ(__s__, __sp__) *RVM_STACK_ADDR(__s__, __sp__)
267 #define RVM_STACK_ADDR(__s__, __sp__) (((rvmreg_t*)(__s__)) + (__sp__))
268 #define RVM_STACK_CHECKSIZE(__cpu__, __s__, __sp__)  ((__sp__) < (__cpu__)->stacksize ? 1 : 0)
269 #define RVM_CODE2BYTE_OFFSET(__codeoff__) ((rword)(((rsword)(__codeoff__)) * ((rsword)sizeof(rvm_asmins_t))))
270 #define RVM_BYTE2CODE_OFFSET(__byteoff__) ((rword)(((rsword)(__byteoff__)) / ((rsword)sizeof(rvm_asmins_t))))
271
272 #define RVM_E_DIVZERO           (1)
273 #define RVM_E_ILLEGAL           (2)
274 #define RVM_E_CAST                      (3)
275 #define RVM_E_SWINUM            (4)
276 #define RVM_E_SWITABLE          (5)
277 #define RVM_E_LVALUE            (6)
278 #define RVM_E_NOMEM                     (7)
279 #define RVM_E_NOTFUNCTION       (8)
280 #define RVM_E_NOTOBJECT         (9)
281
282 typedef struct rvm_asmins_s rvm_asmins_t;
283 typedef struct rvmcpu_s rvmcpu_t;
284 typedef void (*rvmcpu_swi)(rvmcpu_t *cpu, rvm_asmins_t *ins);
285 typedef void (*rvm_cpu_op)(rvmcpu_t *cpu, rvm_asmins_t *ins);
286
287 typedef struct rvm_switable_s {
288         const char *name;
289         rvmcpu_swi op;
290 } rvm_switable_t;
291
292 #define RVM_CEXEC_NAN 0
293 #define RVM_CEXEC_GRE 1
294 #define RVM_CEXEC_GEQ 2
295 #define RVM_CEXEC_EQ  3
296 #define RVM_CEXEC_NEQ 4
297 #define RVM_CEXEC_LEQ 5
298 #define RVM_CEXEC_LES 6
299
300 struct rvm_asmins_s {
301         rvmreg_t data;
302         ruint16 op1:RVM_OPERAND_BITS;
303         ruint16 op2:RVM_OPERAND_BITS;
304         ruint16 op3:RVM_OPERAND_BITS;
305         ruint16 da:1;
306         ruint16 swi;
307         ruint8 cond;
308         ruint8 opcode;
309 };
310
311
312 struct rvm_opmap_s;
313
314 struct rvmcpu_s {
315         rvmreg_t r[RVM_REGS_NUM];
316         rword status;
317         rword error;
318         rword abort;
319         rharray_t *switables;
320         rulong stacksize;
321         void *stack;
322         rcarray_t *data;
323         struct rvm_opmap_s *opmap;
324         rvmreg_t *thisptr;
325         rvm_gc_t *gc;
326         void *userdata1;
327         void *userdata2;
328         void *userdata3;
329         void *userdata4;
330         void *userdata5;
331         void *userdata6;
332         void *userdata7;
333 };
334
335
336 rvmcpu_t *rvm_cpu_create_default();
337 rvmcpu_t *rvm_cpu_create(rulong stacksize);
338 void rvm_cpu_destroy(rvmcpu_t * vm);
339 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
340 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
341 rint rvm_cpu_swilookup(rvmcpu_t *cpu, const rchar *tabname, const rchar *swiname, rsize_t size);
342 rint rvm_cpu_swilookup_s(rvmcpu_t *cpu, const rchar *tabname, const rchar *swiname);
343 rint rvm_cpu_addswitable(rvmcpu_t * cpu, const rchar *tabname, rvm_switable_t *switalbe);
344 rvmreg_t *rvm_cpu_alloc_global(rvmcpu_t *cpu);
345 int rvm_cpu_setreg(rvmcpu_t *cpu, rword regnum, const rvmreg_t *src);
346 rvmreg_t *rvm_cpu_getreg(rvmcpu_t *cpu, rword regnum);
347 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data);
348 rvm_asmins_t rvm_asma(rword opcode, rword op1, rword op2, rword op3, rchar *data, rulong size);
349 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data);
350 rvm_asmins_t rvm_asmb(rword opcode, rword op1, rword op2, rword op3, ruint data);
351 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data);
352 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data);
353 rvm_asmins_t rvm_asms(rword opcode, rword op1, rword op2, rword op3, rword data);
354 rvm_asmins_t rvm_asmf(rword opcode, rword op1, rword op2, rword op3, rword data);
355 rvm_asmins_t rvm_asm2(rword opcode, rword op1, rword op2, rword op3, ruint32 p1, ruint32 p2);
356 void rvm_asm_dump(rvm_asmins_t *pi, ruint count);
357
358
359 #ifdef __cplusplus
360 }
361 #endif
362
363
364 #endif