annotate src/cpu.c @ 36:5683d9ba9acc

Fix call instruction for the case in which A reg == DST reg
author Michael Pavone <pavone@retrodev.com>
date Sun, 03 Apr 2016 21:27:03 -0700
parents 083347ccd508
children 6e7bfe83d2b0
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);
26
083347ccd508 Implemented vblank interrupts and fixed a bug in exception vector address calculation
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
132 context->regs[REG_PC] = cpu_read_16(context, context->vector_base + context->exception * 2);
0
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;
25
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
271 case GETVBR:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
272 context->regs[dst] = context->vector_base;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
273 break;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
274 case SETVBR:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
275 context->vector_base = context->regs[dst];
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
276 break;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
277 default:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
278 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
279 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
280 return;
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 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
283 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
284 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
285 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
286
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
287 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
288 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
289 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
290 uint8_t shift;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
291 switch(op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
292 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
293 case MOVE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
294 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
295 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
296 case NEG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
297 tmp = -context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
298 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
299 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
300 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
301 case NOT:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
302 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
303 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
304 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
305 case CMP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
306 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
307 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
308 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
309 case CALL:
36
5683d9ba9acc Fix call instruction for the case in which A reg == DST reg
Michael Pavone <pavone@retrodev.com>
parents: 26
diff changeset
310 tmp = context->regs[REG_PC] - 2;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
311 context->regs[REG_PC] = context->regs[a];
36
5683d9ba9acc Fix call instruction for the case in which A reg == DST reg
Michael Pavone <pavone@retrodev.com>
parents: 26
diff changeset
312 context->regs[dst] = tmp;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
313 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
314 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
315 case SWAP:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
316 tmp = context->regs[dst];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
317 context->regs[dst] = context->regs[a];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
318 context->regs[a] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
319 if (a == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
320 context->state = STATE_NEED_FETCH;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
321 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
322 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
323 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
324 case IN:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
325 context->regs[dst] = cpu_read_port(context, context->regs[a]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
326 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
327 case OUT:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
328 cpu_write_port(context, context->regs[a], context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
329 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
330 case INI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
331 context->regs[dst] = cpu_read_port(context, a);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
332 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
333 case OUTI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
334 cpu_write_port(context, a, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
335 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
336 case ADDI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
337 tmp = context->regs[dst] + format_immediate(a);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
338 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
339 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
340 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
341 case ANDI:
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
342 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
343 update_flags_bitwise(context, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
344 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
345 case ORI:
2
6204c81e2933 Revert changes to handling of immediate versions of bitwise instructions. Replace asri with cmpi.
Michael Pavone <pavone@retrodev.com>
parents: 0
diff changeset
346 context->regs[dst] = context->regs[dst] | format_immediate(a);
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
347 update_flags_bitwise(context, context->regs[dst]);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
348 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
349 case LSI:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
350 shift = a & 7;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
351 if (!shift) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
352 shift = 8;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
353 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
354 if (a & 8) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
355 tmp = context->regs[dst] >> shift;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
356 tmp |= (context->regs[dst] >> (shift - 1)) << 16 & 0x10000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
357 } else {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
358 tmp = context->regs[dst] << (a & 7);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
359 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
360 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
361 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
362 break;
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
363 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
364 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
365 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
366 a |= 0xFFF0;
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
367 }
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
368 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
369 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
370 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
371 case SINGLE_REG:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
372 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
373 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
374 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
375 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
376 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
377 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
378 }
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 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
381 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
382 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
383 fetch_instruction(context);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
384 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
385 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
386 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
387 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
388 uint32_t tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
389 switch (op)
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
390 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
391 case LDIM:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
392 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
393 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
394 case LDIMH:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
395 context->regs[dst] &= 0xFF;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
396 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
397 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
398 case LD8:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
399 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
400 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
401 case LD16:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
402 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
403 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
404 case STR8:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
405 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
406 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
407 case STR16:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
408 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
409 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
410 case ADD:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
411 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
412 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
413 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
414 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
415 case ADC:
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] + (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
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 AND:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
421 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
422 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
423 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
424 case OR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
425 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
426 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
427 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
428 case XOR:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
429 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
430 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
431 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
432 case LSL:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
433 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
434 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
435 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
436 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
437 case LSR:
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 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
440 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
441 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
442 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
443 case ASR:
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];
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
445 if (tmp & 0x8000) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
446 tmp |= 0xFFFF0000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
447 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
448 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
449 tmp |= (context->regs[a] >> (context->regs[b] - 1)) << 16 & 0x10000;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
450 context->regs[dst] = tmp;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
451 update_flags_arith(context, tmp);
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
452 break;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
453 case BCC:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
454 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
455 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
456 case SINGLE_SOURCE:
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
457 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
458 return;
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
459 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
460 if (dst == REG_PC) {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
461 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
462 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
463 }
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 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
466 {
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
467 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
468 {
25
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
469 context->current_target = target_cycle;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
470 context->pending_interrupts = get_current_interrupts(context);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
471 uint32_t int_cycle = next_interrupt_cycle(context, (~context->pending_interrupts) & 0x3);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
472 if (int_cycle < context->current_target) {
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
473 context->current_target = int_cycle;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
474 }
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
475 while (context->cycles < context->current_target)
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
476 {
25
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
477 switch (context->state)
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
478 {
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
479 case STATE_NEED_FETCH:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
480 fetch_instruction(context);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
481 break;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
482 case STATE_NORMAL:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
483 if (context->regs[REG_SR] & context->pending_interrupts) {
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
484 context->state = STATE_EXCEPTION_START;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
485 context->exception = context->pending_interrupts & 1 ? EXCEPTION_INTERRUPT_0 : EXCEPTION_INTERRUPT_1;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
486 context->pending_interrupts &= ~(1 << context->exception);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
487 ack_interrupt(context, context->exception);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
488 } else {
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
489 run_instruction(context);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
490 }
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
491 break;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
492 case STATE_EXCEPTION_START:
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
493 vector_fetch(context);
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
494 break;
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 20
diff changeset
495 }
0
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
496 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
497 }
7e44f7d5810b Initial commit. CPU working well enough for simple hello world program.
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
498 }