annotate src/cpu.c @ 43:6e7bfe83d2b0

Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
author Michael Pavone <pavone@retrodev.com>
date Sat, 27 Aug 2016 22:38:31 -0700
parents 5683d9ba9acc
children 51672bd41cdd
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
1 #include <stdint.h>
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
2 #include <stdlib.h>
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
3 #include <string.h>
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
4 #include <stdio.h>
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
5 #include "cpu.h"
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
6
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
7 enum {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
8 EXCEPTION_INTERRUPT_0,
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
9 EXCEPTION_INTERRUPT_1,
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
10 EXCEPTION_UNALIGNED_READ,
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
11 EXCEPTION_INVALID_INSTRUCTION
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
12 };
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
13
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
14 enum {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
15 STATE_NEED_FETCH,
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
16 STATE_NORMAL,
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
17 STATE_EXCEPTION_START
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
18 };
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
19
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
20 #define STATUS_INT0_ENABLE 1
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
21 #define STATUS_INT1_ENABLE 2
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
22 #define FLAG_Z 4
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
23 #define FLAG_C 8
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
24 #define FLAG_N 16
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
25
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
26 cpu* alloc_cpu(uint32_t clock_divider, uint32_t num_regions, memory_region *regions)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
27 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
28 size_t alloc_size = sizeof(cpu) + sizeof(memory_region) * num_regions;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
29 cpu *context = malloc(alloc_size);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
30 memset(context, 0, alloc_size);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
31 context->clock_inc = clock_divider;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
32 context->num_mem_regions = num_regions;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
33 memcpy(context->mem_regions, regions, num_regions*sizeof(memory_region));
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
34
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
35 return context;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
36 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
37
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
38 uint16_t cpu_read_16(cpu *context, uint32_t address)
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
39 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
40 context->cycles += context->clock_inc;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
41 if (address & 1) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
42 context->exception = EXCEPTION_UNALIGNED_READ;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
43 context->state = STATE_EXCEPTION_START;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
44 return 0xFFFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
45 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
46 memory_region *cur = context->mem_regions;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
47 for (memory_region *end = cur + context->num_mem_regions; cur < end; cur++)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
48 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
49 if (address >= cur->start && address <= cur->end && (cur->flags & MEM_READ)) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
50 return cur->base[address - cur->start] << 8 | cur->base[address - cur->start + 1];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
51 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
52 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
53 return 0xFFFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
54 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
55
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
56 uint8_t cpu_read_8(cpu *context, uint32_t address)
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
57 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
58 context->cycles += context->clock_inc;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
59 memory_region *cur = context->mem_regions;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
60 for (memory_region *end = cur + context->num_mem_regions; cur < end; cur++)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
61 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
62 if (address >= cur->start && address <= cur->end && (cur->flags & MEM_READ)) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
63 return cur->base[address - cur->start];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
64 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
65 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
66 return 0xFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
67 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
68
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
69 void cpu_write_16(cpu *context, uint32_t address, uint16_t value)
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
70 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
71 context->cycles += context->clock_inc;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
72 if (address & 1) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
73 context->exception = EXCEPTION_UNALIGNED_READ;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
74 context->state = STATE_EXCEPTION_START;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
75 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
76 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
77 memory_region *cur = context->mem_regions;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
78 for (memory_region *end = cur + context->num_mem_regions; cur < end; cur++)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
79 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
80 if (address >= cur->start && address <= cur->end && (cur->flags & MEM_WRITE)) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
81 cur->base[address - cur->start] = value >> 8;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
82 cur->base[address - cur->start + 1] = value;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
83 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
84 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
85 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
86 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
87
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
88 void cpu_write_8(cpu *context, uint32_t address, uint8_t value)
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
89 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
90 context->cycles += context->clock_inc;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
91 memory_region *cur = context->mem_regions;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
92 for (memory_region *end = cur + context->num_mem_regions; cur < end; cur++)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
93 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
94 if (address >= cur->start && address <= cur->end && (cur->flags & MEM_WRITE)) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
95 cur->base[address - cur->start] = value;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
96 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
97 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
98 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
99 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
100
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
101 uint16_t cpu_read_port(cpu *context, uint8_t port)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
102 {
20
a9364f5ee81a Fix timing of port IO
Michael Pavone <pavone@retrodev.com>
parents: 13
diff changeset
103 context->cycles += context->clock_inc;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
104 port &= 0xF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
105 if (context->port_handlers[port].read) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
106 return context->port_handlers[port].read(context, port);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
107 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
108 return 0xFFFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
109 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
110
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
111 void cpu_write_port(cpu *context, uint8_t port, uint16_t value)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
112 {
20
a9364f5ee81a Fix timing of port IO
Michael Pavone <pavone@retrodev.com>
parents: 13
diff changeset
113 context->cycles += context->clock_inc;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
114 port &= 0xF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
115 if (context->port_handlers[port].write) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
116 context->port_handlers[port].write(context, port, value);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
117 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
118 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
119
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
120 void fetch_instruction(cpu *context)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
121 {
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
122 context->prefetch = cpu_read_16(context, context->pc_msb | context->regs[REG_PC]);
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
123 context->regs[REG_PC] += 2;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
124 context->state = STATE_NORMAL;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
125 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
126
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
127 void vector_fetch(cpu *context)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
128 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
129 context->exception_pc = context->regs[REG_PC] - 2;
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
130 context->exception_pch = context->pc_msb >> 16;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
131 context->exception_sr = context->regs[REG_SR];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
132 context->regs[REG_SR] &= ~(STATUS_INT0_ENABLE | STATUS_INT1_ENABLE);
26
083347ccd508 Implemented vblank interrupts and fixed a bug in exception vector address calculation
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
133 context->regs[REG_PC] = cpu_read_16(context, context->vector_base + context->exception * 2);
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
134 context->pc_msb = 0;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
135 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
136 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
137
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
138 uint16_t sign_extend(uint16_t val)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
139 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
140 if (val & 0x80) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
141 return val | 0xFF00;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
142 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
143 return val;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
144 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
145
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
146 void update_flags_arith(cpu *context, uint32_t result)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
147 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
148 context->regs[REG_SR] &= ~(FLAG_N|FLAG_C|FLAG_Z);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
149 if (!(result & 0xFFFF)) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
150 context->regs[REG_SR] |= FLAG_Z;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
151 }
13
d8ae30286d17 Fix flag calculation and condition code tests
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
152 if (result & 0x8000) {
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
153 context->regs[REG_SR] |= FLAG_N;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
154 }
13
d8ae30286d17 Fix flag calculation and condition code tests
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
155 if (result & 0x10000) {
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
156 context->regs[REG_SR] |= FLAG_C;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
157 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
158 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
159
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
160 void update_flags_bitwise(cpu *context, uint32_t result)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
161 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
162 context->regs[REG_SR] &= ~(FLAG_N|FLAG_Z);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
163 if (!(result & 0xFFFF)) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
164 context->regs[REG_SR] |= FLAG_Z;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
165 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
166 if (result &= 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
167 context->regs[REG_SR] |= FLAG_N;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
168 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
169 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
170
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
171 void run_bcc(cpu *context, uint8_t condition, uint8_t a, uint8_t b)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
172 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
173
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
174 uint8_t doit = 0;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
175 switch (condition)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
176 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
177 case COND_ALWAYS:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
178 doit = 1;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
179 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
180 case COND_NEVER:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
181 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
182 case COND_ZERO:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
183 doit = context->regs[REG_SR] & FLAG_Z;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
184 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
185 case COND_NZERO:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
186 doit = !(context->regs[REG_SR] & FLAG_Z);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
187 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
188 case COND_NEG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
189 doit = context->regs[REG_SR] & FLAG_N;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
190 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
191 case COND_POS:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
192 doit = !(context->regs[REG_SR] & FLAG_N);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
193 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
194 case COND_CARRY:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
195 doit = context->regs[REG_SR] & FLAG_C;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
196 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
197 case COND_NCARRY:
13
d8ae30286d17 Fix flag calculation and condition code tests
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
198 doit = !(context->regs[REG_SR] & FLAG_C);
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
199 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
200 case COND_GREATER:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
201 //not zero and not carry
13
d8ae30286d17 Fix flag calculation and condition code tests
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
202 doit = !(context->regs[REG_SR] & FLAG_Z) && !(context->regs[REG_SR] & FLAG_C);
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
203 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
204 case COND_LEQ:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
205 //zero or carry
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
206 doit = (context->regs[REG_SR] & FLAG_Z) || (context->regs[REG_SR] & FLAG_C);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
207 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
208 default:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
209 context->exception = EXCEPTION_INVALID_INSTRUCTION;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
210 context->state = STATE_EXCEPTION_START;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
211 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
212 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
213
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
214 if (doit) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
215 context->regs[REG_PC] += sign_extend(a << 4 | b) * 2;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
216 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
217 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
218 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
219
2
6204c81e2933 Revert changes to handling of immediate versions of bitwise instructions. Replace asri with cmpi.
Michael Pavone <pavone@retrodev.com>
parents: 0
diff changeset
220 uint16_t format_immediate(uint16_t val)
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
221 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
222 if (val & 8) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
223 val |= 0xFFF0;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
224 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
225 if (!val) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
226 val = 8;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
227 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
228 return val;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
229 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
230
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
231 void run_single_reg(cpu *context, uint8_t dst, uint8_t op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
232 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
233 switch(op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
234 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
235 case RETI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
236 context->regs[dst] = context->exception_ur;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
237 context->regs[REG_PC] = context->exception_pc;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
238 context->regs[REG_SR] = context->exception_sr;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
239 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
240 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
241 case TRAPI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
242 context->state = STATE_EXCEPTION_START;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
243 context->exception = dst;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
244 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
245 case GETEPC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
246 context->regs[dst] = context->exception_pc;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
247 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
248 case SETEPC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
249 context->exception_pc = context->regs[dst];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
250 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
251 case GETESR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
252 context->regs[dst] = context->exception_sr;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
253 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
254 case SETESR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
255 context->exception_sr = context->regs[dst];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
256 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
257 case GETEUR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
258 context->regs[dst] = context->exception_ur;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
259 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
260 case SETEUR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
261 context->exception_ur = context->regs[dst];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
262 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
263 case GETENUM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
264 context->regs[dst] = context->exception;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
265 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
266 case SETENUM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
267 context->exception = context->regs[dst];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
268 break;
25
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
269 case GETVBR:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
270 context->regs[dst] = context->vector_base;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
271 break;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
272 case SETVBR:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
273 context->vector_base = context->regs[dst];
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
274 break;
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
275 case GETDATABANKS:
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
276 context->regs[dst] = context->data_high_msb >> 7 | context->data_low_msb >> 15;
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
277 break;
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
278 case SETDATABANKS:
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
279 context->data_high_msb = (context->regs[dst] & 0xFF00) << 7;
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
280 context->data_low_msb = (context->regs[dst] & 0xFF) << 15;
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
281 break;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
282 default:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
283 context->state = STATE_EXCEPTION_START;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
284 context->exception = EXCEPTION_INVALID_INSTRUCTION;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
285 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
286 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
287 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
288 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
289 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
290 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
291
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
292 void run_single_source(cpu *context, uint8_t dst, uint8_t a, uint8_t op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
293 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
294 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
295 uint8_t shift;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
296 switch(op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
297 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
298 case MOVE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
299 context->regs[dst] = context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
300 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
301 case NEG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
302 tmp = -context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
303 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
304 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
305 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
306 case NOT:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
307 context->regs[dst] = ~context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
308 update_flags_bitwise(context, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
309 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
310 case CMP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
311 tmp = context->regs[dst] - context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
312 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
313 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
314 case CALL:
36
5683d9ba9acc Fix call instruction for the case in which A reg == DST reg
Michael Pavone <pavone@retrodev.com>
parents: 26
diff changeset
315 tmp = context->regs[REG_PC] - 2;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
316 context->regs[REG_PC] = context->regs[a];
36
5683d9ba9acc Fix call instruction for the case in which A reg == DST reg
Michael Pavone <pavone@retrodev.com>
parents: 26
diff changeset
317 context->regs[dst] = tmp;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
318 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
319 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
320 case SWAP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
321 tmp = context->regs[dst];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
322 context->regs[dst] = context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
323 context->regs[a] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
324 if (a == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
325 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
326 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
327 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
328 break;
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
329 case LONGJMP:
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
330 context->regs[REG_PC] = context->regs[a];
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
331 context->pc_msb = (context->regs[dst] & 0x7F) << 16;
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
332 context->state = STATE_NEED_FETCH;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
333 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
334 case INI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
335 context->regs[dst] = cpu_read_port(context, a);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
336 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
337 case OUTI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
338 cpu_write_port(context, a, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
339 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
340 case ADDI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
341 tmp = context->regs[dst] + format_immediate(a);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
342 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
343 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
344 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
345 case ANDI:
2
6204c81e2933 Revert changes to handling of immediate versions of bitwise instructions. Replace asri with cmpi.
Michael Pavone <pavone@retrodev.com>
parents: 0
diff changeset
346 context->regs[dst] = context->regs[dst] & format_immediate(a);
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
347 update_flags_bitwise(context, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
348 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
349 case ORI:
2
6204c81e2933 Revert changes to handling of immediate versions of bitwise instructions. Replace asri with cmpi.
Michael Pavone <pavone@retrodev.com>
parents: 0
diff changeset
350 context->regs[dst] = context->regs[dst] | format_immediate(a);
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
351 update_flags_bitwise(context, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
352 break;
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
353 case XORI:
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
354 context->regs[dst] = context->regs[dst] ^ format_immediate(a);
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
355 update_flags_bitwise(context, context->regs[dst]);
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
356 break;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
357 case LSI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
358 shift = a & 7;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
359 if (!shift) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
360 shift = 8;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
361 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
362 if (a & 8) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
363 tmp = context->regs[dst] >> shift;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
364 tmp |= (context->regs[dst] >> (shift - 1)) << 16 & 0x10000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
365 } else {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
366 tmp = context->regs[dst] << (a & 7);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
367 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
368 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
369 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
370 break;
2
6204c81e2933 Revert changes to handling of immediate versions of bitwise instructions. Replace asri with cmpi.
Michael Pavone <pavone@retrodev.com>
parents: 0
diff changeset
371 case CMPI:
6204c81e2933 Revert changes to handling of immediate versions of bitwise instructions. Replace asri with cmpi.
Michael Pavone <pavone@retrodev.com>
parents: 0
diff changeset
372 tmp = a;
6204c81e2933 Revert changes to handling of immediate versions of bitwise instructions. Replace asri with cmpi.
Michael Pavone <pavone@retrodev.com>
parents: 0
diff changeset
373 if (a & 8) {
6204c81e2933 Revert changes to handling of immediate versions of bitwise instructions. Replace asri with cmpi.
Michael Pavone <pavone@retrodev.com>
parents: 0
diff changeset
374 a |= 0xFFF0;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
375 }
2
6204c81e2933 Revert changes to handling of immediate versions of bitwise instructions. Replace asri with cmpi.
Michael Pavone <pavone@retrodev.com>
parents: 0
diff changeset
376 tmp = context->regs[dst] - a;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
377 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
378 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
379 case SINGLE_REG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
380 run_single_reg(context, dst, a);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
381 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
382 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
383 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
384 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
385 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
386 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
387
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
388 uint32_t get_data_address(cpu *context, uint8_t a, uint8_t b)
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
389 {
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
390 uint32_t address = context->regs[a] + context->regs[b];
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
391 if (a == REG_PC || b == REG_PC) {
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
392 address |= context->pc_msb;
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
393 } else if (address & 0x8000) {
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
394 address = (address & 0x7FFF) | context->data_high_msb;
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
395 } else {
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
396 address |= context->data_low_msb;
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
397 }
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
398 return address;
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
399 }
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
400
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
401 void run_instruction(cpu *context)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
402 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
403 uint16_t instruction = context->prefetch;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
404 fetch_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
405 uint8_t dst = instruction >> 12;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
406 uint8_t a = instruction >> 8 & 0xF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
407 uint8_t b = instruction >> 4 & 0xF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
408 uint8_t op = instruction & 0xF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
409 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
410 switch (op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
411 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
412 case LDIM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
413 context->regs[dst] = sign_extend(a << 4 | b);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
414 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
415 case LDIMH:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
416 context->regs[dst] &= 0xFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
417 context->regs[dst] |= a << 12 | b << 8;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
418 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
419 case LD8:
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
420 context->regs[dst] = cpu_read_8(context, get_data_address(context, a, b));
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
421 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
422 case LD16:
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
423 context->regs[dst] = cpu_read_16(context, get_data_address(context, a, b));
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
424 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
425 case STR8:
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
426 cpu_write_8(context, get_data_address(context, a, b), context->regs[dst]);
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
427 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
428 case STR16:
43
6e7bfe83d2b0 Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
Michael Pavone <pavone@retrodev.com>
parents: 36
diff changeset
429 cpu_write_16(context,get_data_address(context, a, b), context->regs[dst]);
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
430 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
431 case ADD:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
432 tmp = context->regs[a] + context->regs[b];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
433 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
434 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
435 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
436 case ADC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
437 tmp = context->regs[a] + context->regs[b] + (context->regs[REG_SR] & FLAG_C ? 1 : 0);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
438 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
439 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
440 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
441 case AND:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
442 context->regs[dst] = context->regs[a] & context->regs[b];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
443 update_flags_bitwise(context, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
444 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
445 case OR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
446 context->regs[dst] = context->regs[a] | context->regs[b];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
447 update_flags_bitwise(context, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
448 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
449 case XOR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
450 context->regs[dst] = context->regs[a] ^ context->regs[b];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
451 update_flags_bitwise(context, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
452 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
453 case LSL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
454 tmp = context->regs[a] << context->regs[b];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
455 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
456 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
457 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
458 case LSR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
459 tmp = context->regs[a] >> context->regs[b];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
460 tmp |= (context->regs[a] >> (context->regs[b] - 1)) << 16 & 0x10000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
461 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
462 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
463 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
464 case ASR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
465 tmp = context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
466 if (tmp & 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
467 tmp |= 0xFFFF0000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
468 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
469 tmp = tmp >> context->regs[b] & 0xFFFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
470 tmp |= (context->regs[a] >> (context->regs[b] - 1)) << 16 & 0x10000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
471 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
472 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
473 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
474 case BCC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
475 run_bcc(context, dst, a, b);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
476 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
477 case SINGLE_SOURCE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
478 run_single_source(context, dst, a, b);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
479 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
480 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
481 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
482 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
483 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
484 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
485
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
486 void run_cpu(cpu *context, uint32_t target_cycle)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
487 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
488 while (context->cycles < target_cycle)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
489 {
25
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
490 context->current_target = target_cycle;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
491 context->pending_interrupts = get_current_interrupts(context);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
492 uint32_t int_cycle = next_interrupt_cycle(context, (~context->pending_interrupts) & 0x3);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
493 if (int_cycle < context->current_target) {
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
494 context->current_target = int_cycle;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
495 }
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
496 while (context->cycles < context->current_target)
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
497 {
25
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
498 switch (context->state)
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
499 {
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
500 case STATE_NEED_FETCH:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
501 fetch_instruction(context);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
502 break;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
503 case STATE_NORMAL:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
504 if (context->regs[REG_SR] & context->pending_interrupts) {
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
505 context->state = STATE_EXCEPTION_START;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
506 context->exception = context->pending_interrupts & 1 ? EXCEPTION_INTERRUPT_0 : EXCEPTION_INTERRUPT_1;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
507 context->pending_interrupts &= ~(1 << context->exception);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
508 ack_interrupt(context, context->exception);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
509 } else {
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
510 run_instruction(context);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
511 }
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
512 break;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
513 case STATE_EXCEPTION_START:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
514 vector_fetch(context);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
515 break;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
516 }
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
517 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
518 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
519 }