Coder Profile - Show off your skills, get a coder profile.
 
 
 
  
Posted: 2.23 Years Ago 

thoughtpolice
United States
Contrib Level: 4
Total Posts: 89
This is just something I thought you guys might find cool.

All today I've been working on this little virtual machine of mine, and I'm nowhere near done (I'm trying to make it use LLVM for JIT compilation,) but I have gotten it to execute a basic fizzbuzz successfully. :)

Here's the code...

engine.c:
CODE: Copy / Restore  ::  Remove Scroll Bars
  1. /*
  2.     engine.c - actual virtual machine
  3.     Copyright (C) 2008 Austin Seipp
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  18.  */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <math.h>
  22. #include "engine.h"
  23.  
  24. /* we use a RISC-like approach; all opcodes are of the same length
  25.    and we use relative offsets for jumps. all opcodes are 32-bits
  26.    in length (4 seperate bytes)
  27.    program bytecodes (# means number):
  28.     0, x, n, 0 -- set register #x to value n
  29.     0, r1, r2, 1 -- set register #r1 to == register #r2
  30.     1, r1, r2, r3 -- add val in r2 to r3 and store in r1
  31.     2, r1, r2, r3 -- sub val in r2 by r3 and store in r1
  32.     3, r1, r2, r3 -- multiply val in r2 by r3 and store in r1
  33.     4, r1, r2, r3 -- divide val in r2 by r3 and store in r1
  34.     5, r1, r2, r3 -- mod val in r2 by r3 and store in r1
  35.     6, x, 0, 0 -- show reg #x
  36.     7, n, 0, 0 -- jump #n opcodes back/forwards (depends on value)
  37.     8, r, v, 0 -- do-next-if: execute next instruction if val in reg 'r' == v
  38.     9, r, v, 0 -- skip-next-if: skip next instruction if val in reg 'r' == v
  39.     10, r, 0, 0 -- print string at data index 'r'
  40.     11, 0, 0, 0 -- exit
  41.   */
  42.  
  43. void* data[] = { "fizz",
  44.                "buzz",
  45.                "hello world!",
  46.                "goodbye world!" };
  47.  
  48.  
  49. // addition
  50. int program1[] = { 0, 0, 10, 0, // reg 0 = 10
  51.                        0, 1, 20, 0, // reg 1 = 20
  52.                   1, 1, 1, 0, // reg 1 = reg1 + reg0
  53.                  6, 1, 0, 0, // show reg 1
  54.                    11, 0, 0, 0 }; // exit
  55.  
  56. // loop
  57. int program2[] = { 0, 0, 10, 0, // reg 0 = 10
  58.                  0, 1, 1, 0, // reg 1 = 1
  59.                    6, 0, 0, 0, // show reg 0
  60.                    2, 0, 0, 1, // reg 0 = reg 0 - reg 1
  61.                    9, 0, 0, 0, // skip next if reg 0 == 0
  62.                    7, (-3), 0, 0, // jump back 3 instrs
  63.                    11, 0, 0, 0 }; // exit
  64.  
  65. // hello world
  66. int program3[] = { 10, 2, 0, 0, // print "hello world!"
  67.                  10, 3, 0, 0, // print "goodbye world!"
  68.                    11, 0, 0, 0 }; // exit
  69.  
  70. // fizzbuzz
  71. int program4[] = { 0, 0, 15, 0, // reg 0 = 10
  72.                  0, 1, 1, 0, // reg 1 = 1
  73.                  0, 2, 3, 0, // reg 2 = 3
  74.                  0, 3, 5, 0, // reg 3 = 5
  75.                  5, 4, 0, 2, // reg 4 = reg0 % reg2
  76.                  5, 5, 0, 3, // reg 5 = reg0 % reg3
  77.                  6, 0, 0, 0, // show reg 0
  78.                  8, 4, 0, 0, // do next if r4 == 0
  79.                  10, 0, 0, 0, // print 'fizz'
  80.                  8, 5, 0, 0, // do next if r5 == 0
  81.                  10, 1, 0, 0, // print 'buzz'
  82.                  2, 0, 0, 1, // reg 0 = reg 0 - reg 1
  83.                  9, 0, 0, 0, // skip next if r0 == 0
  84.                  7, (-10), 0, 0, // jump back 10 instructions
  85.                    11, 0, 0, 0 }; // exit
  86.  
  87. void run_program_dispatch(char *file, int verbosity, int program) { // we ignore the file for now
  88.   void *func_table[] = { &&set, // byte 0
  89.                       &&add, // byte 1
  90.                       &&sub, // byte 2
  91.                       &&mul, // byte 3
  92.                       &&div, // byte 4
  93.                       &&mod, // byte 5
  94.                       &&show, // byte 6
  95.                       &&jump, // byte 7
  96.                       &&nextif, // byte 8
  97.                       &&skipif, // byte 9
  98.                       &&printstr, // byte 10
  99.                       &&exit }; // byte 11
  100.   int regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  101.   int *ip;
  102.  
  103.   if (program == 1) {
  104.     ip = &program1;
  105.     printf("Executing program1:\n");
  106.   } else if (program == 2) {
  107.     ip = &program2;
  108.     printf("Executing program2:\n");
  109.   } else if (program == 3) {
  110.     ip = &program3;
  111.     printf("Executing program3:\n");
  112.   } else if(program == 4) {
  113.     ip = &program4;
  114.     printf("Executing program4:\n");
  115.   }
  116.  
  117.   goto *func_table[ip[0]];
  118.  
  119.  set:
  120.   if (ip[3] == 0) {
  121.     if (verbosity >= 3)
  122.       printf("[op 0] setting reg %d to val %d\n",ip[1],ip[2]);
  123.     regs[ip[1]] = ip[2];
  124.   } else if (ip[3] == 1) {
  125.     if (verbosity >= 3)
  126.       printf("[op 0] setting reg %d to reg%d(%d)\n",ip[1],ip[2],regs[ip[2]]);
  127.     regs[ip[1]] = regs[ip[2]];
  128.   }
  129.  
  130.   ip += 4;
  131.  
  132.   if (verbosity >= 3)
  133.     printf("[op 0] next op is %d\n",ip[0]);
  134.  
  135.   goto *func_table[ip[0]];
  136.  
  137.  add:
  138.   if (verbosity >= 3)
  139.     printf("[op 1] setting reg%d = reg%d + reg%d (%d)\n",
  140.           ip[1],ip[2],ip[3], regs[ip[2]] + regs[ip[3]]);
  141.  
  142.   regs[ip[1]] = regs[ip[2]] + regs[ip[3]];
  143.   ip += 4;
  144.  
  145.   if (verbosity >= 3)
  146.     printf("[op 1] next op is %d\n",ip[0]);
  147.  
  148.   goto *func_table[ip[0]];
  149.  
  150.  sub:
  151.   if (verbosity >= 3)
  152.     printf("[op 2] setting reg%d = reg%d - reg%d (%d)\n",
  153.           ip[1],ip[2],ip[3], regs[ip[2]] - regs[ip[3]]);
  154.  
  155.   regs[ip[1]] = regs[ip[2]] - regs[ip[3]];
  156.   ip += 4;
  157.  
  158.   if (verbosity >= 3)
  159.     printf("[op 2] next op is %d\n",ip[0]);
  160.  
  161.   goto *func_table[ip[0]];
  162.  
  163.  mul:
  164.   if (verbosity >= 3)
  165.     printf("[op 3] setting reg%d = reg%d * reg%d (%d)\n",
  166.           ip[1],ip[2],ip[3], regs[ip[2]] * regs[ip[3]]);
  167.  
  168.   regs[ip[1]] = regs[ip[2]] * regs[ip[3]];
  169.   ip += 4;
  170.  
  171.   if (verbosity >= 3)
  172.     printf("[op 3] next op is %d\n",ip[0]);
  173.   goto *func_table[ip[0]];
  174.  
  175.  div:
  176.   if (verbosity >= 3)
  177.     printf("[op 4] setting reg%d = reg%d / reg%d (%d)\n",
  178.           ip[1],ip[2],ip[3], regs[ip[2]] / regs[ip[3]]);
  179.  
  180.   regs[ip[1]] = regs[ip[2]] / regs[ip[3]];
  181.   ip += 4;
  182.  
  183.   if (verbosity >= 3)
  184.     printf("[op 4] next op is %d\n",ip[0]);
  185.   goto *func_table[ip[0]];
  186.  
  187.  mod:
  188.   if (verbosity >= 3)
  189.     printf("[op 5] setting reg%d = reg%d + reg%d (%d)\n",
  190.           ip[1],ip[2],ip[3], regs[ip[2]] + regs[ip[3]]);
  191.  
  192.   regs[ip[1]] = regs[ip[2]] % regs[ip[3]];
  193.   ip += 4;
  194.  
  195.   if (verbosity >= 3)
  196.     printf("[op 5] next op is %d\n",ip[0]);
  197.   goto *func_table[ip[0]];
  198.  
  199.  show:
  200.   printf("[op 6] reg %d ==> %d\n",ip[1],regs[ip[1]]);
  201.   ip += 4;
  202.  
  203.   if (verbosity >= 3)
  204.     printf("[op 6] next op is %d\n",ip[0]);
  205.  
  206.   goto *func_table[ip[0]];
  207.  
  208.  jump:
  209.   if (verbosity >= 3)
  210.     printf("[op 7] jumping %s %d opcodes\n",
  211.           ip[1] > 0 ? "forward" : "back",abs(ip[1]));
  212.  
  213.   ip += (ip[1]*4);
  214.  
  215.   if (verbosity >= 3)
  216.     printf("[op 7] next op is %d\n",ip[0]);
  217.  
  218.   goto *func_table[ip[0]];
  219.  
  220.  nextif:
  221.   if (verbosity >= 3)
  222.     printf("[op 8] executing next instruction (op %d) if reg%d == %d\n",
  223.           ip[4],ip[1], ip[2]);
  224.  
  225.   if(regs[ip[1]] == ip[2])
  226.     ip += 4;
  227.   else
  228.     ip += 8;
  229.  
  230.   if (verbosity >= 3)
  231.     printf("[op 8] next op is %d\n",ip[0]);
  232.  
  233.   goto *func_table[ip[0]];
  234.  
  235.  skipif:
  236.   if (verbosity >= 3)
  237.     printf("[op 9] skipping next instruction (op %d) if reg%d == %d\n",
  238.           ip[4],ip[1], ip[2]);
  239.  
  240.   if(regs[ip[1]] == ip[2])
  241.     ip += 8;
  242.   else
  243.     ip += 4;
  244.  
  245.   if (verbosity >= 3)
  246.     printf("[op 9] next op is %d\n",ip[0]);
  247.  
  248.   goto *func_table[ip[0]];
  249.  
  250.  printstr:
  251.   if (verbosity >= 3)
  252.     printf("[op 10] printing string, data index %d\n",ip[1]);
  253.  
  254.   printf("%s\n",data[ip[1]]);
  255.   ip += 4;
  256.  
  257.   if (verbosity >= 3)
  258.     printf("[op 10] next op is %d\n",ip[0]);
  259.  
  260.   goto *func_table[ip[0]];
  261.  
  262.  exit:
  263.   if (verbosity >= 3)
  264.     printf("[op 11] exiting\n");
  265.  
  266.   return;
  267. }
After you compile this with something, when executed it looks like this:
CODE: Copy / Restore  ::  Remove Scroll Bars
  1. $ ./a.out
  2. Executing program1:
  3. [op 6] reg 1 ==> 30
  4. Executing program2:
  5. [op 6] reg 0 ==> 10
  6. [op 6] reg 0 ==> 9
  7. [op 6] reg 0 ==> 8
  8. [op 6] reg 0 ==> 7
  9. [op 6] reg 0 ==> 6
  10. [op 6] reg 0 ==> 5
  11. [op 6] reg 0 ==> 4
  12. [op 6] reg 0 ==> 3
  13. [op 6] reg 0 ==> 2
  14. [op 6] reg 0 ==> 1
  15. Executing program3:
  16. hello world!
  17. goodbye world!
  18. Executing program4:
  19. [op 6] reg 0 ==> 15
  20. fizz
  21. buzz
  22. [op 6] reg 0 ==> 14
  23. [op 6] reg 0 ==> 13
  24. [op 6] reg 0 ==> 12
  25. fizz
  26. [op 6] reg 0 ==> 11
  27. [op 6] reg 0 ==> 10
  28. buzz
  29. [op 6] reg 0 ==> 9
  30. fizz
  31. [op 6] reg 0 ==> 8
  32. [op 6] reg 0 ==> 7
  33. [op 6] reg 0 ==> 6
  34. fizz
  35. [op 6] reg 0 ==> 5
  36. buzz
  37. [op 6] reg 0 ==> 4
  38. [op 6] reg 0 ==> 3
  39. fizz
  40. [op 6] reg 0 ==> 2
  41. [op 6] reg 0 ==> 1
  42. $
If executed with level 3 verbosity, you get the output of each opcode :]

This isn't all the code however, it's actually a lot more and I've written other parts and different versions of the VM for benchmark, etc.. You can view the source code here:

http://github.com/thoughtpolice/haitus/tree

You can clone it if you have git by doing:

$ git clone git://github.com/thoughtpolice/haitus.git

Follow instructions in README to build; you'll need GNU make + autoconf (basically, linux/osx.)

Fun. :]
Page 1 of 1
 
 
Latest News About Coder Profile
Coder Profile Poll
Why do you get bored with programming?

Not enough time to do something productive
I run out of ideas
Too hard to show people my creations
Everything i do has too many errors, and it's too hard
I don't get bored!!!


please login to cast your vote
and see the results of this poll
Latest Coder Profile Changes
Coder Profile was last updated
1.77 Year Ago
Official Blog :: Make A Donation :: Credits :: Contact Me
Terms & Conditions :: Privacy Policy :: Documents :: Wallpapers
Version 1.46.00
Copyright © 2007 - 2010, Scott Thompson, All Rights Reserved