1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2010-03-22 Bernard first version
9 */
10 #include <finsh.h>
11
12 #include "finsh_vm.h"
13 #include "finsh_ops.h"
14 #include "finsh_var.h"
15
16 /* stack */
17 union finsh_value finsh_vm_stack[FINSH_STACK_MAX];
18 /* text segment */
19 uint8_t text_segment[FINSH_TEXT_MAX];
20
21 union finsh_value* finsh_sp; /* stack pointer */
22 uint8_t* finsh_pc; /* PC */
23
24 /* syscall list, for dynamic system call register */
25 struct finsh_syscall_item* global_syscall_list = NULL;
26
27 // #define FINSH_VM_DISASSEMBLE
finsh_vm_run()28 void finsh_vm_run()
29 {
30 uint8_t op;
31
32 /* if you want to disassemble the byte code, please define FINSH_VM_DISASSEMBLE */
33 #ifdef FINSH_VM_DISASSEMBLE
34 void finsh_disassemble();
35 finsh_disassemble();
36 #endif
37
38 /* set sp(stack pointer) to the beginning of stack */
39 finsh_sp = &finsh_vm_stack[0];
40
41 /* set pc to the beginning of text segment */
42 finsh_pc = &text_segment[0];
43
44 while ((finsh_pc - &text_segment[0] >= 0) &&
45 (finsh_pc - &text_segment[0] < FINSH_TEXT_MAX))
46 {
47 /* get op */
48 op = *finsh_pc++;
49
50 /* call op function */
51 op_table[op]();
52 }
53 }
54
55 #ifdef RT_USING_HEAP
finsh_syscall_append(const char * name,syscall_func func)56 void finsh_syscall_append(const char* name, syscall_func func)
57 {
58 /* create the syscall */
59 struct finsh_syscall_item* item;
60
61 item = (struct finsh_syscall_item*)rt_malloc(sizeof(struct finsh_syscall_item));
62 if (item != RT_NULL)
63 {
64 item->next = NULL;
65 item->syscall.name = rt_strdup(name);
66 item->syscall.func = func;
67
68 if (global_syscall_list == NULL)
69 {
70 global_syscall_list = item;
71 }
72 else
73 {
74 item->next = global_syscall_list;
75 global_syscall_list = item;
76 }
77 }
78 }
79 #endif
80
81 #if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__))
finsh_syscall_next(struct finsh_syscall * call)82 struct finsh_syscall* finsh_syscall_next(struct finsh_syscall* call)
83 {
84 unsigned int *ptr;
85 ptr = (unsigned int*) (call + 1);
86 while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _syscall_table_end))
87 ptr ++;
88
89 return (struct finsh_syscall*)ptr;
90 }
91
finsh_sysvar_next(struct finsh_sysvar * call)92 struct finsh_sysvar* finsh_sysvar_next(struct finsh_sysvar* call)
93 {
94 unsigned int *ptr;
95 ptr = (unsigned int*) (call + 1);
96 while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _sysvar_table_end))
97 ptr ++;
98
99 return (struct finsh_sysvar*)ptr;
100 }
101 #endif
102
finsh_syscall_lookup(const char * name)103 struct finsh_syscall* finsh_syscall_lookup(const char* name)
104 {
105 struct finsh_syscall* index;
106 struct finsh_syscall_item* item;
107
108 for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
109 {
110 if (strcmp(index->name, name) == 0)
111 return index;
112 }
113
114 /* find on syscall list */
115 item = global_syscall_list;
116 while (item != NULL)
117 {
118 if (strncmp(item->syscall.name, name, strlen(name)) == 0)
119 {
120 return &(item->syscall);
121 }
122
123 item = item->next;
124 }
125
126 return NULL;
127 }
128
129 #ifdef FINSH_VM_DISASSEMBLE
finsh_disassemble()130 void finsh_disassemble()
131 {
132 uint8_t *pc, op;
133
134 pc = &text_segment[0];
135 while (*pc != 0)
136 {
137 op = *pc;
138 switch (op)
139 {
140 case FINSH_OP_ADD_BYTE:
141 pc ++;
142 rt_kprintf("addb\n");
143 break;
144
145 case FINSH_OP_SUB_BYTE:
146 pc ++;
147 rt_kprintf("subb\n");
148 break;
149
150 case FINSH_OP_DIV_BYTE:
151 pc ++;
152 rt_kprintf("divb\n");
153 break;
154
155 case FINSH_OP_MOD_BYTE:
156 pc ++;
157 rt_kprintf("modb\n");
158 break;
159
160 case FINSH_OP_MUL_BYTE:
161 pc ++;
162 rt_kprintf("mulb\n");
163 break;
164
165 case FINSH_OP_AND_BYTE:
166 pc ++;
167 rt_kprintf("andb\n");
168 break;
169
170 case FINSH_OP_OR_BYTE:
171 pc ++;
172 rt_kprintf("orb\n");
173 break;
174
175 case FINSH_OP_XOR_BYTE:
176 pc ++;
177 rt_kprintf("xorb\n");
178 break;
179
180 case FINSH_OP_BITWISE_BYTE:
181 pc ++;
182 rt_kprintf("bwb\n");
183 break;
184
185 case FINSH_OP_SHL_BYTE:
186 pc ++;
187 rt_kprintf("shlb\n");
188 break;
189
190 case FINSH_OP_SHR_BYTE:
191 pc ++;
192 rt_kprintf("shrb\n");
193 break;
194
195 case FINSH_OP_LD_BYTE:
196 pc ++;
197 rt_kprintf("ldb %d\n", *pc++);
198 break;
199
200 case FINSH_OP_LD_VALUE_BYTE:
201 pc ++;
202 rt_kprintf("ldb [0x%x]\n", FINSH_GET32(pc));
203 pc += 4;
204 break;
205
206 case FINSH_OP_ST_BYTE:
207 pc ++;
208 rt_kprintf("stb\n");
209 break;
210
211 case FINSH_OP_ADD_WORD:
212 pc ++;
213 rt_kprintf("addw\n");
214 break;
215
216 case FINSH_OP_SUB_WORD:
217 pc ++;
218 rt_kprintf("subw\n");
219 break;
220
221 case FINSH_OP_DIV_WORD:
222 pc ++;
223 rt_kprintf("divw\n");
224 break;
225
226 case FINSH_OP_MOD_WORD:
227 pc ++;
228 rt_kprintf("modw\n");
229 break;
230
231 case FINSH_OP_MUL_WORD:
232 pc ++;
233 rt_kprintf("mulw\n");
234 break;
235
236 case FINSH_OP_AND_WORD:
237 pc ++;
238 rt_kprintf("andw\n");
239 break;
240
241 case FINSH_OP_OR_WORD:
242 pc ++;
243 rt_kprintf("orw\n");
244 break;
245
246 case FINSH_OP_XOR_WORD:
247 pc ++;
248 rt_kprintf("xorw\n");
249 break;
250
251 case FINSH_OP_BITWISE_WORD:
252 pc ++;
253 rt_kprintf("bww\n");
254 break;
255
256 case FINSH_OP_SHL_WORD:
257 pc ++;
258 rt_kprintf("shlw\n");
259 break;
260
261 case FINSH_OP_SHR_WORD:
262 pc ++;
263 rt_kprintf("shrw\n");
264 break;
265
266 case FINSH_OP_LD_WORD:
267 pc ++;
268 rt_kprintf("ldw %d\n", FINSH_GET16(pc));
269 pc += 2;
270 break;
271
272 case FINSH_OP_LD_VALUE_WORD:
273 pc ++;
274 rt_kprintf("ldw [0x%x]\n", FINSH_GET32(pc));
275 pc += 4;
276 break;
277
278 case FINSH_OP_ST_WORD:
279 pc ++;
280 rt_kprintf("stw\n");
281 break;
282
283 case FINSH_OP_ADD_DWORD:
284 pc ++;
285 rt_kprintf("addd\n");
286 break;
287
288 case FINSH_OP_SUB_DWORD:
289 pc ++;
290 rt_kprintf("subd\n");
291 break;
292
293 case FINSH_OP_DIV_DWORD:
294 pc ++;
295 rt_kprintf("divd\n");
296 break;
297
298 case FINSH_OP_MOD_DWORD:
299 pc ++;
300 rt_kprintf("modd\n");
301 break;
302
303 case FINSH_OP_MUL_DWORD:
304 pc ++;
305 rt_kprintf("muld\n");
306 break;
307
308 case FINSH_OP_AND_DWORD:
309 pc ++;
310 rt_kprintf("andd\n");
311 break;
312
313 case FINSH_OP_OR_DWORD:
314 pc ++;
315 rt_kprintf("ord\n");
316 break;
317
318 case FINSH_OP_XOR_DWORD:
319 pc ++;
320 rt_kprintf("xord\n");
321 break;
322
323 case FINSH_OP_BITWISE_DWORD:
324 pc ++;
325 rt_kprintf("bwd\n");
326 break;
327
328 case FINSH_OP_SHL_DWORD:
329 pc ++;
330 rt_kprintf("shld\n");
331 break;
332
333 case FINSH_OP_SHR_DWORD:
334 pc ++;
335 rt_kprintf("shrd\n");
336 break;
337
338 case FINSH_OP_LD_DWORD:
339 pc ++;
340 rt_kprintf("ldd 0x%x\n", FINSH_GET32(pc));
341 pc += 4;
342 break;
343
344 case FINSH_OP_LD_VALUE_DWORD:
345 pc ++;
346 rt_kprintf("ldd [0x%x]\n", FINSH_GET32(pc));
347 pc += 4;
348 break;
349
350 case FINSH_OP_ST_DWORD:
351 pc ++;
352 rt_kprintf("std\n");
353 break;
354
355 case FINSH_OP_POP:
356 rt_kprintf("pop\n");
357 pc ++;
358 break;
359
360 case FINSH_OP_SYSCALL:
361 pc ++;
362 rt_kprintf("syscall %d\n", *pc++);
363 break;
364
365 case FINSH_OP_LD_VALUE_BYTE_STACK:
366 pc ++;
367 rt_kprintf("ldb [sp]\n");
368 break;
369
370 case FINSH_OP_LD_VALUE_WORD_STACK:
371 pc ++;
372 rt_kprintf("ldw [sp]\n");
373 break;
374
375 case FINSH_OP_LD_VALUE_DWORD_STACK:
376 pc ++;
377 rt_kprintf("ldd [sp]\n");
378 break;
379
380 default:
381 return;
382 }
383 }
384 }
385 #endif
386