RPA Toolkit
added RVM_REF instruction although not sure if I am gonna use it at all
[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
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 #define RVM_MIN_REGSIZE (sizeof(rword)/8)
33
34
35 enum {
36         RVM_EXT = 0,
37         RVM_PRN,
38         RVM_ASR,                /* Arithmetic shift right: op1 = op2 >> op3, preserve the signed bit */
39         RVM_SWI,
40         RVM_MOV,
41         RVM_ADD,                /* Add: op1 = op2 + op3 */
42         RVM_ADDS,               /* Add: op1 = op2 + op3, update the status register */
43         RVM_ADC,                /* Add: op1 = op2 + op3 + C, update the status register */
44         RVM_AND,                /* Bitwise AND: op1 = op2 & op3, update status register */
45         RVM_BIC,                /* Bit Clear: op1 = op2 & ~op3, update status register */
46         RVM_CLZ,                /* Count rvm_reg_settypeLeading Zeros: op1 = leading_zeros(op2) */
47         RVM_CMN,                /* Compare Negative: status register is updated based on the result: op1 + op2 */
48         RVM_XOR,                /* XOR: op1 = op2 ^ op3, update the status register */
49         RVM_SUB,
50         RVM_SUBS,
51         RVM_SBC,
52         RVM_MUL,
53         RVM_MLS,                /* Signed multiplication: op1 = op2 * op3 */
54         RVM_MULS,
55         RVM_NOT,                /* Bitwise NOT: op1 = ~op2, Update the status register */
56         RVM_DIV,                /* Divide: op1 = op2 / op3 */
57         RVM_DVS,                /* Signed division: op1 = op2 / op3 */  
58         RVM_DIVS,               /* Divide: op1 = op2 / op3, Update the status register */
59         RVM_BX,                 /* Jump to op1 */
60         RVM_BL,                 /* Branch Link */
61         RVM_B,                  /* Branch */
62         RVM_STR,                /* Save: val_at_location(op2) = op1 */
63         RVM_STRP,               /* Save pointer: pointer_at_location(op2) = op1 */
64         RVM_STRB,               /* Save: byte_at_location(op2) = op1 */
65         RVM_STRH,               /* Save: u16_at_location(op2) = op1 */
66         RVM_STRW,               /* Save: u32_at_location(op2) = op1 */
67         RVM_STRR,               /* Save: rvmreg_t_at_location(op2) = op1 */
68         RVM_LDR,                /* Load: op1 = val_at_location(op2) */
69         RVM_LDRP,               /* Load pointer: op1 = pointer_at_location(op2) */
70         RVM_LDRB,               /* Load Byte: op1 = byte_at_location(op2) */
71         RVM_LDRH,               /* Load Half Word: op1 = u16_at_location(op2) */
72         RVM_LDRW,               /* Load Word: op1 = u32_at_location(op2) */
73         RVM_LDRR,               /* Load rvmreg_t: op1 = rvmreg_t_at_location(op2) */
74         RVM_CLRR,               /* Clear: rvmreg_t at memory location op1 */
75         RVM_LSL,                /* Logical Shift Left: op1 = op2 << op3, update the status register */
76         RVM_LSR,                /* Logical Shift Right: op1 = op2 >> op3, update the status register */
77         RVM_LSRS,               /* Signed Logical Shift Right: op1 = op2 >> op3, update the status register */
78         RVM_STM,                /* Store multiple */
79         RVM_LDM,                /* Load multiple */
80         RVM_STS,                /* Store op1 on the stack at position op2 + op3, i.e. stack[op2 + op3] = op1 */
81         RVM_LDS,                /* Load op1 from thes stack at position op2 + op3, i.e. op1 = stack[op2 + op3] */
82         RVM_CLS,                /* Clear the stack at pos op2 + op3.  CLEAR(&stack[op2 + op3]) */
83         RVM_ORR,                /* ORR: op1 = op2 | op3, update the status register */
84         RVM_PUSH,
85         RVM_POP,
86         RVM_CMP,
87         RVM_NOP,
88         RVM_BEQ,                /* Branch if equal */
89         RVM_BNEQ,               /* Branch if not equal */
90         RVM_BLEQ,               /* Branch if less or equal */
91         RVM_BGEQ,               /* Branch if greater or equal */
92         RVM_BLES,               /* Branch if less */
93         RVM_BGRE,               /* Branch if greater */
94         RVM_RET,
95         RVM_ROR,                /* Rotate right, the last bit rotated out updates the Carry flag */
96         RVM_PUSHM,
97         RVM_POPM,
98         RVM_TST,
99         RVM_TEQ,
100         RVM_CLR,                /* Clear op1. If the reg has dynamic memory associated with with it (RVM_INFOBIT_ROBJECT) it will be cleared */
101         RVM_REF,                /* Increase reference in op1 if it is refreg type */
102
103
104 /* Extended VM opcodes, */
105         RVM_CAST,               /* Cast: op1 = (op3)op2 */
106         RVM_TYPE,               /* Type: op1 = typeof(op2) */
107         RVM_EMOV,
108         RVM_EADD,               /* Add: op1 = op2 + op3 */
109         RVM_ESUB,               /* Subtract: op1 = op2 - op3 */
110         RVM_EMUL,               /* Multiply: op1 = op2 * op3 */
111         RVM_EDIV,               /* Divide: op1 = op2 / op3 */
112         RVM_ELSL,               /* Logical Shift Left: op1 = op2 << op3, update the status register */
113         RVM_ELSR,               /* Logical Shift Right: op1 = op2 >> op3, update the status register */
114         RVM_EAND,               /* Bitwise AND: op1 = op2 & op3, update status register */
115         RVM_EORR,               /* Logical OR: op1 = op2 | op3, update the status register */
116         RVM_EXOR,               /* LOGICAL XOR: op1 = op2 ^ op3, update the status register */
117         RVM_ENOT,               /* Bitwise NOT: op1 = ~op2, Update the status register */
118         RVM_ECMP,               /* Compare: status register is updated based on the result: op1 - op2 */
119         RVM_ECMN,               /* Compare Negative: status register is updated based on the result: op1 + op2 */
120         RVM_ALLOCSTR    /* Allocate string in op1, op2 is pointer (char*) to string, op3 is the size */
121 };
122
123
124 #define RVM_DTYPE_NONE 0
125 #define RVM_DTYPE_WORD RVM_DTYPE_NONE
126 #define RVM_DTYPE_UNSIGNED RVM_DTYPE_NONE
127 #define RVM_DTYPE_LONG 1
128 #define RVM_DTYPE_POINTER 2                     /* Generic pointer, it can point to any memory object */
129 #define RVM_DTYPE_DOUBLE 3
130 #define RVM_DTYPE_BOOLEAN 4
131 #define RVM_DTYPE_STRING 5
132 #define RVM_DTYPE_ARRAY 6
133 #define RVM_DTYPE_HARRAY 7
134 #define RVM_DTYPE_REFREG 8                      /* Reference pointer, points to another rrefreg_t object */
135 #define RVM_DTYPE_RELOCPTR 14           /* Relocation, using pointers */
136 #define RVM_DTYPE_RELOCINDEX 15         /* Relocation, using offsets */
137 #define RVM_DTYPE_USER 16
138 #define RVM_DTYPE_SIZE (1 << 5)
139 #define RVM_DTYPE_MASK (RVM_DTYPE_SIZE - 1)
140 #define RVM_DTYPE_MAX (RVM_DTYPE_MASK)
141 #define RVM_DTYPE_USERDEF(__n__) (RVM_DTYPE_USER + (__n__))
142
143 #define RVM_INFOBIT_ROBJECT (1 << 0)
144 #define RVM_INFOBIT_LAST (1 << 15)
145 #define RVM_INFOBIT_ALL (RVM_INFOBIT_ROBJECT | RVM_INFOBIT_LAST)
146
147 #define RVM_REGISTER_BITS (8 * sizeof(rword))
148 #define RVM_SIGN_BIT (1LU << (RVM_REGISTER_BITS - 1))
149 #define RVM_STATUS_Z (1 << 0)
150 #define RVM_STATUS_N (1 << 1)
151 #define RVM_STATUS_C (1 << 2)
152 #define RVM_STATUS_V (1 << 3)
153 #define RVM_STATUS_GETBIT(cpu, bit) ((cpu)->status & (bit))
154 #define RVM_STATUS_SETBIT(cpu, bit) do { (cpu)->status |= (bit); } while (0)
155 #define RVM_STATUS_CLRBIT(cpu, bit) do { (cpu)->status &= ~(bit); } while (0)
156 #define RVM_STATUS_CLRALL(cpu) RVM_STATUS_CLRBIT(cpu, (RVM_STATUS_Z | RVM_STATUS_N | RVM_STATUS_C | RVM_STATUS_V))
157
158 #define RVM_STATUS_UPDATE(cpu, b, c) \
159 do { \
160     if (c) \
161         RVM_STATUS_SETBIT(cpu, b); \
162     else \
163         RVM_STATUS_CLRBIT(cpu, b); \
164 } while (0)
165
166
167 #define R0 0
168 #define R1 1
169 #define R2 2
170 #define R3 3
171 #define R4 4
172 #define R5 5
173 #define R6 6
174 #define R7 7
175 #define R8 8
176 #define R9 9
177 #define R10 10
178 #define R11 11
179 #define R12 12
180 #define R13 13
181 #define R14 14
182 #define R15 15
183 #define R16 16
184 #define R17 17
185 #define R18 18
186 #define R19 19
187 #define R20 20
188 #define R21 21
189 #define R22 22
190 #define R23 23
191 #define R24 24
192 #define R25 25
193 #define R26 26
194 #define R27 27
195 #define R28 28
196 #define R29 29
197 #define R30 30
198 #define R31 31
199
200 #define FP R26
201 #define SP R27
202 #define LR R28
203 #define PC R29
204 #define DA 30           /* The DA register should never be modified manually, otherwise the result is undefined */
205 #define XX 31
206 #define RLST 31
207
208 #define RVM_STACK_CHUNK 256
209 #define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; ASSERT(0); return; } while (0)
210 #define BIT(__shiftby__) (1 << (__shiftby__))
211
212 #define RVM_CPUREG_PTR(__cpu__, __r__) (&(__cpu__)->r[(__r__)])
213 #define RVM_CPUREG_GET(__cpu__, __r__) (__cpu__)->r[(__r__)]
214 #define RVM_CPUREG_SET(__cpu__, __r__, __val__) do { (__cpu__)->r[(__r__)] = (rvmreg_t)(__val__); } while (0)
215
216 #define RVM_REG_GETTYPE(__r__) (__r__)->type
217 #define RVM_REG_SETTYPE(__r__, __val__) do { (__r__)->type = (__val__); } while(0);
218 #define RVM_CPUREG_GETTYPE(__cpu__, __r__) RVM_REG_GETTYPE(RVM_CPUREG_PTR(__cpu__, __r__))
219 #define RVM_CPUREG_SETTYPE(__cpu__, __r__, __val__) RVM_REG_SETTYPE(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
220
221 #define RVM_REG_TSTFLAG(__r__, __flag__) ((__r__)->flags & (__flag__)) ? TRUE : FALSE
222 #define RVM_REG_SETFLAG(__r__, __flag__) do { (__r__)->flags |= (__flag__); } while (0)
223 #define RVM_REG_CLRFLAG(__r__, __flag__) do { (__r__)->flags &= ~(__flag__); } while (0)
224 #define RVM_CPUREG_TSTFLAG(__cpu__, __r__, __flag__) RVM_REG_TSTFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
225 #define RVM_CPUREG_SETFLAG(__cpu__, __r__, __flag__) RVM_REG_SETFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
226 #define RVM_CPUREG_CLRFLAG(__cpu__, __r__, __flag__) RVM_REG_CLRFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
227
228 #define RVM_REG_GETU(__r__) (__r__)->v.w
229 #define RVM_REG_SETU(__r__, __val__) do { (__r__)->v.w = (rword)(__val__); } while (0)
230 #define RVM_CPUREG_GETU(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.w
231 #define RVM_CPUREG_SETU(__cpu__, __r__, __val__) RVM_REG_SETU(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
232
233 #define RVM_REG_GETL(__r__) (__r__)->v.l
234 #define RVM_REG_SETL(__r__, __val__) do { (__r__)->v.l = (rlong)(__val__); } while (0)
235 #define RVM_CPUREG_GETL(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.l
236 #define RVM_CPUREG_SETL(__cpu__, __r__, __val__) RVM_REG_SETL(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
237
238 #define RVM_REG_GETP(__r__) (__r__)->v.p
239 #define RVM_REG_SETP(__r__, __val__) do { (__r__)->v.p = (rpointer)(__val__); } while (0)
240 #define RVM_CPUREG_GETP(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.p
241 #define RVM_CPUREG_SETP(__cpu__, __r__, __val__) RVM_REG_SETP(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
242
243 #define RVM_REG_GETD(__r__) (__r__)->v.d
244 #define RVM_REG_SETD(__r__, __val__) do { (__r__)->v.d = (rdouble)(__val__); } while (0)
245 #define RVM_CPUREG_GETD(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.d
246 #define RVM_CPUREG_SETD(__cpu__, __r__, __val__) RVM_REG_SETD(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
247
248 #define RVM_REG_GETIP(__r__) (rvm_asmins_t*)((__r__)->v.p)
249 #define RVM_REG_SETIP(__r__, __val__) do { (__r__)->v.p = (rpointer)(__val__); } while (0)
250 #define RVM_REG_INCIP(__r__, __val__) do {rvm_asmins_t *p = RVM_REG_GETIP(__r__); (__r__)->v.p = (rpointer)(p + (__val__)); } while (0)
251 #define RVM_CPUREG_GETIP(__cpu__, __r__) ((rvm_asmins_t*)RVM_CPUREG_PTR(__cpu__, __r__)->v.p)
252 #define RVM_CPUREG_SETIP(__cpu__, __r__, __val__) RVM_REG_SETIP(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
253 #define RVM_CPUREG_INCIP(__cpu__, __r__, __val__) do {rvm_asmins_t *p = RVM_CPUREG_GETIP(__cpu__, __r__); (__cpu__)->r[(__r__)].v.p = (rpointer)(p + (__val__)); } while (0)
254
255 #define RVM_REG_SIZE(__r__) (__r__)->size
256 //#define RVM_REG_REF(__r__) do { if (rvm_reg_gettype(__r__) == RVM_DTYPE_REFREG) r_ref_inc((rref_t*)RVM_REG_GETP(__r__));} while (0)
257 //#define RVM_REG_UNREF(__r__) do { if (rvm_reg_gettype(__r__) == RVM_DTYPE_REFREG) r_ref_dec((rref_t*)RVM_REG_GETP(__r__));} while (0)
258 #define RVM_REG_CLEAR(__r__) do { (__r__)->v.w = 0UL; (__r__)->type = 0; (__r__)->flags = 0;  } while (0)
259 #define RVM_CPUREG_CLEAR(__cpu__, __r__) RVM_REG_CLEAR(RVM_CPUREG_PTR(__cpu__, __r__))
260
261
262 #define RVM_OPCODE_BITS 8
263 #define RVM_SWI_TABLE_BITS 10
264 #define RVM_SWI_NUM_BITS 8
265 #define RVM_SWI_TABLE(__op__) ((__op__) >> RVM_SWI_NUM_BITS)
266 #define RVM_SWI_NUM(__op__) ((__op__) & ((1 << RVM_SWI_NUM_BITS) - 1))
267 #define RVM_SWI_ID(__t__, __o__) ((((__t__) & ((1 << RVM_SWI_TABLE_BITS) - 1))  << RVM_SWI_NUM_BITS) | ((__o__) & ((1 << RVM_SWI_NUM_BITS) - 1)))
268 #define RVM_ASMINS_OPCODE(__opcode__) ((__opcode__) & ((1 << RVM_OPCODE_BITS) - 1))
269 #define RVM_ASMINS_SWI(__opcode__) ((__opcode__) >> RVM_OPCODE_BITS)
270 #define RVM_OPSWI(__id__) (((__id__) << RVM_OPCODE_BITS) | RVM_SWI)
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_ILLEGALDST        (6)
278
279 typedef struct rvm_asmins_s rvm_asmins_t;
280 typedef struct rvmcpu_s rvmcpu_t;
281 typedef void (*rvmcpu_swi)(rvmcpu_t *cpu, rvm_asmins_t *ins);
282 typedef void (*rvm_cpu_op)(rvmcpu_t *cpu, rvm_asmins_t *ins);
283
284 typedef struct rvm_switable_s {
285         const char *name;
286         rvmcpu_swi op;
287 } rvm_switable_t;
288
289
290 typedef ruint16 rvmreg_type_t;
291 typedef ruint16 rvmreg_flags_t;
292
293 typedef struct rvmreg_s {
294         union {
295                 rword w;
296                 rlong l;
297                 rpointer p;
298                 rdouble d;
299                 ruint8 c[RVM_MIN_REGSIZE];
300         } v;
301         rvmreg_type_t type;
302         rvmreg_flags_t flags;
303         ruint32 size;
304 } rvmreg_t;
305
306 #define RVM_ASMINS_RELOC (1 << 0)
307 #define RVM_ASMINS_RELOCPTR (1 << 1)
308
309 struct rvm_asmins_s {
310         union {
311                 rword u;
312                 rdouble d;
313         } data;
314         ruint16 op1:5;
315         ruint16 op2:5;
316         ruint16 op3:5;
317         ruint32 opcode:7;
318         ruint32 swi:18;
319         ruint32 type:3;
320         ruint32 flags:4;
321 };
322
323 struct rvm_opmap_s;
324
325 struct rvmcpu_s {
326         rvmreg_t r[DA + 1];
327         rword status;
328         rword error;
329         rword abort;
330         rarray_t *switables;
331         rarray_t *stack;
332         struct rvm_opmap_s *opmap;
333         void *userdata;
334 };
335
336
337 rvmcpu_t *rvm_cpu_create();
338 void rvm_cpu_destroy(rvmcpu_t * vm);
339 rint rvmcpu_switable_add(rvmcpu_t * cpu, rvm_switable_t *switalbe);
340 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
341 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
342 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname);
343 void rvm_relocate(rvm_asmins_t *code, rsize_t size);
344 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data);
345 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data);
346 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data);
347 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data);
348 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
349 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
350 void rvm_asm_dump(rvm_asmins_t *pi, ruint count);
351
352
353 #ifdef __cplusplus
354 }
355 #endif
356
357
358 #endif