RPA Toolkit
5a285dd949e7d9ef97cde150143e9d720eb985ed
[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_MAPLDR,
161         RVM_MAPSTR,
162         RVM_MAPLKUP,
163         RVM_MAPADD,
164         RVM_MAPLKUPADD,
165 };
166
167
168 #define RVM_REGISTER_BITS (8 * sizeof(ruword))
169 #define RVM_SIGN_BIT (((ruword)1) << (RVM_REGISTER_BITS - 1))
170 #define RVM_STATUS_Z (1 << 0)
171 #define RVM_STATUS_N (1 << 1)
172 #define RVM_STATUS_C (1 << 2)
173 #define RVM_STATUS_V (1 << 3)
174 #define RVM_STATUS_E (1 << 4)
175 #define RVM_STATUS_ALL (RVM_STATUS_Z | RVM_STATUS_N | RVM_STATUS_C | RVM_STATUS_V | RVM_STATUS_E)
176 #define RVM_STATUS_GETBIT(cpu, bit) ((cpu)->status & (bit))
177 #define RVM_STATUS_SETBIT(cpu, bit) do { (cpu)->status |= (bit); } while (0)
178 #define RVM_STATUS_CLRBIT(cpu, bit) do { (cpu)->status &= ~(bit); } while (0)
179 #define RVM_STATUS_CLRALL(cpu) RVM_STATUS_CLRBIT(cpu, RVM_STATUS_ALL)
180
181 #define RVM_STATUS_UPDATE(cpu, b, c) \
182 do { \
183     if (c) \
184         RVM_STATUS_SETBIT(cpu, b); \
185     else \
186         RVM_STATUS_CLRBIT(cpu, b); \
187 } while (0)
188
189 #define RVM_OPERAND_BITS 4
190 #define RVM_REGS_NUM (1 << RVM_OPERAND_BITS)
191 #define R0 0
192 #define R1 1
193 #define R2 2
194 #define R3 3
195 #define R4 4
196 #define R5 5
197 #define R6 6
198 #define R7 7
199 #define R8 8
200 #define R9 9
201 #define R10 10
202 #define R11 11
203 #define R12 12
204 #define R13 13
205 #define R14 14
206 #define R15 15
207 #define R16 16
208 #define R17 17
209 #define R18 18
210 #define R19 19
211 #define R20 20
212 #define R21 21
213 #define R22 22
214 #define R23 23
215 #define R24 24
216 #define R25 25
217 #define R26 26
218 #define R27 27
219 #define R28 28
220 #define R29 29
221 #define R30 30
222 #define R31 31
223
224 #define RLST (RVM_REGS_NUM - 1)
225 #define IP (RLST - 7)
226 #define TP (RLST - 6)
227 #define FP (RLST - 5)
228 #define SP (RLST - 4)
229 #define LR (RLST - 3)
230 #define PC (RLST - 2)
231 #define DA (RLST - 1)                           /* The DA register should never be modified manually, otherwise the result is undefined */
232 #define XX (RLST)
233
234
235 #define RVM_STACK_CHUNK 256
236 #define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; R_ASSERT(0); return; } while (0)
237 #define BIT(__shiftby__) (1 << (__shiftby__))
238 #define BITR(__f__, __l__, __r__) (((__r__) >= (__f__) && (__r__) <= (__l__)) ? BIT(__r__) : 0)
239 #define BITS(__f__, __l__)  (BITR(__f__, __l__, R0)) | (BITR(__f__, __l__, R1)) | (BITR(__f__, __l__, R2)) | (BITR(__f__, __l__, R3)) | \
240                                                         (BITR(__f__, __l__, R4)) | (BITR(__f__, __l__, R5)) | (BITR(__f__, __l__, R6)) | (BITR(__f__, __l__, R7)) | \
241                                                         (BITR(__f__, __l__, R8)) | (BITR(__f__, __l__, R9)) | (BITR(__f__, __l__, R10)) | (BITR(__f__, __l__, R11)) | \
242                                                         (BITR(__f__, __l__, R12)) | (BITR(__f__, __l__, R13)) | (BITR(__f__, __l__, R14)) | (BITR(__f__, __l__, R15)) | \
243                                                         (BITR(__f__, __l__, R16)) | (BITR(__f__, __l__, R17)) | (BITR(__f__, __l__, R18)) | (BITR(__f__, __l__, R19)) | \
244                                                         (BITR(__f__, __l__, R20)) | (BITR(__f__, __l__, R21)) | (BITR(__f__, __l__, R22)) | (BITR(__f__, __l__, R23)) | \
245                                                         (BITR(__f__, __l__, R24)) | (BITR(__f__, __l__, R25)) | (BITR(__f__, __l__, R26)) | (BITR(__f__, __l__, R27)) | \
246                                                         (BITR(__f__, __l__, R28)) | (BITR(__f__, __l__, R29)) | (BITR(__f__, __l__, R30)) | (BITR(__f__, __l__, R31))
247
248 #define RVM_OPCODE_BITS 8
249 #define RVM_SWI_TABLE_BITS 8
250 #define RVM_SWI_NUM_BITS 8
251 #define RVM_SWI_TABLE(__op__) ((__op__) >> RVM_SWI_NUM_BITS)
252 #define RVM_SWI_NUM(__op__) ((__op__) & ((1 << RVM_SWI_NUM_BITS) - 1))
253 #define RVM_SWI_ID(__t__, __o__) ((((__t__) & ((1 << RVM_SWI_TABLE_BITS) - 1))  << RVM_SWI_NUM_BITS) | ((__o__) & ((1 << RVM_SWI_NUM_BITS) - 1)))
254 #define RVM_ASMINS_OPCODE(__opcode__) ((__opcode__) & ((1 << RVM_OPCODE_BITS) - 1))
255 #define RVM_ASMINS_SWI(__opcode__) ((__opcode__) >> RVM_OPCODE_BITS)
256 #define RVM_OPSWI(__id__) (((__id__) << RVM_OPCODE_BITS) | RVM_SWI)
257
258 //#define RVM_STACK_WRITE(__s__, __sp__, __p__) r_carray_replace((__s__), (__sp__), (rconstpointer)(__p__));
259 //#define RVM_STACK_READ(__s__, __sp__) r_carray_index((__s__), (__sp__), rvmreg_t)
260 //#define RVM_STACK_ADDR(__s__, __sp__) r_carray_slot_expand((__s__), (__sp__))
261
262
263 #define RVM_STACK_WRITE(__s__, __sp__, __p__) do { r_memcpy(((rvmreg_t*)(__s__)) + (__sp__), (__p__), sizeof(rvmreg_t)); } while(0)
264 #define RVM_STACK_READ(__s__, __sp__) *RVM_STACK_ADDR(__s__, __sp__)
265 #define RVM_STACK_ADDR(__s__, __sp__) (((rvmreg_t*)(__s__)) + (__sp__))
266 #define RVM_STACK_CHECKSIZE(__cpu__, __s__, __sp__)  ((__sp__) < (__cpu__)->stacksize ? 1 : 0)
267 #define RVM_CODE2BYTE_OFFSET(__codeoff__) ((ruword)(((rword)(__codeoff__)) * ((rword)sizeof(rvm_asmins_t))))
268 #define RVM_BYTE2CODE_OFFSET(__byteoff__) ((ruword)(((rword)(__byteoff__)) / ((rword)sizeof(rvm_asmins_t))))
269
270 #define RVM_E_DIVZERO           (1)
271 #define RVM_E_ILLEGAL           (2)
272 #define RVM_E_CAST                      (3)
273 #define RVM_E_SWINUM            (4)
274 #define RVM_E_SWITABLE          (5)
275 #define RVM_E_LVALUE            (6)
276 #define RVM_E_NOMEM                     (7)
277 #define RVM_E_NOTFUNCTION       (8)
278 #define RVM_E_NOTOBJECT         (9)
279 #define RVM_E_USERABORT         (10)
280
281 typedef struct rvm_asmins_s rvm_asmins_t;
282 typedef struct rvmcpu_s rvmcpu_t;
283 typedef void (*rvmcpu_swi)(rvmcpu_t *cpu, rvm_asmins_t *ins);
284 typedef void (*rvm_cpu_op)(rvmcpu_t *cpu, rvm_asmins_t *ins);
285
286 typedef struct rvm_switable_s {
287         const char *name;
288         rvmcpu_swi op;
289 } rvm_switable_t;
290
291 #define RVM_CEXEC_NAN 0
292 #define RVM_CEXEC_GRE 1
293 #define RVM_CEXEC_GEQ 2
294 #define RVM_CEXEC_EQ  3
295 #define RVM_CEXEC_NEQ 4
296 #define RVM_CEXEC_LEQ 5
297 #define RVM_CEXEC_LES 6
298
299 struct rvm_asmins_s {
300         rvmreg_t data;
301         ruint16 op1:RVM_OPERAND_BITS;
302         ruint16 op2:RVM_OPERAND_BITS;
303         ruint16 op3:RVM_OPERAND_BITS;
304         ruint16 da:1;
305         ruint16 swi;
306         ruint8 cond;
307         ruint8 opcode;
308 };
309
310
311 struct rvm_opmap_s;
312
313 struct rvmcpu_s {
314         rvmreg_t r[RVM_REGS_NUM];
315         ruword status;
316         ruword error;
317         ruword abort;
318         rharray_t *switables;
319         unsigned long stacksize;
320         void *stack;
321         rcarray_t *data;
322         struct rvm_opmap_s *opmap;
323         rvmreg_t *thisptr;
324         rgc_t *gc;
325         void *userdata1;
326         void *userdata2;
327         void *userdata3;
328         void *userdata4;
329         void *userdata5;
330         void *userdata6;
331         void *userdata7;
332 };
333
334
335 rvmcpu_t *rvm_cpu_create_default();
336 rvmcpu_t *rvm_cpu_create(unsigned long stacksize);
337 void rvm_cpu_destroy(rvmcpu_t * vm);
338 int rvm_cpu_abort(rvmcpu_t *cpu);
339 int rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off);
340 int rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off);
341 int rvm_cpu_swilookup(rvmcpu_t *cpu, const char *tabname, const char *swiname, unsigned long size);
342 int rvm_cpu_swilookup_s(rvmcpu_t *cpu, const char *tabname, const char *swiname);
343 int rvm_cpu_addswitable(rvmcpu_t * cpu, const char *tabname, rvm_switable_t *switalbe);
344 rvmreg_t *rvm_cpu_alloc_global(rvmcpu_t *cpu);
345 int rvm_cpu_setreg(rvmcpu_t *cpu, ruword regnum, const rvmreg_t *src);
346 rvmreg_t *rvm_cpu_getreg(rvmcpu_t *cpu, ruword regnum);
347 void rvm_cpu_dumpregs( rvmcpu_t *cpu, rvm_asmins_t *pi);
348 rvm_asmins_t rvm_asm(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
349 rvm_asmins_t rvm_asma(ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size);
350 rvm_asmins_t rvm_asml(ruword opcode, ruword op1, ruword op2, ruword op3, long data);
351 rvm_asmins_t rvm_asmb(ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data);
352 rvm_asmins_t rvm_asmd(ruword opcode, ruword op1, ruword op2, ruword op3, double data);
353 rvm_asmins_t rvm_asmp(ruword opcode, ruword op1, ruword op2, ruword op3, rpointer data);
354 rvm_asmins_t rvm_asms(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
355 rvm_asmins_t rvm_asmf(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
356 rvm_asmins_t rvm_asm2(ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2);
357
358 rvm_asmins_t rvm_cond_asm(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
359 rvm_asmins_t rvm_cond_asma(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size);
360 rvm_asmins_t rvm_cond_asml(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, long data);
361 rvm_asmins_t rvm_cond_asmb(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data);
362 rvm_asmins_t rvm_cond_asmp(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, rpointer data);
363 rvm_asmins_t rvm_cond_asms(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
364 rvm_asmins_t rvm_cond_asmd(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, double data);
365 rvm_asmins_t rvm_cond_asmf(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
366 rvm_asmins_t rvm_cond_asm2(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2);
367
368
369 void rvm_asm_dump(rvm_asmins_t *pi, unsigned int count);
370
371
372 #ifdef __cplusplus
373 }
374 #endif
375
376
377 #endif