fvm.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <assert.h>
  5. #include "fvm.h"
  6. int fvm_init(struct fvm *vm, void *code, int64_t stack_size) {
  7. void *stack_vm = malloc(stack_size);
  8. vm->sp = (fvm_word_t)(stack_vm + stack_size);
  9. vm->bp = vm->sp;
  10. vm->pc = (fvm_word_t)code;
  11. vm->rv = 0;
  12. return 1;
  13. }
  14. void fvm_push(struct fvm *vm, fvm_word_t val) {
  15. vm->sp -= sizeof(fvm_word_t);
  16. fvm_store(vm, vm->sp, val);
  17. }
  18. int64_t fvm_pop(struct fvm *vm) {
  19. int64_t r = fvm_load(vm, vm->sp);
  20. vm->sp += sizeof(fvm_word_t);
  21. return r;
  22. }
  23. void fvm_pushf(struct fvm *vm, fvm_float_t val) {
  24. assert(sizeof(fvm_word_t) >= sizeof(fvm_float_t));
  25. vm->sp -= sizeof(fvm_word_t);
  26. fvm_storef(vm, vm->sp, val);
  27. }
  28. fvm_float_t fvm_popf(struct fvm *vm) {
  29. assert(sizeof(fvm_word_t) >= sizeof(fvm_float_t));
  30. fvm_float_t r = fvm_loadf(vm, vm->sp);
  31. vm->sp += sizeof(fvm_word_t);
  32. return r;
  33. }
  34. fvm_float_t fvm_loadf(struct fvm *vm, fvm_word_t addr) {
  35. return *(fvm_float_t*)addr;
  36. }
  37. void fvm_storef(struct fvm *vm, fvm_word_t addr, fvm_float_t val) {
  38. *(fvm_float_t*)addr = val;
  39. }
  40. fvm_word_t fvm_load(struct fvm *vm, fvm_word_t addr) {
  41. return *(fvm_word_t*)addr;
  42. }
  43. void fvm_store(struct fvm *vm, fvm_word_t addr, int64_t value) {
  44. *(fvm_word_t*)addr = value;
  45. }
  46. int32_t fvm_load32(struct fvm *vm, fvm_word_t addr) {
  47. return *(int32_t*)addr;
  48. }
  49. void fvm_store32(struct fvm *vm, fvm_word_t addr, int32_t value) {
  50. *(int32_t*)addr = value;
  51. }
  52. int16_t fvm_load16(struct fvm *vm, fvm_word_t addr) {
  53. return *(int16_t*)addr;
  54. }
  55. void fvm_store16(struct fvm *vm, fvm_word_t addr, int16_t value) {
  56. *(int16_t*)addr = value;
  57. }
  58. int8_t fvm_load8(struct fvm *vm, fvm_word_t addr) {
  59. return *(int8_t*)addr;
  60. }
  61. void fvm_store8(struct fvm *vm, fvm_word_t addr, int8_t value) {
  62. *(int8_t*)addr = value;
  63. }
  64. int64_t fvm_execute(struct fvm *vm) {
  65. fvm_word_t a, b, c;
  66. fvm_float_t x, y, z;
  67. while (1) {
  68. enum fvm_op op = (enum fvm_op)(uint8_t)fvm_load8(vm, vm->pc);
  69. switch (op) {
  70. case FVM_OP_SP:
  71. a = vm->sp;
  72. fvm_push(vm, a);
  73. vm->pc++;
  74. break;
  75. case FVM_OP_SSP:
  76. vm->sp = fvm_pop(vm);
  77. vm->pc++;
  78. break;
  79. case FVM_OP_BP:
  80. fvm_push(vm, vm->bp);
  81. vm->pc++;
  82. break;
  83. case FVM_OP_SBP:
  84. vm->bp = fvm_pop(vm);
  85. vm->pc++;
  86. break;
  87. case FVM_OP_RV:
  88. a = vm->rv;
  89. fvm_push(vm, a);
  90. vm->pc++;
  91. break;
  92. case FVM_OP_SRV:
  93. vm->rv = fvm_pop(vm);
  94. vm->pc++;
  95. break;
  96. case FVM_OP_PC:
  97. fvm_push(vm, vm->pc);
  98. vm->pc++;
  99. break;
  100. case FVM_OP_IMM:
  101. fvm_push(vm, fvm_load(vm, vm->pc + 1));
  102. vm->pc += sizeof(fvm_word_t) + 1;
  103. break;
  104. case FVM_OP_LD:
  105. fvm_push(vm, fvm_load(vm, fvm_pop(vm)));
  106. vm->pc++;
  107. break;
  108. case FVM_OP_LD32:
  109. fvm_push(vm, fvm_load32(vm, fvm_pop(vm)));
  110. vm->pc++;
  111. break;
  112. case FVM_OP_LD16:
  113. fvm_push(vm, fvm_load16(vm, fvm_pop(vm)));
  114. vm->pc++;
  115. break;
  116. case FVM_OP_LD8:
  117. fvm_push(vm, fvm_load8(vm, fvm_pop(vm)));
  118. vm->pc++;
  119. break;
  120. case FVM_OP_ST:
  121. b = fvm_pop(vm);
  122. a = fvm_pop(vm);
  123. fvm_store(vm, b, a);
  124. vm->pc++;
  125. break;
  126. case FVM_OP_ST32:
  127. b = fvm_pop(vm);
  128. a = fvm_pop(vm);
  129. fvm_store32(vm, b, a);
  130. vm->pc++;
  131. break;
  132. case FVM_OP_ST16:
  133. b = fvm_pop(vm);
  134. a = fvm_pop(vm);
  135. fvm_store16(vm, b, a);
  136. vm->pc++;
  137. break;
  138. case FVM_OP_ST8:
  139. b = fvm_pop(vm);
  140. a = fvm_pop(vm);
  141. fvm_store8(vm, b, a);
  142. vm->pc++;
  143. break;
  144. case FVM_OP_DUP:
  145. a = fvm_pop(vm);
  146. fvm_push(vm, a);
  147. fvm_push(vm, a);
  148. vm->pc++;
  149. break;
  150. case FVM_OP_POP:
  151. fvm_pop(vm);
  152. vm->pc++;
  153. break;
  154. case FVM_OP_SWAP:
  155. a = fvm_pop(vm);
  156. b = fvm_pop(vm);
  157. fvm_push(vm, a);
  158. fvm_push(vm, b);
  159. vm->pc++;
  160. break;
  161. case FVM_OP_OVER:
  162. a = fvm_pop(vm);
  163. b = fvm_pop(vm);
  164. fvm_push(vm, b);
  165. fvm_push(vm, a);
  166. fvm_push(vm, b);
  167. vm->pc++;
  168. break;
  169. case FVM_OP_ROT:
  170. a = fvm_pop(vm);
  171. b = fvm_pop(vm);
  172. c = fvm_pop(vm);
  173. fvm_push(vm, b);
  174. fvm_push(vm, a);
  175. fvm_push(vm, c);
  176. vm->pc++;
  177. break;
  178. case FVM_OP_ADD:
  179. a = fvm_pop(vm);
  180. b = fvm_pop(vm);
  181. fvm_push(vm, a + b);
  182. vm->pc++;
  183. break;
  184. case FVM_OP_SUB:
  185. b = fvm_pop(vm);
  186. a = fvm_pop(vm);
  187. fvm_push(vm, a - b);
  188. vm->pc++;
  189. break;
  190. case FVM_OP_MUL:
  191. b = fvm_pop(vm);
  192. a = fvm_pop(vm);
  193. fvm_push(vm, a * b);
  194. vm->pc++;
  195. break;
  196. case FVM_OP_DIV:
  197. b = fvm_pop(vm);
  198. a = fvm_pop(vm);
  199. fvm_push(vm, a / b);
  200. vm->pc++;
  201. break;
  202. case FVM_OP_MOD:
  203. b = fvm_pop(vm);
  204. a = fvm_pop(vm);
  205. fvm_push(vm, a % b);
  206. vm->pc++;
  207. break;
  208. case FVM_OP_SHR:
  209. b = fvm_pop(vm);
  210. a = fvm_pop(vm);
  211. fvm_push(vm, (int64_t)(((uint64_t)a) >> b));
  212. vm->pc++;
  213. break;
  214. case FVM_OP_SHL:
  215. b = fvm_pop(vm);
  216. a = fvm_pop(vm);
  217. fvm_push(vm, a << b);
  218. vm->pc++;
  219. break;
  220. case FVM_OP_SAR:
  221. b = fvm_pop(vm);
  222. a = fvm_pop(vm);
  223. fvm_push(vm, a >> b);
  224. vm->pc++;
  225. break;
  226. case FVM_OP_AND:
  227. b = fvm_pop(vm);
  228. a = fvm_pop(vm);
  229. fvm_push(vm, a && b);
  230. vm->pc++;
  231. break;
  232. case FVM_OP_OR:
  233. b = fvm_pop(vm);
  234. a = fvm_pop(vm);
  235. fvm_push(vm, a || b);
  236. vm->pc++;
  237. break;
  238. case FVM_OP_NOT:
  239. a = fvm_pop(vm);
  240. fvm_push(vm, !a);
  241. vm->pc++;
  242. break;
  243. case FVM_OP_BITAND:
  244. b = fvm_pop(vm);
  245. a = fvm_pop(vm);
  246. fvm_push(vm, a & b);
  247. vm->pc++;
  248. break;
  249. case FVM_OP_BITOR:
  250. b = fvm_pop(vm);
  251. a = fvm_pop(vm);
  252. fvm_push(vm, a | b);
  253. vm->pc++;
  254. break;
  255. case FVM_OP_XOR:
  256. b = fvm_pop(vm);
  257. a = fvm_pop(vm);
  258. fvm_push(vm, a ^ b);
  259. vm->pc++;
  260. break;
  261. case FVM_OP_INVERT:
  262. a = fvm_pop(vm);
  263. fvm_push(vm, ~a);
  264. vm->pc++;
  265. break;
  266. case FVM_OP_GE:
  267. b = fvm_pop(vm);
  268. a = fvm_pop(vm);
  269. fvm_push(vm, a >= b);
  270. vm->pc++;
  271. break;
  272. case FVM_OP_LE:
  273. b = fvm_pop(vm);
  274. a = fvm_pop(vm);
  275. fvm_push(vm, a <= b);
  276. vm->pc++;
  277. break;
  278. case FVM_OP_GT:
  279. b = fvm_pop(vm);
  280. a = fvm_pop(vm);
  281. fvm_push(vm, a > b);
  282. vm->pc++;
  283. break;
  284. case FVM_OP_LT:
  285. b = fvm_pop(vm);
  286. a = fvm_pop(vm);
  287. fvm_push(vm, a < b);
  288. vm->pc++;
  289. break;
  290. case FVM_OP_EQ:
  291. b = fvm_pop(vm);
  292. a = fvm_pop(vm);
  293. fvm_push(vm, a == b);
  294. vm->pc++;
  295. break;
  296. case FVM_OP_NEQ:
  297. b = fvm_pop(vm);
  298. a = fvm_pop(vm);
  299. fvm_push(vm, a != b);
  300. vm->pc++;
  301. break;
  302. case FVM_OP_JMP:
  303. vm->pc = fvm_pop(vm);
  304. break;
  305. case FVM_OP_JZ:
  306. b = fvm_pop(vm);
  307. a = fvm_pop(vm);
  308. if (a) {
  309. vm->pc++;
  310. break;
  311. } else {
  312. vm->pc = b;
  313. break;
  314. }
  315. case FVM_OP_JNZ:
  316. b = fvm_pop(vm);
  317. a = fvm_pop(vm);
  318. if (a) {
  319. vm->pc = b;
  320. break;
  321. } else {
  322. vm->pc++;
  323. break;
  324. }
  325. case FVM_OP_CALL:
  326. a = fvm_pop(vm);
  327. fvm_push(vm, vm->pc);
  328. vm->pc = a;
  329. break;
  330. case FVM_OP_RET:
  331. a = fvm_pop(vm);
  332. vm->pc = a;
  333. break;
  334. case FVM_OP_SYSCALL:
  335. a = fvm_pop(vm);
  336. vm->pc++;
  337. (*(vm->syscall_table[a]))(vm);
  338. break;
  339. case FVM_OP_FADD:
  340. y = fvm_popf(vm);
  341. x = fvm_popf(vm);
  342. fvm_pushf(vm, x + y);
  343. vm->pc++;
  344. break;
  345. case FVM_OP_FSUB:
  346. y = fvm_popf(vm);
  347. x = fvm_popf(vm);
  348. fvm_pushf(vm, x - y);
  349. vm->pc++;
  350. break;
  351. case FVM_OP_FMUL:
  352. y = fvm_popf(vm);
  353. x = fvm_popf(vm);
  354. fvm_pushf(vm, x * y);
  355. vm->pc++;
  356. break;
  357. case FVM_OP_FDIV:
  358. y = fvm_popf(vm);
  359. x = fvm_popf(vm);
  360. fvm_pushf(vm, x / y);
  361. vm->pc++;
  362. break;
  363. case FVM_OP_FGE:
  364. y = fvm_popf(vm);
  365. x = fvm_popf(vm);
  366. fvm_push(vm, x >= y);
  367. vm->pc++;
  368. break;
  369. case FVM_OP_FGT:
  370. y = fvm_popf(vm);
  371. x = fvm_popf(vm);
  372. fvm_push(vm, x > y);
  373. vm->pc++;
  374. break;
  375. case FVM_OP_FLE:
  376. y = fvm_popf(vm);
  377. x = fvm_popf(vm);
  378. fvm_push(vm, x <= y);
  379. vm->pc++;
  380. break;
  381. case FVM_OP_FLT:
  382. y = fvm_popf(vm);
  383. x = fvm_popf(vm);
  384. fvm_push(vm, x < y);
  385. vm->pc++;
  386. break;
  387. case FVM_OP_FEQ:
  388. y = fvm_popf(vm);
  389. x = fvm_popf(vm);
  390. fvm_push(vm, x == y);
  391. vm->pc++;
  392. break;
  393. case FVM_OP_FNEQ:
  394. y = fvm_popf(vm);
  395. x = fvm_popf(vm);
  396. fvm_push(vm, x != y);
  397. vm->pc++;
  398. break;
  399. case FVM_OP_FTI:
  400. x = fvm_popf(vm);
  401. fvm_push(vm, (fvm_word_t)x);
  402. vm->pc++;
  403. break;
  404. case FVM_OP_ITF:
  405. a = fvm_pop(vm);
  406. fvm_pushf(vm, (fvm_float_t)x);
  407. vm->pc++;
  408. break;
  409. case FVM_OP_EXIT:
  410. return vm->rv;
  411. default:
  412. fprintf(stderr, "unknown opcode.\n");
  413. exit(-1);
  414. break;
  415. }
  416. }
  417. return -1;
  418. }