annotate src/cpu.c @ 20:a9364f5ee81a

Fix timing of port IO
author Michael Pavone <pavone@retrodev.com>
date Tue, 29 Mar 2016 19:57:34 -0700
parents d8ae30286d17
children fb14515266f4
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
38 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
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
56 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
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
69 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
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
88 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
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 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
122 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
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;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
130 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
131 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
132 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
133 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
134 }
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 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
137 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
138 if (val & 0x80) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
139 return val | 0xFF00;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
140 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
141 return val;
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
144 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
145 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
146 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
147 if (!(result & 0xFFFF)) {
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_Z;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
149 }
13
d8ae30286d17 Fix flag calculation and condition code tests
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
150 if (result & 0x8000) {
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
151 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
152 }
13
d8ae30286d17 Fix flag calculation and condition code tests
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
153 if (result & 0x10000) {
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
154 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
155 }
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 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
159 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
160 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
161 if (!(result & 0xFFFF)) {
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_Z;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
163 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
164 if (result &= 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
165 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
166 }
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 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
170 {
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 uint8_t doit = 0;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
173 switch (condition)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
174 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
175 case COND_ALWAYS:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
176 doit = 1;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
177 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
178 case COND_NEVER:
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_ZERO:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
181 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
182 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
183 case COND_NZERO:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
184 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
185 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
186 case COND_NEG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
187 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
188 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
189 case COND_POS:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
190 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
191 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
192 case COND_CARRY:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
193 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
194 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
195 case COND_NCARRY:
13
d8ae30286d17 Fix flag calculation and condition code tests
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
196 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
197 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
198 case COND_GREATER:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
199 //not zero and not carry
13
d8ae30286d17 Fix flag calculation and condition code tests
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
200 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
201 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
202 case COND_LEQ:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
203 //zero or carry
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
204 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
205 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
206 default:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
207 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
208 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
209 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
210 }
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 if (doit) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
213 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
214 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
215 }
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
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
218 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
219 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
220 if (val & 8) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
221 val |= 0xFFF0;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
222 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
223 if (!val) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
224 val = 8;
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 return val;
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
229 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
230 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
231 switch(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 case RETI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
234 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
235 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
236 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
237 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
238 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
239 case TRAP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
240 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
241 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
242 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
243 case TRAPI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
244 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
245 context->exception = dst;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
246 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
247 case GETEPC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
248 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
249 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
250 case SETEPC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
251 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
252 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
253 case GETESR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
254 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
255 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
256 case SETESR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
257 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
258 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
259 case GETEUR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
260 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
261 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
262 case SETEUR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
263 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
264 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
265 case GETENUM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
266 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
267 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
268 case SETENUM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
269 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
270 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
271 default:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
272 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
273 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
274 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
275 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
276 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
277 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
278 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
279 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
280
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
281 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
282 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
283 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
284 uint8_t shift;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
285 switch(op)
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 case MOVE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
288 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
289 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
290 case NEG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
291 tmp = -context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
292 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
293 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
294 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
295 case NOT:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
296 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
297 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
298 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
299 case CMP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
300 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
301 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
302 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
303 case CALL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
304 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
305 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
306 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
307 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
308 case SWAP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
309 tmp = context->regs[dst];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
310 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
311 context->regs[a] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
312 if (a == REG_PC) {
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 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
316 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
317 case IN:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
318 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
319 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
320 case OUT:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
321 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
322 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
323 case INI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
324 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
325 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
326 case OUTI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
327 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
328 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
329 case ADDI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
330 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
331 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
332 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
333 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
334 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
335 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
336 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
337 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
338 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
339 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
340 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
341 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
342 case LSI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
343 shift = a & 7;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
344 if (!shift) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
345 shift = 8;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
346 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
347 if (a & 8) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
348 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
349 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
350 } else {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
351 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
352 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
353 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
354 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
355 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
356 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
357 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
358 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
359 a |= 0xFFF0;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
360 }
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
361 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
362 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
363 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
364 case SINGLE_REG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
365 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
366 return;
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 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
369 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
370 }
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
373 char * mnemonics[] = {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
374 "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
375 };
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
376
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents: 2
diff changeset
377 char * mnemonics_single_src[] = {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents: 2
diff changeset
378 "mov", "neg", "not", "cmp", "call", "swap", "in", "out", "ini", "outi", "addi", "andi", "ori", "lsi", "cmpi", "single reg"
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents: 2
diff changeset
379 };
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents: 2
diff changeset
380
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents: 2
diff changeset
381 char * mnemonics_single_reg[] = {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents: 2
diff changeset
382 "reti", "trap", "trapi", "getepc", "setepc", "getesr", "setesr", "getenum", "setenum", "setuer", "getuer"
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents: 2
diff changeset
383 };
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents: 2
diff changeset
384
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
385 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
386 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
387 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
388 fetch_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
389 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
390 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
391 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
392 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
393 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
394 switch (op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
395 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
396 case LDIM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
397 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
398 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
399 case LDIMH:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
400 context->regs[dst] &= 0xFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
401 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
402 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
403 case LD8:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
404 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
405 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
406 case LD16:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
407 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
408 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
409 case STR8:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
410 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
411 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
412 case STR16:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
413 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
414 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
415 case ADD:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
416 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
417 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
418 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
419 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
420 case ADC:
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] + (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
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 AND:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
426 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
427 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
428 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
429 case OR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
430 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
431 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
432 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
433 case XOR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
434 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
435 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
436 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
437 case LSL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
438 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
439 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
440 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
441 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
442 case LSR:
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 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
445 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
446 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
447 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
448 case ASR:
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];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
450 if (tmp & 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
451 tmp |= 0xFFFF0000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
452 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
453 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
454 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
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 BCC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
459 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
460 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
461 case SINGLE_SOURCE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
462 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
463 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
464 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
465 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
466 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
467 }
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
470 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
471 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
472 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
473 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
474 switch (context->state)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
475 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
476 case STATE_NEED_FETCH:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
477 fetch_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
478 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
479 case STATE_NORMAL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
480 run_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
481 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
482 case STATE_EXCEPTION_START:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
483 vector_fetch(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
484 break;
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 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
487 }