-
Notifications
You must be signed in to change notification settings - Fork 0
/
emulator.c
146 lines (129 loc) · 4.27 KB
/
emulator.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
137
138
139
140
141
142
143
144
145
146
/*
* Emulator 'native features' interface.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdarg.h>
#include "proto.h"
extern bool _detect_native_features(void);
extern uint32_t _nfID(const char *);
extern uint32_t _nfCall(uint32_t ID, ...);
/*
* d0 - return code
* d1 - old illegal vector
* a0 - address of illegal vector
* a1 - old sp
*/
__asm__ (
"_detect_native_features: \n"
#if defined(__mc68010) || defined(__mc68020) || defined(__mc68030) || defined(__mc68040)
" movec %vbr, %a0 \n"
" add.l #0x10, %a0 \n"
#else
" move.l #0x10, %a0 \n"
#endif
" moveq #0, %d0 /* assume no NatFeats available */ \n"
" move.l %sp, %a1 \n"
" move.l (%a0), %d1 \n"
" move.l #_fail_nf, (%a0) \n"
" pea _nf_version_name \n"
" sub.l #4, %sp \n"
" .dc.w 0x7300 /* NATFEAT_ID */ \n"
" tst.l %d0 \n"
" jeq _fail_nf /* expect non-zero ID */ \n"
" moveq #1, %d0 /* NatFeats detected */ \n"
" \n"
"_fail_nf: \n"
" move.l %a1, %sp \n"
" move.l %d1, (%a0) \n"
" \n"
" rts \n"
" \n"
"_nf_version_name: \n"
" .ascii \"NF_VERSION\\0\" \n"
" .even \n"
" \n"
"_nfID: \n"
" .dc.w 0x7300 \n"
" rts \n"
"_nfCall: \n"
" .dc.w 0x7301 \n"
" rts \n"
);
static int
nf_id(const char *method)
{
#if defined(WITH_NATIVE_FEATURES)
static bool probed, supported;
if (!probed && _detect_native_features()) {
supported = true;
}
probed = true;
if (supported) {
return _nfID(method);
}
#else
(void)method;
#endif /* WITH_NATIVE_FEATURES */
return -1;
}
static void
nf_puts(const char *str)
{
static int nfid_stderr = 0;
if (nfid_stderr == 0) {
nfid_stderr = nf_id("NF_STDERR");
}
if (nfid_stderr > 0) {
_nfCall(nfid_stderr, str);
}
}
#if 0
static void
nf_trace(bool enable)
{
static int nfid_trace = 0;
if (nfid_trace == 0) {
nfid_trace = nf_id("NF_TRACE");
}
if (nfid_trace > 0) {
_nfCall(nfid_trace, enable);
}
}
#endif
void
trace_puts(const char *str)
{
nf_puts(str);
}
void
trace_putc(const char c)
{
char buf[2] = {c, 0};
nf_puts(buf);
}
void
trace_fmt(const char *format, ...)
{
va_list ap;
va_start(ap, format);
_fmt(trace_putc, format, ap);
va_end(ap);
}
#if defined(WITH_NATIVE_FEATURES)
COMMAND(emulator);
static int
emulator(const char *input_buffer)
{
if (input_buffer == NULL) {
puts("shutdown shutdown / quit if running in an emulator\n");
}
if (!strcmp(input_buffer, "shutdown")) {
int nfid_shutdown = nf_id("NF_SHUTDOWN");
if (nfid_shutdown > 0) {
_nfCall(nfid_shutdown);
}
}
return -1;
}
#endif /* WITH_NATIVE_FEATURES */