instruction encoding and decoding working
This commit is contained in:
143
src/emu.c
143
src/emu.c
@@ -1,5 +1,146 @@
|
||||
#include "emu.h"
|
||||
|
||||
inline Instruction fetchInst(Emulator* emu) {
|
||||
return decodeInstruction(emu->mem, &emu->pc);
|
||||
}
|
||||
|
||||
inline void updateFlagsRegister(Emulator* emu, int32_t value) {
|
||||
if (value == 0) {
|
||||
emu->regs[REG_F] = FLAG_ZERO;
|
||||
} else if (value < 0) {
|
||||
emu->regs[REG_F] = FLAG_NEGATIVE;
|
||||
} else if (value > UINT16_MAX) {
|
||||
emu->regs[REG_F] = FLAG_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
void startEmulator(Emulator* emu) {
|
||||
static void* dispatchTable[] = {
|
||||
&&MOV,
|
||||
&&MVI,
|
||||
&&ADD,
|
||||
&&SUB,
|
||||
&&LOAD,
|
||||
&&STORE,
|
||||
&&AND,
|
||||
&&OR,
|
||||
&&XOR,
|
||||
&&SHF,
|
||||
&&JMP,
|
||||
&&JIZ,
|
||||
&&CALL,
|
||||
&&RET,
|
||||
&&SYS,
|
||||
&&HLT
|
||||
};
|
||||
|
||||
emu->halted = false;
|
||||
Instruction inst;
|
||||
|
||||
#define DISPATCH() inst = fetchInst(emu); \
|
||||
goto *dispatchTable[inst.opcode];
|
||||
|
||||
DISPATCH();
|
||||
|
||||
MOV: {
|
||||
emu->regs[inst.operands[0]] = emu->regs[inst.operands[1]];
|
||||
DISPATCH();
|
||||
}
|
||||
MVI: {
|
||||
emu->regs[inst.operands[0]] = inst.immediate;
|
||||
DISPATCH();
|
||||
}
|
||||
ADD: {
|
||||
int32_t result = emu->regs[inst.operands[0]] + emu->regs[inst.operands[1]];
|
||||
updateFlagsRegister(emu, result);
|
||||
emu->regs[inst.operands[0]] = result;
|
||||
DISPATCH();
|
||||
}
|
||||
SUB: {
|
||||
int32_t result = emu->regs[inst.operands[0]] - emu->regs[inst.operands[1]];
|
||||
updateFlagsRegister(emu, result);
|
||||
emu->regs[inst.operands[0]] = result;
|
||||
DISPATCH();
|
||||
}
|
||||
LOAD: {
|
||||
uint32_t addr = getAddress(
|
||||
emu->regs[inst.operands[1]],
|
||||
emu->regs[inst.operands[2]]
|
||||
);
|
||||
|
||||
emu->regs[inst.operands[0]] = memoryLoadWord(emu->mem, addr);
|
||||
DISPATCH();
|
||||
}
|
||||
STORE: {
|
||||
uint32_t addr = getAddress(
|
||||
emu->regs[inst.operands[0]],
|
||||
emu->regs[inst.operands[1]]
|
||||
);
|
||||
memorySaveWord(emu->mem, addr, inst.operands[2]);
|
||||
DISPATCH();
|
||||
}
|
||||
AND: {
|
||||
int32_t result = emu->regs[inst.operands[0]] & emu->regs[inst.operands[1]];
|
||||
updateFlagsRegister(emu, result);
|
||||
emu->regs[inst.operands[0]] = result;
|
||||
DISPATCH();
|
||||
}
|
||||
OR: {
|
||||
int32_t result = emu->regs[inst.operands[0]] | emu->regs[inst.operands[1]];
|
||||
updateFlagsRegister(emu, result);
|
||||
emu->regs[inst.operands[0]] = result;
|
||||
DISPATCH();
|
||||
}
|
||||
XOR: {
|
||||
int32_t result = emu->regs[inst.operands[0]] ^ emu->regs[inst.operands[1]];
|
||||
updateFlagsRegister(emu, result);
|
||||
emu->regs[inst.operands[0]] = result;
|
||||
DISPATCH();
|
||||
}
|
||||
SHF: {
|
||||
int32_t result;
|
||||
if (inst.operands[2] == 0)
|
||||
result = emu->regs[inst.operands[0]] << emu->regs[inst.operands[1]];
|
||||
else
|
||||
result = emu->regs[inst.operands[0]] >> emu->regs[inst.operands[1]];
|
||||
|
||||
updateFlagsRegister(emu, result);
|
||||
emu->regs[inst.operands[0]] = result;
|
||||
DISPATCH();
|
||||
}
|
||||
JMP: {
|
||||
emu->pc = getAddress(inst.operands[0], inst.operands[1]);
|
||||
DISPATCH();
|
||||
}
|
||||
JIZ: {
|
||||
if (emu->regs[REG_F] & FLAG_ZERO)
|
||||
emu->pc = getAddress(inst.operands[0], inst.operands[1]);
|
||||
DISPATCH();
|
||||
}
|
||||
CALL: {
|
||||
// save the pc at the current sp and decrement the sp (stack grows downward)
|
||||
((uint32_t*)emu->mem->data)[emu->sp--] = emu->pc;
|
||||
|
||||
// jump to given addr
|
||||
emu->pc = getAddress(inst.operands[0], inst.operands[1]);
|
||||
|
||||
DISPATCH();
|
||||
}
|
||||
RET: {
|
||||
// return to value at sp and increment it
|
||||
emu->pc = ((uint32_t*)emu->mem->data)[++emu->sp];
|
||||
DISPATCH();
|
||||
}
|
||||
SYS: {
|
||||
// TODO
|
||||
DISPATCH();
|
||||
}
|
||||
HLT: {
|
||||
emu->halted = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Emulator* initEmulator(uint32_t memorySize) {
|
||||
Emulator* newEmu = malloc(sizeof(Emulator));
|
||||
if (!newEmu)
|
||||
@@ -9,7 +150,7 @@ Emulator* initEmulator(uint32_t memorySize) {
|
||||
memset(newEmu->regs, 0, sizeof(newEmu->regs));
|
||||
|
||||
// zero out special regs
|
||||
newEmu->pc = 0;
|
||||
newEmu->pc = MEM_PROGRAM_START;
|
||||
newEmu->sp = 0;
|
||||
newEmu->ihp = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user