Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,408 @@
/*
Copyright 1981
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include <stdio.h>
#include <klib.h>
#include "machine.h"
#include "ctype.h"
#ifdef PDP11
struct {
char lobyte;
char hibyte;
};
struct {
char *ptrw1;
char *ptrw2;
};
struct {
int wd1;
int wd2;
};
struct {
int swd1;
};
#endif
#ifdef MC68000
struct {
char hibyte;
char lobyte;
};
struct {
char *ptrw2;
};
struct {
int wd1;
int wd2;
};
struct {
int swd1;
};
#endif
#ifdef VAX
struct {
short wd2;
short wd1;
};
struct {
short swd1;
};
struct {
char lobyte;
char hibyte;
};
struct {
char *ptrw2;
};
#endif
/* format of a symbol entry in the main table*/
# define NAMELEN 8 /*length of name in symbol table*/
struct symtab {
char name[NAMELEN]; /*symbol name*/
short flags; /*bit flags*/
char *tlnk; /*table link*/
long vl1; /*symbol value*/
};
struct symtab *symtptr;
# define STESIZE (sizeof *symtptr) /*byte length of symbol table entry*/
/* flags for symbols*/
# define SYDF 0100000 /*defined*/
# define SYEQ 0040000 /*equated*/
# define SYGL 0020000 /*global - entry or external*/
# define SYER 0010000 /*equated register*/
# define SYXR 0004000 /*external reference*/
# define SYRA 0002000 /*DATA based relocatable*/
# define SYRO 0001000 /*TEXT based relocatable*/
# define SYBS 0000400 /*BSS based relocatable*/
# define SYIN 0000200 /*internal symbol -- opcode, directive or equ*/
# define SYPC 0000100 /*[vlh]equated using star '*' expression*/
# define SYRM 0000040 /*[vlh]register mask equate*/
/*flags for opcodes and directives*/
# define OPDR 0100000 /*0=>opcode, 1=>directive*/
# define OPFF 037 /*type of instruction (used as mask)*/
struct irts {
char *irle; /*ptr to last entry in chain*/
char *irfe; /*ptr to first entry in chain*/
};
long stlen; /*length of symbol table*/
/*
* intermediate text file
* format of the intermediate text for one statement:
*
* ******************************************************
* * it type = ITBS * # it entries * 0
* ******************************************************
* * absolute line number (long) *
* ******************************************************
* * it type = ITSY * instr length * 1
* ******************************************************
* * symbol table pointer for stmt label (long) *
* ******************************************************
* * it type = ITSY * instr mode length * 2
* ******************************************************
* * opcode ptr (long) *
* ******************************************************
* * it type = ITCN * relocation base * 3
* ******************************************************
* * location counter (pass 1) *
* ******************************************************
* * it type * relocation flag * 4 - oprnds
* ******************************************************
* * value (long) *
* ******************************************************
* .
*
* .
* ******************************************************
* * it type * relocation flag * n - oprnds
* ******************************************************
* * value (long) *
* ******************************************************
*/
#define ITOP1 4 /*first it entry for operands*/
/*
* it type meaning
* 0 beginning of statement
* 1 value is pointer to symbol table
* 2 value is a constant
* 3 value is a specal char
*
* relocation flag for opcode it entry is operand length:
* 'b' => byte
* 'w' => word
* 'l' => long
*/
struct it {
char itty; /*it type*/
char itrl; /*relocation flag or # it entries*/
long itop;
};
int mode; /*operand mode (byte, word, long)*/
int modelen; /*operand length per mode*/
#define BYTE 'b'
#define WORD 'w'
#define LONG 'l'
/* parameters that define the main table*/
#define SZMT 300 /*initial size of the main table */
/*must be large enough to initialize*/
#ifdef PDP11
#define ICRSZMT 10 /*add to main table when run out*/
#else
#define ICRSZMT 50 /*add to main table when run out*/
#endif
int cszmt; /*current size of main table*/
char *bmte; /*beginning of main table*/
char *emte; /*end of main table*/
/* intermediate text types*/
#define ITBS 0 /*beginning of statement*/
#define ITSY 1 /*pointer to symbol table*/
#define ITCN 2 /*constant*/
#define ITSP 3 /*special*/
#define ITRM 4 /*[vlh]register mask!*/
#define ITPC 5 /*[vlh]pc relative argument*/
# define ITBSZ 256 /*size of the it buffer*/
short itbuf[ITBSZ]; /*it buffer*/
#define STMAX 200 /*size of intermediate text buffer*/
struct it stbuf[STMAX]; /*holds it for one statement*/
char sbuf[512]; /*holds one block of source*/
/*initial reference table for symbols*/
# define SZIRT 128
char *sirt[SZIRT];
/*initial reference table to opcodes*/
char *oirt[SZIRT];
/*external symbol table*/
#define EXTSZ 512
char *extbl[EXTSZ];
int extindx; /*index to external symbol table*/
char **pexti; /*ptr to external symbol table*/
int absln; /*absolute line number*/
int p2absln; /*pass 2 line number*/
int fcflg; /*0=>passed an item. 1=>first char*/
int fchr; /*first char in term*/
int ifn; /*source file descriptor*/
short *pitix; /*ptr to it buffer*/
int itwc; /*number of words in it buffer*/
struct it *pitw; /*ptr to it buffer next entry*/
int itype; /*type of item*/
long ival; /*value of item*/
char *lblpt; /*label pointer*/
char lbt[NAMELEN]; /*holds label name*/
char *lmte; /*last entry in main table*/
long loctr; /*location counter*/
long savelc[4]; /*save relocation counters for 3 bases*/
int nite; /*number of entries in stbuf*/
struct it *pnite;
int lfn; /*loader output file descriptor*/
char *opcpt; /*pointer to opcode entry in main table*/
int p2flg; /*0=>pass 1 1=>pass 2*/
char **pirt; /*entry in initial reference table*/
int reloc; /*relocation value returned by expression evaluator (expr)*/
int rlflg; /*relocation value of current location counter*/
/*relocation values*/
# define ABS 0 /*absolute*/
# define DATA 1
# define TEXT 2
# define BSS 3
# define EXTRN 4 /*externally defined*/
#define EOLC '\n' /*end of line character*/
#define EOF 0 /*end of file indicator*/
#define NULL 0 /* [vlh] character null '\0' */
#define TRUE 1 /* [vlh] boolean values */
#define FALSE 0 /* [vlh] boolean values */
int format;
int sbuflen; /*number of chars in sbuf*/
char *psbuf; /*ptr into sbuf*/
int itfn; /*it file number*/
char itfnc; /*last char of it file name*/
int trbfn; /*temp for text relocation bits*/
char trbfnc; /*last char of text rb file*/
int dafn; /*file for data stuff*/
char dafnc; /*last char of data file*/
int drbfn; /*file for data relocation bits*/
char drbfnc; /*last char*/
int prtflg; /*print output flag*/
int undflg; /*make undefined symbols external flag*/
int starmul; /* * is multiply operator*/
char *endptr, *addptr;
char *orgptr;
char *subptr, *addiptr, *addqptr, *subiptr, *subqptr;
char *cmpptr, *addaptr, *cmpaptr, *subaptr, *cmpmptr;
char *equptr;
char *andptr, *andiptr, *eorptr, *eoriptr, *orptr, *oriptr;
char *cmpiptr;
char *moveptr, *moveqptr;
char *exgptr;
char *evenptr;
char *jsrptr, *bsrptr, *nopptr;
char peekc;
int numcon[2], numsym[2], indir[2], immed[2], numreg[2];
int plevel; /*parenthesis level counter*/
int opdix; /*operand index counter*/
int p1inlen; /*pass 1 instr length*/
int instrlen; /*pass 2 bytes in current instruction*/
/* effective address mode bits*/
#define DDIR 000
#define ADIR 010
#define INDIRECT 020
#define INDINC 030
#define DECIND 040
#define INDDISP 050
#define INDINX 060
#define SADDR 070
#define LADDR 071
#define IMM 074
#define AREGLO 8
#define AREGHI 15
/* relocation bit definitions:*/
#define RBMASK 07 /*tells type of relocation*/
#define INSABS 7 /*first word of instr -- absolute*/
#define DABS 0 /*data word absolute*/
#define TRELOC 2 /* TEXT relocatable*/
#define DRELOC 1 /* DATA relocatable*/
#define BRELOC 3 /* BSS relocatable*/
#define EXTVAR 4 /* ref to external variable*/
#define LUPPER 5 /* upper word of long*/
#define EXTREL 6 /* external relative mode*/
/* ptrs to ins[] and rlbits[]*/
int *pins;
int *prlb;
int ins[5]; /*holds instruction words*/
#define PRTCHLEN 128
char prtchars[PRTCHLEN]; /*line buffer for putchar*/
char *prtchidx; /*index for putchar*/
int extflg, extref; /*external in expr*/
#define CCR 16
#define SR 17
#define USP 18
#define MOVECCR 042300
#define MOVESR 043300
#define SRMOVE 040300
#define MOVEUSP 047140
struct op {
int ea; /* effective address bits*/
int len; /* effective address length in bytes*/
long con; /*constant or reloc part of operand*/
int drlc; /*reloc of con*/
int ext; /*external variable #*/
int idx; /*index register if any*/
int xmod; /*mode of index reg*/
} opnd[2];
#define OPSTLEN 10
#define TREELEN 20
struct buf{
int fildes;
int nunused;
char *xfree;
char buff[512];
};
struct buf lbuf;
struct buf tbuf;
struct buf dabuf;
struct buf drbuf;
int nerror; /*# of assembler errors*/
int in_err; /*[vlh] don't generate instrlen err if already err state*/
int shortadr; /*short addresses if set*/
#define CLRFOR 24
#define CLRVAL 041000
long itoffset;
#define LASTCHTFN *tfilptr
char *tfilptr; /* -> Changed filename character */
#define PC 22
int equflg; /*doing an equate stmt*/
#define ANDI 01000
#define AND 0140000
#define ORI 0
#define OR 0100000
#define EORI 05000
#define EOR 0130000
#define MOVE 0
long lseek();
char *sbrk();
char *lemt();
int refpc; /* * referenced in expr*/
#define SOH 1
/* Conditional Assembly variables and constants [vlh] */
#define LOW_CA 21 /* [vlh] */
#define HI_CA 30 /* [vlh] */
int ca_true; /* true unless in a false CA*/
int ca; /* depth of conditional assembly, none = 0*/
int ca_level; /* at what CA depth did CA go false?*/
/* pass 1 global variables */
int numops; /*number of operands*/
int inoffset; /*[vlh]offset directive*/
int didorg;
int initflg; /*initialize flag*/
/* defines */
#define igblk() while(fchr==' ') fchr=gchr()
#define ckein() ((pitw >= pnite))
/* is it an alterable operand */
#define memalt(ap) (memea(ap) && altea(ap))
#define dataalt(ap) (dataea(ap) && altea(ap))
#define altea(ap) ((((ap)->ea&070)!=SADDR || ((ap)->ea&6)==0))
/* is it the specific type of operand */
#define memea(ap) (((ap)->ea&070) >= INDIRECT)
#define dataea(ap) (((ap)->ea&070) != ADIR)
#define pcea(ap) ((ap)->ea==072 || (ap)->ea==073)
#define ckdreg(ap) ((ap)->ea>=0 && (ap)->ea<AREGLO)
#define ckareg(ap) ((ap)->ea>=AREGLO && (ap)->ea<=AREGHI)
/*
* DRI Listing Hacks:
*/
char *sfname; /* -> Source file name */
#define LPP 58 /* # lines / page */
int xline; /* Present line # */
int xpage; /* Present Page # */

View File

@@ -0,0 +1,415 @@
1File: AS68.H Page 1
1 /*
2 Copyright 1981
3 Alcyon Corporation
4 8716 Production Ave.
5 San Diego, Ca. 92121
6 */
7 #include <stdio.h>
8 #include <klib.h>
9 #include "machine.h"
10 #include "ctype.h"
11
12 #ifdef PDP11
13 struct {
14 char lobyte;
15 char hibyte;
16 };
17 struct {
18 char *ptrw1;
19 char *ptrw2;
20 };
21 struct {
22 int wd1;
23 int wd2;
24 };
25 struct {
26 int swd1;
27 };
28 #endif
29
30 #ifdef MC68000
31 struct {
32 char hibyte;
33 char lobyte;
34 };
35 struct {
36 char *ptrw2;
37 };
38 struct {
39 int wd1;
40 int wd2;
41 };
42 struct {
43 int swd1;
44 };
45 #endif
46
47 #ifdef VAX
48 struct {
49 short wd2;
50 short wd1;
51 };
52 struct {
53 short swd1;
54 };
55
56 struct {
57 char lobyte;
58 char hibyte;
59 };
1File: AS68.H Page 2
60 struct {
61 char *ptrw2;
62 };
63 #endif
64
65 /* format of a symbol entry in the main table*/
66
67 # define NAMELEN 8 /*length of name in symbol table*/
68 struct symtab {
69 char name[NAMELEN]; /*symbol name*/
70 short flags; /*bit flags*/
71 char *tlnk; /*table link*/
72 long vl1; /*symbol value*/
73 };
74
75 struct symtab *symtptr;
76 # define STESIZE (sizeof *symtptr) /*byte length of symbol table entry*/
77
78 /* flags for symbols*/
79 # define SYDF 0100000 /*defined*/
80 # define SYEQ 0040000 /*equated*/
81 # define SYGL 0020000 /*global - entry or external*/
82 # define SYER 0010000 /*equated register*/
83 # define SYXR 0004000 /*external reference*/
84 # define SYRA 0002000 /*DATA based relocatable*/
85 # define SYRO 0001000 /*TEXT based relocatable*/
86 # define SYBS 0000400 /*BSS based relocatable*/
87 # define SYIN 0000200 /*internal symbol -- opcode, directive or equ*/
88 # define SYPC 0000100 /*[vlh]equated using star '*' expression*/
89 # define SYRM 0000040 /*[vlh]register mask equate*/
90
91 /*flags for opcodes and directives*/
92 # define OPDR 0100000 /*0=>opcode, 1=>directive*/
93 # define OPFF 037 /*type of instruction (used as mask)*/
94
95 struct irts {
96 char *irle; /*ptr to last entry in chain*/
97 char *irfe; /*ptr to first entry in chain*/
98 };
99
100 long stlen; /*length of symbol table*/
101
102 /*
103 * intermediate text file
104 * format of the intermediate text for one statement:
105 *
106 * ******************************************************
107 * * it type = ITBS * # it entries * 0
108 * ******************************************************
109 * * absolute line number (long) *
110 * ******************************************************
111 * * it type = ITSY * instr length * 1
112 * ******************************************************
113 * * symbol table pointer for stmt label (long) *
114 * ******************************************************
115 * * it type = ITSY * instr mode length * 2
116 * ******************************************************
117 * * opcode ptr (long) *
118 * ******************************************************
1File: AS68.H Page 3
119 * * it type = ITCN * relocation base * 3
120 * ******************************************************
121 * * location counter (pass 1) *
122 * ******************************************************
123 * * it type * relocation flag * 4 - oprnds
124 * ******************************************************
125 * * value (long) *
126 * ******************************************************
127 * .
128 *
129 * .
130 * ******************************************************
131 * * it type * relocation flag * n - oprnds
132 * ******************************************************
133 * * value (long) *
134 * ******************************************************
135 */
136
137 #define ITOP1 4 /*first it entry for operands*/
138
139 /*
140 * it type meaning
141 * 0 beginning of statement
142 * 1 value is pointer to symbol table
143 * 2 value is a constant
144 * 3 value is a specal char
145 *
146 * relocation flag for opcode it entry is operand length:
147 * 'b' => byte
148 * 'w' => word
149 * 'l' => long
150 */
151
152 struct it {
153 char itty; /*it type*/
154 char itrl; /*relocation flag or # it entries*/
155 long itop;
156 };
157
158 int mode; /*operand mode (byte, word, long)*/
159 int modelen; /*operand length per mode*/
160 #define BYTE 'b'
161 #define WORD 'w'
162 #define LONG 'l'
163
164 /* parameters that define the main table*/
165 #define SZMT 300 /*initial size of the main table */
166 /*must be large enough to initialize*/
167 #ifdef PDP11
168 #define ICRSZMT 10 /*add to main table when run out*/
169 #else
170 #define ICRSZMT 50 /*add to main table when run out*/
171 #endif
172 int cszmt; /*current size of main table*/
173 char *bmte; /*beginning of main table*/
174 char *emte; /*end of main table*/
175
176 /* intermediate text types*/
177 #define ITBS 0 /*beginning of statement*/
1File: AS68.H Page 4
178 #define ITSY 1 /*pointer to symbol table*/
179 #define ITCN 2 /*constant*/
180 #define ITSP 3 /*special*/
181 #define ITRM 4 /*[vlh]register mask!*/
182 #define ITPC 5 /*[vlh]pc relative argument*/
183
184 # define ITBSZ 256 /*size of the it buffer*/
185 short itbuf[ITBSZ]; /*it buffer*/
186
187 #define STMAX 200 /*size of intermediate text buffer*/
188 struct it stbuf[STMAX]; /*holds it for one statement*/
189
190 char sbuf[512]; /*holds one block of source*/
191
192 /*initial reference table for symbols*/
193 # define SZIRT 128
194 char *sirt[SZIRT];
195
196 /*initial reference table to opcodes*/
197 char *oirt[SZIRT];
198
199 /*external symbol table*/
200 #define EXTSZ 512
201 char *extbl[EXTSZ];
202 int extindx; /*index to external symbol table*/
203 char **pexti; /*ptr to external symbol table*/
204
205 int absln; /*absolute line number*/
206 int p2absln; /*pass 2 line number*/
207 int fcflg; /*0=>passed an item. 1=>first char*/
208 int fchr; /*first char in term*/
209 int ifn; /*source file descriptor*/
210 short *pitix; /*ptr to it buffer*/
211 int itwc; /*number of words in it buffer*/
212 struct it *pitw; /*ptr to it buffer next entry*/
213 int itype; /*type of item*/
214 long ival; /*value of item*/
215 char *lblpt; /*label pointer*/
216 char lbt[NAMELEN]; /*holds label name*/
217 char *lmte; /*last entry in main table*/
218 long loctr; /*location counter*/
219 long savelc[4]; /*save relocation counters for 3 bases*/
220 int nite; /*number of entries in stbuf*/
221 struct it *pnite;
222 int lfn; /*loader output file descriptor*/
223 char *opcpt; /*pointer to opcode entry in main table*/
224 int p2flg; /*0=>pass 1 1=>pass 2*/
225 char **pirt; /*entry in initial reference table*/
226 int reloc; /*relocation value returned by expression evaluator (expr)*/
227 int rlflg; /*relocation value of current location counter*/
228 /*relocation values*/
229 # define ABS 0 /*absolute*/
230 # define DATA 1
231 # define TEXT 2
232 # define BSS 3
233 # define EXTRN 4 /*externally defined*/
234
235 #define EOLC '\n' /*end of line character*/
236 #define EOF 0 /*end of file indicator*/
1File: AS68.H Page 5
237 #define NULL 0 /* [vlh] character null '\0' */
238 #define TRUE 1 /* [vlh] boolean values */
239 #define FALSE 0 /* [vlh] boolean values */
240
241 int format;
242 int sbuflen; /*number of chars in sbuf*/
243 char *psbuf; /*ptr into sbuf*/
244 int itfn; /*it file number*/
245 char itfnc; /*last char of it file name*/
246 int trbfn; /*temp for text relocation bits*/
247 char trbfnc; /*last char of text rb file*/
248 int dafn; /*file for data stuff*/
249 char dafnc; /*last char of data file*/
250 int drbfn; /*file for data relocation bits*/
251 char drbfnc; /*last char*/
252 int prtflg; /*print output flag*/
253 int undflg; /*make undefined symbols external flag*/
254
255 int starmul; /* * is multiply operator*/
256
257 char *endptr, *addptr;
258 char *orgptr;
259 char *subptr, *addiptr, *addqptr, *subiptr, *subqptr;
260 char *cmpptr, *addaptr, *cmpaptr, *subaptr, *cmpmptr;
261 char *equptr;
262 char *andptr, *andiptr, *eorptr, *eoriptr, *orptr, *oriptr;
263 char *cmpiptr;
264 char *moveptr, *moveqptr;
265 char *exgptr;
266 char *evenptr;
267 char *jsrptr, *bsrptr, *nopptr;
268 char peekc;
269 int numcon[2], numsym[2], indir[2], immed[2], numreg[2];
270 int plevel; /*parenthesis level counter*/
271 int opdix; /*operand index counter*/
272 int p1inlen; /*pass 1 instr length*/
273 int instrlen; /*pass 2 bytes in current instruction*/
274
275 /* effective address mode bits*/
276 #define DDIR 000
277 #define ADIR 010
278 #define INDIRECT 020
279 #define INDINC 030
280 #define DECIND 040
281 #define INDDISP 050
282 #define INDINX 060
283 #define SADDR 070
284 #define LADDR 071
285 #define IMM 074
286
287 #define AREGLO 8
288 #define AREGHI 15
289
290 /* relocation bit definitions:*/
291 #define RBMASK 07 /*tells type of relocation*/
292 #define INSABS 7 /*first word of instr -- absolute*/
293 #define DABS 0 /*data word absolute*/
294 #define TRELOC 2 /* TEXT relocatable*/
295 #define DRELOC 1 /* DATA relocatable*/
1File: AS68.H Page 6
296 #define BRELOC 3 /* BSS relocatable*/
297 #define EXTVAR 4 /* ref to external variable*/
298 #define LUPPER 5 /* upper word of long*/
299 #define EXTREL 6 /* external relative mode*/
300
301 /* ptrs to ins[] and rlbits[]*/
302 int *pins;
303 int *prlb;
304 int ins[5]; /*holds instruction words*/
305
306 #define PRTCHLEN 128
307 char prtchars[PRTCHLEN]; /*line buffer for putchar*/
308 char *prtchidx; /*index for putchar*/
309
310 int extflg, extref; /*external in expr*/
311
312 #define CCR 16
313 #define SR 17
314 #define USP 18
315 #define MOVECCR 042300
316 #define MOVESR 043300
317 #define SRMOVE 040300
318 #define MOVEUSP 047140
319
320 struct op {
321 int ea; /* effective address bits*/
322 int len; /* effective address length in bytes*/
323 long con; /*constant or reloc part of operand*/
324 int drlc; /*reloc of con*/
325 int ext; /*external variable #*/
326 int idx; /*index register if any*/
327 int xmod; /*mode of index reg*/
328 } opnd[2];
329 #define OPSTLEN 10
330 #define TREELEN 20
331 struct buf{
332 int fildes;
333 int nunused;
334 char *xfree;
335 char buff[512];
336 };
337
338 struct buf lbuf;
339 struct buf tbuf;
340 struct buf dabuf;
341 struct buf drbuf;
342
343 int nerror; /*# of assembler errors*/
344 int in_err; /*[vlh] don't generate instrlen err if already err state*/
345 int shortadr; /*short addresses if set*/
346
347 #define CLRFOR 24
348 #define CLRVAL 041000
349
350 long itoffset;
351
352 #define LASTCHTFN *tfilptr
353 char *tfilptr; /* -> Changed filename character */
354 #define PC 22
1File: AS68.H Page 7
355
356 int equflg; /*doing an equate stmt*/
357
358 #define ANDI 01000
359 #define AND 0140000
360 #define ORI 0
361 #define OR 0100000
362 #define EORI 05000
363 #define EOR 0130000
364 #define MOVE 0
365
366 long lseek();
367 char *sbrk();
368 char *lemt();
369
370 int refpc; /* * referenced in expr*/
371 #define SOH 1
372
373 /* Conditional Assembly variables and constants [vlh] */
374 #define LOW_CA 21 /* [vlh] */
375 #define HI_CA 30 /* [vlh] */
376
377 int ca_true; /* true unless in a false CA*/
378 int ca; /* depth of conditional assembly, none = 0*/
379 int ca_level; /* at what CA depth did CA go false?*/
380
381 /* pass 1 global variables */
382 int numops; /*number of operands*/
383 int inoffset; /*[vlh]offset directive*/
384 int didorg;
385 int initflg; /*initialize flag*/
386
387 /* defines */
388 #define igblk() while(fchr==' ') fchr=gchr()
389 #define ckein() ((pitw >= pnite))
390
391 /* is it an alterable operand */
392 #define memalt(ap) (memea(ap) && altea(ap))
393 #define dataalt(ap) (dataea(ap) && altea(ap))
394 #define altea(ap) ((((ap)->ea&070)!=SADDR || ((ap)->ea&6)==0))
395
396 /* is it the specific type of operand */
397 #define memea(ap) (((ap)->ea&070) >= INDIRECT)
398 #define dataea(ap) (((ap)->ea&070) != ADIR)
399 #define pcea(ap) ((ap)->ea==072 || (ap)->ea==073)
400 #define ckdreg(ap) ((ap)->ea>=0 && (ap)->ea<AREGLO)
401 #define ckareg(ap) ((ap)->ea>=AREGLO && (ap)->ea<=AREGHI)
402 /*
403 * DRI Listing Hacks:
404 */
405 char *sfname; /* -> Source file name */
406 #define LPP 58 /* # lines / page */
407 int xline; /* Present line # */
408 int xpage; /* Present Page # */

View File

@@ -0,0 +1,222 @@
*/*
* Copyright 1981
* Alcyon Corporation
* 8716 Production Ave.
* San Diego, Ca. 92121
**/
R0: .equ 0,r
R1: .equ 1,r
R2: .equ 2,r
R3: .equ 3,r
R4: .equ 4,r
R5: .equ 5,r
R6: .equ 6,r
R7: .equ 7,r
R8: .equ 8,r
R9: .equ 9,r
R10: .equ 10,r
R11: .equ 11,r
R12: .equ 12,r
R13: .equ 13,r
R14: .equ 14,r
R15: .equ 15,r
D0: .equ 0,r
D1: .equ 1,r
D2: .equ 2,r
D3: .equ 3,r
D4: .equ 4,r
D5: .equ 5,r
D6: .equ 6,r
D7: .equ 7,r
A0: .equ @10,r
A1: .equ @11,r
A2: .equ @12,r
A3: .equ @13,r
A4: .equ @14,r
A5: .equ @15,r
A6: .equ @16,r
A7: .equ @17,r
USP: .equ 18,r
SP: .equ 15,r
CCR: .equ 16,r
SR: .equ 17,r
r0: .equ 0,r
r1: .equ 1,r
r2: .equ 2,r
r3: .equ 3,r
r4: .equ 4,r
r5: .equ 5,r
r6: .equ 6,r
r7: .equ 7,r
r8: .equ 8,r
r9: .equ 9,r
r10: .equ 10,r
r11: .equ 11,r
r12: .equ 12,r
r13: .equ 13,r
r14: .equ 14,r
r15: .equ 15,r
d0: .equ 0,r
d1: .equ 1,r
d2: .equ 2,r
d3: .equ 3,r
d4: .equ 4,r
d5: .equ 5,r
d6: .equ 6,r
d7: .equ 7,r
a0: .equ @10,r
a1: .equ @11,r
a2: .equ @12,r
a3: .equ @13,r
a4: .equ @14,r
a5: .equ @15,r
a6: .equ @16,r
a7: .equ @17,r
usp: .equ 18,r
sp: .equ 15,r
ccr: .equ 16,r
sr: .equ 17,r
.b: .equ 19,r
.B: .equ 19,r
.w: .equ 20,r
.W: .equ 20,r
.l: .equ 21,r
.L: .equ 21,r
pc: .equ 22,r
PC: .equ 22,r
abcd: .opd 4,@140400
add: .opd 1,@150000
adda: .opd 15,@150000
addi: .opd 2,@003000
addq: .opd 17,@050000
inc: .opd 16,@050000
addx: .opd 27,@150400
and: .opd 1,@140000
andi: .opd 2,@001000
asl: .opd 8,@160400
asr: .opd 8,@160000
bcc: .opd 6,@062000
bcs: .opd 6,@062400
beq: .opd 6,@063400
bze: .opd 6,@063400
bge: .opd 6,@066000
bgt: .opd 6,@067000
bhi: .opd 6,@061000
bhis: .opd 6,@062000
bhs: .opd 6,@062000
ble: .opd 6,@067400
blo: .opd 6,@062400
bls: .opd 6,@061400
blos: .opd 6,@061400
blt: .opd 6,@066400
bmi: .opd 6,@065400
bne: .opd 6,@063000
bnz: .opd 6,@063000
bpl: .opd 6,@065000
bvc: .opd 6,@064000
bvs: .opd 6,@064400
bchg: .opd 7,@000100
bclr: .opd 7,@000200
bra: .opd 6,@060000
bt: .opd 6,@060000
bset: .opd 7,@000300
bsr: .opd 6,@060400
btst: .opd 7,@000000
chk: .opd 26,@040600
clr: .opd 24,@041000
cmp: .opd 26,@130000
cmpa: .opd 15,@130000
cmpi: .opd 2,@006000
cmpm: .opd 10,@130410
dbcc: .opd 11,@052310
dbcs: .opd 11,@052710
dblo: .opd 11,@052710
dbeq: .opd 11,@053710
dbze: .opd 11,@053710
dbra: .opd 11,@050710
dbf: .opd 11,@050710
dbge: .opd 11,@056310
dbgt: .opd 11,@057310
dbhi: .opd 11,@051310
dbhs: .opd 11,@051310
dble: .opd 11,@057710
dbls: .opd 11,@051710
dblt: .opd 11,@056710
dbmi: .opd 11,@055710
dbne: .opd 11,@053310
dbnz: .opd 11,@053310
dbpl: .opd 11,@055310
dbt: .opd 11,@050310
dbvc: .opd 11,@054310
dbvs: .opd 11,@054710
divs: .opd 5,@100700
divu: .opd 5,@100300
eor: .opd 23,@130000
eori: .opd 2,@005000
exg: .opd 12,@140400
ext: .opd 13,@044000
jmp: .opd 9,@047300
jsr: .opd 9,@047200
illegal:.opd 0,@045374
lea: .opd 30,@040700
link: .opd 19,@047120
lsr: .opd 8,@160010
lsl: .opd 8,@160410
move: .opd 3,@000000
movea: .opd 3,@000100
movem: .opd 20,@044200
movep: .opd 21,@000010
moveq: .opd 22,@070000
muls: .opd 5,@140700
mulu: .opd 5,@140300
nbcd: .opd 25,@044000
neg: .opd 24,@042000
negx: .opd 24,@040000
nop: .opd 0,@047161
not: .opd 24,@043000
or: .opd 1,@100000
ori: .opd 2,@000000
pea: .opd 29,@044100
reset: .opd 0,@047160
rol: .opd 8,@160430
ror: .opd 8,@160030
roxl: .opd 8,@160420
roxr: .opd 8,@160020
rte: .opd 0,@047163
rtr: .opd 0,@047167
rts: .opd 0,@047165
sbcd: .opd 4,@100400
scc: .opd 25,@052300
shs: .opd 25,@052300
scs: .opd 25,@052700
slo: .opd 25,@052700
seq: .opd 25,@053700
sze: .opd 25,@053700
sf: .opd 25,@050700
sge: .opd 25,@056300
sgt: .opd 25,@057300
shi: .opd 25,@051300
sle: .opd 25,@057700
sls: .opd 25,@051700
slt: .opd 25,@056700
smi: .opd 25,@055700
sne: .opd 25,@053300
snz: .opd 25,@053300
spl: .opd 25,@055300
st: .opd 25,@050300
svc: .opd 25,@054300
svs: .opd 25,@054700
stop: .opd 14,@047162
sub: .opd 1,@110000
suba: .opd 15,@110000
subi: .opd 2,@002000
subq: .opd 17,@050400
dec: .opd 16,@050400
subx: .opd 27,@110400
swap: .opd 28,@044100
tas: .opd 25,@045300
trap: .opd 18,@047100
trapv: .opd 0,@047166
tst: .opd 24,@045000
unlk: .opd 13,@047130
.end

View File

@@ -0,0 +1,454 @@
/*
Copyright 1981
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "machine.h"
#include "ctype.h"
#ifdef PDP11
struct {
char lobyte;
char hibyte;
};
struct {
char *ptrw1;
char *ptrw2;
};
struct {
int wd1;
int wd2;
};
struct {
int swd1;
};
#endif
#ifdef MC68000
struct {
char hibyte;
char lobyte;
};
struct {
char *ptrw2;
};
struct {
int wd1;
int wd2;
};
struct {
int swd1;
};
#endif
#ifdef VAX
struct {
short wd2;
short wd1;
};
struct {
short swd1;
};
struct {
char lobyte;
char hibyte;
};
struct {
char *ptrw2;
};
#endif
/* format of a symbol entry in the main table*/
# define NAMELEN 8 /*length of name in symbol table*/
struct symtab {
char name[NAMELEN]; /*symbol name*/
int flags; /*bit flags*/
char *tlnk; /*table link*/
long vl1; /*symbol value*/
};
struct symtab *symtptr;
# define STESIZE (sizeof *symtptr) /*byte length of symbol table entry*/
/* flags for symbols*/
# define SYDF 0100000 /*defined*/
# define SYEQ 0040000 /*equated*/
# define SYGL 0020000 /*global - entry or external*/
# define SYER 0010000 /*equated register*/
# define SYXR 0004000 /*external reference*/
# define SYRA 0002000 /*DATA based relocatable*/
# define SYRO 0001000 /*TEXT based relocatable*/
# define SYBS 0000400 /*BSS based relocatable*/
# define SYIN 0000200 /*internal symbol -- opcode, directive or equ*/
# define SYPC 0000100 /*[vlh]equated using star '*' expression*/
# define SYRM 0000040 /*[vlh]register mask equate*/
/*flags for opcodes and directives*/
# define OPDR 0100000 /*0=>opcode, 1=>directive*/
# define OPFF 037 /*type of instruction (used as mask)*/
struct irts {
char *irle; /*ptr to last entry in chain*/
char *irfe; /*ptr to first entry in chain*/
};
long stlen; /*length of symbol table*/
/*
* intermediate text file
* format of the intermediate text for one statement:
*
* ******************************************************
* * it type = ITBS * # it entries * 0
* ******************************************************
* * absolute line number (long) *
* ******************************************************
* * it type = ITSY * instr length * 1
* ******************************************************
* * symbol table pointer for stmt label (long) *
* ******************************************************
* * it type = ITSY * instr mode length * 2
* ******************************************************
* * opcode ptr (long) *
* ******************************************************
* * it type = ITCN * relocation base * 3
* ******************************************************
* * location counter (pass 1) *
* ******************************************************
* * it type * relocation flag * 4 - oprnds
* ******************************************************
* * value (long) *
* ******************************************************
* .
* .
* .
* ******************************************************
* * it type * relocation flag * n - oprnds
* ******************************************************
* * value (long) *
* ******************************************************
*/
#define ITOP1 4 /*first it entry for operands*/
/*
* it type meaning
* 0 beginning of statement
* 1 value is pointer to symbol table
* 2 value is a constant
* 3 value is a specal char
*
* relocation flag for opcode it entry is operand length:
* 'b' => byte
* 'w' => word
* 'l' => long
*/
struct it {
char itty; /*it type*/
char itrl; /*relocation flag or # it entries*/
long itop;
};
int mode=0; /*operand mode (byte, word, long)*/
int modelen=0; /*operand length per mode*/
#define BYTE 'b'
#define WORD 'w'
#define LONG 'l'
/* parameters that define the main table*/
#define SZMT 300 /*initial size of the main table */
/*must be large enough to initialize*/
#ifdef PDP11
#define ICRSZMT 10 /*add to main table when run out*/
#else
#define ICRSZMT 50 /*add to main table when run out*/
#endif
int cszmt=0; /*current size of main table*/
char *bmte=0; /*beginning of main table*/
char *emte=0; /*end of main table*/
/* intermediate text types*/
#define ITBS 0 /*beginning of statement*/
#define ITSY 1 /*pointer to symbol table*/
#define ITCN 2 /*constant*/
#define ITSP 3 /*special*/
#define ITRM 4 /*[vlh]register mask!*/
#define ITPC 5 /*[vlh]pc relative argument*/
# define ITBSZ 256 /*size of the it buffer*/
int itbuf[ITBSZ]={0}; /*it buffer*/
#define STMAX 200 /*size of intermediate text buffer*/
struct it stbuf[STMAX]={0}; /*holds it for one statement*/
char sbuf[512]={0}; /*holds one block of source*/
/*initial reference table for symbols*/
# define SZIRT 128
char *sirt[SZIRT]={0};
/*initial reference table to opcodes*/
char *oirt[SZIRT]={0};
/*external symbol table*/
#define EXTSZ 512
char *extbl[EXTSZ]={0};
int extindx=0; /*index to external symbol table*/
char **pexti=0; /*ptr to external symbol table*/
int absln=0; /*absolute line number*/
int p2absln=0; /*pass 2 line number*/
int fcflg=0; /*0=>passed an item. 1=>first char*/
int fchr=0; /*first char in term*/
int ifn=0; /*source file descriptor*/
int *pitix=0; /*ptr to it buffer*/
int itwc=0; /*number of words in it buffer*/
struct it *pitw=0; /*ptr to it buffer next entry*/
int itype=0; /*type of item*/
long ival=0; /*value of item*/
char *lblpt=0; /*label pointer*/
char lbt[NAMELEN]={0}; /*holds label name*/
char *lmte=0; /*last entry in main table*/
long loctr=0; /*location counter*/
long savelc[4]={0}; /*save relocation counters for 3 bases*/
int nite=0; /*number of entries in stbuf*/
struct it *pnite=0;
int lfn=0; /*loader output file descriptor*/
char *opcpt=0; /*pointer to opcode entry in main table*/
int p2flg=0; /*0=>pass 1 1=>pass 2*/
char **pirt=0; /*entry in initial reference table*/
int reloc=0; /*relocation value returned by expression evaluator (expr)*/
int rlflg=0; /*relocation value of current location counter*/
/*relocation values*/
# define ABS 0 /*absolute*/
# define DATA 1
# define TEXT 2
# define BSS 3
# define EXTRN 4 /*externally defined*/
#define EOLC '\n' /*end of line character*/
#define EOF 0 /*end of file indicator*/
#define NULL 0 /* [vlh] character null '\0' */
#define TRUE 1 /* [vlh] boolean values */
#define FALSE 0 /* [vlh] boolean values */
int format=0;
int sbuflen=0; /*number of chars in sbuf*/
char *psbuf=0; /*ptr into sbuf*/
int itfn=0; /*it file number*/
char itfnc=0; /*last char of it file name*/
int trbfn=0; /*temp for text relocation bits*/
char trbfnc=0; /*last char of text rb file*/
int dafn=0; /*file for data stuff*/
char dafnc=0; /*last char of data file*/
int drbfn=0; /*file for data relocation bits*/
char drbfnc=0; /*last char*/
int prtflg=0; /*print output flag*/
int undflg=0; /*make undefined symbols external flag*/
int starmul=0; /* * is multiply operator*/
char *endptr=0, *addptr=0;
char *orgptr=0;
char *subptr=0, *addiptr=0, *addqptr=0, *subiptr=0, *subqptr=0;
char *cmpptr=0, *addaptr=0, *cmpaptr=0, *subaptr=0, *cmpmptr=0;
char *equptr=0;
char *andptr=0, *andiptr=0, *eorptr=0, *eoriptr=0, *orptr=0, *oriptr=0;
char *cmpiptr=0;
char *moveptr=0, *moveqptr=0;
char *exgptr=0;
char *evenptr=0;
char *jsrptr=0, *bsrptr=0, *nopptr=0;
char peekc=0;
int numcon[2]=0, numsym[2]=0, indir[2]=0, immed[2]=0, numreg[2]=0;
int plevel=0; /*parenthesis level counter*/
int opdix=0; /*operand index counter*/
int p1inlen=0; /*pass 1 instr length*/
int instrlen=0; /*pass 2 bytes in current instruction*/
/* effective address mode bits*/
#define DDIR 000
#define ADIR 010
#define INDIRECT 020
#define INDINC 030
#define DECIND 040
#define INDDISP 050
#define INDINX 060
#define SADDR 070
#define LADDR 071
#define IMM 074
#define AREGLO 8
#define AREGHI 15
/* relocation bit definitions:*/
#define RBMASK 07 /*tells type of relocation*/
#define INSABS 7 /*first word of instr -- absolute*/
#define DABS 0 /*data word absolute*/
#define TRELOC 2 /* TEXT relocatable*/
#define DRELOC 1 /* DATA relocatable*/
#define BRELOC 3 /* BSS relocatable*/
#define EXTVAR 4 /* ref to external variable*/
#define LUPPER 5 /* upper word of long*/
#define EXTREL 6 /* external relative mode*/
/* ptrs to ins[] and rlbits[]*/
int *pins=0;
int *prlb=0;
int ins[5]={0}; /*holds instruction words*/
#define PRTCHLEN 128
char prtchars[PRTCHLEN]={0}; /*line buffer for putchar*/
char *prtchidx=0; /*index for putchar*/
int extflg=0, extref=0; /*external in expr*/
#define CCR 16
#define SR 17
#define USP 18
#define MOVECCR 042300
#define MOVESR 043300
#define SRMOVE 040300
#define MOVEUSP 047140
struct op {
int ea; /* effective address bits*/
int len; /* effective address length in bytes*/
long con; /*constant or reloc part of operand*/
int drlc; /*reloc of con*/
int ext; /*external variable #*/
int idx; /*index register if any*/
int xmod; /*mode of index reg*/
} opnd[2]={0};
#define OPSTLEN 10
#define TREELEN 20
struct buf{
int fildes;
int nunused;
char *xfree;
char buff[512];
};
struct buf lbuf={0};
struct buf tbuf={0};
struct buf dabuf={0};
struct buf drbuf={0};
int nerror=0; /*# of assembler errors*/
int in_err=0; /*[vlh] don't generate instrlen err if already err state*/
int shortadr=0; /*short addresses if set*/
#define CLRFOR 24
#define CLRVAL 041000
long itoffset=0;
#define LASTCHTFN tfilname[11]
#define PC 22
int equflg=0; /*doing an equate stmt*/
#define ANDI 01000
#define AND 0140000
#define ORI 0
#define OR 0100000
#define EORI 05000
#define EOR 0130000
#define MOVE 0
long lseek();
char *sbrk();
char *lemt();
int refpc=0; /* * referenced in expr*/
#define SOH 1
/* Conditional Assembly variables and constants [vlh] */
#define LOW_CA 21 /* [vlh] */
#define HI_CA 30 /* [vlh] */
int ca_true=0; /* true unless in a false CA*/
int ca=0; /* depth of conditional assembly, none = 0*/
int ca_level=0; /* at what CA depth did CA go false?*/
/* pass 1 global variables */
int numops=0; /*number of operands*/
int inoffset=0; /*[vlh]offset directive*/
int didorg=0;
int initflg=0; /*initialize flag*/
/* defines */
#define igblk() while(fchr==' ') fchr=gchr()
#define ckein() ((pitw >= pnite))
/* is it an alterable operand */
#define memalt(ap) (memea(ap) && altea(ap))
#define dataalt(ap) (dataea(ap) && altea(ap))
#define altea(ap) ((((ap)->ea&070)!=SADDR || ((ap)->ea&6)==0))
/* is it the specific type of operand */
#define memea(ap) (((ap)->ea&070) >= INDIRECT)
#define dataea(ap) (((ap)->ea&070) != ADIR)
#define pcea(ap) ((ap)->ea==072 || (ap)->ea==073)
#define ckdreg(ap) ((ap)->ea>=0 && (ap)->ea<AREGLO)
#define ckareg(ap) ((ap)->ea>=AREGLO && (ap)->ea<=AREGHI)
/*
* DRI Listing Hacks:
*/
char *sfname=0; /* -> Source filename */
int xline=0; /* Current line number */
int xpage=0; /* Current page number */
/*
* More Initializations:
*/
char *tfilname[80] = {0}; /* Temp filename area */
char *initfnam[80] = {0}; /* Init filename area */
struct it exitm={0};
int prcnt=0;
int rval=0;
int lpflg=0;
int lastopr=0;
int rlbits[5]={0};
int pline=0;
int prsp=0;
int amode=0;
long stlen=0;
int udfct=0;
int errno=0;
int nitleft=0;
int hibytflg[4]={0};
int hibytw[4]={0};
struct it *piop=0;
struct it *pitr=0;
struct it opstk[OPSTLEN]={0};
struct it tree[TREELEN]={0};
int chmvq=0;
int explmod=0;
int ftudp=0;
int iop=0;
int itr=0;
char ldfn[40]={0};
int opcval=0;
int poslab=0;
int symcon=0;
char *tfilptr=0;
int tlab1=0;
#define HDSIZE (sizeof couthd) /**.o file header size*/
struct hdr {
short ch_magic; /*c.out magic number 060016 = $600E*/
long ch_tsize; /*text size*/
long ch_dsize; /*data size*/
long ch_bsize; /*bss size*/
long ch_ssize; /*symbol table size*/
long ch_stksize; /*stack size*/
long ch_entry; /*entry point*/
short ch_rlbflg; /*relocation bits suppressed flag*/
} couthd={0};
#define MAGIC 0x601a /* bra .+26 instruction*/

View File

@@ -0,0 +1,462 @@
1File: AS68INIT.C Page 1
1 /*
2 Copyright 1981
3 Alcyon Corporation
4 8716 Production Ave.
5 San Diego, Ca. 92121
6 */
7
8 #include "machine.h"
9 #include "ctype.h"
10
11 #ifdef PDP11
12 struct {
13 char lobyte;
14 char hibyte;
15 };
16 struct {
17 char *ptrw1;
18 char *ptrw2;
19 };
20 struct {
21 int wd1;
22 int wd2;
23 };
24 struct {
25 int swd1;
26 };
27 #endif
28
29 #ifdef MC68000
30 struct {
31 char hibyte;
32 char lobyte;
33 };
34 struct {
35 char *ptrw2;
36 };
37 struct {
38 int wd1;
39 int wd2;
40 };
41 struct {
42 int swd1;
43 };
44 #endif
45
46 #ifdef VAX
47 struct {
48 short wd2;
49 short wd1;
50 };
51 struct {
52 short swd1;
53 };
54
55 struct {
56 char lobyte;
57 char hibyte;
58 };
59 struct {
1File: AS68INIT.C Page 2
60 char *ptrw2;
61 };
62 #endif
63
64 /* format of a symbol entry in the main table*/
65
66 # define NAMELEN 8 /*length of name in symbol table*/
67 struct symtab {
68 char name[NAMELEN]; /*symbol name*/
69 int flags; /*bit flags*/
70 char *tlnk; /*table link*/
71 long vl1; /*symbol value*/
72 };
73
74 struct symtab *symtptr;
75 # define STESIZE (sizeof *symtptr) /*byte length of symbol table entry*/
76
77 /* flags for symbols*/
78 # define SYDF 0100000 /*defined*/
79 # define SYEQ 0040000 /*equated*/
80 # define SYGL 0020000 /*global - entry or external*/
81 # define SYER 0010000 /*equated register*/
82 # define SYXR 0004000 /*external reference*/
83 # define SYRA 0002000 /*DATA based relocatable*/
84 # define SYRO 0001000 /*TEXT based relocatable*/
85 # define SYBS 0000400 /*BSS based relocatable*/
86 # define SYIN 0000200 /*internal symbol -- opcode, directive or equ*/
87 # define SYPC 0000100 /*[vlh]equated using star '*' expression*/
88 # define SYRM 0000040 /*[vlh]register mask equate*/
89
90 /*flags for opcodes and directives*/
91 # define OPDR 0100000 /*0=>opcode, 1=>directive*/
92 # define OPFF 037 /*type of instruction (used as mask)*/
93
94 struct irts {
95 char *irle; /*ptr to last entry in chain*/
96 char *irfe; /*ptr to first entry in chain*/
97 };
98
99 long stlen; /*length of symbol table*/
100
101 /*
102 * intermediate text file
103 * format of the intermediate text for one statement:
104 *
105 * ******************************************************
106 * * it type = ITBS * # it entries * 0
107 * ******************************************************
108 * * absolute line number (long) *
109 * ******************************************************
110 * * it type = ITSY * instr length * 1
111 * ******************************************************
112 * * symbol table pointer for stmt label (long) *
113 * ******************************************************
114 * * it type = ITSY * instr mode length * 2
115 * ******************************************************
116 * * opcode ptr (long) *
117 * ******************************************************
118 * * it type = ITCN * relocation base * 3
1File: AS68INIT.C Page 3
119 * ******************************************************
120 * * location counter (pass 1) *
121 * ******************************************************
122 * * it type * relocation flag * 4 - oprnds
123 * ******************************************************
124 * * value (long) *
125 * ******************************************************
126 * .
127 * .
128 * .
129 * ******************************************************
130 * * it type * relocation flag * n - oprnds
131 * ******************************************************
132 * * value (long) *
133 * ******************************************************
134 */
135
136 #define ITOP1 4 /*first it entry for operands*/
137
138 /*
139 * it type meaning
140 * 0 beginning of statement
141 * 1 value is pointer to symbol table
142 * 2 value is a constant
143 * 3 value is a specal char
144 *
145 * relocation flag for opcode it entry is operand length:
146 * 'b' => byte
147 * 'w' => word
148 * 'l' => long
149 */
150
151 struct it {
152 char itty; /*it type*/
153 char itrl; /*relocation flag or # it entries*/
154 long itop;
155 };
156
157 int mode=0; /*operand mode (byte, word, long)*/
158 int modelen=0; /*operand length per mode*/
159 #define BYTE 'b'
160 #define WORD 'w'
161 #define LONG 'l'
162
163 /* parameters that define the main table*/
164 #define SZMT 300 /*initial size of the main table */
165 /*must be large enough to initialize*/
166 #ifdef PDP11
167 #define ICRSZMT 10 /*add to main table when run out*/
168 #else
169 #define ICRSZMT 50 /*add to main table when run out*/
170 #endif
171 int cszmt=0; /*current size of main table*/
172 char *bmte=0; /*beginning of main table*/
173 char *emte=0; /*end of main table*/
174
175 /* intermediate text types*/
176 #define ITBS 0 /*beginning of statement*/
177 #define ITSY 1 /*pointer to symbol table*/
1File: AS68INIT.C Page 4
178 #define ITCN 2 /*constant*/
179 #define ITSP 3 /*special*/
180 #define ITRM 4 /*[vlh]register mask!*/
181 #define ITPC 5 /*[vlh]pc relative argument*/
182
183 # define ITBSZ 256 /*size of the it buffer*/
184 int itbuf[ITBSZ]={0}; /*it buffer*/
185
186 #define STMAX 200 /*size of intermediate text buffer*/
187 struct it stbuf[STMAX]={0}; /*holds it for one statement*/
188
189 char sbuf[512]={0}; /*holds one block of source*/
190
191 /*initial reference table for symbols*/
192 # define SZIRT 128
193 char *sirt[SZIRT]={0};
194
195 /*initial reference table to opcodes*/
196 char *oirt[SZIRT]={0};
197
198 /*external symbol table*/
199 #define EXTSZ 512
200 char *extbl[EXTSZ]={0};
201 int extindx=0; /*index to external symbol table*/
202 char **pexti=0; /*ptr to external symbol table*/
203
204 int absln=0; /*absolute line number*/
205 int p2absln=0; /*pass 2 line number*/
206 int fcflg=0; /*0=>passed an item. 1=>first char*/
207 int fchr=0; /*first char in term*/
208 int ifn=0; /*source file descriptor*/
209 int *pitix=0; /*ptr to it buffer*/
210 int itwc=0; /*number of words in it buffer*/
211 struct it *pitw=0; /*ptr to it buffer next entry*/
212 int itype=0; /*type of item*/
213 long ival=0; /*value of item*/
214 char *lblpt=0; /*label pointer*/
215 char lbt[NAMELEN]={0}; /*holds label name*/
216 char *lmte=0; /*last entry in main table*/
217 long loctr=0; /*location counter*/
218 long savelc[4]={0}; /*save relocation counters for 3 bases*/
219 int nite=0; /*number of entries in stbuf*/
220 struct it *pnite=0;
221 int lfn=0; /*loader output file descriptor*/
222 char *opcpt=0; /*pointer to opcode entry in main table*/
223 int p2flg=0; /*0=>pass 1 1=>pass 2*/
224 char **pirt=0; /*entry in initial reference table*/
225 int reloc=0; /*relocation value returned by expression evaluator (expr)*/
226 int rlflg=0; /*relocation value of current location counter*/
227 /*relocation values*/
228 # define ABS 0 /*absolute*/
229 # define DATA 1
230 # define TEXT 2
231 # define BSS 3
232 # define EXTRN 4 /*externally defined*/
233
234 #define EOLC '\n' /*end of line character*/
235 #define EOF 0 /*end of file indicator*/
236 #define NULL 0 /* [vlh] character null '\0' */
1File: AS68INIT.C Page 5
237 #define TRUE 1 /* [vlh] boolean values */
238 #define FALSE 0 /* [vlh] boolean values */
239
240 int format=0;
241 int sbuflen=0; /*number of chars in sbuf*/
242 char *psbuf=0; /*ptr into sbuf*/
243 int itfn=0; /*it file number*/
244 char itfnc=0; /*last char of it file name*/
245 int trbfn=0; /*temp for text relocation bits*/
246 char trbfnc=0; /*last char of text rb file*/
247 int dafn=0; /*file for data stuff*/
248 char dafnc=0; /*last char of data file*/
249 int drbfn=0; /*file for data relocation bits*/
250 char drbfnc=0; /*last char*/
251 int prtflg=0; /*print output flag*/
252 int undflg=0; /*make undefined symbols external flag*/
253
254 int starmul=0; /* * is multiply operator*/
255
256 char *endptr=0, *addptr=0;
257 char *orgptr=0;
258 char *subptr=0, *addiptr=0, *addqptr=0, *subiptr=0, *subqptr=0;
259 char *cmpptr=0, *addaptr=0, *cmpaptr=0, *subaptr=0, *cmpmptr=0;
260 char *equptr=0;
261 char *andptr=0, *andiptr=0, *eorptr=0, *eoriptr=0, *orptr=0, *oriptr=0;
262 char *cmpiptr=0;
263 char *moveptr=0, *moveqptr=0;
264 char *exgptr=0;
265 char *evenptr=0;
266 char *jsrptr=0, *bsrptr=0, *nopptr=0;
267
268 char peekc=0;
269 int numcon[2]=0, numsym[2]=0, indir[2]=0, immed[2]=0, numreg[2]=0;
270 int plevel=0; /*parenthesis level counter*/
271 int opdix=0; /*operand index counter*/
272 int p1inlen=0; /*pass 1 instr length*/
273 int instrlen=0; /*pass 2 bytes in current instruction*/
274
275 /* effective address mode bits*/
276 #define DDIR 000
277 #define ADIR 010
278 #define INDIRECT 020
279 #define INDINC 030
280 #define DECIND 040
281 #define INDDISP 050
282 #define INDINX 060
283 #define SADDR 070
284 #define LADDR 071
285 #define IMM 074
286
287 #define AREGLO 8
288 #define AREGHI 15
289
290 /* relocation bit definitions:*/
291 #define RBMASK 07 /*tells type of relocation*/
292 #define INSABS 7 /*first word of instr -- absolute*/
293 #define DABS 0 /*data word absolute*/
294 #define TRELOC 2 /* TEXT relocatable*/
295 #define DRELOC 1 /* DATA relocatable*/
1File: AS68INIT.C Page 6
296 #define BRELOC 3 /* BSS relocatable*/
297 #define EXTVAR 4 /* ref to external variable*/
298 #define LUPPER 5 /* upper word of long*/
299 #define EXTREL 6 /* external relative mode*/
300
301 /* ptrs to ins[] and rlbits[]*/
302 int *pins=0;
303 int *prlb=0;
304 int ins[5]={0}; /*holds instruction words*/
305
306 #define PRTCHLEN 128
307 char prtchars[PRTCHLEN]={0}; /*line buffer for putchar*/
308 char *prtchidx=0; /*index for putchar*/
309
310 int extflg=0, extref=0; /*external in expr*/
311
312 #define CCR 16
313 #define SR 17
314 #define USP 18
315 #define MOVECCR 042300
316 #define MOVESR 043300
317 #define SRMOVE 040300
318 #define MOVEUSP 047140
319
320 struct op {
321 int ea; /* effective address bits*/
322 int len; /* effective address length in bytes*/
323 long con; /*constant or reloc part of operand*/
324 int drlc; /*reloc of con*/
325 int ext; /*external variable #*/
326 int idx; /*index register if any*/
327 int xmod; /*mode of index reg*/
328 } opnd[2]={0};
329 #define OPSTLEN 10
330 #define TREELEN 20
331 struct buf{
332 int fildes;
333 int nunused;
334 char *xfree;
335 char buff[512];
336 };
337
338 struct buf lbuf={0};
339 struct buf tbuf={0};
340 struct buf dabuf={0};
341 struct buf drbuf={0};
342
343 int nerror=0; /*# of assembler errors*/
344 int in_err=0; /*[vlh] don't generate instrlen err if already err state*/
345 int shortadr=0; /*short addresses if set*/
346
347 #define CLRFOR 24
348 #define CLRVAL 041000
349
350 long itoffset=0;
351
352 #define LASTCHTFN tfilname[11]
353 #define PC 22
354
1File: AS68INIT.C Page 7
355 int equflg=0; /*doing an equate stmt*/
356
357 #define ANDI 01000
358 #define AND 0140000
359 #define ORI 0
360 #define OR 0100000
361 #define EORI 05000
362 #define EOR 0130000
363 #define MOVE 0
364
365 long lseek();
366 char *sbrk();
367 char *lemt();
368
369 int refpc=0; /* * referenced in expr*/
370 #define SOH 1
371
372 /* Conditional Assembly variables and constants [vlh] */
373 #define LOW_CA 21 /* [vlh] */
374 #define HI_CA 30 /* [vlh] */
375
376 int ca_true=0; /* true unless in a false CA*/
377 int ca=0; /* depth of conditional assembly, none = 0*/
378 int ca_level=0; /* at what CA depth did CA go false?*/
379
380 /* pass 1 global variables */
381 int numops=0; /*number of operands*/
382 int inoffset=0; /*[vlh]offset directive*/
383 int didorg=0;
384 int initflg=0; /*initialize flag*/
385
386 /* defines */
387 #define igblk() while(fchr==' ') fchr=gchr()
388 #define ckein() ((pitw >= pnite))
389
390 /* is it an alterable operand */
391 #define memalt(ap) (memea(ap) && altea(ap))
392 #define dataalt(ap) (dataea(ap) && altea(ap))
393 #define altea(ap) ((((ap)->ea&070)!=SADDR || ((ap)->ea&6)==0))
394
395 /* is it the specific type of operand */
396 #define memea(ap) (((ap)->ea&070) >= INDIRECT)
397 #define dataea(ap) (((ap)->ea&070) != ADIR)
398 #define pcea(ap) ((ap)->ea==072 || (ap)->ea==073)
399 #define ckdreg(ap) ((ap)->ea>=0 && (ap)->ea<AREGLO)
400 #define ckareg(ap) ((ap)->ea>=AREGLO && (ap)->ea<=AREGHI)
401 /*
402 * DRI Listing Hacks:
403 */
404 char *sfname=0; /* -> Source filename */
405 int xline=0; /* Current line number */
406 int xpage=0; /* Current page number */
407 /*
408 * More Initializations:
409 */
410 char *tfilname[80] = {0}; /* Temp filename area */
411 char *initfnam[80] = {0}; /* Init filename area */
412 struct it exitm={0};
413 int prcnt=0;
1File: AS68INIT.C Page 8
414 int rval=0;
415 int lpflg=0;
416 int lastopr=0;
417 int rlbits[5]={0};
418 int pline=0;
419 int prsp=0;
420 int amode=0;
421 long stlen=0;
422 int udfct=0;
423 int errno=0;
424 int nitleft=0;
425 int hibytflg[4]={0};
426 int hibytw[4]={0};
427 struct it *piop=0;
428 struct it *pitr=0;
429 struct it opstk[OPSTLEN]={0};
430 struct it tree[TREELEN]={0};
431 int chmvq=0;
432 int explmod=0;
433 int ftudp=0;
434 int iop=0;
435 int itr=0;
436 char ldfn[40]={0};
437 int opcval=0;
438 int poslab=0;
439 int symcon=0;
440 char *tfilptr=0;
441 int tlab1=0;
442 #define HDSIZE (sizeof couthd) /**.o file header size*/
443 struct hdr {
444 short ch_magic; /*c.out magic number 060016 = $600E*/
445 long ch_tsize; /*text size*/
446 long ch_dsize; /*data size*/
447 long ch_bsize; /*bss size*/
448 long ch_ssize; /*symbol table size*/
449 long ch_stksize; /*stack size*/
450 long ch_entry; /*entry point*/
451 short ch_rlbflg; /*relocation bits suppressed flag*/
452 } couthd={0};
453
454 #define MAGIC 0x601a /* bra .+26 instruction*/

View File

@@ -0,0 +1,13 @@
#define HDSIZE (sizeof couthd) /**.o file header size*/
struct hdr {
short ch_magic; /*c.out magic number 060016 = $600E*/
long ch_tsize; /*text size*/
long ch_dsize; /*data size*/
long ch_bsize; /*bss size*/
long ch_ssize; /*symbol table size*/
long ch_stksize; /*stack size*/
long ch_entry; /*entry point*/
short ch_rlbflg; /*relocation bits suppressed flag*/
} couthd;
#define MAGIC 0x601a /* bra .+26 instruction*/

View File

@@ -0,0 +1,14 @@
1File: COUT.H Page 1
1 #define HDSIZE (sizeof couthd) /**.o file header size*/
2 struct hdr {
3 short ch_magic; /*c.out magic number 060016 = $600E*/
4 long ch_tsize; /*text size*/
5 long ch_dsize; /*data size*/
6 long ch_bsize; /*bss size*/
7 long ch_ssize; /*symbol table size*/
8 long ch_stksize; /*stack size*/
9 long ch_entry; /*entry point*/
10 short ch_rlbflg; /*relocation bits suppressed flag*/
11 } couthd;
12
13 #define MAGIC 0x601a /* bra .+26 instruction*/

View File

@@ -0,0 +1,36 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
/*char *version "@(#)ctype - Aug 13, 1982";
Standard routines... */
#define isspace(c) ((c)==32 || (c)==9 || (c)==13 || (c)==10 ||(c)==12)
#define isupper(c) ((c)<='Z' && (c)>='A')
#define islower(c) ((c)<='z' && (c)>='a')
#define isalpha(c) (isupper((c)) || islower((c)))
#define isdigit(c) ((c)<='9' && (c)>='0')
#define isascii(c) ((c) < 0200 && (c) >= 0)
#define isalnum(c) (isalpha((c)) || isdigit((c)))
#define iscntrl(c) (((c) < 040 || (c) == 0177) && isascii((c)))
#define isprint(c) ((c) >= 040 && (c) < 0177)
#define ispunct(c) (!isalnum((c)) && isprint(c))
#define toupper(c) (islower((c)) ? (c) & ~32 : (c))
#define tolower(c) (isupper((c)) ? (c) | 32 : (c))
#define toascii(c) ((c) & 0177)

View File

@@ -0,0 +1,37 @@
1File: CTYPE.H Page 1
1 /*
2 Copyright 1982
3 Alcyon Corporation
4 8716 Production Ave.
5 San Diego, Ca. 92121
6 */
7
8 /*char *version "@(#)ctype - Aug 13, 1982";
9
10 Standard routines... */
11
12 #define isspace(c) ((c)==32 || (c)==9 || (c)==13 || (c)==10 ||(c)==12)
13
14 #define isupper(c) ((c)<='Z' && (c)>='A')
15
16 #define islower(c) ((c)<='z' && (c)>='a')
17
18 #define isalpha(c) (isupper((c)) || islower((c)))
19
20 #define isdigit(c) ((c)<='9' && (c)>='0')
21
22 #define isascii(c) ((c) < 0200 && (c) >= 0)
23
24 #define isalnum(c) (isalpha((c)) || isdigit((c)))
25
26 #define iscntrl(c) (((c) < 040 || (c) == 0177) && isascii((c)))
27
28 #define isprint(c) ((c) >= 040 && (c) < 0177)
29
30 #define ispunct(c) (!isalnum((c)) && isprint(c))
31
32 #define toupper(c) (islower((c)) ? (c) & ~32 : (c))
33
34 #define tolower(c) (isupper((c)) ? (c) | 32 : (c))
35
36 #define toascii(c) ((c) & 0177)

View File

@@ -0,0 +1,934 @@
/*
Copyright 1981
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
/* Pass 1 and pass 2 directive handling routines */
/* code to handle conditional assembly directives */
#include "as68.h"
#include "cout.h"
long lseek();
int p1gi();
int p2gi();
int igrst();
/*directive to define an opcode*/
hopd()
{
if(!lbt[0]) {
xerr(4); /*no label*/
return;
}
setname(); /*move label into main table*/
if((lblpt=lemt(oirt,TRUE))!=lmte) {
xerr(5); /*opcode redefined*/
return;
}
mmte(); /*make main table entry*/
expr(&p1gi); /*get instruction format*/
if(itype!=ITCN || ival<0 || ival>OPFF) {
xerr(18); /*illegal format specifier*/
return;
}
lblpt->flags =| ival|SYIN; /*remember format*/
if(fchr != ',') { /*field separator*/
xerr(10);
return;
}
expr(&p1gi); /*get opcode value*/
if(itype != ITCN) {
xerr(17); /*not a constant*/
return;
}
lblpt->vl1 = ival; /*put value in main table*/
igrst(); /*ignore rest of statement-comment*/
}
/* equate directive*/
hequ()
{
if(lbt[0] == 0) {
xerr(4); /*no label*/
return;
}
setname();
if((lblpt=lemt(sirt,FALSE))!=lmte) { /*aready there*/
if(lbt[0] == '~') { /*local symbol*/
lblpt = lmte;
mmte();
}
}
else
mmte();
if(lblpt->flags&SYXR) {
xerr(29);
return;
}
lblpt->flags =| SYDF|SYEQ; /*defined & equate*/
equflg = 1;
modelen = 4;
expr(&p1gi);
equflg = 0;
if(itype == ITSY && ival.ptrw2->flags&SYER) {
lblpt->flags =| SYER; /*equated register*/
ival = ival.ptrw2->vl1;
}
else if(itype != ITCN) {
xerr(7); /*not a constant*/
return;
}
if (inoffset && reloc != ABS) { /* [vlh] */
xerr(11);
return;
}
if(initflg) /*doing symbol table initialization*/
lblpt->flags =| SYIN; /*internal symbol*/
lblpt->vl1 = ival;
if(reloc == DATA) /*check relocation*/
{
lblpt->flags =| SYRA; /*DATA relocatable*/
}
else if(reloc == TEXT)
lblpt->flags =| SYRO; /*TEXT relocatable*/
else if(reloc == BSS)
lblpt->flags =| SYBS; /*BSS relocatable*/
else if(fchr==',' && (fchr=gchr())=='r')
lblpt->flags =| SYER; /*equated register*/
if (refpc) /*[vlh] flag directive is pc relative */
lblpt->flags =| SYPC;
igrst();
}
/* process dsect directive*/
hdsect()
{
dorlst(DATA);
}
dorlst(xrtyp)
{
inoffset = 0; /* [vlh] offset mode terminated my sect directive */
chkeven(); /* May need to make pc even */
dlabl(); /*define label on old base if there is one*/
savelc[rlflg] = loctr; /*save old base relocation*/
rlflg = xrtyp;
loctr = savelc[xrtyp]; /*set new base relocation ctr*/
opitb();
stbuf[0].itrl = itwc;
wostb();
igrst();
}
/*process psect directive*/
hpsect()
{
dorlst(TEXT);
}
hbss()
{
dorlst(BSS);
}
/*make pc even*/
heven()
{
modelen = 2; /*Try to figure this one out...*/
if(loctr&1) { /*have to make it even*/
dorlst(rlflg);
}
else {
igrst();
}
}
/*process globl directive*/
hent()
{
while(1) {
gterm(TRUE); /*get entry symbol*/
if(itype!=ITSY) { /*error if not symbol*/
xerr(28);
return;
}
if((lblpt=lemt(sirt,FALSE)) == lmte) /*look up in main table*/
mmte(); /*not there, make new entry*/
else
if(lblpt->flags&SYER) /*already there*/
uerr(29);
lblpt->flags =| SYGL; /*symbol is an entry*/
if(lblpt->flags&SYXR) { /*been thru hext code*/
lblpt->flags =& ~(SYXR|SYDF); /*reset for init of .comm*/
}
if (inoffset && reloc != ABS) { /* [vlh] */
xerr(11);
return;
}
if(fchr == ',') /*skip ',' between entries*/
fchr = gchr();
else {
igrst(); /*statement finished*/
return;
}
}
}
/*process comm directive*/
hext()
{
gterm(TRUE); /*get external symbol*/
if(itype!=ITSY) { /*error if not symbol*/
xerr(28);
return;
}
if((lblpt=lemt(sirt,FALSE)) == lmte) /*look up in main table*/
mmte(); /*not there, make new entry*/
else
if(lblpt->flags&SYDF && (lblpt->flags&SYXR)==0) /*already there*/
uerr(29);
lblpt->flags =| SYXR | SYDF; /*symbol is an external*/
mkextidx(lblpt); /*put into external table*/
if(fchr == ',') { /*skip ',' between operands*/
fchr = gchr();
gterm(TRUE);
if(itype != ITCN) {
xerr(17);
return;
}
lblpt->vl1.wd1 = ival; /* # bytes of storage required*/
}
else
lblpt->vl1.wd1 = 1; /* default # bytes*/
igrst();
}
mkextidx(p)
struct symtab *p;
{
if(extindx >= EXTSZ) { /*check for overflow of external symbol tbl*/
rpterr("overflow of external table\n");
endit();
}
p->vl1.wd2 = pexti - extbl; /* external symbol index #*/
*pexti++ = p; /*save external in external table*/
extindx++;
}
/* end statement*/
hend()
{
register short i;
register int j;
inoffset = 0; /*[vlh] turn off inoffset mode*/
lblpt = 0; /*no label*/
opitb(); /*output beginning of statement*/
igrst(); /* [vlh] ignore operands */
stbuf[0].itrl = itwc; /*number of it entries*/
wostb(); /*write out statement buffer*/
for(i=0; i<ITBSZ; i++)
doitwr(0);
if(initflg) {
putsymtab();
printf("68000 assembler initialized\n");
endit();
}
if((fchr=gchr())!=EOF) {
rpterr("end statement not at end of source\n");
}
savelc[rlflg] = loctr; /*last location on current reloc base*/
fixunds(); /*make golbals and maybe undefineds external*/
if(!didorg) /*did not assign to location counter*/
pass1a(); /*resolve short branches*/
pass2(); /*assembler pass 2*/
}
/* define storage given number of bytes*/
hds()
{
dlabl(); /*define label maybe*/
if (!inoffset) /* [vlh] */
opitb(); /*output it for beginning of statement*/
refpc = 0;
expr(&p1gi);
if(itype!=ITCN) {
xerr(17); /*must be constant*/
return;
}
if(reloc != ABS) {
xerr(9); /*must be absolute*/
return;
}
if (!inoffset) { /* [vlh] don't generate it if in offset */
opitoo(); /*output one operand*/
stbuf[0].itrl = itwc;
wostb(); /*write out statement buffer*/
loctr =+ (ival*modelen);
}
igrst();
}
/* make pc even if necessary for .dc and .ds */
chkeven()
{
register char *pi;
if(modelen>1 && loctr&1) {
pi = opcpt;
opcpt = evenptr;
opitb();
stbuf[0].itrl = itwc;
wostb();
opcpt = pi;
loctr++;
}
}
/* define byte directive*/
hdc()
{
chkeven();
hdata(modelen);
}
/*
* define bytes or words of data
* call with:
* 1 => defining bytes
* 2 => defining words
* 4 => defining long words
*/
hdata(mul)
{
dlabl(); /*define label*/
opitb(); /*beginning of statement*/
numops = 0; /*initialize count for number of operands*/
opito(); /*output it for operands*/
stbuf[0].itrl = itwc; /* # of it entries*/
wostb(); /*write out statement buffer*/
loctr =+ numops*mul; /* count by bytes or words*/
}
/* handle org statement*/
horg()
{
register i;
if(rlflg==TEXT && loctr!=0)
didorg++; /*can't do branch optimization as separate pass now*/
expr(&p1gi); /*value of new relocation counter*/
if(reloc != rlflg && reloc != ABS) {
xerr(27);
return;
}
if(ival < loctr) {
xerr(40); /*trying to go backwards*/
return;
}
opcpt = orgptr; /*org directive for pass 2*/
opitb();
opitoo();
stbuf[0].itrl = itwc;
wostb();
loctr = ival;
dlabl(); /*define label*/
}
/* Assemble for mask2 (R9M), ignore... */
hmask2() /* [vlh] */
{
igrst();
}
/* Define register list */
hreg() /* [vlh] */
{
int mask;
if(lbt[0]==0) {
xerr(4); /*no label*/
return;
}
setname(); /*move label into main table*/
if((lblpt=lemt(sirt,FALSE))!=lmte) {
xerr(5); /*opcode redefined*/
return;
}
if (inoffset)
if (reloc != ABS) {
xerr(11);
return;
}
mmte(); /*make main table entry*/
if ((mask = mkmask()) == -1) {
xerr(6);
return;
}
lblpt->flags =| SYDF|SYEQ|SYRM; /* register mask, defined & equated */
lblpt->vl1 = mask;
igrst();
}
int regmsk[] {0100000,040000,020000,010000,04000,02000,01000,0400,0200,
0100,040,020,010,4,2,1};
/* make a register mask for the reg routine */
mkmask() /* [vlh] */
{
register int *p, i, j, mask;
p = &regmsk; mask = 0;
while ((i = chkreg()) != -1) {
if (fchr == '-') {
fchr = gchr();
if ((j = chkreg()) == -1) {
xerr(40);
return(-1);
}
while (i <= j)
mask =| p[i++];
}
else mask =| p[i];
if (fchr != '/' && fchr != ',') break; /*[vlh] Signetics fix*/
fchr = gchr();
}
return(mask);
}
/* get a register # from file, return -1 if none or illegal */
chkreg() /* [vlh] */
{
register int i, j;
i = j = 0;
if (fchr == 'a' || fchr == 'A')
i = 8;
else if (fchr != 'd' && fchr != 'r' && fchr != 'D' && fchr != 'R')
return(-1);
fchr = gchr();
do {
j = (j*10) + (fchr - '0');
fchr = gchr();
} while (isdigit(fchr));
if (j < 0 || j > AREGHI) return(-1);
i =+ j;
if (i >= 0 && i <= AREGHI) return(i);
else return(-1);
}
/* Define constant block */
hdcb() /* [vlh] */
{
chkeven(); /* on even boundary if not byte block. */
dlabl(); /* define label... */
opitb();
opito();
stbuf[0].itrl = itwc;
numops = stbuf[ITOP1].itop;
loctr =+ numops * modelen;
wostb(); /* write out statement buffer */
}
/* Command line, similar to ds.b */
hcomline() /* [vlh] */
{
dlabl(); /*define label maybe*/
modelen = 1; /* byte store... */
opitb(); /*output it for beginning of statement*/
refpc = 0;
expr(&p1gi);
if(itype!=ITCN) {
xerr(17); /*must be constant*/
return;
}
if(reloc != ABS) {
xerr(9); /*must be absolute*/
return;
}
opitoo(); /*output one operand*/
stbuf[0].itrl = itwc;
wostb(); /*write out statement buffer*/
loctr =+ ival;
igrst();
}
/* Relocateable id record, ignore */
hidnt() /* [vlh] */
{
igrst();
}
/* Define offsets */
hoffset() /* [vlh] */
{
inoffset = 1;
expr(&p1gi); /* get new location counter */
if (itype != ITCN) {
xerr(17); /* constant required */
return;
}
if (reloc != ABS) {
xerr(9); /* must be absolute */
return;
}
loctr = ival;
igrst();
}
/* define sections: map to bss, text and data */
hsection() /* [vlh] */
{
inoffset = 0; /* reseting section turns off offset mode */
dlabl(); /* define label on old base if there is one */
savelc[rlflg] = loctr; /* save old base relocation */
opitb(); /* intermediate table... */
expr(&p1gi); /* get section # */
if (itype != ITCN) {
xerr(17); /* must be a constant */
return;
}
if (ival > 15 || ival < 0) {
xerr(9); /* proper range 0..15 */
return;
}
if (ival==14) rlflg = DATA;
else if (ival==15) rlflg = BSS;
else rlflg = TEXT;
loctr = savelc[rlflg];
stbuf[3].itop = loctr; /* pass 1 location counter */
stbuf[3].itrl = rlflg; /* relocation base */
stbuf[0].itrl = itwc;
wostb();
igrst();
}
/* hopt -- ignore, set up assembler options */
hopt() /* vlh */
{
igrst();
}
/**** Second pass directive handling routines ****/
/* second pass end statement*/
send()
{
register int i;
savelc[rlflg] = loctr;
if(savelc[TEXT]&1) {
rlflg = TEXT;
outbyte(0,DABS);
savelc[TEXT]++;
}
if(savelc[DATA]&1) {
rlflg = DATA;
outbyte(0,DABS);
savelc[DATA]++;
}
if(savelc[BSS]&1) {
savelc[BSS]++;
}
ival = 0;
reloc = ABS;
ckeop(9);
print(0);
cpdata(); /*copy data to loader file*/
osymt(); /*output symbol table*/
myfflush(&tbuf); /*flush text relocation bits*/
cprlbits(); /*copy relocation bits*/
myfflush(&lbuf);
i = (sizeof couthd.ch_magic) + 3*(sizeof couthd.ch_tsize);
if((lseek(lfn,(long)i,0) == -1) || write(lfn,&stlen,4) != 4)
rpterr("I/O error on loader output file\n");
endit(); /*end*/
}
/*second pass define storage - ds*/
sds()
{
print(0);
if(rlflg == TEXT || rlflg==DATA) {
expr(&p2gi);
if(itype != ITCN) {
uerr(13);
return;
}
ival =* modelen;
while(ival) {
outbyte(0,DABS);
loctr++;
ival--;
}
}
else
loctr =+ stbuf[ITOP1].itop*modelen; /*reserve storage*/
}
/* second pass - define block storage, initialized */
sdcb() /* [vlh] */
{
register int pfg, i, hflg, len;
expr(&p2gi);
if (itype != ITCN || reloc != ABS) {
uerr(13); /* must be absolute constant */
return;
}
len = ival;
expr(&p2gi);
if (modelen==1 && (ival<-128 || ival>=256 || reloc != ABS)) {
uerr(20);
ival = 0;
reloc = ABS;
}
while (len--) {
if (modelen==1) {
if (!hflg) {
ins[i].hibyte = ival;
outbyte(ival.wd2,DABS);
hflg++;
}
else {
ins[i++].lobyte = ival;
outbyte(ival.wd2,DABS);
hflg=0;
}
goto sdbl2;
}
else if (modelen==2) {
sdbl1:
ins[i++] = ival.wd2;
outword(ival.wd2, reloc);
sdbl2:
if (i>3) {
instrlen = i*2;
print ((pfg++) ? 2 : 1);
loctr =+ instrlen;
i=0;
}
}
else { /* long word... */
ins[i++] = ival.wd1;
outword(ival.wd1,LUPPER);
goto sdbl1;
}
}
if (i) { /* more printing */
instrlen = i*2 - hflg;
print ((pfg) ? 2 : 1);
loctr =+ instrlen;
}
}
/*second pass data*/
sdsect()
{
savelc[rlflg] = loctr;
rlflg = DATA;
loctr = savelc[DATA];
print(0); /*print the new location counter*/
}
/*second pass text*/
spsect()
{
savelc[rlflg] = loctr;
rlflg = TEXT;
loctr = savelc[TEXT];
print(0); /*print the new location counter*/
}
sbss()
{
savelc[rlflg] = loctr;
rlflg = BSS;
loctr = savelc[BSS];
print(0); /*print the new location counter*/
}
/* make loctr even*/
seven()
{
if(loctr&1) {
if(rlflg==TEXT || rlflg==DATA)
outbyte(0,DABS);
loctr++;
}
print(0);
}
/* second pass org*/
sorg()
{
long l;
if(rlflg==TEXT || rlflg==DATA) { /*must put out zeros*/
l = stbuf[ITOP1].itop - loctr; /*# zeroes to output*/
ins[0] = 0;
print(1);
while(l > 0) {
outbyte(0,DABS);
loctr++;
l--;
}
}
else { /*BSS*/
loctr = stbuf[ITOP1].itop; /*new location counter*/
print(0);
}
}
/*
*second pass define data (words or bytes)
* call with
* 2 => defining words
* 1 => defining bytes
* 4 => defining long words
*/
sdata(dtyp)
{
register pfg,i;
register hflg;
hflg = i = pfg = 0;
while(1) {
expr(&p2gi); /*evaluate expression*/
if(pitw < pnite)
pitw--; /*expr passed a token*/
if(itype!=ITCN && reloc != EXTRN) { /*must be constant*/
uerr(13);
ival=0;
reloc = ABS;
}
if(reloc == EXTRN)
reloc = (extref<<3)|EXTVAR; /*gen extern reference*/
if(dtyp==1) { /*defining a byte*/
if(ival<-128 || ival>=256 || reloc!=ABS) { /*not a byte*/
uerr(20);
ival=0;
reloc = ABS;
}
if(!hflg) {
ins[i].hibyte = ival;
outbyte(ival.wd2,DABS);
hflg++;
}
else {
ins[i++].lobyte = ival;
hflg = 0;
outbyte(ival.wd2,DABS);
}
goto sdal2;
}
else if(dtyp == 2) { /*defining a word*/
sdal1:
ins[i++] = ival.wd2;
outword(ival.wd2, reloc);
sdal2:
if(i>3) {
instrlen = i*2;
print ((pfg++) ? 2 : 1);
loctr =+ instrlen;
i=0;
}
}
else { /*long words*/
ins[i++] = ival.wd1;
outword(ival.wd1,LUPPER);
goto sdal1;
}
if(!ckeop(15)) /*should be end of operand*/
return;
pitw++;
if(ckein()) {
if(hflg) {
ins[i++].lobyte = 0;
}
if(i) { /*more printing*/
instrlen = i*2 - hflg;
print ((pfg) ? 2 : 1);
loctr =+ instrlen;
}
return;
}
}
}
sdc()
{
sdata(modelen);
}
ssection() /* [vlh] */
{
int sect;
sect = stbuf[3].itrl;
if (sect==DATA) sdsect();
else if (sect==BSS) sbss();
else spsect();
}
/*define word statement*/
sdw()
{
sdata(0); /*defining words*/
}
/**** Conditional assembly directives ****/
hifeq() /* [vlh] */
{
if (!acok()) return;
if (ival) {
if (ca_true) ca_level = ca;
ca_true = 0;
}
ca++;
}
hifne() /* [vlh] */
{
if (!acok()) return;
if (!ival) {
if (ca_true) ca_level = ca;
ca_true = 0;
}
ca++;
}
hiflt() /* [vlh] */
{
if (!acok()) return;
if (ival >= 0) {
if (ca_true) ca_level = ca;
ca_true = 0;
}
ca++;
}
hifle() /* [vlh] */
{
if (!acok()) return;
if (ival > 0) {
if (ca_true) ca_level = ca;
ca_true = 0;
}
ca++;
}
hifgt() /* [vlh] */
{
if (!acok()) return;
if (ival <= 0) {
if (ca_true) ca_level = ca;
ca_true = 0;
}
ca++;
}
hifge() /* [vlh] */
{
if (!acok()) return;
if (ival < 0) {
if (ca_true) ca_level = ca;
ca_true = 0;
}
ca++;
}
hifc() /* [vlh] */
{
if (!cmp_ops()) {
if (ca_true) ca_level = ca;
ca_true = 0;
}
ca++;
}
hifnc() /* [vlh] */
{
if (cmp_ops()) {
if (ca_true) ca_level = ca;
ca_true = 0;
}
ca++;
}
hendc() /* [vlh] */
{
if (!ca) {
xerr(25); /* unexpected endc */
return;
}
ca--;
if (!ca_true)
if (ca_level == ca) ca_true = 1;
igrst();
}
hpage()
{
opitb(); /* Output beginning */
wostb(); /* Write out buffer */
igrst(); /* Ignore rest of line */
}
spage()
{
print(0); /* Print the directive */
xline = LPP; /* Force page on next print */
page();
}
acok()
{
expr(&p1gi);
if (itype != ITCN) {
xerr(7); /* must be a constant */
return(0);
}
if (reloc != ABS) {
xerr(11); /* must be absolute, no forward references */
return(0);
}
igrst();
return(1);
}
cmp_ops()
{
char str1[25], str2[25];
register int len1, len2;
if (fchr != '\'') { xerr(9); return(0); }
len1 = len2 = 0;
while (fchr = gchr()) {
if (fchr == '\'') break;
if (fchr == EOLC) return(0);
str1[len1++] = fchr;
}
if ((fchr=gchr()) != ',') { xerr(9); return; }
if ((fchr=gchr()) != '\'') { xerr(10); return;}
while (fchr = gchr()) {
if (fchr == '\'') break;
if (fchr == EOLC) return(0);
str2[len2++] = fchr;
}
igrst();
if (len1 != len2) return(0);
str1[len1] = str2[len2] = NULL;
if (strcmp(str1,str2) == 0) return(1);
return(0);
}
strcmp(s,t)
register char *s, *t;
{
for( ; *s == *t; s++, t++ )
if( *s == '\0' )
return(0);
return( *s - *t );
}

View File

@@ -0,0 +1,950 @@
1File: DIR.C Page 1
1 /*
2 Copyright 1981
3 Alcyon Corporation
4 8716 Production Ave.
5 San Diego, Ca. 92121
6 */
7
8 /* Pass 1 and pass 2 directive handling routines */
9 /* code to handle conditional assembly directives */
10
11 #include "as68.h"
12 #include "cout.h"
13
14 long lseek();
15 int p1gi();
16 int p2gi();
17 int igrst();
18
19 /*directive to define an opcode*/
20 hopd()
21 {
22
23 if(!lbt[0]) {
24 xerr(4); /*no label*/
25 return;
26 }
27 setname(); /*move label into main table*/
28 if((lblpt=lemt(oirt,TRUE))!=lmte) {
29 xerr(5); /*opcode redefined*/
30 return;
31 }
32 mmte(); /*make main table entry*/
33 expr(&p1gi); /*get instruction format*/
34 if(itype!=ITCN || ival<0 || ival>OPFF) {
35 xerr(18); /*illegal format specifier*/
36 return;
37 }
38 lblpt->flags =| ival|SYIN; /*remember format*/
39 if(fchr != ',') { /*field separator*/
40 xerr(10);
41 return;
42 }
43 expr(&p1gi); /*get opcode value*/
44 if(itype != ITCN) {
45 xerr(17); /*not a constant*/
46 return;
47 }
48 lblpt->vl1 = ival; /*put value in main table*/
49 igrst(); /*ignore rest of statement-comment*/
50 }
51
52 /* equate directive*/
53 hequ()
54 {
55 if(lbt[0] == 0) {
56 xerr(4); /*no label*/
57 return;
58 }
59 setname();
1File: DIR.C Page 2
60 if((lblpt=lemt(sirt,FALSE))!=lmte) { /*aready there*/
61 if(lbt[0] == '~') { /*local symbol*/
62 lblpt = lmte;
63 mmte();
64 }
65 }
66 else
67 mmte();
68 if(lblpt->flags&SYXR) {
69 xerr(29);
70 return;
71 }
72 lblpt->flags =| SYDF|SYEQ; /*defined & equate*/
73 equflg = 1;
74 modelen = 4;
75 expr(&p1gi);
76 equflg = 0;
77 if(itype == ITSY && ival.ptrw2->flags&SYER) {
78 lblpt->flags =| SYER; /*equated register*/
79 ival = ival.ptrw2->vl1;
80 }
81 else if(itype != ITCN) {
82 xerr(7); /*not a constant*/
83 return;
84 }
85 if (inoffset && reloc != ABS) { /* [vlh] */
86 xerr(11);
87 return;
88 }
89 if(initflg) /*doing symbol table initialization*/
90 lblpt->flags =| SYIN; /*internal symbol*/
91 lblpt->vl1 = ival;
92 if(reloc == DATA) /*check relocation*/
93 {
94 lblpt->flags =| SYRA; /*DATA relocatable*/
95 }
96 else if(reloc == TEXT)
97 lblpt->flags =| SYRO; /*TEXT relocatable*/
98 else if(reloc == BSS)
99 lblpt->flags =| SYBS; /*BSS relocatable*/
100 else if(fchr==',' && (fchr=gchr())=='r')
101 lblpt->flags =| SYER; /*equated register*/
102 if (refpc) /*[vlh] flag directive is pc relative */
103 lblpt->flags =| SYPC;
104 igrst();
105 }
106
107 /* process dsect directive*/
108 hdsect()
109 {
110 dorlst(DATA);
111 }
112
113 dorlst(xrtyp)
114 {
115 inoffset = 0; /* [vlh] offset mode terminated my sect directive */
116 chkeven(); /* May need to make pc even */
117 dlabl(); /*define label on old base if there is one*/
118 savelc[rlflg] = loctr; /*save old base relocation*/
1File: DIR.C Page 3
119 rlflg = xrtyp;
120 loctr = savelc[xrtyp]; /*set new base relocation ctr*/
121 opitb();
122 stbuf[0].itrl = itwc;
123 wostb();
124 igrst();
125 }
126
127 /*process psect directive*/
128 hpsect()
129 {
130 dorlst(TEXT);
131 }
132
133 hbss()
134 {
135 dorlst(BSS);
136 }
137
138 /*make pc even*/
139 heven()
140 {
141 modelen = 2; /*Try to figure this one out...*/
142 if(loctr&1) { /*have to make it even*/
143 dorlst(rlflg);
144 }
145 else {
146 igrst();
147 }
148 }
149
150 /*process globl directive*/
151 hent()
152 {
153 while(1) {
154 gterm(TRUE); /*get entry symbol*/
155 if(itype!=ITSY) { /*error if not symbol*/
156 xerr(28);
157 return;
158 }
159 if((lblpt=lemt(sirt,FALSE)) == lmte) /*look up in main table*/
160 mmte(); /*not there, make new entry*/
161 else
162 if(lblpt->flags&SYER) /*already there*/
163 uerr(29);
164 lblpt->flags =| SYGL; /*symbol is an entry*/
165 if(lblpt->flags&SYXR) { /*been thru hext code*/
166 lblpt->flags =& ~(SYXR|SYDF); /*reset for init of .comm*/
167 }
168 if (inoffset && reloc != ABS) { /* [vlh] */
169 xerr(11);
170 return;
171 }
172 if(fchr == ',') /*skip ',' between entries*/
173 fchr = gchr();
174 else {
175 igrst(); /*statement finished*/
176 return;
177 }
1File: DIR.C Page 4
178 }
179 }
180
181 /*process comm directive*/
182 hext()
183 {
184 gterm(TRUE); /*get external symbol*/
185 if(itype!=ITSY) { /*error if not symbol*/
186 xerr(28);
187 return;
188 }
189 if((lblpt=lemt(sirt,FALSE)) == lmte) /*look up in main table*/
190 mmte(); /*not there, make new entry*/
191 else
192 if(lblpt->flags&SYDF && (lblpt->flags&SYXR)==0) /*already there*/
193 uerr(29);
194 lblpt->flags =| SYXR | SYDF; /*symbol is an external*/
195 mkextidx(lblpt); /*put into external table*/
196 if(fchr == ',') { /*skip ',' between operands*/
197 fchr = gchr();
198 gterm(TRUE);
199 if(itype != ITCN) {
200 xerr(17);
201 return;
202 }
203 lblpt->vl1.wd1 = ival; /* # bytes of storage required*/
204 }
205 else
206 lblpt->vl1.wd1 = 1; /* default # bytes*/
207 igrst();
208 }
209
210 mkextidx(p)
211 struct symtab *p;
212 {
213
214 if(extindx >= EXTSZ) { /*check for overflow of external symbol tbl*/
215 rpterr("overflow of external table\n");
216 endit();
217 }
218 p->vl1.wd2 = pexti - extbl; /* external symbol index #*/
219 *pexti++ = p; /*save external in external table*/
220 extindx++;
221 }
222
223 /* end statement*/
224 hend()
225 {
226 register short i;
227 register int j;
228
229 inoffset = 0; /*[vlh] turn off inoffset mode*/
230 lblpt = 0; /*no label*/
231 opitb(); /*output beginning of statement*/
232 igrst(); /* [vlh] ignore operands */
233 stbuf[0].itrl = itwc; /*number of it entries*/
234 wostb(); /*write out statement buffer*/
235 for(i=0; i<ITBSZ; i++)
236 doitwr(0);
1File: DIR.C Page 5
237 if(initflg) {
238 putsymtab();
239 printf("68000 assembler initialized\n");
240 endit();
241 }
242 if((fchr=gchr())!=EOF) {
243 rpterr("end statement not at end of source\n");
244 }
245 savelc[rlflg] = loctr; /*last location on current reloc base*/
246 fixunds(); /*make golbals and maybe undefineds external*/
247 if(!didorg) /*did not assign to location counter*/
248 pass1a(); /*resolve short branches*/
249 pass2(); /*assembler pass 2*/
250 }
251
252 /* define storage given number of bytes*/
253 hds()
254 {
255 dlabl(); /*define label maybe*/
256 if (!inoffset) /* [vlh] */
257 opitb(); /*output it for beginning of statement*/
258 refpc = 0;
259 expr(&p1gi);
260 if(itype!=ITCN) {
261 xerr(17); /*must be constant*/
262 return;
263 }
264 if(reloc != ABS) {
265 xerr(9); /*must be absolute*/
266 return;
267 }
268 if (!inoffset) { /* [vlh] don't generate it if in offset */
269 opitoo(); /*output one operand*/
270 stbuf[0].itrl = itwc;
271 wostb(); /*write out statement buffer*/
272 loctr =+ (ival*modelen);
273 }
274 igrst();
275 }
276
277 /* make pc even if necessary for .dc and .ds */
278 chkeven()
279 {
280 register char *pi;
281
282 if(modelen>1 && loctr&1) {
283 pi = opcpt;
284 opcpt = evenptr;
285 opitb();
286 stbuf[0].itrl = itwc;
287 wostb();
288 opcpt = pi;
289 loctr++;
290 }
291 }
292
293 /* define byte directive*/
294 hdc()
295 {
1File: DIR.C Page 6
296 chkeven();
297 hdata(modelen);
298 }
299
300 /*
301 * define bytes or words of data
302 * call with:
303 * 1 => defining bytes
304 * 2 => defining words
305 * 4 => defining long words
306 */
307 hdata(mul)
308 {
309 dlabl(); /*define label*/
310 opitb(); /*beginning of statement*/
311 numops = 0; /*initialize count for number of operands*/
312 opito(); /*output it for operands*/
313 stbuf[0].itrl = itwc; /* # of it entries*/
314 wostb(); /*write out statement buffer*/
315 loctr =+ numops*mul; /* count by bytes or words*/
316 }
317
318 /* handle org statement*/
319 horg()
320 {
321 register i;
322
323 if(rlflg==TEXT && loctr!=0)
324 didorg++; /*can't do branch optimization as separate pass now*/
325 expr(&p1gi); /*value of new relocation counter*/
326 if(reloc != rlflg && reloc != ABS) {
327 xerr(27);
328 return;
329 }
330 if(ival < loctr) {
331 xerr(40); /*trying to go backwards*/
332 return;
333 }
334 opcpt = orgptr; /*org directive for pass 2*/
335 opitb();
336 opitoo();
337 stbuf[0].itrl = itwc;
338 wostb();
339 loctr = ival;
340 dlabl(); /*define label*/
341 }
342
343 /* Assemble for mask2 (R9M), ignore... */
344 hmask2() /* [vlh] */
345 {
346 igrst();
347 }
348
349 /* Define register list */
350 hreg() /* [vlh] */
351 {
352 int mask;
353 if(lbt[0]==0) {
354 xerr(4); /*no label*/
1File: DIR.C Page 7
355 return;
356 }
357 setname(); /*move label into main table*/
358 if((lblpt=lemt(sirt,FALSE))!=lmte) {
359 xerr(5); /*opcode redefined*/
360 return;
361 }
362 if (inoffset)
363 if (reloc != ABS) {
364 xerr(11);
365 return;
366 }
367 mmte(); /*make main table entry*/
368 if ((mask = mkmask()) == -1) {
369 xerr(6);
370 return;
371 }
372 lblpt->flags =| SYDF|SYEQ|SYRM; /* register mask, defined & equated */
373 lblpt->vl1 = mask;
374 igrst();
375 }
376
377 int regmsk[] {0100000,040000,020000,010000,04000,02000,01000,0400,0200,
378 0100,040,020,010,4,2,1};
379 /* make a register mask for the reg routine */
380 mkmask() /* [vlh] */
381 {
382 register int *p, i, j, mask;
383
384 p = &regmsk; mask = 0;
385 while ((i = chkreg()) != -1) {
386 if (fchr == '-') {
387 fchr = gchr();
388 if ((j = chkreg()) == -1) {
389 xerr(40);
390 return(-1);
391 }
392 while (i <= j)
393 mask =| p[i++];
394 }
395 else mask =| p[i];
396 if (fchr != '/' && fchr != ',') break; /*[vlh] Signetics fix*/
397 fchr = gchr();
398 }
399 return(mask);
400 }
401
402 /* get a register # from file, return -1 if none or illegal */
403 chkreg() /* [vlh] */
404 {
405 register int i, j;
406
407 i = j = 0;
408 if (fchr == 'a' || fchr == 'A')
409 i = 8;
410 else if (fchr != 'd' && fchr != 'r' && fchr != 'D' && fchr != 'R')
411 return(-1);
412 fchr = gchr();
413 do {
1File: DIR.C Page 8
414 j = (j*10) + (fchr - '0');
415 fchr = gchr();
416 } while (isdigit(fchr));
417 if (j < 0 || j > AREGHI) return(-1);
418 i =+ j;
419 if (i >= 0 && i <= AREGHI) return(i);
420 else return(-1);
421 }
422
423 /* Define constant block */
424 hdcb() /* [vlh] */
425 {
426 chkeven(); /* on even boundary if not byte block. */
427 dlabl(); /* define label... */
428 opitb();
429 opito();
430 stbuf[0].itrl = itwc;
431 numops = stbuf[ITOP1].itop;
432 loctr =+ numops * modelen;
433 wostb(); /* write out statement buffer */
434 }
435
436 /* Command line, similar to ds.b */
437 hcomline() /* [vlh] */
438 {
439 dlabl(); /*define label maybe*/
440 modelen = 1; /* byte store... */
441 opitb(); /*output it for beginning of statement*/
442 refpc = 0;
443 expr(&p1gi);
444 if(itype!=ITCN) {
445 xerr(17); /*must be constant*/
446 return;
447 }
448 if(reloc != ABS) {
449 xerr(9); /*must be absolute*/
450 return;
451 }
452 opitoo(); /*output one operand*/
453 stbuf[0].itrl = itwc;
454 wostb(); /*write out statement buffer*/
455 loctr =+ ival;
456 igrst();
457 }
458
459 /* Relocateable id record, ignore */
460 hidnt() /* [vlh] */
461 {
462 igrst();
463 }
464
465 /* Define offsets */
466 hoffset() /* [vlh] */
467 {
468 inoffset = 1;
469 expr(&p1gi); /* get new location counter */
470 if (itype != ITCN) {
471 xerr(17); /* constant required */
472 return;
1File: DIR.C Page 9
473 }
474 if (reloc != ABS) {
475 xerr(9); /* must be absolute */
476 return;
477 }
478 loctr = ival;
479 igrst();
480 }
481
482 /* define sections: map to bss, text and data */
483 hsection() /* [vlh] */
484 {
485 inoffset = 0; /* reseting section turns off offset mode */
486 dlabl(); /* define label on old base if there is one */
487 savelc[rlflg] = loctr; /* save old base relocation */
488 opitb(); /* intermediate table... */
489 expr(&p1gi); /* get section # */
490 if (itype != ITCN) {
491 xerr(17); /* must be a constant */
492 return;
493 }
494 if (ival > 15 || ival < 0) {
495 xerr(9); /* proper range 0..15 */
496 return;
497 }
498 if (ival==14) rlflg = DATA;
499 else if (ival==15) rlflg = BSS;
500 else rlflg = TEXT;
501 loctr = savelc[rlflg];
502 stbuf[3].itop = loctr; /* pass 1 location counter */
503 stbuf[3].itrl = rlflg; /* relocation base */
504 stbuf[0].itrl = itwc;
505 wostb();
506 igrst();
507 }
508
509 /* hopt -- ignore, set up assembler options */
510 hopt() /* vlh */
511 {
512 igrst();
513 }
514
515 /**** Second pass directive handling routines ****/
516
517 /* second pass end statement*/
518 send()
519 {
520 register int i;
521
522 savelc[rlflg] = loctr;
523 if(savelc[TEXT]&1) {
524 rlflg = TEXT;
525 outbyte(0,DABS);
526 savelc[TEXT]++;
527 }
528 if(savelc[DATA]&1) {
529 rlflg = DATA;
530 outbyte(0,DABS);
531 savelc[DATA]++;
1File: DIR.C Page 10
532 }
533 if(savelc[BSS]&1) {
534 savelc[BSS]++;
535 }
536
537 ival = 0;
538 reloc = ABS;
539 ckeop(9);
540 print(0);
541 cpdata(); /*copy data to loader file*/
542 osymt(); /*output symbol table*/
543 myfflush(&tbuf); /*flush text relocation bits*/
544 cprlbits(); /*copy relocation bits*/
545 myfflush(&lbuf);
546 i = (sizeof couthd.ch_magic) + 3*(sizeof couthd.ch_tsize);
547 if((lseek(lfn,(long)i,0) == -1) || write(lfn,&stlen,4) != 4)
548 rpterr("I/O error on loader output file\n");
549 endit(); /*end*/
550 }
551
552 /*second pass define storage - ds*/
553 sds()
554 {
555 print(0);
556 if(rlflg == TEXT || rlflg==DATA) {
557 expr(&p2gi);
558 if(itype != ITCN) {
559 uerr(13);
560 return;
561 }
562 ival =* modelen;
563 while(ival) {
564 outbyte(0,DABS);
565 loctr++;
566 ival--;
567 }
568 }
569 else
570 loctr =+ stbuf[ITOP1].itop*modelen; /*reserve storage*/
571 }
572
573 /* second pass - define block storage, initialized */
574 sdcb() /* [vlh] */
575 {
576 register int pfg, i, hflg, len;
577
578 expr(&p2gi);
579 if (itype != ITCN || reloc != ABS) {
580 uerr(13); /* must be absolute constant */
581 return;
582 }
583 len = ival;
584 expr(&p2gi);
585 if (modelen==1 && (ival<-128 || ival>=256 || reloc != ABS)) {
586 uerr(20);
587 ival = 0;
588 reloc = ABS;
589 }
590 while (len--) {
1File: DIR.C Page 11
591 if (modelen==1) {
592 if (!hflg) {
593 ins[i].hibyte = ival;
594 outbyte(ival.wd2,DABS);
595 hflg++;
596 }
597 else {
598 ins[i++].lobyte = ival;
599 outbyte(ival.wd2,DABS);
600 hflg=0;
601 }
602 goto sdbl2;
603 }
604 else if (modelen==2) {
605 sdbl1:
606 ins[i++] = ival.wd2;
607 outword(ival.wd2, reloc);
608 sdbl2:
609 if (i>3) {
610 instrlen = i*2;
611 print ((pfg++) ? 2 : 1);
612 loctr =+ instrlen;
613 i=0;
614 }
615 }
616 else { /* long word... */
617 ins[i++] = ival.wd1;
618 outword(ival.wd1,LUPPER);
619 goto sdbl1;
620 }
621 }
622 if (i) { /* more printing */
623 instrlen = i*2 - hflg;
624 print ((pfg) ? 2 : 1);
625 loctr =+ instrlen;
626 }
627 }
628
629 /*second pass data*/
630 sdsect()
631 {
632 savelc[rlflg] = loctr;
633 rlflg = DATA;
634 loctr = savelc[DATA];
635 print(0); /*print the new location counter*/
636 }
637
638 /*second pass text*/
639 spsect()
640 {
641 savelc[rlflg] = loctr;
642 rlflg = TEXT;
643 loctr = savelc[TEXT];
644 print(0); /*print the new location counter*/
645 }
646
647 sbss()
648 {
649 savelc[rlflg] = loctr;
1File: DIR.C Page 12
650 rlflg = BSS;
651 loctr = savelc[BSS];
652 print(0); /*print the new location counter*/
653 }
654
655 /* make loctr even*/
656 seven()
657 {
658 if(loctr&1) {
659 if(rlflg==TEXT || rlflg==DATA)
660 outbyte(0,DABS);
661 loctr++;
662 }
663 print(0);
664 }
665
666 /* second pass org*/
667 sorg()
668 {
669 long l;
670
671 if(rlflg==TEXT || rlflg==DATA) { /*must put out zeros*/
672 l = stbuf[ITOP1].itop - loctr; /*# zeroes to output*/
673 ins[0] = 0;
674 print(1);
675 while(l > 0) {
676 outbyte(0,DABS);
677 loctr++;
678 l--;
679 }
680 }
681 else { /*BSS*/
682 loctr = stbuf[ITOP1].itop; /*new location counter*/
683 print(0);
684 }
685 }
686
687 /*
688 *second pass define data (words or bytes)
689 * call with
690 * 2 => defining words
691 * 1 => defining bytes
692 * 4 => defining long words
693 */
694 sdata(dtyp)
695 {
696 register pfg,i;
697 register hflg;
698
699 hflg = i = pfg = 0;
700 while(1) {
701 expr(&p2gi); /*evaluate expression*/
702 if(pitw < pnite)
703 pitw--; /*expr passed a token*/
704 if(itype!=ITCN && reloc != EXTRN) { /*must be constant*/
705 uerr(13);
706 ival=0;
707 reloc = ABS;
708 }
1File: DIR.C Page 13
709 if(reloc == EXTRN)
710 reloc = (extref<<3)|EXTVAR; /*gen extern reference*/
711 if(dtyp==1) { /*defining a byte*/
712 if(ival<-128 || ival>=256 || reloc!=ABS) { /*not a byte*/
713 uerr(20);
714 ival=0;
715 reloc = ABS;
716 }
717 if(!hflg) {
718 ins[i].hibyte = ival;
719 outbyte(ival.wd2,DABS);
720 hflg++;
721 }
722 else {
723 ins[i++].lobyte = ival;
724 hflg = 0;
725 outbyte(ival.wd2,DABS);
726 }
727 goto sdal2;
728 }
729 else if(dtyp == 2) { /*defining a word*/
730 sdal1:
731 ins[i++] = ival.wd2;
732 outword(ival.wd2, reloc);
733 sdal2:
734 if(i>3) {
735 instrlen = i*2;
736 print ((pfg++) ? 2 : 1);
737 loctr =+ instrlen;
738 i=0;
739 }
740 }
741 else { /*long words*/
742 ins[i++] = ival.wd1;
743 outword(ival.wd1,LUPPER);
744 goto sdal1;
745 }
746 if(!ckeop(15)) /*should be end of operand*/
747 return;
748 pitw++;
749 if(ckein()) {
750 if(hflg) {
751 ins[i++].lobyte = 0;
752 }
753 if(i) { /*more printing*/
754 instrlen = i*2 - hflg;
755 print ((pfg) ? 2 : 1);
756 loctr =+ instrlen;
757 }
758 return;
759 }
760 }
761 }
762
763 sdc()
764 {
765 sdata(modelen);
766 }
767
1File: DIR.C Page 14
768 ssection() /* [vlh] */
769 {
770 int sect;
771
772 sect = stbuf[3].itrl;
773 if (sect==DATA) sdsect();
774 else if (sect==BSS) sbss();
775 else spsect();
776 }
777
778 /*define word statement*/
779 sdw()
780 {
781 sdata(0); /*defining words*/
782 }
783 /**** Conditional assembly directives ****/
784
785 hifeq() /* [vlh] */
786 {
787 if (!acok()) return;
788 if (ival) {
789 if (ca_true) ca_level = ca;
790 ca_true = 0;
791 }
792 ca++;
793 }
794
795 hifne() /* [vlh] */
796 {
797 if (!acok()) return;
798 if (!ival) {
799 if (ca_true) ca_level = ca;
800 ca_true = 0;
801 }
802 ca++;
803 }
804
805 hiflt() /* [vlh] */
806 {
807 if (!acok()) return;
808 if (ival >= 0) {
809 if (ca_true) ca_level = ca;
810 ca_true = 0;
811 }
812 ca++;
813 }
814
815 hifle() /* [vlh] */
816 {
817 if (!acok()) return;
818 if (ival > 0) {
819 if (ca_true) ca_level = ca;
820 ca_true = 0;
821 }
822 ca++;
823 }
824
825 hifgt() /* [vlh] */
826 {
1File: DIR.C Page 15
827 if (!acok()) return;
828 if (ival <= 0) {
829 if (ca_true) ca_level = ca;
830 ca_true = 0;
831 }
832 ca++;
833 }
834
835 hifge() /* [vlh] */
836 {
837 if (!acok()) return;
838 if (ival < 0) {
839 if (ca_true) ca_level = ca;
840 ca_true = 0;
841 }
842 ca++;
843 }
844
845 hifc() /* [vlh] */
846 {
847 if (!cmp_ops()) {
848 if (ca_true) ca_level = ca;
849 ca_true = 0;
850 }
851 ca++;
852 }
853
854 hifnc() /* [vlh] */
855 {
856 if (cmp_ops()) {
857 if (ca_true) ca_level = ca;
858 ca_true = 0;
859 }
860 ca++;
861 }
862
863 hendc() /* [vlh] */
864 {
865 if (!ca) {
866 xerr(25); /* unexpected endc */
867 return;
868 }
869 ca--;
870 if (!ca_true)
871 if (ca_level == ca) ca_true = 1;
872 igrst();
873 }
874 hpage()
875 {
876 opitb(); /* Output beginning */
877 wostb(); /* Write out buffer */
878 igrst(); /* Ignore rest of line */
879 }
880 spage()
881 {
882 print(0); /* Print the directive */
883 xline = LPP; /* Force page on next print */
884 page();
885 }
1File: DIR.C Page 16
886 acok()
887 {
888 expr(&p1gi);
889 if (itype != ITCN) {
890 xerr(7); /* must be a constant */
891 return(0);
892 }
893 if (reloc != ABS) {
894 xerr(11); /* must be absolute, no forward references */
895 return(0);
896 }
897 igrst();
898 return(1);
899 }
900
901 cmp_ops()
902 {
903 char str1[25], str2[25];
904 register int len1, len2;
905
906 if (fchr != '\'') { xerr(9); return(0); }
907 len1 = len2 = 0;
908 while (fchr = gchr()) {
909 if (fchr == '\'') break;
910 if (fchr == EOLC) return(0);
911 str1[len1++] = fchr;
912 }
913 if ((fchr=gchr()) != ',') { xerr(9); return; }
914 if ((fchr=gchr()) != '\'') { xerr(10); return;}
915 while (fchr = gchr()) {
916 if (fchr == '\'') break;
917 if (fchr == EOLC) return(0);
918 str2[len2++] = fchr;
919 }
920 igrst();
921 if (len1 != len2) return(0);
922 str1[len1] = str2[len2] = NULL;
923 if (strcmp(str1,str2) == 0) return(1);
924 return(0);
925 }
926
927 strcmp(s,t)
928 register char *s, *t;
929 {
930 for( ; *s == *t; s++, t++ )
931 if( *s == '\0' )
932 return(0);
933 return( *s - *t );
934 }

View File

@@ -0,0 +1,505 @@
/*
Copyright 1981
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
/* Expression evaluator */
# include "as68.h"
/*precedence of operators*/
# define PAO 2 /*AND, OR*/
# define PPM 2 /*+ -*/
# define PMD 3 /** /*/
# define PLP 1 /* (*/
# define PRP 4 /* )*/
# define PEE 0 /* all other special chars*/
/*global integers for this package*/
struct it exitm; /*expression item*/
int prcnt; /*paren count*/
int rval; /*relocation value*/
int lpflg;
int lastopr; /*last token was operator when set*/
long gval(); /*get operand value*/
/*
* expression evaluator
* call with:
* address of function to get input
* returns:
* item type in itype
* item value in ival
* relocation flag in reloc:
* 0 => absolute
* 1 => data
* 2 => text
* 3 => bss
* 4 => external
*
* The only expressions involving externals which are legal are
* external+constant or external-constant
*/
struct it *piop, *pitr;
int iop, itr;
struct it opstk[OPSTLEN]; /*operator stack*/
struct it tree[TREELEN]; /*operand stack*/
expr(iploc)
int (*iploc)();
{
register int i, ipr;
extflg = starmul = iop = lpflg = 0;
piop = &opstk[0];
itr = -1; /*tree stack pointer*/
pitr = &tree[0];
pitr--;
/* form end of expression operator*/
opstk[0].itty = ITSP; /*special character*/
opstk[0].itop.wd2 = '?';
lastopr = 1;
/* get an input item*/
while(1) {
if(itr >= TREELEN-2) {
rpterr("expr tree overflow\n");
abort();
}
if(iop >= OPSTLEN-1) {
rpterr("expr opstk overflow\n");
abort();
}
(*iploc)(); /*get an input term*/
if (itype==ITPC) return;
starmul=0; /* * is location counter*/
/* special character*/
if(itype==ITSP) {
ipr = gprc(i=ival.wd2); /*get precedence of character*/
if(ipr==PEE) /*end of expression*/
break;
lastopr = 1;
if(ipr==PLP) { /*left paren*/
lpflg++;
prcnt++;
iop++; /*up stack pointer*/
piop++;
piop->swd1=exitm.swd1; /*put operator on stack*/
piop->itop=exitm.itop;
continue;
}
if(ipr==PRP) { /*right paren*/
if(lpflg) { exerr(1); return; }
starmul = 1; /* * is multiply*/
prcnt--; /*down one level*/
while (piop->itop != '(') { /* top stk is '(' */
itr++; /*up tree pointer*/
pitr++;
pitr->swd1 = piop->swd1; /*move operator*/
pitr->itop = piop->itop;
iop--; /*reduce operand stack*/
piop--;
}
iop--; /*remove stack*/
piop--;
continue;
}
while(ipr<=gprc(i=piop->itop.wd2)) { /* >= precedence */
itr++;
pitr++;
pitr->swd1 = piop->swd1; /*move operator*/
pitr->itop = piop->itop;
iop--; /*reduce operand stack*/
piop--;
}
iop++; /*up operator stack*/
piop++;
piop->swd1 = exitm.swd1; /*put in operator stack*/
piop->itop = exitm.itop;
continue;
}
/* symbol or constant*/
else {
lastopr = lpflg = 0; /*clear flag*/
itr++; /*up tree pointer*/
pitr++;
pitr->swd1 = exitm.swd1; /*put in tree*/
pitr->itop = exitm.itop;
starmul = 1; /* * is multiply*/
continue;
}
} /* end while(1)... */
/*output the rest of the operator stack to the tree*/
for(i=iop; i>=0; i--) {
itr++;
pitr++;
pitr->swd1 = piop->swd1; /*move operator*/
pitr->itop = piop->itop;
piop--;
}
collapse();
}
/* collapse the tree into one entry*/
collapse()
{
register int rv1, rv2, topr, i, bos;
register long tv1, tv2;
bos = 0;
exct1:
if(itr>=3) {
piop = &tree[bos];
iop = bos;
while (iop<=(itr-3+bos) && (piop->itty==ITSP ||
(piop+1)->itty==ITSP || (piop+2)->itty!=ITSP)) {
iop++;
piop++;
}
if (iop<=(itr-3+bos)) {
tv1 = gval(piop); /*get value of first operand*/
rv1 = rval; /*relocation value*/
tv2 = gval(piop+1);
rv2 = rval;
topr = (piop+2)->itop; /*operator*/
/* handle operators */
if (topr == '+') {
tv1=+ tv2;
rv1 = ckrl1(rv1,rv2); /*relocation*/
}
else if (topr == '-') {
tv1 =- tv2;
rv1 = ckrl2(rv1,rv2); /*relocation*/
}
else {
switch(topr) { /*operator*/
case '/': /* division */
tv1 =/ tv2; break;
case '*': /* multiplication */
tv1 =* tv2; break;
case '&': /* logical and */
tv1 =& tv2; break;
case '!': /* logical or */
tv1 =| tv2; break;
case '<': /* left shift */
tv1 =<< tv2.wd2; break;
case '>': /* right shift */
tv1 =>> tv2.wd2; break;
default: /*invalid operator*/
exerr(2); return;
}
rv1 = ckrl3(rv1,rv2); /* relocation */
}
/*put new value in tree*/
if (iop==bos) {
bos =+ 2;
iop = bos;
}
piop = &tree[iop];
piop->itty = ITCN; /*must be constant*/
piop->itop = tv1; /*value*/
piop->itrl = rv1; /*relocation value*/
if (iop != bos) { /* push up the rest of the tree... */
i = iop + 2 - bos;
pitr = piop+2;
for(; i<itr; i++) {
piop++;
pitr++;
piop->swd1 = pitr->swd1;
piop->itop = pitr->itop;
}
}
itr =- 2;
goto exct1;
}
}
/* check for unary minus and unary plus*/
if (tree[bos+1].itty!=ITSP && tree[bos].itop.wd2=='?')
{ exerr(3); return; }
if (tree[bos+1].itty!=ITSP || tree[bos].itty==ITSP) {
reloc = ABS;
ival = 0;
itype = ITCN;
return;
}
if(tree[bos+1].itop.wd2!='?') { /*end of statement*/
if(tree[bos+1].itop.wd2!='+') { /*ignore unary plus*/
if(tree[bos+1].itop.wd2!='-') { /* invalid operator */
exerr(4);
return;
}
tree[bos+1].itop = -gval(&tree[bos]);
tree[bos+1].itty = ITCN;
tree[bos+1].itrl = tree[bos].itrl;
bos++;
itr--;
goto exct1;
}
}
/* send results back to caller*/
if ((itype = tree[bos].itty)==ITCN)
ival = gval(&tree[bos]);
else {
ival = tree[bos].itop;
if(itype==ITSY && !(ival.ptrw2->flags&SYDF)) { /*undef symbol*/
reloc = ABS;
ival = 0;
itype = ITCN;
return;
}
}
get_val(tree[bos].itrl);
}
/*
*if defined symbol get value and say constant
* except for externals and equated registers
*/
get_val(reloc_val)
int reloc_val;
{
if(itype==ITSY && (ival.ptrw2->flags&(SYXR|SYER))==0) {
if(ival.ptrw2->flags&SYRA) /*get symbol relocation factor*/
reloc = DATA;
else if(ival.ptrw2->flags&SYRO)
reloc = TEXT;
else if(ival.ptrw2->flags&SYBS)
reloc = BSS;
else reloc = ABS;
ival = ival.ptrw2->vl1; /*symbol vaue*/
itype = ITCN; /*constant*/
}
else
if(itype == ITSY && ival.ptrw2->flags&SYXR) { /*external symbol*/
fixext(ival.ptrw2);
reloc = EXTRN;
}
else
reloc = reloc_val; /*relocation value of item*/
}
exerr(n) /* [vlh] */
int n;
{
uerr(6);
ival = 0;
itype = ITCN;
reloc = ABS;
}
/*
* get precedence of a operator
* call with
* operator
* returns
* precedence
*/
gprc(dprc)
{
switch(dprc) {
case '+':
case '-':
case '&': /* and*/
case '!': /* or*/
case '^': /*exclusive or*/
return(PPM);
case '/':
case '*':
case '<': /*left shift*/
case '>': /*right shift*/
return(PMD);
case '(':
if(lastopr)
return(PLP);
break;
case ')':
if(!prcnt) /*no left parens*/
break;
return(PRP);
}
return(PEE); /*end of expression*/
}
/*
* get value from an it format item
* call with
* address of it format item
* returns
* the value
* relocation value in rval
* calls uerr if it cant get a value
*/
long gval(avwrd)
struct it *avwrd;
{
register struct it *vwrd;
register struct symtab *p;
vwrd = avwrd;
if(vwrd->itty == ITCN) { /*constant*/
rval = vwrd->itrl;
return(vwrd->itop); /*value*/
}
if(vwrd->itty != ITSY) {
uerr(6);
rval = ABS;
return(0);
}
p = vwrd->itop.ptrw2;
if(p->flags&SYXR) { /*external reference*/
fixext(p);
return(0);
}
if((p->flags&SYDF) != SYDF || (p->flags&SYER)) {
uerr(6);
rval = ABS;
return(0);
}
rval = (p->flags&SYRA) ? DATA : (p->flags&SYRO) /* reloc of item */
? TEXT : (p->flags&SYBS) ? BSS : ABS;
return(p->vl1);
}
/*
* get items for expression evaluator (pass one)
* returns:
* item type in itype
* item value in ival
* item in it format in exitm
*/
p1gi()
{
if(fcflg) /*used item so must pass it*/
gterm(TRUE);
if(!fcflg && ckspc(fchr)==1) {
fcflg=1; /*just pass first character*/
itype=ITSP; /*special char*/
ival=fchr; /*value is the char*/
}
else { /*get a whole term*/
fcflg = 0;
gterm(TRUE); /*get a term*/
if(itype==ITSY) { /* got a symbol*/
ival.ptrw2=lemt(sirt,FALSE); /*look it up in main table*/
if(ival.ptrw2==lmte) /*not there before*/
mmte(); /*put it in table*/
}
else
if(itype == ITCN)
exitm.itrl = reloc;
}
exitm.itty = itype;
exitm.itop = ival;
}
/*
* get items for expression evaluator (pass 2)
* returns:
* item type in itype
* item value in ival
* item in it format in exitm
*/
p2gi()
{
if(pitw==pnite) { /*end of statement*/
itype = ITSP;
ival = ' '; /*blank*/
exitm.itty = itype;
exitm.itop = ival;
return;
}
if((itype = pitw->itty) == ITPC) { /*vlh*/
pitw->itop = loctr;
if (p2flg || format==6) itype = pitw->itty = ITCN;
}
ival = pitw->itop; /*value*/
exitm.swd1 = pitw->swd1;
exitm.itop = ival;
pitw++;
}
/*
*check for a special character
* call with
* character to check
* returns:
* 0 => character is number or letter
*/
ckspc(acksc)
{
register cksc;
cksc = acksc;
if (isalnum(cksc)) return(0);
return((index("_~*.@$%\'",cksc) != -1) ? 0 : 1); /*[vlh] compacted*/
}
/* generate new relocation for op + op*/
ckrl1(rv1,rv2)
{
if(rv1==rv2)
return(rv1);
if(rv1==ABS || rv2==ABS)
return(rv1+rv2); /*the one that is not ABS*/
uerr(27);
return(ABS);
}
/*generate new relocation for op - op*/
ckrl2(rv1,rv2)
{
if(rv2==EXTRN)
uerr(26);
if(rv1==rv2)
return(ABS);
if(rv2==ABS)
return(rv1+rv2);
uerr(27);
return(ABS);
}
/*generate new relocation for op /*&|<>^! op*/
ckrl3(rv1,rv2)
{
if(rv1!=ABS || rv2!=ABS)
uerr(27);
return(ABS);
}
fixext(p)
struct symtab *p;
{
if(extflg)
uerr(36); /*two externals in expr*/
extflg++;
extref = p->vl1.wd2; /*get external #*/
rval = EXTRN;
itype = ITCN;
ival = 0;
}

View File

@@ -0,0 +1,514 @@
1File: EXPR.C Page 1
1 /*
2 Copyright 1981
3 Alcyon Corporation
4 8716 Production Ave.
5 San Diego, Ca. 92121
6 */
7
8 /* Expression evaluator */
9
10 # include "as68.h"
11
12 /*precedence of operators*/
13 # define PAO 2 /*AND, OR*/
14 # define PPM 2 /*+ -*/
15 # define PMD 3 /** /*/
16 # define PLP 1 /* (*/
17 # define PRP 4 /* )*/
18 # define PEE 0 /* all other special chars*/
19
20
21 /*global integers for this package*/
22 struct it exitm; /*expression item*/
23 int prcnt; /*paren count*/
24 int rval; /*relocation value*/
25 int lpflg;
26 int lastopr; /*last token was operator when set*/
27
28 long gval(); /*get operand value*/
29
30 /*
31 * expression evaluator
32 * call with:
33 * address of function to get input
34 * returns:
35 * item type in itype
36 * item value in ival
37 * relocation flag in reloc:
38 * 0 => absolute
39 * 1 => data
40 * 2 => text
41 * 3 => bss
42 * 4 => external
43 *
44 * The only expressions involving externals which are legal are
45 * external+constant or external-constant
46 */
47
48 struct it *piop, *pitr;
49 int iop, itr;
50
51 struct it opstk[OPSTLEN]; /*operator stack*/
52 struct it tree[TREELEN]; /*operand stack*/
53
54 expr(iploc)
55 int (*iploc)();
56 {
57 register int i, ipr;
58
59 extflg = starmul = iop = lpflg = 0;
1File: EXPR.C Page 2
60 piop = &opstk[0];
61 itr = -1; /*tree stack pointer*/
62 pitr = &tree[0];
63 pitr--;
64 /* form end of expression operator*/
65 opstk[0].itty = ITSP; /*special character*/
66 opstk[0].itop.wd2 = '?';
67 lastopr = 1;
68
69 /* get an input item*/
70 while(1) {
71 if(itr >= TREELEN-2) {
72 rpterr("expr tree overflow\n");
73 abort();
74 }
75 if(iop >= OPSTLEN-1) {
76 rpterr("expr opstk overflow\n");
77 abort();
78 }
79 (*iploc)(); /*get an input term*/
80 if (itype==ITPC) return;
81 starmul=0; /* * is location counter*/
82
83 /* special character*/
84 if(itype==ITSP) {
85 ipr = gprc(i=ival.wd2); /*get precedence of character*/
86 if(ipr==PEE) /*end of expression*/
87 break;
88 lastopr = 1;
89 if(ipr==PLP) { /*left paren*/
90 lpflg++;
91 prcnt++;
92 iop++; /*up stack pointer*/
93 piop++;
94 piop->swd1=exitm.swd1; /*put operator on stack*/
95 piop->itop=exitm.itop;
96 continue;
97 }
98 if(ipr==PRP) { /*right paren*/
99 if(lpflg) { exerr(1); return; }
100 starmul = 1; /* * is multiply*/
101 prcnt--; /*down one level*/
102
103 while (piop->itop != '(') { /* top stk is '(' */
104 itr++; /*up tree pointer*/
105 pitr++;
106 pitr->swd1 = piop->swd1; /*move operator*/
107 pitr->itop = piop->itop;
108 iop--; /*reduce operand stack*/
109 piop--;
110 }
111 iop--; /*remove stack*/
112 piop--;
113 continue;
114 }
115
116 while(ipr<=gprc(i=piop->itop.wd2)) { /* >= precedence */
117 itr++;
118 pitr++;
1File: EXPR.C Page 3
119 pitr->swd1 = piop->swd1; /*move operator*/
120 pitr->itop = piop->itop;
121 iop--; /*reduce operand stack*/
122 piop--;
123 }
124 iop++; /*up operator stack*/
125 piop++;
126 piop->swd1 = exitm.swd1; /*put in operator stack*/
127 piop->itop = exitm.itop;
128 continue;
129 }
130
131 /* symbol or constant*/
132 else {
133 lastopr = lpflg = 0; /*clear flag*/
134 itr++; /*up tree pointer*/
135 pitr++;
136 pitr->swd1 = exitm.swd1; /*put in tree*/
137 pitr->itop = exitm.itop;
138 starmul = 1; /* * is multiply*/
139 continue;
140 }
141 } /* end while(1)... */
142
143 /*output the rest of the operator stack to the tree*/
144 for(i=iop; i>=0; i--) {
145 itr++;
146 pitr++;
147 pitr->swd1 = piop->swd1; /*move operator*/
148 pitr->itop = piop->itop;
149 piop--;
150 }
151
152 collapse();
153 }
154
155 /* collapse the tree into one entry*/
156 collapse()
157 {
158 register int rv1, rv2, topr, i, bos;
159 register long tv1, tv2;
160
161 bos = 0;
162 exct1:
163 if(itr>=3) {
164 piop = &tree[bos];
165 iop = bos;
166 while (iop<=(itr-3+bos) && (piop->itty==ITSP ||
167 (piop+1)->itty==ITSP || (piop+2)->itty!=ITSP)) {
168 iop++;
169 piop++;
170 }
171 if (iop<=(itr-3+bos)) {
172 tv1 = gval(piop); /*get value of first operand*/
173 rv1 = rval; /*relocation value*/
174 tv2 = gval(piop+1);
175 rv2 = rval;
176 topr = (piop+2)->itop; /*operator*/
177
1File: EXPR.C Page 4
178 /* handle operators */
179 if (topr == '+') {
180 tv1=+ tv2;
181 rv1 = ckrl1(rv1,rv2); /*relocation*/
182 }
183 else if (topr == '-') {
184 tv1 =- tv2;
185 rv1 = ckrl2(rv1,rv2); /*relocation*/
186 }
187 else {
188 switch(topr) { /*operator*/
189 case '/': /* division */
190 tv1 =/ tv2; break;
191 case '*': /* multiplication */
192 tv1 =* tv2; break;
193 case '&': /* logical and */
194 tv1 =& tv2; break;
195 case '!': /* logical or */
196 tv1 =| tv2; break;
197 case '<': /* left shift */
198 tv1 =<< tv2.wd2; break;
199 case '>': /* right shift */
200 tv1 =>> tv2.wd2; break;
201 default: /*invalid operator*/
202 exerr(2); return;
203 }
204 rv1 = ckrl3(rv1,rv2); /* relocation */
205 }
206
207 /*put new value in tree*/
208 if (iop==bos) {
209 bos =+ 2;
210 iop = bos;
211 }
212 piop = &tree[iop];
213 piop->itty = ITCN; /*must be constant*/
214 piop->itop = tv1; /*value*/
215 piop->itrl = rv1; /*relocation value*/
216
217 if (iop != bos) { /* push up the rest of the tree... */
218 i = iop + 2 - bos;
219 pitr = piop+2;
220 for(; i<itr; i++) {
221 piop++;
222 pitr++;
223 piop->swd1 = pitr->swd1;
224 piop->itop = pitr->itop;
225 }
226 }
227 itr =- 2;
228 goto exct1;
229 }
230 }
231
232 /* check for unary minus and unary plus*/
233 if (tree[bos+1].itty!=ITSP && tree[bos].itop.wd2=='?')
234 { exerr(3); return; }
235 if (tree[bos+1].itty!=ITSP || tree[bos].itty==ITSP) {
236 reloc = ABS;
1File: EXPR.C Page 5
237 ival = 0;
238 itype = ITCN;
239 return;
240 }
241
242 if(tree[bos+1].itop.wd2!='?') { /*end of statement*/
243 if(tree[bos+1].itop.wd2!='+') { /*ignore unary plus*/
244 if(tree[bos+1].itop.wd2!='-') { /* invalid operator */
245 exerr(4);
246 return;
247 }
248 tree[bos+1].itop = -gval(&tree[bos]);
249 tree[bos+1].itty = ITCN;
250 tree[bos+1].itrl = tree[bos].itrl;
251 bos++;
252 itr--;
253 goto exct1;
254 }
255 }
256 /* send results back to caller*/
257 if ((itype = tree[bos].itty)==ITCN)
258 ival = gval(&tree[bos]);
259 else {
260 ival = tree[bos].itop;
261 if(itype==ITSY && !(ival.ptrw2->flags&SYDF)) { /*undef symbol*/
262 reloc = ABS;
263 ival = 0;
264 itype = ITCN;
265 return;
266 }
267 }
268 get_val(tree[bos].itrl);
269 }
270
271 /*
272 *if defined symbol get value and say constant
273 * except for externals and equated registers
274 */
275 get_val(reloc_val)
276 int reloc_val;
277 {
278 if(itype==ITSY && (ival.ptrw2->flags&(SYXR|SYER))==0) {
279 if(ival.ptrw2->flags&SYRA) /*get symbol relocation factor*/
280 reloc = DATA;
281 else if(ival.ptrw2->flags&SYRO)
282 reloc = TEXT;
283 else if(ival.ptrw2->flags&SYBS)
284 reloc = BSS;
285 else reloc = ABS;
286 ival = ival.ptrw2->vl1; /*symbol vaue*/
287 itype = ITCN; /*constant*/
288 }
289 else
290 if(itype == ITSY && ival.ptrw2->flags&SYXR) { /*external symbol*/
291 fixext(ival.ptrw2);
292 reloc = EXTRN;
293 }
294 else
295 reloc = reloc_val; /*relocation value of item*/
1File: EXPR.C Page 6
296 }
297
298 exerr(n) /* [vlh] */
299 int n;
300 {
301 uerr(6);
302 ival = 0;
303 itype = ITCN;
304 reloc = ABS;
305 }
306
307 /*
308 * get precedence of a operator
309 * call with
310 * operator
311 * returns
312 * precedence
313 */
314 gprc(dprc)
315 {
316
317 switch(dprc) {
318
319 case '+':
320 case '-':
321 case '&': /* and*/
322 case '!': /* or*/
323 case '^': /*exclusive or*/
324 return(PPM);
325
326 case '/':
327 case '*':
328 case '<': /*left shift*/
329 case '>': /*right shift*/
330 return(PMD);
331
332 case '(':
333 if(lastopr)
334 return(PLP);
335 break;
336
337 case ')':
338 if(!prcnt) /*no left parens*/
339 break;
340 return(PRP);
341
342 }
343 return(PEE); /*end of expression*/
344 }
345
346 /*
347 * get value from an it format item
348 * call with
349 * address of it format item
350 * returns
351 * the value
352 * relocation value in rval
353 * calls uerr if it cant get a value
354 */
1File: EXPR.C Page 7
355 long gval(avwrd)
356 struct it *avwrd;
357 {
358 register struct it *vwrd;
359 register struct symtab *p;
360
361 vwrd = avwrd;
362 if(vwrd->itty == ITCN) { /*constant*/
363 rval = vwrd->itrl;
364 return(vwrd->itop); /*value*/
365 }
366 if(vwrd->itty != ITSY) {
367 uerr(6);
368 rval = ABS;
369 return(0);
370 }
371 p = vwrd->itop.ptrw2;
372 if(p->flags&SYXR) { /*external reference*/
373 fixext(p);
374 return(0);
375 }
376 if((p->flags&SYDF) != SYDF || (p->flags&SYER)) {
377 uerr(6);
378 rval = ABS;
379 return(0);
380 }
381 rval = (p->flags&SYRA) ? DATA : (p->flags&SYRO) /* reloc of item */
382 ? TEXT : (p->flags&SYBS) ? BSS : ABS;
383 return(p->vl1);
384 }
385
386 /*
387 * get items for expression evaluator (pass one)
388 * returns:
389 * item type in itype
390 * item value in ival
391 * item in it format in exitm
392 */
393 p1gi()
394 {
395 if(fcflg) /*used item so must pass it*/
396 gterm(TRUE);
397 if(!fcflg && ckspc(fchr)==1) {
398 fcflg=1; /*just pass first character*/
399 itype=ITSP; /*special char*/
400 ival=fchr; /*value is the char*/
401 }
402 else { /*get a whole term*/
403 fcflg = 0;
404 gterm(TRUE); /*get a term*/
405 if(itype==ITSY) { /* got a symbol*/
406 ival.ptrw2=lemt(sirt,FALSE); /*look it up in main table*/
407 if(ival.ptrw2==lmte) /*not there before*/
408 mmte(); /*put it in table*/
409 }
410 else
411 if(itype == ITCN)
412 exitm.itrl = reloc;
413 }
1File: EXPR.C Page 8
414 exitm.itty = itype;
415 exitm.itop = ival;
416 }
417
418 /*
419 * get items for expression evaluator (pass 2)
420 * returns:
421 * item type in itype
422 * item value in ival
423 * item in it format in exitm
424 */
425 p2gi()
426 {
427 if(pitw==pnite) { /*end of statement*/
428 itype = ITSP;
429 ival = ' '; /*blank*/
430 exitm.itty = itype;
431 exitm.itop = ival;
432 return;
433 }
434
435 if((itype = pitw->itty) == ITPC) { /*vlh*/
436 pitw->itop = loctr;
437 if (p2flg || format==6) itype = pitw->itty = ITCN;
438 }
439 ival = pitw->itop; /*value*/
440 exitm.swd1 = pitw->swd1;
441 exitm.itop = ival;
442 pitw++;
443 }
444
445 /*
446 *check for a special character
447 * call with
448 * character to check
449 * returns:
450 * 0 => character is number or letter
451 */
452 ckspc(acksc)
453 {
454 register cksc;
455
456 cksc = acksc;
457 if (isalnum(cksc)) return(0);
458 return((index("_~*.@$%\'",cksc) != -1) ? 0 : 1); /*[vlh] compacted*/
459 }
460
461 /* generate new relocation for op + op*/
462 ckrl1(rv1,rv2)
463 {
464 if(rv1==rv2)
465 return(rv1);
466 if(rv1==ABS || rv2==ABS)
467 return(rv1+rv2); /*the one that is not ABS*/
468 uerr(27);
469 return(ABS);
470 }
471
472 /*generate new relocation for op - op*/
1File: EXPR.C Page 9
473 ckrl2(rv1,rv2)
474 {
475 if(rv2==EXTRN)
476 uerr(26);
477 if(rv1==rv2)
478 return(ABS);
479 if(rv2==ABS)
480 return(rv1+rv2);
481 uerr(27);
482 return(ABS);
483 }
484
485 /*generate new relocation for op /*&|<>^! op*/
486 ckrl3(rv1,rv2)
487 {
488 if(rv1!=ABS || rv2!=ABS)
489 uerr(27);
490 return(ABS);
491 }
492
493 fixext(p)
494 struct symtab *p;
495 {
496 if(extflg)
497 uerr(36); /*two externals in expr*/
498 extflg++;
499 extref = p->vl1.wd2; /*get external #*/
500 rval = EXTRN;
501 itype = ITCN;
502 ival = 0;
503 }
504
505

View File

@@ -0,0 +1,39 @@
$ num
AS68INIT.C
AS68INIT.lis
$ num
DIR.C
DIR.lis
$ num
EXPR.C
EXPR.lis
$ num
MAIN.C
MAIN.lis
$ num
MISC.C
MISC.lis
$ num
PASS1A.C
PASS1A.lis
$ num
PASS2.C
PASS2.lis
$ num
SYMT.C
SYMT.lis
$ num
VERSION.C
VERSION.lis
$ num
AS68.H
AS68.lst
$ num
COUT.H
COUT.lst
$ num
CTYPE.H
CTYPE.lst
$ num
MACHINE.H
MACHINE.lst

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
/*#define MC68000 1*/ /* 68000 version */
/*#define VAX 1*/ /* VAX Version */
#define PDP11 1 /* PDP-11 Version*/
/*#define CPM 1*/ /* CP/M Operating System*/
#define UNIX 1 /* UNIX Operating System*/
/*#define VMS 1*/ /* VMS Operating System*/

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
#define MC68000 1 /* 68000 version */
/*#define VAX 1*/ /* VAX Version */
/*#define PDP11 1*/ /* PDP-11 Version*/
#define CPM 1 /* CP/M Operating System*/
/*#define UNIX 1*/ /* UNIX Operating System*/
/*#define VMS 1*/ /* VMS Operating System*/

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
/*#define MC68000 1*/ /* 68000 version */
#define VAX 1 /* VAX Version */
/*#define PDP11 1*/ /* PDP-11 Version*/
/*#define CPM 1*/ /* CP/M Operating System*/
/*#define UNIX 1*/ /* UNIX Operating System*/
#define VMS 1 /* VMS Operating System*/

View File

@@ -0,0 +1,11 @@
1File: MACHINE.H Page 1
1 /*
2 * Use this file to determine what kind of machine you want the
3 * Alcyon stuff to run on ....
4 */
5 /*#define MC68000 1*/ /* 68000 version */
6 #define VAX 1 /* VAX Version */
7 /*#define PDP11 1*/ /* PDP-11 Version*/
8 /*#define CPM 1*/ /* CP/M Operating System*/
9 /*#define UNIX 1*/ /* UNIX Operating System*/
10 #define VMS 1 /* VMS Operating System*/

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
/*#define MC68000 1*/ /* 68000 version */
#define VAX 1 /* VAX Version */
/*#define PDP11 1*/ /* PDP-11 Version*/
/*#define CPM 1*/ /* CP/M Operating System*/
/*#define UNIX 1*/ /* UNIX Operating System*/
#define VMS 1 /* VMS Operating System*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
$1stat machine.h=rw
$1pip machine.h=machine.68k
$1cp68 -i 0$1 DIR.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic DIR.s -L
$1as68 -f $1 -s 0$1 -l -u DIR.s
era dir.s
$1cp68 -i 0$1 EXPR.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic EXPR.s -L
$1as68 -f $1 -s 0$1 -l -u EXPR.s
era expr.s
$1cp68 -i 0$1 MAIN.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic MAIN.s -L
$1as68 -f $1 -s 0$1 -l -u MAIN.s
era main.s
$1cp68 -i 0$1 misc.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic MISC.s -L
$1as68 -f $1 -s 0$1 -l -u MISC.s
era misc.s
$1cp68 -i 0$1 PASS1A.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic PASS1A.s -L
$1as68 -f $1 -s 0$1 -l -u PASS1A.s
era pass1a.s
$1cp68 -i 0$1 PASS2.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic PASS2.s -L
$1as68 -f $1 -s 0$1 -l -u PASS2.s
era pass2.s
$1cp68 -i 0$1 STRNCMP.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic STRNCMP.s -L
$1as68 -f $1 -s 0$1 -l -u STRNCMP.s
era strncmp.s
$1cp68 -i 0$1 SYMT.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic SYMT.s -L
$1as68 -f $1 -s 0$1 -l -u SYMT.s
era symt.s
relink $1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,109 @@
/*
Copyright 1981
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
/* reduce long relative branches to short if possible*/
#include "as68.h"
int nitleft;
char tfilname[];
int p2gi();
long lseek();
pass1a()
{
register long reduced;
register int i, wsize;
register long oldpos,newpos; /* Old and new file seek pointers */
register j; /* temp */
pitix = itbuf;
nitleft = 0;
reduced = 0; itoffset = 0; stbuf[0].itrl = 0;
wsize = 3*sizeof stbuf[0]; /* [vlh] don't calculate many times */
close(itfn);
LASTCHTFN = itfnc;
itfn = openfi(tfilname,2,1); /*open it for update*/
while(ristb()) {
opcpt = stbuf[2].itop.ptrw2; /*ptr to opcode entry in main tab*/
if(!(opcpt->flags&OPDR)) { /*not a directive*/
format = (opcpt->flags)&OPFF;
p1inlen = stbuf[1].itrl; /*pass 1 instr length guess*/
if(((format==6 && p1inlen==4) || opcpt==jsrptr) &&
(rlflg=stbuf[3].itrl)==TEXT) {
nite = stbuf[0].itrl & 0377;/* # of it entries */
pnite = &stbuf[nite].itty; /*ptr to end of stmt*/
modelen = stbuf[2].itrl; /*instr mode length*/
opdix = ITOP1; /*first operand*/
pitw = &stbuf[ITOP1].itty; /*ptr to first operand*/
loctr = stbuf[3].itop - reduced;
expr(&p2gi);
ival =- loctr+2L;
if(itype==ITCN && !extflg && reloc!=ABS) {
if(format==9) { /*jsr*/
i = (ival>= -128 && ival<=127) ? p1inlen-2 :
(ival>= -32768 && ival<=32767) ? p1inlen-4 : 0;
if (!i)
continue;
stbuf[2].itop.ptrw2 = bsrptr; /*chng to bsr*/
}
else if(ival>= -128 && ival<=127) {
i = 2; /*[vlh]was 4 for ival=2*/
if (!ival) stbuf[2].itop.ptrw2 = nopptr;
}
else
continue;
fixsyadr(i);
reduced =+ i;
stbuf[1].itrl =- i; /*reduced somewhat*/
if(!stbuf[1].itrl)
stbuf[1].itrl = -1; /*ignore flag*/
oldpos=lseek(itfn,0L,1); /* Remember current position */
newpos= itoffset -
(stbuf[0].itrl*sizeof stbuf[0]);
if(lseek(itfn,newpos,0) < 0) {
rpterr("seek error on it file\n");
abort();
}
if(write(itfn,&stbuf[0],wsize) != wsize) {
rpterr("write error on it file\n");
abort();
}
lseek(itfn,oldpos,0);
}
}
}
else if(opcpt == endptr) {
savelc[TEXT] =- reduced;
return;
}
}
}
/* fix all symbol addresses that are text based and greater than loctr*/
/* fix means subtract 2 from them*/
fixsyadr(al)
{
register char **sx1, **sx2;
register l;
l = al;
/* loop thru symbol initial reference table*/
for(sx1= sirt; sx1<&sirt[SZIRT-1]; sx1 =+ 2) {
if(*(sx2 = sx1+1)==0) /* this chain is empty*/
continue;
/* symbols on one chain*/
sx2 = *sx2; /*first entry on this chain*/
while(1) {
if((sx2->flags&SYDF || sx2->flags&SYPC) && sx2->flags&SYRO &&
sx2->vl1 > loctr) /* [vlh] */
sx2->vl1 =- l;
if(sx2 == *sx1) /*end of chain*/
break;
sx2 = sx2->tlnk; /*next entry in chain*/
}
}
}

View File

@@ -0,0 +1,111 @@
1File: PASS1A.C Page 1
1 /*
2 Copyright 1981
3 Alcyon Corporation
4 8716 Production Ave.
5 San Diego, Ca. 92121
6 */
7
8 /* reduce long relative branches to short if possible*/
9
10 #include "as68.h"
11 int nitleft;
12 char tfilname[];
13 int p2gi();
14 long lseek();
15 pass1a()
16 {
17 register long reduced;
18 register int i, wsize;
19 register long oldpos,newpos; /* Old and new file seek pointers */
20 register j; /* temp */
21
22 pitix = itbuf;
23 nitleft = 0;
24 reduced = 0; itoffset = 0; stbuf[0].itrl = 0;
25 wsize = 3*sizeof stbuf[0]; /* [vlh] don't calculate many times */
26 close(itfn);
27 LASTCHTFN = itfnc;
28 itfn = openfi(tfilname,2,1); /*open it for update*/
29 while(ristb()) {
30 opcpt = stbuf[2].itop.ptrw2; /*ptr to opcode entry in main tab*/
31 if(!(opcpt->flags&OPDR)) { /*not a directive*/
32 format = (opcpt->flags)&OPFF;
33 p1inlen = stbuf[1].itrl; /*pass 1 instr length guess*/
34 if(((format==6 && p1inlen==4) || opcpt==jsrptr) &&
35 (rlflg=stbuf[3].itrl)==TEXT) {
36 nite = stbuf[0].itrl & 0377;/* # of it entries */
37 pnite = &stbuf[nite].itty; /*ptr to end of stmt*/
38 modelen = stbuf[2].itrl; /*instr mode length*/
39 opdix = ITOP1; /*first operand*/
40 pitw = &stbuf[ITOP1].itty; /*ptr to first operand*/
41 loctr = stbuf[3].itop - reduced;
42 expr(&p2gi);
43 ival =- loctr+2L;
44 if(itype==ITCN && !extflg && reloc!=ABS) {
45 if(format==9) { /*jsr*/
46 i = (ival>= -128 && ival<=127) ? p1inlen-2 :
47 (ival>= -32768 && ival<=32767) ? p1inlen-4 : 0;
48 if (!i)
49 continue;
50 stbuf[2].itop.ptrw2 = bsrptr; /*chng to bsr*/
51 }
52 else if(ival>= -128 && ival<=127) {
53 i = 2; /*[vlh]was 4 for ival=2*/
54 if (!ival) stbuf[2].itop.ptrw2 = nopptr;
55 }
56 else
57 continue;
58 fixsyadr(i);
59 reduced =+ i;
1File: PASS1A.C Page 2
60 stbuf[1].itrl =- i; /*reduced somewhat*/
61 if(!stbuf[1].itrl)
62 stbuf[1].itrl = -1; /*ignore flag*/
63 oldpos=lseek(itfn,0L,1); /* Remember current position */
64 newpos= itoffset -
65 (stbuf[0].itrl*sizeof stbuf[0]);
66 if(lseek(itfn,newpos,0) < 0) {
67 rpterr("seek error on it file\n");
68 abort();
69 }
70 if(write(itfn,&stbuf[0],wsize) != wsize) {
71 rpterr("write error on it file\n");
72 abort();
73 }
74 lseek(itfn,oldpos,0);
75 }
76 }
77 }
78 else if(opcpt == endptr) {
79 savelc[TEXT] =- reduced;
80 return;
81 }
82 }
83 }
84
85 /* fix all symbol addresses that are text based and greater than loctr*/
86 /* fix means subtract 2 from them*/
87 fixsyadr(al)
88 {
89 register char **sx1, **sx2;
90 register l;
91
92 l = al;
93 /* loop thru symbol initial reference table*/
94 for(sx1= sirt; sx1<&sirt[SZIRT-1]; sx1 =+ 2) {
95 if(*(sx2 = sx1+1)==0) /* this chain is empty*/
96 continue;
97
98 /* symbols on one chain*/
99 sx2 = *sx2; /*first entry on this chain*/
100 while(1) {
101 if((sx2->flags&SYDF || sx2->flags&SYPC) && sx2->flags&SYRO &&
102 sx2->vl1 > loctr) /* [vlh] */
103 sx2->vl1 =- l;
104 if(sx2 == *sx1) /*end of chain*/
105 break;
106 sx2 = sx2->tlnk; /*next entry in chain*/
107 }
108 }
109 }

View File

@@ -0,0 +1,841 @@
/*
Copyright 1981
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
/*
* pass two for the 68000 assembler
* Bill Allen
* March 1980
*/
#include "as68.h"
#include "cout.h" /*c.out header definition & MAGIC*/
#define MOVEA 0100
int p2gi();
extern char tfilname[]; /*name of it file*/
extern char initfnam[]; /*name of the initilization file*/
int (*p2direct[])();
int opf1(), opf2(), opf3(), opf4(), opf5(), relbr(), opf7(), opf8();
int opf9(), opf11(), opf12(), opf13(), opf15(), opf17(), opf20();
int opf21(), opf22(), opf23();
int (*opfary[])() {
0, /*0*/
opf1, /*1*/
opf2, /*2*/
opf3, /*3*/
opf4, /*4*/
opf5, /*5*/
relbr, /*6*/
opf7, /*7*/
opf8, /*8*/
opf9, /*9*/
opf4, /*10*/
opf11, /*11*/
opf12, /*12*/
opf13, /*13*/
opf9, /*14*/
opf15, /*15*/
opf17, /*16*/
opf17, /*17*/
opf13, /*18*/
opf11, /*19*/
opf20, /*20*/
opf21, /*21*/
opf22, /*22*/
opf23, /*23*/
opf9, /*24*/
opf9, /*25*/
opf5, /*26*/ /* [vlh] cmp, chk, extention verification */
opf4, /*27*/ /* [vlh] addx, subx, extension verification */
opf13, /*28*/ /* [vlh] swap, extension verification */
opf9, /*29*/ /* [vlh] pea, extention verification */
opf15 /*30*/ /* [vlh] lea, extension verification */
};
#define LSTFRMT 30
int f1mode[] {0,0,0100,0,0200};
int f2mode[] {0,0,0100,0,0200};
int f3mode[] {0,010000,030000,0,020000};
int f15mode[] {0,0,0300,0,0700};
int f5mode[] {0,0,0100,0,0200};
int f5amode[] {0,0,0300,0,0700};
int f13mode[] {0,0,0200,0,0300};
int f23mode[] {0,0400,0500,0,0600};
int rlbits[5]; /*holds relocation bits for instr*/
int pline; /*number of last printed line*/
int brkln2 077777; /*pass 2 break line number for debugging*/
int prsp; /*special print alignment flag*/
int amode; /*addressing mode*/
int nitleft;
/*pass two driver*/
pass2()
{
register short *p;
register i;
register (*dirop)();
pitix = itbuf; /* This is init for doitrd*/
xline = LPP;
nitleft = 0;
lbuf.nunused = tbuf.nunused = dabuf.nunused = drbuf.nunused = 512;
lbuf.fildes = lfn; /*set buffered io for binary file*/
lbuf.xfree = &lbuf.buff[0];
tbuf.fildes = trbfn; /*set buffered io for text reloc bits file*/
tbuf.xfree = &tbuf.buff[0];
dabuf.fildes = dafn; /*set buffered io for data bytes*/
dabuf.xfree = &dabuf.buff[0];
drbuf.fildes = drbfn; /*set buffered io for data reloc bits*/
drbuf.xfree = &drbuf.buff[0];
couthd.ch_magic = MAGIC;/*c.out magic number*/
if(savelc[TEXT]&1)
savelc[TEXT]++; /*make it even*/
couthd.ch_tsize = savelc[TEXT]; /*text size*/
if(savelc[DATA]&1)
savelc[DATA]++; /*make it even*/
couthd.ch_dsize = savelc[DATA]; /*data size*/
couthd.ch_bsize = savelc[BSS]; /*bss size*/
/*symbol table size is not known now -- it is set at end of pass 2*/
/* entry point and stack size are zero for now*/
p = &couthd;
for(i=0; i<HDSIZE/2; i++) {
putw(*p++,&lbuf); /*write the file header words*/
}
savelc[0] = 0; savelc[1] = 0; savelc[2] = 0; savelc[3] = 0;
loctr = 0; /*location counter*/
rlflg = TEXT; /*TEXT relocatable*/
p2flg = 1; /*pass two*/
#ifdef UNIX
if (lseek(ifn,0L,0) == -1) { /*beginning of source*/
rpterr("seek error on source file\n");
abort();
}
#else
close(ifn); /* This way for goddamn Whitesmith's */
ifn=open(sfname,0,0); /* Re-open the fucking source file */
if(ifn < 0) /* Couldn't */
{
printf("Unable to open file %s\n",sfname);
abort();
}
#endif
close(itfn);
LASTCHTFN = itfnc;
itfn = openfi(tfilname,0); /*open it for reading*/
pline = 1; /*no lines printed*/
fchr=gchr(); /*get first char*/
while(ristb()) { /*pass 2 main loop*/
p2absln = stbuf[0].itop; /*line number*/
if(p2absln>=brkln2) /*for debugging the assembler*/
i=0;
opcpt = stbuf[2].itop.ptrw2; /*ptr to opcode entry in main tab*/
nite = stbuf[0].itrl & 0377; /*number of it entries*/
pnite = &stbuf[nite]; /*ptr to end of stmt*/
modelen = stbuf[2].itrl; /*instr mode length*/
p1inlen = stbuf[1].itrl; /*pass 1 instr length guess*/
opdix = ITOP1; /*first operand*/
pitw = &stbuf[ITOP1]; /*ptr to first operand*/
prsp = 0; /*special print flag off*/
instrlen = 2; /*default for print*/
if(opcpt->flags&OPDR) { /*opcode is a directive*/
i = opcpt->vl1; /*directive number*/
dirop = p2direct[i];
(*dirop)(); /*handle directive*/
}
else {
gcist(); /*generate code for one statement*/
}
}
}
/* generate code for an instruction*/
/* call with*/
/* intermediate text for instruction in stbuf*/
gcist()
{
register i,j;
if(stbuf[0].itty != ITBS) /*beginning of statement*/
abort();
format = (opcpt->flags)&OPFF;
in_err = 0; /*[vlh] no error this instruction, yet*/
ival = 0; /*initial value for possible operand*/
reloc = ABS;
instrlen = 2; /*at least 2 bytes*/
ins[0] = opcpt->vl1; /*opcode value*/
rlbits[0] = INSABS; /*instruction absolute*/
pins = &ins[1];
prlb = &rlbits[1];
if(nite>ITOP1) { /*operands*/
if(!format) {
uerr(9);
}
else if(format>LSTFRMT) /* [vlh] was a magic number... */
abort();
else {
(*opfary[format])();
}
}
if (!ckein() && !in_err) /* at end of statement ?? */
uerr(6);
print(1); /*print source*/
loctr =+ p1inlen;
if (!in_err && p1inlen != instrlen) /* [vlh] 2nd pass error recovery */
uerr(38);
outinstr(); /*write out instr binary*/
}
/* relative branches*/
relbr()
{
expr(&p2gi);
if(extflg) { /*external reference*/
instrlen =+ 2; /*long relative*/
*pins++ = ival; /*pass constant part*/
*prlb++ = (extref<<3)|EXTREL; /*ext ref*/
return;
}
ival =- (loctr+2); /*calc relative offset*/
if(itype!=ITCN || reloc != rlflg) {
uerr(22); /*invalid relative branch*/
ival = 0;
}
reloc = ABS;
if(p1inlen==4) { /*long displacement*/
if(ival< (-32768L) || ival > (32767L))
uerr(22);
instrlen =+ 2;
*pins++ = ival;
*prlb++ = DABS; /*data absolute*/
}
else { /*short displacement*/
if (ival>127 || ival<-128)
uerr(22);
ins[0] =| (ival.wd2&0377);
}
if (!ival) { /* make it a nop */
opcpt = nopptr;
ins[0] = opcpt->vl1.wd2;
pins = &ins[1];
if (modelen==4) {
*pins++ = opcpt->vl1.wd2;
rlbits[1] = INSABS;
}
}
in_err++; /* ignore extra eg. bra *+$d04(pc) vs. bra *+d04 */
}
/* format one -- add, sub, and, or, cmp, etc.*/
/* one operand must be a D reg (or A reg dest for add, sub, or cmp)*/
opf1()
{
register int *p;
if(get2ops())
return;
if (ins[0]==AND || ins[0]==OR)
if (cksprg(&opnd[1],CCR) || cksprg(&opnd[1],SR)) {
if (ins[0]==AND) opcpt = andiptr;
else opcpt = oriptr;
ins[0] = opcpt->vl1.wd2;
format = (opcpt->flags)&OPFF;
ccr_or_sr();
return;
}
p = f1mode;
if(ckdreg(&opnd[1])) { /*destn is D reg*/
if((opcpt==andptr||opcpt==orptr)&&ckareg(&opnd[0])) /*A source*/
uerr(20);
makef1(opnd[1].ea,p[modelen],&opnd[0]); /*make instr*/
return;
}
else if(ckdreg(&opnd[0]) && memalt(&opnd[1])) { /*source is D reg*/
if (pcea(&opnd[1])) uerr(10);
makef1(opnd[0].ea,p[modelen]+0400,&opnd[1]);
return;
}
else if(ckareg(&opnd[1])) { /*A reg is dstn*/
if(opcpt==addptr)
opcpt = addaptr;
else if(opcpt==cmpptr)
opcpt = cmpaptr;
else if(opcpt==subptr)
opcpt = subaptr;
else {
uerr(20);
return;
}
format = (opcpt->flags)&OPFF;
opnd[1].ea =& 07;
p = f15mode;
makef1(opnd[1].ea,p[modelen],&opnd[0]); /*make instr*/
return;
}
else if(!makeimm()) /*make an immediate instr*/
uerr(20);
}
/* format 2 -- addi, andi, subi, etc*/
opf2()
{
if(get2ops())
return;
if(ins[0]==ANDI || ins[0]==ORI || ins[0]==EORI) {
if(cksprg(&opnd[1],CCR) || cksprg(&opnd[1],SR)) {
ccr_or_sr();
return;
}
}
if(opnd[0].ea != IMM) {
uerr(9);
return;
}
if(!dataalt(&opnd[1]) || pcea(&opnd[1])) {
uerr(20);
return;
}
genimm();
}
/*format #3 -- move and movea*/
opf3()
{
register i,j,k;
if(get2ops())
return;
if(cksprg(&opnd[1],CCR)) {
ins[0] = MOVECCR;
opf3l1:
if (modelen==1 || modelen==4) uerr(34);
if(anysprg(&opnd[0]))
uerr(20);
ins[0] =| opnd[0].ea;
if(!dataea(&opnd[0]))
uerr(9);
doea(&opnd[0]);
return;
}
if(cksprg(&opnd[1],SR)) {
ins[0] = MOVESR;
goto opf3l1;
}
if(cksprg(&opnd[0],SR)) {
if (modelen==1 || modelen==4)
uerr(34);
if(anysprg(&opnd[1]))
uerr(20);
ins[0] = SRMOVE | opnd[1].ea;
if(!dataalt(&opnd[1]) || pcea(&opnd[1]))
uerr(10);
doea(&opnd[1]);
return;
}
if(cksprg(&opnd[0],USP)) {
if (modelen == 1)
uerr(34); /* default is word, can't test */
if (!ckareg(&opnd[1]))
uerr(33);
ins[0] = MOVEUSP|8|(opnd[1].ea&7);
return;
}
if(cksprg(&opnd[1],USP)) {
if (modelen == 1)
uerr(34); /* default is word, can't test */
if (!ckareg(&opnd[0]))
uerr(33);
ins[0] = MOVEUSP|(opnd[0].ea&7);
return;
}
k = ins[0];
ins[0] =| f3mode[modelen];
ckbytea();
ins[0] =| opnd[0].ea; /*source ea*/
doea(&opnd[0]);
ins[0] =| (opnd[1].ea&7)<<9; /*dest register*/
ins[0] =| (opnd[1].ea&070)<<3; /*dest mode*/
doea(&opnd[1]);
if(k==MOVEA) {
if(dataea(&opnd[1]))
uerr(20);
}
else if((pcea(&opnd[1]) && dataea(&opnd[1])) || opnd[1].ea==IMM)
uerr(20);
}
/* format 4 -- abcd, sbcd */
/* format 10 -- cmpm*/
/* format 27 -- addx, subx */
opf4()
{
if(get2ops())
return;
if (format==27) { /*addx,subx add in size bits*/
ins[0] =| f1mode[modelen];
}
else if(format==10) { /*cmpm*/
if((opnd[0].ea&070)!=INDINC || (opnd[1].ea&070)!=INDINC)
uerr(20);
ins[0] =| f1mode[modelen] | ((opnd[0].ea&7)|((opnd[1].ea&7)<<9));
return;
}
if(ckdreg(&opnd[0]) && ckdreg(&opnd[1])) {
ins[0] =| ((opnd[0].ea&7)|((opnd[1].ea&7)<<9));
return;
}
if((opnd[0].ea&070)==DECIND && (opnd[1].ea&070)==DECIND) {
ins[0] =| 010 | ((opnd[0].ea&7)|((opnd[1].ea&7)<<9));
return;
}
uerr(20);
}
/*format 5 -- div, mul*/
/*format 26 -- cmp, chk */
opf5()
{
if(get2ops())
return;
if(!ckdreg(&opnd[1])) {
if(opcpt==cmpptr) {
if(!dataea(&opnd[1])) /* [vlh] made define */
ins[0] =| f5amode[modelen]; /* was pumode */
else if(makeimm())
return;
else
uerr(20);
}
else
uerr(20);
}
if(opcpt==cmpptr) {
ins[0] =| f5mode[modelen]; /* was pumode */
ckbytea();
}
else if(!dataea(&opnd[0]))
uerr(20);
ins[0] =| (opnd[1].ea&7)<<9 | opnd[0].ea;
doea(&opnd[0]);
}
#define BTST 0000
/* format 7 -- bit instrs -- btst, bclr, bset, etc*/
opf7()
{
if(get2ops())
return;
if(opnd[1].ea==IMM||(ins[0]!=BTST&&pcea(&opnd[1]))||ckareg(&opnd[1]))
uerr(20);
if(ckdreg(&opnd[0])) {
ins[0] =| (opnd[0].ea<<9)|0400;
}
else { /*static bit #*/
if(opnd[0].con<0L || opnd[0].con>31 ||
(opnd[1].ea&INDIRECT&&opnd[0].con>7)) /* [vlh] */
uerr(23);
if(opnd[0].ea != IMM)
uerr(17);
ins[0] =| 04000;
dodisp(&opnd[0]);
}
if (modelen==1 && !(memea(&opnd[1]))) /*[vlh]*/
uerr(20);
else if (!(ckdreg(&opnd[1])) && modelen==4)
uerr(20);
ins[0] =| opnd[1].ea;
doea(&opnd[1]);
}
/* format 8 -- shifts and rotates*/
opf8()
{
register i;
getea(0); /*get first operand*/
if(pitw >= pnite) { /*end of all ops*/
if(ckdreg(&opnd[0])) { /*shift dreg one bit*/
cpop01(); /*copy opnd 0 to 1*/
opnd[0].ea = IMM;
opnd[0].con = 1L;
if (!ckdreg(&opnd[1])) uerr(20);
opf8l1:
if(opnd[0].con<1 || opnd[0].con>8) /*[vlh legal range 1..8*/
uerr(37);
ins[0] =| ((opnd[0].con.wd2&7)<<9)|f1mode[modelen]|opnd[1].ea;
return;
}
i = (ins[0]&077)<<6;
ins[0] =& 0177700;
ins[0] =| 0300|i|opnd[0].ea;
if(!memalt(&opnd[0]) || pcea(&opnd[0]) || modelen != 2)
uerr(20);
doea(&opnd[0]);
return;
}
if(!ckcomma()) {
uerr(10);
return;
}
getea(1); /*get second operand*/
if(!ckdreg(&opnd[1])) /* [vlh] second operand must be dreg */
uerr(20);
if(ckdreg(&opnd[0])) { /*first op is D reg*/
ins[0] =| (opnd[0].ea<<9)|040; /*reg # and reg bit*/
}
else {
if(opnd[0].ea != IMM)
uerr(20);
goto opf8l1;
}
ins[0] =| f1mode[modelen] | opnd[1].ea; /*put in size and reg #*/
}
/* format 9 -- jmp, jsr */
/* format 14 -- stop */
/* format 24 -- clr, neg, negx, not */
/* format 25 -- s?? */
/* format 29 -- pea */
/* one operand instructions -- jmp, clr, neg, not, sge, etc.*/
opf9()
{
getea(0);
if(format==24) { /*clr, not, etc*/
ins[0] =| f1mode[modelen]; /*add size bits*/
if(!dataalt(&opnd[0]) || pcea(&opnd[0]))
uerr(20);
}
else if(format==25) { /*tas,scc, etc*/
if(ckareg(&opnd[0]) || pcea(&opnd[0]) || opnd[0].ea==IMM)
uerr(20);
}
else if(format==14) { /*stop*/
if(modelen!=2 || opnd[0].ea!=IMM)
uerr(20);
doea(&opnd[0]);
return;
}
else if(!controlea(&opnd[0])) /*jmp, jsr, etc*/
uerr(20);
ins[0] =| opnd[0].ea;
doea(&opnd[0]);
}
/* format 11 -- dbcc*/
/* format 19 -- link*/
opf11()
{
if(get2ops())
return;
if(format==19) { /*link*/
if(!ckareg(&opnd[0]))
uerr(33);
if(opnd[1].ea != IMM)
uerr(17);
}
else {
if(!ckdreg(&opnd[0]))
uerr(33);
if(opnd[1].drlc!=rlflg) /*[vlh]don't chk opnd[1].ea!=LADDR||SADDR*/
uerr(22);
opnd[1].con =- (loctr+2L);
cksize(&opnd[1]);
opnd[1].drlc = ABS; /*not relocatable*/
}
ins[0] =| opnd[0].ea&7; /*put in reg #*/
dodisp(&opnd[1]);
}
/* format 12 -- exg*/
opf12()
{
register i;
if(get2ops())
return;
if(ckdreg(&opnd[0])) {
if(ckdreg(&opnd[1])) { /*exchange D regs*/
ins[0] =| 0100 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
return;
}
if(ckareg(&opnd[1])) { /*ins[0] <- A and D flag*/
ins[0] =| 0210 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
return;
}
}
if(ckareg(&opnd[0])) {
if(ckareg(&opnd[1])) { /*both a regs*/
ins[0] =| 0110 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
return;
}
if(ckdreg(&opnd[1])) { /*A and D regs*/
i = opnd[0].ea; /*exchg ea's*/
opnd[0].ea = opnd[1].ea;
opnd[1].ea = i;
ins[0] =| 0210 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
return;
}
}
uerr(20);
}
/* format 13 -- ext, unlk*/
/* format 18 -- trap*/
/* format 28 -- swap */
#define UNLK 047130
opf13()
{
getea(0);
if(format==18) { /*trap*/
if(opnd[0].con<0 || opnd[0].con>15)
uerr(15);
ins[0] =| opnd[0].con.wd2;
return;
}
if(ins[0]==UNLK) { /*unlk instr*/
if(!ckareg(&opnd[0]))
uerr(20);
}
else {
if(!ckdreg(&opnd[0]))
uerr(20);
if (format==13) /* ext */
ins[0] =| f13mode[modelen];
}
ins[0] =| opnd[0].ea&7;
}
/* format 15 -- adda, cmpa, suba*/
/* format 30 -- lea */
opf15()
{
register i;
if(get2ops())
return;
if(!ckareg(&opnd[1]))
uerr(33);
if(format==30) {
i = 0700;
if(!controlea(&opnd[0]))
uerr(20);
}
else
i = f15mode[modelen];
makef1(opnd[1].ea&7,i,&opnd[0]);
if (format==15 && opnd[0].ea != 071) cksize(&opnd[0]);
}
/*formats 16 and 17 -- addq, inc, subq, dec*/
opf17()
{
if(format==16) { /*inc or dec*/
clrea(&opnd[0]);
opnd[0].ea = IMM;
opnd[0].con = 1L;
opnd[0].drlc = ABS;
getea(1);
}
else {
if(get2ops())
return;
}
if(opnd[0].ea != IMM || !altea(&opnd[1]) || pcea(&opnd[1]))
uerr(20);
if(opnd[0].con<=0 || opnd[0].con>8)
uerr(15);
if(modelen==1 && !dataea(&opnd[1]))
uerr(34);
ins[0] =| f1mode[modelen]|((opnd[0].con.wd2&7)<<9)|opnd[1].ea;
doea(&opnd[1]);
}
/* format 20 -- movem */
int regmsk0[] {0100000,040000,020000,010000,04000,02000,01000,0400,0200,
0100,040,020,010,4,2,1};
int regmsk1[] {1,2,4,010,020,040,0100,0200,0400,01000,02000,04000,010000,
020000,040000,0100000};
opf20()
{
register dr;
register i,j;
dr = 0;
if(getreg() != -1 || pitw->itty == ITRM) { /*regs to memory*/
if (pitw->itty != ITRM) { /* [vlh] */
pitw--;
j = getrlist(regmsk0);
}
else {
j = pitw->itop;
pitw++;
}
if(!ckcomma())
uerr(10);
}
else
dr = 02000;
getea(0);
if(dr) {
if(!ckcomma())
uerr(10);
if (pitw->itty != ITRM) /* [vlh] */
j = getrlist(regmsk1); /*mem to regs*/
else {
j = pitw->itop;
j = fixmask(j);
pitw++;
}
}
else {
if(controlea(&opnd[0]))
j = fixmask(j);
}
i = opnd[0].ea&070;
if(!controlea(&opnd[0]) && i!=INDINC && i!=DECIND)
uerr(20);
if(modelen==4) /*long*/
ins[0] =| 0100;
ins[0] =| opnd[0].ea|dr;
*pins++ = j; /*reg mask*/
*prlb++ = DABS;
instrlen =+ 2;
doea(&opnd[0]);
if (!dr) { /* 1st argument (2nd is reg list) */
if (pcea(&opnd[0]) || (opnd[0].ea&070)==INDINC)
uerr(20); /* xx(pc), xx(pc,dx), -(ax) */
}
else /* 2nd argument (1st is reg list) */
if ((opnd[0].ea&070)==DECIND)
uerr(20); /* (ax)+ */
}
/*
* get a list of registers for the movem instr
* call with:
* ptr to reg-to-mem or mem-to-reg array of bits
*/
getrlist(ap)
int *ap;
{
register int *p,i,j;
register int mask;
p = ap;
mask = 0;
while((i=getreg()) != -1) {
if(ckitc(pitw,'-')) {
pitw++;
if((j=getreg()) == -1) {
uerr(40);
break;
}
while(i<=j)
mask =| p[i++];
}
else
mask =| p[i];
if(ckitc(pitw,'/'))
pitw++;
else
break;
}
if(!mask)
uerr(40);
return(mask);
}
/*reverse a movem register mask for control ea to memory*/
fixmask(msk)
{
register i,j,k;
k = (msk&1) ? 0100000 : 0;
i = 2;
j = 040000;
while(i) {
if(msk&i)
k =| j;
i =<< 1;
j =>> 1;
}
return(k);
}
/* format 21 -- movep*/
opf21()
{
register m,d;
register char *p;
if(get2ops())
return;
if(ckdreg(&opnd[0])) { /*d reg source*/
m = 0600;
d = opnd[0].ea;
p = &opnd[1];
}
else if(ckdreg(&opnd[1])) { /*d reg dest*/
m = 0400;
d = opnd[1].ea;
p = &opnd[0];
}
else {
uerr(20);
}
if((p->ea&070) != INDDISP)
uerr(20);
if(modelen == 4)
m =| 0100;
ins[0] =| (d<<9)|m|(p->ea&7);
*pins++ = p->con.wd2;
*prlb++ = p->drlc;
instrlen =+ 2;
}
/* format 22 -- moveq*/
opf22()
{
if(get2ops())
return;
if(opnd[0].ea != IMM)
uerr(17);
if(opnd[0].con>255L || opnd[0].con<-256L)
uerr(15);
if(!ckdreg(&opnd[1]))
uerr(33);
ins[0] =| (opnd[1].ea<<9) | (opnd[0].con.wd2&0377);
}
/* format 23 -- eor*/
opf23()
{
if(get2ops())
return;
if (cksprg(&opnd[1],CCR) || cksprg(&opnd[1],SR)) {
opcpt = eoriptr;
ins[0] = opcpt->vl1.wd2;
format = (opcpt->flags)&OPFF;
ccr_or_sr();
return;
}
if(!ckdreg(&opnd[0])) {
if(makeimm()) /*must be immediate*/
return;
uerr(20); /*or error*/
}
if(!dataalt(&opnd[1]) || pcea(&opnd[1]))
uerr(20);
ins[0] =| (opnd[0].ea<<9)|f23mode[modelen]|opnd[1].ea;
doea(&opnd[1]);
}

View File

@@ -0,0 +1,856 @@
1File: PASS2.C Page 1
1 /*
2 Copyright 1981
3 Alcyon Corporation
4 8716 Production Ave.
5 San Diego, Ca. 92121
6 */
7
8 /*
9 * pass two for the 68000 assembler
10 * Bill Allen
11 * March 1980
12 */
13
14 #include "as68.h"
15 #include "cout.h" /*c.out header definition & MAGIC*/
16
17 #define MOVEA 0100
18
19 int p2gi();
20
21 extern char tfilname[]; /*name of it file*/
22 extern char initfnam[]; /*name of the initilization file*/
23 int (*p2direct[])();
24
25 int opf1(), opf2(), opf3(), opf4(), opf5(), relbr(), opf7(), opf8();
26 int opf9(), opf11(), opf12(), opf13(), opf15(), opf17(), opf20();
27 int opf21(), opf22(), opf23();
28
29 int (*opfary[])() {
30 0, /*0*/
31 opf1, /*1*/
32 opf2, /*2*/
33 opf3, /*3*/
34 opf4, /*4*/
35 opf5, /*5*/
36 relbr, /*6*/
37 opf7, /*7*/
38 opf8, /*8*/
39 opf9, /*9*/
40 opf4, /*10*/
41 opf11, /*11*/
42 opf12, /*12*/
43 opf13, /*13*/
44 opf9, /*14*/
45 opf15, /*15*/
46 opf17, /*16*/
47 opf17, /*17*/
48 opf13, /*18*/
49 opf11, /*19*/
50 opf20, /*20*/
51 opf21, /*21*/
52 opf22, /*22*/
53 opf23, /*23*/
54 opf9, /*24*/
55 opf9, /*25*/
56 opf5, /*26*/ /* [vlh] cmp, chk, extention verification */
57 opf4, /*27*/ /* [vlh] addx, subx, extension verification */
58 opf13, /*28*/ /* [vlh] swap, extension verification */
59 opf9, /*29*/ /* [vlh] pea, extention verification */
1File: PASS2.C Page 2
60 opf15 /*30*/ /* [vlh] lea, extension verification */
61 };
62
63 #define LSTFRMT 30
64
65 int f1mode[] {0,0,0100,0,0200};
66 int f2mode[] {0,0,0100,0,0200};
67 int f3mode[] {0,010000,030000,0,020000};
68 int f15mode[] {0,0,0300,0,0700};
69 int f5mode[] {0,0,0100,0,0200};
70 int f5amode[] {0,0,0300,0,0700};
71 int f13mode[] {0,0,0200,0,0300};
72 int f23mode[] {0,0400,0500,0,0600};
73 int rlbits[5]; /*holds relocation bits for instr*/
74 int pline; /*number of last printed line*/
75 int brkln2 077777; /*pass 2 break line number for debugging*/
76 int prsp; /*special print alignment flag*/
77 int amode; /*addressing mode*/
78 int nitleft;
79 /*pass two driver*/
80 pass2()
81 {
82 register short *p;
83 register i;
84 register (*dirop)();
85
86 pitix = itbuf; /* This is init for doitrd*/
87 xline = LPP;
88 nitleft = 0;
89 lbuf.nunused = tbuf.nunused = dabuf.nunused = drbuf.nunused = 512;
90 lbuf.fildes = lfn; /*set buffered io for binary file*/
91 lbuf.xfree = &lbuf.buff[0];
92 tbuf.fildes = trbfn; /*set buffered io for text reloc bits file*/
93 tbuf.xfree = &tbuf.buff[0];
94 dabuf.fildes = dafn; /*set buffered io for data bytes*/
95 dabuf.xfree = &dabuf.buff[0];
96 drbuf.fildes = drbfn; /*set buffered io for data reloc bits*/
97 drbuf.xfree = &drbuf.buff[0];
98 couthd.ch_magic = MAGIC;/*c.out magic number*/
99 if(savelc[TEXT]&1)
100 savelc[TEXT]++; /*make it even*/
101 couthd.ch_tsize = savelc[TEXT]; /*text size*/
102 if(savelc[DATA]&1)
103 savelc[DATA]++; /*make it even*/
104 couthd.ch_dsize = savelc[DATA]; /*data size*/
105 couthd.ch_bsize = savelc[BSS]; /*bss size*/
106 /*symbol table size is not known now -- it is set at end of pass 2*/
107 /* entry point and stack size are zero for now*/
108 p = &couthd;
109 for(i=0; i<HDSIZE/2; i++) {
110 putw(*p++,&lbuf); /*write the file header words*/
111 }
112 savelc[0] = 0; savelc[1] = 0; savelc[2] = 0; savelc[3] = 0;
113 loctr = 0; /*location counter*/
114 rlflg = TEXT; /*TEXT relocatable*/
115 p2flg = 1; /*pass two*/
116 #ifdef UNIX
117 if (lseek(ifn,0L,0) == -1) { /*beginning of source*/
118 rpterr("seek error on source file\n");
1File: PASS2.C Page 3
119 abort();
120 }
121 #else
122 close(ifn); /* This way for goddamn Whitesmith's */
123 ifn=open(sfname,0,0); /* Re-open the fucking source file */
124 if(ifn < 0) /* Couldn't */
125 {
126 printf("Unable to open file %s\n",sfname);
127 abort();
128 }
129 #endif
130 close(itfn);
131 LASTCHTFN = itfnc;
132 itfn = openfi(tfilname,0); /*open it for reading*/
133 pline = 1; /*no lines printed*/
134 fchr=gchr(); /*get first char*/
135 while(ristb()) { /*pass 2 main loop*/
136 p2absln = stbuf[0].itop; /*line number*/
137 if(p2absln>=brkln2) /*for debugging the assembler*/
138 i=0;
139 opcpt = stbuf[2].itop.ptrw2; /*ptr to opcode entry in main tab*/
140 nite = stbuf[0].itrl & 0377; /*number of it entries*/
141 pnite = &stbuf[nite]; /*ptr to end of stmt*/
142 modelen = stbuf[2].itrl; /*instr mode length*/
143 p1inlen = stbuf[1].itrl; /*pass 1 instr length guess*/
144 opdix = ITOP1; /*first operand*/
145 pitw = &stbuf[ITOP1]; /*ptr to first operand*/
146 prsp = 0; /*special print flag off*/
147 instrlen = 2; /*default for print*/
148 if(opcpt->flags&OPDR) { /*opcode is a directive*/
149 i = opcpt->vl1; /*directive number*/
150 dirop = p2direct[i];
151 (*dirop)(); /*handle directive*/
152 }
153 else {
154 gcist(); /*generate code for one statement*/
155 }
156 }
157 }
158
159 /* generate code for an instruction*/
160 /* call with*/
161 /* intermediate text for instruction in stbuf*/
162 gcist()
163 {
164 register i,j;
165
166 if(stbuf[0].itty != ITBS) /*beginning of statement*/
167 abort();
168 format = (opcpt->flags)&OPFF;
169 in_err = 0; /*[vlh] no error this instruction, yet*/
170 ival = 0; /*initial value for possible operand*/
171 reloc = ABS;
172 instrlen = 2; /*at least 2 bytes*/
173 ins[0] = opcpt->vl1; /*opcode value*/
174 rlbits[0] = INSABS; /*instruction absolute*/
175 pins = &ins[1];
176 prlb = &rlbits[1];
177 if(nite>ITOP1) { /*operands*/
1File: PASS2.C Page 4
178 if(!format) {
179 uerr(9);
180 }
181 else if(format>LSTFRMT) /* [vlh] was a magic number... */
182 abort();
183 else {
184 (*opfary[format])();
185 }
186 }
187 if (!ckein() && !in_err) /* at end of statement ?? */
188 uerr(6);
189 print(1); /*print source*/
190
191 loctr =+ p1inlen;
192 if (!in_err && p1inlen != instrlen) /* [vlh] 2nd pass error recovery */
193 uerr(38);
194 outinstr(); /*write out instr binary*/
195 }
196
197 /* relative branches*/
198 relbr()
199 {
200 expr(&p2gi);
201 if(extflg) { /*external reference*/
202 instrlen =+ 2; /*long relative*/
203 *pins++ = ival; /*pass constant part*/
204 *prlb++ = (extref<<3)|EXTREL; /*ext ref*/
205 return;
206 }
207 ival =- (loctr+2); /*calc relative offset*/
208 if(itype!=ITCN || reloc != rlflg) {
209 uerr(22); /*invalid relative branch*/
210 ival = 0;
211 }
212 reloc = ABS;
213 if(p1inlen==4) { /*long displacement*/
214 if(ival< (-32768L) || ival > (32767L))
215 uerr(22);
216 instrlen =+ 2;
217 *pins++ = ival;
218 *prlb++ = DABS; /*data absolute*/
219 }
220 else { /*short displacement*/
221 if (ival>127 || ival<-128)
222 uerr(22);
223 ins[0] =| (ival.wd2&0377);
224 }
225 if (!ival) { /* make it a nop */
226 opcpt = nopptr;
227 ins[0] = opcpt->vl1.wd2;
228 pins = &ins[1];
229 if (modelen==4) {
230 *pins++ = opcpt->vl1.wd2;
231 rlbits[1] = INSABS;
232 }
233 }
234 in_err++; /* ignore extra eg. bra *+$d04(pc) vs. bra *+d04 */
235 }
236
1File: PASS2.C Page 5
237 /* format one -- add, sub, and, or, cmp, etc.*/
238 /* one operand must be a D reg (or A reg dest for add, sub, or cmp)*/
239 opf1()
240 {
241 register int *p;
242
243 if(get2ops())
244 return;
245 if (ins[0]==AND || ins[0]==OR)
246 if (cksprg(&opnd[1],CCR) || cksprg(&opnd[1],SR)) {
247 if (ins[0]==AND) opcpt = andiptr;
248 else opcpt = oriptr;
249 ins[0] = opcpt->vl1.wd2;
250 format = (opcpt->flags)&OPFF;
251 ccr_or_sr();
252 return;
253 }
254 p = f1mode;
255 if(ckdreg(&opnd[1])) { /*destn is D reg*/
256 if((opcpt==andptr||opcpt==orptr)&&ckareg(&opnd[0])) /*A source*/
257 uerr(20);
258 makef1(opnd[1].ea,p[modelen],&opnd[0]); /*make instr*/
259 return;
260 }
261 else if(ckdreg(&opnd[0]) && memalt(&opnd[1])) { /*source is D reg*/
262 if (pcea(&opnd[1])) uerr(10);
263 makef1(opnd[0].ea,p[modelen]+0400,&opnd[1]);
264 return;
265 }
266 else if(ckareg(&opnd[1])) { /*A reg is dstn*/
267 if(opcpt==addptr)
268 opcpt = addaptr;
269 else if(opcpt==cmpptr)
270 opcpt = cmpaptr;
271 else if(opcpt==subptr)
272 opcpt = subaptr;
273 else {
274 uerr(20);
275 return;
276 }
277 format = (opcpt->flags)&OPFF;
278 opnd[1].ea =& 07;
279 p = f15mode;
280 makef1(opnd[1].ea,p[modelen],&opnd[0]); /*make instr*/
281 return;
282 }
283 else if(!makeimm()) /*make an immediate instr*/
284 uerr(20);
285 }
286
287 /* format 2 -- addi, andi, subi, etc*/
288 opf2()
289 {
290 if(get2ops())
291 return;
292 if(ins[0]==ANDI || ins[0]==ORI || ins[0]==EORI) {
293 if(cksprg(&opnd[1],CCR) || cksprg(&opnd[1],SR)) {
294 ccr_or_sr();
295 return;
1File: PASS2.C Page 6
296 }
297 }
298 if(opnd[0].ea != IMM) {
299 uerr(9);
300 return;
301 }
302 if(!dataalt(&opnd[1]) || pcea(&opnd[1])) {
303 uerr(20);
304 return;
305 }
306 genimm();
307 }
308
309 /*format #3 -- move and movea*/
310 opf3()
311 {
312 register i,j,k;
313
314 if(get2ops())
315 return;
316 if(cksprg(&opnd[1],CCR)) {
317 ins[0] = MOVECCR;
318 opf3l1:
319 if (modelen==1 || modelen==4) uerr(34);
320 if(anysprg(&opnd[0]))
321 uerr(20);
322 ins[0] =| opnd[0].ea;
323 if(!dataea(&opnd[0]))
324 uerr(9);
325 doea(&opnd[0]);
326 return;
327 }
328 if(cksprg(&opnd[1],SR)) {
329 ins[0] = MOVESR;
330 goto opf3l1;
331 }
332 if(cksprg(&opnd[0],SR)) {
333 if (modelen==1 || modelen==4)
334 uerr(34);
335 if(anysprg(&opnd[1]))
336 uerr(20);
337 ins[0] = SRMOVE | opnd[1].ea;
338 if(!dataalt(&opnd[1]) || pcea(&opnd[1]))
339 uerr(10);
340 doea(&opnd[1]);
341 return;
342 }
343 if(cksprg(&opnd[0],USP)) {
344 if (modelen == 1)
345 uerr(34); /* default is word, can't test */
346 if (!ckareg(&opnd[1]))
347 uerr(33);
348 ins[0] = MOVEUSP|8|(opnd[1].ea&7);
349 return;
350 }
351 if(cksprg(&opnd[1],USP)) {
352 if (modelen == 1)
353 uerr(34); /* default is word, can't test */
354 if (!ckareg(&opnd[0]))
1File: PASS2.C Page 7
355 uerr(33);
356 ins[0] = MOVEUSP|(opnd[0].ea&7);
357 return;
358 }
359 k = ins[0];
360 ins[0] =| f3mode[modelen];
361 ckbytea();
362 ins[0] =| opnd[0].ea; /*source ea*/
363 doea(&opnd[0]);
364 ins[0] =| (opnd[1].ea&7)<<9; /*dest register*/
365 ins[0] =| (opnd[1].ea&070)<<3; /*dest mode*/
366 doea(&opnd[1]);
367 if(k==MOVEA) {
368 if(dataea(&opnd[1]))
369 uerr(20);
370 }
371 else if((pcea(&opnd[1]) && dataea(&opnd[1])) || opnd[1].ea==IMM)
372 uerr(20);
373 }
374
375 /* format 4 -- abcd, sbcd */
376 /* format 10 -- cmpm*/
377 /* format 27 -- addx, subx */
378 opf4()
379 {
380 if(get2ops())
381 return;
382 if (format==27) { /*addx,subx add in size bits*/
383 ins[0] =| f1mode[modelen];
384 }
385 else if(format==10) { /*cmpm*/
386 if((opnd[0].ea&070)!=INDINC || (opnd[1].ea&070)!=INDINC)
387 uerr(20);
388 ins[0] =| f1mode[modelen] | ((opnd[0].ea&7)|((opnd[1].ea&7)<<9));
389 return;
390 }
391 if(ckdreg(&opnd[0]) && ckdreg(&opnd[1])) {
392 ins[0] =| ((opnd[0].ea&7)|((opnd[1].ea&7)<<9));
393 return;
394 }
395 if((opnd[0].ea&070)==DECIND && (opnd[1].ea&070)==DECIND) {
396 ins[0] =| 010 | ((opnd[0].ea&7)|((opnd[1].ea&7)<<9));
397 return;
398 }
399 uerr(20);
400 }
401
402 /*format 5 -- div, mul*/
403 /*format 26 -- cmp, chk */
404 opf5()
405 {
406 if(get2ops())
407 return;
408 if(!ckdreg(&opnd[1])) {
409 if(opcpt==cmpptr) {
410 if(!dataea(&opnd[1])) /* [vlh] made define */
411 ins[0] =| f5amode[modelen]; /* was pumode */
412 else if(makeimm())
413 return;
1File: PASS2.C Page 8
414 else
415 uerr(20);
416 }
417 else
418 uerr(20);
419 }
420 if(opcpt==cmpptr) {
421 ins[0] =| f5mode[modelen]; /* was pumode */
422 ckbytea();
423 }
424 else if(!dataea(&opnd[0]))
425 uerr(20);
426 ins[0] =| (opnd[1].ea&7)<<9 | opnd[0].ea;
427 doea(&opnd[0]);
428 }
429
430 #define BTST 0000
431 /* format 7 -- bit instrs -- btst, bclr, bset, etc*/
432 opf7()
433 {
434 if(get2ops())
435 return;
436 if(opnd[1].ea==IMM||(ins[0]!=BTST&&pcea(&opnd[1]))||ckareg(&opnd[1]))
437 uerr(20);
438 if(ckdreg(&opnd[0])) {
439 ins[0] =| (opnd[0].ea<<9)|0400;
440 }
441 else { /*static bit #*/
442 if(opnd[0].con<0L || opnd[0].con>31 ||
443 (opnd[1].ea&INDIRECT&&opnd[0].con>7)) /* [vlh] */
444 uerr(23);
445 if(opnd[0].ea != IMM)
446 uerr(17);
447 ins[0] =| 04000;
448 dodisp(&opnd[0]);
449 }
450 if (modelen==1 && !(memea(&opnd[1]))) /*[vlh]*/
451 uerr(20);
452 else if (!(ckdreg(&opnd[1])) && modelen==4)
453 uerr(20);
454 ins[0] =| opnd[1].ea;
455 doea(&opnd[1]);
456 }
457
458 /* format 8 -- shifts and rotates*/
459 opf8()
460 {
461 register i;
462
463 getea(0); /*get first operand*/
464 if(pitw >= pnite) { /*end of all ops*/
465 if(ckdreg(&opnd[0])) { /*shift dreg one bit*/
466 cpop01(); /*copy opnd 0 to 1*/
467 opnd[0].ea = IMM;
468 opnd[0].con = 1L;
469 if (!ckdreg(&opnd[1])) uerr(20);
470 opf8l1:
471 if(opnd[0].con<1 || opnd[0].con>8) /*[vlh legal range 1..8*/
472 uerr(37);
1File: PASS2.C Page 9
473 ins[0] =| ((opnd[0].con.wd2&7)<<9)|f1mode[modelen]|opnd[1].ea;
474 return;
475 }
476 i = (ins[0]&077)<<6;
477 ins[0] =& 0177700;
478 ins[0] =| 0300|i|opnd[0].ea;
479 if(!memalt(&opnd[0]) || pcea(&opnd[0]) || modelen != 2)
480 uerr(20);
481 doea(&opnd[0]);
482 return;
483 }
484 if(!ckcomma()) {
485 uerr(10);
486 return;
487 }
488 getea(1); /*get second operand*/
489 if(!ckdreg(&opnd[1])) /* [vlh] second operand must be dreg */
490 uerr(20);
491 if(ckdreg(&opnd[0])) { /*first op is D reg*/
492 ins[0] =| (opnd[0].ea<<9)|040; /*reg # and reg bit*/
493 }
494 else {
495 if(opnd[0].ea != IMM)
496 uerr(20);
497 goto opf8l1;
498 }
499 ins[0] =| f1mode[modelen] | opnd[1].ea; /*put in size and reg #*/
500 }
501
502 /* format 9 -- jmp, jsr */
503 /* format 14 -- stop */
504 /* format 24 -- clr, neg, negx, not */
505 /* format 25 -- s?? */
506 /* format 29 -- pea */
507 /* one operand instructions -- jmp, clr, neg, not, sge, etc.*/
508 opf9()
509 {
510 getea(0);
511 if(format==24) { /*clr, not, etc*/
512 ins[0] =| f1mode[modelen]; /*add size bits*/
513 if(!dataalt(&opnd[0]) || pcea(&opnd[0]))
514 uerr(20);
515 }
516 else if(format==25) { /*tas,scc, etc*/
517 if(ckareg(&opnd[0]) || pcea(&opnd[0]) || opnd[0].ea==IMM)
518 uerr(20);
519 }
520 else if(format==14) { /*stop*/
521 if(modelen!=2 || opnd[0].ea!=IMM)
522 uerr(20);
523 doea(&opnd[0]);
524 return;
525 }
526 else if(!controlea(&opnd[0])) /*jmp, jsr, etc*/
527 uerr(20);
528 ins[0] =| opnd[0].ea;
529 doea(&opnd[0]);
530 }
531
1File: PASS2.C Page 10
532 /* format 11 -- dbcc*/
533 /* format 19 -- link*/
534 opf11()
535 {
536 if(get2ops())
537 return;
538 if(format==19) { /*link*/
539 if(!ckareg(&opnd[0]))
540 uerr(33);
541 if(opnd[1].ea != IMM)
542 uerr(17);
543 }
544 else {
545 if(!ckdreg(&opnd[0]))
546 uerr(33);
547 if(opnd[1].drlc!=rlflg) /*[vlh]don't chk opnd[1].ea!=LADDR||SADDR*/
548 uerr(22);
549 opnd[1].con =- (loctr+2L);
550 cksize(&opnd[1]);
551 opnd[1].drlc = ABS; /*not relocatable*/
552 }
553 ins[0] =| opnd[0].ea&7; /*put in reg #*/
554 dodisp(&opnd[1]);
555 }
556
557 /* format 12 -- exg*/
558 opf12()
559 {
560 register i;
561
562 if(get2ops())
563 return;
564 if(ckdreg(&opnd[0])) {
565 if(ckdreg(&opnd[1])) { /*exchange D regs*/
566 ins[0] =| 0100 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
567 return;
568 }
569 if(ckareg(&opnd[1])) { /*ins[0] <- A and D flag*/
570 ins[0] =| 0210 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
571 return;
572 }
573 }
574 if(ckareg(&opnd[0])) {
575 if(ckareg(&opnd[1])) { /*both a regs*/
576 ins[0] =| 0110 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
577 return;
578 }
579 if(ckdreg(&opnd[1])) { /*A and D regs*/
580 i = opnd[0].ea; /*exchg ea's*/
581 opnd[0].ea = opnd[1].ea;
582 opnd[1].ea = i;
583 ins[0] =| 0210 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
584 return;
585 }
586 }
587 uerr(20);
588 }
589
590 /* format 13 -- ext, unlk*/
1File: PASS2.C Page 11
591 /* format 18 -- trap*/
592 /* format 28 -- swap */
593 #define UNLK 047130
594
595 opf13()
596 {
597 getea(0);
598 if(format==18) { /*trap*/
599 if(opnd[0].con<0 || opnd[0].con>15)
600 uerr(15);
601 ins[0] =| opnd[0].con.wd2;
602 return;
603 }
604 if(ins[0]==UNLK) { /*unlk instr*/
605 if(!ckareg(&opnd[0]))
606 uerr(20);
607 }
608 else {
609 if(!ckdreg(&opnd[0]))
610 uerr(20);
611 if (format==13) /* ext */
612 ins[0] =| f13mode[modelen];
613 }
614 ins[0] =| opnd[0].ea&7;
615 }
616
617 /* format 15 -- adda, cmpa, suba*/
618 /* format 30 -- lea */
619 opf15()
620 {
621 register i;
622
623 if(get2ops())
624 return;
625 if(!ckareg(&opnd[1]))
626 uerr(33);
627 if(format==30) {
628 i = 0700;
629 if(!controlea(&opnd[0]))
630 uerr(20);
631 }
632 else
633 i = f15mode[modelen];
634 makef1(opnd[1].ea&7,i,&opnd[0]);
635 if (format==15 && opnd[0].ea != 071) cksize(&opnd[0]);
636 }
637
638 /*formats 16 and 17 -- addq, inc, subq, dec*/
639 opf17()
640 {
641 if(format==16) { /*inc or dec*/
642 clrea(&opnd[0]);
643 opnd[0].ea = IMM;
644 opnd[0].con = 1L;
645 opnd[0].drlc = ABS;
646 getea(1);
647 }
648 else {
649 if(get2ops())
1File: PASS2.C Page 12
650 return;
651 }
652 if(opnd[0].ea != IMM || !altea(&opnd[1]) || pcea(&opnd[1]))
653 uerr(20);
654 if(opnd[0].con<=0 || opnd[0].con>8)
655 uerr(15);
656 if(modelen==1 && !dataea(&opnd[1]))
657 uerr(34);
658 ins[0] =| f1mode[modelen]|((opnd[0].con.wd2&7)<<9)|opnd[1].ea;
659 doea(&opnd[1]);
660 }
661
662 /* format 20 -- movem */
663 int regmsk0[] {0100000,040000,020000,010000,04000,02000,01000,0400,0200,
664 0100,040,020,010,4,2,1};
665 int regmsk1[] {1,2,4,010,020,040,0100,0200,0400,01000,02000,04000,010000,
666 020000,040000,0100000};
667 opf20()
668 {
669 register dr;
670 register i,j;
671
672 dr = 0;
673 if(getreg() != -1 || pitw->itty == ITRM) { /*regs to memory*/
674 if (pitw->itty != ITRM) { /* [vlh] */
675 pitw--;
676 j = getrlist(regmsk0);
677 }
678 else {
679 j = pitw->itop;
680 pitw++;
681 }
682 if(!ckcomma())
683 uerr(10);
684 }
685 else
686 dr = 02000;
687 getea(0);
688 if(dr) {
689 if(!ckcomma())
690 uerr(10);
691 if (pitw->itty != ITRM) /* [vlh] */
692 j = getrlist(regmsk1); /*mem to regs*/
693 else {
694 j = pitw->itop;
695 j = fixmask(j);
696 pitw++;
697 }
698 }
699 else {
700 if(controlea(&opnd[0]))
701 j = fixmask(j);
702 }
703 i = opnd[0].ea&070;
704 if(!controlea(&opnd[0]) && i!=INDINC && i!=DECIND)
705 uerr(20);
706 if(modelen==4) /*long*/
707 ins[0] =| 0100;
708 ins[0] =| opnd[0].ea|dr;
1File: PASS2.C Page 13
709 *pins++ = j; /*reg mask*/
710 *prlb++ = DABS;
711 instrlen =+ 2;
712 doea(&opnd[0]);
713 if (!dr) { /* 1st argument (2nd is reg list) */
714 if (pcea(&opnd[0]) || (opnd[0].ea&070)==INDINC)
715 uerr(20); /* xx(pc), xx(pc,dx), -(ax) */
716 }
717 else /* 2nd argument (1st is reg list) */
718 if ((opnd[0].ea&070)==DECIND)
719 uerr(20); /* (ax)+ */
720 }
721
722 /*
723 * get a list of registers for the movem instr
724 * call with:
725 * ptr to reg-to-mem or mem-to-reg array of bits
726 */
727 getrlist(ap)
728 int *ap;
729 {
730 register int *p,i,j;
731 register int mask;
732
733 p = ap;
734 mask = 0;
735 while((i=getreg()) != -1) {
736 if(ckitc(pitw,'-')) {
737 pitw++;
738 if((j=getreg()) == -1) {
739 uerr(40);
740 break;
741 }
742 while(i<=j)
743 mask =| p[i++];
744 }
745 else
746 mask =| p[i];
747 if(ckitc(pitw,'/'))
748 pitw++;
749 else
750 break;
751 }
752 if(!mask)
753 uerr(40);
754 return(mask);
755 }
756
757 /*reverse a movem register mask for control ea to memory*/
758 fixmask(msk)
759 {
760 register i,j,k;
761
762 k = (msk&1) ? 0100000 : 0;
763 i = 2;
764 j = 040000;
765 while(i) {
766 if(msk&i)
767 k =| j;
1File: PASS2.C Page 14
768 i =<< 1;
769 j =>> 1;
770 }
771 return(k);
772 }
773
774 /* format 21 -- movep*/
775 opf21()
776 {
777 register m,d;
778 register char *p;
779
780 if(get2ops())
781 return;
782 if(ckdreg(&opnd[0])) { /*d reg source*/
783 m = 0600;
784 d = opnd[0].ea;
785 p = &opnd[1];
786 }
787 else if(ckdreg(&opnd[1])) { /*d reg dest*/
788 m = 0400;
789 d = opnd[1].ea;
790 p = &opnd[0];
791 }
792 else {
793 uerr(20);
794 }
795 if((p->ea&070) != INDDISP)
796 uerr(20);
797 if(modelen == 4)
798 m =| 0100;
799 ins[0] =| (d<<9)|m|(p->ea&7);
800 *pins++ = p->con.wd2;
801 *prlb++ = p->drlc;
802 instrlen =+ 2;
803 }
804
805 /* format 22 -- moveq*/
806 opf22()
807 {
808 if(get2ops())
809 return;
810 if(opnd[0].ea != IMM)
811 uerr(17);
812 if(opnd[0].con>255L || opnd[0].con<-256L)
813 uerr(15);
814 if(!ckdreg(&opnd[1]))
815 uerr(33);
816 ins[0] =| (opnd[1].ea<<9) | (opnd[0].con.wd2&0377);
817 }
818
819 /* format 23 -- eor*/
820 opf23()
821 {
822 if(get2ops())
823 return;
824 if (cksprg(&opnd[1],CCR) || cksprg(&opnd[1],SR)) {
825 opcpt = eoriptr;
826 ins[0] = opcpt->vl1.wd2;
1File: PASS2.C Page 15
827 format = (opcpt->flags)&OPFF;
828 ccr_or_sr();
829 return;
830 }
831 if(!ckdreg(&opnd[0])) {
832 if(makeimm()) /*must be immediate*/
833 return;
834 uerr(20); /*or error*/
835 }
836 if(!dataalt(&opnd[1]) || pcea(&opnd[1]))
837 uerr(20);
838 ins[0] =| (opnd[0].ea<<9)|f23mode[modelen]|opnd[1].ea;
839 doea(&opnd[1]);
840 }
841

View File

@@ -0,0 +1,4 @@
$1lo68 -r -o as68.rel -f $1 -unofloat 0$1s.o dir.o expr.o main.o misc.o pass1a.o pass2.o strncmp.o symt.o 0$1lib6.a 0$1clib
era *.o
user 10!make $1

View File

@@ -0,0 +1,30 @@
/*********************************************************************
* STRNCMP - compares strings up to n chars
*
* WORD strncmp(s1,s2,n)
* BYTE *s1, *s2;
* UWORD n;
*
* 'strncmp' compares null terminated strings s1 and s2, and examines
* at most n chars.
* Always compares at least 1 char.
* n < 0 compares many, many characters.
* Returns:
* strncmp < 0 if s1<s2 (within n chars)
* strncmp = 0 if s1=s2 " " "
* strncmp > 0 if s1>s2 " " "
*********************************************************************/
#include <portab.h>
WORD strncmp(s1,s2,n)
REG BYTE *s1, *s2;
REG WORD n;
{
for( ; --n > 0 && (*s1 == *s2); s1++, s2++ )
{
if( *s1 == NULL )
return(0);
}
return(*s1 - *s2);
}

View File

@@ -0,0 +1,850 @@
/*
Copyright 1981
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "as68.h"
/* symbol table and misc routines*/
int errno;
char *ermsg[];
char tfilname[];
char initfnam[];
char ldfn[];
char tlab1[];
int stdofd;
int ftudp;
int poslab;
/*output it for beginning of statement*/
opitb()
{
stbuf[0].itty = ITBS; /*beginning of statement*/
stbuf[0].itop = (fchr!=EOLC) ? absln : absln-1;
stbuf[1].itty = ITSY; /*label entry*/
stbuf[1].itop.ptrw2 = lblpt; /*pointer to symbol or 0*/
/*put opcode in it buffer*/
stbuf[2].itty = ITSY;
stbuf[2].itrl = modelen; /*mode of instr(byte, word, long)*/
stbuf[2].itop.ptrw2 = opcpt; /*pointer to opcode in main table*/
stbuf[3].itty = ITCN;
stbuf[3].itrl = rlflg; /*relocation base*/
stbuf[3].itop = loctr; /*pass1 location counter*/
itwc = ITOP1; /*next available slot-currently 4*/
pitw = &stbuf[ITOP1].itty; /*init the pointer*/
}
/*
* get an input term (symbol, constant, or special character)
* call with:
* the first character in fchr
* returns:
* item type in itype
* item value in ival if item is a constant or special character
* if it is a symbol it is placed at the end of the main table
* meaning of state table:
* currently getting: symbol(0) constant(1) beginning(2)
* next char:
* digit(0) 0 1 1
* letter(3) 0 3 0
* special char(6) 3 3 3
* contents of the state table is the next state. processing stops when
* state 3 is encountered. state 2 is the beginning state.
*/
int sttbl[] {0,1,1,0,3,0,3,3,3}; /*state table for parser*/
gterm(constpc)
int constpc;
{
register smode, i;
register char *p;
register int tmode;
register char *j;
long num;
char istr[80];
/* if(fchr == '\'' || fchr == '"') */ /* Fucking Whitesmith's */
if(fchr == 047 || fchr == 042)
if(astring()) /*maybe ascii string*/
return;
smode = 2; /*beginning state*/
i = 0;
p = istr;
/*loop to put item on istr*/
while(fchr>=' ') { /*until a control char*/
if(smode==2 && fchr=='.')
tmode = 3;
else if(isalpha(fchr) || fchr=='~' || fchr=='_' || (fchr=='$'&&i))
tmode=3;
else if(isdigit(fchr))
tmode=0;
else
tmode = 6;
tmode = sttbl[tmode+smode]; /*new state*/
if(tmode==3) break; /*end of item*/
smode = tmode;
*p++ = fchr; /*save character*/
i++;
fchr=gchr();
}
/* end of item*/
switch(smode) {
case 0: /*symbol*/
*p = '\0'; /*end of symbol*/
itype = ITSY; /*symbol*/
pack(istr,lmte); /*put symbol at end of main table*/
j = lemt(sirt,FALSE);
if(istr[0]!='~' && !poslab && (j->flags&(SYEQ|SYER))==SYEQ) {
itype = (j->flags&SYRM) ? ITRM : ITCN; /* [vlh] */
ival = j->vl1;
reloc = ((j->flags)&SYRO) ? TEXT : ((j->flags)&SYRA) ? DATA :
((j->flags)&SYBS) ? BSS : ABS;
}
return;
case 1: /*constant*/
if(!constant(&num,istr,i)) {
uerr(17); /*illegal constant*/
num = 0;
}
ival = num;
itype = ITCN;
reloc = ABS;
return;
case 2: /*just a special char*/
switch(fchr) {
case '*': /*location counter*/
if(starmul) { /*multiply*/
starmul = 0;
goto specsy;
}
refpc++; /*referenced pgm ctr*/
reloc = rlflg; /*relocation of location counter*/
ival = loctr;
itype = (constpc) ? ITCN : ITPC;
break;
case '$': /*hex constant*/
oconst(16);
return;
case '@': /*octal const*/
oconst(8);
return;
case '%': /*binary const*/
oconst(2);
return;
case '#':
immed[opdix]++;
goto specsy;
case '(':
indir[opdix]++;
plevel++;
goto specsy;
case ')':
plevel--;
goto specsy;
default:
specsy:
itype = ITSP; /*return special char*/
ival = fchr;
}
if(fchr != EOLC)
fchr=gchr(); /*get next char*/
if((ival=='>' && fchr=='>') || (ival=='<' && fchr=='<'))
fchr=gchr(); /*shift op, ignore second char*/
return;
default:
abort(); /*not possible*/
}
}
/*check for an ascii string enclosed in single quotes*/
astring()
{
register char delim;
/* if(fchr != '\'' && fchr != '"') *//*valid delimiter*/
if(fchr != 047 && fchr != 042)
return;
delim = fchr;
if(equflg || (itype==ITSP && ival.wd2=='#')) { /*immediate operand*/
if(astr1(delim)) {
fchr = gchr();
if(fchr!=delim)
xerr(19);
fchr=gchr();
}
return((equflg) ? 1 : 0);
}
while(astr1(delim)) {
itype = ITSP;
ival = ','; /*separate by commas*/
reloc = ABS;
opitoo();
}
return(0);
}
astr1(adelim)
{
register delim,i,retv;
register long l;
delim = adelim;
i = 0; l = 0;
retv = 1;
while((fchr=gchr()) != EOF) {
if(fchr==delim) {
fchr = gchr();
if(fchr != delim) {
retv = 0; /*end of string*/
break;
}
}
if(fchr == EOLC) {
xerr(19);
retv = 0; /*end of string*/
break;
}
l = (l<<8) | fchr;
if(++i >= modelen) {
if((fchr=gchr()) == delim) {
fchr = gchr();
retv = 0; /*end of string*/
}
else
peekc = fchr; /*next char in string*/
break; /*filled one bucket*/
}
}
while(i < modelen) {
l =<< 8;
i++;
}
itype = ITCN;
ival = l;
reloc = ABS;
if(!equflg)
opitoo(); /*output one operand*/
return(retv);
}
/*get constant given radix*/
oconst(ardx)
{
register trdx,j;
register long i;
switch (ardx) { /* radix as power of 2 */
case 16 : trdx = 4; break;
case 8 : trdx = 3; break;
case 2 : trdx = 1; break;
default :
rpterr("invalid radix in oconst");
abort();
}
i=0;
while(1) {
fchr=gchr();
j=fchr;
if(isdigit(j))
j =- '0';
else if((j=tolower(j))>='a' && j<='f')
j = j-'a'+10;
else
break; /*not valid numeric char*/
if(j>=0 && j<ardx)
i = (i<<trdx)+j;
else
break;
}
ival = i;
itype = ITCN;
reloc = ABS;
}
/*convert ascii constant to binary*/
constant(pnum,pstr,idx)
long *pnum;
char *pstr;
{
register i,j;
register char *p;
register long l;
p = pstr;
l = 0;
for(i=0; i<idx; i++) {
j = *pstr++;
if(isdigit(j))
j =- '0';
if(j<0 || j>=10)
return(0);
l = (l<<3) + (l<<1) + j; /* l = l*10 + j*/
}
*pnum = l;
return(1);
}
/*
* method for looking up entries in the main table
*
* Note: The entry to be looked up must be placed at the end
* of the main table. The global cell 'lmte'(last main
* entry) points to the next available entry in the main
* table. The address of an initial reference table must
* also be provided.
*
* 1) Compute the hash code for the symbol and add it to the base address
* of the initial reference table given as input. Thus, two words are
* accessed which define the chain on which the symbol must be if it
* is in the table at all.
*
* 2) Alter the table link of the last symbol in the chain so that it
* points to the symbol being looked up. Note that the symbol to be
* looked up is always placed at the end of the main table before
* calling the lookup routine. This essentially adds one more element
* to the end of the chain, namely the symbol to be looked up.
*
* 3) Now start at the first symbol in the chain and follow the chain
* looking for a symbol equal to the smbol being looked up. It is
* guaranteed that such a symbol will be found because it is always
* the last symbol on the chain.
*
* 4) When the symbol is found, check to see if it is the last symbol
* on the chain. If not, the symbol being looked for is in the table
* and has been found. If it is the last symbol, the symbol being
* looked up is not in the table.
*
* 5) In the case the looked up symbol is not found, it is usually added
* to the end of the table. This is done simply b changing the
* initial reference table entry which points to the previous
* last symbol on the chain so that is now points to the symbol at the
* end of the main table. In case the symbol just looked up is not to
* be added to the main table then no action is needed . This means
* that the table link of the last symbol on a chain may point any-
* where.
*
* look up entry in the main table
* call with:
* address of initial reference table
* entry to be looked up at the end of the main table
* returns:
* a pointer to the entry. if this pointer is equal to
* lmte then the symbol was not previously in the table.
*/
char *lemt(airt,oplook)
char **airt;
int oplook; /* if true then looking in opcode table */
{
register char *mtpt;
register int *p1, *p2;
register int i, j;
if (oplook) { /* [vlh] get rid of preceding '.', to lowercase */
if (lmte->name[0]=='.') {
lmte->name[NAMELEN-1] = NULL; /* in case of '.' */
j = 1;
}
else j = 0;
for (i=0; j<NAMELEN; i++, j++)
lmte->name[i] = tolower(lmte->name[j]);
}
pirt = airt + hash(); /*hashed ptr to irt*/
mtpt = pirt->irfe; /*pointer to first entry in chain*/
if(!mtpt) /*empty chain*/
mtpt = lmte; /*start at end of main table*/
else
(pirt->irle)->tlnk = lmte; /*last entry in chain is new symbol*/
/*loop to locate entry in main table*/
lemtl:
p1 = &mtpt->name[0];
p2 = &lmte->name[0];
i = NAMELEN/(sizeof i);
while(i) {
if(*p1++ != *p2++) {
mtpt = mtpt->tlnk; /*go to next entry in chain*/
goto lemtl;
}
i--;
}
return(mtpt);
}
/* compute a hash code for the last entry in the main table*/
/* returns the hash code*/
hash()
{
register int i;
register ht1;
register char *p;
ht1 = 0;
p = &lmte->name[0];
for(i=0; i<NAMELEN; i++)
ht1 =+ *p++;
return(ht1&(SZIRT-2)); /*make hash code even and between 0 & SZIRT-2*/
}
/*
* Make an entry in the main table
* assumes :
* entry to be made is pointed at by lmte
* pirt points to the correct initial reference table entry.
*/
mmte()
{
pirt->irle = lmte; /*pointer to last entry in chain*/
if(pirt->irfe == 0) /*first entry in chain*/
pirt->irfe = lmte;
lmte =+ STESIZE; /*bump last main table entry pointer*/
if(lmte>=emte) { /*main table overflow*/
if(sbrk(STESIZE*ICRSZMT) == -1){ /*get more memory*/
rpterr("symbol table overflow\n");
endit();
}
else {
emte =+ STESIZE*ICRSZMT; /*move end of main table*/
cszmt =+ ICRSZMT;
}
}
}
/*
* make an entry in the main table for a directive
* call with:
* pointer to string containing directive name
* address of routine to handle directive in pass one
* address of routine to handle directive in pass two
*/
mdemt(mdstr,dirnum)
char *mdstr;
{
register char *mdept;
pack(mdstr,lmte); /*pack name at end of main table*/
mdept=lemt(oirt,TRUE); /*look up in opcode table*/
if(mdept != lmte) { /*best not be there already*/
uerr(5);
abort();
return;
}
mmte(); /*make main table entry*/
mdept->flags =| OPDR|SYIN; /*directive*/
mdept->vl1 = dirnum; /*directive #*/
}
/*
* pack a string into an entry in the main table
* call with:
* pointer to the string
* pointer to desired entry in the main table
*/
pack(apkstr,apkptr)
char *apkstr, *apkptr;
{
register i;
register char *pkstr, *pkptr;
pkstr = apkstr;
pkptr = apkptr;
i = NAMELEN;
while(*pkstr && i) {
*pkptr++ = *pkstr++;
i--;
}
while(i--)
*pkptr++ = '\0'; /*pad with nulls*/
}
/* function to get characters for source file*/
int xcol = 0; /* Column Counter */
int spcnt = 0; /* Space count for tab expansion */
gchr()
{
register chr1;
if(peekc) {
chr1 = peekc;
peekc = 0;
if(chr1 != SOH)
xcol--;
}
else if (spcnt)
{
spcnt--;
return(' ');
}
else
{
gchr1:
if(sbuflen<=0){ /*nothing on input buffer*/
sbuflen=read(ifn,sbuf,512); /*read in source*/
if(sbuflen<=0)
return(EOF); /*end of file*/
psbuf = sbuf;
}
chr1 = *psbuf++;
sbuflen--;
}
if (chr1 == SOH) /*preprocessor flag*/
goto gchr1; /*ignore it*/
if(chr1 == EOLC) { /*end of line*/
xcol = -1; /* Clear column counter */
if(!p2flg) /*pass 1 only*/
absln++;
}
if(chr1=='\t') /*convert tabs to spaces*/
{
spcnt += 7 - (xcol&7); /* This many spaces */
xcol += spcnt; /* New column number */
chr1 = ' ';
}
xcol++;
return(chr1);
}
/*
* write out intermediate text for one statement
* call with
* the it for the statement in stbuf
*/
wostb()
{
register int woix;
register short *itwo;
register int i;
if(stbuf[0].itty != ITBS) abort(); /*not beginning of stmt*/
itwo = &stbuf;
woix = stbuf[0].itrl & 0377; /*unsigned byte*/
while(woix--) {
for(i=0; i<(sizeof stbuf[0])/(sizeof *itwo); i++) {
doitwr(*itwo++);
}
}
/* debug(); //call debug package*/
}
doitwr(word)
short word;
{
short i;
if( pitix < itbuf || pitix > &itbuf[ITBSZ] ) {
printf("doitwr: it buffer botch\n");
endit();
}
if( pitix >= &itbuf[ITBSZ]) {
if(write(itfn,itbuf,ITBSZ*(sizeof i)) != ITBSZ*(sizeof i)) {
rpterr("it write error errno=%o\n",errno);
endit();
}
pitix = itbuf;
}
*pitix++ = word;
}
/*
* user source error
* call with:
* number to indicate reason for error
* types the error number and the line number on which
* the error occured.
*/
uerr(errn)
{
if(p2flg) { /*pass 2 gets two ampersands*/
in_err++; /* [vlh] instrlen <- pass1 estimation */
printf("&& %d: %s\n",p2absln,ermsg[errn-1]);
}
else
printf("& %d: %s\n",(fchr==EOLC)?absln-1:absln,ermsg[errn-1]);
nerror++;
}
/*
* user error that causes the statement to be abandoned
* call with:
* error number
*/
xerr(xern)
{
uerr(xern); /*type error message*/
if(!p2flg) /*pass one*/
igrst(); /*pass rest of source*/
}
/* abort the assembly*/
abort()
{
rpterr("as68 abort\n");
nerror++;
endit();
}
/*ignore rest of statement*/
igrst()
{
while(fchr!=EOLC && fchr!=EOF) /*until end of line*/
fchr=gchr();
while((fchr=gchr())==EOLC) ; /*ignore null lines*/
}
/*ignore blanks after a label*/
ligblk()
{
if(fchr == EOF) return;
igblk();
if(fchr==EOLC) {
fchr=gchr();
ligblk();
}
}
rubout()
{
nerror = -1;
endit();
}
/* exit from the assembler*/
endit()
{
LASTCHTFN = itfnc;
unlink(tfilname); /*delete temporary files*/
LASTCHTFN = trbfnc;
unlink(tfilname);
LASTCHTFN = dafnc;
unlink(tfilname);
LASTCHTFN = drbfnc;
unlink(tfilname);
if(nerror != -1) { /*not rubout*/
if(ftudp)
putchar('\n');
}
if(nerror > 0) {
fprintf(stderr,"& %d errors\n",nerror);
}
if (initflg)
unlink(ldfn); /* [vlh] get rid of empty .o file */
exit(nerror!=0);
}
/*
* open files
* call with:
* pointer to name of file to open
* flag for how to open
* 0 => read
* 1 => write
*/
openfi(pname,hflag)
char *pname;
{
register fd;
fd = (hflag==1) ? creat(pname,0666,1) : open(pname,hflag,1);
if(fd < 0) { /*open failed*/
rpterr("can't open %s errno=%o\n",pname,errno);
endit();
}
return(fd);
}
/* get a temp file for the intermediate text*/
char lastfile = 'A';
gettempf()
{
register i,j;
register char *p;
LASTCHTFN = lastfile++; /* Creat temp name */
if((j=creat(tfilname,0600,1)) >= 0)
return(j); /* File created OK */
rpterr("Unable to open temporary file\n");
endit();
}
/* move label name from lbt to main table entry pointed to by lmte*/
setname()
{
register i;
register int *p1, *p2;
p1 = &lmte->name[0];
for(p2 = &lbt[0]; p2 < &lbt[NAMELEN]; ) {
*p1++ = *p2;
*p2++ = 0;
}
}
/* get the initialized main table and initial reference tables from*/
/* the initialize file*/
getsymtab()
{
long j; /* length for read / write */
register char **p;
register struct symtab *p1;
register char *p2;
register fd,i;
if((fd=open(initfnam,0,1)) < 0) {
rerr:
printf("& Unable to read init file: %s\n", initfnam);
endit();
}
if(read(fd,sirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0])) {
goto rerr;
}
if(read(fd,oirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0]))
goto rerr;
if(read(fd,&j,(sizeof j)) != (sizeof j)) /* Read Count */
goto rerr; /* Y-U-K!!! */
if((i=read(fd,bmte,(int)j)) != j) /* Read table */
goto rerr;
if((i%STESIZE) != 0)
goto rerr;
lmte = bmte + i;
p2 = bmte-1;
for(p=sirt; p<&sirt[SZIRT]; p++) {
if(*p)
*p =+ (long)p2;
}
for(p=oirt; p<&oirt[SZIRT]; p++) {
if(*p)
*p =+ (long)p2;
}
for(p1=bmte; p1<lmte; p1++) {
if(p1->tlnk)
p1->tlnk =+ (long)p2;
}
close(fd);
}
/* write the initialization file*/
putsymtab()
{
long j;
register char **p;
register struct symtab *p1;
register char *p2;
register fd,i;
if((fd=creat(initfnam,0644,1))<0) {
printf("& Cannot create init: %s\n", initfnam);
return;
}
/*
* change all pointers so that they are relative to the beginning
* of the symbol table
*/
p2 = bmte-1;
for(p=sirt; p<&sirt[SZIRT]; p++) {
if(*p)
*p =- (long)p2;
}
for(p=oirt; p<&oirt[SZIRT]; p++) {
if(*p)
*p =- (long)p2;
}
for(p1=bmte; p1<lmte; p1++) {
if(p1->tlnk)
p1->tlnk =- (long)p2;
}
if(write(fd,sirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0])) {
goto werr;
}
if(write(fd,oirt,SZIRT*(sizeof oirt[0])) != SZIRT*(sizeof oirt[0]))
goto werr;
i = lmte - bmte; /*length of current main table*/
if((i % STESIZE) != 0) {
goto werr;
}
j = i;
if(write(fd,&j,(sizeof j)) != (sizeof j)) /* Y-U-K!! */
goto werr;
if(write(fd,bmte,i) != i) {
werr:
printf("& Write error on init file: %s\n",initfnam);
return;
}
close(fd);
}
/* print an error on file descriptor 2*/
/* used for errors with disasterous consequences*/
rpterr(ptch,x1,x2,x3,x4,x5,x6)
char *ptch;
{
if(prtflg==0) /* Check for paging output */
page(); /* Perform page checks */
fprintf(stderr,"& %d: ",absln);
fprintf(stderr,ptch,x1,x2,x3,x4,x5,x6);
}
/* set the file name for the relocatable object file (sourcefile.o)*/
setldfn(ap)
char *ap;
{
register char *p1,*p2;
p1 = ap;
p2 = ldfn;
while(*p1) {
*p2++ = *p1++;
}
if(*(p2-2) != '.') { /*not name.?*/
*p2++ = '.';
*p2++ = 'o';
}
else { /* is name.? */
*(p2-1) = 'o';
}
*p2 = '\0';
}
savelab()
{
register int *p1, *p2;
p2 = &lmte->name[0];
for(p1= &tlab1[0]; p1 < &tlab1[NAMELEN]; )
*p1++ = *p2++;
}

View File

@@ -0,0 +1,865 @@
1File: SYMT.C Page 1
1 /*
2 Copyright 1981
3 Alcyon Corporation
4 8716 Production Ave.
5 San Diego, Ca. 92121
6 */
7
8 #include "as68.h"
9
10 /* symbol table and misc routines*/
11
12 int errno;
13 char *ermsg[];
14 char tfilname[];
15 char initfnam[];
16 char ldfn[];
17 char tlab1[];
18 int stdofd;
19 int ftudp;
20 int poslab;
21
22 /*output it for beginning of statement*/
23 opitb()
24 {
25 stbuf[0].itty = ITBS; /*beginning of statement*/
26 stbuf[0].itop = (fchr!=EOLC) ? absln : absln-1;
27 stbuf[1].itty = ITSY; /*label entry*/
28 stbuf[1].itop.ptrw2 = lblpt; /*pointer to symbol or 0*/
29
30 /*put opcode in it buffer*/
31 stbuf[2].itty = ITSY;
32 stbuf[2].itrl = modelen; /*mode of instr(byte, word, long)*/
33 stbuf[2].itop.ptrw2 = opcpt; /*pointer to opcode in main table*/
34 stbuf[3].itty = ITCN;
35 stbuf[3].itrl = rlflg; /*relocation base*/
36 stbuf[3].itop = loctr; /*pass1 location counter*/
37 itwc = ITOP1; /*next available slot-currently 4*/
38 pitw = &stbuf[ITOP1].itty; /*init the pointer*/
39 }
40
41 /*
42 * get an input term (symbol, constant, or special character)
43 * call with:
44 * the first character in fchr
45 * returns:
46 * item type in itype
47 * item value in ival if item is a constant or special character
48 * if it is a symbol it is placed at the end of the main table
49
50 * meaning of state table:
51
52 * currently getting: symbol(0) constant(1) beginning(2)
53
54 * next char:
55 * digit(0) 0 1 1
56
57 * letter(3) 0 3 0
58
59 * special char(6) 3 3 3
1File: SYMT.C Page 2
60
61 * contents of the state table is the next state. processing stops when
62 * state 3 is encountered. state 2 is the beginning state.
63 */
64 int sttbl[] {0,1,1,0,3,0,3,3,3}; /*state table for parser*/
65
66 gterm(constpc)
67 int constpc;
68 {
69 register smode, i;
70 register char *p;
71 register int tmode;
72 register char *j;
73 long num;
74 char istr[80];
75
76 /* if(fchr == '\'' || fchr == '"') */ /* Fucking Whitesmith's */
77 if(fchr == 047 || fchr == 042)
78 if(astring()) /*maybe ascii string*/
79 return;
80 smode = 2; /*beginning state*/
81 i = 0;
82 p = istr;
83
84 /*loop to put item on istr*/
85 while(fchr>=' ') { /*until a control char*/
86 if(smode==2 && fchr=='.')
87 tmode = 3;
88 else if(isalpha(fchr) || fchr=='~' || fchr=='_' || (fchr=='$'&&i))
89 tmode=3;
90 else if(isdigit(fchr))
91 tmode=0;
92 else
93 tmode = 6;
94 tmode = sttbl[tmode+smode]; /*new state*/
95 if(tmode==3) break; /*end of item*/
96 smode = tmode;
97 *p++ = fchr; /*save character*/
98 i++;
99 fchr=gchr();
100 }
101
102 /* end of item*/
103 switch(smode) {
104
105 case 0: /*symbol*/
106 *p = '\0'; /*end of symbol*/
107 itype = ITSY; /*symbol*/
108 pack(istr,lmte); /*put symbol at end of main table*/
109 j = lemt(sirt,FALSE);
110 if(istr[0]!='~' && !poslab && (j->flags&(SYEQ|SYER))==SYEQ) {
111 itype = (j->flags&SYRM) ? ITRM : ITCN; /* [vlh] */
112 ival = j->vl1;
113 reloc = ((j->flags)&SYRO) ? TEXT : ((j->flags)&SYRA) ? DATA :
114 ((j->flags)&SYBS) ? BSS : ABS;
115 }
116 return;
117
118 case 1: /*constant*/
1File: SYMT.C Page 3
119 if(!constant(&num,istr,i)) {
120 uerr(17); /*illegal constant*/
121 num = 0;
122 }
123 ival = num;
124 itype = ITCN;
125 reloc = ABS;
126 return;
127
128 case 2: /*just a special char*/
129 switch(fchr) {
130
131 case '*': /*location counter*/
132 if(starmul) { /*multiply*/
133 starmul = 0;
134 goto specsy;
135 }
136 refpc++; /*referenced pgm ctr*/
137 reloc = rlflg; /*relocation of location counter*/
138 ival = loctr;
139 itype = (constpc) ? ITCN : ITPC;
140 break;
141
142
143 case '$': /*hex constant*/
144 oconst(16);
145 return;
146
147 case '@': /*octal const*/
148 oconst(8);
149 return;
150
151 case '%': /*binary const*/
152 oconst(2);
153 return;
154
155 case '#':
156 immed[opdix]++;
157 goto specsy;
158
159 case '(':
160 indir[opdix]++;
161 plevel++;
162 goto specsy;
163
164 case ')':
165 plevel--;
166 goto specsy;
167
168 default:
169 specsy:
170 itype = ITSP; /*return special char*/
171 ival = fchr;
172 }
173 if(fchr != EOLC)
174 fchr=gchr(); /*get next char*/
175 if((ival=='>' && fchr=='>') || (ival=='<' && fchr=='<'))
176 fchr=gchr(); /*shift op, ignore second char*/
177 return;
1File: SYMT.C Page 4
178
179 default:
180 abort(); /*not possible*/
181 }
182 }
183
184 /*check for an ascii string enclosed in single quotes*/
185
186 astring()
187 {
188 register char delim;
189
190 /* if(fchr != '\'' && fchr != '"') *//*valid delimiter*/
191 if(fchr != 047 && fchr != 042)
192 return;
193 delim = fchr;
194 if(equflg || (itype==ITSP && ival.wd2=='#')) { /*immediate operand*/
195 if(astr1(delim)) {
196 fchr = gchr();
197 if(fchr!=delim)
198 xerr(19);
199 fchr=gchr();
200 }
201 return((equflg) ? 1 : 0);
202 }
203 while(astr1(delim)) {
204 itype = ITSP;
205 ival = ','; /*separate by commas*/
206 reloc = ABS;
207 opitoo();
208 }
209 return(0);
210 }
211
212 astr1(adelim)
213 {
214 register delim,i,retv;
215 register long l;
216
217 delim = adelim;
218 i = 0; l = 0;
219 retv = 1;
220 while((fchr=gchr()) != EOF) {
221 if(fchr==delim) {
222 fchr = gchr();
223 if(fchr != delim) {
224 retv = 0; /*end of string*/
225 break;
226 }
227 }
228 if(fchr == EOLC) {
229 xerr(19);
230 retv = 0; /*end of string*/
231 break;
232 }
233 l = (l<<8) | fchr;
234 if(++i >= modelen) {
235 if((fchr=gchr()) == delim) {
236 fchr = gchr();
1File: SYMT.C Page 5
237 retv = 0; /*end of string*/
238 }
239 else
240 peekc = fchr; /*next char in string*/
241 break; /*filled one bucket*/
242 }
243 }
244 while(i < modelen) {
245 l =<< 8;
246 i++;
247 }
248 itype = ITCN;
249 ival = l;
250 reloc = ABS;
251 if(!equflg)
252 opitoo(); /*output one operand*/
253 return(retv);
254 }
255
256 /*get constant given radix*/
257 oconst(ardx)
258 {
259 register trdx,j;
260 register long i;
261
262 switch (ardx) { /* radix as power of 2 */
263 case 16 : trdx = 4; break;
264 case 8 : trdx = 3; break;
265 case 2 : trdx = 1; break;
266 default :
267 rpterr("invalid radix in oconst");
268 abort();
269 }
270 i=0;
271 while(1) {
272 fchr=gchr();
273 j=fchr;
274 if(isdigit(j))
275 j =- '0';
276 else if((j=tolower(j))>='a' && j<='f')
277 j = j-'a'+10;
278 else
279 break; /*not valid numeric char*/
280 if(j>=0 && j<ardx)
281 i = (i<<trdx)+j;
282 else
283 break;
284 }
285 ival = i;
286 itype = ITCN;
287 reloc = ABS;
288 }
289
290
291 /*convert ascii constant to binary*/
292 constant(pnum,pstr,idx)
293 long *pnum;
294 char *pstr;
295 {
1File: SYMT.C Page 6
296 register i,j;
297 register char *p;
298 register long l;
299
300 p = pstr;
301 l = 0;
302 for(i=0; i<idx; i++) {
303 j = *pstr++;
304 if(isdigit(j))
305 j =- '0';
306 if(j<0 || j>=10)
307 return(0);
308 l = (l<<3) + (l<<1) + j; /* l = l*10 + j*/
309 }
310 *pnum = l;
311 return(1);
312 }
313
314 /*
315 * method for looking up entries in the main table
316 *
317 * Note: The entry to be looked up must be placed at the end
318 * of the main table. The global cell 'lmte'(last main
319 * entry) points to the next available entry in the main
320 * table. The address of an initial reference table must
321 * also be provided.
322 *
323 * 1) Compute the hash code for the symbol and add it to the base address
324 * of the initial reference table given as input. Thus, two words are
325 * accessed which define the chain on which the symbol must be if it
326 * is in the table at all.
327 *
328 * 2) Alter the table link of the last symbol in the chain so that it
329 * points to the symbol being looked up. Note that the symbol to be
330 * looked up is always placed at the end of the main table before
331 * calling the lookup routine. This essentially adds one more element
332 * to the end of the chain, namely the symbol to be looked up.
333 *
334 * 3) Now start at the first symbol in the chain and follow the chain
335 * looking for a symbol equal to the smbol being looked up. It is
336 * guaranteed that such a symbol will be found because it is always
337 * the last symbol on the chain.
338 *
339 * 4) When the symbol is found, check to see if it is the last symbol
340 * on the chain. If not, the symbol being looked for is in the table
341 * and has been found. If it is the last symbol, the symbol being
342 * looked up is not in the table.
343 *
344 * 5) In the case the looked up symbol is not found, it is usually added
345 * to the end of the table. This is done simply b changing the
346 * initial reference table entry which points to the previous
347 * last symbol on the chain so that is now points to the symbol at the
348 * end of the main table. In case the symbol just looked up is not to
349 * be added to the main table then no action is needed . This means
350 * that the table link of the last symbol on a chain may point any-
351 * where.
352 *
353 * look up entry in the main table
354 * call with:
1File: SYMT.C Page 7
355 * address of initial reference table
356 * entry to be looked up at the end of the main table
357 * returns:
358 * a pointer to the entry. if this pointer is equal to
359 * lmte then the symbol was not previously in the table.
360 */
361
362 char *lemt(airt,oplook)
363 char **airt;
364 int oplook; /* if true then looking in opcode table */
365 {
366 register char *mtpt;
367 register int *p1, *p2;
368 register int i, j;
369
370 if (oplook) { /* [vlh] get rid of preceding '.', to lowercase */
371 if (lmte->name[0]=='.') {
372 lmte->name[NAMELEN-1] = NULL; /* in case of '.' */
373 j = 1;
374 }
375 else j = 0;
376 for (i=0; j<NAMELEN; i++, j++)
377 lmte->name[i] = tolower(lmte->name[j]);
378 }
379
380 pirt = airt + hash(); /*hashed ptr to irt*/
381 mtpt = pirt->irfe; /*pointer to first entry in chain*/
382 if(!mtpt) /*empty chain*/
383 mtpt = lmte; /*start at end of main table*/
384 else
385 (pirt->irle)->tlnk = lmte; /*last entry in chain is new symbol*/
386
387 /*loop to locate entry in main table*/
388 lemtl:
389 p1 = &mtpt->name[0];
390 p2 = &lmte->name[0];
391 i = NAMELEN/(sizeof i);
392 while(i) {
393 if(*p1++ != *p2++) {
394 mtpt = mtpt->tlnk; /*go to next entry in chain*/
395 goto lemtl;
396 }
397 i--;
398 }
399 return(mtpt);
400 }
401
402 /* compute a hash code for the last entry in the main table*/
403 /* returns the hash code*/
404 hash()
405 {
406 register int i;
407 register ht1;
408 register char *p;
409
410 ht1 = 0;
411 p = &lmte->name[0];
412 for(i=0; i<NAMELEN; i++)
413 ht1 =+ *p++;
1File: SYMT.C Page 8
414 return(ht1&(SZIRT-2)); /*make hash code even and between 0 & SZIRT-2*/
415 }
416
417 /*
418 * Make an entry in the main table
419 * assumes :
420 * entry to be made is pointed at by lmte
421 * pirt points to the correct initial reference table entry.
422 */
423 mmte()
424 {
425 pirt->irle = lmte; /*pointer to last entry in chain*/
426 if(pirt->irfe == 0) /*first entry in chain*/
427 pirt->irfe = lmte;
428 lmte =+ STESIZE; /*bump last main table entry pointer*/
429 if(lmte>=emte) { /*main table overflow*/
430 if(sbrk(STESIZE*ICRSZMT) == -1){ /*get more memory*/
431 rpterr("symbol table overflow\n");
432 endit();
433 }
434 else {
435 emte =+ STESIZE*ICRSZMT; /*move end of main table*/
436 cszmt =+ ICRSZMT;
437 }
438 }
439 }
440
441 /*
442 * make an entry in the main table for a directive
443 * call with:
444 * pointer to string containing directive name
445 * address of routine to handle directive in pass one
446 * address of routine to handle directive in pass two
447 */
448 mdemt(mdstr,dirnum)
449 char *mdstr;
450 {
451 register char *mdept;
452
453 pack(mdstr,lmte); /*pack name at end of main table*/
454 mdept=lemt(oirt,TRUE); /*look up in opcode table*/
455 if(mdept != lmte) { /*best not be there already*/
456 uerr(5);
457 abort();
458 return;
459 }
460 mmte(); /*make main table entry*/
461 mdept->flags =| OPDR|SYIN; /*directive*/
462 mdept->vl1 = dirnum; /*directive #*/
463 }
464
465 /*
466 * pack a string into an entry in the main table
467 * call with:
468 * pointer to the string
469 * pointer to desired entry in the main table
470 */
471 pack(apkstr,apkptr)
472 char *apkstr, *apkptr;
1File: SYMT.C Page 9
473 {
474 register i;
475 register char *pkstr, *pkptr;
476
477 pkstr = apkstr;
478 pkptr = apkptr;
479 i = NAMELEN;
480 while(*pkstr && i) {
481 *pkptr++ = *pkstr++;
482 i--;
483 }
484 while(i--)
485 *pkptr++ = '\0'; /*pad with nulls*/
486 }
487
488 /* function to get characters for source file*/
489 int xcol = 0; /* Column Counter */
490 int spcnt = 0; /* Space count for tab expansion */
491 gchr()
492 {
493 register chr1;
494
495 if(peekc) {
496 chr1 = peekc;
497 peekc = 0;
498 if(chr1 != SOH)
499 xcol--;
500 }
501 else if (spcnt)
502 {
503 spcnt--;
504 return(' ');
505 }
506 else
507 {
508 gchr1:
509 if(sbuflen<=0){ /*nothing on input buffer*/
510 sbuflen=read(ifn,sbuf,512); /*read in source*/
511 if(sbuflen<=0)
512 return(EOF); /*end of file*/
513 psbuf = sbuf;
514 }
515 chr1 = *psbuf++;
516 sbuflen--;
517 }
518 if (chr1 == SOH) /*preprocessor flag*/
519 goto gchr1; /*ignore it*/
520 if(chr1 == EOLC) { /*end of line*/
521 xcol = -1; /* Clear column counter */
522 if(!p2flg) /*pass 1 only*/
523 absln++;
524 }
525 if(chr1=='\t') /*convert tabs to spaces*/
526 {
527 spcnt += 7 - (xcol&7); /* This many spaces */
528 xcol += spcnt; /* New column number */
529 chr1 = ' ';
530 }
531 xcol++;
1File: SYMT.C Page 10
532 return(chr1);
533 }
534
535 /*
536 * write out intermediate text for one statement
537 * call with
538 * the it for the statement in stbuf
539 */
540 wostb()
541 {
542 register int woix;
543 register short *itwo;
544 register int i;
545
546 if(stbuf[0].itty != ITBS) abort(); /*not beginning of stmt*/
547 itwo = &stbuf;
548 woix = stbuf[0].itrl & 0377; /*unsigned byte*/
549 while(woix--) {
550 for(i=0; i<(sizeof stbuf[0])/(sizeof *itwo); i++) {
551 doitwr(*itwo++);
552 }
553 }
554 /* debug(); //call debug package*/
555 }
556
557 doitwr(word)
558 short word;
559 {
560 short i;
561
562 if( pitix < itbuf || pitix > &itbuf[ITBSZ] ) {
563 printf("doitwr: it buffer botch\n");
564 endit();
565 }
566 if( pitix >= &itbuf[ITBSZ]) {
567 if(write(itfn,itbuf,ITBSZ*(sizeof i)) != ITBSZ*(sizeof i)) {
568 rpterr("it write error errno=%o\n",errno);
569 endit();
570 }
571 pitix = itbuf;
572 }
573 *pitix++ = word;
574 }
575
576 /*
577 * user source error
578 * call with:
579 * number to indicate reason for error
580 * types the error number and the line number on which
581 * the error occured.
582 */
583 uerr(errn)
584 {
585 if(p2flg) { /*pass 2 gets two ampersands*/
586 in_err++; /* [vlh] instrlen <- pass1 estimation */
587 printf("&& %d: %s\n",p2absln,ermsg[errn-1]);
588 }
589 else
590 printf("& %d: %s\n",(fchr==EOLC)?absln-1:absln,ermsg[errn-1]);
1File: SYMT.C Page 11
591 nerror++;
592 }
593 /*
594 * user error that causes the statement to be abandoned
595 * call with:
596 * error number
597 */
598 xerr(xern)
599 {
600 uerr(xern); /*type error message*/
601 if(!p2flg) /*pass one*/
602 igrst(); /*pass rest of source*/
603 }
604
605 /* abort the assembly*/
606 abort()
607 {
608 rpterr("as68 abort\n");
609 nerror++;
610 endit();
611 }
612
613 /*ignore rest of statement*/
614 igrst()
615 {
616 while(fchr!=EOLC && fchr!=EOF) /*until end of line*/
617 fchr=gchr();
618 while((fchr=gchr())==EOLC) ; /*ignore null lines*/
619 }
620
621 /*ignore blanks after a label*/
622 ligblk()
623 {
624 if(fchr == EOF) return;
625 igblk();
626 if(fchr==EOLC) {
627 fchr=gchr();
628 ligblk();
629 }
630 }
631
632 rubout()
633 {
634 nerror = -1;
635 endit();
636 }
637
638 /* exit from the assembler*/
639 endit()
640 {
641 LASTCHTFN = itfnc;
642 unlink(tfilname); /*delete temporary files*/
643 LASTCHTFN = trbfnc;
644 unlink(tfilname);
645 LASTCHTFN = dafnc;
646 unlink(tfilname);
647 LASTCHTFN = drbfnc;
648 unlink(tfilname);
649 if(nerror != -1) { /*not rubout*/
1File: SYMT.C Page 12
650 if(ftudp)
651 putchar('\n');
652 }
653 if(nerror > 0) {
654 fprintf(stderr,"& %d errors\n",nerror);
655 }
656 if (initflg)
657 unlink(ldfn); /* [vlh] get rid of empty .o file */
658 exit(nerror!=0);
659 }
660
661 /*
662 * open files
663 * call with:
664 * pointer to name of file to open
665 * flag for how to open
666 * 0 => read
667 * 1 => write
668 */
669 openfi(pname,hflag)
670 char *pname;
671 {
672 register fd;
673
674 fd = (hflag==1) ? creat(pname,0666,1) : open(pname,hflag,1);
675 if(fd < 0) { /*open failed*/
676 rpterr("can't open %s errno=%o\n",pname,errno);
677 endit();
678 }
679 return(fd);
680 }
681
682 /* get a temp file for the intermediate text*/
683 char lastfile = 'A';
684 gettempf()
685 {
686 register i,j;
687 register char *p;
688
689 LASTCHTFN = lastfile++; /* Creat temp name */
690 if((j=creat(tfilname,0600,1)) >= 0)
691 return(j); /* File created OK */
692 rpterr("Unable to open temporary file\n");
693 endit();
694 }
695
696 /* move label name from lbt to main table entry pointed to by lmte*/
697 setname()
698 {
699 register i;
700 register int *p1, *p2;
701
702 p1 = &lmte->name[0];
703 for(p2 = &lbt[0]; p2 < &lbt[NAMELEN]; ) {
704 *p1++ = *p2;
705 *p2++ = 0;
706 }
707 }
708
1File: SYMT.C Page 13
709 /* get the initialized main table and initial reference tables from*/
710 /* the initialize file*/
711 getsymtab()
712 {
713 long j; /* length for read / write */
714 register char **p;
715 register struct symtab *p1;
716 register char *p2;
717 register fd,i;
718
719 if((fd=open(initfnam,0,1)) < 0) {
720 rerr:
721 printf("& Unable to read init file: %s\n", initfnam);
722 endit();
723 }
724 if(read(fd,sirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0])) {
725 goto rerr;
726 }
727
728 if(read(fd,oirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0]))
729 goto rerr;
730
731 if(read(fd,&j,(sizeof j)) != (sizeof j)) /* Read Count */
732 goto rerr; /* Y-U-K!!! */
733
734 if((i=read(fd,bmte,(int)j)) != j) /* Read table */
735 goto rerr;
736
737 if((i%STESIZE) != 0)
738 goto rerr;
739
740 lmte = bmte + i;
741 p2 = bmte-1;
742 for(p=sirt; p<&sirt[SZIRT]; p++) {
743 if(*p)
744 *p =+ (long)p2;
745 }
746 for(p=oirt; p<&oirt[SZIRT]; p++) {
747 if(*p)
748 *p =+ (long)p2;
749 }
750 for(p1=bmte; p1<lmte; p1++) {
751 if(p1->tlnk)
752 p1->tlnk =+ (long)p2;
753 }
754 close(fd);
755 }
756
757 /* write the initialization file*/
758 putsymtab()
759 {
760 long j;
761 register char **p;
762 register struct symtab *p1;
763 register char *p2;
764 register fd,i;
765
766 if((fd=creat(initfnam,0644,1))<0) {
767 printf("& Cannot create init: %s\n", initfnam);
1File: SYMT.C Page 14
768 return;
769 }
770 /*
771 * change all pointers so that they are relative to the beginning
772 * of the symbol table
773 */
774 p2 = bmte-1;
775 for(p=sirt; p<&sirt[SZIRT]; p++) {
776 if(*p)
777 *p =- (long)p2;
778 }
779 for(p=oirt; p<&oirt[SZIRT]; p++) {
780 if(*p)
781 *p =- (long)p2;
782 }
783 for(p1=bmte; p1<lmte; p1++) {
784 if(p1->tlnk)
785 p1->tlnk =- (long)p2;
786 }
787
788 if(write(fd,sirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0])) {
789 goto werr;
790 }
791
792 if(write(fd,oirt,SZIRT*(sizeof oirt[0])) != SZIRT*(sizeof oirt[0]))
793 goto werr;
794
795 i = lmte - bmte; /*length of current main table*/
796 if((i % STESIZE) != 0) {
797 goto werr;
798 }
799 j = i;
800 if(write(fd,&j,(sizeof j)) != (sizeof j)) /* Y-U-K!! */
801 goto werr;
802
803 if(write(fd,bmte,i) != i) {
804 werr:
805 printf("& Write error on init file: %s\n",initfnam);
806 return;
807 }
808 close(fd);
809 }
810
811 /* print an error on file descriptor 2*/
812 /* used for errors with disasterous consequences*/
813 rpterr(ptch,x1,x2,x3,x4,x5,x6)
814 char *ptch;
815 {
816 if(prtflg==0) /* Check for paging output */
817 page(); /* Perform page checks */
818 fprintf(stderr,"& %d: ",absln);
819 fprintf(stderr,ptch,x1,x2,x3,x4,x5,x6);
820 }
821
822 /* set the file name for the relocatable object file (sourcefile.o)*/
823 setldfn(ap)
824 char *ap;
825 {
826 register char *p1,*p2;
1File: SYMT.C Page 15
827
828 p1 = ap;
829 p2 = ldfn;
830 while(*p1) {
831 *p2++ = *p1++;
832 }
833 if(*(p2-2) != '.') { /*not name.?*/
834 *p2++ = '.';
835 *p2++ = 'o';
836 }
837 else { /* is name.? */
838 *(p2-1) = 'o';
839 }
840 *p2 = '\0';
841 }
842
843 savelab()
844 {
845 register int *p1, *p2;
846
847 p2 = &lmte->name[0];
848 for(p1= &tlab1[0]; p1 < &tlab1[NAMELEN]; )
849 *p1++ = *p2++;
850 }

View File

@@ -0,0 +1,19 @@
e:vax DIR.C s
e:vax EXPR.C s
e:vax MAIN.C s
e:vax MISC.C s
e:vax PASS1A.C s
e:vax PASS2.C s
e:vax MAKE.SUB s
e:vax STRNCMP.C s
e:vax SYMT.C s
e:vax VERSION.C s
e:vax AS68.H s
e:vax COUT.H s
e:vax CTYPE.H s
e:vax MACHINE.H s
e:vax RELINK.SUB s
e:vax MACHINE.11 s
e:vax MACHINE.68K s
e:vax MACHINE.VAX s
e:vax AS68INIT. s

View File

@@ -0,0 +1 @@
char *version "@(#) Tue Nov 23 14:31";

View File

@@ -0,0 +1,2 @@
1File: VERSION.C Page 1
1 char *version "@(#) Tue Nov 23 14:31";

View File

@@ -0,0 +1,15 @@
$ asm
$ !
$ ! as68 Version 2.3 make file for VMS
$ !
$ set noon
$ copy machine.vax machine.h
$ cx AS68INIT
$ cx DIR
$ cx EXPR
$ cx MAIN
$ cx MISC
$ cx PASS1A
$ cx PASS2
$ cx SYMT
$ @vrelink

View File

@@ -0,0 +1 @@
$ clink AS68INIT,DIR,EXPR,MAIN,PASS1A,PASS2,SYMT,MISC,lib:klib/lib as68

View File

@@ -0,0 +1,26 @@
$ set noon
$ vsend AS68.H
$ vsend AS68INIT.
$ vsend AS68INIT.C
$ vsend COUT.H
$ vsend CTYPE.H
$ vsend DIR.C
$ vsend EXPR.C
$ vsend LIST.COM
$ vsend MACHINE.11
$ vsend MACHINE.68K
$ vsend MACHINE.H
$ vsend MACHINE.VAX
$ vsend MAIN.C
$ vsend MAKE.SUB
$ vsend MISC.C
$ vsend PASS1A.C
$ vsend PASS2.C
$ vsend RELINK.SUB
$ vsend STRNCMP.C
$ vsend SYMT.C
$ vsend UP9.SUB
$ vsend VERSION.C
$ vsend VMAKE.COM
$ vsend VRELINK.COM
$ vsend done

View File

@@ -0,0 +1,13 @@
$ xer AS68INIT.LIS
$ xer DIR.LIS
$ xer EXPR.LIS
$ xer MAIN.LIS
$ xer MISC.LIS
$ xer PASS1A.LIS
$ xer PASS2.LIS
$ xer SYMT.LIS
$ xer VERSION.LIS
$ xer AS68.LST
$ xer COUT.LST
$ xer CTYPE.LST
$ xer MACHINE.LST

View File

@@ -0,0 +1,18 @@
Directory DRB0:[STEVE.CPM68K.V102.AS68]
AS68INIT.LIS;1
DIR.LIS;1
EXPR.LIS;1
MAIN.LIS;1
MISC.LIS;1
PASS1A.LIS;1
PASS2.LIS;1
SYMT.LIS;1
VERSION.LIS;1
AS68.LST;1
COUT.LST;1
CTYPE.LST;1
MACHINE.LST;1
Total of 13 files.

View File

@@ -0,0 +1,180 @@
/********************************************************
* *
* CP/M-68K header file *
* Copyright (c) 1982 by Digital Research, Inc. *
* Structure definitions for BDOS globals *
* and BDOS data structures *
* *
* Desecrated 6-Aug-83 (sw) for type-ahead *
* *
********************************************************/
/**************************************************************************
The BDOS data structures, especially those relating to global variables,
are structured in a way that hopefully will enable this BDOS, in the future,
to easily become a re-entrant multi-tasking file system. Consequently,
the BDOS global variables are divided into two classes. Those that are
truly global, even in the case of multiple tasks using the file system
concurrently, are simply declared as global variables in bdosmain.c.
Only a few "globals" are really global in this sense.
The majority of the "global" variables are actually state variables that
relate to the state of the task using the file system. In CP/M-68K, these
are "global", since there's only one task, but in a multi-thread model they're
not. This type of variables is put into a data structure, with the
intention that in the multi-task environment this structure will be based.
The following declarations take this philosophy into account, and define
a simple structure for the single thread environment while leaving the
possibilities open for the multi-thread environment.
****************************************************************************/
#define snglthrd TRUE
/* TRUE for single-thread environment
FALSE to create based structure for re-entrant model */
#if snglthrd
#define GBL gbls
/* In single thread case, GBL just names
the structure */
#define BSETUP EXTERN struct stvars gbls;
/* and BSETUP defines the extern structure */
#endif
#if ! snglthrd
#define GBL (*statep)
/* If multi-task, state vars are based */
#define BSETUP REG struct stvars *statep; \
statep = &gbls;
/* set up pointer to state variables */
/* This is intended as an example to show the intent */
#endif
/* Note that there are a few critical regions in the file system that must
execute without interruption. They pertain mostly to the manipulation of
the allocation vector. This isn't a problem in a single-thread model, but
must be provided for in a multi-tasking file system. Consequently, the
primitives LOCK and UNLOCK are defined and used where necessary in the
file system. For the single thread model, they are null routines */
#define LOCK /**/
#define UNLOCK /**/
/* Be sure LOCK and UNLOCK are implemented to allow recursive calls to LOCK.
That is, if a process that calls LOCK already owns the lock, let it proceed,
but remember that only the outer-most call to UNLOCK really releases the
file system. */
#define VERSION 0x2022 /* Version number for CP/M-68K */
#define robit 0 /* read-only bit in file type field of fcb */
#define arbit 2 /* archive bit in file type field of fcb */
#define SECLEN 128 /* length of a CP/M sector */
/* File Control Block definition */
struct fcb
{
UBYTE drvcode; /* 0 = default drive, 1..16 are drives A..P */
UBYTE fname[8]; /* File name (ASCII) */
UBYTE ftype[3]; /* File type (ASCII) */
UBYTE extent; /* Extent number (bits 0..4 used) */
UBYTE s1; /* Reserved */
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
union
{
UBYTE small[16]; /* 16 block numbers of 1 byte */
WORD big[8]; /* or 8 block numbers of 1 word */
} dskmap;
UBYTE cur_rec; /* current record field */
UBYTE ran0; /* random record field (3 bytes) */
UBYTE ran1;
UBYTE ran2;
};
/* Declaration of directory entry */
struct dirent
{
UBYTE entry; /* 0 - 15 for user numbers, E5 for empty */
/* the rest are reserved */
UBYTE fname[8]; /* File name (ASCII) */
UBYTE ftype[3]; /* File type (ASCII) */
UBYTE extent; /* Extent number (bits 0..4 used) */
UBYTE s1; /* Reserved */
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
union
{
UBYTE small[16]; /* 16 block numbers of 1 byte */
WORD big[8]; /* or 8 block numbers of 1 word */
} dskmap;
};
/* Declaration of disk parameter tables */
struct dpb /* disk parameter table */
{
UWORD spt; /* sectors per track */
UBYTE bsh; /* block shift factor */
UBYTE blm; /* block mask */
UBYTE exm; /* extent mask */
UBYTE dpbdum; /* dummy byte for fill */
UWORD dsm; /* max disk size in blocks */
UWORD drm; /* max directory entries */
UWORD dir_al; /* initial allocation for dir */
UWORD cks; /* number dir sectors to checksum */
UWORD trk_off; /* track offset */
};
struct dph /* disk parameter header */
{
UBYTE *xlt; /* pointer to sector translate table */
UWORD hiwater; /* high water mark for this disk */
UWORD dum1; /* dummy (unused) */
UWORD dum2;
UBYTE *dbufp; /* pointer to 128 byte directory buffer */
struct dpb *dpbp; /* pointer to disk parameter block */
UBYTE *csv; /* pointer to check vector */
UBYTE *alv; /* pointer to allocation vector */
};
/* Declaration of structure containing "global" state variables */
#define TBUFSIZ 126 /*sw # typed-ahead characters */
struct stvars
{
UBYTE kbchar; /* keyboard type-ahead buffer count */
UBYTE delim; /* Delimiter for function 9 */
BOOLEAN lstecho; /* True if echoing console output to lst: */
BOOLEAN echodel; /* Echo char when getting <del> ? */
UWORD column; /* CRT column number for expanding tabs */
UBYTE *chainp; /* Used for chain to program call */
UBYTE curdsk; /* Currently selected disk */
UBYTE dfltdsk; /* Default disk (last selected by fcn 14) */
UBYTE user; /* Current user number */
struct dph *dphp; /* pointer to disk parm hdr for cur disk */
struct dirent *dirbufp; /* pointer for directory buff for process */
/* stored here so that each process can */
/* have a separate dirbuf. */
struct dpb *parmp; /* pointer to disk parameter block for cur */
/* disk. Stored here to save ref calc */
UWORD srchpos; /* position in directory for search next */
UBYTE *dmaadr; /* Disk dma address */
struct fcb *srchp; /* Pointer to search FCB for function 17 */
UBYTE *excvec[18]; /* Array of exception vectors */
UBYTE *insptr; /*sw Insertion pointer for typeahead */
UBYTE *remptr; /*sw Removal pointer for typeahead */
UBYTE t_buff[TBUFSIZ]; /*sw Type-ahead buffer itself */
};
/* Console buffer structure declaration */
struct conbuf
{
UBYTE maxlen; /* Maximum length from calling routine */
UBYTE retlen; /* Length actually found by BDOS */
UBYTE cbuf[]; /* Console data */
};

View File

@@ -0,0 +1,154 @@
*****************************************************************
* *
* CP/M-68K Basic Disk Operating System interface module *
* For "C" version of CP/M-68K *
* *
* Copyright (c) 1982 Digital Research, Inc. *
* *
* Version 0.2 -- September 22, 1982 *
* *
*****************************************************************
* Declare Public Routines
.globl _bios1 * 6 BIOS entry points from BDOS
.globl _bios2
.globl _bios3
.globl _bios4
.globl _bios5
.globl _bios6
.globl _traphnd * trap #2 handler
.globl _swap * byte swapper
.globl _udiv * unsigned divide routine
* Declare external routines
.globl __bdos * BDOS entry point in bdosmain
* The following external references were put in just to make sure that all
* the BDOS modules were referenced, so we could put them in a library
.globl _constat * references conbdos.o
.globl _dirscan * references dskutil.o
.globl _create * references fileio.o
.globl _bdosrw * references bdosrw.o
biosf = 50
setsupf = 62
_traphnd:
*
* first save the registers and
* check for functions handled by assembly language routines
*
cmpi #setsupf,d0
beq setsup
movem.l d1-d7/a0-a6,-(sp)
cmpi #biosf,d0
beq bioscall
*
* function number is passed in D0
* byte and word pararmeters are passed in D1.W
* address parameters are passed in D1.L
*
move.l d1,-(a7)
move.w d1,-(a7)
move.w d0,-(a7)
jsr __bdos * call BDOS
*
* now restore the regs
*
ext.l d0
addq #8,sp * fix up the stack
bdone:
movem.l (sp)+,a0-a6/d1-d7
rte * return from trap call
*
* direct BIOS call function
*
bioscall:
move.l d1,a0 * get address of CPB
move.w (a0)+,d0
movem.l (a0)+,d1-d2
trap #3
bra bdone
*
* Set supervisor mode procedure
*
setsup:
ori #$2000,(sp) * turn on supervisor bit in SR
rte
*
* BIOS Interface Routines
*
*
* Note - there are 6 BIOS entry points from the BDOS, labelled BIOS1 -
* BIOS6, depending on the parameters passed.
_bios5:
* For BIOS functions sectran and set exception vector
* Has function number and 2 parameters, a word followed by a long word
move.l 8(sp),d2 * get 2nd parameter (long word)
bra _bios2 * join common routine
_bios4:
* For BIOS function seldsk
* Has function number followed by 2 word parameters
move.w 8(sp),d2 * get 2nd parameter (word)
bra _bios2 * join common routine
_bios3:
* For BIOS function set dma
* Has function number followed by 1 long parameter
move.l 6(sp),d1 * get long word parameter
bra _bios1 * join common routine
_bios2:
* For all BIOS functions with a word parameter
* Word parameter follows function number
move.w 6(sp),d1 * get 1st parameter (word)
_bios6:
_bios1:
* For all BIOS functions that have no parameter other than function number
move.w 4(sp),d0 * get function number
movem.l d3-d7/a3-a6,-(sp)
* * save C register variables
trap #3 * do BIOS call
* * returns value in d0
movem.l (sp)+,d3-d7/a3-a6
rts
*
* Utility Subroutines
*
_swap:
* Swap bytes of a word, return swapped value in d0
move.b 5(sp),d0
lsl #8,d0
move.b 4(sp),d0
rts
_udiv:
* Unsigned divide routine
* returns unsigned quotient in D0.W
* UWORD udiv( divisor, dividend, remp )
*
* REG LONG divisor;
* UWORD dividend;
* UWORD *remp /* pointer to remainder (returned) */
move.l 4(sp), d0 * get dividend
divu 8(sp), d0 * do the divide
movea.l 10(sp),a0
swap d0
move.w d0, (a0) * store remainder
clr.w d0
swap d0 * word quotient in d0
rts
.end

View File

@@ -0,0 +1,68 @@
/*****************************************************************************
*
* C P / M C H E A D E R F I L E
* -----------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* This is an include file for assisting the user to write portable
* programs for C.
*
*****************************************************************************/
#define ALCYON 1 /* using Alcyon compiler */
/*
* Standard type definitions
*/
/***************************/
#define BYTE char /* Signed byte */
#define BOOLEAN char /* 2 valued (true/false) */
#define WORD short /* Signed word (16 bits) */
#define UWORD unsigned int /* unsigned word */
#define LONG long /* signed long (32 bits) */
#define ULONG unsigned long /* Unsigned long */
#define REG register /* register variable */
#define LOCAL auto /* Local var on 68000 */
#define EXTERN extern /* External variable */
#define MLOCAL static /* Local to module */
#define GLOBAL /**/ /* Global variable */
#define VOID /**/ /* Void function return */
/***************************/
#ifdef ALCYON
#define UBYTE char
#define UBWORD(a) ((UWORD)a & 0xff)
/* Unsigned byte to word cast */
#else
#define UBYTE unsigned char /* Unsigned byte */
#define UBWORD(a) (UWORD)a
#endif
/****************************************************************************/
/* Miscellaneous Definitions: */
/****************************************************************************/
#define FAILURE (-1) /* Function failure return val */
#define SUCCESS (0) /* Function success return val */
#define YES 1 /* "TRUE" */
#define NO 0 /* "FALSE" */
#define FOREVER for(;;) /* Infinite loop declaration */
#define NULL (BYTE *)0 /* Null pointer value */
#define EOF (-1) /* EOF Value */
#define TRUE (1) /* Function TRUE value */
#define FALSE (0) /* Function FALSE value */
/****************************************************************************/
/* */
/* M A C R O S */
/* ----------- */
/* */
/* Define some stuff as macros .... */
/* */
/****************************************************************************/
#define abs(x) ((x) < 0 ? -(x) : (x)) /* Absolute value function */
#define max(x,y) (((x) > (y)) ? (x) : (y)) /* Max function */
#define min(x,y) (((x) < (y)) ? (x) : (y)) /* Min function */
/*************************** end of stdio.h *********************************/

View File

@@ -0,0 +1,304 @@
/****************************************************************
* *
* CP/M-68K BDOS Main Routine *
* *
* This is the main routine for the BDOS for CP/M-68K *
* It has one entry point, _bdos, which is called from *
* the assembly language trap handler found in bdosif.s. *
* The parameters are a function number (integer) and an *
* information parameter (which is passed from bdosif as *
* both an integer and a pointer).
* The BDOS can potentially return a pointer, long word, *
* or word *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "bdosinc.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "biosdef.h" /* Declarations of BIOS functions */
/* Declare EXTERN functions */
EXTERN warmboot(); /* Warm Boot function */
EXTERN BOOLEAN constat(); /* Console status */
EXTERN UBYTE conin(); /* Console Input function */
EXTERN tabout(); /* Console output with tab expansion */
EXTERN UBYTE rawconio(); /* Raw console I/O */
EXTERN prt_line(); /* Print line until delimiter */
EXTERN readline(); /* Buffered console read */
EXTERN seldsk(); /* Select disk */
EXTERN BOOLEAN openfile(); /* Open File */
EXTERN UWORD close_fi(); /* Close File */
EXTERN UWORD search(); /* Search first and next fcns */
EXTERN UWORD dirscan(); /* General directory scanning routine */
EXTERN UWORD bdosrw(); /* Sequential and Random disk read/write */
EXTERN BOOLEAN create(); /* Create file */
EXTERN BOOLEAN delete(); /* Delete file */
EXTERN BOOLEAN rename(); /* Rename file */
EXTERN BOOLEAN set_attr(); /* Set file attributes */
EXTERN getsize(); /* Get File Size */
EXTERN setran(); /* Set Random Record */
EXTERN free_sp(); /* Get Disk Free Space */
EXTERN UWORD flushit(); /* Flush Buffers */
EXTERN UWORD pgmld(); /* Program Load */
EXTERN UWORD setexc(); /* Set Exception Vector */
EXTERN set_tpa(); /* Get/Set TPA Limits */
EXTERN move(); /* general purpose byte mover */
/* Declare "true" global variables; i.e., those which will pertain to the
entire file system and thus will remain global even when this becomes
a multi-tasking file system */
GLOBAL UWORD log_dsk; /* 16-bit vector of logged in drives */
GLOBAL UWORD ro_dsk; /* 16-bit vector of read-only drives */
GLOBAL UWORD crit_dsk; /* 16-bit vector of drives in "critical"
state. Used to control dir checksums */
GLOBAL BYTE *tpa_lp; /* TPA lower boundary (permanent) */
GLOBAL BYTE *tpa_lt; /* TPA lower boundary (temporary) */
GLOBAL BYTE *tpa_hp; /* TPA upper boundary (permanent) */
GLOBAL BYTE *tpa_ht; /* TPA upper boundary (temporary) */
/* Declare the "state variables". These are globals for the single-thread
version of the file system, but are put in a structure so they can be
based, with a pointer coming from the calling process */
GLOBAL struct stvars gbls;
struct tempstr
{
UBYTE tempdisk;
BOOLEAN reselect;
struct fcb *fptr;
};
/****************************************************************
* *
* _bdos MAIN ROUTINE *
* *
* Called with _bdos(func, info, infop) *
* *
* Where: *
* func is the BDOS function number (d0.w) *
* info is the word parameter (d1.w) *
* infop is the pointer parameter (d1.l) *
* note that info is the word form of infop*
* *
****************************************************************/
UWORD _bdos(func,info,infop)
REG WORD func; /* BDOS function number */
REG UWORD info; /* d1.w word parameter */
REG UBYTE *infop; /* d1.l pointer parameter */
{
REG UWORD rtnval;
LOCAL struct tempstr temp;
BSETUP
temp.reselect = FALSE;
temp.fptr = infop;
rtnval = 0;
switch (func) /* switch on function number */
{
case 0: warmboot(0); /* warm boot function */
/* break; */
case 1: return((UWORD)conin()); /* console input function */
/* break; */
case 2: tabout((UBYTE)info); /* console output with */
break; /* tab expansion */
case 3: return((UWORD)brdr()); /* get reader from bios */
/* break; */
case 4: bpun((UBYTE)info); /* punch output to bios */
break;
case 5: blstout((UBYTE)info); /* list output from bios */
break;
case 6: return((UWORD)rawconio(info)); /* raw console I/O */
/* break; */
case 7: return(bgetiob()); /* get i/o byte */
/* break; */
case 8: bsetiob(info); /* set i/o byte function */
break;
case 9: prt_line(infop); /* print line function */
break;
case 10: readline(infop); /* read buffered con input */
break;
case 11: return((UWORD)constat()); /* console status */
/* break; */
case 12: return(VERSION); /* return version number */
/* break; */
case 13: log_dsk = 0; /* reset disk system */
ro_dsk = 0;
crit_dsk= 0;
GBL.curdsk = 0xff;
GBL.dfltdsk = 0;
break;
case 14: seldsk((UBYTE)info); /* select disk */
GBL.dfltdsk = (UBYTE)info;
break;
case 15: tmp_sel(&temp); /* open file */
infop->extent = 0;
infop->s2 = 0;
rtnval = dirscan(openfile, infop, 0);
break;
case 16: tmp_sel(&temp); /* close file */
rtnval = close_fi(infop);
break;
case 17: GBL.srchp = infop; /* search first */
rtnval = search(infop, 0, &temp);
break;
case 18: infop = GBL.srchp; /* search next */
temp.fptr = infop;
rtnval = search(infop, 1, &temp);
break;
case 19: tmp_sel(&temp); /* delete file */
rtnval = dirscan(delete, infop, 2);
break;
case 20: tmp_sel(&temp); /* read sequential */
rtnval = bdosrw(infop, TRUE, 0);
break;
case 21: tmp_sel(&temp); /* write sequential */
rtnval = bdosrw(infop, FALSE, 0);
break;
case 22: tmp_sel(&temp); /* create file */
infop->extent = 0;
infop->s1 = 0;
infop->s2 = 0;
infop->rcdcnt = 0;
/* Zero extent, S1, S2, rcrdcnt. create zeros rest */
rtnval = dirscan(create, infop, 8);
break;
case 23: tmp_sel(&temp); /* rename file */
rtnval = dirscan(rename, infop, 2);
break;
case 24: return(log_dsk); /* return login vector */
/* break; */
case 25: return(UBWORD(GBL.dfltdsk)); /* return current disk */
/* break; */
case 26: GBL.dmaadr = infop; /* set dma address */
break;
/* No function 27 -- Get Allocation Vector */
case 28: ro_dsk |= 1<<GBL.dfltdsk; /* set disk read-only */
break;
case 29: return(ro_dsk); /* get read-only vector */
/* break; */
case 30: tmp_sel(&temp); /* set file attributes */
rtnval = dirscan(set_attr, infop, 2);
break;
case 31: if (GBL.curdsk != GBL.dfltdsk) seldsk(GBL.dfltdsk);
move( (GBL.parmp), infop, sizeof *(GBL.parmp) );
break; /* return disk parameters */
case 32: if ( (info & 0xff) <= 15 ) /* get/set user number */
GBL.user = (UBYTE)info;
return(UBWORD(GBL.user));
/* break; */
case 33: tmp_sel(&temp); /* random read */
rtnval = bdosrw(infop, TRUE, 1);
break;
case 34: tmp_sel(&temp); /* random write */
rtnval = bdosrw(infop, FALSE, 1);
break;
case 35: tmp_sel(&temp); /* get file size */
getsize(infop);
break;
case 36: tmp_sel(&temp); /* set random record */
setran(infop);
break;
case 37: info = ~info; /* reset drive */
log_dsk &= info;
ro_dsk &= info;
crit_dsk &= info;
break;
case 40: tmp_sel(&temp); /* write random with 0 fill */
rtnval = bdosrw(infop, FALSE, 2);
break;
case 46: free_sp(info); /* get disk free space */
break;
case 47: GBL.chainp = GBL.dmaadr; /* chain to program */
warmboot(0); /* terminate calling program */
/* break; */
case 48: return( flushit() ); /* flush buffers */
/* break; */
case 59: return(pgmld(infop,GBL.dmaadr)); /* program load */
/* break; */
case 61: return(setexc(infop)); /* set exception vector */
/* break; */
case 63: set_tpa(infop); /* get/set TPA limits */
break;
default: return(-1); /* bad function number */
/* break; */
}; /* end of switch statement */
if (temp.reselect) infop->drvcode = temp.tempdisk;
/* if reselected disk, restore it now */
return(rtnval); /* return the BDOS return value */
} /* end _bdos */
tmp_sel(temptr) /* temporarily select disk pointed to by fcb */
REG struct tempstr *temptr;
{
REG struct fcb *fcbp;
REG UBYTE tmp_dsk;
BSETUP
fcbp = temptr->fptr; /* get local copy of fcb pointer */
tmp_dsk = (temptr->tempdisk = fcbp->drvcode);
seldsk( tmp_dsk ? tmp_dsk - 1 : GBL.dfltdsk );
fcbp->drvcode = GBL.user;
temptr->reselect = TRUE;
}

View File

@@ -0,0 +1,308 @@
/****************************************************************
* *
* CP/M-68K BDOS Miscellaneous Module *
* *
* This module contains miscellaneous loose ends for *
* CP/M-68K. Included are: *
* *
* bdosinit() - BDOS initialization routine *
* called from CCP for system init *
* warmboot() - BDOS warm boot exit routine *
* error() - BDOS error printing routine *
* ro_err() - BDOS read-only file error routine *
* setexc() - BDOS set exception vector *
* set_tpa() - BDOS get/set TPA limits *
* serial # and copyright notice, machine readable *
* *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "bdosinc.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "biosdef.h" /* BIOS definitions, needed for bios wboot */
/* serial # and copyright notice */
char *copyrt="CP/M-68K(tm), Version 1.1, Copyright (c) 1983, Digital Research";
char *serial="XXXX-0000-654321";
/* Declare external functions */
EXTERN conout(); /* Console Output function */
EXTERN UBYTE conin(); /* Console Input function */
EXTERN prt_line(); /* Print String function */
EXTERN UWORD _bdos(); /* BDOS main routine */
EXTERN UBYTE *traphndl(); /* assembly language trap handler */
EXTERN initexc(); /* init the exception handler in */
/* exceptn.s */
EXTERN UWORD dirscan(); /* Directory scanning routine */
EXTERN BOOLEAN set_attr(); /* Set File attributes function */
EXTERN UWORD dir_rd(); /* Read directory sector routine */
/* Declare external variables */
EXTERN UWORD log_dsk; /* logged-on disk vector */
EXTERN UWORD ro_dsk; /* read-only disk vector */
EXTERN UWORD crit_dsk; /* vector of critical disks */
EXTERN BYTE *tpa_lt; /* TPA lower limit (temporary) */
EXTERN BYTE *tpa_lp; /* TPA lower limit (permanent) */
EXTERN BYTE *tpa_ht; /* TPA upper limit (temporary) */
EXTERN BYTE *tpa_hp; /* TPA upper limit (permanent) */
EXTERN BOOLEAN submit; /* external variables from CCP */
EXTERN BOOLEAN morecmds;
#define trap2v 34 /* trap 2 vector number */
#define ctrlc 3 /* control-c */
/********************************
* bdos initialization routine *
********************************/
bdosinit()
/* Initialize the File System */
{
REG struct
{
WORD nmbr;
BYTE *low;
LONG length;
} *segp;
BSETUP
bsetvec(trap2v, &traphndl); /* set up trap vector */
GBL.kbchar = 0; /* initialize the "global" variables */
GBL.insptr = GBL.remptr = &(GBL.t_buff[0]);
GBL.delim = '$';
GBL.lstecho = FALSE;
GBL.echodel = TRUE;
GBL.chainp = NULL;
_bdos(13); /* reset disk system function */
segp = bgetseg(); /* get pointer to memory segment table */
tpa_lt = tpa_lp = segp->low;
tpa_ht = tpa_hp = tpa_lp + segp->length;
initexc( &(GBL.excvec[0]) );
}
/************************
* warmboot entry point *
************************/
warmboot(parm)
/* Warm Boot the system */
WORD parm; /* 1 to reset submit flag */
{
BSETUP
log_dsk &= ~ro_dsk; /* log off any disk marked read-only */
/* note that this code is specifically for a single-
thread system. It won't work in a multi-task sys */
ro_dsk = 0;
crit_dsk = 0;
if (parm)
submit = morecmds = FALSE;
GBL.curdsk = 0xff; /* set current disk to "unknown" */
tpa_lt = tpa_lp;
tpa_ht = tpa_hp;
initexc( &(GBL.excvec[0]) );
bwboot();
}
/*************************/
/* disk error handlers */
/*************************/
prt_err(p)
/* print the error message */
BYTE *p;
{
BSETUP
prt_line(p);
prt_line(" error on drive $");
conout(GBL.curdsk + 'A');
}
abrt_err(p)
/* print the error message and always abort */
BYTE *p;
{
prt_err(p);
warmboot(1);
}
ext_err(cont,p)
/* print the error message, and allow for retry, abort, or ignore */
REG BOOLEAN cont; /* Boolean for whether continuing is allowed */
BYTE *p; /* pointer to error message */
{
REG UBYTE ch;
prt_err(p);
do
{
prt_line("\n\rDo you want to: Abort (A), Retry (R)$");
if (cont) prt_line(", or Continue with bad data (C)$");
prt_line("? $");
ch = conin() & 0x5f;
prt_line("\r\n$");
switch ( ch )
{
case ctrlc: warmboot(1);
case 'A': warmboot(1);
case 'C': if (cont) return(1);
break;
case 'R': return(0);
}
} while (TRUE);
}
/********************************/
/* Read-only File Error Routine */
/********************************/
ro_err(fcbp,dirindx)
/* File R/O error */
REG struct fcb *fcbp;
WORD dirindx;
{
REG BYTE *p;
REG UWORD i;
REG UBYTE ch;
p = (BYTE *)fcbp;
prt_line("CP/M Disk file error: $");
i = 8;
do conout(*++p & 0x7f); while (--i);
conout('.');
i = 3;
do conout(*++p & 0x7f); while (--i);
prt_line(" is read-only.$");
do
{
prt_line("\r\nDo you want to: Change it to read/write (C), or Abort (A)? $");
ch = conin() & 0x5f;
prt_line("\r\n$");
switch ( ch )
{
case ctrlc: warmboot(1);
case 'A': warmboot(1);
case 'C': fcbp->ftype[robit] &= 0x7f;
dirscan(set_attr, fcbp, 2);
return(dir_rd(dirindx >> 2));
} /* Reset the directory buffer !!!! */
} while (TRUE);
}
/************************
* error entry point *
************************/
error(errnum)
/* Print error message, do appropriate response */
UWORD errnum; /* error number */
{
BSETUP
prt_line("\r\nCP/M Disk $");
switch (errnum)
{
case 0: return( ext_err(TRUE,"read$") );
/* break; */
case 1: return( ext_err(TRUE,"write$") );
/* break; */
case 2: abrt_err("select$");
/* break; */
case 3: return( ext_err(FALSE,"select$") );
/* break; */
case 4: abrt_err("change$");
/* break; */
}
}
/*****************************
* set exception entry point *
*****************************/
setexc(epbp)
/* Set Exception Vector */
REG struct
{
WORD vecnum;
BYTE *newvec;
BYTE *oldvec;
} *epbp;
{
REG WORD i;
BSETUP
i = epbp->vecnum-2;
if ( i==32 || i==33) return(-1);
if ( (30 <= i) && (i <= 37) ) i -= 20;
else if ( (i < 0) || (i > 9) ) return(255);
epbp->oldvec = GBL.excvec[i];
GBL.excvec[i] = epbp->newvec;
return(0);
}
/*****************************
* get/set TPA entry point *
*****************************/
set_tpa(p)
/* Get/Set TPA Limits */
REG struct
{
UWORD parms;
BYTE *low;
BYTE *high;
} *p;
#define set 1
#define sticky 2
{
if (p->parms & set)
{
tpa_lt = p->low;
tpa_ht = p->high;
if (p->parms & sticky)
{
tpa_lp = tpa_lt;
tpa_hp = tpa_ht;
}
}
else
{
p->low = tpa_lt;
p->high = tpa_ht;
}
}

View File

@@ -0,0 +1,314 @@
/****************************************************************
* *
* CP/M-68K BDOS Disk Read/Write Module *
* *
* This module contains functions to perform sequential *
* or random access read or write to the disk for CP/M-68K *
* *
* It includes the following external functions: *
* *
* bdosrw() - sequential and random disk I/O *
* *
* *
* Compiled with Alcyon C on the VAX *
* *
****************************************************************/
#include "bdosinc.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
/* External function definitions */
EXTERN UWORD rdwrt(); /* disk read/write routine */
EXTERN WORD getaloc(); /* allocate a block of disk space */
EXTERN WORD swap(); /* assembly language byte swapper */
EXTERN UWORD dirscan(); /* directory scanning routine */
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
EXTERN UWORD close_fi(); /* close file function */
EXTERN BOOLEAN create(); /* create file function passed to dirscan */
EXTERN UWORD ro_err(); /* read-only file error handler */
/* External variable definitions */
EXTERN UWORD ro_dsk; /* read-only disk vector */
/**********************************************************/
/* First, some utility functions used by seqio and ranio */
/**********************************************************/
/******************************
* FCB block number routines *
******************************/
WORD blkindx(fcbp)
/* return index into fcb disk map */
REG struct fcb *fcbp; /* pointer to fcb */
{
REG struct dpb *dparmp; /* pointer to disk parameter block */
REG WORD i;
REG WORD blkshf;
BSETUP
dparmp = GBL.parmp;
blkshf = dparmp->bsh;
i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
}
UWORD blknum(fcbp, index, wrdfcb)
/* return block number in fcb indicated by index */
REG struct fcb *fcbp; /* pointer to fcb */
REG WORD index; /* index into disk map of fcb */
WORD wrdfcb; /* boolean, fcb disk map of words */
{
if (wrdfcb)
return( swap(fcbp->dskmap.big[index]) );
else return( UBWORD(fcbp->dskmap.small[index]) );
}
setblk(fcbp, index, wrdfcb, block)
/* put block number into fcb */
REG struct fcb *fcbp; /* pointer to fcb */
REG WORD index; /* index into disk map of fcb */
WORD wrdfcb; /* boolean, fcb disk map of words */
REG UWORD block; /* block number */
{
fcbp->s2 &= 0x7f; /* set file write flag */
if (wrdfcb)
fcbp->dskmap.big[index] = swap(block);
else fcbp->dskmap.small[index] = (UBYTE)block;
}
/***************************
* disk read/write routine *
***************************/
UWORD do_io(block, rcrd, parm)
UWORD block; /* block number */
UBYTE rcrd; /* record number */
REG WORD parm; /* write parameter */
{
REG LONG lsec;
REG struct dpb *dparmp;
BSETUP
dparmp = GBL.parmp; /* init dpb pointer */
lsec = ((LONG)block << (dparmp->bsh)) +
(LONG)(rcrd & (dparmp->blm));
return( rdwrt(lsec, GBL.dmaadr, parm) );
}
/*******************************************
* routine for crossing extent boundaries *
*******************************************/
WORD new_ext(fcbp, reading, ran)
/* If sequential I/O, open the next extent */
/* If random I/O, compute new extent from random record field */
REG struct fcb *fcbp; /* pointer to fcb */
BOOLEAN reading; /* read/write flag */
WORD ran; /* random I/O flag */
{
REG UBYTE mod; /* module number */
REG UBYTE ext; /* extent number */
REG UBYTE t_mod; /* temp mod number */
REG UBYTE t_ext; /* temp extent */
BSETUP
if (ran)
{
mod = ( (fcbp->ran0) << 4) | ( (fcbp->ran1) >> 4);
ext = ( ((fcbp->ran1) & 0x0f) << 1);
if ((fcbp->ran2) & 0x80) ext |= 1;
/* the calculation of ext was coded this way because of a */
/* compiler bug from Alcyon */
}
else
{
mod = (fcbp->s2) & 0x3f;
ext = (fcbp->extent) + 1; /* for sequential, incr extent */
}
if (ext >= 32)
{
ext = 0;
mod += 1;
}
if (mod >= 64) return(6); /* past maximum file size */
if ( mod == ((fcbp->s2) & 0x3f) )
if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
{ /* we're in same logical extent */
fcbp->extent = ext;
return(0);
}
/* Extent or Module numbers don't match */
/* Close the old extent and open a one */
if ( close_fi(fcbp) >= 255 ) return(3);
/* can't close old extent */
t_mod = fcbp->s2;
t_ext = fcbp->extent;
fcbp->s2 = mod;
fcbp->extent = ext;
if ( dirscan(openfile, fcbp, 0) >= 255 ) /* open extent */
{
if (reading)
{ /* reading unwritten extent */
fcbp->s2 = t_mod;
fcbp->extent = t_ext;
return(4);
}
if ( dirscan(create, fcbp, 8) >= 255 )
return(5); /* can't create new extent */
}
return(0);
}
/************************************
* Routine to calculate the maximum *
* extent number of an FCB in a *
* extent-folded environment *
************************************/
UWORD calcext(fcbp)
REG struct fcb *fcbp;
{
REG UWORD i;
REG BYTE *p;
BSETUP
i = 15;
p = &(fcbp->dskmap.small[16]);
do
{
if (*--p) break;
i -= 1;
} while (i);
/* Now i contains the index of the last non-zero block in the FCB */
if ((GBL.parmp)->dsm > 255) i >>= 1;
i >>= 7 - ((GBL.parmp)->bsh);
return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
}
/*********************************
* Routine to get the actual *
* record count of the currently *
* active logical extent of a FCB *
*********************************/
UWORD get_rc(fcbp)
REG struct fcb *fcbp;
{
REG UWORD ext;
ext = calcext(fcbp); /* find last active extent in fcb */
if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
/* if this is the last active fcb, return fcb's rc */
else if (ext > fcbp->extent) return(128);
/* if the fcb has more extents past this one, then */
/* the current one is logically full */
else return (0);
/* if we seeked past the last active extent, rc = 0 */
}
/************************
* bdosrw entry point *
************************/
UWORD bdosrw(fcbp, reading, random)
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
REG BOOLEAN reading; /* boolean to tell whether to read or write */
WORD random; /* 0 = sequential, 1 = random (normal), */
/* 2 = random with zero fill */
{
REG UWORD block; /* block number from fcb */
REG WORD index; /* index into disk map of fcb */
REG BYTE *old_dma; /* temp holding spot for dmaadr */
REG WORD parm; /* parameter to do-io */
REG WORD bigfile; /* file system is in word mode */
REG UWORD rtn; /* return parameter */
REG UBYTE rc; /* temp storage for rcdcnt */
BSETUP
bigfile = ((GBL.parmp)->dsm) & ~0xff;
if ( ( ! reading) && (fcbp->ftype[robit] & 0x80) )
ro_err(fcbp,((GBL.dpbp)->dpbp)->drm);
/* check for read-only file */
if (random)
{
if ( rtn = new_ext(fcbp, reading, TRUE) ) return(rtn);
/* open new extent if necessary, return if error */
fcbp->cur_rec = (fcbp->ran2) & 0x7f;
}
else /* sequential */
if (fcbp->cur_rec == 128)
{ /* time to try next extent */
if ( new_ext(fcbp, reading, FALSE) )
return(1); /* if can't open new extent, error */
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
}
/* record is now in active fcb */
rc = fcbp->rcdcnt;
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
{
if (reading) return(1); /* reading unwritten data */
fcbp->s2 &= 0x7f; /* set file write flag */
rc = fcbp->cur_rec + 1;
}
index = blkindx(fcbp); /* get index into fcb disk map */
block = blknum(fcbp, index, bigfile);
if (block) parm = (reading ? 0 : 1);
else /* if allocated block, parm is just read or write */
{ /* unallocated block */
if (reading) return(1); /* reading unwritten data */
/* Writing to new block */
/* The parm passed to getaloc is the previously allocated block */
/* or 0, if the previous block is not allocated */
block = getaloc(blknum(fcbp, (index ? (index - 1) : 0), bigfile));
if (block == ~0) return(2); /* out of space */
setblk(fcbp, index, bigfile, block);
parm = 3;
if (random == 2)
{ /* Write random with zero fill */
old_dma = GBL.dmaadr;
GBL.dmaadr = GBL.dirbufp; /* Do DMA from dir_buf */
index = SECLEN;
do GBL.dmaadr[--index] = 0;
while (index); /* zero the dma buffer */
for (index = 0; index <= ((GBL.parmp)->blm); index++)
{
do_io(block, (UBYTE)index, parm);
/* write zeros to the block */
parm = 1; /* next write is not to new block */
}
GBL.dmaadr = old_dma; /* restore dma address */
}
}
rtn = do_io(block, fcbp->cur_rec, parm);
if ( rtn == 0 )
{
fcbp->rcdcnt = rc;
if ( ! random ) fcbp->cur_rec += 1;
}
return(rtn);
}

View File

@@ -0,0 +1,46 @@
/********************************************************
* *
* BIOS definitions for CP/M-68K *
* *
* Copyright (c) 1982 Digital Research, Inc. *
* *
* This include file simply defines the BIOS calls *
* *
********************************************************/
EXTERN UBYTE bios1(); /* used for character I/O functions */
EXTERN bios2(); /* parm1 is word, no return value */
EXTERN bios3(); /* used for set dma only */
/* parm1 is a pointer, no return */
EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
/* words, returns a pointer to dph */
EXTERN UWORD bios5(); /* for sectran and set exception */
EXTERN BYTE *bios6(); /* for get memory segment table */
#define bwboot() bios1(1) /* warm boot */
#define bconstat() bios1(2) /* console status */
#define bconin() bios1(3) /* console input */
#define bconout(parm) bios2(4,parm) /* console output parm */
#define blstout(parm) bios2(5,parm) /* list device output */
#define bpun(parm) bios2(6,parm) /* punch char output */
#define brdr() bios1(7) /* reader input */
#define bhome() bios1(8) /* recalibrate drive */
#define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
/* select disk and return info */
#define bsettrk(parm) bios2(10,parm) /* set track on disk */
#define bsetsec(parm) bios2(11,parm) /* set sector for disk */
#define bsetdma(parm) bios3(12,parm) /* set dma address */
#define bread() bios1(13) /* read sector from disk */
#define bwrite(parm) bios2(14,parm) /* write sector to disk */
#define blistst() bios1(15) /* list device status */
#define bsectrn(parm1,parm2) bios5(16,parm1,parm2)
/* sector translate */
#define bgetseg() bios6(18) /* get memory segment tbl */
#define bgetiob() bios1(19) /* get I/O byte */
#define bsetiob(parm) bios2(20,parm) /* set I/O byte */
#define bflush() bios1(21) /* flush buffers */
#define bsetvec(parm1,parm2) bios5(22,parm1,parm2)
/* set exception vector */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
*************************************************************************
* *
* INTERFACE MODULE BETWEEN *
* CCP and THE BDOS *
* *
* *
* THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM *
* ================================================== *
* *
* (C) Copyright Digital Research 1983 all rights reserved *
* *
*************************************************************************
.globl _bdos
_bdos: move.w 4(sp),d0
move.l 6(sp),d1
trap #2
rts

View File

@@ -0,0 +1,158 @@
/*--------------------------------------------------------------*\
| ccp_def.c DEFINES v1.0 |
| ======= |
| |
| CP/M 68k: A CP/M derived operating system |
| |
| File contents: |
| ------------- |
| This file contains all of the #defines |
| used by the console command processor. |
| |
| created by : Tom Saulpaugh Date: 7/13/82 |
| ---------- |
| last modified: 10/29/82 |
| ------------- |
| |
| (c) COPYRIGHT Digital Research 1982 |
| all rights reserved |
| |
\*--------------------------------------------------------------*/
/*-------------------------------------------*\
| CP/M Transient Commands |
\*-------------------------------------------*/
#define DIRCMD 0
#define TYPECMD 1
#define RENCMD 2
#define ERACMD 3
#define UCMD 4
#define CH_DISK 5
#define SUBCMD 6
#define SUB_FILE 7
#define FILE 8
#define DIRSCMD 9
#define SEARCH 10
/*-------------------------------------------*\
| Modes and Flags |
\*-------------------------------------------*/
#define ON 1
#define OFF 0
#define MATCH 0
#define GOOD 1
#define BAD 0
#define FILL 1
#define NOFILL 0
#define VOID /*no return value*/
#define NO_FILE 98
#define STOP 99
#define USER_ZERO 0
#define DISK_A 1
#define SOURCEDRIVE 88
#define DESTDRIVE 99
#define BYTE char
#define REG register
#define WORD signed short
#define UWORD unsigned int
#define LONG signed long
#define ULONG unsigned long
#define GET_MEM_REG 18
#define ZERO 0
#define NULL '\0'
#define TRUE 1
#define FALSE 0
#define NO_READ 255
#define BLANK ' '
#define BACKSLH '\\'
#define EXLIMPT '!'
#define CMASK 0177
#define ONE (long)49
#define TAB 9
#define Cr 13
#define Lf 10
#define CR (long)13
#define LF (long)10
#define EOF 26
#define BLANKS (long)32
#define PERIOD (long)46
#define COLON (long)58
#define ARROW (long)62
/*-------------------------------------------*\
| Data Structure Size Constants |
\*-------------------------------------------*/
#define CMD_LEN 128
#define BIG_CMD_LEN 255
#define MAX_ARGS 4
#define ARG_LEN 26
#define NO_OF_DRIVES 16
#define NUMDELS 16
#define FCB_LEN 36
#define DMA_LEN 128
#define FILES_PER_LINE 5
#define SCR_HEIGHT 23
#define BIG_WIDTH 80
#define SMALL_WIDTH 40
/*-------------------------------------------*\
| BDOS Function Calls |
\*-------------------------------------------*/
#define WARMBOOT 0
#define CONIN 1
#define CONSOLE_OUTPUT 2
#define READER_INPUT 3
#define PUNCH_OUTPUT 4
#define LIST_OUTPUT 5
#define DIR_CONS_I/O 6
#define GET_I/O_BYTE 7
#define SET_I/O_BYTE 8
#define PRINT_STRING 9
#define READ_CONS_BUF 10
#define GET_CONS_STAT 11
#define RET_VERSION_NO 12
#define RESET_DISK_SYS 13
#define SELECT_DISK 14
#define OPEN_FILE 15
#define CLOSE_FILE 16
#define SEARCH_FIRST 17
#define SEARCH_NEXT 18
#define DELETE_FILE 19
#define READ_SEQ 20
#define WRITE_SEQ 21
#define MAKE_FILE 22
#define RENAME_FILE 23
#define RET_LOGIN_VEC 24
#define RET_CUR_DISK 25
#define SET_DMA_ADDR 26
#define GET_ADDR(ALLOC) 27
#define WRITE_PROT_DISK 28
#define GET_READ/O_VEC 29
#define SET_FILE_ATTRIB 30
#define GET_ADDR_D_PARM 31
#define GET_USER_NO 32
#define READ_RANDOM 33
#define WRITE_RANDOM 34
#define COMP_FILE-SIZE 35
#define SET_RANDOM_REC 36
#define RESET_DRIVE 37
#define WRITE_RAN_ZERO 40
#define BIOS_CALL 50
#define LOAD_PROGRAM 59
/*----------------------------------------------*\
| MACROS |
\*----------------------------------------------*/
#define isalpha(c) (islower(c) || isupper(c))
#define islower(c) ('a' <= (c) && (c) <= 'z')
#define isupper(c) ('A' <= (c) && (c) <= 'Z')
#define tolower(c) (isupper(c) ? ((c)+040):(c))
#define toupper(c) (islower(c) ? ((c)-040):(c))
#define isdigit(c) ('0' <= (c) && (c) <= '9')

View File

@@ -0,0 +1,113 @@
*************************************************************************
* *
* CPM68K INTERFACE MODULE FOR *
* THE CONSOLE COMMAND PROCESSOR *
* *
* THIS IS THE DUAL-PROCESSOR,ROMABLE CP/M-68K SYSTEM *
* ================================================== *
* *
* (C) Copyright Digital Research 1983 all rights reserved *
* *
*************************************************************************
.globl _bios1
.globl _bdos
.globl _load68k
.globl _load_tbl
.globl init_tbl
.globl _load_try
.globl _autorom
.globl flags
.globl TPAB
.globl stack
.globl _bdosini
.globl _main
.globl _submit
.globl _morecmds
.globl _autost
.globl _usercmd
.globl _init
.globl _ccp
.globl _patch
.globl cpm
.text
cpm:
jmp.l ccpstart * start ccp with possible initial command
jmp.l ccpclear * clear auto start flag
.bss
_autost: .ds.b 1 * autostart command flag
_usercmd: .ds.b 130 * user command buffer
.text
copy: .dc.b 'COPYRIGHT (C) 1982, Digital Research '
.text
ccpclear:
clr.b _autost * clear the autostart flag
ccpstart:
lea stack,sp * set up the stack pointer
clr.b _autost * clear the auto start flag
jsr _init * call bios init
move.w d0,dskuser * save user # & disk
*
*
* ROM SYSTEM INITIALIZATION
* OF BSS VARIABLES
*
*
clr.b _load_try
clr.b _submit
clr.b _morecmds
move.b #$1,_autorom
clr.w flags
clr.w TPAB
jsr init_tbl
jsr _bdosini * do bdos init
move.w #32,d0 * get user bdos func #
clr.l d1 * clear out d1
move.b dskuser,d1 * get the user #
trap #2 * set the user number
clr.l d0 * clear d0
move.w #14,d0 * select function
clr.l d1 * clear d1
move.w dskuser,d1 * get disk to be selected
andi #$0ff,d1 * mask off the user #
trap #2 * select the disk
_ccp:
lea stack,sp * set up the stack pointer
jsr _main * call the CCP
bra _ccp
.bss
.even
dskuser: .ds.w 1
.even
_submit: .ds.b 1
.even
_morecmds: .ds.b 1
.even
_patch .ds.l 25
.end

View File

@@ -0,0 +1,188 @@
*****************************************************************
* *
* COMMAND FILE LOADER FOR CPM68K *
* ============================== *
* *
* (c) COPYRIGHT Digital Research 1983 *
* all rights reserved *
* *
* THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM *
* ================================================== *
* *
* Description: *
* ----------- The command file loader is envoked by *
* the CCP after the CCP has successfully *
* opened that file. The loader must *
* call the BDOS to obtain the boundries *
* of the TPA. The load parameter block *
* defined in this loader holds all the *
* memory size and location details. *
* Next the loader returns the system to *
* its original user #. The CCP might *
* have switched to user zero during its *
* search for the file. Next the default *
* dma address is set for the loaded *
* program. Next the command tail is *
* placed,along with the first two parsed *
* fcb's,into the user basepage. *
* Lastly the user stack pointer is set up *
* and the return address is put on the *
* user stack. An RTE transferes control. *
* If a load was not successfull, the *
* appropriate error message is printed. *
* *
* Created by: Tom Saulpaugh *
* *
* Last Modified: 3/02/83 *
* *
*****************************************************************
.globl _load68k * make this procedure public
.globl _user * global user # before load occured
.globl _cmdfcb * parsed fcb
.globl _tail * global pointer to command tail
.globl _fill_fcb * procedure to fill fcb's
.globl flags * ROM SYSTEM INITIALIZATION
.globl TPAB * ROM SYSTEM INITIALIZATION
reboot = 0
printstr = 9
setdma = 26
chuser = 32
pgmldf = 59
gettpa = 63
_load68k:
*
* Load the 68k file into the TPA
* ------------------------------
*
.text
move.l #TPAB,d1 * move in address of tpa parameter block
move.w #gettpa,d0 * get function number
trap #2 * get the tpa limits
move.l low,lowadr * put it in the lpb
move.l high,hiadr * put high tpa addr in lpb
move.l #_cmdfcb,LPB * get address of opened fcb
move.l #pgmldf,d0 * move in bdos function no
move.l #LPB,d1 * d1 points to load block
trap #2 * do the program load
tst d0 * was the load successful?
bne lderr * if not print error message and return
*
* return to original user #
* -------------------------
move.w _user,d1 * put user # to switch to in d1
move.l #chuser,d0 * put bdos func # in d0
trap #2 * do the user # change
*
* set the default dma address
* ---------------------------
clr.l d1 * clear d1 register
move.l baspag,d1 * d1 points to user base page
add #$80,d1 * d1 points to default dma in base page
movea.l d1,a1 * save it for later use
move #setdma,d0 * move in bdos function no
trap #2 * set the default dma address
*
* move in the command tail
* ------------------------
move.l a1,a2 * save a pointer to the count field
add.l #$01,a1 * point past count field
move.l _tail,a0 * point to command tail
clr.l d0 * clear out d0
mvtail: cmpi.b #$00,(a0) * check for a NULL ending byte
beq done * NULL byte terminates command
cmpi.b #$21,(a0) * check for an '!'
beq done * '!' ends the command
move.b (a0)+,(a1)+ * move a byte of the command tail
addq #1,d0 * bump up the character count
bra mvtail * continue byte move
done: move.b d0,(a2) * put in the character count
move.b #$00,(a1) * terminate cmd tail with a NULL byte
*
* fill fcb1 & fcb2
* ----------------
move.l #_cmdfcb,-(sp) * put address of fcb buffer onto stack
move.w #1,-(sp) * put 1 on stack(parm1)
jsr _fill_fcb * jump to 'C' code & fill cmdfcb with parm1
add.l #6,sp * clean off the stack
clr.l d0 * clear register d0
moveq #$5c,d0 * put basepage address of fcb1 in d0
bsr movfcb * put fcb1 in the basepage
move.l #_cmdfcb,-(sp) * put address of fcb buffer onto stack
move.w #2,-(sp) * put 2 on stack(parm2)
jsr _fill_fcb * jump to 'C' code & fill cmdfcb with parm2
add.l #6,sp * clean off the stack
clr.l d0 * clear register d0
moveq #$38,d0 * put basepage address of fcb1 in d0
bsr movfcb * put fcb2 in the basepage
*
* now push rte stuff on stack
* ---------------------------
movea.l usrstk,a0 * get user stack pointer
move.l baspag,a1 * get basepage address
move.l 8(a1),-(sp) * push address we want to jump to
move sr,d0 * get the status register in d0
andi #$5f00,d0 * mask trace,system bits,user flags
move.w d0,-(sp) * push it on stack
move.l a1,-(a0) * push addr of basepage onto user stack
move.l #cmdrtn,-(a0) * push return address onto user stack
move.l a0,usp * set up user stack pointer
rte
*
* load error
* ----------
lderr:
rts * return with error code in d0
cmdrtn:
move #reboot,d0 * reboot CPM
trap #2
movfcb:
add.l baspag,d0 * get offset into basepage
move.l d0,a0 * move address into a0
move.l #_cmdfcb,a1 * a1 points to fcb to be moved
clr.l d0 * clear register d0
moveq #35,d0 * get length of fcb
mov1:
move.b (a1)+,(a0)+ * move a byte into the basepage
dbf d0,mov1 * if not done branch to mov1
rts
.bss
.even
*
* LOAD PARAMETER BLOCK
*
LPB: .ds.l 1
lowadr: .ds.l 1
hiadr: .ds.l 1
baspag: .ds.l 1
usrstk: .ds.l 1
flags: .ds.w 1
*
* TPA Parameter Block
*
.even
TPAB: .ds.w 1
low: .ds.l 1
high: .ds.l 1
.end

View File

@@ -0,0 +1,346 @@
/********************************************************
* *
* CP/M-68K BDOS Character I/O Routines *
* *
* This module does BDOS functions 1 thru 11 *
* *
* It contains the following functions which *
* are called from the BDOS main routine: *
* constat(); *
* conin(); *
* tabout(); *
* rawconio(); *
* prt_line(); *
* readline(); *
* *
* Copyright (c) 1982 Digital Research, Inc. *
* *
********************************************************/
#include "bdosinc.h"
#include "bdosdef.h"
#include "biosdef.h"
#define ctrlc 0x03
#define ctrle 0x05
#define ctrlp 0x10
#define ctrlq 0x11
#define ctrlr 0x12
#define ctrls 0x13
#define ctrlu 0x15
#define ctrlx 0x18
#define cr 0x0d
#define lf 0x0a
#define tab 0x09
#define rub 0x7f
#define bs 0x08
#define space 0x20
EXTERN warmboot(); /* External function definition */
/******************/
/* console status */
/******************/
BOOLEAN constat()
{
BSETUP
return( GBL.kbchar ? TRUE : bconstat() );
}
/********************/
/* check for ctrl/s */
/* used internally */
/********************/
conbrk()
{
REG UBYTE ch;
REG BOOLEAN stop;
BSETUP
stop = FALSE;
if ( bconstat() ) do
{
if ( (ch = bconin()) == ctrlc ) warmboot(1);
if ( ch == ctrls ) stop = TRUE;
else if (ch == ctrlq) stop = FALSE;
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
else /* Insert character in ring buffer */
{ /* */
if(GBL.kbchar < TBUFSIZ) /* Room? */
{ /************************************/
*GBL.insptr++ = ch; /* Yes, insert the character in buff*/
GBL.kbchar++; /* Up count */
} /************************************/
} /* Note if no room, character is */
/* Ignomiously discarded (!) */
/************************************/
} while (stop);
}
/******************/
/* console output */
/* used internally*/
/******************/
conout(ch)
REG UBYTE ch;
{
BSETUP
conbrk(); /* check for control-s break */
bconout(ch); /* output character to console */
if (GBL.lstecho) blstout(ch); /* if ctrl-p on, echo to list dev */
if (ch >= ' ') GBL.column++; /* keep track of screen column */
else if (ch == cr) GBL.column = 0;
else if (ch == bs) GBL.column--;
}
/*************************************/
/* console output with tab expansion */
/*************************************/
tabout(ch)
REG UBYTE ch; /* character to output to console */
{
BSETUP
if (ch == tab) do
conout(' ');
while (GBL.column & 7);
else conout(ch);
}
/*******************************/
/* console output with tab and */
/* control character expansion */
/*******************************/
cookdout(ch)
REG UBYTE ch; /* character to output to console */
{
if (ch == tab) tabout(ch); /* if tab, expand it */
else
{
if ( (UWORD)ch < (UWORD)' ' )
{
conout( '^' );
ch |= 0x40;
}
conout(ch); /* output the character */
}
}
/*****************/
/* console input */
/*****************/
UBYTE getch() /* Get char from buffer or bios */
/* For internal use only */
{
REG UBYTE temp;
BSETUP
if(GBL.kbchar)
{
temp = *GBL.remptr++; /* Fetch the character */
GBL.kbchar--; /* Decrement the count */
if(!GBL.kbchar) /* Gone to zero? */
GBL.remptr = GBL.insptr = &(GBL.t_buff[0]);
return(temp);
}
return( bconin() ); /* else get char from bios */
}
UBYTE conin() /* BDOS console input function */
{
REG UBYTE ch;
BSETUP
conout( ch = getch() );
if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
return(ch);
}
/******************
* raw console i/o *
******************/
UBYTE rawconio(parm) /* BDOS raw console I/O function */
REG UWORD parm;
{
BSETUP
if (parm == 0xff) return(getch());
else if (parm == 0xfe) return(constat());
else bconout(parm & 0xff);
}
/****************************************************/
/* print line up to delimiter($) with tab expansion */
/****************************************************/
prt_line(p)
REG UBYTE *p;
{
BSETUP
while( *p != GBL.delim ) tabout( *p++ );
}
/**********************************************/
/* read line with editing and bounds checking */
/**********************************************/
/* Two subroutines first */
newline(startcol)
REG UWORD startcol;
{
BSETUP
conout(cr); /* go to new line */
conout(lf);
while(startcol)
{
conout(' ');
startcol -= 1; /* start output at starting column */
}
}
backsp(bufp, col)
/* backspace one character position */
REG struct conbuf *bufp; /* pointer to console buffer */
REG WORD col; /* starting console column */
{
REG UBYTE ch; /* current character */
REG WORD i;
REG UBYTE *p; /* character pointer */
BSETUP
if (bufp->retlen) --(bufp->retlen);
/* if buffer non-empty, decrease it by 1 */
i = UBWORD(bufp->retlen); /* get new character count */
p = &(bufp->cbuf[0]); /* point to character buffer */
while (i--) /* calculate column position */
{ /* across entire char buffer */
ch = *p++; /* get next char */
if ( ch == tab )
{
col += 8;
col &= ~7; /* for tab, go to multiple of 8 */
}
else if ( (UWORD)ch < (UWORD)' ' ) col += 2;
/* control chars put out 2 printable chars */
else col += 1;
}
while (GBL.column > col)
{
conout(bs); /* backspace until we get to proper column */
conout(' ');
conout(bs);
}
}
readline(p) /* BDOS function 10 */
REG struct conbuf *p;
{
REG UBYTE ch;
REG UWORD i;
REG UWORD j;
REG UBYTE *q;
UWORD stcol;
BSETUP
stcol = GBL.column; /* set up starting column */
if (GBL.chainp != NULL) /* chain to program code */
{
i = UBWORD(*(GBL.chainp++));
j = UBWORD(p->maxlen);
if (j < i) i = j; /* don't overflow console buffer! */
p->retlen = (UBYTE)i;
q = p->cbuf;
while (i)
{
cookdout( *q++ = *(GBL.chainp++) );
i -= 1;
}
GBL.chainp = NULL;
return;
}
p->retlen = 0; /* start out with empty buffer */
while ( UBWORD(p->retlen) < UBWORD(p->maxlen) )
{ /* main loop for read console buffer */
if ( ((ch=getch()) == ctrlc) && !(p->retlen) )
{
cookdout(ctrlc);
warmboot(1);
}
else if ( (ch == cr) || (ch == lf) )
{ /* if cr or lf, exit */
conout(cr);
break;
}
else if (ch == bs) backsp(p, stcol); /* backspace */
else if (ch == rub) /* delete character */
{
if (GBL.echodel)
{
if (p->retlen)
{
i = UBWORD(--(p->retlen));
conout( p->cbuf[i] );
}
}
else backsp(p, stcol);
}
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
/* control-p */
else if (ch == ctrlx) /* control-x */
do backsp(p,stcol); while (p->retlen);
else if (ch == ctrle) newline(stcol); /* control-e */
else if (ch == ctrlu) /* control-u */
{
conout('#');
newline(stcol);
p->retlen = 0;
}
else if (ch == ctrlr) /* control-r */
{
conout('#');
newline(stcol);
for (i=0; i < UBWORD(p->retlen); i++)
cookdout( p->cbuf[i] );
}
else /* normal character */
cookdout( p->cbuf[UBWORD((p->retlen)++)] = ch );
}
}

View File

@@ -0,0 +1,41 @@
The following is a list of the modules that form the BDOS for the
C language version of CP/M-68K:
SOURCE FILES
bdosif.s - assembly language interface, trap handler,
BIOS caller, function 62 (set supervisor)
conbdos.c - BDOS functions 1 thru 11 (console functions)
bdosmisc.c - BDOS initialization, warmboot, error handler, set exception,
(used for miscellaneous BDOS routines)
dskutil.c - bit map handlers, directory read & write, dirscan
(miscellaneous disk handling utilities)
fileio.c - all file handling calls except read & write
includes open, close, delete, rename, etc.
bdosrw.c - sequential and random read & write
bdosmain.c - the BDOS case statement, global variable declarations
iosys.c - packet I/O to BIOS interface
pgmld.s - program load (function 59)
exceptn.s - exception handler
INCLUDE FILES
bdosinc.h - standard i/o stuff, universal declarations
bdosdef.h - BDOS data structure declarations
biosdef.h - procedure declarations to interface to BIOS
pktio.h - definition of data structure for packet I/O

View File

@@ -0,0 +1,31 @@
e:vax BDOSDEF.H r
e:vax BDOSIF.S r
e:vax BDOSINC.H r
e:vax BDOSMAIN.C r
e:vax BDOSMISC.C r
e:vax BDOSRW.C r
e:vax BIOSDEF.H r
e:vax CCP.C r
e:vax CCPBDOS.S r
e:vax CCPDEF.H r
e:vax CCPIF.S r
e:vax CCPLOAD.S r
e:vax CONBDOS.C r
e:vax CPMC.DOC r
e:vax CPMLIB. r
e:vax DOWN.SUB r
e:vax DOWN2.SUB r
e:vax DSKUTIL.C r
e:vax EXCEPTN.S r
e:vax FILEIO.C r
e:vax FILETYPS.S r
e:vax IOSYS.C r
e:vax MAKE.SUB r
e:vax PGMLD.S r
e:vax PKTIO.H r
e:vax REAR.SUB r
e:vax SEND2.SUB r
e:vax STACK.S r
e:vax UP2.SUB r
e:vax VMAKE.COM r
e:vax VSEND.COM r

View File

@@ -0,0 +1,36 @@
Directory _DRB0:[STEVE.CPM68K.V102.BDOS]
BDOSDEF.H;3
BDOSIF.S;1
BDOSINC.H;1
BDOSMAIN.C;1
BDOSMISC.C;2
BDOSRW.C;1
BIOSDEF.H;1
CCP.C;2
CCPBDOS.S;1
CCPDEF.H;1
CCPIF.S;1
CCPLOAD.S;1
CONBDOS.C;3
CPMC.DOC;1
CPMLIB.;1
DOWN.SUB;1
DOWN2.SUB;2
DSKUTIL.C;1
EXCEPTN.S;1
FILEIO.C;1
FILETYPS.S;1
IOSYS.C;1
MAKE.SUB;5
PGMLD.S;1
PKTIO.H;1
REAR.SUB;4
SEND2.SUB;1
STACK.S;1
UP2.SUB;1
VMAKE.COM;3
VSEND.COM;3
Total of 31 files.

View File

@@ -0,0 +1,26 @@
vax REAR.SUB r
vax MAKE.SUB r
vax BDOSDEF.H r
vax BDOSIF.S r
vax BDOSINC.H r
vax BDOSMAIN.C r
vax BDOSMISC.C r
vax BDOSRW.C r
vax BIOSDEF.H r
vax CONBDOS.C r
vax CPMC.DOC r
vax DSKUTIL.C r
vax EXCEPTN.S r
vax FILEIO.C r
vax IOSYS.C r
vax PGMLD.S r
vax PKTIO.H r
vax CCP.C r
vax CCPBDOS.S r
vax CCPDEF.H r
vax CCPIF.S r
vax CCPLOAD.S r
vax FILETYPS.S r
vax STACK.S r
vax SEND2.SUB r
vax up2.sub r

View File

@@ -0,0 +1,297 @@
/****************************************************************
* *
* CP/M-68K BDOS Disk Utilities Module *
* *
* This module contains the miscellaneous utilities *
* for manipulating the disk in CP/M-68K. Included are: *
* *
* dirscan() - general purpose dir scanning *
* setaloc() - set bit in allocation vector *
* clraloc() - clear bit in allocation vector *
* getaloc() - get free allocation block *
* dchksum() - directory checksum calculator *
* dir_rd() - read directory sector *
* dir_wr() - write directory sector *
* rdwrt() - read/write disk sector *
* *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "bdosinc.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "pktio.h" /* Packet I/O definitions */
/* declare external functions and variables */
EXTERN UWORD do_phio(); /* external physical disk I/O routine */
EXTERN UWORD error(); /* external error routine */
EXTERN UWORD log_dsk; /* logged-on disk vector */
EXTERN UWORD ro_dsk; /* read-only disk vector */
EXTERN UWORD crit_dsk; /* critical disk vector */
/**********************
* read/write routine *
**********************/
UWORD rdwrt(secnum, dma, parm)
/* General disk sector read/write routine */
/* It simply sets up a I/O packet and sends it to do_phio */
LONG secnum; /* logical sector number to read/write */
UBYTE *dma; /* dma address */
REG WORD parm; /* 0 for read, write parm + 1 for write */
{
struct iopb rwpkt;
BSETUP
rwpkt.devnum = GBL.curdsk; /* disk to read/write */
if (parm)
{
rwpkt.iofcn = (BYTE)write; /* if parm non-zero, we're doing a write */
rwpkt.ioflags = (BYTE)(parm-1); /* pass write parm */
if ( ro_dsk & (1 << (rwpkt.devnum)) ) error(4);
/* don't write on read-only disk */
}
else
{
rwpkt.iofcn = (BYTE)read;
rwpkt.ioflags = (BYTE)0;
}
rwpkt.devadr = secnum; /* sector number */
rwpkt.xferadr = dma; /* dma address */
/* parameters that are currently not used by do_phio
rwpkt.devtype = disk;
rwpkt.xferlen = 1;
*/
rwpkt.infop = GBL.dphp; /* pass ptr to dph */
while ( do_phio(&rwpkt) )
if ( error( parm ? 1 : 0 ) ) break;
return(0);
}
/***************************
* directory read routine *
***************************/
UWORD dir_rd(secnum)
WORD secnum;
{
BSETUP
return( rdwrt((LONG)secnum, GBL.dirbufp, 0) );
}
/****************************
* directory write routine *
****************************/
UWORD dir_wr(secnum)
REG WORD secnum;
{
REG UWORD rtn;
BSETUP
rtn = rdwrt( (LONG)secnum, GBL.dirbufp, 2);
if ( secnum < (GBL.parmp)->cks )
*((GBL.dphp)->csv + secnum) = dchksum();
return(rtn);
}
/*******************************
* directory checksum routine *
*******************************/
UBYTE dchksum()
/* Compute checksum over one directory sector */
/* Note that this implementation is dependant on the representation */
/* of a LONG and is therefore not very portable. But it's fast */
{
REG LONG *p; /* local temp variables */
REG LONG lsum;
REG WORD i;
BSETUP
p = GBL.dirbufp; /* point to directory buffer */
lsum = 0;
i = SECLEN / (sizeof lsum);
do
{
lsum += *p++; /* add next 4 bytes of directory */
i -= 1;
} while (i);
lsum += (lsum >> 16);
lsum += (lsum >> 8);
return( (UBYTE)(lsum & 0xff) );
}
/************************
* dirscan entry point *
************************/
UWORD dirscan(funcp, fcbp, parms)
BOOLEAN (*funcp)(); /* funcp is a pointer to a Boolean function */
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
REG UWORD parms; /* parms is 16 bit set of bit parameters */
/* Parms & 1 = 0 to start at beginning of dir, 1 to continue from last */
/* Parms & 2 = 0 to stop when *funcp is true, 1 to go until end */
/* Parms & 4 = 0 to check the dir checksum, 1 to store new checksum */
/* Parms & 8 = 0 to stop at hiwater, 1 to go until end of directory */
#define continue 1
#define full 2
#define initckv 4
#define pasthw 8
{
REG UWORD i; /* loop counter */
REG struct dpb *dparmp; /* pointer to disk parm block */
REG UWORD dirsec; /* sector number we're working on */
REG UWORD rtn; /* return value */
REG UBYTE *p; /* scratch pointer */
REG UWORD bitvec; /* disk nmbr represented as a vector */
BSETUP
dparmp = GBL.parmp; /* init ptr to dpb */
rtn = 255; /* assume it doesn't work */
i = ( (parms & continue) ? GBL.srchpos + 1 : 0 );
while ( (parms & pasthw) || (i <= ((GBL.dphp)->hiwater + 1)) )
{ /* main directory scanning loop */
if ( i > dparmp->drm ) break;
if ( ! (i & 3) )
{ /* inside loop happens when we need to
read another directory sector */
retry: dirsec = i >> 2;
dir_rd(dirsec); /* read the directory sector */
if ( dirsec < (dparmp->cks) ) /* checksumming on this sector? */
{
p = ((GBL.dphp)->csv) + dirsec;
/* point to checksum vector byte */
if (parms & initckv) *p = dchksum();
else if (*p != dchksum())
{ /* checksum error! */
(GBL.dphp)->hiwater = dparmp->drm; /* reset hi water */
bitvec = 1 << (GBL.curdsk);
if (crit_dsk & bitvec) /* if disk in critical mode */
ro_dsk |= bitvec; /* then set it to r/o */
else
{
log_dsk &= ~bitvec; /* else log it off */
seldsk(GBL.curdsk); /* and re-select it */
goto retry; /* and re-do current op */
}
}
}
}
GBL.srchpos = i;
if ( (*funcp)(fcbp, (GBL.dirbufp) + (i&3), i) )
/* call function with parms of (1) fcb ptr,
(2) pointer to directory entry, and
(3) directory index */
{
if (parms & full) rtn = 0; /* found a match, but keep going */
else return(i & 3); /* return directory code */
}
i += 1;
}
return(rtn);
}
/****************************************
* Routines to manage allocation vector *
* setaloc() *
* clraloc() *
* getaloc() *
****************************************/
setaloc(bitnum)
/* Set bit in allocation vector */
REG UWORD bitnum;
{
BSETUP
if (bitnum >= 0 && bitnum <= (GBL.parmp)->dsm)
*((GBL.dphp)->alv + (bitnum>>3)) |= 0x80 >> (bitnum & 7);
}
clraloc(bitnum)
/* Clear bit in allocation vector */
REG UWORD bitnum;
{
BSETUP
if (bitnum > 0 && bitnum <= (GBL.parmp)->dsm)
*((GBL.dphp)->alv + (bitnum>>3)) &= ~(0x80 >> (bitnum & 7));
}
UWORD chkaloc(i)
/* Check bit i in allocation vector */
/* Return non-zero if block free, else return zero */
REG UWORD i;
{
BSETUP
return( ~(*( (GBL.dphp)->alv + (i >> 3) )) & (0x80 >> (i&7)) );
}
UWORD getaloc(leftblk)
/* Get a free block in the file system and set the bit in allocation vector */
/* It is passed the block number of the last block allocated to the file */
/* It tries to allocate the block closest to the block that was passed */
REG UWORD leftblk;
{
REG UWORD blk; /* block number to allocate */
REG UWORD rtblk; /* high block number to try */
REG UWORD diskmax; /* # bits in alv - 1 */
BSETUP
LOCK /* need to lock the file system while messing
with the allocation vector */
diskmax = (GBL.parmp)->dsm;
/* get disk max field from dpb */
rtblk = leftblk;
blk = ~0; /* -1 returned if no free block found */
while (leftblk || rtblk < diskmax)
{
if (leftblk)
if (chkaloc(--leftblk))
{
blk = leftblk;
break;
}
if (rtblk < diskmax)
if (chkaloc(++rtblk))
{
blk = rtblk;
break;
}
}
if (blk != ~0) setaloc(blk);
UNLOCK
return(blk);
}

View File

@@ -0,0 +1,291 @@
*************************************************
* *
* CP/M-68k Basic Disk Operating System *
* Exception Handling Module *
* *
* Version 0.0 -- July 21, 1982 *
* Version 0.1 -- July 25, 1982 *
* Version 0.2 -- October 6, 1982 *
* Version 0.3 -- December 21, 1982 *
* *
*************************************************
.globl _initexc
.globl _tpa_lp
.globl _tpa_hp
bgetseg = 18
bsetexc = 22
buserr = 2
spurious = 24
trap0 = 32
trap2 = 34
trap3 = 35
endvec = 48
_initexc:
* Initialize Exception Vector Handlers
* It has 1 passed parameter: the address of the exception vector array
move #bsetexc,d0
moveq #2,d1
move.l #exchndl,d2
init1:
movem.l d0-d2,-(sp)
trap #3 * BIOS call to set exception vector
movem.l (sp)+,d0-d2
init2: addq #1,d1
add.l #4,d2
cmpi #spurious,d1
bne init3
move #trap0,d1
init3: cmpi #trap2,d1
beq init2 * don't init trap 2 or trap 3
cmpi #trap3,d1
beq init2
cmpi #endvec,d1
blt init1
* initialize the exception vector array
moveq #bgetseg,d0
trap #3 * get the original TPA limits
movea.l d0,a0
tst.w (a0)+
move.l (a0)+,d1 * d1 = original low TPA limit
move.l d1,d2
add.l (a0),d2 * d2 = original high TPA limit
move.l _tpa_lp,d3 * d3 = new low TPA limit
move.l _tpa_hp,d4 * d4 = new high TPA limit
move #17,d0
movea.l 4(sp),a0
move.l a0,evec_adr * save exception vector address
init4:
cmp.l (a0),d1
bhi do_init * if old exception outside orig TPA, clear it
cmp.l (a0),d2
bls do_init
* current exception array entry is in original TPA
cmp.l (a0),d3
bhi dontinit * if old exception in old TPA but outside new
cmp.l (a0),d4 * TPA, don't clear it
bls dontinit
do_init:
clr.l (a0)
dontinit:
tst.l (a0)+
dbf d0,init4
rts
exchndl:
bsr.w except
excrtn0:
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
except:
clr.w -(sp)
movem.l a0/d0,-(sp) * 10 words now on stack in following order:
* _______________________________
* |____________D0.L_______________|
* |____________A0.L_______________|
* |____0000______|________________
* |_______Handler Return__________|
* If bus error, extra 2 longs are here
* ______________
* |__Status Reg__|________________
* |_____Exception Return__________|
move.l 10(sp),d0 * get return address from above array
sub.l #excrtn0,d0 * d0 now has 4 * (encoded excptn nmbr), where
* encoded excptn nmbr is in [0..21,22..37]
* representing [2..23,32..47]
cmpi #36,d0 * if d0/4 is in [0..9,22..29] then
ble chkredir * the exception may be redirected
cmpi #88,d0
blt dfltexc
cmpi #116,d0
bgt dfltexc
* in range of redirected exceptions
subi #48,d0 * subtract 4*12 to normalize [0..9,22..29]
* into [0..9,10..17]
chkredir:
movea.l evec_adr,a0
adda d0,a0 * index into exception vector array
tst.l (a0) * if 00000000, then not redirected
bne usrexc
* not redirected, do default handler
cmpi #40,d0
blt dfltexc
addi #48,d0 * add 4*12 that was sub'd above
dfltexc:
adda #14,sp * throw away 7 words that we added to stack
asr #2,d0 * divide d0 by 4
* now d0 is in [0..21,22..37]
* to represent [2..23,32..47]
cmpi #2,d0 * bus or address error?
bge nobusexc
movem.l (sp)+,a0-a1 * if yes, throw away 4 words from stack
nobusexc:
tst.w (sp)+ * throw away stacked SR
addi #2,d0
cmpi #23,d0 * get back real excptn nmbr in [2..23,32..47]
ble lowexc
addi #8,d0
lowexc: move d0,-(sp) * save excptn nmbr
lea excmsg1,a0
bsr print * print default exception message
move (sp)+,d0
bsr prtbyte
lea excmsg2, a0
bsr print
move.l (sp)+,d0
bsr prtlong
lea excmsg3, a0
bsr print
clr.l d0
trap #2 * warm boot
rte
usrexc:
* Call user exception handler
* make sure exception information is on his stack
move.l (a0),10(sp) * put user handler address on our stack
move.l usp,a0 * user stack pointer to a0
cmpi #8,d0 * address or bus error?
blt addrexc * if yes, skip
btst #13,14(sp) * exception occured in user state?
bne supstat1 * if no, go to supervisor handler
move.l 16(sp),-(a0) * put exception return on user stack
move.w 14(sp),-(a0) * put SR on user stack
move.l a0,usp * update user stack pointer
movem.l (sp)+,a0/d0 * restore regs
move.l 2(sp),8(sp) * move address of user handler to excptn rtn
addq #6,sp * clear junk from stack
andi #$7fff,(sp) * clear trace bit
rte * go to user handler
addrexc:
btst #13,22(sp) * exception occured in user state?
bne supstat2 * if no, go to supervisor handler
move.l 24(sp),-(a0) * put exception return on user stack
move.w 22(sp),-(a0) * put SR on user stack
move.l 18(sp),-(a0) * put extra 2 longs on user stack
move.l 14(sp),-(a0)
move.l a0,usp * update user stack pointer
movem.l (sp)+,a0/d0 * restore regs
move.l 2(sp),16(sp) * move address of user handler to excptn rtn
adda #14,sp * clear junk from stack
andi #$7fff,(sp) * clear trace bit
rte * go to user handler
supstat1:
move.w 14(sp),8(sp) * move SR to our exception return
bra supstat3
supstat2:
move.w 22(sp),8(sp)
supstat3:
movem.l (sp)+,a0/d0
rte
*
* Subroutines
*
print:
clr.l d1
move.b (a0)+, d1
beq prtdone
move #2, d0
trap #2
bra print
prtdone:
rts
prtlong:
* Print d0.l in hex format
move d0,-(sp)
swap d0
bsr prtword
move (sp)+,d0
prtword:
* Print d0.w in hex format
move d0,-(sp)
lsr #8,d0
bsr prtbyte
move (sp)+,d0
prtbyte:
* Print d0.b in hex format
move d0,-(sp)
lsr #4,d0
bsr prtnib
move (sp)+,d0
prtnib:
andi #$f,d0
cmpi #10,d0
blt lt10
addi.b #'A'-'9'-1,d0
lt10:
addi.b #'0',d0
move d0,d1
move #2,d0
trap #2
rts
.data
excmsg1:
.dc.b 13,10,10,'Exception $',0
excmsg2:
.dc.b ' at user address $',0
excmsg3:
.dc.b '. Aborted.',0
.bss
evec_adr:
.ds.l 1
.end

View File

@@ -0,0 +1,659 @@
/****************************************************************
* *
* CP/M-68K BDOS File I/O Module *
* *
* This module contains all file handling BDOS functions *
* except for read and write for CP/M-68K. Included are: *
* *
* seldsk() - select disk *
* openfile() - open file *
* close_fi() - close file *
* search() - search for first/next file match *
* create() - create file *
* delete() - delete file *
* rename() - rename file *
* set_attr() - set file attributes *
* getsize() - get file size *
* setran() - set random record field *
* free_sp() - get disk free space *
* move() - general purpose byte mover *
* *
* *
* Compiled with Alcyon C on the VAX *
* *
****************************************************************/
#include "bdosinc.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "pktio.h" /* Packet I/O definitions */
/* declare external fucntions */
EXTERN UWORD dirscan(); /* directory scanning routine */
EXTERN UWORD error(); /* disk error routine */
EXTERN UWORD ro_err(); /* read-only file error routine */
EXTERN UWORD do_phio(); /* packet disk i/o handler */
EXTERN clraloc(); /* clear bit in allocation vector */
EXTERN setaloc(); /* set bit in allocation vector */
EXTERN UWORD swap(); /* assembly language byte swapper */
EXTERN UWORD dir_wr(); /* directory write routine */
EXTERN tmp_sel(); /* temporary select disk routine */
EXTERN UWORD calcext(); /* calc max extent allocated for fcb */
EXTERN UWORD udiv(); /* unsigned divide routine */
/* declare external variables */
EXTERN UWORD log_dsk; /* logged-on disk vector */
EXTERN UWORD ro_dsk; /* read-only disk vector */
EXTERN UWORD crit_dsk; /* vector of disks in critical state */
/************************************
* This function passed to dirscan *
* from seldsk (below) *
************************************/
BOOLEAN alloc(fcbp, dirp, dirindx)
/* Set up allocation vector for directory entry pointed to by dirp */
struct fcb *fcbp; /* not used in this function */
REG struct dirent *dirp; /* pointer to directory entry */
WORD dirindx; /* index into directory for *dirp */
{
REG WORD i; /* loop counter */
BSETUP
if ( UBWORD(dirp->entry) < 0x10 ) /* skip MP/M 2.x and CP/M 3.x XFCBs */
{
(GBL.dphp)->hiwater = dirindx; /* set up high water mark for disk */
i = 0;
if ((GBL.parmp)->dsm < 256)
{
do setaloc( UBWORD(dirp->dskmap.small[i++]) );
while (i <= 15);
}
else
{
do setaloc(swap(dirp->dskmap.big[i++]));
while (i <= 7);
}
}
}
/************************
* seldsk entry point *
************************/
seldsk(dsknum)
REG UBYTE dsknum; /* disk number to select */
{
struct iopb selpkt;
REG WORD i;
UWORD j;
REG UBYTE logflag;
BSETUP
logflag = ~(log_dsk >> dsknum) & 1;
if ((GBL.curdsk != dsknum) || logflag)
{ /* if not last used disk or not logged on */
selpkt.iofcn = sel_info;
GBL.curdsk = (selpkt.devnum = dsknum);
if (UBWORD(dsknum) > 15) error(2);
selpkt.ioflags = logflag ^ 1;
do
{
do_phio(&selpkt); /* actually do the disk select */
if ( (GBL.dphp = selpkt.infop) != NULL ) break;
} while ( ! error(3) );
GBL.dirbufp = (GBL.dphp)->dbufp;
/* set up GBL copies of dir_buf and dpb ptrs */
GBL.parmp = (GBL.dphp)->dpbp;
}
if (logflag)
{ /* if disk not previously logged on, do it now */
LOCK /* must lock the file system while messing with alloc vec */
i = (GBL.parmp)->dsm;
do clraloc(i); while (i--); /* clear the allocation vector */
i = udiv( (LONG)(((GBL.parmp)->drm) + 1),
4 * (((GBL.parmp)->blm) + 1), &j);
/* calculate nmbr of directory blks */
if (j) i++; /* round up */
do setaloc(--i); while (i); /* alloc directory blocks */
dirscan(alloc, NULL, 0x0e); /* do directory scan & alloc blocks */
log_dsk |= 1 << dsknum; /* mark disk as logged in */
}
}
/*******************************
* General purpose byte mover *
*******************************/
move(p1, p2, i)
REG BYTE *p1;
REG BYTE *p2;
REG WORD i;
{
while (i--)
*p2++ = *p1++;
}
/*************************************
* General purpose filename matcher *
*************************************/
BOOLEAN match(p1, p2, chk_ext)
REG UBYTE *p1;
REG UBYTE *p2;
BOOLEAN chk_ext;
{
REG WORD i;
REG UBYTE temp;
BSETUP
i = 12;
do
{
temp = (*p1 ^ '?');
if ( ((*p1++ ^ *p2++) & 0x7f) && temp )
return(FALSE);
i -= 1;
} while (i);
if (chk_ext)
{
if ( (*p1 != '?') && ((*p1 ^ *p2) & ~((GBL.parmp)->exm)) )
return(FALSE);
p1 += 2;
p2 += 2;
if ((*p1 ^ *p2) & 0x3f) return(FALSE);
}
return(TRUE);
}
/************************
* openfile entry point *
************************/
BOOLEAN openfile(fcbp, dirp, dirindx)
REG struct fcb *fcbp; /* pointer to fcb for file to open */
struct dirent *dirp; /* pointer to directory entry */
WORD dirindx;
{
REG UBYTE fcb_ext; /* extent field from fcb */
REG BOOLEAN rtn;
BSETUP
if ( rtn = match(fcbp, dirp, TRUE) )
{
fcb_ext = fcbp->extent; /* save extent number from user's fcb */
move(dirp, fcbp, sizeof *dirp);
/* copy dir entry into user's fcb */
fcbp->extent = fcb_ext;
fcbp->s2 |= 0x80; /* set hi bit of S2 (write flag) */
crit_dsk |= 1 << (GBL.curdsk);
}
return(rtn);
}
/*************************/
/* flush buffers routine */
/*************************/
UWORD flushit()
{
REG UWORD rtn; /* return code from flush buffers call */
struct iopb flushpkt; /* I/O packet for flush buffers call */
flushpkt.iofcn = flush;
while ( rtn = do_phio(&flushpkt) )
if ( error(1) ) break;
return(rtn);
}
/*********************************
* file close routine for dirscan *
*********************************/
BOOLEAN close(fcbp, dirp, dirindx)
REG struct fcb *fcbp; /* pointer to fcb */
REG struct dirent *dirp; /* pointer to directory entry */
WORD dirindx; /* index into directory */
{
REG WORD i;
REG UBYTE *fp;
REG UBYTE *dp;
REG UWORD fcb_ext;
REG UWORD dir_ext;
BSETUP
if ( match(fcbp, dirp, TRUE) )
{ /* Note that FCB merging is done here as a final
confirmation that disks haven't been swapped */
LOCK
fp = &(fcbp->dskmap.small[0]);
dp = &(dirp->dskmap.small[0]);
if ((GBL.parmp)->dsm < 256)
{ /* Small disk map merge routine */
i = 16;
do
{
if (*dp)
{
if (*fp)
{
if (*dp != *fp) goto badmerge;
}
else *fp = *dp;
}
else *dp = *fp;
fp += 1;
dp += 1;
i -= 1;
} while (i);
}
else
{ /* Large disk map merge routine */
i = 8;
do
{
if (*(UWORD *)dp)
{
if (*(UWORD *)fp)
{
if (*(UWORD *)dp != *(UWORD *)fp) goto badmerge;
}
else *(UWORD *)fp = *(UWORD *)dp;
}
else *(UWORD *)dp = *(UWORD *)fp;
(UWORD *)fp += 1;
(UWORD *)dp += 1;
i -= 1;
} while (i);
}
/* Disk map merging complete */
fcb_ext = calcext(fcbp); /* calc max extent for fcb */
dir_ext = (UWORD)(dirp->extent) & 0x1f;
if ( (fcb_ext > dir_ext) ||
((fcb_ext == dir_ext) &&
(UBWORD(fcbp->rcdcnt) > UBWORD(dirp->rcdcnt))) )
/* if fcb points to larger file than dirp */
{
dirp->rcdcnt = fcbp->rcdcnt; /* set up rc, ext from fcb */
dirp->extent = (BYTE)fcb_ext;
}
dirp->s1 = fcbp->s1;
if ( (dirp->ftype[robit]) & 0x80) ro_err(fcbp,dirindx);
/* read-only file error */
dirp->ftype[arbit] &= 0x7f; /* clear archive bit */
dir_wr(dirindx >> 2);
UNLOCK
return(TRUE);
badmerge:
UNLOCK
ro_dsk |= (1 << GBL.curdsk);
return(FALSE);
}
else return(FALSE);
}
/************************
* close_fi entry point *
************************/
UWORD close_fi(fcbp)
struct fcb *fcbp; /* pointer to fcb for file to close */
{
flushit(); /* first, flush the buffers */
if ((fcbp->s2) & 0x80) return(0); /* if file write flag not on,
don't need to do physical close */
return( dirscan(close, fcbp, 0)); /* call dirscan with close function */
}
/************************
* search entry point *
************************/
/* First two functions for dirscan */
BOOLEAN alltrue(p1, p2, i)
UBYTE *p1;
UBYTE *p2;
WORD i;
{
return(TRUE);
}
BOOLEAN matchit(p1, p2, i)
UBYTE *p1;
UBYTE *p2;
WORD i;
{
return(match(p1, p2, TRUE));
}
/* search entry point */
UWORD search(fcbp, dsparm, p)
REG struct fcb *fcbp; /* pointer to fcb for file to search */
REG UWORD dsparm; /* parameter to pass through to dirscan */
UBYTE *p; /* pointer to pass through to tmp_sel */
{
REG UWORD rtn; /* return value */
BSETUP
if (fcbp->drvcode == '?')
{
seldsk(GBL.dfltdsk);
rtn = dirscan(alltrue, fcbp, dsparm);
}
else
{
tmp_sel(p); /* temporarily select disk */
if (fcbp->extent != '?') fcbp->extent = 0;
fcbp->s2 = 0;
rtn = dirscan(matchit, fcbp, dsparm);
}
move( GBL.dirbufp, GBL.dmaadr, SECLEN);
return(rtn);
}
/************************
* create entry point *
************************/
BOOLEAN create(fcbp, dirp, dirindx)
REG struct fcb *fcbp; /* pointer to fcb for file to create */
REG struct dirent *dirp; /* pointer to directory entry */
REG WORD dirindx; /* index into directory */
{
REG BYTE *p;
REG WORD i;
REG BOOLEAN rtn;
BSETUP
if ( rtn = ((dirp->entry) == 0xe5) )
{
p = &(fcbp->rcdcnt);
i = 17;
do
{ /* clear fcb rcdcnt and disk map */
*p++ = 0;
i -= 1;
} while (i);
move(fcbp, dirp, sizeof *dirp); /* move the fcb to the directory */
dir_wr(dirindx >> 2); /* write the directory sector */
if ( dirindx > (GBL.dphp)->hiwater )
(GBL.dphp)->hiwater = dirindx;
crit_dsk |= 1 << (GBL.curdsk);
}
return(rtn);
}
/************************
* delete entry point *
************************/
BOOLEAN delete(fcbp, dirp, dirindx)
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
REG struct dirent *dirp; /* pointer to directory entry */
REG WORD dirindx; /* index into directory */
{
REG WORD i;
REG BOOLEAN rtn;
BSETUP
if ( rtn = match(fcbp, dirp, FALSE) )
{
if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
/* check for read-only file */
dirp->entry = 0xe5;
LOCK
dir_wr(dirindx >> 2);
/* Now free up the space in the allocation vector */
if ((GBL.parmp)->dsm < 256)
{
i = 16;
do clraloc(UBWORD(dirp->dskmap.small[--i]));
while (i);
}
else
{
i = 8;
do clraloc(swap(dirp->dskmap.big[--i]));
while (i);
}
UNLOCK
}
return(rtn);
}
/************************
* rename entry point *
************************/
BOOLEAN rename(fcbp, dirp, dirindx)
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
REG struct dirent *dirp; /* pointer to directory entry */
REG WORD dirindx; /* index into directory */
{
REG UWORD i;
REG BYTE *p; /* general purpose pointers */
REG BYTE *q;
REG BOOLEAN rtn;
BSETUP
if ( rtn = match(fcbp, dirp, FALSE) )
{
if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
/* check for read-only file */
p = &(fcbp->dskmap.small[1]);
q = &(dirp->fname[0]);
i = 11;
do
{
*q++ = *p++ & 0x7f;
i -= 1;
} while (i);
dir_wr(dirindx >> 2);
}
return(rtn);
}
/************************
* set_attr entry point *
************************/
BOOLEAN set_attr(fcbp, dirp, dirindx)
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
REG struct dirent *dirp; /* pointer to directory entry */
REG WORD dirindx; /* index into directory */
{
REG BOOLEAN rtn;
BSETUP
if ( rtn = match(fcbp, dirp, FALSE) )
{
move(&fcbp->fname[0], &dirp->fname[0], 11);
dir_wr(dirindx >> 2);
}
return(rtn);
}
/****************************
* utility routine used by *
* setran and getsize *
****************************/
LONG extsize(fcbp)
/* Return size of extent pointed to by fcbp */
REG struct fcb *fcbp;
{
return( ((LONG)(fcbp->extent & 0x1f) << 7)
| ((LONG)(fcbp->s2 & 0x3f) << 12) );
}
/************************
* setran entry point *
************************/
setran(fcbp)
REG struct fcb *fcbp; /* pointer to fcb for file to set ran rec */
{
struct
{
BYTE b3;
BYTE b2;
BYTE b1;
BYTE b0;
};
LONG random;
random = (LONG)UBWORD(fcbp->cur_rec) + extsize(fcbp);
/* compute random record field */
fcbp->ran0 = random.b2;
fcbp->ran1 = random.b1;
fcbp->ran2 = random.b0;
}
/**********************************/
/* fsize is a funtion for dirscan */
/* passed from getsize */
/**********************************/
BOOLEAN fsize(fcbp, dirp, dirindx)
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
REG struct dirent *dirp; /* pointer to directory entry */
WORD dirindx; /* index into directory */
{
REG BOOLEAN rtn;
struct
{
BYTE b3;
BYTE b2;
BYTE b1;
BYTE b0;
};
LONG temp;
if ( rtn = match(fcbp, dirp, FALSE) )
{
temp = (LONG)UBWORD(dirp->rcdcnt) + extsize(dirp);
/* compute file size */
fcbp->ran0 = temp.b2;
fcbp->ran1 = temp.b1;
fcbp->ran2 = temp.b0;
}
return(rtn);
}
/************************
* getsize entry point *
************************/
getsize(fcbp)
/* get file size */
REG struct fcb *fcbp; /* pointer to fcb to get file size for */
{
LONG maxrcd;
LONG temp;
REG WORD dsparm;
struct
{
BYTE b3;
BYTE b2;
BYTE b1;
BYTE b0;
};
maxrcd = 0;
dsparm = 0;
temp = 0;
while ( dirscan(fsize, fcbp, dsparm) < 255 )
{ /* loop until no more matches */
temp.b2 = fcbp->ran0;
temp.b1 = fcbp->ran1;
temp.b0 = fcbp->ran2;
if (temp > maxrcd) maxrcd = temp;
dsparm = 1;
}
fcbp->ran0 = maxrcd.b2;
fcbp->ran1 = maxrcd.b1;
fcbp->ran2 = maxrcd.b0;
}
/************************
* free_sp entry point *
************************/
free_sp(dsknum)
UBYTE dsknum; /* disk number to get free space of */
{
REG LONG records;
REG UWORD *alvec;
REG UWORD bitmask;
REG UWORD alvword;
REG WORD i;
BSETUP
seldsk(dsknum); /* select the disk */
records = (LONG)0; /* initialize the variables */
alvec = (GBL.dphp)->alv;
bitmask = 0;
for (i = 0; i <= (GBL.parmp)->dsm; i++) /* for loop to compute */
{
if ( ! bitmask)
{
bitmask = 0x8000;
alvword = ~(*alvec++);
}
if ( alvword & bitmask)
records += (LONG)( ((GBL.parmp)->blm) + 1 );
bitmask >>= 1;
}
*(LONG *)GBL.dmaadr = records; /* move # records to DMA address */
}

View File

@@ -0,0 +1,106 @@
*
* CP/M-68K table driven file search module
* ========================================
*
* GLOBALS
.globl _load_tbl * loader table
.globl _load68k * default load program
.globl init_tbl * initializes table on COLD BOOT
.text
*************************************************************************
* *
* This is the DUAL PROCESSOR,ROMABLE version of CP/M-68K *
* ====================================================== *
* *
* (c) Copyright Digital Research 1983 *
* all rights reserved *
* *
*************************************************************************
*
* The following code allows CP/M-68K to be ROM-able.
* -------------------------------------------------
*
init_tbl:
move.l #typ1,typ1p
move.l #typ2,typ2p * init the pointers to the filetypes
move.l #typ3,typ3p
move.l #null,typ4p
move.l #_load68k,pgld1
move.l #_load68k,pgld2 * init the pointers to the loaders
move.l #_load68k,pgld3
move.l #_load68k,pgld4
rts
.bss
.even
*************************************************************************
* *
* CP/M-68K LOADER TABLE *
* ===================== *
* *
*-----------------------------------------------------------------------*
* *
* STRUCTURE OF A LOADER TABLE ENTRY: *
* ================================= *
* *
* (1) LONG WORD pointer to a filetype *
* (2) LONG WORD address of the program loader for the above type *
* (3) BYTE flag #1 *
* (4) BYTE flag #2 *
* *
*************************************************************************
_load_tbl:
typ1p: .ds.l 1
pgld1: .ds.l 1
.ds.b 1
.ds.b 1
typ2p: .ds.l 1
pgld2: .ds.l 1
.ds.b 1
.ds.b 1
typ3p: .ds.l 1
pgld3: .ds.l 1
.ds.b 1
.ds.b 1
typ4p: .ds.l 1
pgld4: .ds.l 1
.ds.b 1
.ds.b 1
*****************************************
* *
* FILETYPE TABLE *
* ============== *
* *
*****************************************
.data
.even
typ1: .dc.b '68K',0
.even
typ2: .dc.b ' ',0
.even
typ3: .dc.b 'SUB',0
.even
null: .dc.l 0
.end

View File

@@ -0,0 +1,77 @@
/****************************************************************
* *
* CP/M-68K BDOS Disk I/O System Module *
* *
* This module translates from the packet oriented I/O *
* passed from the other BDOS modules into BIOS calls. *
* *
* It includes only one external entry point:
* do_phio() - do physical i/o *
* *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "bdosinc.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "pktio.h" /* Packet I/O definitions */
#include "biosdef.h" /* Declarations for BIOS entry points */
EXTERN udiv(); /* Assembly language unsigned divide routine */
/* in bdosif.s. It's used because Alcyon C */
/* can't do / or % without an external */
/************************
* do_phio entry point *
************************/
UWORD do_phio(iop)
REG struct iopb *iop; /* iop is a pointer to a i/o parameter block */
{
MLOCAL UBYTE last_dsk; /* static variable to tell which disk
was last used, to avoid disk selects */
REG struct dph *hdrp; /* pointer to disk parameter header */
REG struct dpb *dparmp; /* pointer to disk parameter block */
REG UWORD rtn; /* return parameter */
UWORD iosect; /* sector number returned from divide rtn */
LOCK /* lock the disk system while doing physical i/o */
rtn = 0;
switch (iop->iofcn)
{
case sel_info:
last_dsk = iop->devnum;
iop->infop = bseldsk(last_dsk, iop->ioflags);
break;
case read:
case write:
if (last_dsk != iop->devnum)
bseldsk((last_dsk = iop->devnum), 0);
/* guaranteed disk is logged on, because temp_sel in
BDOSMAIN does it */
hdrp = iop->infop;
dparmp = hdrp->dpbp;
bsettrk( udiv( iop->devadr, dparmp->spt, &iosect )
+ dparmp->trk_off );
bsetsec( bsectrn( iosect, hdrp->xlt ) );
bsetdma(iop->xferadr);
if ((iop->iofcn) == read) rtn = bread();
else rtn = bwrite(iop->ioflags);
break;
case flush:
rtn = bflush();
}
UNLOCK
return(rtn);
}

View File

@@ -0,0 +1,83 @@
$1cp68 bdosmain.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic bdosmain.s -ld
era $1x.ic
$1as68 -s 0$1 -l -u -f $1 bdosmain.s
era bdosmain.s
$1cp68 bdosmisc.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic bdosmisc.s -ld
era $1x.ic
$1as68 -s 0$1 -l -u -f $1 bdosmisc.s
era bdosmisc.s
$1cp68 bdosrw.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic bdosrw.s -ld
era $1x.ic
$1as68 -s 0$1 -l -u -f $1 bdosrw.s
era bdosrw.s
$1cp68 conbdos.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic conbdos.s -ld
era $1x.ic
$1as68 -s 0$1 -l -u -f $1 conbdos.s
era conbdos.s
$1cp68 dskutil.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic dskutil.s -ld
era $1x.ic
$1as68 -s 0$1 -l -u -f $1 dskutil.s
era dskutil.s
$1cp68 fileio.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic fileio.s -ld
era $1x.ic
$1as68 -s 0$1 -l -u -f $1 fileio.s
era fileio.s
$1cp68 iosys.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic iosys.s -ld
era $1x.ic
$1as68 -s 0$1 -l -u -f $1 iosys.s
era iosys.s
$1cp68 ccp.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
era $1x.i
era $1x.st
$1c168 $1x.ic ccp.s -ld
era $1x.ic
$1as68 -s 0$1 -l -u -f $1 ccp.s
era ccp.s
$1as68 -s 0$1 -l -u -f $1 bdosif.s
$1as68 -s 0$1 -l -u -f $1 -n exceptn.s
$1as68 -s 0$1 -l -u -f $1 pgmld.s
$1as68 -s 0$1 -l -u -f $1 ccpbdos.s
$1as68 -s 0$1 -l -u -f $1 ccpif.s
$1as68 -s 0$1 -l -u -f $1 ccpload.s
$1as68 -s 0$1 -l -u -f $1 filetyps.s
$1as68 -s 0$1 -l -u -f $1 stack.s
rear $1

View File

@@ -0,0 +1,537 @@
*********************************
* *
* Function 59 -- Program Load *
* Assembly language version *
* *
* June 8, 1982 *
* *
*********************************
.globl _pgmld * this routine is public
secsize = 128 * CP/M sector size
* d0 always contains the return parameter from pgmld
* d1 is the return register from local subroutines
* a0 contains the pointer to the Load Parm Block passed to pgmld
* Return parameters in d0 are:
* 00 - function successful
* 01 - insufficient memory or bad header in file
* 02 - read error on file
* 03 - bad relocation information in file
* Entry point for Program Load routine
_pgmld:
movem.l d1-d7/a0-a6, -(sp) * save everything, just to be safe
move.l 60(sp),a0 * get pointer to LPB
clr.l d0 * start with return parm cleared
bsr gethdr * get header
tst d0
bne lddone * if unsuccessful, return
bsr setaddr * set up load addresses
tst d0
bne lddone * if unsuccessful, return
bsr rdtxt * read code and data text segments into mem
tst d0
bne lddone * if unsuccessful, return
move.l tstart,d7
cmp.l cseg,d7
beq noreloc
bsr reloc * do relocation if necessary
noreloc:
tst d0
bne lddone
bsr setrtn * set up return parameters
lddone:
move.l 64(sp), d1
bsr setdma * restore dma address
movem.l (sp)+,d1-d7/a0-a6
rts
* Subroutines
readseq:
* CP/M read sequential function
move.l d0,-(sp) * save return parm
move.l FCBPtr(a0),d1
moveq #20,d0 * read seq function
trap #2 * call bdos
move.l d0,d1 * return parm in d1
move.l (sp)+,d0
rts
setdma:
* CP/M set dma function
move.l d0,-(sp) * save return parm
moveq #26,d0 * set dma function
trap #2 * call bdos
move.l (sp)+,d0 * restore d0
rts
gethdr:
* Get header into buffer in data segment
move.l LoAdr(a0),d1
bsr setdma
bsr readseq
tst d1 * read ok?
bne badhdr * if no, return bad
moveq #18,d7
movea.l LoAdr(a0),a5
movea.l #hdr,a6
geth1: move.w (a5)+,(a6)+ * move header into hdr
dbf d7,geth1
rts
badhdr: moveq #2,d0
rts
conflict:
* input parms: d2, d3 = 4 * segment nmbr
* if segment d2/4 overlaps segment d3/4, then return 1 in d1
* else return 0 in d1
* uses d7, a2, a3
clr.l d1 * assume it will work
movea.l #cseg,a2 * a2 points to start of segment addresses
movea.l #csize,a3 * a3 points to start of segment lengths
move.l 0(a2,d2),d7 * get 1st seg start
cmp.l 0(a2,d3),d7 * is 1st seg above 2nd seg?
bge conf1
add.l 0(a3,d2),d7 * yes, find top of 1st seg
cmp.l 0(a2,d3),d7 * above start of 2nd seg?
bgt confbd * if yes, we have a conflict
rts * else, return good
conf1:
move.l 0(a2,d3),d7
add.l 0(a3,d3),d7 * find top of 2nd seg
cmp.l 0(a2,d2),d7 * above start of 1st seg?
ble confgd * if no, we're ok
confbd: moveq.l #1,d1
confgd: rts
trymemtp:
* entry: d2 is a segment nmbr [0..4]
* try to fit it at top of memory
* uses d3, d6, d7, a5, a6
* returns 0 in d1 if ok
move.l d2,d6 * d6 is loop counter for chksegs
subq #1,d6
lsl #2,d2 * multiply d2 by 4
move.l HiAdr(a0),d7 * top of mem to d7
chksegs:
* entry: d2 = 4 * (segment nmbr to try)
* d6 = (d2/4) - 1 (loop counter)
* d7 = address below which to try it
* check for conflicts with segments [0..d6] and low memory boundary
* return 0 in d1 if no conflicts, else d1 = 1
* uses d3, a5, a6
movea.l #cseg,a5
movea.l #csize,a6
sub.l 0(a6,d2),d7 * subtract size of segment to try
bclr #0,d7 * make it even address
move.l d7,0(a5,d2) * insert address in segment table
cmp.l LoAdr(a0),d7 * check for conflict with low memory
blt confbd
clr.l d3 * check for conflicts with 0..d6
chk1:
bsr conflict
addq.l #4,d3
tst.l d1 * conflict with this seg?
dbne d6,chk1 * if no, try next
rts
fndseg:
* entry: d2 is a segment nmbr [0..4]
* try to fit segment d2 directly below segments 0..(d2-1)
* uses d3-d7, a5, a6
move.l d2,d5 * d5 is loop counter to find fit
subq.l #1,d5
move.l d5,temp
lsl.l #2,d2 * multiply segment by 4
clr.l d4 * d4 is segment to try to fit below
fnd1:
move.l temp,d6 * d6 is loop counter for chksegs
movea.l #cseg,a5
move.l 0(a5,d4),d7 * segment address to d7
bsr chksegs * check for conflicts
addq.l #4,d4
tst.l d1
dbeq d5,fnd1 * if conflict, try next
rts
setaddr:
* Set up load addresses for cseg, dseg, bss, basepg, and stack
move.w magic,d6
andi.w #$fffe,d6
cmpi.w #$601a,d6
bne badadr * if magic nmbr <> 601a or 601b, skip
move.l bpsize,symsize
move.l #256,d7
move.l d7,bpsize * base page is 256 bytes
lea stksize,a2
cmp (a2),d7
blt set0 * if stack size < 256, set to 256
move.l d7,(a2)
set0: cmpi.w #$601b,magic
beq seta
tst.w rlbflg
beq set1
seta: move.l tstart,cseg * if not relocatable or hdr = $601b,
bra set2 * cseg starts at tstart
set1: btst #0,Flags(a0)
bne sldhi
* relocatable, load low
move.l LoAdr(a0),d7
add.l #$101,d7 * leave room for base page
bclr #0,d7
move.l d7,cseg * cseg is bottom of mem + $100 (even boundary)
bra set2
sldhi:
* relocatable, load high
move.l HiAdr(a0),d7
sub.l csize,d7
sub.l dsize,d7
sub.l bsize,d7
subq.l #4,d7
bclr #0,d7 * put cseg at next even address below
move.l d7,cseg * high memory - (sum of sizes)
set2:
* Cseg has been set up. Now do dseg, bseg
cmpi.w #$601b,magic
bne set3
* if magic # = 601b, take addr from hdr
move.l dstart,dseg
move.l bstart,bseg
bra set4
set3:
* if short header, dseg and bseg follow cseg
move.l cseg,d7
add.l csize,d7
addq.l #1,d7
bclr #0,d7
move.l d7,dseg
add.l dsize,d7
addq.l #1,d7
bclr #0,d7
move.l d7,bseg
set4:
* cseg, dseg, bseg set up
* now find a place for the base page and stack
moveq.l #3,d2
bsr fndseg * try to fit base page below cseg, dseg, bseg
tst.l d1
beq set5 * if found, skip
moveq.l #3,d2
bsr trymemtp * else, try top of memory
tst.l d1
bne badadr * if fail, exit
set5: moveq.l #4,d2
bsr trymemtp * try to fit stack at top of memory
tst.l d1
beq set6 * if ok, skip
moveq.l #4,d2
bsr fndseg * else, try to fit below other segs
tst.l d1
bne badadr
set6:
* now check all segments for conflicts with low and high memory boundaries
movea.l #cseg,a5
movea.l #csize,a6
clr.l d2
moveq #4,d3 * loop counter
set7: move.l 0(a5,d2),d7 * get segment base
cmp.l LoAdr(a0),d7 * above bottom of memory?
blt badadr
add.l 0(a6,d2),d7 * find top of segment
cmp.l HiAdr(a0),d7 * below top of memory?
bgt badadr
addq.l #4,d2 * point to next segment
dbf d3,set7
rts
badadr: moveq.l #1,d0
rts
movebuf:
* move (d3) bytes from the base page buffer to (a2)
* uses d6
movea.l basepg,a1
move.l #secsize,d6
sub.w bufbyts,d6 * address to move from =
adda.w d6,a1 * (basepg) + secsize - (bufbyts)
sub.w d3,bufbyts * update # bytes buffered
bra moveb2
moveb1: move.b (a1)+,(a2)+ * do the move
moveb2: dbf d3,moveb1
rts
rdtxt:
* Read code and data text into memory
* during this routine, a2 is always the load address,
* d2 is number of bytes left to load
moveq #63,d7
movea.l LoAdr(a0),a5
movea.l basepg,a6
rdtxt1: move.w (a5)+,(a6)+ * move header sector to base page
dbf d7,rdtxt1
move.w #secsize-28,d7
cmpi.w #$601a,magic * short header?
beq rdtxt2
subq.w #8,d7
rdtxt2: move.w d7,bufbyts * indicate # bytes of text in buffer
move.w #2,loop * do for code, data segments
move.l cseg,a2 * start at cseg
move.l csize,d2 * for csize bytes
rdtxt3:
clr.l d3
move.w bufbyts,d3
cmp.l d2,d3 * # bytes in buffer >= # bytes to load?
blt rdtxt4
move.l d2,d3
bsr movebuf * if yes, move # bytes to load
bra finrd
rdtxt4:
sub.l d3,d2 * if no, update # bytes to load
bsr movebuf * move remainder of buffer
move.l #secsize,d3 * d3 = secsize fo following loop
rdtxt5:
cmp.l d3,d2 * have at least one more full sector?
blt rdtxt6
move.l a2,d1
bsr setdma * if yes, set up dma address
bsr readseq * read next sector
tst.w d1
bne rdbad * if no good, exit
sub.l d3,d2 * decrement # bytes to load
adda.l #secsize,a2 * increment dma address
bra rdtxt5
rdtxt6:
tst.l d2 * any more bytes to read?
beq finrd
move.l basepg,d1
bsr setdma
bsr readseq * if yes, read into base page
tst.w d1
bne rdbad
move.w d3,bufbyts * indicate that we've buffered a sector
move.l d2,d3
bsr movebuf * move remainder of segment
finrd:
move.l dseg,a2 * set up to load data segment
move.l dsize,d2
sub.w #1,loop
bne rdtxt3
move.l bseg,a2 * clear the bss segment
move.l bsize,d2
beq rdtxt8
rdtxt7: clr.b (a2)+
subq.l #1,d2
bne rdtxt7
rdtxt8: rts
rdbad: moveq.l #2,d0
rts
relocword:
* relocate word at (a2) based on reloc bits at (a3)
* lsb of d2 indicates whether previous word was 1st half of long-word
move.w (a3)+,d7 * get relocation info
andi.w #7,d7 * strip off symbol table bits
lsl #1,d7 * multiply by 2
jmp 2(pc,d7)
bra relabs
bra reldata
bra relcode
bra relbss
bra relbad
bra rellong
bra relbad
bra relop
relbad: move.l (sp)+,d0 * pop return address
moveq #3,d0 * return bad relocation to main routine
rts
relabs:
relop: bclr #0,d2 * reset long word flag
tst.w (a2)+ * point to next word of segment
rts
rellong:
bset #0,d2 * set long word flag
tst.w (a2)+ * point to next word of segment
rts
reldata:
relbss:
relcode:
bclr #0,d2 * long word flag set?
bne relc1 * if yes, skip
move.w (a2),d6
add.w d5,d6
move.w d6,(a2)+
rts
relc1: tst.w -(a2) * point to first word of long
move.l (a2),d6
add.l d5,d6
move.l d6,(a2)+ * note that a2 points past long word
rts
reloc:
* Modify address references of code and data segments based on relocation bits
* During this routine,
* a2 points to text file to relocate
* a3 points to relocation word in basepg
* lsb of d2 is long word flag (set on reloc type 5, reset on next word)
* d3 is # words in relocation buffer
* d4 is nmbr of words left to relocate
* d5 is relocation offset
move.l basepg,d1
bsr setdma * we will always read into base page
* skip past the symbol table
move.l symsize,d7
divu #secsize,d7 * calculate how many sectors to skip
* note that max # symbols is 8k, which is 896 sectors of 128 bytes
move.w d7,d6 * d6 is nmbr sectors to skip
swap d7 * d7 is nmbr bytes to skip
move.w bufbyts,d3
sub.w d7,d3 * subtract bytes to skip from buffer
bge skip1
addi #secsize,d3 *if amt in buffer < # bytes to skip,
addq #1,d6 * read in 1 extra sector
skip1: move.l basepg,a3
adda #secsize,a3
suba.w d3,a3 * set up a3 to point to buffer
lsr #1,d3 * d3 is nmbr words in buffer
bra skip3
skip2:
bsr readseq * read next symbol table sector
tst.w d1
bne rdbad
skip3: dbf d6,skip2
* we got past symbol table
* a3, d3 are set up
move.l cseg,d5
move.l d5,a2 * relocate cseg first
sub.l tstart,d5 * d5 contains the relocation offset
move.l csize,d4 * nmbr of bytes to relocate
move.w #2,loop * we're going to relocate 2 segments
reloc1:
* relocate one segment
clr.l d2 * clear long word flag
lsr.l #1,d4 * make d4 indicate # words
bra reloc4
reloc2:
subq.w #1,d3
bpl reloc3
bsr readseq * if no more words in buffer, refill it
tst.w d1
bne rdbad
move.l basepg,a3
move.w #(secsize/2)-1,d3
reloc3:
bsr relocword * relocate one word
subq.l #1,d4
reloc4:
tst.l d4 * any more to relocate in this segment?
bne reloc2 * if yes, do it
move.l dseg,a2 * else, set up for dseg
move.l dsize,d4
sub.w #1,loop
bne reloc1
rts
setrtn:
* Set up the return parameters in Ld Parm Blk and Base Page
move.l basepg,BasPage(a0)
move.l stk,d7
add.l stksize,d7
bclr #0,d7
move.l d7,Stack(a0)
move.l basepg,a1
move.l LoAdr(a0),(a1)+
move.l HiAdr(a0),(a1)+
move.l cseg,(a1)+
move.l csize,(a1)+
move.l dseg,(a1)+
move.l dsize,(a1)+
move.l bseg,(a1)+
move.l bsize,(a1)
* find size of free memory after bss segment
move.l HiAdr(a0),d7 * d7 contains next segment above bss
move.l -4(a1),d6
add.l (a1)+,d6 * d6 points to start of free mem after bss
movea.l #cseg,a6 * a6 points to segment to try
moveq #4,d5 * try for all segments
clr.l bseg * but force bss not to appear
setb1: cmp.l (a6),d6 * segment above bss?
bhi setb2
cmp.l (a6),d7 * segment is above bss. Is it below previous?
bls setb2
move.l (a6),d7
setb2: tst.l (a6)+ * point to next segment
dbf d5,setb1
sub.l d6,d7 * diff between bss top and next segment abv
move.l d7,(a1)+
* now put disk number that we loaded from into base page
movea.l FCBPtr(a0),a2
move.b (a2),d0 * get disk select byte
bne setb3 * if not auto-select, skip
move #25,d0
trap #2 * get default disk
addq #1,d0 * we want it in range of 1..16
setb3: move.b d0,(a1)+ * move disk number into base page
clr.l d0 * function OK
rts
.bss
* offsets from start of parameter block
FCBPtr = 0
LoAdr = 4
HiAdr = 8
BasPage = 12 * return parameters
Stack = 16
Flags = 21
hdr:
* load file header is read into here
magic: .ds.w 1
csize: .ds.l 1
dsize: .ds.l 1
bsize: .ds.l 1
bpsize: .ds.l 1 * symb tbl size is swapped with base page size
stksize: .ds.l 1
tstart: .ds.l 1
rlbflg: .ds.w 1
dstart: .ds.l 1
bstart: .ds.l 1
cseg: .ds.l 1
dseg: .ds.l 1
bseg: .ds.l 1
basepg: .ds.l 1
stk: .ds.l 1
symsize: .ds.l 1
temp: .ds.l 1
loop: .ds.w 1
bufbyts: .ds.w 1
.end

View File

@@ -0,0 +1,57 @@
/********************************************************
* *
* CP/M-68K header file *
* Copyright (c) 1982 by Digital Research, Inc. *
* Structure definitions for doing I/O in packets *
* *
********************************************************/
/* May use this information structure instead of disk parameter header and
disk parameter block in future, but for now it's unused
struct dskinfo
{
UBYTE *dbuffp;
UBYTE *csv;
UBYTE *alv;
UBYTE blksize;
UBYTE didummy;
UWORD dskmax;
UWORD dirmax;
UWORD chksize;
};
*/
struct iopb
{
UBYTE iofcn; /* function number, see defines below */
UBYTE ioflags; /* used for login flag and write flag */
UBYTE devtype; /* device type, see defines below */
/* currently unused */
UBYTE devnum; /* device number, or, devtype and devnum
taken together form int device number */
LONG devadr; /* item nmbr on device to start xfer at */
/* note -- item is sector for disks, byte for char devs */
UWORD xferlen; /* number items to transfer */
UBYTE *xferadr; /* memory address to xfer to/from */
struct dph *infop; /* pointer to disk parameter header */
/* return parm for fcn 0, input for rest */
};
/* Definitions for iofcn, the function number */
#define sel_info 0 /* select and return info on device */
#define read 1
#define write 2
#define flush 3
#define status 4 /* not currently used */
/* Definitions for devtype, the device type */
/* This field not currently used */
#define console 0
#define printer 1
#define disk 2
#define memory 3 /* gets TPA boundaries */
#define redir 4 /* read/write IOByte */
#define exc_vec 5 /* set exception vector */

View File

@@ -0,0 +1,4 @@
$1ar68 rvf $1 cpmlib ccpif.o ccpbdos.o ccpload.o ccp.o bdosif.o conbdos.o
$1ar68 rvf $1 cpmlib bdosmisc.o dskutil.o fileio.o bdosrw.o bdosmain.o
$1ar68 rvf $1 cpmlib iosys.o pgmld.o exceptn.o filetyps.o stack.o
era *.o

View File

@@ -0,0 +1,25 @@
E:SEND REAR.SUB
E:SEND MAKE.SUB
E:SEND BDOSDEF.H
E:SEND BDOSIF.S
E:SEND BDOSINC.H
E:SEND BDOSMAIN.C
E:SEND BDOSMISC.C
E:SEND BDOSRW.C
E:SEND BIOSDEF.H
E:SEND CONBDOS.C
E:SEND CPMC.DOC
E:SEND DSKUTIL.C
E:SEND EXCEPTN.S
E:SEND FILEIO.C
E:SEND IOSYS.C
E:SEND PGMLD.S
E:SEND PKTIO.H
E:SEND CCP.C
E:SEND CCPBDOS.S
E:SEND CCPDEF.H
E:SEND CCPIF.S
E:SEND CCPLOAD.S
E:SEND FILETYPS.S
E:SEND STACK.S
E:SEND SEND2.SUB

View File

@@ -0,0 +1,15 @@
*************************************************************************
* *
* THIS IS THE SYSTEM STACK AREA *
* *
* *
* THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM *
* ================================================== *
*************************************************************************
.globl stack
.bss
.ds.l 400
stack:
.ds.w 1
.end

View File

@@ -0,0 +1,26 @@
vax REAR.SUB s
vax MAKE.SUB s
vax BDOSDEF.H s
vax BDOSIF.S s
vax BDOSINC.H s
vax BDOSMAIN.C s
vax BDOSMISC.C s
vax BDOSRW.C s
vax BIOSDEF.H s
vax CONBDOS.C s
vax CPMC.DOC s
vax DSKUTIL.C s
vax EXCEPTN.S s
vax FILEIO.C s
vax IOSYS.C s
vax PGMLD.S s
vax PKTIO.H s
vax CCP.C s
vax CCPBDOS.S s
vax CCPDEF.H s
vax CCPIF.S s
vax CCPLOAD.S s
vax FILETYPS.S s
vax STACK.S s
vax SEND2.SUB s
vax up2.sub s

View File

@@ -0,0 +1,25 @@
$ bdos
$ !
$ ! VMS command file to build CPMLIB using cross tools
$ !
$ set noon
$ cc68 bdosmain
$ cc68 bdosmisc
$ cc68 bdosrw
$ cc68 conbdos
$ cc68 dskutil
$ cc68 fileio
$ cc68 iosys
$ cc68 ccp
$ as68 -l -u bdosif.s
$ as68 -l -u -n exceptn.s
$ as68 -l -u pgmld.s
$ as68 -l -u ccpbdos.s
$ as68 -l -u ccpif.s
$ as68 -l -u ccpload.s
$ as68 -l -u filetyps.s
$ as68 -l -u stack.s
$ ar68 r cpmlib ccpif.o ccpbdos.o ccpload.o ccp.o bdosif.o conbdos.o
$ ar68 r cpmlib bdosmisc.o dskutil.o fileio.o bdosrw.o bdosmain.o
$ ar68 r cpmlib iosys.o pgmld.o exceptn.o filetyps.o stack.o
$ del *.o;*

View File

@@ -0,0 +1,30 @@
$ set noon
$ vsend BDOSDEF.H
$ vsend BDOSIF.S
$ vsend BDOSINC.H
$ vsend BDOSMAIN.C
$ vsend BDOSMISC.C
$ vsend BDOSRW.C
$ vsend BIOSDEF.H
$ vsend CCP.C
$ vsend CCPBDOS.S
$ vsend CCPDEF.H
$ vsend CCPIF.S
$ vsend CCPLOAD.S
$ vsend CONBDOS.C
$ vsend CPMC.DOC
$ vsend DOWN2.SUB
$ vsend DSKUTIL.C
$ vsend EXCEPTN.S
$ vsend FILEIO.C
$ vsend FILETYPS.S
$ vsend IOSYS.C
$ vsend MAKE.SUB
$ vsend PGMLD.S
$ vsend PKTIO.H
$ vsend REAR.SUB
$ vsend SEND2.SUB
$ vsend STACK.S
$ vsend UP2.SUB
$ vsend VMAKE.COM
$ vsend done

View File

@@ -0,0 +1 @@
hello

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
.text
*
* Global Code addresses
*
.globl _init
.globl _biosinit
.globl _flush
.globl _wboot
.globl _cbios
.globl _dskia
.globl _dskic
.globl _setimask
.globl _ccp
.globl cpm * Lowest addr of CP/M
.globl _end * Highest addr of CP/M
*
* Global data addresses
*
.globl _memtab * memory region table
.globl _dpb3 * RAM disk dpb address
.globl _memdsk * -> First memory disk location
*
* Vector Addresses
*
dskint: .equ $3fc * UDC Interrupt vector
trap3: .equ $8c * Trap 3 vector
buserr: .equ $8 * Bus error vector
*
*
_init: lea entry,a0
move.l a0,trap3
lea _dskia,a0
move.l a0,dskint
*
* Auto-Size TPA
*
lea _memtab,a0 * a0 -> Memory region table
move.w #1,(a0)+ * 1 region
move.l #$400,(a0)+ * TPA starts at 400
move.l #cpm-$408,(a0)+ * Ends where CP/M begins
*
* Auto-Size RAM disk
*
move.l buserr,-(sp) * Push bus err vector
lea _end,a0 * a0 -> Last location in CP/M
add.l #cpm,a0 * Linker doesn't reloc this!!
move.l a0,_memdsk * -> first location in RAM disk
move.l #quit,buserr * set up vector -> ourselves
loop:
tst.w (a0)+ * Find
bra loop * End of memory
quit:
add.l #14,a7 * Clear buserr gorp
move.l (a7)+,buserr * Pop buserr vector
sub.l #_end,a0 * a0 = # bytes in RAM disk
sub.l #cpm,a0 * Relocation bug
move.l a0,d0 * Into D reg for shift
move.l #11,d1 * Load shift count
lsr.l d1,d0 * Divide by 2048
move.w d0,_dpb3+6 * Load DRM field of dpb
move #$2000,sr
jsr _biosinit
clr.l d0
rts
*
_wboot: clr.l d0
jmp _ccp
*
entry: move.l d2,-(a7)
move.l d1,-(a7)
move.w d0,-(a7)
jsr _cbios
add #10,a7
rte
*
_dskia: link a6,#0
movem.l d0-d7/a0-a5,-(a7)
jsr _dskic
movem.l (a7)+,d0-d7/a0-a5
unlk a6
rte
*
_setimask: move sr,d0
lsr #8,d0
and.l #7,d0
move sr,d1
ror.w #8,d1
and.w #$fff8,d1
add.w 4(a7),d1
ror.w #8,d1
move d1,sr
rts
.end

View File

@@ -0,0 +1,3 @@
#define LOADER 0
#define CTLTYPE 0
#define MEMDSK 4

View File

@@ -0,0 +1,23 @@
/************************************************/
/* */
/* Portable type definitions for use */
/* with the C BIOS according to */
/* CP/M-68K (tm) standard usage. */
/* */
/************************************************/
#define LONG long
#define ULONG unsigned long
#define WORD short int
#define UWORD unsigned short
#define BYTE char
#define UBYTE unsigned char
#define VOID
#define REG register
#define LOCAL auto
#define MLOCAL static
#define GLOBAL extern
#define EXTERN extern
/************************************************/

View File

@@ -0,0 +1,59 @@
***************************************
* Information to go on the 256 byte *
* boot sector of an ExorMacs *
***************************************
.text
.dc.l $4000 * starting stack pointer
.dc.l start * starting program counter
.dc.w 1 * garbage
.dc.w 1 * length of SAT
.dc.l 2 * secondary directory start
.dc.l 0 * primary directory PSN list start
.dc.l 0 * start of boot loader
.dc.w 26 * length of boot loader
.dc.l $0 * boot execution address
.dc.l $0 * boot load address
.dc.b '9/30' * generation date
.dc.b 'CP/M-68K of 9/30/82 ' * volume descriptor
.dc.b '0020' * version/revision
.dc.w $0a484 * checksum (god help us)
.dc.l $0f1e2d3c * diagnostic test pattern
.dc.l $4b5a6978
.dc.l $8796a5b4
.dc.l $c3d2e1f0
.dc.l $0f1e2d3c * diagnostic test pattern
.dc.l $4b5a6978
.dc.l $8796a5b4
.dc.l $c3d2e1f0
.dc.l $4f8f0f07 * diagnostic test pattern
.dc.l $0b0d0e06
.dc.l $0a0c0408
.dc.l $04020100
.dc.l 00, 00, 00, 00 * diagnostic test pattern
.dc.l 0 * diagnostic test area directory
.dc.l 0 * start of dump area
.dc.w 0 * length of dump area
.dc.l 0 * start of sector lockout table
.dc.w 0 * length of sector lockout table
.dc.l 0,0,0,0,0,0,0 * unused, reserved
.dc.l 0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0
.dc.b 'EXORMACS' * let's hear it for Motorola
*
* end of volume id
*
* begin boot info proper
*
.ds.b $300 * skip over exception vectors
.even
start: move #$2700,sr
move.l #$8,a0
move.w #253,d0
exlp: move.l #expdef,(a0)+
dbf d0,exlp
jmp grunt
expdef: rte
grunt: move #$2000,sr
.end

View File

@@ -0,0 +1,168 @@
_submit 4EA2 global bss
_morecmd 4EA4 global bss
_autost 4E1C global bss
_usercmd 4E1D global bss
_ccp A4 global text
_patch 4EA6 global bss
cpm 0 global text
_bdos B2 global text
_load68k BE global text
flags 4F1E global bss
TPAB 4F20 global bss
_cmd_tbl 4922 global data
_msg 4952 global data
_msg2 496C global data
_msg3 497E global data
_msg4 4990 global data
_msg5 49A2 global data
_msg6 49B8 global data
_msg7 49C2 global data
_msg8 49DA global data
_msg9 49F8 global data
_msg10 4A08 global data
_msg11 4A1A global data
_msg12 4A30 global data
_msg13 4A48 global data
_lderr1 4A5E global data
_lderr2 4A86 global data
_lderr3 4AA2 global data
_lderror 4AC4 global data
_del 4AD8 global data
_cr_lf 1AC global text
_cpy 1D8 global text
_strcmp 1F8 global text
_copy_cm 240 global text
_prompt 28C global text
_echo_cm 334 global text
_decode 3A4 global text
_fill_fc 7B6 global text
_delim 73A global text
_check_c 4EA global text
_get_cmd 56C global text
_scan_cm 64C global text
_get_par 68A global text
_true_ch 77E global text
_too_man 9DA global text
_find_co A12 global text
_chk_col A4A global text
_dir_cmd A9A global text
_type_cm CA6 global text
_ren_cmd DD8 global text
_era_cmd 1124 global text
_user_cm 1272 global text
_cmd_fil 133E global text
_sub_rea 1858 global text
_dollar 1886 global text
_comment 19CC global text
_transla 1AB0 global text
_submit_ 1C72 global text
_execute 1D8C global text
_main 1EDE global text
_bios1 2124 global text
_bios2 2120 global text
_bios3 211A global text
_bios4 2114 global text
_bios5 210E global text
_bios6 2124 global text
_traphnd 20D6 global text
_swap 2134 global text
_udiv 2140 global text
_constat 2156 global text
_conbrk 2176 global text
_conout 220A global text
_tabout 2278 global text
_cookdou 22B4 global text
_getch 22F6 global text
_conin 2350 global text
_rawconi 238C global text
_prt_lin 23D0 global text
_newline 23FE global text
_backsp 2434 global text
_readlin 24AE global text
_copyrt 4B6E global data
_serial 4B72 global data
_bdosini 26AA global text
_warmboo 274E global text
_prt_err 27B6 global text
_abrt_er 27E8 global text
_ext_err 27FE global text
_ro_err 289E global text
_error 2984 global text
_setexc 29FC global text
_set_tpa 2A70 global text
_rdwrt 2ACC global text
_dir_rd 2B66 global text
_dir_wr 2B84 global text
_dchksum 2BD6 global text
_dirscan 2C12 global text
_setaloc 2D40 global text
_clraloc 2D8C global text
_chkaloc 2DDE global text
_getaloc 2E1C global text
_alloc 2E7E global text
_seldsk 2EF8 global text
_move 3036 global text
_match 3060 global text
_openfil 30E8 global text
_flushit 3148 global text
_close 3186 global text
_close_f 32CC global text
_alltrue 32FE global text
_matchit 330A global text
_search 3326 global text
_create 33B2 global text
_delete 3436 global text
_rename 34D6 global text
_set_att 3550 global text
_extsize 35A2 global text
_setran 35DA global text
_fsize 3618 global text
_getsize 3672 global text
_free_sp 36E2 global text
_blkindx 3750 global text
_blknum 379C global text
_setblk 37DA global text
_do_io 3826 global text
_new_ext 3878 global text
_calcext 3990 global text
_get_rc 39FA global text
_bdosrw 3A44 global text
__bdos 3C1E global text
_tmp_sel 4034 global text
_do_phio 4080 global text
_pgmld 41B2 global text
_initexc 4660 global text
_load_tb 4F74 global bss
init_tbl 48D0 global text
stack 55DC global bss
_sub_ind 55DE global bss
_log_dsk 55E0 global bss
_load_tr 55E2 global bss
_gbls 55E4 global bss
_crit_ds 56D6 global bss
_tail 56D8 global bss
_cur_dis 56DC global bss
_parm 56DE global bss
_dma 5746 global bss
_init 57CA global bss
_sub_use 57D0 global bss
_save_su 57D2 global bss
_subfcb 5854 global bss
_first_s 5878 global bss
_subdma 587A global bss
_tpa_hp 58FA global bss
_user 58FE global bss
_tpa_lp 5900 global bss
_tpa_ht 5904 global bss
_user_pt 5908 global bss
_ro_dsk 590C global bss
_tpa_lt 590E global bss
_autorom 5912 global bss
_subprom 5914 global bss
_end_of_ 5916 global bss
_subcom 5918 global bss
_glb_ind 599A global bss
_chain_s 599E global bss
_index 59A0 global bss
_dirflag 59A2 global bss
_cmdfcb 59A4 global bss

View File

@@ -0,0 +1,288 @@
*****************************************************************
* *
* CP/M-68K Loader BIOS *
* Basic Input/Output Subsystem *
* For ERG 68000 with Tarbell floppy disk controller *
* *
*****************************************************************
.globl _bios * declare external entry point
_bios:
cmpi #nfuncs,d0
bge nogood
lsl #2,d0 * multiply bios function by 4
movea.l 6(pc,d0),a0 * get handler address
jsr (a0) * call handler
nogood:
rts
biosbase:
.dc.l nogood
.dc.l nogood
.dc.l constat
.dc.l conin
.dc.l conout
.dc.l nogood
.dc.l nogood
.dc.l nogood
.dc.l home
.dc.l seldsk
.dc.l settrk
.dc.l setsec
.dc.l setdma
.dc.l read
.dc.l nogood
.dc.l nogood
.dc.l sectran
.dc.l setdma
.dc.l getseg
.dc.l nogood
.dc.l nogood
.dc.l nogood
.dc.l setexc
nfuncs=(*-biosbase)/4
constat: move.b $ffff01,d0 * get status byte
andi.w #2,d0 * data available bit on?
beq noton * branch if not
moveq.l #$1,d0 * set result to true
rts
noton: clr.l d0 * set result to false
rts
conin: bsr constat * see if key pressed
tst d0
beq conin * wait until key pressed
move.b $ffff00,d0 * get key
and.l #$7f,d0 * clear all but low 7 bits
rts
conout: move.b $ffff01,d0 * get status
and.b #$1,d0 * check for transmitter buffer empty
beq conout * wait until our port has aged...
move.b d1,$ffff00 * and output it
rts * and exit
*
* Disk Handlers for Tarbell 1793 floppy disk controller
*
maxdsk = 2 * this BIOS supports 2 floppy drives
dphlen = 26 * length of disk parameter header
iobase = $00fffff8 * Tarbell floppy disk port base address
dcmd = iobase * output port for command
dstat = iobase * input status port
dtrk = iobase+1 * disk track port
dsect = iobase+2 * disk sector port
ddata = iobase+3 * disk data port
dwait = iobase+4 * input port to wait for op finished
dcntrl = iobase+4 * output control port for drive selection
home: clr.b track
rts
seldsk:
* select disk A
clr.b seldrv * select drive A
clr.b selcode * select code is 00 for drv 0, $10 for drv 1
move.l #dph0,d0
selrtn: rts
settrk: move.b d1,track
rts
setsec: move.b d1,sector
rts
sectran:
* translate sector in d1 with translate table pointed to by d2
* result in d0
movea.l d2,a0
ext.l d1
move.b #0(a0,d1),d0
ext.l d0
rts
setdma:
move.l d1,dma
rts
read:
* Read one sector from requested disk, track, sector to dma address
* Retry if necessary, return in d0 00 if ok, else non-zero
move.b #10,errcnt * set up retry counter
rretry:
bsr setup
ori #$88,d3 * OR read command with head load bit
move.b d3,dcmd * output it to FDC
rloop: btst #7,dwait
beq rdone * if end of read, exit
move.b ddata,(a0)+ * else, move next byte of data
bra rloop
rdone:
bsr rstatus * get FDC status
bne rerror
clr.l d0
rts
rerror: bsr errchk * go to error handler
subq.b #1,errcnt
bne rretry
move.l #$ffffffff,d0
rts
setup:
* common read and write setup code
* select disk, set track, set sector were all deferred until now
move.b #$d0,dcmd * clear controller, get status
move.b curdrv,d3
cmp.b seldrv,d3
bne newdrive * if drive not selected, do it
move.b track,d3
cmp.b oldtrk,d3
bne newtrk * if not on right track, do it
clr.l d3 * if head already loaded, no head load delay
btst #5,dstat * if head unloaded, treat as new disk
bne sexit
newdrive:
move.b selcode,dcntrl * select the drive
move.b seldrv,curdrv
newtrk:
bsr chkseek * seek to correct track if required
moveq #4,d3 * force head load delay
sexit:
move.b sector,dsect * set up sector number
move.b track,dtrk * set up track number
move.l dma,a0 * dma address to a0
rts
errchk:
btst.b #4,d7
bne chkseek * if record not found error, reseek
rts
chkseek:
* check for correct track, seek if necessary
bsr readid * find out what track we're on
beq chks1 * if read id ok, skip restore code
restore:
* home the drive and reseek to correct track
move.b #$0B,dcmd * restore command to command port
rstwait:
btst #7,dwait
bne rstwait * loop until restore completed
btst #2,dstat
beq restore * if not at track 0, try again
clr.l d3 * track number returned in d3 from readid
chks1:
move.b d3,dtrk * update track register in FDC
move.b track,oldtrk * update oldtrk
cmp.b track,d3 * are we at right track?
beq chkdone * if yes, exit
move.b track,ddata * else, put desired track in data reg of FDC
move.b #$18,dcmd * and issue a seek command
chks2: btst #7,dwait
bne chks2 * loop until seek complete
move.b dstat,d3 * read status to clear FDC
chkdone:
rts
readid:
* read track id, return track number in d3
move.b #$c4,dcmd * issue read id command
move.b dwait,d7 * wait for intrq
move.b ddata,d3 * track byte to d3
rid2:
btst #7,dwait
beq rstatus * wait for intrq
move.b ddata,d7 * read another byte
bra rid2 * and loop
rstatus:
move.b dstat,d7
andi.b #$9d,d7 * set condition codes
rts
getseg:
move.l #memrgn,d0 * return address of mem region table
rts
setexc:
andi.l #$ff,d1 * do only for exceptions 0 - 255
lsl #2,d1 * multiply exception number by 4
movea.l d1,a0
move.l (a0),d0 * return old vector value
move.l d2,(a0) * insert new vector
rts
.data
seldrv: .dc.b $ff * drive requested by seldsk
curdrv: .dc.b $ff * currently selected drive
track: .dc.b 0 * track requested by settrk
oldtrk: .dc.b 0 * track we were on
sector: .dc.w 0
dma: .dc.l 0
selcode: .dc.b 0 * drive select code
errcnt: .dc.b 10 * retry counter
memrgn: .dc.w 1 * 1 memory region
.dc.l $18000 * load the system at 18000 hex
.dc.l $8000
* disk parameter headers
dph0: .dc.l xlt
.dc.w 0 * dummy
.dc.w 0
.dc.w 0
.dc.l dirbuf * ptr to directory buffer
.dc.l dpb * ptr to disk parameter block
.dc.l 0 * ptr to check vector
.dc.l 0 * ptr to allocation vector
* disk parameter block
dpb: .dc.w 26 * sectors per track
.dc.b 3 * block shift
.dc.b 7 * block mask
.dc.b 0 * extent mask
.dc.b 0 * dummy fill
.dc.w 242 * disk size
.dc.w 63 * 64 directory entries
.dc.w $c000 * directory mask
.dc.w 16 * directory check size
.dc.w 2 * track offset
* sector translate table
xlt: .dc.b 1, 7,13,19
.dc.b 25, 5,11,17
.dc.b 23, 3, 9,15
.dc.b 21, 2, 8,14
.dc.b 20,26, 6,12
.dc.b 18,24, 4,10
.dc.b 16,22
.bss
dirbuf: .ds.b 128 * directory buffer
.end

View File

@@ -0,0 +1,360 @@
*****************************************************************
* *
* CP/M-68K BIOS *
* Basic Input/Output Subsystem *
* For ERG 68000 with Tarbell floppy disk controller *
* *
*****************************************************************
.globl _init * bios initialization entry point
.globl _ccp * ccp entry point
_init: move.l #traphndl,$8c * set up trap #3 handler
clr.l d0 * log on disk A, user 0
rts
traphndl:
cmpi #nfuncs,d0
bcc trapng
lsl #2,d0 * multiply bios function by 4
movea.l 6(pc,d0),a0 * get handler address
jsr (a0) * call handler
trapng:
rte
biosbase:
.dc.l _init
.dc.l wboot
.dc.l constat
.dc.l conin
.dc.l conout
.dc.l lstout
.dc.l pun
.dc.l rdr
.dc.l home
.dc.l seldsk
.dc.l settrk
.dc.l setsec
.dc.l setdma
.dc.l read
.dc.l write
.dc.l listst
.dc.l sectran
.dc.l setdma
.dc.l getseg
.dc.l getiob
.dc.l setiob
.dc.l flush
.dc.l setexc
nfuncs=(*-biosbase)/4
wboot: jmp _ccp
constat: move.b $ffff01,d0 * get status byte
andi.w #2,d0 * data available bit on?
beq noton * branch if not
moveq.l #$1,d0 * set result to true
rts
noton: clr.l d0 * set result to false
rts
conin: bsr constat * see if key pressed
tst d0
beq conin * wait until key pressed
move.b $ffff00,d0 * get key
and.l #$7f,d0 * clear all but low 7 bits
cmpi.b #1,d0
beq break
rts
break:
trap $f
.dc.w 0 * return to MACSBUG
rts
conout: move.b $ffff01,d0 * get status
and.b #$1,d0 * check for transmitter buffer empty
beq conout * wait until our port has aged...
move.b d1,$ffff00 * and output it
rts * and exit
lstout: rts
pun: rts
rdr: rts
listst: move.b #$ff,d0
rts
*
* Disk Handlers for Tarbell 1793 floppy disk controller
*
maxdsk = 2 * this BIOS supports 2 floppy drives
dphlen = 26 * length of disk parameter header
iobase = $00fffff8 * Tarbell floppy disk port base address
dcmd = iobase * output port for command
dstat = iobase * input status port
dtrk = iobase+1 * disk track port
dsect = iobase+2 * disk sector port
ddata = iobase+3 * disk data port
dwait = iobase+4 * input port to wait for op finished
dcntrl = iobase+4 * output control port for drive selection
home: clr.b track
rts
seldsk:
* select disk given by register d1.b
moveq #0,d0
cmp.b #maxdsk,d1 * valid drive number?
bpl selrtn * if no, return 0 in d0
move.b d1,seldrv * else, save drive number
lsl.b #4,d1
move.b d1,selcode * select code is 00 for drv 0, $10 for drv 1
move.b seldrv,d0
mulu #dphlen,d0
add.l #dph0,d0 * point d0 at correct dph
selrtn: rts
settrk: move.b d1,track
rts
setsec: move.b d1,sector
rts
sectran:
* translate sector in d1 with translate table pointed to by d2
* result in d0
movea.l d2,a0
ext.l d1
move.b #0(a0,d1),d0
ext.l d0
rts
setdma:
move.l d1,dma
rts
read:
* Read one sector from requested disk, track, sector to dma address
* Retry if necessary, return in d0 00 if ok, else non-zero
move.b #10,errcnt * set up retry counter
rretry:
bsr setup
ori #$88,d3 * OR read command with head load bit
move.b d3,dcmd * output it to FDC
rloop: btst #7,dwait
beq rdone * if end of read, exit
move.b ddata,(a0)+ * else, move next byte of data
bra rloop
rdone:
bsr rstatus * get FDC status
bne rerror
clr.l d0
rts
rerror: bsr errchk * go to error handler
subq.b #1,errcnt
bne rretry
move.l #$ffffffff,d0
rts
write:
* Write one sector to requested disk, track, sector from dma address
* Retry if necessary, return in d0 00 if ok, else non-zero
move.b #10,errcnt * set up retry counter
wretry:
bsr setup
ori #$a8,d3 * OR write command with head load bit
move.b d3,dcmd * output it to FDC
wloop: btst #7,dwait
beq wdone * if end of read, exit
move.b (a0)+,ddata * else, move next byte of data
bra wloop
wdone:
bsr rstatus * get FDC status
bne werror
clr.l d0
rts
werror: bsr errchk * go to error handler
subq.b #1,errcnt
bne wretry
move.l #$ffffffff,d0
rts
setup:
* common read and write setup code
* select disk, set track, set sector were all deferred until now
move.b #$d0,dcmd * clear controller, get status
move.b curdrv,d3
cmp.b seldrv,d3
bne newdrive * if drive not selected, do it
move.b track,d3
cmp.b oldtrk,d3
bne newtrk * if not on right track, do it
clr.l d3 * if head already loaded, no head load delay
btst #5,dstat * if head unloaded, treat as new disk
bne sexit
newdrive:
move.b selcode,dcntrl * select the drive
move.b seldrv,curdrv
newtrk:
bsr chkseek * seek to correct track if required
moveq #4,d3 * force head load delay
sexit:
move.b sector,dsect * set up sector number
move.b track,dtrk * set up track number
move.l dma,a0 * dma address to a0
rts
errchk:
btst.b #4,d7
bne chkseek * if record not found error, reseek
rts
chkseek:
* check for correct track, seek if necessary
bsr readid * find out what track we're on
beq chks1 * if read id ok, skip restore code
restore:
* home the drive and reseek to correct track
move.b #$0B,dcmd * restore command to command port
rstwait:
btst #7,dwait
bne rstwait * loop until restore completed
btst #2,dstat
beq restore * if not at track 0, try again
clr.l d3 * track number returned in d3 from readid
chks1:
move.b d3,dtrk * update track register in FDC
move.b track,oldtrk * update oldtrk
cmp.b track,d3 * are we at right track?
beq chkdone * if yes, exit
move.b track,ddata * else, put desired track in data reg of FDC
move.b #$18,dcmd * and issue a seek command
chks2: btst #7,dwait
bne chks2 * loop until seek complete
move.b dstat,d3 * read status to clear FDC
chkdone:
rts
readid:
* read track id, return track number in d3
move.b #$c4,dcmd * issue read id command
move.b dwait,d7 * wait for intrq
move.b ddata,d3 * track byte to d3
rid2:
btst #7,dwait
beq rstatus * wait for intrq
move.b ddata,d7 * read another byte
bra rid2 * and loop
rstatus:
move.b dstat,d7
andi.b #$9d,d7 * set condition codes
rts
flush:
clr.l d0 * return successful
rts
getseg:
move.l #memrgn,d0 * return address of mem region table
rts
getiob:
rts
setiob:
rts
setexc:
andi.l #$ff,d1 * do only for exceptions 0 - 255
cmpi #47,d1
beq noset * this BIOS doesn't set Trap 15
cmpi #9,d1 * or Trace
beq noset
lsl #2,d1 * multiply exception nmbr by 4
movea.l d1,a0
move.l (a0),d0 * return old vector value
move.l d2,(a0) * insert new vector
noset: rts
.data
seldrv: .dc.b $ff * drive requested by seldsk
curdrv: .dc.b $ff * currently selected drive
track: .dc.b 0 * track requested by settrk
oldtrk: .dc.b 0 * track we were on
sector: .dc.w 0
dma: .dc.l 0
selcode: .dc.b 0 * drive select code
errcnt: .dc.b 10 * retry counter
memrgn: .dc.w 1 * 1 memory region
.dc.l $800 * starts at 800 hex
.dc.l $17800 * goes until 18000 hex
* disk parameter headers
dph0: .dc.l xlt
.dc.w 0 * dummy
.dc.w 0
.dc.w 0
.dc.l dirbuf * ptr to directory buffer
.dc.l dpb * ptr to disk parameter block
.dc.l ckv0 * ptr to check vector
.dc.l alv0 * ptr to allocation vector
dph1: .dc.l xlt
.dc.w 0 * dummy
.dc.w 0
.dc.w 0
.dc.l dirbuf * ptr to directory buffer
.dc.l dpb * ptr to disk parameter block
.dc.l ckv1 * ptr to check vector
.dc.l alv1 * ptr to allocation vector
* disk parameter block
dpb: .dc.w 26 * sectors per track
.dc.b 3 * block shift
.dc.b 7 * block mask
.dc.b 0 * extent mask
.dc.b 0 * dummy fill
.dc.w 242 * disk size
.dc.w 63 * 64 directory entries
.dc.w $c000 * directory mask
.dc.w 16 * directory check size
.dc.w 2 * track offset
* sector translate table
xlt: .dc.b 1, 7,13,19
.dc.b 25, 5,11,17
.dc.b 23, 3, 9,15
.dc.b 21, 2, 8,14
.dc.b 20,26, 6,12
.dc.b 18,24, 4,10
.dc.b 16,22
.bss
dirbuf: .ds.b 128 * directory buffer
ckv0: .ds.b 16 * check vector
ckv1: .ds.b 16
alv0: .ds.b 32 * allocation vector
alv1: .ds.b 32
.end

View File

@@ -0,0 +1 @@
lo68 -r -o cpm.rel -ucpm cpmlib biosa.o bios.o

View File

@@ -0,0 +1,41 @@
.text
.globl _bios
.globl _biosinit
.globl _cbios
.globl _dskia
.globl _dskic
.globl _setimask
*
*
*
*
_bios: link a6,#0
move.l d2,-(a7)
move.l d1,-(a7)
move.w d0,-(a7)
move #$2000,sr
lea _dskia,a0
move.l a0,$3fc
jsr _cbios
unlk a6
rts
*
_dskia: link a6,#0
movem.l d0-d7/a0-a5,-(a7)
jsr _dskic
movem.l (a7)+,d0-d7/a0-a5
unlk a6
rte
*
_setimask: move sr,d0
lsr #8,d0
and.l #7,d0
move sr,d1
ror.w #8,d1
and.w #$fff8,d1
add.w 4(a7),d1
ror.w #8,d1
move d1,sr
rts
*
.end

View File

@@ -0,0 +1,3 @@
#define LOADER 1
#define CTLTYPE 0
#define MEMDSK 0

View File

@@ -0,0 +1,9 @@
pip biostype.h=loadbios.h
cp68 bios.c bios.i
c068 bios.i bios.ic bios.st
era bios.i
era bios.st
c168 bios.ic bios.s -l
as68 -u -l bios.s
as68 -u -l ldbiosa.s
pip ldbios.o=bios.o

View File

@@ -0,0 +1 @@
lo68 -s -t0 -uldr -o cpmldr.sys booter.o ldrlib ldbiosa.o ldbios.o

View File

@@ -0,0 +1,3 @@
#define LOADER 0
#define CTLTYPE 0
#define MEMDSK 4

View File

@@ -0,0 +1,8 @@
pip biostype.h=normbios.h
cp68 bios.c bios.i
c068 bios.i bios.ic bios.st
era bios.i
era bios.st
c168 bios.ic bios.s -l
as68 -u -l bios.s
as68 -u -l biosa.s

View File

@@ -0,0 +1,194 @@
*********************************************************
* *
* Program to Write Boot Tracks for CP/M-68K (tm) *
* *
* Copyright Digital Research 1982 *
* *
*********************************************************
*
*
*
prntstr = 9 BDOS Functions
dseldsk = 14
open = 15
readseq = 20
dsetdma = 26
*
seldsk = 9 BIOS Functions
settrk = 10
setsec = 11
isetdma = 12
write = 14
sectran = 16
flush = 21
*
bufcnt = $80
bufsize = $80*bufcnt
*
.text
*
start: link a6,#0
move.l 8(a6),a0 base page address
lea $5c(a0),a1
move.l a1,fcb
clr.b hflag
add #$81,a0 first character of command tail
scan: cmpi.b #$20,(a0)+ skip over blanks
beq scan
sub.l #1,a0
scan1: tst.b (a0)
beq erxit
cmpi.b #$2d,(a0)+ check for -H flag
bne nohyph
cmpi.b #$48,(a0)+
bne erxit
tst.b hflag
bne erxit
move.b #$ff,hflag
sub.l #$24,fcb change to 2nd default fcb
bra scan
nohyph: cmpi.b #$20,(a0)
bne scan1
scan2: cmpi.b #$20,(a0)+
beq scan2
cmpi.b #$61,-(a0) get disk letter
blt upper upshift
sub #$20,(a0)
upper: cmpi.b #$41,(a0) compare with range A - P
blt erxit
cmpi.b #$50,(a0)
bgt erxit
move.b (a0),d0
ext.w d0 put disk letter into range 0 - 15
sub.w #$41,d0
move.w d0,dsk
*
* open file to copy
*
move.w #open,d0
move.l fcb,d1
trap #2
cmpi.w #$00ff,d0
bne openok
move.l #opnfl,d1
jmp erx
openok: move.l fcb,a0
clr.b 32(a0)
*
* read
*
move.l #buf,d2
clr.w count
rloop: move.w #dsetdma,d0
move.l d2,d1
trap #2
move.w #readseq,d0
move.l fcb,d1
trap #2
tst.w d0
bne wrtout
add.l #128,d2
add.w #1,count
cmpi.w #bufcnt,count
bgt bufoflx
bra rloop
*
* write
*
wrtout: move.w #seldsk,d0 select the disk
move.w dsk,d1
clr.b d2
trap #3
tst.l d0 check for select error
beq selerx
move.l d0,a0
move.l 14(a0),a0 get DPB address
move.w (a0),spt get sectors per track
move.w 14(a0),off get offset
clr.w trk start at trk 0
move.w #1,sect start at sector 1
lea buf,a0
tst.b hflag
bne wrt1
cmpi.w #$601a,(a0)
bne wrt1
add.l #28,a0
wrt1: move.l a0,bufp
*
wloop: tst.w count
beq exit
move.w sect,d1 check for end-of-track
cmp.w spt,d1
ble sok
move.w #1,sect advance to new track
move.w trk,d0
add.w #1,d0
move.w d0,trk
cmp.w off,d0
bge oflex
sok: move.w #settrk,d0 set the track
move.w trk,d1
trap #3
move.w sect,d1 set sector
move.w #setsec,d0
trap #3
move.w #isetdma,d0 set up dma address for write
move.l bufp,d1
trap #3
move.w #write,d0 and write
clr.w d1
trap #3
tst.w d0 check for write error
bne wrterx
add #1,sect increment sector number
sub #1,count
add.l #128,bufp
bra wloop
*
exit: move.w #flush,d0 exit location - flush bios buffers
trap #3
unlk a6
rts and exit to CCP
*
erxit: move.l #erstr,d1 miscellaneous errors
erx: move.w #prntstr,d0 print error message and exit
trap #2
bra exit
*
selerx: move.l #selstr,d1 disk select error
bra erx
wrterx: move.l #wrtstr,d1 disk write error
bra erx
bufoflx: move.l #bufofl,d1 buffer overflow
bra erx
oflex: move.l #trkofl,d1
bra erx
*
*
.bss
*
.even
*
buf: .ds.b bufsize+128
*
fcb: .ds.l 1 fcb address
spt: .ds.w 1 sectors per track
sect: .ds.w 1 current sector
trk: .ds.w 1 current track
dsk: .ds.w 1 selected disk
off: .ds.w 1 1st track of non-boot area
count: .ds.w 1
bufp: .ds.l 1
hflag: .ds.b 1
*
.data
*
erstr: .dc.b 'Invalid Command Line',13,10,'$'
selstr: .dc.b 'Select Error',13,10,'$'
wrtstr: .dc.b 'Write Error',13,10,'$'
opnfl: .dc.b 'Cannot Open Source File',13,10,'$'
bufofl: .dc.b 'Buffer Overflow',13,10,'$'
trkofl: .dc.b 'Too Much Data for System Tracks',13,10,'$'
*
*
.end

View File

@@ -0,0 +1 @@
reloc -b$1 cpm.rel cpm.sys

View File

@@ -0,0 +1,17 @@
vax biosa.s s
vax biostyps.h s
vax booter.s s
vax bios.c s
vax eldbios.s s
vax ergbios.s s
vax lcpm.sub s
vax biostype.h s
vax ldbiosa.s s
vax loadbios.sub s
vax makeldr.sub s
vax normbios.h s
vax normbios.sub s
vax putboot.s s
vax relcpm.sub s
vax loadbios.h s
vax up1.sub s

View File

@@ -0,0 +1,14 @@
$ bios
$ set noon
$ !
$ ! VMS build file for EXORmacs bios using cross tools
$ !
$ copy loadbios.h biostype.h
$ cc68 bios
$ rename bios.o ldbios.o
$ as68 -u -l ldbiosa.s
$ as68 -u -l booter.s
$ copy normbios.h biostype.h
$ cc68 bios
$ as68 -u -l biosa.s
$ pur biostype.h

View File

@@ -0,0 +1,20 @@
$ set noon
$ vsend BIOS.C
$ vsend BIOSA.S
$ vsend BIOSTYPE.H
$ vsend BIOSTYPS.H
$ vsend BOOTER.S
$ vsend ELDBIOS.S
$ vsend ERGBIOS.S
$ vsend LCPM.SUB
$ vsend LDBIOSA.S
$ vsend LOADBIOS.H
$ vsend LOADBIOS.SUB
$ vsend MAKELDR.SUB
$ vsend NORMBIOS.H
$ vsend NORMBIOS.SUB
$ vsend PUTBOOT.S
$ vsend RELCPM.SUB
$ vsend UP1.SUB
$ vsend VMAKE.COM
$ vsend done

View File

@@ -0,0 +1,152 @@
/********************************************************
* *
* CP/M-68K header file *
* Copyright (c) 1982 by Digital Research, Inc. *
* Structure definitions for BDOS globals *
* and BDOS data structures *
* *
********************************************************/
/**************************************************************************
The BDOS data structures, especially those relating to global variables,
are structured in a way that hopefully will enable this BDOS, in the future,
to easily become a re-entrant multi-tasking file system. Consequently,
the BDOS global variables are divided into two classes. Those that are
truly global, even in the case of multiple tasks using the file system
concurrently, are simply declared as global variables in bdosmain.c.
Only a few "globals" are really global in this sense.
The majority of the "global" variables are actually state variables that
relate to the state of the task using the file system. In CP/M-68K, these
are "global", since there's only one task, but in a multi-thread model they're
not. These type of variables are put into a data structure, with the
intention that in the multi-task environment this structure will be based.
The following declarations take this philosophy into account, and define
a simple structure for the single thread environment while leaving the
possibilities open for the multi-thread environment.
****************************************************************************/
#define snglthrd TRUE
/* TRUE for single-thread environment
FALSE to create based structure for re-entrant model */
#if snglthrd
#define GBL gbls
/* In single thread case, GBL just names
the structure */
#define BSETUP EXTERN struct stvars gbls;
/* and BSETUP defines the extern structure */
#endif
#if ! snglthrd
#define GBL (*statep)
/* If multi-task, state vars are based */
#define BSETUP REG struct stvars *statep; \
statep = &gbls;
/* set up pointer to state variables */
/* This is intended as an example to show the intent */
#endif
/* Note that there are a few critical regions in the file system that must
execute without interruption. They pertain mostly to the manipulation of
the allocation vector. This isn't a problem in a single-thread model, but
must be provided for in a multi-tasking file system. Consequently, the
primitives LOCK and UNLOCK are defined and used where necessary in the
file system. For the single thread model, they are null routines */
#define LOCK /**/
#define UNLOCK /**/
/* Be sure LOCK and UNLOCK are implemented to allow recursive calls to LOCK.
That is, if a process that calls LOCK already owns the lock, let it proceed,
but remember that only the outer-most call to UNLOCK really releases the
file system. */
#define VERSION 0x2022 /* Version number for CP/M-68K */
#define robit 0 /* read-only bit in file type field of fcb */
#define SECLEN 128 /* length of a CP/M sector */
/* File Control Block definition */
struct fcb
{
UBYTE drvcode; /* 0 = default drive, 1..16 are drives A..P */
UBYTE fname[8]; /* File name (ASCII) */
UBYTE ftype[3]; /* File type (ASCII) */
UBYTE extent; /* Extent number (bits 0..4 used) */
UBYTE s1; /* Reserved */
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
union
{
UBYTE small[16]; /* 16 block numbers of 1 byte */
WORD big[8]; /* or 8 block numbers of 1 word */
} dskmap;
UBYTE cur_rec; /* current record field */
UBYTE ran0; /* random record field (3 bytes) */
UBYTE ran1;
UBYTE ran2;
};
/* Declaration of directory entry */
struct dirent
{
UBYTE entry; /* 0 - 15 for user numbers, E5 for empty */
/* the rest are reserved */
UBYTE fname[8]; /* File name (ASCII) */
UBYTE ftype[3]; /* File type (ASCII) */
UBYTE extent; /* Extent number (bits 0..4 used) */
UBYTE s1; /* Reserved */
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
union
{
UBYTE small[16]; /* 16 block numbers of 1 byte */
WORD big[8]; /* or 8 block numbers of 1 word */
} dskmap;
};
/* Declaration of disk parameter tables */
struct dpb /* disk parameter table */
{
UWORD spt; /* sectors per track */
UBYTE bsh; /* block shift factor */
UBYTE blm; /* block mask */
UBYTE exm; /* extent mask */
UBYTE dpbdum; /* dummy byte for fill */
UWORD dsm; /* max disk size in blocks */
UWORD drm; /* max directory entries */
UWORD dir_al; /* initial allocation for dir */
UWORD cks; /* number dir sectors to checksum */
UWORD trk_off; /* track offset */
};
struct dph /* disk parameter header */
{
UBYTE *xlt; /* pointer to sector translate table */
UWORD hiwater; /* high water mark for this disk */
UWORD dum1; /* dummy (unused) */
UWORD dum2;
UBYTE *dbufp; /* pointer to 128 byte directory buffer */
struct dpb *dpbp; /* pointer to disk parameter block */
UBYTE *csv; /* pointer to check vector */
UBYTE *alv; /* pointer to allocation vector */
};
/* Declaration of structure containing "global" state variables */
struct stvars
{
struct dph *dphp; /* pointer to disk parm hdr for cur disk */
struct dirent *dirbufp; /* pointer for directory buff for process */
/* stored here so that each process can */
/* have a separate dirbuf. */
struct dpb *parmp; /* pointer to disk parameter block for cur */
/* disk. Stored here to save ref calc */
UBYTE *dmaadr; /* Disk dma address */
};

View File

@@ -0,0 +1,91 @@
*****************************************************************
* *
* CP/M-68K Interface Module for the Loader BDOS *
* For "C" version of CP/M-68K *
* *
* Copyright (c) 1982 Digital Research, Inc. *
* *
* Version 0.1 -- September 22, 1982 *
* *
*****************************************************************
* Declare Public Routines
.globl _bios1 * 5 BIOS entry points from BDOS
.globl _bios2
.globl _bios3
.globl _bios4
.globl _bios5
.globl _swap * byte swapper
.globl _udiv * unsigned divide routine
* External Routine
.globl _bios
*
* BIOS Interface Routines
*
*
* Note - there are 5 BIOS entry points from the BDOS, labelled BIOS1 -
* BIOS5, depending on the parameters passed.
_bios5:
* For BIOS functions sectran and set exception vector
* Has function number and 2 parameters, a word followed by a long word
move.l 8(sp),d2 * get 2nd parameter (long word)
bra _bios2 * join common routine
_bios4:
* For BIOS function seldsk
* Has function number followed by 2 word parameters
move.w 8(sp),d2 * get 2nd parameter (word)
bra _bios2 * join common routine
_bios3:
* For BIOS function set dma
* Has function number followed by 1 long parameter
move.l 6(sp),d1 * get long word parameter
bra _bios1 * join common routine
_bios2:
* For all BIOS functions with a word parameter
* Word parameter follows function number
move.w 6(sp),d1 * get 1st parameter (word)
_bios1:
* For all BIOS functions that have no parameter other than function number
move.w 4(sp),d0 * get function number
movem.l d3-d7/a3-a6,-(sp)
jsr _bios * do BIOS call
movem.l (sp)+,d3-d7/a3-a6
* * returns value in d0
rts
*
* Utility Subroutines
*
_swap:
* Swap bytes of a word, return swapped value in d0
move.b 5(sp),d0
lsl #8,d0
move.b 4(sp),d0
rts
_udiv:
* Unsigned divide.
* Inputs: Long dividend, unsigned word divisor, address of return structure
* Return: In structure passed, unsigned word quotient, unsigned word remainder
move.l a0, -(sp) * save a0
move.l 14(sp), a0 * get address of return structure
move.l 8(sp), d0 * get dividend
divu 12(sp), d0 * do the divide
move.w d0, (a0)+ * store quotient
swap d0
move.w d0, (a0) * store remainder
move.l (sp)+, a0 * restore a0
rts
.end

View File

@@ -0,0 +1,93 @@
/****************************************************************
* *
* CP/M-68K Loader BDOS Main Routine *
* *
* This is the main routine for the Loader BDOS for *
* CP/M-68K. It has one entry point, _bdos. *
* the assembly language trap handler found in bdosif.s. *
* There are two parameters: a function number (integer) *
* and an information parameter, potentially a long word *
* The BDOS can potentially return a pointer, long word, *
* or word *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "biosdef.h" /* Declarations of BIOS functions */
/* Serial Number and Copyright Notice */
char *copyrt="CP/M-68K(tm), Version 1.1, Copyright (c) 1983, Digital Research";
char *serial = "XXXX-0000-654321";
/* Declare EXTERN functions */
EXTERN WORD seldisk(); /* Select disk */
EXTERN BOOLEAN openfile(); /* Open File */
EXTERN UWORD dirscan(); /* General directory scanning routine */
EXTERN UWORD seqread(); /* Sequential disk read */
/* Declare the "state variables". These are globals for the single-thread
version of the file system, but are put in a structure so they can be
based, with a pointer coming from the calling process */
GLOBAL struct stvars gbls;
/****************************************************************
* *
* _bdos MAIN ROUTINE *
* *
* Called with _bdos(func, info, infop) *
* *
* Where: *
* func is the BDOS function number (d0.w) *
* info is the word parameter (d1.w) *
* infop is the pointer parameter (d1.l) *
* note that info is the word form of infop*
* *
****************************************************************/
UWORD _bdos(func,info,infop)
REG WORD func; /* BDOS function number */
REG UWORD info; /* d1.w word parameter */
REG UBYTE *infop; /* d1.l pointer parameter */
{
switch (func) /* switch on function number */
{
case 2: bconout((UBYTE)info); /* console output */
break;
case 14: return(seldisk(info)); /* select disk */
case 15: infop->drvcode = 0; /* open file */
infop->extent = 0;
infop->s2 = 0;
return(dirscan(openfile, infop));
case 20: infop->drvcode = 0; /* read sequential */
return(seqread(infop));
case 26: GBL.dmaadr = infop; /* set dma address */
break;
default: return(0xffff); /* bad function number */
/* break; */
}; /* end of switch statement */
return(0); /* return the BDOS return value */
} /* end _bdos */

View File

@@ -0,0 +1,208 @@
/****************************************************************
* *
* CP/M-68K BDOS Disk Read/Write Module *
* *
* This module contains functions to perform sequential *
* or random access read or write to the disk for CP/M-68K *
* *
* It includes the following external functions: *
* *
* seqread() - sequential disk read *
* *
* *
* Compiled with Alcyon C on the VAX *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
/* External function definitions */
EXTERN UWORD rdsec(); /* disk read routine */
EXTERN WORD swap(); /* assembly language byte swapper */
EXTERN UWORD dirscan(); /* directory scanning routine */
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
/**********************************************************/
/* First, some utility functions used by seqio and ranio */
/**********************************************************/
/******************************
* FCB block number routines *
******************************/
WORD blkindx(fcbp)
/* return index into fcb disk map */
REG struct fcb *fcbp; /* pointer to fcb */
{
REG struct dpb *dparmp; /* pointer to disk parameter block */
REG WORD i;
REG WORD blkshf;
BSETUP
dparmp = GBL.parmp;
blkshf = dparmp->bsh;
i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
}
UWORD blknum(fcbp, index, wrdfcb)
/* return block number in fcb indicated by index */
REG struct fcb *fcbp; /* pointer to fcb */
REG WORD index; /* index into disk map of fcb */
WORD wrdfcb; /* boolean, fcb disk map of words? */
{
if (wrdfcb)
return( swap(fcbp->dskmap.big[index]) );
else return( UBWORD(fcbp->dskmap.small[index]) );
}
/*********************
* disk read routine *
*********************/
UWORD do_io(block, rcrd)
UWORD block; /* block number */
UBYTE rcrd; /* record number */
{
LONG lsec;
REG struct dpb *dparmp;
BSETUP
dparmp = GBL.parmp; /* init dpb pointer */
lsec = ((LONG)block << (dparmp->bsh)) +
(LONG)(rcrd & (dparmp->blm));
return( rdsec(lsec, GBL.dmaadr) );
}
/*******************************************
* routine for crossing extent boundaries *
*******************************************/
WORD new_ext(fcbp)
/* If sequential I/O, open the next extent */
REG struct fcb *fcbp; /* pointer to fcb */
{
REG UBYTE mod; /* module number */
REG UBYTE ext; /* extent number */
BSETUP
mod = (fcbp->s2) & 0x3f;
ext = (fcbp->extent) + 1; /* for sequential, incr extent */
if (ext >= 32)
{
ext = 0;
mod += 1;
}
if (mod >= 64) return(6); /* past maximum file size */
if ( mod == ((fcbp->s2) & 0x3f) )
if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
{ /* we're in same logical extent */
fcbp->extent = ext;
return(0);
}
/* Extent or Module numbers don't match */
/* Close the old extent and open a new one */
fcbp->s2 = mod;
fcbp->extent = ext;
if ( dirscan(openfile, fcbp) >= 255 ) /* open new extent */
return(4); /* reading unwritten extent */
return(0);
}
/************************************
* Routine to calculate the maximum *
* extent number of an FCB in a *
* extent-folded environment *
************************************/
UWORD calcext(fcbp)
REG struct fcb *fcbp;
{
REG UWORD i;
REG BYTE *p;
BSETUP
i = 15;
p = &(fcbp->dskmap.small[16]);
do
{
if (*--p) break;
i -= 1;
} while (i);
/* Now i contains the index of the last non-zero block in the FCB */
if ((GBL.parmp)->dsm > 255) i >>= 1;
i >>= 7 - ((GBL.parmp)->bsh);
return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
}
/*********************************
* Routine to get the actual *
* record count of the currently *
* active logical extent of a FCB *
*********************************/
UWORD get_rc(fcbp)
REG struct fcb *fcbp;
{
REG UWORD ext;
ext = calcext(fcbp); /* find last active extent in fcb */
if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
/* if this is the last active fcb, return fcb's rc */
else if (ext > fcbp->extent) return(128);
/* if the fcb has more extents past this one, then */
/* the current one is logically full */
else return (0);
/* if we seeked past the last active extent, rc = 0 */
}
/************************
* seqread entry point *
************************/
UWORD seqread(fcbp)
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
{
REG UWORD block; /* block number from fcb */
REG WORD index; /* index into disk map of fcb */
REG WORD parm; /* parameter to do-io */
REG WORD bigfile; /* file system is in word mode */
BSETUP
bigfile = ((GBL.parmp)->dsm) & ~0xff;
if (fcbp->cur_rec == 128)
{ /* time to try next extent */
if ( new_ext(fcbp) )
return(1); /* if can't open new extent, error */
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
}
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
return(1); /* this is end of file */
index = blkindx(fcbp); /* get index into fcb disk map */
block = blknum(fcbp, index, bigfile);
if ( ! block) /* no data allocated at that position */
return(1); /* reading unwritten data */
return( do_io(block, (fcbp->cur_rec)++) );
}

View File

@@ -0,0 +1,45 @@
/********************************************************
* *
* BIOS definitions for CP/M-68K *
* *
* Copyright (c) 1982 Digital Research, Inc. *
* *
* This include file simply defines the BIOS calls *
* *
********************************************************/
EXTERN UBYTE bios1(); /* used for character I/O functions */
EXTERN bios2(); /* parm1 is word, no return value */
EXTERN bios3(); /* used for set dma only */
/* parm1 is a pointer, no return */
EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
/* words, returns a pointer to dph */
EXTERN UWORD bios5(); /* for sectran and set exception */
#define bwboot() bios1(1) /* warm boot */
#define bconstat() bios1(2) /* console status */
#define bconin() bios1(3) /* console input */
#define bconout(parm) bios2(4,parm) /* console output parm */
#define blstout(parm) bios2(5,parm) /* list device output */
#define bpun(parm) bios2(6,parm) /* punch char output */
#define brdr() bios1(7) /* reader input */
#define bhome() bios1(8) /* recalibrate drive */
#define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
/* select disk and return info */
#define bsettrk(parm) bios2(10,parm) /* set track on disk */
#define bsetsec(parm) bios2(11,parm) /* set sector for disk */
#define bsetdma(parm) bios3(12,parm) /* set dma address */
#define bread() bios1(13) /* read sector from disk */
#define bwrite(parm) bios2(14,parm) /* write sector to disk */
#define blistst() bios1(15) /* list device status */
#define bsectrn(parm1,parm2) bios5(16,parm1,parm2)
/* sector translate */
#define bgetseg() bios1(18) /* get memory segment tbl */
#define bgetiob() bios1(19) /* get I/O byte */
#define bsetiob(parm) bios2(20,parm) /* set I/O byte */
#define bflush() bios1(21) /* flush buffers */
#define bsetvec(parm1,parm2) bios5(22,parm1,parm2)
/* set exception vector */

View File

@@ -0,0 +1,59 @@
***************************************
* Information to go on the 256 byte *
* boot sector of an ExorMacs *
***************************************
.text
.dc.l $4000 * starting stack pointer
.dc.l start * starting program counter
.dc.w 1 * garbage
.dc.w 1 * length of SAT
.dc.l 2 * secondary directory start
.dc.l 0 * primary directory PSN list start
.dc.l 0 * start of boot loader
.dc.w 26 * length of boot loader
.dc.l $0 * boot execution address
.dc.l $0 * boot load address
.dc.b '9/30' * generation date
.dc.b 'CP/M-68K of 9/30/82 ' * volume descriptor
.dc.b '0020' * version/revision
.dc.w $0a484 * checksum (god help us)
.dc.l $0f1e2d3c * diagnostic test pattern
.dc.l $4b5a6978
.dc.l $8796a5b4
.dc.l $c3d2e1f0
.dc.l $0f1e2d3c * diagnostic test pattern
.dc.l $4b5a6978
.dc.l $8796a5b4
.dc.l $c3d2e1f0
.dc.l $4f8f0f07 * diagnostic test pattern
.dc.l $0b0d0e06
.dc.l $0a0c0408
.dc.l $04020100
.dc.l 00, 00, 00, 00 * diagnostic test pattern
.dc.l 0 * diagnostic test area directory
.dc.l 0 * start of dump area
.dc.w 0 * length of dump area
.dc.l 0 * start of sector lockout table
.dc.w 0 * length of sector lockout table
.dc.l 0,0,0,0,0,0,0 * unused, reserved
.dc.l 0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0
.dc.b 'EXORMACS' * let's hear it for Motorola
*
* end of volume id
*
* begin boot info proper
*
.ds.b $300 * skip over exception vectors
.even
start: move #$2700,sr
move.l #$8,a0
move.w #253,d0
exlp: move.l #expdef,(a0)+
dbf d0,exlp
jmp grunt
expdef: rte
grunt: move #$2000,sr
.end

View File

@@ -0,0 +1,174 @@
/****************************************************************
* *
* CP/M-68K Loader *
* *
* This is the main routine for the CP/M-68K Loader. *
* It has one entry point, ldcpm, which is called from *
* the assembly language routine called startld found in *
* ldrif.s. startld just sets up the stack. *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#define ALCYON TRUE /* TRUE if compiling with the ALCYON 68K C compiler */
#define SECLEN 128 /* CP/M sector length */
/* Declare EXTERN functions */
EXTERN WORD _bdos(); /* Loader BDOS entry point */
EXTERN startld(); /* Assembly routine to set up stack & retry */
EXTERN BYTE *bios1(); /* bios entry point for get segment table */
EXTERN move(); /* general purpose byte mover */
#define conout(ch) _bdos(2,ch)
#define seldsk(dsk) _bdos(14,dsk)
#define open(fcbp) _bdos(15,0,fcbp)
#define read(fcbp) _bdos(20,0,fcbp)
#define setdma(p) _bdos(26,0,p)
/* Define the data structures used in ldcpm */
struct fcb
{
UBYTE drvcode; /* drive code, must be 0 for loader BDOS */
/* (auto disk select not supported) */
UBYTE fname[11]; /* includes file name and type fields */
UBYTE sys_info[4]; /* ex, s1, s2, rc. These are don't cares */
UBYTE dskmap[16]; /* disk map, also a don't care */
UBYTE cur_rec; /* current record field */
};
struct hdr
{
WORD magic; /* magic number. We only recognize 0x601a */
LONG size[5]; /* sizes of code, data, bss, sym tbl, stack */
BYTE *tstart; /* start address of text segment */
WORD rlbflg; /* relocation bits suppressed flag */
};
struct segtbl
{ /* memory segment table from LDRBIOS */
WORD entrys; /* number of segments, must be 1 */
BYTE *start; /* low memory address */
LONG length; /* length of segment */
};
/**********************/
/* Global Variables */
/**********************/
BYTE buffer[SECLEN]; /* 128 byte dma buffer to read program headers */
/* We need 2 FCB's: one to read CPM.SYS and one to read BIOS.SYS */
/* Unfortunately, due to a bug in the Alcyon compiler, we can't initialize */
/* them in a straightforward way. So: */
#if ALCYON
struct fcb cpmfcb =
{ 0x0043, 0x504d, 0x2020, 0x2020, 0x2053, 0x5953, /* drive, name, and type */
0,0,0,0,0,0,0,0,0,0,0 /* the rest of the fcb */
};
#else
struct fcb cpmfcb =
{ (BYTE)0 /* drive code */
'CPM SYS', /* file name */
0,0,0,0,0,0,0,0,0,0 /* the rest of the fcb */
0,0,0,0,0,0,0,0,0,0,0
};
#endif
/**************************/
/* Utility Routines */
/**************************/
pstring(p)
/* print string */
REG BYTE *p;
{
while (*p) conout(*p++);
}
badload(errtype)
/* Load failed. Print message and try again */
REG WORD errtype;
{
REG WORD i;
switch (errtype)
{
case 0: pstring("\r\nBoot error.");
startld();
case 1: pstring("\n\rOpen or Read error on ");
break;
case 2: pstring("\n\rBad file format on ");
}
pstring("CPM.SYS");
startld();
}
/********************
* load subroutine *
********************/
BYTE *load(fcbp)
/* load the file pointed to by fcbp and return pointer to load point */
REG struct fcb *fcbp;
{
REG BYTE *p;
REG struct hdr *hp;
REG LONG length;
setdma( buffer );
if ( open(fcbp) >= 255 ) badload(1);
fcbp->cur_rec = 0;
if ( read(fcbp) ) badload(1);
hp = buffer;
if ( (hp->magic != 0x601a) || ! (hp->rlbflg) )
badload(2);
p = hp->tstart;
length = hp->size[0] + hp->size[1];
move(&buffer[sizeof *hp], p, SECLEN - (sizeof *hp));
/* move the first record minus header to load point */
p += SECLEN - (sizeof *hp);
length -= SECLEN - (sizeof *hp);
while (length > 0L)
{
setdma(p);
if ( read(fcbp) ) badload(1);
p += SECLEN;
length -= SECLEN;
}
return(hp->tstart);
}
/***************************
* ldcpm main routine *
***************************/
ldcpm()
{
WORD (*gocpm)();
if (seldsk(0)) badload(0);
gocpm = load(&cpmfcb); /* load the CP/M system */
pstring("\r\n\nCP/M-68K(tm) Version 1.2 Alpha 8/21/83 ");
pstring("\n\rCopyright (c) 1982 Digital Research, Inc.\r\n\n");
(*gocpm)(); /* jump to the CCP */
}

Some files were not shown because too many files have changed in this diff Show More