Added arithmetic and control flow functions.

It passes very simple test files.
This commit is contained in:
Mitchell Plamann
2015-03-22 22:32:38 -04:00
parent 2b2726e230
commit 3eb1346eef

View File

@@ -3,6 +3,15 @@ pc = 0;
program = [];
variables = [];
function doIf(shouldJump) {
if (shouldJump) {
var address_offset = (program[pc+1] * 0x1000) + program[pc+2];
pc += address_offset;
} else {
pc += 3;
}
}
// Takes in a parsed .bc0 file and runs it
function execute(file) {
console.log("Beginning execution of file " + file);
@@ -33,7 +42,12 @@ function execute(file) {
break;
case BIPUSH:
pc += 2;
stack.push(program[pc-1]);
var val = program[pc-1];
// Do sign extension if necessary
if (val & 0x80 != 0)
val = -0x80 + (val & 0x7F);
stack.push(val);
break;
// Returning from a function
@@ -47,19 +61,147 @@ function execute(file) {
var y = stack.pop();
var x = stack.pop();
console.log("Adding " + x + " and " + y);
stack.push((x+y) % 0x100);
stack.push((x+y) % 0x100000000);
break;
case ISUB:
pc++;
var y = stack.pop();
var x = stack.pop();
stack.push((x-y) % 0x100);
stack.push((x-y) % 0x100000000);
break;
case IMUL:
pc++;
var y = stack.pop();
var x = stack.pop();
stack.push((x*y) % 0x100);
stack.push((x*y) % 0x100000000);
break;
case IDIV:
pc++;
var y = stack.pop();
var x = stack.pop();
if (y == 0) c0_arith_error("Divide by zero");
if (x == INT_MIN && y == -1) c0_arith_error("Arithmetic overflow");
// This does int division.
// As I understand it, the ~~ is treated as the identity on integers
// which forces the type to int, not float
stack.push(~~(x/y));
break;
case IREM:
pc++;
var y = stack.pop();
var x = stack.pop();
if (y == 0) c0_arith_error("Divide by zero");
if (x == INT_MIN && y == -1) c0_arith_error("Arithmetic overflow");
stack.push(x%y);
break;
case IAND:
pc++;
var y = stack.pop();
var x = stack.pop();
stack.push(x&y);
break;
case IOR:
pc++;
var y = stack.pop();
var x = stack.pop();
stack.push(x|y);
break;
case IXOR:
pc++;
var y = stack.pop();
var x = stack.pop();
stack.push(x^y);
break;
case ISHL:
pc++;
var y = stack.pop();
var x = stack.pop();
if (y < 0 || y > 31) c0_arith_error("Shifting by too many bits");
stack.push(x<<y);
break;
case ISHR:
pc++;
var y = stack.pop();
var x = stack.pop();
if (y < 0 || y > 31) c0_arith_error("Shifting by too many bits");
stack.push(x>>y);
break;
// Operations on local variables
case VLOAD:
pc += 2;
var index = program[pc-1];
stack.push(variables[index]);
break;
case VSTORE:
pc +=2 ;
var index = program[pc-1];
variables[index] = stack.pop();
break;
case ACONST_NULL:
pc++;
stack.push(0);
break;
case ILDC:
pc += 3;
var c1 = program[pc-2];
var c2 = program[pc-1];
var index = (c1 * 0x1000) + c2;
stack.push(file.int_pool[index]);
break;
case ALDC:
console.log("Error: I don't know how to handle ALDC yet");
return;
// Control flow
case NOP:
pc++;
break;
case IF_CMPEQ:
var y = stack.pop();
var x = stack.pop();
doIf(y == x);
break;
case IF_CMPNE:
var y = stack.pop();
var x = stack.pop();
doIf(y != x);
break;
case IF_CMPLT:
var y = stack.pop();
var x = stack.pop();
doIf(y > x);
break;
case IF_CMPGE:
var y = stack.pop();
var x = stack.pop();
doIf(y <= x);
break;
case IF_CMPGT:
var y = stack.pop();
var x = stack.pop();
doIf(y < x);
break;
case IF_CMPLE:
var y = stack.pop();
var x = stack.pop();
doIf(y >= x);
break;
case GOTO:
doIf(true);
break;
case ATHROW:
pc++;
c0_user_error(stack.pop());
break;
case ASSERT:
pc++;
var a = stack.pop();
if (stack.pop() == 0)
c0_assertion_failure(a);
break;
default: