diff options
| author | vin <git@vineetk.net> | 2024-06-08 22:08:51 +0530 |
|---|---|---|
| committer | vin <git@vineetk.net> | 2024-06-08 22:08:51 +0530 |
| commit | 72e29b3d25bfe93810b3faf3133dfc3c15f15e14 (patch) | |
| tree | 56b346179eb7da1b64f11de836f086b30dd87b9e /cpu.c | |
| parent | 1ac30a026b7877ca6b295c661d91b20eaddb01c9 (diff) | |
move addressing mode parsing into separate function
Diffstat (limited to 'cpu.c')
| -rw-r--r-- | cpu.c | 117 |
1 files changed, 44 insertions, 73 deletions
| @@ -62,49 +62,58 @@ peek16(uint16_t addr) | |||
| 62 | return (uint16_t)memory[addr] | ((uint16_t)memory[addr + 1] << 8); | 62 | return (uint16_t)memory[addr] | ((uint16_t)memory[addr + 1] << 8); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void | 65 | uint8_t |
| 66 | adc(enum addressing_mode mode) | 66 | opmode_arg(enum addressing_mode mode) |
| 67 | { | 67 | { |
| 68 | uint8_t arg, val; | 68 | uint8_t arg, val; |
| 69 | uint16_t sum; // 16-bit sum makes it easier to determine carry flag | ||
| 70 | 69 | ||
| 71 | if (mode != AM_ABS && mode != AM_ABS_X && mode != AM_ABS_Y) | 70 | if (mode != AM_ABS && mode != AM_ABS_X && mode != AM_ABS_Y) |
| 72 | arg = peek(regs.pc++); | 71 | arg = peek(regs.pc++); |
| 73 | else | 72 | else |
| 74 | arg = peek16(regs.pc++); | 73 | arg = peek16(regs.pc), regs.pc += 2; |
| 75 | 74 | ||
| 76 | switch (mode) { | 75 | switch (mode) { |
| 77 | case AM_IMM: /* $69 */ | 76 | case AM_IMM: |
| 78 | val = arg; | 77 | val = arg; |
| 79 | break; | 78 | break; |
| 80 | case AM_ZP: /* $65 */ | 79 | case AM_ZP: |
| 81 | val = peek(arg % 256); | 80 | val = peek(arg % 256); |
| 82 | break; | 81 | break; |
| 83 | case AM_ABS: /* $6D */ | 82 | case AM_ZP_X: |
| 84 | val = peek16(arg); | ||
| 85 | break; | ||
| 86 | case AM_ZP_X: /* $75 */ | ||
| 87 | val = peek((arg + regs.x) % 256); | 83 | val = peek((arg + regs.x) % 256); |
| 88 | break; | 84 | break; |
| 89 | case AM_ABS_X: /* $7D */ | 85 | case AM_ZP_Y: |
| 86 | val = peek((arg + regs.y) % 256); | ||
| 87 | break; | ||
| 88 | case AM_ABS: | ||
| 89 | val = peek16(arg); | ||
| 90 | break; | ||
| 91 | case AM_ABS_X: | ||
| 90 | val = peek16(arg + regs.x); | 92 | val = peek16(arg + regs.x); |
| 91 | break; | 93 | break; |
| 92 | case AM_ABS_Y: /* $79 */ | 94 | case AM_ABS_Y: |
| 93 | val = peek16(arg + regs.y); | 95 | val = peek16(arg + regs.y); |
| 94 | break; | 96 | break; |
| 95 | case AM_IND_X: /* $61 */ | 97 | case AM_IND_X: |
| 96 | val = peek(peek((arg + regs.x) % 256) + peek((arg + regs.x + 1) % 256) * 256); | 98 | val = peek(peek((arg + regs.x) % 256) + peek((arg + regs.x + 1) % 256) * 256); |
| 97 | break; | 99 | break; |
| 98 | case AM_IND_Y: /* $71 */ | 100 | case AM_IND_Y: |
| 99 | val = peek(peek(arg) + peek((arg + 1) % 256) * 256 + regs.y); | 101 | val = peek(peek(arg) + peek((arg + 1) % 256) * 256 + regs.y); |
| 100 | break; | 102 | break; |
| 101 | default: | 103 | default: |
| 102 | fprintf(stderr, "INVALID ADC ADDRESSING MODE\n"); | 104 | fprintf(stderr, "INVALID ADDRESSING MODE\n"); |
| 103 | abort(); | 105 | abort(); |
| 104 | return; | ||
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | sum = regs.a + val + regs.status.carry; | 108 | return val; |
| 109 | } | ||
| 110 | |||
| 111 | void | ||
| 112 | adc(uint8_t arg) | ||
| 113 | { | ||
| 114 | uint16_t sum; // 16-bit sum makes it easier to determine carry flag | ||
| 115 | |||
| 116 | sum = regs.a + arg + regs.status.carry; | ||
| 108 | regs.a = sum & 0xFF; | 117 | regs.a = sum & 0xFF; |
| 109 | 118 | ||
| 110 | regs.status.carry = sum > 0xFF; | 119 | regs.status.carry = sum > 0xFF; |
| @@ -144,48 +153,10 @@ inx(void) | |||
| 144 | } | 153 | } |
| 145 | 154 | ||
| 146 | void | 155 | void |
| 147 | lda(enum addressing_mode mode) | 156 | lda(uint8_t arg) |
| 148 | { | 157 | { |
| 149 | uint8_t arg, val; | ||
| 150 | |||
| 151 | if (mode != AM_ABS && mode != AM_ABS_X && mode != AM_ABS_Y) | ||
| 152 | arg = peek(regs.pc++); | ||
| 153 | else | ||
| 154 | arg = peek16(regs.pc++); | ||
| 155 | |||
| 156 | switch (mode) { | ||
| 157 | case AM_IMM: /* $A9 */ | ||
| 158 | val = arg; | ||
| 159 | break; | ||
| 160 | case AM_ZP: /* $A5 */ | ||
| 161 | val = peek(arg % 256); | ||
| 162 | break; | ||
| 163 | case AM_ABS: /* $AD */ | ||
| 164 | val = peek16(arg); | ||
| 165 | break; | ||
| 166 | case AM_ZP_X: /* $B5 */ | ||
| 167 | val = peek((arg + regs.x) % 256); | ||
| 168 | break; | ||
| 169 | case AM_ABS_X: /* $BD */ | ||
| 170 | val = peek16(arg + regs.x); | ||
| 171 | break; | ||
| 172 | case AM_ABS_Y: /* $B9 */ | ||
| 173 | val = peek16(arg + regs.y); | ||
| 174 | break; | ||
| 175 | case AM_IND_X: /* $A1 */ | ||
| 176 | val = peek(peek((arg + regs.x) % 256) + peek((arg + regs.x + 1) % 256) * 256); | ||
| 177 | break; | ||
| 178 | case AM_IND_Y: /* $B1 */ | ||
| 179 | val = peek(peek(arg) + peek((arg + 1) % 256) * 256 + regs.y); | ||
| 180 | break; | ||
| 181 | default: | ||
| 182 | fprintf(stderr, "INVALID LDA ADDRESSING MODE\n"); | ||
| 183 | abort(); | ||
| 184 | return; | ||
| 185 | } | ||
| 186 | |||
| 187 | printf("arg1 $%02X\n", arg); | 158 | printf("arg1 $%02X\n", arg); |
| 188 | regs.a = val; | 159 | regs.a = arg; |
| 189 | 160 | ||
| 190 | STATUS_UPDATE_ZERO(regs.a); | 161 | STATUS_UPDATE_ZERO(regs.a); |
| 191 | STATUS_UPDATE_NEGATIVE(regs.a); | 162 | STATUS_UPDATE_NEGATIVE(regs.a); |
| @@ -206,55 +177,55 @@ interpret(void) | |||
| 206 | brk(); | 177 | brk(); |
| 207 | return; | 178 | return; |
| 208 | case 0x61: | 179 | case 0x61: |
| 209 | adc(AM_IND_X); | 180 | adc(opmode_arg(AM_IND_X)); |
| 210 | break; | 181 | break; |
| 211 | case 0x65: | 182 | case 0x65: |
| 212 | adc(AM_ZP); | 183 | adc(opmode_arg(AM_ZP)); |
| 213 | break; | 184 | break; |
| 214 | case 0x69: | 185 | case 0x69: |
| 215 | adc(AM_IMM); | 186 | adc(opmode_arg(AM_IMM)); |
| 216 | break; | 187 | break; |
| 217 | case 0x6D: | 188 | case 0x6D: |
| 218 | adc(AM_ABS); | 189 | adc(opmode_arg(AM_ABS)); |
| 219 | break; | 190 | break; |
| 220 | case 0x71: | 191 | case 0x71: |
| 221 | adc(AM_IND_Y); | 192 | adc(opmode_arg(AM_IND_Y)); |
| 222 | break; | 193 | break; |
| 223 | case 0x75: | 194 | case 0x75: |
| 224 | adc(AM_ZP_X); | 195 | adc(opmode_arg(AM_ZP_X)); |
| 225 | break; | 196 | break; |
| 226 | case 0x79: | 197 | case 0x79: |
| 227 | adc(AM_ABS_Y); | 198 | adc(opmode_arg(AM_ABS_Y)); |
| 228 | break; | 199 | break; |
| 229 | case 0x7D: | 200 | case 0x7D: |
| 230 | adc(AM_ABS_X); | 201 | adc(opmode_arg(AM_ABS_X)); |
| 231 | break; | 202 | break; |
| 232 | case 0xa1: | 203 | case 0xa1: |
| 233 | lda(AM_IND_X); | 204 | lda(opmode_arg(AM_IND_X)); |
| 234 | break; | 205 | break; |
| 235 | case 0xa5: | 206 | case 0xa5: |
| 236 | lda(AM_ZP); | 207 | lda(opmode_arg(AM_ZP)); |
| 237 | break; | 208 | break; |
| 238 | case 0xa9: | 209 | case 0xa9: |
| 239 | lda(AM_IMM); | 210 | lda(opmode_arg(AM_IMM)); |
| 240 | break; | 211 | break; |
| 241 | case 0xaa: | 212 | case 0xaa: |
| 242 | tax(); | 213 | tax(); |
| 243 | break; | 214 | break; |
| 244 | case 0xad: | 215 | case 0xad: |
| 245 | lda(AM_ABS); | 216 | lda(opmode_arg(AM_ABS)); |
| 246 | break; | 217 | break; |
| 247 | case 0xb1: | 218 | case 0xb1: |
| 248 | lda(AM_IND_Y); | 219 | lda(opmode_arg(AM_IND_Y)); |
| 249 | break; | 220 | break; |
| 250 | case 0xb5: | 221 | case 0xb5: |
| 251 | lda(AM_ZP_X); | 222 | lda(opmode_arg(AM_ZP_X)); |
| 252 | break; | 223 | break; |
| 253 | case 0xb9: | 224 | case 0xb9: |
| 254 | lda(AM_ABS_Y); | 225 | lda(opmode_arg(AM_ABS_Y)); |
| 255 | break; | 226 | break; |
| 256 | case 0xbd: | 227 | case 0xbd: |
| 257 | lda(AM_ABS_X); | 228 | lda(opmode_arg(AM_ABS_X)); |
| 258 | break; | 229 | break; |
| 259 | case 0xe8: | 230 | case 0xe8: |
| 260 | inx(); | 231 | inx(); |
