Subastra
Loading...
Searching...
No Matches
chip.h
Go to the documentation of this file.
1#ifndef __H__CHIP__
2#define __H__CHIP__
3
4#include <stdbool.h>
5#include <stdio.h>
6#include <string.h>
7
8#include "../defs.h"
9#include "../memory.h"
10#include "addressing.h"
11
12#define CHIP_STACK_BOTTOM_ADDR 0x0100
13#define CHIP_MAXIMUM_MEMORY 0x10000
14
15typedef byte (*chip_memory_callback_t)(void *, bool is_write, u16 addr,
16 byte value);
17
22
23typedef struct chip_t chip_t;
24
25typedef void (*chip_external_call_f)(chip_t *chip);
26
41
42typedef enum register_flags_t {
47 // TODO: This is cryptic, find a better name
48 FLAG_B = 4,
53
55 FLAG_MASK_CARRY = 0b00000001,
56 FLAG_MASK_ZERO = 0b00000010,
58 FLAG_MASK_DECIMAL = 0b00001000,
59 FLAG_MASK_B = 0b00010000,
60 FLAG_MASK_UNUSED = 0b00100000,
61 FLAG_MASK_OVERFLOW = 0b01000000,
62 FLAG_MASK_NEGATIVE = 0b10000000,
64
65static void chip_dbg_dump(chip_t *self) {
66 printf("PC=0x%04X AC=0x%02X X=0x%02X Y=0x%02X SR=0x%02X SP=0x%02X\n",
67 self->pc, self->ac, self->x, self->y, self->sr, self->sp);
68}
69
70static void chip_init(chip_t *self, allocator_t allocator, sz memory_size,
71 u32 quota) {
72 self->memory_callback = 0;
73 self->userdata = 0;
74
75 self->quota = quota;
76 self->halted = false;
77
78 byte *memory = allocator_alloc_ty(byte, allocator, memory_size);
79 self->memory = memory;
80 self->ac = 0;
81 self->sp = 0xFF;
82
83 self->external_call = 0;
84
85 self->pc = 0;
86 self->x = 0;
87 self->y = 0;
88 self->sr = 0;
89}
90
92 chip_memory_callback_t callback) {
95 current->callback = callback;
96 current->next = self->memory_callback;
97 self->memory_callback = current;
98}
99
100static void chip_load_rom(chip_t *self, byte *rom, size_t len, u16 rom_start) {
101 memcpy(self->memory + rom_start, rom, len);
102
103 byte lo = self->memory[0xFFFC];
104 byte hi = self->memory[0xFFFD];
105
106 self->pc = (u16)hi << 8 | lo;
107}
108
109static byte chip_memory_read_direct(chip_t *self, u16 at) {
110 byte value = self->memory[at & 0xFFFF];
111
112 for (chip_memory_callback_node_t *read_node = self->memory_callback;
113 read_node; read_node = read_node->next)
114 value = read_node->callback(self->userdata, false, at, value);
115
116 return value;
117}
118
119static void chip_memory_write_direct(chip_t *self, u16 at, byte value) {
120 for (chip_memory_callback_node_t *write_node = self->memory_callback;
121 write_node; write_node = write_node->next)
122 value = write_node->callback(self->userdata, true, at, value);
123
124 self->memory[at & 0xFFFF] = value;
125}
126
127static byte chip_pc_inc(chip_t *self) {
128 return chip_memory_read_direct(self, self->pc++);
129}
130
132 u16 value = 0;
133 u16 addr = 0;
134
135 switch (mode) {
137 addr |= chip_pc_inc(self);
138 addr |= (u16)chip_pc_inc(self) << 8;
139 break;
141 addr |= chip_pc_inc(self);
142 addr |= (u16)chip_pc_inc(self) << 8;
143 addr = (addr + self->x) & 0xFFFF;
144 break;
146 addr |= chip_pc_inc(self);
147 addr |= (u16)chip_pc_inc(self) << 8;
148 addr = (addr + self->y) & 0xFFFF;
149 break;
151 addr = self->pc;
152 chip_pc_inc(self);
153 break;
155 addr = chip_pc_inc(self);
156 break;
158 u16 zp_addr = chip_pc_inc(self);
159 addr |= (u16)chip_memory_read_direct(self, zp_addr);
160 addr |= (u16)chip_memory_read_direct(self, (zp_addr + 1) & 0xFFFF) << 8;
161 addr += self->y;
162 break;
163 }
165 PANIC_("The ACCUMULATOR addressing read mode is handled on per-instruction "
166 "basis");
167 default:
168 PANIC("Unhandled addressing mode read %d", mode);
169 }
170
171 value |= (u32)chip_memory_read_direct(self, addr);
172 value |= (u32)chip_memory_read_direct(self, (addr + 1) & 0xFF) << 8;
173
174 return ((u32)addr << 16) | value;
175}
176
178 byte value) {
179 u16 addr = 0;
180
181 switch (mode) {
182 case ADDR_MODE_ABSOLUTE: {
183 addr |= chip_pc_inc(self);
184 addr |= (u16)chip_pc_inc(self) << 8;
185 break;
186 }
188 addr |= chip_pc_inc(self);
189 addr |= (u16)chip_pc_inc(self) << 8;
190 addr = (addr + self->x) & 0xFFFF;
191 break;
192 }
193 case ADDR_MODE_ZERO_PAGE: {
194 addr = chip_pc_inc(self);
195 break;
196 }
198 // NOTE(Artur): can this method leave the zero page?
199 // that would be a cool bug/feature
200 // in the original 6502 it will just ignore the higher
201 // byte, but I think its an interesting feature
202 // https://www.masswerk.at/6502/6502_instruction_set.html#modes
203 addr = chip_pc_inc(self);
204 addr += self->y;
205 addr &= 0xFF;
206 break;
207 }
209 u16 zp_addr = chip_pc_inc(self);
210 addr |= (u16)chip_memory_read_direct(self, zp_addr);
211 addr |= (u16)chip_memory_read_direct(self, (zp_addr + 1) & 0xFF) << 8;
212 addr += self->y;
213 break;
214 }
216 PANIC_("The ACCUMULATOR addressing read mode is handled on per-instruction "
217 "basis");
218 default:
219 PANIC("Unhandled addressing mode write %d", mode);
220 }
221
222 self->memory[addr] = value;
223 return addr;
224}
225
226static u16 get_memory_addr(u32 read) { return (read >> 16) & 0xFFFF; }
227
228static byte get_memory_word(u32 read) { return read & 0xFF; }
229
233
235 return chip_memory_perform_read(self, mode) & 0xFF;
236}
237
239 return chip_memory_perform_read(self, mode) & 0xFFFF;
240}
241
242static void chip_stack_push(chip_t *self, byte value) {
243 if (self->sp == 0x00) {
244 PANIC_("Stack overflow");
245 }
246
248 self->sp--;
249 self->sp &= 0xFF;
250}
251
252static byte chip_stack_pull(chip_t *self) {
253 if (self->sp == 0xFF) {
254 PANIC_("Stack underflow");
255 }
256
257 self->sp++;
258 self->sp &= 0xFF;
259 byte value = chip_memory_read_direct(self, CHIP_STACK_BOTTOM_ADDR + self->sp);
260 return value;
261}
262
263static byte chip_flags_get(chip_t *self, register_flags_t flag) {
264 return (self->sr >> flag) & 1;
265}
266
267static void chip_flags_set(chip_t *self, register_flags_t flag, byte value) {
268 self->sr &= ~(1 << flag);
269 self->sr |= !!value << flag;
270}
271
272static void chip_flags_update_carry(chip_t *self, byte value) {
273 chip_flags_set(self, FLAG_CARRY, value);
274}
275
276static void chip_flags_update_zero_negative(chip_t *self, byte value) {
279 self->sr &= ~mask;
280 chip_flags_set(self, FLAG_ZERO, value == 0);
281 chip_flags_set(self, FLAG_NEGATIVE, value & 0x80);
282}
283
284static void chip_flags_update_overflow(chip_t *self, byte value) {
285 chip_flags_set(self, FLAG_OVERFLOW, value);
286}
287
288#endif
addressing_mode_t
Definition addressing.h:6
@ ADDR_MODE_INDIRECT_Y
Definition addressing.h:16
@ ADDR_MODE_ACCUMULATOR
Definition addressing.h:19
@ ADDR_MODE_ZERO_PAGE
Definition addressing.h:15
@ ADDR_MODE_IMMEDIATE
Definition addressing.h:10
@ ADDR_MODE_ABSOLUTE
Definition addressing.h:7
@ ADDR_MODE_ABSOLUTE_X
Definition addressing.h:8
@ ADDR_MODE_ABSOLUTE_Y
Definition addressing.h:9
@ ADDR_MODE_ZERO_PAGE_Y
Definition addressing.h:18
#define CHIP_STACK_BOTTOM_ADDR
Definition chip.h:12
static u16 chip_memory_read_dword(chip_t *self, addressing_mode_t mode)
Definition chip.h:238
static void chip_stack_push(chip_t *self, byte value)
Definition chip.h:242
byte(* chip_memory_callback_t)(void *, bool is_write, u16 addr, byte value)
Definition chip.h:15
static u32 chip_memory_perform_read(chip_t *self, addressing_mode_t mode)
Definition chip.h:131
static byte chip_memory_read_word(chip_t *self, addressing_mode_t mode)
Definition chip.h:234
static u16 get_memory_addr(u32 read)
Definition chip.h:226
static void chip_flags_update_overflow(chip_t *self, byte value)
Definition chip.h:284
static u16 chip_memory_perform_write(chip_t *self, addressing_mode_t mode, byte value)
Definition chip.h:177
static void chip_dbg_dump(chip_t *self)
Definition chip.h:65
static byte get_memory_word(u32 read)
Definition chip.h:228
static void chip_load_rom(chip_t *self, byte *rom, size_t len, u16 rom_start)
Definition chip.h:100
static void chip_flags_set(chip_t *self, register_flags_t flag, byte value)
Definition chip.h:267
void(* chip_external_call_f)(chip_t *chip)
Definition chip.h:25
static byte chip_pc_inc(chip_t *self)
Definition chip.h:127
static void chip_memory_write_direct(chip_t *self, u16 at, byte value)
Definition chip.h:119
static u16 chip_memory_read_addr(chip_t *self, addressing_mode_t mode)
Definition chip.h:230
register_flags_mask_t
Definition chip.h:54
@ FLAG_MASK_CARRY
Definition chip.h:55
@ FLAG_MASK_DECIMAL
Definition chip.h:58
@ FLAG_MASK_UNUSED
Definition chip.h:60
@ FLAG_MASK_B
Definition chip.h:59
@ FLAG_MASK_INTERRUPT_DISABLE
Definition chip.h:57
@ FLAG_MASK_ZERO
Definition chip.h:56
@ FLAG_MASK_NEGATIVE
Definition chip.h:62
@ FLAG_MASK_OVERFLOW
Definition chip.h:61
static byte chip_memory_read_direct(chip_t *self, u16 at)
Definition chip.h:109
static void chip_flags_update_carry(chip_t *self, byte value)
Definition chip.h:272
register_flags_t
Definition chip.h:42
@ FLAG_NEGATIVE
Definition chip.h:51
@ FLAG_OVERFLOW
Definition chip.h:50
@ FLAG_ZERO
Definition chip.h:44
@ FLAG_B
Definition chip.h:48
@ FLAG_UNUSED
Definition chip.h:49
@ FLAG_CARRY
Definition chip.h:43
@ FLAG_DECIMAL
Definition chip.h:46
@ FLAG_INTERRUPT_DISABLE
Definition chip.h:45
static void chip_init(chip_t *self, allocator_t allocator, sz memory_size, u32 quota)
Definition chip.h:70
static byte chip_stack_pull(chip_t *self)
Definition chip.h:252
static void chip_flags_update_zero_negative(chip_t *self, byte value)
Definition chip.h:276
static void chip_memory_add_callback(chip_t *self, chip_memory_callback_t callback)
Definition chip.h:91
static byte chip_flags_get(chip_t *self, register_flags_t flag)
Definition chip.h:263
unsigned char byte
Definition defs.h:49
size_t sz
Definition defs.h:51
uint16_t u16
Definition defs.h:48
#define PANIC_(msg)
Definition defs.h:9
#define PANIC(msg,...)
Definition defs.h:15
uint32_t u32
Definition defs.h:45
A generic allocator type passed by value. Contains a fallback allocator and a set of function pointer...
Definition memory.h:30
Definition chip.h:18
chip_memory_callback_t callback
Definition chip.h:19
struct chip_memory_callback_node_t * next
Definition chip.h:20
Definition chip.h:27
byte ac
Definition chip.h:39
byte sp
Definition chip.h:39
bool halted
Definition chip.h:34
u32 quota
Definition chip.h:33
chip_external_call_f external_call
Definition chip.h:29
u16 pc
Definition chip.h:38
byte x
Definition chip.h:39
chip_memory_callback_node_t * memory_callback
Definition chip.h:28
byte y
Definition chip.h:39
byte * memory
Definition chip.h:36
byte sr
Definition chip.h:39
void * userdata
Definition chip.h:31