annotate src/cpu.c @ 5:18b66690ae13

Removed redundant definitino of some exception register instructinos in spec
author Michael Pavone <pavone@retrodev.com>
date Sat, 26 Mar 2016 23:30:50 -0700
parents 6204c81e2933
children 74a6d629b78f
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
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
219 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
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 if (!val) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
225 val = 8;
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 return 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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
230 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
231 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
232 switch(op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
233 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
234 case RETI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
235 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
236 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
237 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
238 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
239 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
240 case TRAP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
241 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
242 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
243 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
244 case TRAPI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
245 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
246 context->exception = dst;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
247 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
248 case GETEPC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
249 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
250 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
251 case SETEPC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
252 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
253 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
254 case GETESR:
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_sr;
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 SETESR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
258 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
259 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
260 case GETEUR:
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_ur;
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 SETEUR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
264 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
265 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
266 case GETENUM:
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;
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 SETENUM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
270 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
271 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
272 default:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
273 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
274 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
275 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
276 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
277 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
278 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
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
282 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
283 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
284 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
285 uint8_t shift;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
286 switch(op)
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 case MOVE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
289 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
290 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
291 case NEG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
292 tmp = -context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
293 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
294 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
295 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
296 case NOT:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
297 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
298 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
299 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
300 case CMP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
301 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
302 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
303 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
304 case CALL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
305 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
306 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
307 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
308 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
309 case SWAP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
310 tmp = context->regs[dst];
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[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
312 context->regs[a] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
313 if (a == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
314 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
315 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
316 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
317 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
318 case IN:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
319 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
320 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
321 case OUT:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
322 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
323 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
324 case INI:
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, 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 OUTI:
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, 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 ADDI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
331 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
332 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
333 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
334 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
335 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
336 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
337 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
338 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
339 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
340 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
341 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
342 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
343 case LSI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
344 shift = a & 7;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
345 if (!shift) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
346 shift = 8;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
347 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
348 if (a & 8) {
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;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
350 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
351 } else {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
352 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
353 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
354 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
355 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
356 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
357 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
358 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
359 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
360 a |= 0xFFF0;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
361 }
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
362 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
363 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
364 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
365 case SINGLE_REG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
366 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
367 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
368 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
369 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
370 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
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
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
374 char * mnemonics[] = {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
375 "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
376 };
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
377
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
378 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
379 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
380 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
381 fetch_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
382 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
383 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
384 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
385 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
386 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
387 switch (op)
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 case LDIM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
390 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
391 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
392 case LDIMH:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
393 context->regs[dst] &= 0xFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
394 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
395 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
396 case LD8:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
397 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
398 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
399 case LD16:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
400 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
401 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
402 case STR8:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
403 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
404 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
405 case STR16:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
406 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
407 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
408 case ADD:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
409 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
410 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
411 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
412 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
413 case ADC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
414 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
415 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
416 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
417 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
418 case AND:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
419 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
420 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
421 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
422 case OR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
423 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
424 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
425 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
426 case XOR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
427 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
428 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
429 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
430 case LSL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
431 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
432 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
433 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
434 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
435 case LSR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
436 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
437 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
438 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
439 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
440 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
441 case ASR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
442 tmp = context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
443 if (tmp & 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
444 tmp |= 0xFFFF0000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
445 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
446 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
447 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
448 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
449 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
450 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
451 case BCC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
452 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
453 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
454 case SINGLE_SOURCE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
455 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
456 return;
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 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
459 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
460 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
461 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
462
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
463 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
464 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
465 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
466 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
467 switch (context->state)
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 case STATE_NEED_FETCH:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
470 fetch_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
471 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
472 case STATE_NORMAL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
473 run_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
474 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
475 case STATE_EXCEPTION_START:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
476 vector_fetch(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
477 break;
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 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
480 }