File: kern.t0

package info (click to toggle)
bearssl 0.6%2Bdfsg.1-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 4,484 kB
  • sloc: ansic: 49,044; cs: 3,473; sh: 524; makefile: 40
file content (309 lines) | stat: -rw-r--r-- 7,654 bytes parent folder | download | duplicates (3)
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
: \ `\n parse drop ; immediate

\ This file defines the core non-native functions (mainly used for
\ parsing words, i.e. not part of the generated output). The line above
\ defines the syntax for comments.

\ Define parenthesis comments.
\ : ( `) parse drop ; immediate

: else postpone ahead 1 cs-roll postpone then ; immediate
: while postpone if 1 cs-roll ; immediate
: repeat postpone again postpone then ; immediate

: ['] ' ; immediate
: [compile] compile ; immediate

: 2drop drop drop ;
: dup2 over over ;

\ Local variables are defined with the native word '(local)'. We define
\ a helper construction that mimics what is found in Apple's Open Firmware
\ implementation. The syntax is: { a b ... ; c d ... }
\ I.e. there is an opening brace, then some names. Names appearing before
\ the semicolon are locals that are both defined and then filled with the
\ values on stack (in stack order: { a b } fills 'b' with the top-of-stack,
\ and 'a' with the value immediately below). Names appearing after the
\ semicolon are not initialized.
: __deflocal ( from_stack name -- )
	dup (local) swap if
		compile-local-write
	else
		drop
	then ;
: __deflocals ( from_stack -- )
	next-word
	dup "}" eqstr if
		2drop ret
	then
	dup ";" eqstr if
		2drop 0 __deflocals ret
	then
	over __deflocals
	__deflocal ;
: {
	-1 __deflocals ; immediate

\ Data building words.
: data:
	new-data-block next-word define-data-word ;
: hexb|
	0 0 { acc z }
	begin
		char
		dup `| = if
			z if "Truncated hexadecimal byte" puts cr exitvm then
			ret
		then
		dup 0x20 > if
			hexval
			z if acc 4 << + data-add8 else >acc then
			z not >z
		then
	again ;

\ Convert hexadecimal character to number. Complain loudly if conversion
\ is not possible.
: hexval ( char -- x )
	hexval-nf dup 0 < if "Not an hex digit: " puts . cr exitvm then ;

\ Convert hexadecimal character to number. If not an hexadecimal digit,
\ return -1.
: hexval-nf ( char -- x )
	dup dup `0 >= swap `9 <= and if `0 - ret then
	dup dup `A >= swap `F <= and if `A - 10 + ret then
	dup dup `a >= swap `f <= and if `a - 10 + ret then
	drop -1 ;

\ Convert decimal character to number. Complain loudly if conversion
\ is not possible.
: decval ( char -- x )
	decval-nf dup 0 < if "Not a decimal digit: " puts . cr exitvm then ;

\ Convert decimal character to number. If not a decimal digit,
\ return -1.
: decval-nf ( char -- x )
	dup dup `0 >= swap `9 <= and if `0 - ret then
	drop -1 ;

\ Commonly used shorthands.
: 1+ 1 + ;
: 2+ 2 + ;
: 1- 1 - ;
: 2- 2 - ;
: 0= 0 = ;
: 0<> 0 <> ;
: 0< 0 < ;
: 0> 0 > ;

\ Get a 16-bit value from the constant data block. This uses big-endian
\ encoding.
: data-get16 ( addr -- x )
	dup data-get8 8 << swap 1+ data-get8 + ;

\ The case..endcase construction is the equivalent of 'switch' is C.
\ Usage:
\     case
\         E1 of C1 endof
\         E2 of C2 endof
\         ...
\         CN
\     endcase
\
\ Upon entry, it considers the TOS (let's call it X). It will then evaluate
\ E1, which should yield a single value Y1; at that point, the X value is
\ still on the stack, just below Y1, and must remain untouched. The 'of'
\ word compares X with Y1; if they are equal, C1 is executed, and then
\ control jumps to after the 'endcase'. The X value is popped from the
\ stack immediately before evaluating C1.
\
\ If X and Y1 are not equal, flow proceeds to E2, to obtain a value Y2 to
\ compare with X. And so on.
\
\ If none of the 'of' clauses found a match, then CN is evaluated. When CN
\ is evaluated, the X value is on the TOS, and CN must either leave it on
\ the stack, or replace it with exactly one value; the 'endcase' word
\ expects (and drops) one value.
\
\ Implementation: this is mostly copied from ANS Forth specification,
\ although simplified a bit because we know that our control-flow stack
\ is independent of the data stack. During compilation, the number of
\ clauses is maintained on the stack; each of..endof clause really is
\ an 'if..else' that must be terminated with a matching 'then' in 'endcase'.

: case 0 ; immediate
: of 1+ postpone over postpone = postpone if postpone drop ; immediate
: endof postpone else ; immediate
: endcase
	postpone drop
	begin dup while 1- postpone then repeat drop ; immediate

\ A simpler and more generic "case": there is no management for a value
\ on the stack, and each test is supposed to come up with its own boolean
\ value.
: choice 0 ; immediate
: uf 1+ postpone if ; immediate
: ufnot 1+ postpone ifnot ; immediate
: enduf postpone else ; immediate
: endchoice begin dup while 1- postpone then repeat drop ; immediate

\ C implementations for native words that can be used in generated code.
add-cc: co { T0_CO(); }
add-cc: execute { T0_ENTER(ip, rp, T0_POP()); }
add-cc: drop { (void)T0_POP(); }
add-cc: dup { T0_PUSH(T0_PEEK(0)); }
add-cc: swap { T0_SWAP(); }
add-cc: over { T0_PUSH(T0_PEEK(1)); }
add-cc: rot { T0_ROT(); }
add-cc: -rot { T0_NROT(); }
add-cc: roll { T0_ROLL(T0_POP()); }
add-cc: pick { T0_PICK(T0_POP()); }
add-cc: + {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(a + b);
}
add-cc: - {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(a - b);
}
add-cc: neg {
	uint32_t a = T0_POP();
	T0_PUSH(-a);
}
add-cc: * {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(a * b);
}
add-cc: / {
	int32_t b = T0_POPi();
	int32_t a = T0_POPi();
	T0_PUSHi(a / b);
}
add-cc: u/ {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(a / b);
}
add-cc: % {
	int32_t b = T0_POPi();
	int32_t a = T0_POPi();
	T0_PUSHi(a % b);
}
add-cc: u% {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(a % b);
}
add-cc: < {
	int32_t b = T0_POPi();
	int32_t a = T0_POPi();
	T0_PUSH(-(uint32_t)(a < b));
}
add-cc: <= {
	int32_t b = T0_POPi();
	int32_t a = T0_POPi();
	T0_PUSH(-(uint32_t)(a <= b));
}
add-cc: > {
	int32_t b = T0_POPi();
	int32_t a = T0_POPi();
	T0_PUSH(-(uint32_t)(a > b));
}
add-cc: >= {
	int32_t b = T0_POPi();
	int32_t a = T0_POPi();
	T0_PUSH(-(uint32_t)(a >= b));
}
add-cc: = {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(-(uint32_t)(a == b));
}
add-cc: <> {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(-(uint32_t)(a != b));
}
add-cc: u< {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(-(uint32_t)(a < b));
}
add-cc: u<= {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(-(uint32_t)(a <= b));
}
add-cc: u> {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(-(uint32_t)(a > b));
}
add-cc: u>= {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(-(uint32_t)(a >= b));
}
add-cc: and {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(a & b);
}
add-cc: or {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(a | b);
}
add-cc: xor {
	uint32_t b = T0_POP();
	uint32_t a = T0_POP();
	T0_PUSH(a ^ b);
}
add-cc: not {
	uint32_t a = T0_POP();
	T0_PUSH(~a);
}
add-cc: << {
	int c = (int)T0_POPi();
	uint32_t x = T0_POP();
	T0_PUSH(x << c);
}
add-cc: >> {
	int c = (int)T0_POPi();
	int32_t x = T0_POPi();
	T0_PUSHi(x >> c);
}
add-cc: u>> {
	int c = (int)T0_POPi();
	uint32_t x = T0_POP();
	T0_PUSH(x >> c);
}
add-cc: data-get8 {
	size_t addr = T0_POP();
	T0_PUSH(t0_datablock[addr]);
}

add-cc: . {
	extern int printf(const char *fmt, ...);
	printf(" %ld", (long)T0_POPi());
}
add-cc: putc {
	extern int printf(const char *fmt, ...);
	printf("%c", (char)T0_POPi());
}
add-cc: puts {
	extern int printf(const char *fmt, ...);
	printf("%s", &t0_datablock[T0_POPi()]);
}
add-cc: cr {
	extern int printf(const char *fmt, ...);
	printf("\n");
}
add-cc: eqstr {
	const void *b = &t0_datablock[T0_POPi()];
	const void *a = &t0_datablock[T0_POPi()];
	T0_PUSH(-(int32_t)(strcmp(a, b) == 0));
}