Implemented Missing instructions from Logic, stack and math
This commit is contained in:
parent
56543ca5c6
commit
63d9d2fb54
|
@ -81,8 +81,9 @@
|
|||
09 00 06 xx # Reserved
|
||||
...
|
||||
09 00 FF xx # Reserved
|
||||
09 01 00 ab # BRANCH a b :: Mem[b] = PC; PC = a
|
||||
09 01 01 xx # Reserved
|
||||
09 01 00 ab # BRANCH a b :: MEM[b] = PC; PC = a
|
||||
09 01 01 ab # CALL a b :: MEM[b] = PC; b = b + (register size in bytes); PC = a
|
||||
09 01 02 xx # Reserved
|
||||
...
|
||||
09 FF FF xx # Reserved
|
||||
0A nn nn ab # 2OP Floating group
|
||||
|
@ -99,7 +100,13 @@
|
|||
...
|
||||
0D 00 FF Fx # Reserved
|
||||
0D 01 00 0a # JSR_COROUTINE a; PC = a
|
||||
0D 01 00 1x # Reserved
|
||||
0D 01 00 1a # RET a :: PC = MEM[a]; a = a - (register size in bytes)
|
||||
0D 01 00 2x # Reserved
|
||||
...
|
||||
0D 01 FF Fx # Reserved
|
||||
0D 02 00 0a # PUSHPC a :: MEM[a] = PC; a = a + (register size in bytes)
|
||||
0D 02 00 1a # POPPC a :: PC = MEM[a]; a = a - (register size in bytes)
|
||||
0D 02 00 2x # Reserved
|
||||
...
|
||||
0D FF FF Fx # Reserved
|
||||
|
||||
|
|
199
vm.c
199
vm.c
|
@ -114,50 +114,98 @@ bool eval_3OP_Int(struct lilith* vm, struct Instruction* c)
|
|||
}
|
||||
case 0x006: /* MUL */
|
||||
{
|
||||
int64_t sum = tmp1 * tmp2;
|
||||
/* We only want the bottom 32bits */
|
||||
vm->reg[c->reg0] = sum % 0x100000000;
|
||||
break;
|
||||
}
|
||||
case 0x007: /* MULH */
|
||||
{
|
||||
int64_t sum = tmp1 * tmp2;
|
||||
/* We only want the top 32bits */
|
||||
vm->reg[c->reg0] = sum / 0x100000000;
|
||||
break;
|
||||
}
|
||||
case 0x008: /* MULU */
|
||||
{
|
||||
uint64_t sum = tmp1 * tmp2;
|
||||
/* We only want the bottom 32bits */
|
||||
vm->reg[c->reg0] = sum % 0x100000000;
|
||||
break;
|
||||
}
|
||||
case 0x009: /* MULUH */
|
||||
{
|
||||
uint64_t sum = tmp1 * tmp2;
|
||||
/* We only want the top 32bits */
|
||||
vm->reg[c->reg0] = sum / 0x100000000;
|
||||
break;
|
||||
}
|
||||
case 0x00A: /* DIV */
|
||||
{
|
||||
vm->reg[c->reg0] = tmp1 / tmp2;
|
||||
break;
|
||||
}
|
||||
case 0x00B: /* MOD */
|
||||
{
|
||||
vm->reg[c->reg0] = tmp1 % tmp2;
|
||||
break;
|
||||
}
|
||||
case 0x00C: /* DIVU */
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1 / utmp2;
|
||||
break;
|
||||
}
|
||||
case 0x00D: /* MODU */
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1 % utmp2;
|
||||
break;
|
||||
}
|
||||
case 0x010: /* MAX */
|
||||
{
|
||||
if(tmp1 > tmp2)
|
||||
{
|
||||
vm->reg[c->reg0] = tmp1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->reg[c->reg0] = tmp2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x011: /* MAXU */
|
||||
{
|
||||
if(utmp1 > utmp2)
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->reg[c->reg0] = utmp2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x012: /* MIN */
|
||||
{
|
||||
if(tmp1 < tmp2)
|
||||
{
|
||||
vm->reg[c->reg0] = tmp1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->reg[c->reg0] = tmp2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x013: /* MINU */
|
||||
{
|
||||
if(utmp1 < utmp2)
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->reg[c->reg0] = utmp2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x014: /* PACK */
|
||||
|
@ -194,42 +242,52 @@ bool eval_3OP_Int(struct lilith* vm, struct Instruction* c)
|
|||
}
|
||||
case 0x020: /* AND */
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1 & utmp2;
|
||||
break;
|
||||
}
|
||||
case 0x021: /* OR */
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1 | utmp2;
|
||||
break;
|
||||
}
|
||||
case 0x022: /* XOR */
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1 ^ utmp2;
|
||||
break;
|
||||
}
|
||||
case 0x023: /* NAND */
|
||||
{
|
||||
vm->reg[c->reg0] = ~(utmp1 & utmp2);
|
||||
break;
|
||||
}
|
||||
case 0x024: /* NOR */
|
||||
{
|
||||
vm->reg[c->reg0] = ~(utmp1 | utmp2);
|
||||
break;
|
||||
}
|
||||
case 0x025: /* XNOR */
|
||||
{
|
||||
vm->reg[c->reg0] = ~(utmp1 ^ utmp2);
|
||||
break;
|
||||
}
|
||||
case 0x026: /* MPQ */
|
||||
{
|
||||
vm->reg[c->reg0] = (~utmp1) & utmp2;
|
||||
break;
|
||||
}
|
||||
case 0x027: /* LPQ */
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1 & (~utmp2);
|
||||
break;
|
||||
}
|
||||
case 0x028: /* CPQ */
|
||||
{
|
||||
vm->reg[c->reg0] = (~utmp1) | utmp2;
|
||||
break;
|
||||
}
|
||||
case 0x029: /* BPQ */
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1 | (~utmp2);
|
||||
break;
|
||||
}
|
||||
case 0x030: /* SAL */
|
||||
|
@ -272,34 +330,91 @@ bool eval_3OP_Int(struct lilith* vm, struct Instruction* c)
|
|||
/* Process 2OP Integer instructions */
|
||||
bool eval_2OP_Int(struct lilith* vm, struct Instruction* c)
|
||||
{
|
||||
int32_t tmp1 = (int32_t)(vm->reg[c->reg1]);
|
||||
uint32_t utmp1 = vm->reg[c->reg1];
|
||||
|
||||
switch(c->raw_XOP)
|
||||
{
|
||||
case 0x0000: /* NEG */
|
||||
{
|
||||
vm->reg[c->reg0] = tmp1*-1;
|
||||
break;
|
||||
}
|
||||
case 0x0001: /* ABS */
|
||||
{
|
||||
if(0 <= tmp1)
|
||||
{
|
||||
vm->reg[c->reg0] = tmp1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->reg[c->reg0] = tmp1*-1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x0002: /* NABS */
|
||||
{
|
||||
if(0 > tmp1)
|
||||
{
|
||||
vm->reg[c->reg0] = tmp1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->reg[c->reg0] = tmp1*-1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x0003: /* SWAP */
|
||||
{
|
||||
vm->reg[c->reg1] = vm->reg[c->reg0];
|
||||
vm->reg[c->reg0] = utmp1;
|
||||
break;
|
||||
}
|
||||
case 0x0004: /* COPY */
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1;
|
||||
break;
|
||||
}
|
||||
case 0x0005: /* MOVE */
|
||||
{
|
||||
vm->reg[c->reg0] = utmp1;
|
||||
vm->reg[c->reg1] = 0;
|
||||
break;
|
||||
}
|
||||
case 0x0100: /* BRANCH */
|
||||
{
|
||||
/* Preserve index */
|
||||
uint32_t utmp1 = vm->reg[c->reg1];
|
||||
|
||||
/* Use the index register to store the PC for upload to MEM */
|
||||
vm->reg[c->reg1] = vm->ip;
|
||||
|
||||
/* Write out the PC */
|
||||
writeout_Reg(vm, utmp1, c->reg1);
|
||||
|
||||
/* Restore our index */
|
||||
vm->reg[c->reg1] = utmp1;
|
||||
|
||||
/* Update PC */
|
||||
vm->ip = vm->reg[c->reg0];
|
||||
break;
|
||||
}
|
||||
case 0x0101: /* CALL */
|
||||
{
|
||||
/* Preserve index */
|
||||
uint32_t utmp1 = vm->reg[c->reg1];
|
||||
|
||||
/* Use the index register to store the PC for upload to MEM */
|
||||
vm->reg[c->reg1] = vm->ip;
|
||||
|
||||
/* Write out the PC */
|
||||
writeout_Reg(vm, utmp1, c->reg1);
|
||||
|
||||
/* Update our index */
|
||||
vm->reg[c->reg1] = utmp1 + 4;
|
||||
|
||||
/* Update PC */
|
||||
vm->ip = vm->reg[c->reg0];
|
||||
break;
|
||||
}
|
||||
default: return true;
|
||||
|
@ -314,22 +429,69 @@ bool eval_1OP_Int(struct lilith* vm, struct Instruction* c)
|
|||
{
|
||||
case 0x00000: /* READPC */
|
||||
{
|
||||
vm->reg[c->reg0] = vm->ip;
|
||||
break;
|
||||
}
|
||||
case 0x00001: /* READSCID */
|
||||
{
|
||||
/* We only support Base 8,16 and 32*/
|
||||
vm->reg[c->reg0] = 0x00000007;
|
||||
break;
|
||||
}
|
||||
case 0x00002: /* FALSE */
|
||||
{
|
||||
vm->reg[c->reg0] = 0;
|
||||
break;
|
||||
}
|
||||
case 0x00003: /* TRUE */
|
||||
{
|
||||
vm->reg[c->reg0] = 0xFFFFFFFF;
|
||||
break;
|
||||
}
|
||||
case 0x01000: /* JSR_COROUTINE */
|
||||
{
|
||||
vm->ip = vm->reg[c->reg0];
|
||||
break;
|
||||
}
|
||||
case 0x01001: /* RET */
|
||||
{
|
||||
/* Preserve index */
|
||||
uint32_t utmp1 = vm->reg[c->reg0];
|
||||
|
||||
/* Read in the new PC */
|
||||
readin_Reg(vm, utmp1, c->reg0);
|
||||
vm->ip = vm->reg[c->reg0];
|
||||
|
||||
/* Update our index */
|
||||
vm->reg[c->reg0] = utmp1 - 4;
|
||||
break;
|
||||
}
|
||||
case 0x02000: /* PUSHPC */
|
||||
{
|
||||
/* Preserve index */
|
||||
uint32_t utmp1 = vm->reg[c->reg0];
|
||||
|
||||
/* Use the index register to store the PC for upload to MEM */
|
||||
vm->reg[c->reg0] = vm->ip;
|
||||
|
||||
/* Write out the PC */
|
||||
writeout_Reg(vm, utmp1, c->reg0);
|
||||
|
||||
/* Update our index */
|
||||
vm->reg[c->reg0] = utmp1 + 4;
|
||||
break;
|
||||
}
|
||||
case 0x02001: /* POPPC */
|
||||
{
|
||||
/* Preserve index */
|
||||
uint32_t utmp1 = vm->reg[c->reg0];
|
||||
|
||||
/* Read in the new PC */
|
||||
readin_Reg(vm, utmp1, c->reg0);
|
||||
vm->ip = vm->reg[c->reg0];
|
||||
|
||||
/* Update our index */
|
||||
vm->reg[c->reg0] = utmp1 - 4;
|
||||
break;
|
||||
}
|
||||
default: return true;
|
||||
|
@ -388,6 +550,11 @@ bool eval_2OPI_Int(struct lilith* vm, struct Instruction* c)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x13: /* LOAD */
|
||||
{
|
||||
readin_Reg(vm, (utmp1 + c->raw_Immediate) , c->reg0);
|
||||
break;
|
||||
}
|
||||
case 0x14: /* LOAD8 */
|
||||
{
|
||||
raw0 = vm->memory[utmp1 + c->raw_Immediate];
|
||||
|
@ -428,17 +595,8 @@ bool eval_2OPI_Int(struct lilith* vm, struct Instruction* c)
|
|||
}
|
||||
case 0x18: /* LOAD32 */
|
||||
case 0x19: /* LOADU32 */
|
||||
case 0x13: /* LOAD */
|
||||
{
|
||||
raw0 = vm->memory[utmp1 + c->raw_Immediate];
|
||||
raw1 = vm->memory[utmp1 + c->raw_Immediate + 1];
|
||||
raw2 = vm->memory[utmp1 + c->raw_Immediate + 2];
|
||||
raw3 = vm->memory[utmp1 + c->raw_Immediate + 3];
|
||||
|
||||
vm->reg[c->reg0] = raw0*0x1000000 +
|
||||
raw1*0x10000 +
|
||||
raw2*0x100 +
|
||||
raw3;
|
||||
readin_Reg(vm, (utmp1 + c->raw_Immediate) , c->reg0);
|
||||
break;
|
||||
}
|
||||
case 0x1F: /* CMPUI */
|
||||
|
@ -459,6 +617,11 @@ bool eval_2OPI_Int(struct lilith* vm, struct Instruction* c)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x20: /* STORE */
|
||||
{
|
||||
writeout_Reg(vm, (utmp1 + c->raw_Immediate), c->reg0);
|
||||
break;
|
||||
}
|
||||
case 0x21: /* STORE8 */
|
||||
{
|
||||
int32_t tmp = (int8_t)(vm->reg[c->reg0]);
|
||||
|
@ -499,22 +662,8 @@ bool eval_2OPI_Int(struct lilith* vm, struct Instruction* c)
|
|||
}
|
||||
case 0x25: /* STORE32 */
|
||||
case 0x26: /* STOREU32 */
|
||||
case 0x20: /* STORE */
|
||||
{
|
||||
uint32_t tmp = vm->reg[c->reg0];
|
||||
raw3 = tmp%0x100;
|
||||
tmp = tmp/0x100;
|
||||
raw2 = tmp%0x100;
|
||||
tmp = tmp/0x100;
|
||||
raw1 = tmp%0x100;
|
||||
tmp = tmp/0x100;
|
||||
raw0 = tmp%0x100;
|
||||
|
||||
vm->memory[utmp1 + c->raw_Immediate] = raw0;
|
||||
vm->memory[utmp1 + c->raw_Immediate + 1] = raw1;
|
||||
vm->memory[utmp1 + c->raw_Immediate + 2] = raw2;
|
||||
vm->memory[utmp1 + c->raw_Immediate + 3] = raw3;
|
||||
|
||||
writeout_Reg(vm, (utmp1 + c->raw_Immediate), c->reg0);
|
||||
break;
|
||||
}
|
||||
default: return true;
|
||||
|
|
32
vm.h
32
vm.h
|
@ -179,3 +179,35 @@ void unpack_instruction(struct Instruction* c)
|
|||
c->opcode[0] = c->operation[0];
|
||||
c->opcode[1] = c->operation[1];
|
||||
}
|
||||
|
||||
void writeout_Reg(struct lilith* vm, uint32_t p, uint8_t r)
|
||||
{
|
||||
uint8_t raw0, raw1, raw2, raw3;
|
||||
uint32_t tmp = vm->reg[r];
|
||||
raw3 = tmp%0x100;
|
||||
tmp = tmp/0x100;
|
||||
raw2 = tmp%0x100;
|
||||
tmp = tmp/0x100;
|
||||
raw1 = tmp%0x100;
|
||||
tmp = tmp/0x100;
|
||||
raw0 = tmp%0x100;
|
||||
|
||||
vm->memory[p] = raw0;
|
||||
vm->memory[p + 1] = raw1;
|
||||
vm->memory[p + 2] = raw2;
|
||||
vm->memory[p + 3] = raw3;
|
||||
}
|
||||
|
||||
void readin_Reg(struct lilith* vm, uint32_t p, uint8_t r)
|
||||
{
|
||||
uint8_t raw0, raw1, raw2, raw3;
|
||||
raw0 = vm->memory[p];
|
||||
raw1 = vm->memory[p + 1];
|
||||
raw2 = vm->memory[p + 2];
|
||||
raw3 = vm->memory[p + 3];
|
||||
|
||||
vm->reg[r] = raw0*0x1000000 +
|
||||
raw1*0x10000 +
|
||||
raw2*0x100 +
|
||||
raw3;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue