vm_halcode.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /* Copyright (C) 2016 Jeremiah Orians
  2. * This file is part of stage0.
  3. *
  4. * stage0 is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * stage0 is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with stage0. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "vm.h"
  18. #include <unistd.h>
  19. #include <sys/stat.h>
  20. #include <fcntl.h>
  21. FILE* tape_01;
  22. FILE* tape_02;
  23. #ifdef tty_lib
  24. char tty_getchar();
  25. #endif
  26. /* Imported functions */
  27. void writeout_string(struct lilith* vm, char* s, unsigned_vm_register pointer);
  28. char* string_copy(struct lilith* vm, signed_vm_register address);
  29. /******************************************
  30. * Always existing calls *
  31. ******************************************/
  32. void vm_HAL_MEM(struct lilith* vm)
  33. {
  34. vm->reg[0] = vm->amount_of_Ram;
  35. }
  36. void vm_HALT(struct lilith* vm, uint64_t performance_counter)
  37. {
  38. vm->halted = true;
  39. fprintf(stderr, "Computer Program has Halted\nAfter Executing %lu instructions\n", performance_counter);
  40. #ifdef TRACE
  41. record_trace("HALT");
  42. print_traces();
  43. #endif
  44. }
  45. /******************************************
  46. * POSIX specific calls *
  47. ******************************************/
  48. char* SYS_READ_BUF;
  49. void vm_SYS_READ(struct lilith* vm)
  50. {
  51. if(NULL == SYS_READ_BUF) SYS_READ_BUF = calloc(Memory_Size, sizeof(char)); /* 20MB */
  52. int fd = vm->reg[0];
  53. int want = vm->reg[2];
  54. require(want < Memory_Size, "ERROR trying to read more than we have memory\n");
  55. int count = read(fd, SYS_READ_BUF, want);
  56. int i = 0;
  57. while(i < count)
  58. {
  59. vm->memory[vm->reg[1] + i] = SYS_READ_BUF[i];
  60. i = i + 1;
  61. }
  62. vm->reg[0] = count;
  63. }
  64. char* SYS_WRITE_BUF;
  65. void vm_SYS_WRITE(struct lilith* vm)
  66. {
  67. if(NULL == SYS_WRITE_BUF) SYS_WRITE_BUF = calloc(Memory_Size, sizeof(char)); /* 20MB */
  68. int i = 0;
  69. while(i < vm->reg[2])
  70. {
  71. SYS_WRITE_BUF[i] = vm->memory[vm->reg[1] + i];
  72. i = i + 1;
  73. }
  74. int count = write(vm->reg[0], SYS_WRITE_BUF, vm->reg[2]);
  75. vm->reg[0] = count;
  76. }
  77. void vm_SYS_FOPEN(struct lilith* vm)
  78. {
  79. char* s = string_copy(vm, vm->reg[0]);
  80. vm->reg[0] = open(s, vm->reg[1], vm->reg[2]);
  81. free(s);
  82. }
  83. void vm_SYS_FCLOSE(struct lilith* vm)
  84. {
  85. close(vm->reg[0]);
  86. }
  87. void vm_SYS_FSEEK(struct lilith* vm)
  88. {
  89. vm->reg[0] = lseek(vm->reg[0], vm->reg[1], vm->reg[2]);
  90. }
  91. void vm_SYS_EXIT(struct lilith* vm, uint64_t performance_counter)
  92. {
  93. vm->halted = true;
  94. fprintf(stderr, "Computer Program has Halted\nAfter Executing %lu instructions\n", performance_counter);
  95. #ifdef TRACE
  96. record_trace("SYS_EXIT");
  97. print_traces();
  98. #endif
  99. exit(vm->reg[0]);
  100. }
  101. void vm_SYS_CHMOD(struct lilith* vm)
  102. {
  103. char* s = string_copy(vm, vm->reg[0]);
  104. chmod(s, vm->reg[1]);
  105. free(s);
  106. }
  107. void vm_SYS_UNAME(struct lilith* vm)
  108. {
  109. writeout_string(vm, "sysname", vm->reg[0]);
  110. writeout_string(vm, "nodename", vm->reg[0] + 65);
  111. writeout_string(vm, "release", vm->reg[0] + 130);
  112. writeout_string(vm, "version", vm->reg[0] + 195);
  113. writeout_string(vm, arch_name, vm->reg[0] + 260);
  114. }
  115. void vm_SYS_GETCWD(struct lilith* vm)
  116. {
  117. char* s = malloc(vm->reg[1]);
  118. s = getcwd(s, vm->reg[1]);
  119. if(NULL == s)
  120. {
  121. vm->reg[0] = 0;
  122. }
  123. else
  124. {
  125. writeout_string(vm, s, vm->reg[0]);
  126. }
  127. free(s);
  128. }
  129. void vm_SYS_CHDIR(struct lilith* vm)
  130. {
  131. char* s = string_copy(vm, vm->reg[0]);
  132. vm->reg[0] = chdir(s);
  133. free(s);
  134. }
  135. void vm_SYS_FCHDIR(struct lilith* vm)
  136. {
  137. vm->reg[0] = fchdir(vm->reg[0]);
  138. }
  139. void vm_SYS_ACCESS(struct lilith* vm)
  140. {
  141. char* s = string_copy(vm, vm->reg[0]);
  142. vm->reg[0] = access(s, vm->reg[1]);
  143. free(s);
  144. }
  145. /******************************************
  146. * Bare metal specific instructions *
  147. ******************************************/
  148. void vm_FOPEN_READ(struct lilith* vm)
  149. {
  150. struct stat sb;
  151. if(0x00001100 == vm->reg[0])
  152. {
  153. if(-1 == stat(tape_01_name, &sb))
  154. {
  155. fprintf(stderr, "File named %s does not exist\n", tape_01_name);
  156. exit(EXIT_FAILURE);
  157. }
  158. tape_01 = fopen(tape_01_name, "r");
  159. }
  160. if (0x00001101 == vm->reg[0])
  161. {
  162. if(-1 == stat(tape_02_name, &sb))
  163. {
  164. fprintf(stderr, "File named %s does not exist\n", tape_02_name);
  165. exit(EXIT_FAILURE);
  166. }
  167. tape_02 = fopen(tape_02_name, "r");
  168. }
  169. }
  170. void vm_FOPEN_WRITE(struct lilith* vm)
  171. {
  172. if(FUZZING)
  173. {
  174. vm->reg[0] = 0;
  175. }
  176. else
  177. {
  178. if(0x00001100 == vm->reg[0])
  179. {
  180. tape_01 = fopen(tape_01_name, "w");
  181. }
  182. if (0x00001101 == vm->reg[0])
  183. {
  184. tape_02 = fopen(tape_02_name, "w");
  185. }
  186. }
  187. }
  188. void vm_FCLOSE(struct lilith* vm)
  189. {
  190. if(0x00001100 == vm->reg[0])
  191. {
  192. require(NULL != tape_01, "tape_01 not valid for fclose\nAborting to prevent issues\n");
  193. fclose(tape_01);
  194. tape_01 = NULL;
  195. }
  196. if (0x00001101 == vm->reg[0])
  197. {
  198. require(NULL != tape_02, "tape_02 not valid for fclose\nAborting to prevent issues\n");
  199. fclose(tape_02);
  200. tape_02 = NULL;
  201. }
  202. }
  203. void vm_REWIND(struct lilith* vm)
  204. {
  205. if(0x00001100 == vm->reg[0])
  206. {
  207. require(NULL != tape_01, "tape_01 not valid for rewind\nAborting to prevent issues\n");
  208. rewind(tape_01);
  209. }
  210. if (0x00001101 == vm->reg[0])
  211. {
  212. require(NULL != tape_02, "tape_02 not valid for rewind\nAborting to prevent issues\n");
  213. rewind(tape_02);
  214. }
  215. }
  216. void vm_FGETC(struct lilith* vm)
  217. {
  218. signed_vm_register byte = -1;
  219. if (0x00000000 == vm->reg[1])
  220. {
  221. #ifdef tty_lib
  222. byte = tty_getchar();
  223. #endif
  224. #ifndef tty_lib
  225. byte = fgetc(TTY_in);
  226. #endif
  227. }
  228. if(0x00001100 == vm->reg[1])
  229. {
  230. require(NULL != tape_01, "tape_01 not valid for fgetc\nAborting to prevent issues\n");
  231. byte = fgetc(tape_01);
  232. }
  233. if (0x00001101 == vm->reg[1])
  234. {
  235. require(NULL != tape_02, "tape_02 not valid for fgetc\nAborting to prevent issues\n");
  236. byte = fgetc(tape_02);
  237. }
  238. vm->reg[0] = byte;
  239. }
  240. void vm_FPUTC(struct lilith* vm)
  241. {
  242. signed_vm_register byte = vm->reg[0] & 0xFF;
  243. if (0x00000000 == vm->reg[1])
  244. {
  245. fputc(byte, TTY_out);
  246. #ifdef tty_lib
  247. fflush(TTY_out);
  248. #endif
  249. }
  250. if(0x00001100 == vm->reg[1])
  251. {
  252. require(NULL != tape_01, "tape_01 not valid for fputc\nAborting to prevent issues\n");
  253. fputc(byte, tape_01);
  254. }
  255. if (0x00001101 == vm->reg[1])
  256. {
  257. require(NULL != tape_02, "tape_02 not valid for fputc\nAborting to prevent issues\n");
  258. fputc(byte, tape_02);
  259. }
  260. }