annotate src/cpu.c @ 0:7e44f7d5810b

Initial commit. CPU working well enough for simple hello world program.
author Michael Pavone <pavone@retrodev.com>
date Tue, 22 Mar 2016 22:44:02 -0700
parents
children 6204c81e2933
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 #define REG_PC 14
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
27 #define REG_SR 15
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
28
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
29 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
30 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
31 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
32 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
33 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
34 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
35 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
36 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
37
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
38 return context;
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
41 uint16_t cpu_read_16(cpu *context, uint16_t address)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
42 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
43 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
44 if (address & 1) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
45 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
46 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
47 return 0xFFFF;
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 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
50 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
51 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
52 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
53 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
54 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
55 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
56 return 0xFFFF;
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
59 uint8_t cpu_read_8(cpu *context, uint16_t address)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
60 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
61 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
62 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
63 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
64 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
65 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
66 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
67 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
68 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
69 return 0xFF;
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
72 void cpu_write_16(cpu *context, uint16_t address, uint16_t value)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
73 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
74 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
75 if (address & 1) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
76 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
77 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
78 return;
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 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
81 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
82 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
83 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
84 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
85 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
86 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
87 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
88 }
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
91 void cpu_write_8(cpu *context, uint16_t address, uint8_t value)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
92 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
93 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
94 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
95 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
96 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
97 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
98 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
99 break;
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 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
102 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
103
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
104 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
105 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
106 port &= 0xF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
107 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
108 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
109 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
110 return 0xFFFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
111 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
112
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
113 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
114 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
115 port &= 0xF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
116 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
117 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
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
121 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
122 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
123 context->prefetch = cpu_read_16(context, context->regs[REG_PC]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
124 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
125 context->state = STATE_NORMAL;
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
128 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
129 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
130 context->exception_pc = 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
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);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
133 context->regs[REG_PC] = cpu_read_16(context, context->vector_base + context->exception);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
134 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
135 }
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 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
138 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
139 if (val & 0x80) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
140 return val | 0xFF00;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
141 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
142 return val;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
143 }
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 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
146 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
147 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
148 if (!(result & 0xFFFF)) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
149 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
150 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
151 if (result &= 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
152 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
153 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
154 if (result &= 0x10000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
155 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
156 }
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 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
160 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
161 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
162 if (!(result & 0xFFFF)) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
163 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
164 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
165 if (result &= 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
166 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
167 }
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 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
171 {
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 uint8_t doit = 0;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
174 switch (condition)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
175 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
176 case COND_ALWAYS:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
177 doit = 1;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
178 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
179 case COND_NEVER:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
180 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
181 case COND_ZERO:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
182 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
183 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
184 case COND_NZERO:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
185 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
186 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
187 case COND_NEG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
188 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
189 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
190 case COND_POS:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
191 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
192 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
193 case COND_CARRY:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
194 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
195 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
196 case COND_NCARRY:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
197 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
198 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
199 case COND_GREATER:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
200 //not zero and not carry
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
201 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
202 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
203 case COND_LEQ:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
204 //zero or carry
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
205 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
206 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
207 default:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
208 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
209 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
210 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
211 }
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 if (doit) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
214 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
215 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
216 }
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 uint16_t format_immediate_bitwise(uint16_t val)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
220 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
221 if (val & 8) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
222 val |= 0xFFF0;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
223 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
224 return val;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
225 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
226
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
227 uint16_t format_immediate(uint16_t val)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
228 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
229 val = format_immediate_bitwise(val);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
230 if (!val) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
231 val = 8;
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 return val;
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
236 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
237 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
238 switch(op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
239 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
240 case RETI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
241 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
242 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
243 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
244 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
245 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
246 case TRAP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
247 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
248 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
249 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
250 case TRAPI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
251 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
252 context->exception = dst;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
253 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
254 case GETEPC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
255 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
256 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
257 case SETEPC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
258 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
259 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
260 case GETESR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
261 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
262 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
263 case SETESR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
264 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
265 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
266 case GETEUR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
267 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
268 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
269 case SETEUR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
270 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
271 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
272 case GETENUM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
273 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
274 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
275 case SETENUM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
276 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
277 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
278 default:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
279 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
280 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
281 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
282 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
283 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
284 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
285 }
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
288 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
289 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
290 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
291 uint8_t shift;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
292 switch(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 case MOVE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
295 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
296 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
297 case NEG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
298 tmp = -context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
299 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
300 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
301 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
302 case NOT:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
303 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
304 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
305 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
306 case CMP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
307 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
308 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
309 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
310 case CALL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
311 context->regs[dst] = 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
312 context->regs[REG_PC] = context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
313 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
314 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
315 case SWAP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
316 tmp = context->regs[dst];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
317 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
318 context->regs[a] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
319 if (a == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
320 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
321 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
322 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
323 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
324 case IN:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
325 context->regs[dst] = cpu_read_port(context, context->regs[a]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
326 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
327 case OUT:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
328 cpu_write_port(context, context->regs[a], context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
329 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
330 case INI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
331 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
332 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
333 case OUTI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
334 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
335 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
336 case ADDI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
337 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
338 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
339 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
340 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
341 case ANDI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
342 context->regs[dst] = context->regs[dst] & format_immediate_bitwise(a);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
343 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
344 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
345 case ORI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
346 context->regs[dst] = context->regs[dst] | format_immediate_bitwise(a);
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 LSI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
350 shift = a & 7;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
351 if (!shift) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
352 shift = 8;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
353 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
354 if (a & 8) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
355 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
356 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
357 } else {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
358 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
359 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
360 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
361 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
362 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
363 case ASRI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
364 shift = a;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
365 if (!shift) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
366 shift = 16;
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 tmp = context->regs[dst];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
369 if (tmp & 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
370 tmp |= 0xFFFF0000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
371 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
372 tmp = tmp >> shift & 0xFFFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
373 tmp |= (context->regs[dst] >> (context->regs[shift] - 1)) << 16 & 0x10000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
374 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
375 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
376 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
377 case SINGLE_REG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
378 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
379 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
380 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
381 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
382 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
383 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
384 }
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 char * mnemonics[] = {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
387 "ldim", "ldimh", "ld8", "ld16", "str8", "str16", "add", "adc", "and", "or", "xor", "lsl", "lsr", "asr", "bcc", "single"
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
388 };
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
389
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
390 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
391 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
392 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
393 fetch_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
394 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
395 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
396 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
397 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
398 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
399 switch (op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
400 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
401 case LDIM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
402 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
403 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
404 case LDIMH:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
405 context->regs[dst] &= 0xFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
406 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
407 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
408 case LD8:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
409 context->regs[dst] = cpu_read_8(context, 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
410 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
411 case LD16:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
412 context->regs[dst] = cpu_read_16(context, 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
413 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
414 case STR8:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
415 cpu_write_8(context, context->regs[a] + context->regs[b], context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
416 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
417 case STR16:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
418 cpu_write_16(context, context->regs[a] + context->regs[b], context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
419 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
420 case ADD:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
421 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
422 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
423 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
424 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
425 case ADC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
426 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
427 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
428 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
429 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
430 case AND:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
431 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
432 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
433 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
434 case OR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
435 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
436 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
437 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
438 case XOR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
439 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
440 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
441 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
442 case LSL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
443 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
444 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
445 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
446 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
447 case LSR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
448 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
449 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
450 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
451 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
452 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
453 case ASR:
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];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
455 if (tmp & 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
456 tmp |= 0xFFFF0000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
457 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
458 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
459 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
460 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
461 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
462 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
463 case BCC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
464 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
465 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
466 case SINGLE_SOURCE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
467 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
468 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
469 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
470 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
471 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
472 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
473 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
474
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
475 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
476 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
477 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
478 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
479 switch (context->state)
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 case STATE_NEED_FETCH:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
482 fetch_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
483 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
484 case STATE_NORMAL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
485 run_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
486 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
487 case STATE_EXCEPTION_START:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
488 vector_fetch(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
489 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
490 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
491 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
492 }