Compare commits

...

2 Commits

7 changed files with 123 additions and 25 deletions

View File

@@ -5,7 +5,8 @@ sources = files(
'src/emu.c',
'src/memory.c',
'src/instruction.c',
'src/util.c'
'src/util.c',
'src/device.c'
)
asmSources = files(

View File

@@ -2,11 +2,37 @@
Device* createDevice(
const char* name,
void (*sendToDevice)(uint16_t number),
uint16_t (*receiveFromDevice)(),
void (*update)()
void (*update)(Device* self)
) {
Device* new = malloc(sizeof(Device));
if (!new)
return NULL;
size_t nameLen = strlen(name) + 1;
nameLen = nameLen < 32 ? nameLen : 32;
memcpy(new->name, name, nameLen);
new->name[nameLen] = 0;
new->update = update;
return new;
}
uint16_t deviceRead(Device* self) {
if (self->inPos == 0)
return 0;
return self->in[--self->inPos];
}
void deviceSend(Device* self, uint16_t value) {
if (self->outPos == DEVICE_BUFFER_LENGTH)
return;
self->out[self->outPos++] = value;
}
bool deviceCanRead(Device* self) {
return self->inPos > 0;
}

View File

@@ -1,18 +1,30 @@
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
typedef struct {
#define DEVICE_BUFFER_LENGTH 128
typedef struct Device Device;
struct Device {
char name[32];
void (*sendToDevice)(uint16_t number);
uint16_t (*receiveFromDevice)();
void (*update)();
} Device;
uint16_t in[DEVICE_BUFFER_LENGTH];
uint8_t inPos;
uint16_t out[DEVICE_BUFFER_LENGTH];
uint8_t outPos;
void (*update)(Device* self);
};
Device* createDevice(
const char* name,
void (*sendToDevice)(uint16_t number),
uint16_t (*receiveFromDevice)(),
void (*update)()
void (*update)(Device* self)
);
uint16_t deviceRead(Device* self);
void deviceSend(Device* self, uint16_t value);
bool deviceCanRead(Device* self);

View File

@@ -1,9 +1,7 @@
#include "emu.h"
static inline Instruction fetchInst(Emulator* emu) {
Instruction inst = decodeInstruction(emu->mem, &emu->pc);
printf("%s\n", instructionToCStr(inst));
return inst;
return decodeInstruction(emu->mem, &emu->pc);
}
static inline void updateFlagsRegister(Emulator* emu, int32_t value) {
@@ -16,6 +14,17 @@ static inline void updateFlagsRegister(Emulator* emu, int32_t value) {
}
}
static inline void updateDevices(Emulator* emu) {
for (size_t i = 0; i < MAX_DEVICES; i++) {
Device* device = emu->devices[i];
if (!device) continue;
if (device->update) {
device->update(device);
}
}
}
void startEmulator(Emulator* emu) {
static void* dispatchTable[] = {
&&MOV,
@@ -32,15 +41,16 @@ void startEmulator(Emulator* emu) {
&&JIZ,
&&CALL,
&&RET,
&&SYS,
&&PORT,
&&HLT
};
emu->halted = false;
Instruction inst;
#define DISPATCH() inst = fetchInst(emu); \
goto *dispatchTable[inst.opcode];
#define DISPATCH() updateDevices(emu); \
inst = fetchInst(emu); \
goto *dispatchTable[inst.opcode]
DISPATCH();
@@ -133,8 +143,39 @@ void startEmulator(Emulator* emu) {
emu->pc = ((uint32_t*)emu->mem->data)[++emu->sp];
DISPATCH();
}
SYS: {
// TODO
PORT: {
uint16_t port = emu->regs[inst.operands[0]];
if (port >= MAX_DEVICES) {
DISPATCH();
}
uint8_t direction = inst.operands[2];
Device* device = emu->devices[port];
if (!device) {
DISPATCH();
}
if (direction == 0) {
uint16_t value = emu->regs[inst.operands[1]];
if (device->inPos == DEVICE_BUFFER_LENGTH) {
DISPATCH();
}
device->in[device->inPos] = value;
device->inPos++;
} else {
if (device->outPos == 0) {
emu->regs[inst.operands[1]] = 0;
DISPATCH();
}
emu->regs[inst.operands[1]] = device->out[device->outPos-1];
if (device->outPos > 0)
device->outPos--;
}
DISPATCH();
}
HLT: {
@@ -170,3 +211,8 @@ void freeEmulator(Emulator* emu) {
freeMemory(emu->mem);
free(emu);
}
void installDevice(Emulator* emu, Device* device, uint8_t deviceNumber) {
assert(deviceNumber < MAX_DEVICES);
emu->devices[deviceNumber] = device;
}

View File

@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include "memory.h"
#include "device.h"
@@ -11,10 +12,13 @@
#define FLAG_NEGATIVE (1 << 1)
#define FLAG_OVERFLOW (1 << 2)
#define MAX_DEVICES 64
// -- TYPES -- //
typedef struct {
uint16_t regs[REG_MAX];
Memory* mem;
Device* devices[MAX_DEVICES];
uint32_t pc;
uint32_t ihp;
@@ -27,3 +31,4 @@ typedef struct {
Emulator* initEmulator(uint32_t memorySize);
void freeEmulator(Emulator* emu);
void startEmulator(Emulator* emu);
void installDevice(Emulator* emu, Device* device, uint8_t deviceNumber);

View File

@@ -9,10 +9,17 @@ int main() {
return 1;
}
RomFile* romFile = readProgramFromFile("../test.bin");
memoryLoadProgram(emu->mem, romFile->instructions, romFile->header.numInstructions);
Instruction program[] = {
{INST_MVI, {REG_A}, 0, true},
{INST_MVI, {REG_B}, 123, true},
{INST_PORT, {REG_A, REG_B, 0}, 0, false},
{INST_PORT, {REG_A, REG_B, 1}, 0, false},
{INST_HLT, {}, 0, false}
};
//startEmulator(emu);
memoryLoadProgram(emu->mem, program, sizeof(program)/sizeof(program[0]));
startEmulator(emu);
freeEmulator(emu);
return 0;

View File

@@ -71,6 +71,7 @@ Instruction decodeInstruction(Memory* m, uint32_t* pc) {
uint8_t offset = 0;
for (uint8_t i = 0; i < 3; i++) {
switch (opTypes[i]) {
case OP_IMM4:
case OP_REG: {
// get the data at the current offset, and grab the 4 bits that are there with a bitwise
// "and" operator