home *** CD-ROM | disk | FTP | other *** search
/ cs.rhul.ac.uk / www.cs.rhul.ac.uk.zip / www.cs.rhul.ac.uk / pub / rdp / rdp_cs3460.tar / mvmsim.c < prev    next >
C/C++ Source or Header  |  1998-05-07  |  8KB  |  324 lines

  1. /*******************************************************************************
  2. *
  3. * RDP release 1.50 by Adrian Johnstone (A.Johnstone@rhbnc.ac.uk) 20 December 1997
  4. *
  5. * mvmsim.c - Mini Virtual Machine simulator
  6. *
  7. * This file may be freely distributed. Please mail improvements to the author.
  8. *
  9. *******************************************************************************/
  10. #include <time.h>
  11. #include <stdio.h>
  12. #include <math.h>
  13. #include "arg.h"
  14. #include "memalloc.h"
  15. #include "textio.h"
  16. #include "mvm_def.h"
  17.  
  18. #define MEM_SIZE 65536lu
  19. int mvmsim_verbose = 0; 
  20. int mvmsim_echo_load = 0; 
  21. int mvmsim_trace = 0; 
  22. unsigned char memory[MEM_SIZE]; 
  23. unsigned long pc = 0; 
  24. unsigned long exec_count = 0; 
  25. FILE * input_file = NULL; 
  26. int in_char = ' '; 
  27.  
  28. #define get_char in_char = fgetc(input_file)
  29.  
  30. static void test_address(unsigned long address)
  31. {
  32.   if (address >= MEM_SIZE)
  33.   {
  34.     text_printf("\n"); 
  35.     text_message(TEXT_FATAL, "illegal access to location %lu, PC = %lu\n", address, pc); 
  36.   }
  37. }
  38.  
  39. static int get_memory_byte(unsigned long address)
  40. {
  41.   int val; 
  42.   
  43.   test_address(address); 
  44.   val = memory[address]; 
  45.   
  46.   if (val & 0x40)             /* negative? */
  47.     val =(- 1l << 8)| val; 
  48.   
  49.   return val; 
  50. }
  51.  
  52. static int get_memory_word(unsigned long address)
  53. {
  54.   int val; 
  55.   
  56.   test_address(address + 1); 
  57.   val =((int) memory[address]<< 8)|((int) memory[address + 1]); 
  58.   
  59.   if (val & 0x4000)           /* negative? */
  60.     val =(- 1l << 16)| val; 
  61.   
  62.   return val; 
  63. }
  64.  
  65. static void put_memory_byte(unsigned long address, int data)
  66. {
  67.   test_address(address); 
  68.   memory[address]=(unsigned char) data; 
  69. }
  70.  
  71. static void put_memory_word(unsigned long address, int data)
  72. {
  73.   test_address(address + 1); 
  74.   memory[address]=(unsigned char)(data >> 8); 
  75.   memory[address + 1]=(unsigned char) data; 
  76. }
  77.  
  78. static void skip_space(void)
  79. {
  80.   while (in_char == ' ')      /* skip spaces */
  81.     get_char; 
  82. }
  83.  
  84. static long int get1hex(void)
  85. {
  86.   int ret = 0; 
  87.   
  88.   if (in_char >= '0' && in_char <= '9')
  89.     ret = in_char - '0'; 
  90.   else if (in_char >= 'A' && in_char <= 'F')
  91.     ret = in_char - 'A' + 10; 
  92.   else if (in_char >= 'a' && in_char <= 'f')
  93.     ret = in_char - 'a' + 10; 
  94.   else
  95.   {
  96.     text_printf("\n"); 
  97.     text_message(TEXT_FATAL, "unexpected non-hexadecimal character in input file\n"); 
  98.   }
  99.   
  100.   get_char; 
  101.   skip_space(); 
  102.   
  103.   return ret; 
  104. }
  105.  
  106. static long int get2hex(void)
  107. {
  108.   return(get1hex()<< 4)| get1hex(); 
  109. }
  110.  
  111. static long int get4hex(void)
  112. {
  113.   return(get2hex()<< 8)| get2hex(); 
  114. }
  115.  
  116. static void mvmsim_load(void)
  117. {
  118.   unsigned long address, 
  119.   data; 
  120.   
  121.   while (in_char != EOF)
  122.   {
  123.     while (in_char == '\n' || in_char == ' ')
  124.       get_char;               /* skip empty spaces and lines */
  125.     
  126.     address = get4hex(); 
  127.     
  128.     if (mvmsim_echo_load)
  129.       text_printf("Load address %.4lX ", address); 
  130.     
  131.     if (in_char == '*')       /* get transfer address */
  132.     {
  133.       get_char;               /* skip * */
  134.       pc = get4hex(); 
  135.       if (mvmsim_echo_load)
  136.         text_printf("*%.4lX", pc); 
  137.     }
  138.     else
  139.       while (in_char != '\n')
  140.     {
  141.       data = get2hex(); 
  142.       if (mvmsim_echo_load)
  143.         text_printf("%.2lX", data); 
  144.       put_memory_byte(address++, data); 
  145.     }
  146.     
  147.     get_char;                 /* skip end of line */
  148.     
  149.     if (mvmsim_echo_load)
  150.       text_printf("\n"); 
  151.   }
  152. }
  153.  
  154. static void display(char * op, unsigned dst, unsigned src1, unsigned src2)
  155. {
  156.   if (mvmsim_trace)
  157.     printf("\n%.4X %s %.4X, %.4X, %.4X -> %.4X  ", (unsigned) pc, op, dst & 0xFFFF, src1 & 0xFFFF, src2 & 0xFFFF, get_memory_word(dst)& 0xFFFF); 
  158. }
  159.  
  160. static void mvmsim_execute(void)
  161. {
  162.   int stop = 0; 
  163.   
  164.   while (!stop)
  165.   {
  166.     unsigned op = get_memory_byte(pc), 
  167.     mode = get_memory_byte(pc + 1); 
  168.     int dst = get_memory_word(pc + 2), 
  169.     src1 = get_memory_word(pc + 4), 
  170.     src2 = get_memory_word(pc + 6); 
  171.     
  172.     exec_count++; 
  173.     
  174.     /* do indirections on modes */
  175.     if ((mode >> 4)== 1)
  176.       src1 = get_memory_word(src1); 
  177.     
  178.     if ((mode & 7)== 1)
  179.       src2 = get_memory_word(src2); 
  180.     
  181.     switch (op)
  182.     {
  183.       case OP_ADD: 
  184.       put_memory_word(dst, src1 + src2); 
  185.       display("ADD ", dst, src1, src2); 
  186.       pc += 8; 
  187.       break; 
  188.       case OP_SUB: 
  189.       put_memory_word(dst, src1 - src2); 
  190.       display("SUB ", dst, src1, src2); 
  191.       pc += 8; 
  192.       break; 
  193.       case OP_MUL: 
  194.       put_memory_word(dst, src1 * src2); 
  195.       display("MUL ", dst, src1, src2); 
  196.       pc += 8; 
  197.       break; 
  198.       case OP_DIV: 
  199.       put_memory_word(dst, src1 / src2); 
  200.       display("DIV ", dst, src1, src2); 
  201.       pc += 8; 
  202.       break; 
  203.       case OP_EXP: 
  204.       put_memory_word(dst, (int) pow((double) src1, (double) src2)); 
  205.       display("EXP ", dst, src1, src2); 
  206.       pc += 8; 
  207.       break; 
  208.       case OP_EQ: 
  209.       put_memory_word(dst, src1 == src2); 
  210.       display("EQ  ", dst, src1, src2); 
  211.       pc += 8; 
  212.       break; 
  213.       case OP_NE: 
  214.       put_memory_word(dst, src1 != src2); 
  215.       display("NE  ", dst, src1, src2); 
  216.       pc += 8; 
  217.       break; 
  218.       case OP_GT: 
  219.       put_memory_word(dst, src1 > src2); 
  220.       display("GT  ", dst, src1, src2); 
  221.       pc += 8; 
  222.       break; 
  223.       case OP_GE: 
  224.       put_memory_word(dst, src1 >= src2); 
  225.       display("GE  ", dst, src1, src2); 
  226.       pc += 8; 
  227.       break; 
  228.       case OP_LT: 
  229.       put_memory_word(dst, src1 < src2); 
  230.       display("LT  ", dst, src1, src2); 
  231.       pc += 8; 
  232.       break; 
  233.       case OP_LE: 
  234.       put_memory_word(dst, src1 <= src2); 
  235.       display("LE  ", dst, src1, src2); 
  236.       pc += 8; 
  237.       break; 
  238.       case OP_CPY: 
  239.       put_memory_word(dst, src1); 
  240.       display("CPY ", dst, src1, src2); 
  241.       pc += 6; 
  242.       break; 
  243.       case OP_BNE: 
  244.       display("BNE ", dst, src1, src2); 
  245.       if (src1 != 0)
  246.         pc = dst; 
  247.       else
  248.         pc += 6; 
  249.       break; 
  250.       case OP_BEQ: 
  251.       display("BEQ ", dst, src1, src2); 
  252.       if (src1 == 0)
  253.         pc = dst; 
  254.       else
  255.         pc += 6; 
  256.       break; 
  257.       case OP_PRTS: 
  258.       display("PRTS", dst, src1, src2); 
  259.       printf("%s", memory + src1); 
  260.       pc += 6; 
  261.       break; 
  262.       case OP_PRTI: 
  263.       display("PRTI", dst, src1, src2); 
  264.       printf("%i", (int) src1); 
  265.       pc += 6; 
  266.       break; 
  267.       case OP_HALT: 
  268.       display("HALT", dst, src1, src2); 
  269.       printf(" -- Halted --\n"); 
  270.       stop = 1; 
  271.       pc += 2; 
  272.       break; 
  273.       default: 
  274.       display("----", dst, src1, src2); 
  275.       text_printf("\n"); 
  276.       text_message(TEXT_FATAL, "illegal instruction encountered\n"); 
  277.       break; 
  278.     }
  279.   }
  280. }
  281.  
  282. int main(int argc, char * argv[])
  283. {
  284.   clock_t mvmsim_finish_time, 
  285.   mvmsim_start_time = clock(); 
  286.   char * mvmsim_sourcefilename; 
  287.   
  288.   arg_message("mvmsim v1.5 - simulator for mvm\n\n" "Usage: mvmsim [options] source"); 
  289.   
  290.   arg_message(""); 
  291.   arg_boolean('l', "Show load sequence", & mvmsim_echo_load); 
  292.   arg_boolean('t', "Print execution trace", & mvmsim_trace); 
  293.   arg_boolean('v', "Set verbose mode", & mvmsim_verbose); 
  294.   arg_message(""); 
  295.   arg_message("You can contact the author (Adrian Johnstone) at:"); 
  296.   arg_message(""); 
  297.   arg_message("Computer Science Department, Royal Holloway, University of London"); 
  298.   arg_message("Egham, Surrey, TW20 0EX UK. Email: A.Johnstone@rhbnc.ac.uk"); 
  299.   
  300.   mvmsim_sourcefilename = * arg_process(argc, argv); 
  301.   
  302.   if (mvmsim_sourcefilename == NULL)
  303.     arg_help("No source file specified"); 
  304.   
  305.   if ((input_file = fopen(mvmsim_sourcefilename, "r"))== NULL)
  306.     arg_help("Unable to open source file"); 
  307.   
  308.   if (mvmsim_verbose)
  309.     text_printf("\nmvmsim v1.5 - simulator for mvm\n\n"); 
  310.   
  311.   mvmsim_load(); 
  312.   mvmsim_execute(); 
  313.   
  314.   if (mvmsim_verbose)
  315.   {
  316.     mvmsim_finish_time = clock(); 
  317.     text_printf("\n\n%.3f CPU seconds used, %lu MVM instructions executed\n", ((double)(mvmsim_finish_time - mvmsim_start_time))/ CLOCKS_PER_SEC, exec_count); 
  318.   }
  319.   
  320.   return 0; 
  321. }
  322.  
  323. /* End of mvmsim.c */
  324.