initial commit
This commit is contained in:
12
meson.build
Normal file
12
meson.build
Normal file
@@ -0,0 +1,12 @@
|
||||
project('MyLittleCPU', 'c')
|
||||
|
||||
sources = [
|
||||
'src/main.c',
|
||||
'src/emu.c',
|
||||
'src/memory.c',
|
||||
'src/instruction.c'
|
||||
]
|
||||
|
||||
args = ['-Wall', '-Wextra', '-Wpedantic', '-O3']
|
||||
|
||||
executable('emu', sources, c_args: args)
|
||||
19
src/emu.c
Normal file
19
src/emu.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "emu.h"
|
||||
|
||||
Emulator* initEmulator(uint32_t memorySize) {
|
||||
Emulator* newEmu = malloc(sizeof(Emulator));
|
||||
if (!newEmu)
|
||||
return NULL;
|
||||
|
||||
// zero out registers
|
||||
memset(newEmu->regs, 0, sizeof(newEmu->regs));
|
||||
|
||||
// init memory
|
||||
newEmu->mem = initMemory(memorySize);
|
||||
if (!newEmu->mem) {
|
||||
free(newEmu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return newEmu;
|
||||
}
|
||||
27
src/emu.h
Normal file
27
src/emu.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "memory.h"
|
||||
|
||||
// -- TYPES -- //
|
||||
typedef enum {
|
||||
REG_A, REG_B, REG_C,
|
||||
|
||||
REG_X, REG_Y, REG_Z,
|
||||
REG_R,
|
||||
|
||||
REG_PC, REG_IHP, REG_SP, REG_F,
|
||||
|
||||
REG_MAX // all registers should come before this one, this is so we can
|
||||
// automatically know the length of the registers array
|
||||
} Register;
|
||||
|
||||
typedef struct {
|
||||
uint16_t regs[REG_MAX];
|
||||
Memory* mem;
|
||||
} Emulator;
|
||||
|
||||
// -- FUNCTIONS -- //
|
||||
Emulator* initEmulator(uint32_t memorySize);
|
||||
20
src/instruction.c
Normal file
20
src/instruction.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "instruction.h"
|
||||
|
||||
const InstructionOperands INSTRUCTION_OPERAND_TYPES[] = {
|
||||
{ INST_MVI, {OP_IMM4, OP_IMM4, OP_NONE} },
|
||||
{ INST_MOV, {OP_IMM4, OP_NONE, OP_NONE} },
|
||||
{ INST_ADD, {OP_IMM4, OP_IMM4, OP_NONE} },
|
||||
{ INST_SUB, {OP_IMM4, OP_IMM4, OP_NONE} },
|
||||
{ INST_LOAD, {OP_IMM4, OP_IMM4, OP_IMM4} },
|
||||
{ INST_STORE, {OP_IMM4, OP_IMM4, OP_IMM4} },
|
||||
{ INST_AND, {OP_IMM4, OP_IMM4, OP_NONE} },
|
||||
{ INST_OR, {OP_IMM4, OP_IMM4, OP_NONE} },
|
||||
{ INST_XOR, {OP_IMM4, OP_IMM4, OP_NONE} },
|
||||
{ INST_SHF, {OP_IMM4, OP_IMM4, OP_IMM4} },
|
||||
{ INST_JMP, {OP_IMM4, OP_IMM4, OP_NONE} },
|
||||
{ INST_JIZ, {OP_IMM4, OP_IMM4, OP_NONE} },
|
||||
{ INST_CALL, {OP_IMM4, OP_IMM4, OP_NONE} },
|
||||
{ INST_RET, {OP_NONE, OP_NONE, OP_NONE} },
|
||||
{ INST_SYS, {OP_IMM4, OP_IMM4, OP_IMM4} },
|
||||
{ INST_HLT, {OP_NONE, OP_NONE, OP_NONE} },
|
||||
};
|
||||
30
src/instruction.h
Normal file
30
src/instruction.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// -- TYPES -- //
|
||||
typedef enum {
|
||||
INST_MOV, INST_MVI, INST_ADD, INST_SUB, INST_LOAD, INST_STORE, INST_AND, INST_OR,
|
||||
INST_XOR, INST_SHF, INST_JMP, INST_JIZ, INST_CALL, INST_RET, INST_SYS, INST_HLT
|
||||
} InstructionOpcode;
|
||||
|
||||
typedef uint16_t SerializedInst;
|
||||
|
||||
typedef struct {
|
||||
InstructionOpcode opcode;
|
||||
uint16_t a;
|
||||
uint16_t b;
|
||||
uint16_t c;
|
||||
} Instruction;
|
||||
|
||||
typedef enum {
|
||||
OP_NONE, OP_IMM4
|
||||
} OperandType;
|
||||
|
||||
typedef struct {
|
||||
InstructionOpcode opcode;
|
||||
OperandType operandTypes[3];
|
||||
} InstructionOperands;
|
||||
|
||||
// -- CONSTANTS -- //
|
||||
extern const InstructionOperands INSTRUCTION_OPERAND_TYPES[];
|
||||
14
src/main.c
Normal file
14
src/main.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
#include "emu.h"
|
||||
|
||||
int main() {
|
||||
Emulator* emu = initEmulator(0x00010FFF);
|
||||
if (!emu) {
|
||||
fprintf(stderr, "emu: error: failed to allocate memory for emulator\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(emu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
24
src/memory.c
Normal file
24
src/memory.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "memory.h"
|
||||
|
||||
Memory* initMemory(uint32_t size) {
|
||||
Memory* newMemory = malloc(sizeof(Memory));
|
||||
if (!newMemory)
|
||||
return NULL;
|
||||
|
||||
newMemory->size = size;
|
||||
newMemory->data = calloc(size, sizeof(uint8_t));
|
||||
if (!newMemory->data) {
|
||||
free(newMemory);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return newMemory;
|
||||
}
|
||||
|
||||
inline uint16_t memoryLoadWord(Memory* m, uint32_t address) {
|
||||
return m->data[address];
|
||||
}
|
||||
|
||||
inline void memorySaveWord(Memory* m, uint32_t address, uint16_t value) {
|
||||
((uint16_t*)m->data)[address] = value;
|
||||
}
|
||||
22
src/memory.h
Normal file
22
src/memory.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "instruction.h"
|
||||
|
||||
#define MEM_CALL_STACK_OFFSET 0x00000FFF
|
||||
#define MEM_PROGRAM_START 0x00001000
|
||||
#define MEM_PROGRAM_END 0x0000FFFF
|
||||
#define MEM_GP_START 0x00010000
|
||||
|
||||
// -- TYPES -- //
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
uint8_t* data;
|
||||
} Memory;
|
||||
|
||||
// -- FUNCTIONS -- //
|
||||
Memory* initMemory(uint32_t size);
|
||||
uint16_t memoryLoadWord(Memory* m, uint32_t address);
|
||||
void memorySaveWord(Memory* m, uint32_t address, uint16_t value);
|
||||
Instruction decodeInstruction(Memory* m, uint32_t pc);
|
||||
Reference in New Issue
Block a user