| 2875 |
dpurdie |
1 |
#pragma force_top_level
|
|
|
2 |
#pragma include_only_once
|
|
|
3 |
|
|
|
4 |
/*
|
|
|
5 |
* Interface to host OS.
|
|
|
6 |
* Copyright (C) Acorn Computers Ltd., 1988
|
|
|
7 |
*/
|
|
|
8 |
|
|
|
9 |
#ifndef __kernel_h
|
|
|
10 |
#define __kernel_h
|
|
|
11 |
|
|
|
12 |
#ifndef __size_t
|
|
|
13 |
# define __size_t 1
|
|
|
14 |
typedef unsigned int size_t; /* from <stddef.h> */
|
|
|
15 |
#endif
|
|
|
16 |
|
|
|
17 |
typedef struct {
|
|
|
18 |
int r[10]; /* only r0 - r9 matter for swi's */
|
|
|
19 |
} _kernel_swi_regs;
|
|
|
20 |
|
|
|
21 |
typedef struct {
|
|
|
22 |
int load, exec; /* load, exec addresses */
|
|
|
23 |
int start, end; /* start address/length, end address/attributes */
|
|
|
24 |
} _kernel_osfile_block;
|
|
|
25 |
|
|
|
26 |
typedef struct {
|
|
|
27 |
void * dataptr; /* memory address of data */
|
|
|
28 |
int nbytes, fileptr;
|
|
|
29 |
int buf_len; /* these fields for Arthur gpbp extensions */
|
|
|
30 |
char * wild_fld; /* points to wildcarded filename to match */
|
|
|
31 |
} _kernel_osgbpb_block;
|
|
|
32 |
|
|
|
33 |
typedef struct {
|
|
|
34 |
int errnum; /* error number */
|
|
|
35 |
char errmess[252]; /* error message (zero terminated) */
|
|
|
36 |
} _kernel_oserror;
|
|
|
37 |
|
|
|
38 |
typedef struct stack_chunk {
|
|
|
39 |
unsigned long sc_mark; /* == 0xf60690ff */
|
|
|
40 |
struct stack_chunk *sc_next, *sc_prev;
|
|
|
41 |
unsigned long sc_size;
|
|
|
42 |
int (*sc_deallocate)();
|
|
|
43 |
} _kernel_stack_chunk;
|
|
|
44 |
|
|
|
45 |
extern _kernel_stack_chunk *_kernel_current_stack_chunk(void);
|
|
|
46 |
|
|
|
47 |
extern void _kernel_setreturncode(unsigned code);
|
|
|
48 |
|
|
|
49 |
extern void _kernel_exit(int);
|
|
|
50 |
|
|
|
51 |
extern void _kernel_raise_error(_kernel_oserror *);
|
|
|
52 |
/* return the specified error to the parent */
|
|
|
53 |
|
|
|
54 |
extern void _kernel_exittraphandler(void);
|
|
|
55 |
|
|
|
56 |
#define _kernel_HOST_UNDEFINED -1
|
|
|
57 |
#define _kernel_BBC_MOS1_0 0
|
|
|
58 |
#define _kernel_BBC_MOS1_2 1
|
|
|
59 |
#define _kernel_BBC_ACW 2
|
|
|
60 |
#define _kernel_BBC_MASTER 3
|
|
|
61 |
#define _kernel_BBC_MASTER_ET 4
|
|
|
62 |
#define _kernel_BBC_MASTER_COMPACT 5
|
|
|
63 |
#define _kernel_ARTHUR 6
|
|
|
64 |
#define _kernel_SPRINGBOARD 7
|
|
|
65 |
#define _kernel_A_UNIX 8
|
|
|
66 |
|
|
|
67 |
extern int _kernel_hostos(void);
|
|
|
68 |
/*
|
|
|
69 |
* Returns the identity of the host OS
|
|
|
70 |
*/
|
|
|
71 |
|
|
|
72 |
extern int _kernel_fpavailable(void);
|
|
|
73 |
/*
|
|
|
74 |
* Returns 0 if floating point is not available (no emulator nor hardware)
|
|
|
75 |
*/
|
|
|
76 |
|
|
|
77 |
#define _kernel_NONX 0x80000000
|
|
|
78 |
extern _kernel_oserror *_kernel_swi(int no, _kernel_swi_regs *in,
|
|
|
79 |
_kernel_swi_regs *out);
|
|
|
80 |
/*
|
|
|
81 |
* Generic SWI interface. Returns NULL if there was no error.
|
|
|
82 |
* The SWI called normally has the X bit set. To call a non-X bit set SWI,
|
|
|
83 |
* _kernel_NONX must be orred into no (in which case, if an error occurs,
|
|
|
84 |
* _kernel_oserror does not return).
|
|
|
85 |
*/
|
|
|
86 |
|
|
|
87 |
extern _kernel_oserror *_kernel_swi_c(int no, _kernel_swi_regs *in,
|
|
|
88 |
_kernel_swi_regs *out, int *carry);
|
|
|
89 |
/*
|
|
|
90 |
* As _kernel_swi, but for use with SWIs which return status in the C flag.
|
|
|
91 |
* The int to which carry points is set to reflect the state of the C flag on
|
|
|
92 |
* exit from the SWI.
|
|
|
93 |
*/
|
|
|
94 |
|
|
|
95 |
extern char *_kernel_command_string(void);
|
|
|
96 |
/*
|
|
|
97 |
* Returns the address of (maybe a copy of) the string used to run the program
|
|
|
98 |
*/
|
|
|
99 |
|
|
|
100 |
/*
|
|
|
101 |
* The int value returned by the following functions may have value:
|
|
|
102 |
* >= 0 if the call succeeds (significance then depends on the function)
|
|
|
103 |
* -1 if the call fails but causes no os error (eg escape for rdch). Not
|
|
|
104 |
* all functions are capable of generating this result. This return
|
|
|
105 |
* value corresponds to the C flag being set by the SWI.
|
|
|
106 |
* -2 if the call causes an os error (in which case, _kernel_last_oserror
|
|
|
107 |
* must be used to find which error it was)
|
|
|
108 |
*/
|
|
|
109 |
|
|
|
110 |
#define _kernel_ERROR (-2)
|
|
|
111 |
|
|
|
112 |
extern int _kernel_osbyte(int op, int x, int y);
|
|
|
113 |
/*
|
|
|
114 |
* Performs an OSByte operation.
|
|
|
115 |
* If there is no error, the result contains
|
|
|
116 |
* the return value of R1 (X) in its bottom byte
|
|
|
117 |
* the return value of R2 (Y) in its second byte
|
|
|
118 |
* 1 in the third byte if carry is set on return, otherwise 0
|
|
|
119 |
* 0 in its top byte
|
|
|
120 |
* (Not all of these values will be significant, depending on the
|
|
|
121 |
* particular OSByte operation).
|
|
|
122 |
*/
|
|
|
123 |
|
|
|
124 |
extern int _kernel_osrdch(void);
|
|
|
125 |
/*
|
|
|
126 |
* Returns a character read from the currently selected OS input stream
|
|
|
127 |
*/
|
|
|
128 |
|
|
|
129 |
extern int _kernel_oswrch(int ch);
|
|
|
130 |
/*
|
|
|
131 |
* Writes a byte to all currently selected OS output streams
|
|
|
132 |
* The return value just indicates success or failure.
|
|
|
133 |
*/
|
|
|
134 |
|
|
|
135 |
extern int _kernel_osbget(unsigned handle);
|
|
|
136 |
/*
|
|
|
137 |
* Returns the next byte from the file identified by 'handle'.
|
|
|
138 |
* (-1 => EOF).
|
|
|
139 |
*/
|
|
|
140 |
|
|
|
141 |
extern int _kernel_osbput(int ch, unsigned handle);
|
|
|
142 |
/*
|
|
|
143 |
* Writes a byte to the file identified by 'handle'.
|
|
|
144 |
* The return value just indicates success or failure.
|
|
|
145 |
*/
|
|
|
146 |
|
|
|
147 |
extern int _kernel_osgbpb(int op, unsigned handle, _kernel_osgbpb_block *inout);/*
|
|
|
148 |
* Reads or writes a number of bytes from a filing system.
|
|
|
149 |
* The return value just indicates success or failure.
|
|
|
150 |
* Note that for some operations, the return value of C is significant,
|
|
|
151 |
* and for others it isn't. In all cases, therefore, a return value of -1
|
|
|
152 |
* is possible, but for some operations it should be ignored.
|
|
|
153 |
*/
|
|
|
154 |
|
|
|
155 |
extern int _kernel_osword(int op, int *data);
|
|
|
156 |
/*
|
|
|
157 |
* Performs an OSWord operation.
|
|
|
158 |
* The size and format of the block *data depends on the particular OSWord
|
|
|
159 |
* being used; it may be updated.
|
|
|
160 |
*/
|
|
|
161 |
|
|
|
162 |
extern int _kernel_osfind(int op, char *name);
|
|
|
163 |
/*
|
|
|
164 |
* Opens or closes a file.
|
|
|
165 |
* Open returns a file handle (0 => open failed without error)
|
|
|
166 |
* Close the return value just indicates success or failure
|
|
|
167 |
*/
|
|
|
168 |
|
|
|
169 |
extern int _kernel_osfile(int op, const char *name, _kernel_osfile_block *inout);
|
|
|
170 |
/* Performs an OSFile operation, with values of r2 - r5 taken from the osfile
|
|
|
171 |
* block. The block is updated with the return values of these registers,
|
|
|
172 |
* and the result is the return value of r0 (or an error indication)
|
|
|
173 |
*/
|
|
|
174 |
|
|
|
175 |
extern int _kernel_osargs(int op, unsigned handle, int arg);
|
|
|
176 |
/*
|
|
|
177 |
* Performs an OSArgs operation.
|
|
|
178 |
* The result is an error indication, or
|
|
|
179 |
* the current filing system number (if op = handle = 0)
|
|
|
180 |
* the value returned in R2 by the OSArgs operation otherwise
|
|
|
181 |
*/
|
|
|
182 |
|
|
|
183 |
extern int _kernel_oscli(const char *s);
|
|
|
184 |
/*
|
|
|
185 |
* Hands the argument string to the OS command line interpreter to execute
|
|
|
186 |
* as a command. This should not be used to invoke other applications:
|
|
|
187 |
* _kernel_system exists for that. Even using it to run a replacement
|
|
|
188 |
* application is somewhat dubious (abort handlers are left as those of the
|
|
|
189 |
* current application).
|
|
|
190 |
* The return value just indicates error or no error
|
|
|
191 |
*/
|
|
|
192 |
|
|
|
193 |
extern _kernel_oserror *_kernel_last_oserror(void);
|
|
|
194 |
/*
|
|
|
195 |
* Returns a pointer to an error block describing the last os error since
|
|
|
196 |
* _kernel_last_oserror was last called (or since there program started
|
|
|
197 |
* if there has been no such call). If there has been no os error, returns
|
|
|
198 |
* a null pointer. Note that occurrence of a further error may overwrite the
|
|
|
199 |
* contents of the block.
|
|
|
200 |
* If _kernel_swi caused the last os error, the error already returned by that
|
|
|
201 |
* call gets returned by this too.
|
|
|
202 |
*/
|
|
|
203 |
|
|
|
204 |
extern _kernel_oserror *_kernel_getenv(const char *name, char *buffer, unsigned size);
|
|
|
205 |
/*
|
|
|
206 |
* Reads the value of a system variable, placing the value string in the
|
|
|
207 |
* buffer (of size size).
|
|
|
208 |
* (This just gives access to OS_ReadVarVal).
|
|
|
209 |
*/
|
|
|
210 |
|
|
|
211 |
extern _kernel_oserror *_kernel_setenv(const char *name, const char *value);
|
|
|
212 |
/*
|
|
|
213 |
* Updates the value of a system variable to be string valued, with the
|
|
|
214 |
* given value (value = NULL deletes the variable)
|
|
|
215 |
*/
|
|
|
216 |
|
|
|
217 |
extern int _kernel_system(const char *string, int chain);
|
|
|
218 |
/*
|
|
|
219 |
* Hands the argument string to the OS command line interpreter to execute.
|
|
|
220 |
* If chain is 0, the calling application is copied to the top of memory first,
|
|
|
221 |
* then handlers are installed so that if the command string causes an
|
|
|
222 |
* application to be invoked, control returns to _kernel_system, which then
|
|
|
223 |
* copies the calling application back into its proper place - the command
|
|
|
224 |
* is executed as a sub-program. Of course, since the sub-program executes
|
|
|
225 |
* in the same address space, there is no protection against errant writes
|
|
|
226 |
* by it to the code or data of the caller. And if there is insufficient
|
|
|
227 |
* space to load the sub-program, the manner of the subsequent death is
|
|
|
228 |
* unlikely to be pretty.
|
|
|
229 |
* If chain is 1, all handlers are removed before calling the CLI, and if it
|
|
|
230 |
* returns (the command is built-in) _kernel_system Exits.
|
|
|
231 |
* The return value just indicates error or no error
|
|
|
232 |
*/
|
|
|
233 |
|
|
|
234 |
|
|
|
235 |
extern unsigned _kernel_alloc(unsigned minwords, void **block);
|
|
|
236 |
/*
|
|
|
237 |
* Tries to allocate a block of sensible size >= minwords. Failing that,
|
|
|
238 |
* it allocates the largest possible block (may be size zero).
|
|
|
239 |
* Sensible size means at least 2K words.
|
|
|
240 |
* *block is returned a pointer to the start of the allocated block
|
|
|
241 |
* (NULL if 'a block of size zero' has been allocated).
|
|
|
242 |
*/
|
|
|
243 |
|
|
|
244 |
typedef void freeproc(void *);
|
|
|
245 |
typedef void * allocproc(unsigned);
|
|
|
246 |
|
|
|
247 |
extern void _kernel_register_allocs(allocproc *malloc, freeproc *free);
|
|
|
248 |
/*
|
|
|
249 |
* Registers procedures to be used by the kernel when it requires to
|
|
|
250 |
* free or allocate storage. The allocproc may be called during stack
|
|
|
251 |
* extension, so may not check for stack overflow (nor may any procedure
|
|
|
252 |
* called from it), and must guarantee to require no more than 41 words
|
|
|
253 |
* of stack.
|
|
|
254 |
*/
|
|
|
255 |
|
|
|
256 |
typedef int _kernel_ExtendProc(int /*n*/, void** /*p*/);
|
|
|
257 |
extern _kernel_ExtendProc *_kernel_register_slotextend(_kernel_ExtendProc *proc);
|
|
|
258 |
/* When the initial heap is full, the kernel is normally capable of extending
|
|
|
259 |
it (if the OS will allow). However, if the heap limit is not the same as
|
|
|
260 |
the OS limit, it is assumed that someone else has acquired the space between,
|
|
|
261 |
and the procedure registered here is called to request n bytes from it.
|
|
|
262 |
Its return value is expected to be >= n or = 0 (failure); if success,
|
|
|
263 |
*p is set to point to the space returned.
|
|
|
264 |
*/
|
|
|
265 |
|
|
|
266 |
extern int _kernel_escape_seen(void);
|
|
|
267 |
/*
|
|
|
268 |
* Returns 1 if there has been an escape since the previous call of
|
|
|
269 |
* _kernel_escape_seen (or since program start, if there has been no
|
|
|
270 |
* previous call). Escapes are never ignored with this mechanism,
|
|
|
271 |
* whereas they may be with the language EventProc mechanism since there
|
|
|
272 |
* may be no stack to call it on.
|
|
|
273 |
*/
|
|
|
274 |
|
|
|
275 |
typedef union {
|
|
|
276 |
struct {int s:1, u:16, x: 15; unsigned mhi, mlo; } i;
|
|
|
277 |
int w[3]; } _extended_fp_number;
|
|
|
278 |
|
|
|
279 |
typedef struct {
|
|
|
280 |
int r4, r5, r6, r7, r8, r9;
|
|
|
281 |
int fp, sp, pc, sl;
|
|
|
282 |
_extended_fp_number f4, f5, f6, f7; } _kernel_unwindblock;
|
|
|
283 |
|
|
|
284 |
extern int _kernel_unwind(_kernel_unwindblock *inout, char **language);
|
|
|
285 |
/*
|
|
|
286 |
* Unwinds the call stack one level.
|
|
|
287 |
* Returns >0 if it succeeds
|
|
|
288 |
* 0 if it fails because it has reached the stack end
|
|
|
289 |
* <0 if it fails for any other reason (eg stack corrupt)
|
|
|
290 |
* Input values for fp, sl and pc must be correct.
|
|
|
291 |
* r4-r9 and f4-f7 are updated if the frame addressed by the input value
|
|
|
292 |
* of fp contains saved values for the corresponding registers.
|
|
|
293 |
* fp, sp, sl and pc are always updated
|
|
|
294 |
* *language is returned a pointer to a string naming the language
|
|
|
295 |
* corresponding to the returned value of pc.
|
|
|
296 |
*/
|
|
|
297 |
|
|
|
298 |
extern char *_kernel_procname(int pc);
|
|
|
299 |
/*
|
|
|
300 |
* Returns a string naming the procedure containing the address pc.
|
|
|
301 |
* (or 0 if no name for it can be found).
|
|
|
302 |
*/
|
|
|
303 |
|
|
|
304 |
extern char *_kernel_language(int pc);
|
|
|
305 |
/*
|
|
|
306 |
* Returns a string naming the language in whose code the address pc lies.
|
|
|
307 |
* (or 0 if it is in no known language).
|
|
|
308 |
*/
|
|
|
309 |
|
|
|
310 |
/* divide and remainder functions.
|
|
|
311 |
* The signed functions round towards zero.
|
|
|
312 |
*
|
|
|
313 |
* The div functions actually also return the remainder in a2, and use of
|
|
|
314 |
* this by a code-generator will be more efficient than a call to the rem
|
|
|
315 |
* function.
|
|
|
316 |
*
|
|
|
317 |
* Language RTSs are encouraged to use these functions rather than providing
|
|
|
318 |
* their own, since considerable effort has been expended to make these fast.
|
|
|
319 |
*/
|
|
|
320 |
|
|
|
321 |
extern unsigned _kernel_udiv(unsigned divisor, unsigned dividend);
|
|
|
322 |
extern unsigned _kernel_urem(unsigned divisor, unsigned dividend);
|
|
|
323 |
extern unsigned _kernel_udiv10(unsigned dividend);
|
|
|
324 |
|
|
|
325 |
extern int _kernel_sdiv(int divisor, int dividend);
|
|
|
326 |
extern int _kernel_srem(int divisor, int dividend);
|
|
|
327 |
extern int _kernel_sdiv10(int dividend);
|
|
|
328 |
|
|
|
329 |
/*
|
|
|
330 |
* Description of a 'Language description block'
|
|
|
331 |
*/
|
|
|
332 |
|
|
|
333 |
typedef enum { NotHandled, Handled } _kernel_HandledOrNot;
|
|
|
334 |
|
|
|
335 |
typedef struct {
|
|
|
336 |
int regs [16];
|
|
|
337 |
} _kernel_registerset;
|
|
|
338 |
|
|
|
339 |
typedef struct {
|
|
|
340 |
int regs [10];
|
|
|
341 |
} _kernel_eventregisters;
|
|
|
342 |
|
|
|
343 |
typedef void (*PROC) (void);
|
|
|
344 |
typedef _kernel_HandledOrNot (*_kernel_trapproc) (int code, _kernel_registerset *regs);
|
|
|
345 |
typedef _kernel_HandledOrNot (*_kernel_eventproc) (int code, _kernel_registerset *regs);
|
|
|
346 |
|
|
|
347 |
typedef struct {
|
|
|
348 |
int size;
|
|
|
349 |
int codestart, codeend;
|
|
|
350 |
char *name;
|
|
|
351 |
PROC (*InitProc)(void);
|
|
|
352 |
PROC FinaliseProc;
|
|
|
353 |
_kernel_trapproc TrapProc;
|
|
|
354 |
_kernel_trapproc UncaughtTrapProc;
|
|
|
355 |
_kernel_eventproc EventProc;
|
|
|
356 |
_kernel_eventproc UnhandledEventProc;
|
|
|
357 |
void (*FastEventProc) (_kernel_eventregisters *);
|
|
|
358 |
int (*UnwindProc) (_kernel_unwindblock *inout, char **language);
|
|
|
359 |
char * (*NameProc) (int pc);
|
|
|
360 |
} _kernel_languagedescription;
|
|
|
361 |
|
|
|
362 |
typedef int _kernel_ccproc(int, int, int);
|
|
|
363 |
|
|
|
364 |
extern int _kernel_call_client(int a1, int a2, int a3, _kernel_ccproc callee);
|
|
|
365 |
/* This is for shared library use only, and is not exported to shared library
|
|
|
366 |
* clients. It is provided to allow library functions which call arbitrary
|
|
|
367 |
* client code (C library signal, exit, _main) to do so correctly if the
|
|
|
368 |
* client uses the old calling standard.
|
|
|
369 |
*/
|
|
|
370 |
|
|
|
371 |
extern int _kernel_client_is_module(void);
|
|
|
372 |
/* For shared library use only, not exported to clients. Returns a
|
|
|
373 |
* non-zero value if the library's client is a module executing in user
|
|
|
374 |
* mode (ie module run code).
|
|
|
375 |
*/
|
|
|
376 |
|
|
|
377 |
extern int _kernel_processor_mode(void);
|
|
|
378 |
|
|
|
379 |
extern void _kernel_irqs_on(void);
|
|
|
380 |
|
|
|
381 |
extern void _kernel_irqs_off(void);
|
|
|
382 |
|
|
|
383 |
extern int _kernel_irqs_disabled(void);
|
|
|
384 |
/* returns 0 if interrupts are enabled; some non-zero value if disabled. */
|
|
|
385 |
|
|
|
386 |
extern void *_kernel_RMAalloc(size_t size);
|
|
|
387 |
|
|
|
388 |
extern void *_kernel_RMAextend(void *p, size_t size);
|
|
|
389 |
|
|
|
390 |
extern void _kernel_RMAfree(void *p);
|
|
|
391 |
|
|
|
392 |
#endif
|
|
|
393 |
/* end of kernel.h */
|