Compare commits
2 Commits
68b7667725
...
8e1f83ab31
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e1f83ab31 | |||
| fb3efc77c3 |
@@ -5,7 +5,8 @@ sources = files(
|
|||||||
'src/emu.c',
|
'src/emu.c',
|
||||||
'src/memory.c',
|
'src/memory.c',
|
||||||
'src/instruction.c',
|
'src/instruction.c',
|
||||||
'src/util.c'
|
'src/util.c',
|
||||||
|
'src/device.c'
|
||||||
)
|
)
|
||||||
|
|
||||||
asmSources = files(
|
asmSources = files(
|
||||||
|
|||||||
32
src/device.c
32
src/device.c
@@ -2,11 +2,37 @@
|
|||||||
|
|
||||||
Device* createDevice(
|
Device* createDevice(
|
||||||
const char* name,
|
const char* name,
|
||||||
void (*sendToDevice)(uint16_t number),
|
void (*update)(Device* self)
|
||||||
uint16_t (*receiveFromDevice)(),
|
|
||||||
void (*update)()
|
|
||||||
) {
|
) {
|
||||||
Device* new = malloc(sizeof(Device));
|
Device* new = malloc(sizeof(Device));
|
||||||
if (!new)
|
if (!new)
|
||||||
return NULL;
|
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;
|
||||||
}
|
}
|
||||||
30
src/device.h
30
src/device.h
@@ -1,18 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.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];
|
char name[32];
|
||||||
|
|
||||||
void (*sendToDevice)(uint16_t number);
|
uint16_t in[DEVICE_BUFFER_LENGTH];
|
||||||
uint16_t (*receiveFromDevice)();
|
uint8_t inPos;
|
||||||
void (*update)();
|
|
||||||
} Device;
|
uint16_t out[DEVICE_BUFFER_LENGTH];
|
||||||
|
uint8_t outPos;
|
||||||
|
|
||||||
|
void (*update)(Device* self);
|
||||||
|
};
|
||||||
|
|
||||||
Device* createDevice(
|
Device* createDevice(
|
||||||
const char* name,
|
const char* name,
|
||||||
void (*sendToDevice)(uint16_t number),
|
void (*update)(Device* self)
|
||||||
uint16_t (*receiveFromDevice)(),
|
);
|
||||||
void (*update)()
|
|
||||||
);
|
uint16_t deviceRead(Device* self);
|
||||||
|
void deviceSend(Device* self, uint16_t value);
|
||||||
|
bool deviceCanRead(Device* self);
|
||||||
62
src/emu.c
62
src/emu.c
@@ -1,9 +1,7 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
|
|
||||||
static inline Instruction fetchInst(Emulator* emu) {
|
static inline Instruction fetchInst(Emulator* emu) {
|
||||||
Instruction inst = decodeInstruction(emu->mem, &emu->pc);
|
return decodeInstruction(emu->mem, &emu->pc);
|
||||||
printf("%s\n", instructionToCStr(inst));
|
|
||||||
return inst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void updateFlagsRegister(Emulator* emu, int32_t value) {
|
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) {
|
void startEmulator(Emulator* emu) {
|
||||||
static void* dispatchTable[] = {
|
static void* dispatchTable[] = {
|
||||||
&&MOV,
|
&&MOV,
|
||||||
@@ -32,15 +41,16 @@ void startEmulator(Emulator* emu) {
|
|||||||
&&JIZ,
|
&&JIZ,
|
||||||
&&CALL,
|
&&CALL,
|
||||||
&&RET,
|
&&RET,
|
||||||
&&SYS,
|
&&PORT,
|
||||||
&&HLT
|
&&HLT
|
||||||
};
|
};
|
||||||
|
|
||||||
emu->halted = false;
|
emu->halted = false;
|
||||||
Instruction inst;
|
Instruction inst;
|
||||||
|
|
||||||
#define DISPATCH() inst = fetchInst(emu); \
|
#define DISPATCH() updateDevices(emu); \
|
||||||
goto *dispatchTable[inst.opcode];
|
inst = fetchInst(emu); \
|
||||||
|
goto *dispatchTable[inst.opcode]
|
||||||
|
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
|
||||||
@@ -133,8 +143,39 @@ void startEmulator(Emulator* emu) {
|
|||||||
emu->pc = ((uint32_t*)emu->mem->data)[++emu->sp];
|
emu->pc = ((uint32_t*)emu->mem->data)[++emu->sp];
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
SYS: {
|
PORT: {
|
||||||
// TODO
|
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();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
HLT: {
|
HLT: {
|
||||||
@@ -170,3 +211,8 @@ void freeEmulator(Emulator* emu) {
|
|||||||
freeMemory(emu->mem);
|
freeMemory(emu->mem);
|
||||||
free(emu);
|
free(emu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void installDevice(Emulator* emu, Device* device, uint8_t deviceNumber) {
|
||||||
|
assert(deviceNumber < MAX_DEVICES);
|
||||||
|
emu->devices[deviceNumber] = device;
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
@@ -11,10 +12,13 @@
|
|||||||
#define FLAG_NEGATIVE (1 << 1)
|
#define FLAG_NEGATIVE (1 << 1)
|
||||||
#define FLAG_OVERFLOW (1 << 2)
|
#define FLAG_OVERFLOW (1 << 2)
|
||||||
|
|
||||||
|
#define MAX_DEVICES 64
|
||||||
|
|
||||||
// -- TYPES -- //
|
// -- TYPES -- //
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t regs[REG_MAX];
|
uint16_t regs[REG_MAX];
|
||||||
Memory* mem;
|
Memory* mem;
|
||||||
|
Device* devices[MAX_DEVICES];
|
||||||
|
|
||||||
uint32_t pc;
|
uint32_t pc;
|
||||||
uint32_t ihp;
|
uint32_t ihp;
|
||||||
@@ -26,4 +30,5 @@ typedef struct {
|
|||||||
// -- FUNCTIONS -- //
|
// -- FUNCTIONS -- //
|
||||||
Emulator* initEmulator(uint32_t memorySize);
|
Emulator* initEmulator(uint32_t memorySize);
|
||||||
void freeEmulator(Emulator* emu);
|
void freeEmulator(Emulator* emu);
|
||||||
void startEmulator(Emulator* emu);
|
void startEmulator(Emulator* emu);
|
||||||
|
void installDevice(Emulator* emu, Device* device, uint8_t deviceNumber);
|
||||||
13
src/main.c
13
src/main.c
@@ -9,10 +9,17 @@ int main() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RomFile* romFile = readProgramFromFile("../test.bin");
|
Instruction program[] = {
|
||||||
memoryLoadProgram(emu->mem, romFile->instructions, romFile->header.numInstructions);
|
{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);
|
freeEmulator(emu);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ Instruction decodeInstruction(Memory* m, uint32_t* pc) {
|
|||||||
uint8_t offset = 0;
|
uint8_t offset = 0;
|
||||||
for (uint8_t i = 0; i < 3; i++) {
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
switch (opTypes[i]) {
|
switch (opTypes[i]) {
|
||||||
|
case OP_IMM4:
|
||||||
case OP_REG: {
|
case OP_REG: {
|
||||||
// get the data at the current offset, and grab the 4 bits that are there with a bitwise
|
// get the data at the current offset, and grab the 4 bits that are there with a bitwise
|
||||||
// "and" operator
|
// "and" operator
|
||||||
|
|||||||
Reference in New Issue
Block a user