-
Notifications
You must be signed in to change notification settings - Fork 1
/
asmdriver.c
225 lines (202 loc) · 5.26 KB
/
asmdriver.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <fcntl.h>
#ifdef _MSC_VER
#include <io.h>
#define open _open
#define close _close
#define read _read
#define write _write
#define STDIN_FILENO _fileno(stdin)
#define STDOUT_FILENO _fileno(stdout)
#else
#include <unistd.h>
#endif
#define F_HIDDEN 0x80
#define F_IMMED 0x40
#define F_LENMASK 0x1F
typedef struct WordHeader {
struct WordHeader* Prev; // Points to previous word (or NULL)
uint8_t LengthAndFlags; // Length possibly OR'ed with F_IMMED AND/OR F_HIDDEN
char Name[1]; // Note length can actually be 0 (for :NONAME)
// ....
// CodeWordFunc CodeWord; <-- CFA
// Cell* Instructions[...]; <-- Points to CFAs of instructions
} WordHeader;
typedef void (*CodeWordFunc)(void);
typedef union Cell {
CodeWordFunc CodeWord;
intptr_t Number;
uint8_t Raw[sizeof(intptr_t)];
union Cell* CellPtr;
} Cell;
extern WordHeader* Latest;
extern uint8_t WordBuffer[];
extern intptr_t Base;
extern intptr_t State;
extern intptr_t StdoutFile;
extern intptr_t InputFile;
extern intptr_t OutputFile;
extern int ForthMain(int argc, char* argv[]);
intptr_t C_Open(const char* Filename, int mode)
{
if (mode != O_RDONLY) {
printf("TODO: open(%s, %d)\n", Filename, mode);
exit(1);
}
// printf("C_Open(%s, %d)\n", Filename, mode);
return open(Filename, mode);
}
void C_Close(intptr_t fd)
{
// printf("C_Close(%d)\n", (int)fd);
close((int)fd);
}
intptr_t C_Read(intptr_t fd, void* buf, unsigned len)
{
//printf("C_Read(%d, %p, %u)\n", (int)fd, buf, len);
return read((int)fd, buf, len);
}
intptr_t C_Write(intptr_t fd, const void* buf, unsigned len)
{
// printf("C_Write(%d, %p, %u)\n", (int)fd, buf, len);
return write((int)fd, buf, len);
}
static const char* InputText;
uint8_t C_ReadKey(void)
{
if (InputText) {
return *InputText ? *InputText++ : 0;
}
uint8_t ch;
if (C_Read(InputFile, &ch, 1) != 1) {
return 0;
}
return ch;
}
void C_ReadWord(void)
{
uint8_t C;
SkipSpaces:
while ((C = C_ReadKey()) != 0 && C <= ' ') {
}
if (C == '\\') {
while ((C = C_ReadKey()) != 0 && C != '\n') {
}
goto SkipSpaces;
}
int WordLen = 0;
while (C > ' ' && WordLen < F_LENMASK) {
if (C >= 'a' && C <= 'z') {
C &= 0xdf;
}
WordBuffer[WordLen++] = C;
C = C_ReadKey();
}
WordBuffer[WordLen] = '\0'; // NUL termination is only for C's sake
WordBuffer[F_LENMASK+1] = (uint8_t)WordLen;
//printf("Read word: \"%s\"\n", WordBuffer);
}
WordHeader* C_FindWord(uint8_t WordLen, const char* Name)
{
for (WordHeader* WH = Latest; WH; WH = WH->Prev) {
if ((WH->LengthAndFlags & (F_LENMASK|F_HIDDEN)) == WordLen && !memcmp(Name, WH->Name, WordLen)) {
//printf("Found word \"%*.*s\" -> %p\n", WordLen, WordLen, Name, (void*)WH);
return WH;
}
}
//printf("Word not found \"%*.*s\"\n", WordLen, WordLen, Name);
return NULL;
}
intptr_t C_ConvertNumber(uint8_t WordLen, const char* Name)
{
if (!WordLen) {
goto Error;
}
uint8_t n = WordLen;
const char* s = Name;
bool neg = false;
if (*s == '-') {
neg = true;
s++;
n--;
if (!n) {
goto Error;
}
}
intptr_t Res = 0;
while (n--) {
uint8_t ch = *s++;
uint8_t dig;
if (ch >= '0' && ch <= '9') {
dig = ch - '0';
} else if (ch >= 'A' && ch <= 'Z') {
dig = ch - 'A' + 10;
} else {
goto Error;
}
if (dig >= Base) {
goto Error;
}
Res = Res*Base + dig;
}
//printf("Converted \"%*.*s\" to %d\n", WordLen, WordLen, Name, (int)(neg ? -Res : Res));
return neg ? -Res : Res;
Error:
printf("Invalid number \"%*.*s\"\n", WordLen, WordLen, Name);
exit(1);
}
void C_Emit(uint8_t ch)
{
//printf("Emitting %c (%02X)\n", ch, ch);
C_Write(STDOUT_FILENO, &ch, 1);
}
void C_PrintWords(void)
{
for (WordHeader* WH = Latest; WH; WH = WH->Prev) {
printf("%p: %-*.*s %02X\n", (void*)WH, F_LENMASK, WH->LengthAndFlags & F_LENMASK, WH->Name, WH->LengthAndFlags & ~F_LENMASK);
}
}
#if 0
extern int QDiv32(int a, int b);
extern int RDiv32(int a, int b);
void testdiv(int a, int b)
{
printf("%+4d / %+4d = %+4d (mod %+4d) ----- CHECK: ", a, b, QDiv32(a, b), RDiv32(a, b));
printf("%+4d / %+4d = %+4d (mod %+4d)\n", a, b, a / b, a % b);
}
void testdivs(void)
{
testdiv(-67, 13);
testdiv(-67, -13);
testdiv(67, 13);
testdiv(67, -13);
}
#endif
void C_Debug(intptr_t val)
{
printf("Debug: %d (%08X)\n", (int)val, (unsigned)val);
}
int main(int argc, char* argv[])
{
// InputText = ": X ' LITSTRING , ; X";
#if 0
OutputFile = StdoutFile = STDOUT_FILENO;
if (argc > 1) {
InputFile = C_Open(argv[1], O_RDONLY);
if (InputFile == -1) {
printf("Error opening %s\n", argv[1]);
return 1;
}
} else {
InputFile = STDIN_FILENO;
}
#endif
int retval = ForthMain(argc, argv);
printf("Interpreter exited with code %d (%08X) State=%d\n", retval, retval, (int)State);
// C_PrintWords();
return 0;
}