vm.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 <getopt.h>
  19. /* Load program tape into Memory */
  20. size_t load_program(struct lilith* vm, char* rom_name)
  21. {
  22. FILE* program;
  23. program = fopen(rom_name, "r");
  24. /* Figure out how much we need to load */
  25. fseek(program, 0, SEEK_END);
  26. size_t end = ftell(program);
  27. rewind(program);
  28. /* Deal with the special case of the ROM is bigger than available memory */
  29. if(end > vm->amount_of_Ram)
  30. {
  31. fprintf(stderr, "Program %s is %d bytes large but only %d bytes of memory have been allocated!\n", rom_name, (int)end, (int)vm->amount_of_Ram);
  32. exit(EXIT_FAILURE);
  33. }
  34. /* Load the entire tape into memory */
  35. fread(vm->memory, 1, end, program);
  36. fclose(program);
  37. return end;
  38. }
  39. void execute_vm(struct lilith* vm)
  40. {
  41. struct Instruction* current;
  42. current = calloc(1, sizeof(struct Instruction));
  43. while(!vm->halted)
  44. {
  45. read_instruction(vm, current);
  46. eval_instruction(vm, current);
  47. }
  48. free(current);
  49. return;
  50. }
  51. /* Standard C main program */
  52. int main(int argc, char **argv)
  53. {
  54. POSIX_MODE = false;
  55. int c;
  56. int Memory_Size = (16 * 1024);
  57. tape_01_name = "tape_01";
  58. tape_02_name = "tape_02";
  59. char* rom_name = NULL;
  60. char class;
  61. static struct option long_options[] = {
  62. {"rom", required_argument, 0, 'r'},
  63. {"tape_01", required_argument, 0, '1'},
  64. {"tape_02", required_argument, 0, '2'},
  65. {"memory", required_argument, 0, 'm'},
  66. {"POSIX-MODE", no_argument, 0, 'P'},
  67. {"help", no_argument, 0, 'h'},
  68. {0, 0, 0, 0}
  69. };
  70. int option_index = 0;
  71. while ((c = getopt_long(argc, argv, "r:h:1:2:m:P", long_options, &option_index)) != -1)
  72. {
  73. switch (c)
  74. {
  75. case 0: break;
  76. case 'r':
  77. {
  78. rom_name = optarg;
  79. break;
  80. }
  81. case 'h':
  82. {
  83. fprintf(stdout, "Usage: %s --rom $rom [--tape_01 $foo] [--tape_02 $bar]\n", argv[0]);
  84. exit(EXIT_SUCCESS);
  85. }
  86. case '1':
  87. {
  88. tape_01_name = optarg;
  89. break;
  90. }
  91. case '2':
  92. {
  93. tape_02_name = optarg;
  94. break;
  95. }
  96. case 'm':
  97. {
  98. int length = strlen(optarg) - 1;
  99. class = optarg[length];
  100. optarg[length] = 0;
  101. Memory_Size = atoi(optarg);
  102. if('K' == class)
  103. {
  104. Memory_Size = Memory_Size * 1024;
  105. }
  106. else if('M' == class)
  107. {
  108. Memory_Size = Memory_Size * 1024 * 1024;
  109. }
  110. else if('G' == class)
  111. {
  112. Memory_Size = Memory_Size * 1024 * 1024 * 1024;
  113. }
  114. break;
  115. }
  116. case 'P':
  117. {
  118. POSIX_MODE = true;
  119. break;
  120. }
  121. default:
  122. {
  123. exit(EXIT_FAILURE);
  124. }
  125. }
  126. }
  127. if(NULL == rom_name)
  128. {
  129. fprintf(stderr, "Usage: %s --rom $rom [--tape_01 $foo] [--tape_02 $bar]\n", argv[0]);
  130. exit(EXIT_FAILURE);
  131. }
  132. /* Perform all the essential stages in order */
  133. struct lilith* vm;
  134. size_t image;
  135. vm = create_vm(Memory_Size);
  136. image = load_program(vm, rom_name);
  137. if(POSIX_MODE) vm->reg[15] = image;
  138. execute_vm(vm);
  139. destroy_vm(vm);
  140. return EXIT_SUCCESS;
  141. }