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