finsh_vm.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * Virtual machine of finsh shell.
  3. *
  4. * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
  5. *
  6. * This file is part of RT-Thread (http://www.rt-thread.org)
  7. * Maintainer: bernard.xiong <bernard.xiong at gmail.com>
  8. *
  9. * All rights reserved.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with this program; if not, write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  24. *
  25. * Change Logs:
  26. * Date Author Notes
  27. * 2010-03-22 Bernard first version
  28. */
  29. #include <finsh.h>
  30. #include "finsh_vm.h"
  31. #include "finsh_ops.h"
  32. #include "finsh_var.h"
  33. /* stack */
  34. union finsh_value finsh_vm_stack[FINSH_STACK_MAX];
  35. /* text segment */
  36. u_char text_segment[FINSH_TEXT_MAX];
  37. union finsh_value* finsh_sp; /* stack pointer */
  38. u_char* finsh_pc; /* PC */
  39. /* syscall list, for dynamic system call register */
  40. struct finsh_syscall_item* global_syscall_list = NULL;
  41. // #define FINSH_VM_DISASSEMBLE
  42. void finsh_vm_run()
  43. {
  44. u_char op;
  45. /* if you want to disassemble the byte code, please define FINSH_VM_DISASSEMBLE */
  46. #ifdef FINSH_VM_DISASSEMBLE
  47. void finsh_disassemble();
  48. finsh_disassemble();
  49. #endif
  50. /* set sp(stack pointer) to the beginning of stack */
  51. finsh_sp = &finsh_vm_stack[0];
  52. /* set pc to the beginning of text segment */
  53. finsh_pc = &text_segment[0];
  54. while ((finsh_pc - &text_segment[0] >= 0) &&
  55. (finsh_pc - &text_segment[0] < FINSH_TEXT_MAX))
  56. {
  57. /* get op */
  58. op = *finsh_pc++;
  59. /* call op function */
  60. op_table[op]();
  61. }
  62. }
  63. #ifdef RT_USING_HEAP
  64. extern char *strdup(const char *s);
  65. void finsh_syscall_append(const char* name, syscall_func func)
  66. {
  67. /* create the syscall */
  68. struct finsh_syscall_item* item;
  69. item = (struct finsh_syscall_item*)rt_malloc(sizeof(struct finsh_syscall_item));
  70. if (item != RT_NULL)
  71. {
  72. item->next = NULL;
  73. item->syscall.name = strdup(name);
  74. item->syscall.func = func;
  75. if (global_syscall_list == NULL)
  76. {
  77. global_syscall_list = item;
  78. }
  79. else
  80. {
  81. item->next = global_syscall_list;
  82. global_syscall_list = item;
  83. }
  84. }
  85. }
  86. #endif
  87. #if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__))
  88. struct finsh_syscall* finsh_syscall_next(struct finsh_syscall* call)
  89. {
  90. unsigned int *ptr;
  91. ptr = (unsigned int*) (call + 1);
  92. while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _syscall_table_end))
  93. ptr ++;
  94. return (struct finsh_syscall*)ptr;
  95. }
  96. struct finsh_sysvar* finsh_sysvar_next(struct finsh_sysvar* call)
  97. {
  98. unsigned int *ptr;
  99. ptr = (unsigned int*) (call + 1);
  100. while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _sysvar_table_end))
  101. ptr ++;
  102. return (struct finsh_sysvar*)ptr;
  103. }
  104. #endif
  105. struct finsh_syscall* finsh_syscall_lookup(const char* name)
  106. {
  107. struct finsh_syscall* index;
  108. struct finsh_syscall_item* item;
  109. for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
  110. {
  111. if (strcmp(index->name, name) == 0)
  112. return index;
  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. item = item->next;
  123. }
  124. return NULL;
  125. }
  126. #ifdef FINSH_VM_DISASSEMBLE
  127. void finsh_disassemble()
  128. {
  129. u_char *pc, op;
  130. pc = &text_segment[0];
  131. while (*pc != 0)
  132. {
  133. op = *pc;
  134. switch (op)
  135. {
  136. case FINSH_OP_ADD_BYTE:
  137. pc ++;
  138. rt_kprintf("addb\n");
  139. break;
  140. case FINSH_OP_SUB_BYTE:
  141. pc ++;
  142. rt_kprintf("subb\n");
  143. break;
  144. case FINSH_OP_DIV_BYTE:
  145. pc ++;
  146. rt_kprintf("divb\n");
  147. break;
  148. case FINSH_OP_MOD_BYTE:
  149. pc ++;
  150. rt_kprintf("modb\n");
  151. break;
  152. case FINSH_OP_MUL_BYTE:
  153. pc ++;
  154. rt_kprintf("mulb\n");
  155. break;
  156. case FINSH_OP_AND_BYTE:
  157. pc ++;
  158. rt_kprintf("andb\n");
  159. break;
  160. case FINSH_OP_OR_BYTE:
  161. pc ++;
  162. rt_kprintf("orb\n");
  163. break;
  164. case FINSH_OP_XOR_BYTE:
  165. pc ++;
  166. rt_kprintf("xorb\n");
  167. break;
  168. case FINSH_OP_BITWISE_BYTE:
  169. pc ++;
  170. rt_kprintf("bwb\n");
  171. break;
  172. case FINSH_OP_SHL_BYTE:
  173. pc ++;
  174. rt_kprintf("shlb\n");
  175. break;
  176. case FINSH_OP_SHR_BYTE:
  177. pc ++;
  178. rt_kprintf("shrb\n");
  179. break;
  180. case FINSH_OP_LD_BYTE:
  181. pc ++;
  182. rt_kprintf("ldb %d\n", *pc++);
  183. break;
  184. case FINSH_OP_LD_VALUE_BYTE:
  185. pc ++;
  186. rt_kprintf("ldb [0x%x]\n", FINSH_GET32(pc));
  187. pc += 4;
  188. break;
  189. case FINSH_OP_ST_BYTE:
  190. pc ++;
  191. rt_kprintf("stb\n");
  192. break;
  193. case FINSH_OP_ADD_WORD:
  194. pc ++;
  195. rt_kprintf("addw\n");
  196. break;
  197. case FINSH_OP_SUB_WORD:
  198. pc ++;
  199. rt_kprintf("subw\n");
  200. break;
  201. case FINSH_OP_DIV_WORD:
  202. pc ++;
  203. rt_kprintf("divw\n");
  204. break;
  205. case FINSH_OP_MOD_WORD:
  206. pc ++;
  207. rt_kprintf("modw\n");
  208. break;
  209. case FINSH_OP_MUL_WORD:
  210. pc ++;
  211. rt_kprintf("mulw\n");
  212. break;
  213. case FINSH_OP_AND_WORD:
  214. pc ++;
  215. rt_kprintf("andw\n");
  216. break;
  217. case FINSH_OP_OR_WORD:
  218. pc ++;
  219. rt_kprintf("orw\n");
  220. break;
  221. case FINSH_OP_XOR_WORD:
  222. pc ++;
  223. rt_kprintf("xorw\n");
  224. break;
  225. case FINSH_OP_BITWISE_WORD:
  226. pc ++;
  227. rt_kprintf("bww\n");
  228. break;
  229. case FINSH_OP_SHL_WORD:
  230. pc ++;
  231. rt_kprintf("shlw\n");
  232. break;
  233. case FINSH_OP_SHR_WORD:
  234. pc ++;
  235. rt_kprintf("shrw\n");
  236. break;
  237. case FINSH_OP_LD_WORD:
  238. pc ++;
  239. rt_kprintf("ldw %d\n", FINSH_GET16(pc));
  240. pc += 2;
  241. break;
  242. case FINSH_OP_LD_VALUE_WORD:
  243. pc ++;
  244. rt_kprintf("ldw [0x%x]\n", FINSH_GET32(pc));
  245. pc += 4;
  246. break;
  247. case FINSH_OP_ST_WORD:
  248. pc ++;
  249. rt_kprintf("stw\n");
  250. break;
  251. case FINSH_OP_ADD_DWORD:
  252. pc ++;
  253. rt_kprintf("addd\n");
  254. break;
  255. case FINSH_OP_SUB_DWORD:
  256. pc ++;
  257. rt_kprintf("subd\n");
  258. break;
  259. case FINSH_OP_DIV_DWORD:
  260. pc ++;
  261. rt_kprintf("divd\n");
  262. break;
  263. case FINSH_OP_MOD_DWORD:
  264. pc ++;
  265. rt_kprintf("modd\n");
  266. break;
  267. case FINSH_OP_MUL_DWORD:
  268. pc ++;
  269. rt_kprintf("muld\n");
  270. break;
  271. case FINSH_OP_AND_DWORD:
  272. pc ++;
  273. rt_kprintf("andd\n");
  274. break;
  275. case FINSH_OP_OR_DWORD:
  276. pc ++;
  277. rt_kprintf("ord\n");
  278. break;
  279. case FINSH_OP_XOR_DWORD:
  280. pc ++;
  281. rt_kprintf("xord\n");
  282. break;
  283. case FINSH_OP_BITWISE_DWORD:
  284. pc ++;
  285. rt_kprintf("bwd\n");
  286. break;
  287. case FINSH_OP_SHL_DWORD:
  288. pc ++;
  289. rt_kprintf("shld\n");
  290. break;
  291. case FINSH_OP_SHR_DWORD:
  292. pc ++;
  293. rt_kprintf("shrd\n");
  294. break;
  295. case FINSH_OP_LD_DWORD:
  296. pc ++;
  297. rt_kprintf("ldd 0x%x\n", FINSH_GET32(pc));
  298. pc += 4;
  299. break;
  300. case FINSH_OP_LD_VALUE_DWORD:
  301. pc ++;
  302. rt_kprintf("ldd [0x%x]\n", FINSH_GET32(pc));
  303. pc += 4;
  304. break;
  305. case FINSH_OP_ST_DWORD:
  306. pc ++;
  307. rt_kprintf("std\n");
  308. break;
  309. case FINSH_OP_POP:
  310. rt_kprintf("pop\n");
  311. pc ++;
  312. break;
  313. case FINSH_OP_SYSCALL:
  314. pc ++;
  315. rt_kprintf("syscall %d\n", *pc++);
  316. break;
  317. case FINSH_OP_LD_VALUE_BYTE_STACK:
  318. pc ++;
  319. rt_kprintf("ldb [sp]\n");
  320. break;
  321. case FINSH_OP_LD_VALUE_WORD_STACK:
  322. pc ++;
  323. rt_kprintf("ldw [sp]\n");
  324. break;
  325. case FINSH_OP_LD_VALUE_DWORD_STACK:
  326. pc ++;
  327. rt_kprintf("ldd [sp]\n");
  328. break;
  329. default:
  330. return;
  331. }
  332. }
  333. }
  334. #endif