diff --git a/vm.c b/vm.c index 03f0cb2..4ed45d8 100644 --- a/vm.c +++ b/vm.c @@ -46,11 +46,70 @@ bool eval_4OP_Int(struct lilith* vm, struct Instruction* c) /* Process 3OP Integer instructions */ bool eval_3OP_Int(struct lilith* vm, struct Instruction* c) { + int64_t tmp1, tmp2; + uint64_t utmp1, utmp2; + + tmp1 = (int64_t)(vm->reg[c->reg1]); + tmp2 = (int64_t)(vm->reg[c->reg2]); + utmp1 = vm->reg[c->reg1]; + utmp2 = vm->reg[c->reg2]; + switch(c->raw_XOP) { case 0x000: /* ADD */ { - vm->reg[c->reg0] = vm->reg[c->reg1] + vm->reg[c->reg2]; + vm->reg[c->reg0] = (int64_t)(tmp1 + tmp2); + break; + } + case 0x001: /* ADDU */ + { + vm->reg[c->reg0] = utmp1 + utmp2; + break; + } + case 0x002: /* SUB */ + { + vm->reg[c->reg0] = (int64_t)(tmp1 - tmp2); + break; + } + case 0x003: /* SUBU */ + { + vm->reg[c->reg0] = utmp1 - utmp2; + break; + } + case 0x004: /* CMP */ + { + /* Clear bottom 3 bits of condition register */ + vm->reg[c->reg0] = vm->reg[c->reg0] & 0xFFFFFFFFFFFFFFF8; + if(tmp1 > tmp2) + { + vm->reg[c->reg0] = vm->reg[c->reg0] | GreaterThan; + } + else if(tmp1 == tmp2) + { + vm->reg[c->reg0] = vm->reg[c->reg0] | EQual; + } + else + { + vm->reg[c->reg0] = vm->reg[c->reg0] | LessThan; + } + break; + } + case 0x005: /* CMPU */ + { + /* Clear bottom 3 bits of condition register */ + vm->reg[c->reg0] = vm->reg[c->reg0] & 0xFFFFFFFFFFFFFFF8; + if(utmp1 > utmp2) + { + vm->reg[c->reg0] = vm->reg[c->reg0] | GreaterThan; + } + else if(utmp1 == utmp2) + { + vm->reg[c->reg0] = vm->reg[c->reg0] | EQual; + } + else + { + vm->reg[c->reg0] = vm->reg[c->reg0] | LessThan; + } break; } default: return true; @@ -73,17 +132,138 @@ bool eval_1OP_Int(struct lilith* vm, struct Instruction* c) /* Process 2OPI Integer instructions */ bool eval_2OPI_Int(struct lilith* vm, struct Instruction* c) { + int64_t tmp1; + uint64_t utmp1; + + tmp1 = (int64_t)(vm->reg[c->reg1]); + utmp1 = vm->reg[c->reg1]; + /* 0x0E ... 0x2B */ switch(c->raw0) { case 0x0E: /* ADDI */ { - vm->reg[c->reg0] = (int8_t)(vm->reg[c->reg1] + c->raw_Immediate); + vm->reg[c->reg0] = (int64_t)(tmp1 + c->raw_Immediate); break; } case 0x0F: /* ADDUI */ { - vm->reg[c->reg0] = vm->reg[c->reg1] + c->raw_Immediate; break; + vm->reg[c->reg0] = utmp1 + c->raw_Immediate; + break; + } + case 0x10: /* SUB */ + { + vm->reg[c->reg0] = (int64_t)(tmp1 - c->raw_Immediate); + break; + } + case 0x11: /* SUBU */ + { + vm->reg[c->reg0] = utmp1 + c->raw_Immediate; + break; + } + default: return true; + } + return false; +} + +/* Process 1OPI instructions */ +bool eval_1OPI(struct lilith* vm, struct Instruction* c) +{ + bool C, B, O, GT, EQ, LT; + uint64_t tmp; + + tmp = vm->reg[c->reg0]; + + C = tmp & Carry; + B = tmp & Borrow; + O = tmp & Overflow; + GT = tmp & GreaterThan; + EQ = tmp & EQual; + LT = tmp & LessThan; + + /* 0x2C ... 0x3B */ + switch(c->raw0) + { + case 0x2C: /*JMP.C*/ + { + if(1 == C) + { + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + c->raw_Immediate - 4; + } + break; + } + case 0x2D: /*JMP.B*/ + { + if(1 == B) + { + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + c->raw_Immediate - 4; + } + break; + } + case 0x2E: /*JMP.O*/ + { + if(1 == O) + { + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + c->raw_Immediate - 4; + } + break; + } + case 0x2F: /*JMP.G*/ + { + if(1 == GT) + { + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + c->raw_Immediate - 4; + } + break; + } + case 0x30: /*JMP.GE*/ + { + if((1 == GT) || (1 == EQ)) + { + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + c->raw_Immediate - 4; + } + break; + } + case 0x31: /*JMP.E*/ + { + if(1 == EQ) + { + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + c->raw_Immediate - 4; + } + break; + } + case 0x32: /*JMP.NE*/ + { + if(1 != EQ) + { + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + c->raw_Immediate - 4; + } + break; + } + case 0x33: /*JMP.LE*/ + { + if((1 == EQ) || (1 == LT)) + { + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + c->raw_Immediate - 4; + } + break; + } + case 0x34: /*JMP.L*/ + { + if(1 == LT) + { + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + c->raw_Immediate - 4; + } + break; } default: return true; } @@ -99,7 +279,6 @@ void eval_instruction(struct lilith* vm, struct Instruction* current) { case 0x00: /* Deal with NOPs */ { - vm->halted = true; return; } case 0x01: @@ -137,17 +316,30 @@ void eval_instruction(struct lilith* vm, struct Instruction* current) if ( invalid) goto fail; break; } - case 0x2C: + case 0x2C ... 0x3B: { + decode_1OPI(current); + invalid = eval_1OPI(vm, current); + if ( invalid) goto fail; + break; } - case 0x3C: + case 0x3C: /* JUMP */ { + decode_0OPI(current); + /* Adust the IP relative the the start of this instruction*/ + vm->ip = vm->ip + current->raw_Immediate - 4; + break; } case 0x42: { } - case 0xFF: /* Deal with illegal instruction */ - default: + case 0xFF: /* Deal with HALT */ + { + vm->halted = true; + fprintf(stderr, "Computer Program has Halted\n"); + break; + } + default: /* Deal with illegal instruction */ { fail: fprintf(stderr, "Unable to execute the following instruction:\n%c %c %c %c\n", current->raw0, current->raw1, current->raw2, current->raw3); diff --git a/vm.h b/vm.h index 4c2dbf5..415da39 100644 --- a/vm.h +++ b/vm.h @@ -23,7 +23,7 @@ struct Instruction uint32_t raw_XOP; char XOP[6]; char operation[9]; - uint32_t raw_Immediate; + int32_t raw_Immediate; char Immediate[7]; uint32_t HAL_CODE; uint8_t reg0; @@ -36,11 +36,11 @@ struct Instruction /* Condition Codes */ enum condition { -Carry = 1 << 5, -Borrow = 1 << 4, -Overflow = 1 << 3, -GreaterThan = 1 << 2, -EQual = 1 << 1, +Carry = (1 << 5), +Borrow = (1 << 4), +Overflow = (1 << 3), +GreaterThan = (1 << 2), +EQual = (1 << 1), LessThan = 1 }; @@ -78,7 +78,7 @@ void decode_4OP(struct Instruction* c) /* Deal with 3OP */ void decode_3OP(struct Instruction* c) { - c->raw_XOP = c->raw1*16 + c->raw2/16; + c->raw_XOP = c->raw1*0x10 + c->raw2/16; c->XOP[0] = c->operation[2]; c->XOP[1] = c->operation[3]; c->XOP[2] = c->operation[4]; @@ -91,7 +91,7 @@ void decode_3OP(struct Instruction* c) /* Deal with 2OP */ void decode_2OP(struct Instruction* c) { - c->raw_XOP = c->raw1*256 + c->raw2; + c->raw_XOP = c->raw1*0x100 + c->raw2; c->XOP[0] = c->operation[2]; c->XOP[1] = c->operation[3]; c->XOP[2] = c->operation[4]; @@ -104,7 +104,7 @@ void decode_2OP(struct Instruction* c) /* Deal with 1OP */ void decode_1OP(struct Instruction* c) { - c->raw_XOP = c->raw1*4096 + c->raw2*16 + c->raw3/16; + c->raw_XOP = c->raw1*0x1000 + c->raw2*0x10 + c->raw3/16; c->XOP[0] = c->operation[2]; c->XOP[1] = c->operation[3]; c->XOP[2] = c->operation[4]; @@ -117,7 +117,7 @@ void decode_1OP(struct Instruction* c) /* Deal with 2OPI */ void decode_2OPI(struct Instruction* c) { - c->raw_Immediate = c->raw2*256 + c->raw3; + c->raw_Immediate = c->raw2*0x100 + c->raw3; c->Immediate[0] = c->operation[4]; c->Immediate[1] = c->operation[5]; c->Immediate[2] = c->operation[6]; @@ -129,19 +129,25 @@ void decode_2OPI(struct Instruction* c) /* Deal with 1OPI */ void decode_1OPI(struct Instruction* c) { - c->raw_Immediate = (c->raw1%16)*4096 + c->raw2*256 + c->raw3; + c->raw_Immediate = (c->raw1%16)*0x10000 + c->raw2*0x100 + c->raw3; + /* Sign extend immediate*/ + c->raw_Immediate = c->raw_Immediate << 12; + c->raw_Immediate = c->raw_Immediate >> 12; c->Immediate[0] = c->operation[3]; c->Immediate[1] = c->operation[4]; c->Immediate[2] = c->operation[5]; c->Immediate[3] = c->operation[6]; c->Immediate[4] = c->operation[7]; c->HAL_CODE = 0; - c->reg0 = c->raw1/16; + c->reg0 = c->raw3/16; } /* Deal with 0OPI */ void decode_0OPI(struct Instruction* c) { - c->raw_Immediate = c->raw1*4096 + c->raw2*256 + c->raw3; + c->raw_Immediate = c->raw1*0x10000 + c->raw2*0x100 + c->raw3; + /* Sign extend immediate*/ + c->raw_Immediate = c->raw_Immediate << 8; + c->raw_Immediate = c->raw_Immediate >> 8; c->Immediate[0] = c->operation[2]; c->Immediate[1] = c->operation[3]; c->Immediate[2] = c->operation[4]; @@ -153,7 +159,7 @@ void decode_0OPI(struct Instruction* c) /* Deal with Halcode */ void decode_HALCODE(struct Instruction* c) { - c->HAL_CODE = c->raw1*4096 + c->raw2*256 + c->raw3; + c->HAL_CODE = c->raw1*0x10000 + c->raw2*0x100 + c->raw3; } /* Useful unpacking functions */