-
Notifications
You must be signed in to change notification settings - Fork 23
/
copro-pdp11.c
136 lines (119 loc) · 3.41 KB
/
copro-pdp11.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* PDP11 Co Pro Emulation
*
* (c) 2018 David Banks
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "tube-client.h"
#include "tube-ula.h"
#include "tube.h"
#include "pdp11/pdp11.h"
#include "pdp11/tuberom.h"
#include "copro-pdp11.h"
#ifdef INCLUDE_DEBUGGER
#include "cpu_debug.h"
#include "pdp11/pdp11_debug.h"
#endif
static uint8_t *memory;
void copro_pdp11_write8(const uint16_t addr, const uint8_t data) {
#ifdef INCLUDE_DEBUGGER
if (pdp11_debug_enabled) {
debug_memwrite(&pdp11_cpu_debug, addr, data, 1);
}
#endif
if ((addr & 0xFFF0) == 0xFFF0) {
tube_parasite_write((addr >> 1) & 7, data);
} else {
*(memory + addr) = data;
}
}
uint8_t copro_pdp11_read8(const uint16_t addr) {
uint8_t data;
if ((addr & 0xFFF0) == 0xFFF0) {
data = tube_parasite_read((addr >> 1) & 7);
} else {
data = *(memory + addr);
}
#ifdef INCLUDE_DEBUGGER
if (pdp11_debug_enabled) {
debug_memread(&pdp11_cpu_debug, addr, data, 1);
}
#endif
return data;
}
void copro_pdp11_write16(const uint16_t addr, const uint16_t data) {
#ifdef INCLUDE_DEBUGGER
if (pdp11_debug_enabled) {
debug_memwrite(&pdp11_cpu_debug, addr, data, 2);
}
#endif
if ((addr & 0xFFF0) == 0xFFF0) {
tube_parasite_write((addr >> 1) & 7, ( uint8_t)data & 255);
} else {
*(uint16_t *)(memory + addr) = data;
}
}
uint16_t copro_pdp11_read16(const uint16_t addr) {
uint16_t data;
if ((addr & 0xFFF0) == 0xFFF0) {
data = tube_parasite_read((addr >> 1) & 7);
} else {
data = *(uint16_t *)(memory + addr);
}
#ifdef INCLUDE_DEBUGGER
if (pdp11_debug_enabled) {
debug_memread(&pdp11_cpu_debug, addr, data, 2);
}
#endif
return data;
}
static void copro_pdp11_poweron_reset() {
// Initialize memory pointer to zero (the start of the 2MB of memory shared with the 6502)
memory = copro_mem_reset(0x10000);
}
static void copro_pdp11_reset() {
// Log ARM performance counters
tube_log_performance_counters();
// Copy over client ROM to top of memory
copro_memcpy((void *) (memory + 0x10000 - sizeof(tuberom_pdp11)), (const void *)tuberom_pdp11, sizeof(tuberom_pdp11));
// Reset the processor, start at first ROM location
pdp11_reset(0x10000 - sizeof(tuberom_pdp11));
// Wait for rst become inactive before continuing to execute
tube_wait_for_rst_release();
// Reset ARM performance counters
tube_reset_performance_counters();
}
void copro_pdp11_emulator()
{
// Remember the current copro so we can exit if it changes
unsigned int last_copro = copro;
copro_pdp11_poweron_reset();
copro_pdp11_reset();
while (1) {
pdp11_execute();
int tube_irq_copy = tube_irq & ( RESET_BIT + NMI_BIT + IRQ_BIT) ;
if (tube_irq_copy) {
// Reset the processor on active edge of rst
if (tube_irq_copy & RESET_BIT) {
// Exit if the copro has changed
if (copro != last_copro) {
break;
}
copro_pdp11_reset();
}
// NMI is edge sensitive, so only check after mailbox activity
if (tube_irq_copy & NMI_BIT) {
pdp11_interrupt(0x80, 7);
tube_ack_nmi();
}
// IRQ is level sensitive, so check between every instruction
if (tube_irq_copy & IRQ_BIT) {
if (((m_pdp11->PS >> 5) & 7) < 6) {
pdp11_interrupt(0x84, 6);
}
}
}
}
}