summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--as/6809/const.h501
-rw-r--r--as/Makefile27
-rw-r--r--as/TODO1
-rw-r--r--as/address.h30
-rw-r--r--as/as.c296
-rw-r--r--as/asm/calljmp.asm70
-rw-r--r--as/asm/ea.asm109
-rw-r--r--as/asm/each.asm145
-rw-r--r--as/asm/easlow.as1219
-rw-r--r--as/asm/f.asm114
-rw-r--r--as/asm/fadd.asm271
-rw-r--r--as/asm/farcall.asm10
-rw-r--r--as/asm/group1.asm31
-rw-r--r--as/asm/group6.asm24
-rw-r--r--as/asm/group7.asm34
-rw-r--r--as/asm/imul.asm33
-rw-r--r--as/asm/incdec.asm83
-rw-r--r--as/asm/inher.asm127
-rw-r--r--as/asm/inout.asm25
-rw-r--r--as/asm/movspec.asm246
-rw-r--r--as/asm/pushpop.asm86
-rw-r--r--as/asm/seg.asm6
-rw-r--r--as/asm/shdouble.asm34
-rw-r--r--as/asm/shift.asm119
-rw-r--r--as/asm/summary.as385
-rw-r--r--as/asm/xchg.asm103
-rw-r--r--as/assemble.c309
-rw-r--r--as/bin/calljmp.binbin0 -> 146 bytes
-rw-r--r--as/bin/ea.binbin0 -> 441 bytes
-rw-r--r--as/bin/each.binbin0 -> 657 bytes
-rw-r--r--as/bin/f.binbin0 -> 181 bytes
-rw-r--r--as/bin/fadd.binbin0 -> 605 bytes
-rw-r--r--as/bin/farcall.binbin0 -> 41 bytes
-rw-r--r--as/bin/group1.binbin0 -> 115 bytes
-rw-r--r--as/bin/group6.binbin0 -> 38 bytes
-rw-r--r--as/bin/group7.binbin0 -> 53 bytes
-rw-r--r--as/bin/imul.binbin0 -> 119 bytes
-rw-r--r--as/bin/incdec.binbin0 -> 116 bytes
-rw-r--r--as/bin/inher.binbin0 -> 129 bytes
-rw-r--r--as/bin/inout.binbin0 -> 54 bytes
-rw-r--r--as/bin/movspec.binbin0 -> 682 bytes
-rw-r--r--as/bin/pushpop.binbin0 -> 128 bytes
-rw-r--r--as/bin/seg.binbin0 -> 16 bytes
-rw-r--r--as/bin/shdouble.binbin0 -> 61 bytes
-rw-r--r--as/bin/shift.binbin0 -> 276 bytes
-rw-r--r--as/bin/xchg.binbin0 -> 234 bytes
-rw-r--r--as/byteord.h18
-rwxr-xr-xas/chk9
-rw-r--r--as/const.h409
-rw-r--r--as/error.c106
-rw-r--r--as/express.c382
-rw-r--r--as/file.h12
-rw-r--r--as/flag.h5
-rw-r--r--as/genbin.c220
-rw-r--r--as/genlist.c463
-rw-r--r--as/genobj.c682
-rw-r--r--as/gensym.c212
-rw-r--r--as/globvar.h93
-rw-r--r--as/macro.c175
-rw-r--r--as/macro.h10
-rw-r--r--as/mops.c2835
-rw-r--r--as/obj1/calljmp.objbin0 -> 200 bytes
-rw-r--r--as/obj1/ea.objbin0 -> 472 bytes
-rw-r--r--as/obj1/each.objbin0 -> 715 bytes
-rw-r--r--as/obj1/f.objbin0 -> 207 bytes
-rw-r--r--as/obj1/fadd.objbin0 -> 1069 bytes
-rw-r--r--as/obj1/farcall.objbin0 -> 71 bytes
-rw-r--r--as/obj1/group1.objbin0 -> 145 bytes
-rw-r--r--as/obj1/group6.objbin0 -> 67 bytes
-rw-r--r--as/obj1/group7.objbin0 -> 82 bytes
-rw-r--r--as/obj1/imul.objbin0 -> 147 bytes
-rw-r--r--as/obj1/incdec.objbin0 -> 146 bytes
-rw-r--r--as/obj1/inher.objbin0 -> 158 bytes
-rw-r--r--as/obj1/inout.objbin0 -> 82 bytes
-rw-r--r--as/obj1/movspec.objbin0 -> 722 bytes
-rw-r--r--as/obj1/pushpop.objbin0 -> 159 bytes
-rw-r--r--as/obj1/seg.objbin0 -> 42 bytes
-rw-r--r--as/obj1/shdouble.objbin0 -> 106 bytes
-rw-r--r--as/obj1/shift.objbin0 -> 308 bytes
-rw-r--r--as/obj1/xchg.objbin0 -> 264 bytes
-rw-r--r--as/opcode.h157
-rw-r--r--as/pops.c1048
-rw-r--r--as/proto.h218
-rw-r--r--as/readsrc.c341
-rw-r--r--as/scan.c247
-rw-r--r--as/scan.h12
-rw-r--r--as/source.h4
-rw-r--r--as/table.c945
-rw-r--r--as/todo14
-rw-r--r--as/type.h167
-rw-r--r--bcc-bruce/6809/const.h52
-rw-r--r--bcc-bruce/Makefile27
-rw-r--r--bcc-bruce/align.h16
-rw-r--r--bcc-bruce/assign.c387
-rw-r--r--bcc-bruce/bcc-cc1.c25
-rw-r--r--bcc-bruce/bcc.bugs169
-rw-r--r--bcc-bruce/bcc.c875
-rw-r--r--bcc-bruce/bcc.doc173
-rw-r--r--bcc-bruce/byteord.h13
-rw-r--r--bcc-bruce/codefrag.c1843
-rw-r--r--bcc-bruce/condcode.h16
-rw-r--r--bcc-bruce/const.h52
-rw-r--r--bcc-bruce/debug.c202
-rw-r--r--bcc-bruce/declare.c1124
-rw-r--r--bcc-bruce/express.c466
-rw-r--r--bcc-bruce/exptree.c1086
-rw-r--r--bcc-bruce/floatop.c173
-rw-r--r--bcc-bruce/function.c413
-rw-r--r--bcc-bruce/gencode.c736
-rw-r--r--bcc-bruce/gencode.h101
-rw-r--r--bcc-bruce/genloads.c1254
-rw-r--r--bcc-bruce/glogcode.c560
-rw-r--r--bcc-bruce/hardop.c510
-rw-r--r--bcc-bruce/input.c729
-rw-r--r--bcc-bruce/input.h37
-rw-r--r--bcc-bruce/label.c429
-rw-r--r--bcc-bruce/label.h24
-rw-r--r--bcc-bruce/loadexp.c180
-rw-r--r--bcc-bruce/longop.c169
-rw-r--r--bcc-bruce/misc/sformat56
-rw-r--r--bcc-bruce/misc/test/8queens.pas33
-rw-r--r--bcc-bruce/misc/test/8queens.t74
-rw-r--r--bcc-bruce/misc/test/atol.t29
-rw-r--r--bcc-bruce/misc/test/bigsievec.t29
-rw-r--r--bcc-bruce/misc/test/bt.t373
-rw-r--r--bcc-bruce/misc/test/cast.t144
-rw-r--r--bcc-bruce/misc/test/cast1.t144
-rw-r--r--bcc-bruce/misc/test/castest.t74
-rw-r--r--bcc-bruce/misc/test/ctype.t38
-rw-r--r--bcc-bruce/misc/test/error.t78
-rw-r--r--bcc-bruce/misc/test/extern.t236
-rw-r--r--bcc-bruce/misc/test/hilbert.t169
-rw-r--r--bcc-bruce/misc/test/longtest.c24
-rw-r--r--bcc-bruce/misc/test/longtest.dat15
-rwxr-xr-xbcc-bruce/misc/test/longtest.mak3
-rwxr-xr-xbcc-bruce/misc/test/longtest.sh4
-rw-r--r--bcc-bruce/misc/test/miniltest.t72
-rw-r--r--bcc-bruce/misc/test/op1.t120
-rw-r--r--bcc-bruce/misc/test/opcmp.t106
-rw-r--r--bcc-bruce/misc/test/oplong.t264
-rw-r--r--bcc-bruce/misc/test/opplus.t122
-rw-r--r--bcc-bruce/misc/test/opsoft.t259
-rw-r--r--bcc-bruce/misc/test/puzzle.t178
-rw-r--r--bcc-bruce/misc/test/sierpin.t123
-rw-r--r--bcc-bruce/misc/test/sievec.t28
-rw-r--r--bcc-bruce/misc/test/sievecp.t45
-rw-r--r--bcc-bruce/misc/test/sievei.t28
-rw-r--r--bcc-bruce/misc/test/sort.t104
-rw-r--r--bcc-bruce/misc/test/stdio.t87
-rw-r--r--bcc-bruce/os.h79
-rw-r--r--bcc-bruce/output.c813
-rw-r--r--bcc-bruce/output.h14
-rw-r--r--bcc-bruce/parse.h19
-rw-r--r--bcc-bruce/preproc.c944
-rw-r--r--bcc-bruce/preserve.c215
-rw-r--r--bcc-bruce/proto.h399
-rw-r--r--bcc-bruce/reg.h139
-rw-r--r--bcc-bruce/sc.h27
-rw-r--r--bcc-bruce/scan.c806
-rw-r--r--bcc-bruce/scan.h201
-rw-r--r--bcc-bruce/sizes.h50
-rw-r--r--bcc-bruce/softop.c222
-rw-r--r--bcc-bruce/state.c793
-rw-r--r--bcc-bruce/table.c668
-rw-r--r--bcc-bruce/table.h71
-rw-r--r--bcc-bruce/type.c203
-rw-r--r--bcc-bruce/type.h98
-rw-r--r--bcc-bruce/types.h206
-rw-r--r--bcc-linux16.patch444
-rw-r--r--bin86-0.3/ChangeLog67
-rw-r--r--bin86-0.3/Makefile36
-rw-r--r--bin86-0.3/README79
-rw-r--r--bin86-0.3/a.out.h/a.out.gnu.h276
-rw-r--r--bin86-0.3/a.out.h/bsd-a.out.h108
-rw-r--r--bin86-0.3/as/6809/const.h507
-rw-r--r--bin86-0.3/as/Makefile57
-rw-r--r--bin86-0.3/as/address.h36
-rw-r--r--bin86-0.3/as/as.c280
-rw-r--r--bin86-0.3/as/asm/calljmp.asm70
-rw-r--r--bin86-0.3/as/asm/ea.asm109
-rw-r--r--bin86-0.3/as/asm/each.asm145
-rw-r--r--bin86-0.3/as/asm/easlow.as1219
-rw-r--r--bin86-0.3/as/asm/f.asm114
-rw-r--r--bin86-0.3/as/asm/fadd.asm271
-rw-r--r--bin86-0.3/as/asm/farcall.asm10
-rw-r--r--bin86-0.3/as/asm/group1.asm31
-rw-r--r--bin86-0.3/as/asm/group6.asm24
-rw-r--r--bin86-0.3/as/asm/group7.asm34
-rw-r--r--bin86-0.3/as/asm/imul.asm33
-rw-r--r--bin86-0.3/as/asm/incdec.asm83
-rw-r--r--bin86-0.3/as/asm/inher.asm127
-rw-r--r--bin86-0.3/as/asm/inout.asm25
-rw-r--r--bin86-0.3/as/asm/movspec.asm246
-rw-r--r--bin86-0.3/as/asm/pushpop.asm86
-rw-r--r--bin86-0.3/as/asm/seg.asm6
-rw-r--r--bin86-0.3/as/asm/shdouble.asm34
-rw-r--r--bin86-0.3/as/asm/shift.asm119
-rw-r--r--bin86-0.3/as/asm/summary.as385
-rw-r--r--bin86-0.3/as/asm/xchg.asm103
-rw-r--r--bin86-0.3/as/assemble.c314
-rw-r--r--bin86-0.3/as/byteord.h24
-rwxr-xr-xbin86-0.3/as/chk9
-rw-r--r--bin86-0.3/as/const.h430
-rw-r--r--bin86-0.3/as/det_endian.c34
-rw-r--r--bin86-0.3/as/error.c105
-rw-r--r--bin86-0.3/as/express.c388
-rw-r--r--bin86-0.3/as/file.h18
-rw-r--r--bin86-0.3/as/flag.h11
-rw-r--r--bin86-0.3/as/genbin.c226
-rw-r--r--bin86-0.3/as/genlist.c454
-rw-r--r--bin86-0.3/as/genobj.c669
-rw-r--r--bin86-0.3/as/gensym.c202
-rw-r--r--bin86-0.3/as/globvar.h95
-rw-r--r--bin86-0.3/as/keywords.c733
-rw-r--r--bin86-0.3/as/macro.c174
-rw-r--r--bin86-0.3/as/macro.h16
-rw-r--r--bin86-0.3/as/mops.c2840
-rw-r--r--bin86-0.3/as/opcode.h162
-rw-r--r--bin86-0.3/as/pops.c977
-rw-r--r--bin86-0.3/as/proto.h256
-rw-r--r--bin86-0.3/as/readsrc.c335
-rw-r--r--bin86-0.3/as/scan.c253
-rw-r--r--bin86-0.3/as/scan.h18
-rw-r--r--bin86-0.3/as/source.h10
-rw-r--r--bin86-0.3/as/table.c229
-rw-r--r--bin86-0.3/as/todo10
-rw-r--r--bin86-0.3/as/type.h177
-rw-r--r--bin86-0.3/as/work/q4
-rw-r--r--bin86-0.3/as/work/r4
-rw-r--r--bin86-0.3/as/work/r-good1183
-rw-r--r--bin86-0.3/as/work/t3
-rw-r--r--bin86-0.3/as/work/t110
-rw-r--r--bin86-0.3/as/work/z5
-rw-r--r--bin86-0.3/bcc/bcc.c831
-rw-r--r--bin86-0.3/bcc/bcc.doc165
-rw-r--r--bin86-0.3/bccfp/Makefile44
-rw-r--r--bin86-0.3/bccfp/bccfp.tex0
-rw-r--r--bin86-0.3/bccfp/changes30
-rw-r--r--bin86-0.3/bccfp/fabs.x17
-rw-r--r--bin86-0.3/bccfp/fadd.x485
-rw-r--r--bin86-0.3/bccfp/fcomp.x89
-rw-r--r--bin86-0.3/bccfp/fdiv.x312
-rw-r--r--bin86-0.3/bccfp/fmul.x150
-rw-r--r--bin86-0.3/bccfp/fpbsr.x25
-rw-r--r--bin86-0.3/bccfp/fperr.c50
-rw-r--r--bin86-0.3/bccfp/fperr.h14
-rw-r--r--bin86-0.3/bccfp/fperror.x126
-rw-r--r--bin86-0.3/bccfp/fplib.h49
-rw-r--r--bin86-0.3/bccfp/fptoi.x117
-rw-r--r--bin86-0.3/bccfp/fpulld.x20
-rw-r--r--bin86-0.3/bccfp/fpullf.x101
-rw-r--r--bin86-0.3/bccfp/fpushd.x60
-rw-r--r--bin86-0.3/bccfp/fpushf.x74
-rw-r--r--bin86-0.3/bccfp/fpushi.x126
-rw-r--r--bin86-0.3/bccfp/frexp.x66
-rw-r--r--bin86-0.3/bccfp/ftst.x28
-rw-r--r--bin86-0.3/bccfp/ldexp.x74
-rw-r--r--bin86-0.3/bccfp/modf.c20
-rw-r--r--bin86-0.3/bccfp/test.c124
-rw-r--r--bin86-0.3/ld/6809/config.h34
-rw-r--r--bin86-0.3/ld/Makefile29
-rw-r--r--bin86-0.3/ld/align.h14
-rw-r--r--bin86-0.3/ld/ar.h24
-rw-r--r--bin86-0.3/ld/bugs17
-rw-r--r--bin86-0.3/ld/byteord.h24
-rw-r--r--bin86-0.3/ld/config.h34
-rw-r--r--bin86-0.3/ld/const.h20
-rw-r--r--bin86-0.3/ld/dumps.c72
-rw-r--r--bin86-0.3/ld/globvar.h18
-rw-r--r--bin86-0.3/ld/io.c583
-rw-r--r--bin86-0.3/ld/ld.c180
-rw-r--r--bin86-0.3/ld/obj.h58
-rw-r--r--bin86-0.3/ld/readobj.c368
-rw-r--r--bin86-0.3/ld/table.c202
-rw-r--r--bin86-0.3/ld/type.h228
-rw-r--r--bin86-0.3/ld/typeconv.c540
-rw-r--r--bin86-0.3/ld/writebin.c949
-rw-r--r--ld/6809/config.h28
-rw-r--r--ld/Makefile18
-rw-r--r--ld/Makefile.minix20
-rw-r--r--ld/README.199417
-rw-r--r--ld/align.h10
-rw-r--r--ld/bugs17
-rw-r--r--ld/byteord.h20
-rw-r--r--ld/config.h28
-rw-r--r--ld/const.h14
-rw-r--r--ld/dumps.c68
-rw-r--r--ld/globvar.h14
-rw-r--r--ld/io.c606
-rw-r--r--ld/ld.c187
-rw-r--r--ld/obj.h54
-rw-r--r--ld/readobj.c374
-rw-r--r--ld/table.c205
-rw-r--r--ld/type.h163
-rw-r--r--ld/typeconv.c536
-rw-r--r--ld/writebin.c989
296 files changed, 59590 insertions, 0 deletions
diff --git a/as/6809/const.h b/as/6809/const.h
new file mode 100644
index 0000000..abd9469
--- /dev/null
+++ b/as/6809/const.h
@@ -0,0 +1,501 @@
+#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */
+#define LOW_BYTE 0 /* must be changed for big-endian */
+
+/* const.h - constants for assembler */
+
+/* major switches */
+
+#undef I80386 /* generate 80386 code */
+#define MC6809 /* generate 6809 code */
+#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */
+#undef SOS_EDOS /* source OS is EDOS */
+
+/* defaults */
+
+#define DIRCHAR '/' /* character separating filename from dir */
+#define INBUFSIZE 8192
+#define SOS_EOLSTR "\012"
+
+/* defaults modified by switches */
+
+#ifdef SOS_EDOS
+# undef INBUFSIZE
+# define INBUFSIZE 512
+# undef SOS_EOLSTR
+# define SOS_EOLSTR "\015\012"
+# define STAKSIZ 256 /* table grows up to stack less this */
+#endif
+
+/* booleans */
+
+#define FALSE 0
+#define TRUE 1
+
+/* ASCII constants */
+
+#define ETB 23
+
+/* C tricks */
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+#define NULL 0
+
+/* O/S constants */
+
+#define CREAT_PERMS 0666
+#define EOF (-1)
+#define STDIN 0
+#define STDOUT 1
+
+/* register codes (internal to assembler) */
+
+#ifdef I80386
+
+/* index regs must be first */
+
+#define BPREG 0
+#define BXREG 1
+#define DIREG 2
+#define SIREG 3
+#define MAX16BITINDREG 3
+
+#define EAXREG 4
+#define EBPREG 5
+#define EBXREG 6
+#define ECXREG 7
+#define EDIREG 8
+#define EDXREG 9
+#define ESIREG 10
+#define ESPREG 11
+#define MAXINDREG 11
+
+#define AXREG 12
+#define CXREG 13
+#define DXREG 14
+#define SPREG 15
+
+#define AHREG 16
+#define ALREG 17
+#define BHREG 18
+#define BLREG 19
+#define CHREG 20
+#define CLREG 21
+#define DHREG 22
+#define DLREG 23
+
+#define CSREG 24
+#define DSREG 25
+#define ESREG 26
+#define FSREG 27
+#define GSREG 28
+#define SSREG 29
+
+#define CR0REG 30
+#define CR2REG 31
+#define CR3REG 32
+#define DR0REG 33
+#define DR1REG 34
+#define DR2REG 35
+#define DR3REG 36
+#define DR6REG 37
+#define DR7REG 38
+#define TR6REG 39
+#define TR7REG 40
+
+#define NOREG 41
+
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* index regs must be first, then PC, then other regs */
+
+#define AREG 5
+#define BREG 6
+#define CCREG 7
+#define DPREG 8
+#define DREG 9
+#define MAXINDREG 3
+#define NOREG 10
+#define PCREG 4
+#define SREG 0
+#define UREG 1
+#define XREG 2
+#define YREG 3
+
+#endif
+
+#ifdef I80386
+
+/* type and size keywords */
+
+#define BYTEOP 0
+#define DWORDOP 1
+#define FWORDOP 2
+#define FAROP 3
+#define PTROP 4
+#define PWORDOP 5
+#define QWORDOP 6
+#define TBYTEOP 7
+#define WORDOP 8
+#endif
+
+/* special chars */
+
+#define EOL 0
+#define MACROCHAR '?'
+
+/* symbol codes */
+
+/* the first 2 must be from chars in identifiers */
+#define IDENT 0
+#define INTCONST 1
+
+/* the next few are best for other possibly-multi-char tokens */
+#define ADDOP 2 /* also ++ */
+#define BINCONST 3
+#define CHARCONST 4
+#define GREATERTHAN 5 /* also >> and context-sensitive */
+#define HEXCONST 6
+#define LESSTHAN 7 /* also << and context-sensitive */
+#define SUBOP 8 /* also -- */
+#define WHITESPACE 9
+
+#define ANDOP 10
+#define COMMA 11
+#define EOLSYM 12
+#define EQOP 13
+#define IMMEDIATE 14
+#define INDIRECT 15
+#define LBRACKET 16
+#define LPAREN 17
+#define MACROARG 18
+#define NOTOP 19
+#define OROP 20
+#define OTHERSYM 21
+#define POSTINCOP 22
+#define PREDECOP 23
+#define RBRACKET 24
+#define RPAREN 25
+#define SLASH 26 /* context-sensitive */
+#define SLOP 27
+#define SROP 28
+#define STAR 29 /* context-sensitive */
+#define STRINGCONST 30
+#define COLON 31
+
+/* these are from assembler errors module */
+
+/* syntax errors */
+
+#define COMEXP 0
+#define DELEXP 1
+#define FACEXP 2
+#define IREGEXP 3
+#define LABEXP 4
+#define LPEXP 5
+#define OPEXP 6
+#define RBEXP 7
+#define REGEXP 8
+#define RPEXP 9
+#define SPEXP 10
+
+/* expression errors */
+
+#define ABSREQ 11
+#define NONIMPREQ 12
+#define RELBAD 13
+
+/* label errors */
+
+#define ILLAB 14
+#define MACUID 15
+#define MISLAB 16
+#define MNUID 17
+#define REGUID 18
+#define RELAB 19
+#define UNBLAB 20
+#define UNLAB 21
+#define VARLAB 22
+
+/* addressing errors */
+
+#define ABOUNDS 23
+#define DBOUNDS 24
+#define ILLMOD 25
+#define ILLREG 26
+
+/* control structure errors */
+
+#define ELSEBAD 27
+#define ELSEIFBAD 27
+#define ENDBBAD 28
+#define ENDIFBAD 27
+#define EOFBLOCK 29
+#define EOFIF 30
+
+#define EOFLC 31
+#define EOFMAC 32
+#define FAILERR 33
+
+/* overflow errors */
+
+#define BLOCKOV 34
+#define BWRAP 35
+#define COUNTOV 36
+#define COUNTUN 37
+#define GETOV 38
+#define IFOV 39
+
+#define LINLONG 40
+#define MACOV 41
+#define OBJSYMOV 42
+#define OWRITE 43
+#define PAROV 44
+#define SYMOV 45
+#define SYMOUTOV 46
+
+/* i/o errors */
+
+#define OBJOUT 47
+
+/* miscellaneous errors */
+
+#define CTLINS 48
+#define FURTHER 49
+#define NOIMPORT 50
+#define NOTIMPLEMENTED 51
+#define REENTER 52
+#define SEGREL 53
+
+/* warnings */
+
+#define MINWARN 54
+#define ALREADY 54
+#define SHORTB 55
+
+/* symbol table entry */
+
+ /* type entry contains following flags */
+#define ENTBIT (1<<0) /* entry point (=OBJ_N_MASK) */
+#define COMMBIT (1<<1) /* common */
+#define LABIT (1<<2) /* label (a PC location or defined by EQU) */
+#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */
+#define MACBIT (1<<4) /* macro */
+#define REDBIT (1<<5) /* redefined */
+#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */
+#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */
+
+ /* data entry contains following flags, valid */
+ /* for expressions as well as syms */
+#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT \ PAGE1 */
+#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT \ PAGE2 */
+#define REGBIT (1<<2) /* register = MNREGBIT \ REGBIT */
+#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT \ SIZEBIT */
+#define SEGM 15 /* 1st 4 bits reused for segment if !MNREGBIT */
+#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */
+#define FORBIT (1<<5) /* forward referenced */
+#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */
+#define UNDBIT (1<<7) /* undefined */
+
+/* pseudo-op routine numbers */
+/* conditionals are first, this is used to test if op is a conditional */
+
+#define ELSEOP 0
+#define ELSEIFOP 1
+#define ELSEIFCOP 2
+#define ENDIFOP 3
+#define IFOP 4
+#define IFCOP 5
+#define MAXCOND 6 /* limit of conditionals */
+
+#define BLOCKOP 6
+#define COMMOP 7
+#define ENDOP 8
+#define ENDBOP 9
+#define ENTEROP 10
+#define ENTRYOP 11
+#define EQUOP 12
+#define EXPORTOP 13
+#define FAILOP 14
+#define FCBOP 15
+#define FCCOP 16
+#define FDBOP 17
+#define GETOP 18
+#define IDENTOP 19
+#define IMPORTOP 20
+#define _LISTOP 21
+#define LOCOP 22
+#define _MACLISTOP 23
+#define MACROOP 24
+#define _MAPOP 25
+#define ORGOP 26
+#define RMBOP 27
+#define SETOP 28
+#define SETDPOP 29
+#define _WARNOP 30
+
+#ifdef I80386
+
+/* further pseudo-ops */
+
+#define BSSOP 31
+#define COMMOP1 32
+#define DATAOP 33
+#define TEXTOP 34
+#define USE16OP 35
+#define USE32OP 36
+
+/* machine-op routine numbers */
+
+#define ARPL 37
+#define BCC 38
+#define BOUND 39
+#define CALL 40
+#define DIVMUL 41
+#define ENTER 42
+#define GROUP1 43
+#define GROUP2 44
+#define GROUP6 45
+#define GROUP7 46
+#define GROUP8 47
+#define GvEv 48
+#define IMUL 49
+#define IN 50
+#define INCDEC 51
+#define INHER 52
+#define INHER16 53
+#define INHER32 54
+#define INHER_A 55
+#define INT 56
+#define JCC 57
+#define JCXZ 58
+#define LEA 59
+#define LOAD_FULL_POINTER 60
+#define MOV 61
+#define MOVX 62
+#define NEGNOT 63
+#define OUT 64
+#define PUSHPOP 65
+#define RET 66
+#define RETF 67
+#define SEG 68
+#define SETCC 69
+#define SH_DOUBLE 70
+#define TEST 71
+#define XCHG 72
+
+/* further pseudo-ops */
+
+#define BLKWOP 73
+#define EVENOP 74
+#define FQBOP 75
+#define ALIGNOP 76
+
+/* further machine-ops */
+
+#define CALLI 77
+
+/* yet further pseudo-ops */
+
+#define LCOMMOP 78
+#define LCOMMOP1 79
+
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* machine-op routine numbers */
+
+#define ALL 31 /* all address modes allowed, like LDA */
+#define ALTER 32 /* all but immediate, like STA */
+#define IMMED 33 /* immediate only (ANDCC, ORCC) */
+#define INDEXD 34 /* indexed (LEA's) */
+#define INHER 35 /* inherent, like CLC or CLRA */
+#define LONG 36 /* long branches */
+#define SHORT 37 /* short branches */
+#define SSTAK 38 /* S-stack (PSHS, PULS) */
+#define SWAP 39 /* TFR, EXG */
+#define USTAK 40 /* U-stack (PSHU,PULU) */
+
+/* yet further pseudo-ops */
+
+#define LCOMMOP 41
+
+#endif
+
+/* object code format (Introl) */
+
+#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */
+
+#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */
+
+#define OBJ_ABS 0x40 /* absolute code command */
+#define OBJ_OFFSET_REL 0x80 /* offset relocation command */
+#define OBJ_SET_SEG 0x20 /* set segment command */
+#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */
+#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */
+#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */
+#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */
+
+#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */
+#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */
+oops - RELBIT misplaced
+#endif
+#define OBJ_E_MASK 0x80 /* exported bit (symbols) */
+#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */
+oops - EXPBIT misplaced
+#endif
+#define OBJ_I_MASK 0x40 /* imported bit (symbols) */
+#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */
+oops - IMPBIT misplaced
+#endif
+#define OBJ_N_MASK 0x01 /* entry bit (symbols) */
+#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */
+oops - ENTBIT misplaced
+#endif
+#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */
+#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */
+#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */
+#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */
+
+#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */
+#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */
+
+#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */
+#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */
+
+#define SYMLIS_NAMELEN 26
+#define SYMLIS_LEN (sizeof (struct sym_listing_s))
+
+#define FILNAMLEN 64 /* max length of a file name */
+#define LINLEN 256 /* max length of input line */
+#define LINUM_LEN 5 /* length of formatted line number */
+
+#define SPTSIZ 1024 /* number of symbol ptrs */
+ /* pseudo-op flags */
+#define POPHI 1 /* set to print hi byte of adr */
+#define POPLO 2 /* to print lo byte of ADR */
+#define POPLC 4 /* to print LC */
+#define POPLONG 8 /* to print high word of ADR */
+#define MAXBLOCK 8 /* max nesting level of BLOCK stack */
+#define MAXGET 8 /* max nesting level of GET stack */
+#define MAXIF 8 /* max nesting level of IF stack */
+#define MACPSIZ (128/sizeof (struct schain_s))
+ /* size of macro param buffer */
+#define MAXMAC 8 /* max nesting level of macro stack */
+#define NLOC 16 /* number of location counters */
+#ifdef I80386
+#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */
+#endif
+
+/* special segments */
+
+#define BSSLOC 3
+#define DATALOC 3
+#define DPLOC 2
+#define STRLOC 1
+#define TEXTLOC 0
diff --git a/as/Makefile b/as/Makefile
new file mode 100644
index 0000000..d7468a9
--- /dev/null
+++ b/as/Makefile
@@ -0,0 +1,27 @@
+CFLAGS =-O
+LDFLAGS =
+
+OBJS =as.o assemble.o error.o express.o \
+ genbin.o genlist.o genobj.o gensym.o \
+ macro.o mops.o pops.o readsrc.o \
+ scan.o table.o typeconv.o
+
+as: $(OBJS)
+ $(CC) $(LDFLAGS) $(OBJS) -o as
+ chmem =182000 as
+
+as.o: const.h type.h byteord.h macro.h file.h flag.h globvar.h
+assemble.o: const.h type.h address.h globvar.h opcode.h scan.h
+error.o: const.h type.h
+express.o: const.h type.h address.h globvar.h scan.h source.h
+genbin.o: const.h type.h address.h file.h globvar.h
+genlist.o: const.h type.h address.h flag.h file.h globvar.h macro.h scan.h \
+ source.h
+genobj.o: const.h type.h address.h file.h globvar.h
+gensym.o: const.h type.h flag.h file.h globvar.h
+macro.o: const.h type.h globvar.h scan.h macro.h
+mops.o: const.h type.h globvar.h opcode.h scan.h address.h
+pops.o: const.h type.h address.h flag.h globvar.h opcode.h scan.h
+readsrc.o: const.h type.h flag.h file.h globvar.h macro.h scan.h source.h
+scan.o: const.h type.h globvar.h scan.h
+table.o: const.h type.h globvar.h opcode.h scan.h
diff --git a/as/TODO b/as/TODO
new file mode 100644
index 0000000..b8166c8
--- /dev/null
+++ b/as/TODO
@@ -0,0 +1 @@
+6809/const.h is out of date.
diff --git a/as/address.h b/as/address.h
new file mode 100644
index 0000000..26fcf33
--- /dev/null
+++ b/as/address.h
@@ -0,0 +1,30 @@
+/* address.h - global variables involving addresses for assembler */
+
+EXTERN struct address_s lastexp;/* last expression parsed */
+
+EXTERN union
+{
+ char fcbuf[LINLEN - 6]; /* buffer for fcb and fcc data */
+ /* data is absolute in 1 char pieces */
+ /* limited by FCC\t"" etc on line */
+ struct address_s fdbuf[(LINLEN - 4) / 2];
+ /* buffer for fdb data */
+ /* data can be of any 2-byte adr type */
+ /* limited by FDB\t and commas on line */
+#if SIZEOF_OFFSET_T > 2
+ struct address_s fqbuf[(LINLEN - 4) / 4];
+ /* buffer for fqb data */
+ /* data can be of any 4-byte adr type */
+ /* limited by FQB\t and commas on line */
+#endif
+}
+ databuf;
+
+EXTERN bool_t fcflag;
+EXTERN bool_t fdflag;
+#if SIZEOF_OFFSET_T > 2
+EXTERN bool_t fqflag;
+#endif
+
+EXTERN struct address_s immadr;
+EXTERN smallcount_t immcount;
diff --git a/as/as.c b/as/as.c
new file mode 100644
index 0000000..666fd79
--- /dev/null
+++ b/as/as.c
@@ -0,0 +1,296 @@
+/* as.c - assembler */
+
+/*
+ usage: as source [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] [-guw]
+ in any order (but no repeated file options)
+*/
+
+#include "const.h"
+#include "type.h"
+#include "byteord.h"
+#include "macro.h"
+#undef EXTERN
+#define EXTERN
+#include "file.h"
+#include "flag.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void exit P((int status));
+void *malloc P((unsigned size));
+char *strcpy P((char *s1, const char *s2));
+unsigned strlen P((const char *s));
+#else
+#undef NULL
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+int close P((int fd));
+int creat P((const char *path, int mode));
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#undef NULL
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+PUBLIC char hexdigit[] = "0123456789ABCDEF"; /* XXX - ld uses lower case */
+
+PRIVATE struct block_s hid_blockstak[MAXBLOCK]; /* block stack */
+PRIVATE struct lc_s hid_lctab[NLOC]; /* location counter table */
+PRIVATE struct if_s hid_ifstak[MAXBLOCK]; /* if stack */
+PRIVATE struct schain_s hid_mcpar[MACPSIZ]; /* MACRO params */
+PRIVATE struct macro_s hid_macstak[MAXBLOCK]; /* macro stack */
+PRIVATE struct sym_s *hid_spt[SPTSIZ]; /* hash table */
+
+FORWARD void initp1 P((void));
+FORWARD int my_creat P((char *name, char *message));
+FORWARD void process_args P((int argc, char **argv));
+FORWARD void summary P((fd_t fd));
+FORWARD void summ_number P((unsigned num));
+FORWARD void usage P((void));
+
+#define USERMEM (sizeof(int) <= 2 ? (unsigned) 0xAC00 : (unsigned) 0x28000L)
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ heapptr = malloc(USERMEM);
+ heapend = heapptr + USERMEM;
+ if (heapptr == 0)
+ as_abort("cannot allocate memory");
+#ifdef SOS_EDOS
+ heapend = stackreg() - STAKSIZ;
+#endif
+ initp1();
+ initp1p2();
+ inst_keywords();
+ initbin();
+ initobj();
+ initsource(); /* only nec to init for unsupported mem file */
+ typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN);
+ warn.global = TRUE; /* constant */
+ process_args(argc, argv);
+ initscan();
+
+ assemble(); /* doesn't return, maybe use setjmp */
+
+ /* NOTREACHED */
+ return 0;
+}
+
+PUBLIC void as_abort(message)
+char *message;
+{
+ write(STDOUT, "as: ", 4);
+ write(STDOUT, message, strlen(message));
+ write(STDOUT, "\n", 1);
+ exit(1);
+}
+
+PUBLIC void finishup()
+{
+ bintrailer();
+ objtrailer();
+ if (list.global ||symgen)
+ gensym(); /* output to lstfil and/or symfil */
+ if (list.global ||toterr != 0 || totwarn != 0)
+ summary(lstfil);
+ if (lstfil != STDOUT && (toterr != 0 || totwarn != 0))
+ summary(STDOUT);
+ statistics();
+ exit(toterr != 0 ? 1 : 0); /* should close output files and check */
+}
+
+/* initialise constant nonzero values */
+
+PRIVATE void initp1()
+{
+#ifdef I80386
+ idefsize = defsize = sizeof (char *) > 2 ? 4 : 2;
+#endif
+ lctabtop = lctab + NLOC;
+ lstfil = STDOUT;
+ mapnum = 15; /* default map number for symbol table */
+ spt_top = (spt = hid_spt) + SPTSIZ;
+}
+
+/* initialise nonzero values which start same each pass */
+
+PUBLIC void initp1p2()
+{
+ register struct lc_s *lcp;
+
+ ifflag = TRUE;
+ pedata = UNDBIT; /* program entry point not defined */
+ blockstak = hid_blockstak + MAXBLOCK;
+ ifstak = hid_ifstak + MAXIF;
+ macstak = hid_macstak + MAXMAC;
+ macptop = (macpar = hid_mcpar) + MACPSIZ;
+ lctabtop = (lcptr = lctab = hid_lctab) + NLOC;
+ for (lcp = lctab; lcp < lctabtop; ++lcp)
+ /* init of lcdata/lc (many times) in loop to save space */
+ {
+ lcp->data = lcdata = RELBIT; /* lc relocatable until 1st ORG */
+ lcp->lc = lc = 0;
+ }
+}
+
+PRIVATE int my_creat(name, message)
+char *name;
+char *message;
+{
+ int fd;
+
+ if ((fd = creat(name, CREAT_PERMS)) < 0 || fd > 255)
+ as_abort(message);
+ return fd;
+}
+
+PRIVATE void process_args(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+ bool_t isnextarg;
+ char *nextarg;
+
+ if (argc <= 1)
+ usage();
+ do
+ {
+ arg = *++argv;
+ if (arg[0] == '-')
+ {
+ if (arg[2] != 0)
+ usage(); /* no multiple options */
+ isnextarg = FALSE;
+ if (argc > 2)
+ {
+ nextarg = argv[1];
+ if (nextarg[0] != 0 && nextarg[0] != '-')
+ isnextarg = TRUE;
+ }
+ switch (arg[1])
+ {
+#ifdef I80386
+ case '0':
+ idefsize = defsize = 0x2;
+ break;
+ case '3':
+ idefsize = defsize = 0x4;
+ break;
+ case 'a':
+ asld_compatible = TRUE;
+ break;
+#endif
+ case 'b':
+ if (!isnextarg || binfil != 0)
+ usage();
+ binfil = my_creat(nextarg, "error creating binary file");
+ binaryg = TRUE;
+ --argc;
+ ++argv;
+ break;
+ case 'g':
+ globals_only_in_obj = TRUE;
+ break;
+#ifdef I80386
+ case 'j':
+ jumps_long = TRUE;
+ break;
+#endif
+ case 'l':
+ list.global = TRUE;
+ goto get_any_list_file;
+ case 'm':
+ maclist.global = TRUE;
+ get_any_list_file:
+ if (isnextarg)
+ {
+ if (lstfil != STDOUT)
+ usage();
+ lstfil = my_creat(nextarg, "error creating list file");
+ --argc;
+ ++argv;
+ }
+ break;
+ case 'n':
+ if (!isnextarg)
+ usage();
+ truefilename = nextarg;
+ --argc;
+ ++argv;
+ break;
+ case 'o':
+ if (!isnextarg || objfil != 0)
+ usage();
+ objectg = TRUE;
+ objfil = my_creat(nextarg, "error creating object file");
+ --argc;
+ ++argv;
+ break;
+ case 's':
+ if (!isnextarg || symfil != 0)
+ usage();
+ symgen = TRUE;
+ symfil = my_creat(nextarg, "error creating symbol file");
+ --argc;
+ ++argv;
+ break;
+ case 'u':
+ inidata = IMPBIT | SEGM;
+ break;
+ case 'w':
+ warn.semaphore = -1;
+ break;
+ default:
+ usage(); /* bad option */
+ }
+ }
+ else if (infil != 0)
+ usage(); /* no multiple sources */
+ else
+ {
+ if (strlen(arg) > FILNAMLEN)
+ as_abort("source file name too long");
+ infil = open_input(strcpy(filnamptr, arg));
+ infiln = infil0 = 1;
+ }
+ }
+ while (--argc != 1);
+ inidata = (~binaryg & inidata) | (RELBIT | UNDBIT);
+} /* IMPBIT from inidata unless binaryg */
+
+PRIVATE void summary(fd)
+int fd;
+{
+ innum = fd;
+ writenl();
+ summ_number(toterr);
+ writesn(" errors");
+ summ_number(totwarn);
+ writesn(" warnings");
+}
+
+PRIVATE void summ_number(num)
+unsigned num;
+{
+ /* format number like line numbers, build it at free spot heapptr */
+ *build_number(num, LINUM_LEN, heapptr) = 0;
+ writes(heapptr);
+}
+
+PRIVATE void usage()
+{
+ as_abort(
+#ifdef I80386
+"usage: as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src");
+#else
+ "usage: as [-guw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src");
+#endif
+}
diff --git a/as/asm/calljmp.asm b/as/asm/calljmp.asm
new file mode 100644
index 0000000..36a6ea4
--- /dev/null
+++ b/as/asm/calljmp.asm
@@ -0,0 +1,70 @@
+ CALL 0x10:0x20 ; not implemented
+ CALL AL; ; illeg
+ CALL DS ; illeg
+
+ CALL REL16
+
+ CALL AX
+ CALL BX
+ CALL CX
+ CALL DX
+ CALL SP
+ CALL BP
+ CALL SI
+ CALL DI
+
+ CALL BYTE [BX] ; illeg
+ CALL [BX]
+ CALL WORD [BX]
+
+ USE32
+ CALL REL32
+
+ USE16
+ CALL EAX
+ CALL EBX
+ CALL ECX
+ CALL EDX
+ CALL ESP
+ CALL EBP
+ CALL ESI
+ CALL EDI
+
+ CALL DWORD [BX]
+
+ JMP 0x10:0x20 ; not implemented
+ JMP AL; ; illeg
+ JMP DS ; illeg
+
+ JMP REL16
+
+ JMP AX
+ JMP BX
+ JMP CX
+ JMP DX
+ JMP SP
+ JMP BP
+ JMP SI
+ JMP DI
+
+ JMP BYTE [BX] ; illeg
+ JMP [BX]
+ JMP WORD [BX]
+
+ USE32
+ JMP REL32
+
+ USE16
+ JMP EAX
+ JMP EBX
+ JMP ECX
+ JMP EDX
+ JMP ESP
+ JMP EBP
+ JMP ESI
+ JMP EDI
+
+ JMP DWORD [BX]
+
+REL16:
+REL32:
diff --git a/as/asm/ea.asm b/as/asm/ea.asm
new file mode 100644
index 0000000..8717a73
--- /dev/null
+++ b/as/asm/ea.asm
@@ -0,0 +1,109 @@
+ MOV AX,[BX+SI]
+ MOV AX,[BX+DI]
+ MOV AX,[BP+SI]
+ MOV AX,[BP+DI]
+ MOV AX,[SI]
+ MOV AX,[DI]
+ MOV AX,[0x1234]
+ MOV AX,[BX]
+
+ MOV AX,[BX+SI+0x12]
+ MOV AX,[BX+DI+0x12]
+ MOV AX,[BP+SI+0x12]
+ MOV AX,[BP+DI+0x12]
+ MOV AX,[SI+0x12]
+ MOV AX,[DI+0x12]
+ MOV AX,[BP+0x12]
+ MOV AX,[BX+0x12]
+
+ MOV AX,[BX+SI+0x1234]
+ MOV AX,[BX+DI+0x1234]
+ MOV AX,[BP+SI+0x1234]
+ MOV AX,[BP+DI+0x1234]
+ MOV AX,[SI+0x1234]
+ MOV AX,[DI+0x1234]
+ MOV AX,[BP+0x1234]
+ MOV AX,[BX+0x1234]
+
+ MOV AL,AL
+ MOV AL,AH
+ MOV AL,BL
+ MOV AL,BH
+ MOV AL,CL
+ MOV AL,CH
+ MOV AL,DL
+ MOV AL,DH
+
+ MOV AX,AX
+ MOV AX,CX
+ MOV AX,DX
+ MOV AX,BX
+ MOV AX,SP
+ MOV AX,BP
+ MOV AX,SI
+ MOV AX,DI
+
+ MOV AX,[EAX]
+ MOV AX,[ECX]
+ MOV AX,[EDX]
+ MOV AX,[EBX]
+
+ MOV AX,[0x12345678]
+ MOV AX,[ESI]
+ MOV AX,[EDI]
+
+ MOV AX,[EAX+0x12]
+ MOV AX,[ECX+0x12]
+ MOV AX,[EDX+0x12]
+ MOV AX,[EBX+0x12]
+
+ MOV AX,[EBP+0x12]
+ MOV AX,[ESI+0x12]
+ MOV AX,[EDI+0x12]
+
+ MOV AX,[EAX+0x12345678]
+ MOV AX,[ECX+0x12345678]
+ MOV AX,[EDX+0x12345678]
+ MOV AX,[EBX+0x12345678]
+
+ MOV AX,[EBP+0x12345678]
+ MOV AX,[ESI+0x12345678]
+ MOV AX,[EDI+0x12345678]
+
+ MOV EAX,EAX
+ MOV EAX,ECX
+ MOV EAX,EDX
+ MOV EAX,EBX
+ MOV EAX,ESP
+ MOV EAX,EBP
+ MOV EAX,ESI
+ MOV EAX,EDI
+
+ MOV AX,[EAX+ESI*2]
+ MOV AX,[ECX+ESI*2]
+ MOV AX,[EDX+ESI*2]
+ MOV AX,[EBX+ESI*2]
+ MOV AX,[ESP+ESI*2]
+ MOV AX,[ESI*2+0x12345678]
+ MOV AX,[ESI+ESI*2]
+ MOV AX,[EDI+ESI*2]
+
+ MOV AX,[EAX+ESI*2+0x12]
+ MOV AX,[ECX+ESI*2+0x12]
+ MOV AX,[EDX+ESI*2+0x12]
+ MOV AX,[EBX+ESI*2+0x12]
+ MOV AX,[ESP+ESI*2+0x12]
+ MOV AX,[ESP+0x12]
+ MOV AX,[EBP+ESI*2+0x12]
+ MOV AX,[ESI+ESI*2+0x12]
+ MOV AX,[EDI+ESI*2+0x12]
+
+ MOV AX,[EAX+ESI*2+0x12345678]
+ MOV AX,[ECX+ESI*2+0x12345678]
+ MOV AX,[EDX+ESI*2+0x12345678]
+ MOV AX,[EBX+ESI*2+0x12345678]
+ MOV AX,[ESP+ESI*2+0x12345678]
+ MOV AX,[ESP+0x12345678]
+ MOV AX,[EBP+ESI*2+0x12345678]
+ MOV AX,[ESI+ESI*2+0x12345678]
+ MOV AX,[EDI+ESI*2+0x12345678]
diff --git a/as/asm/each.asm b/as/asm/each.asm
new file mode 100644
index 0000000..2145489
--- /dev/null
+++ b/as/asm/each.asm
@@ -0,0 +1,145 @@
+aaa
+aad
+aam
+aas
+adc bx,[esi*4]
+add bx,[esi*4]
+and bx,[esi*4]
+arpl [esi*4],bx
+bound bx,[esi*4]
+bsf bx,[esi*4]
+bsr bx,[esi*4]
+bswap ebx
+bt [esi*4],bx
+btc [esi*4],bx
+btr [esi*4],bx
+bts [esi*4],bx
+call [esi*4]
+cbw
+cwde
+clc
+cld
+cli
+clts
+cmc
+cmp bx,[esi*4]
+cmpsb
+cmpsw
+cmpsd
+cmpxchg [esi*4],bx
+cwd
+cdq
+daa
+das
+dec [esi*4]
+div [esi*4]
+enter 0x200,3
+hlt
+idiv [esi*4]
+imul [esi*4]
+in al,0x20
+inc [esi*4]
+insb
+insw
+insd
+int 0x20
+into
+invd
+invlpg [esi*4]
+iret
+iretd
+jnz many
+many:
+jmp [esi*4]
+lahf
+lar bx,[esi*4]
+lea bx,[esi*4]
+leave
+lgdt [esi*4]
+lidt [esi*4]
+lds bx,[esi*4]
+les bx,[esi*4]
+lfs bx,[esi*4]
+lgs bx,[esi*4]
+lss bx,[esi*4]
+lldt [esi*4]
+lmsw [esi*4]
+lock
+lodsb
+lodsw
+lodsd
+loop alot
+alot:
+lsl bx,[esi*4]
+ltr [esi*4]
+mov ax,[esi*4]
+mov bx,[esi*4]
+mov cr0,eax
+movsb
+movsw
+movsd
+movsx bx,byte [esi*4]
+movzx bx,byte [esi*4]
+mul [esi*4]
+neg [esi*4]
+nop
+not [esi*4]
+or bx,[esi*4]
+out 0x20,al
+outsb
+outsw
+outsd
+pop [esi*4]
+popa
+popad
+popf
+popfd
+push [esi*4]
+pusha
+pushad
+pushf
+pushfd
+rcl [esi*4],1
+rcr [esi*4],1
+rol [esi*4],1
+ror [esi*4],1
+rep
+repe
+repz
+repne
+repnz
+ret
+retf
+sahf
+sal [esi*4],1
+sar [esi*4],1
+shl [esi*4],1
+shr [esi*4],1
+sbb bx,[esi*4]
+scasb
+scasw
+scasd
+setnz byte [esi*4]
+sgdt [esi*4]
+sidt [esi*4]
+shld [esi*4],bx,1
+shrd [esi*4],bx,1
+sldt [esi*4]
+smsw [esi*4]
+stc
+std
+sti
+stosb
+stosw
+stosd
+str [esi*4]
+sub bx,[esi*4]
+test bx,[esi*4]
+verr [esi*4]
+verw [esi*4]
+wait
+wbinvd
+xadd [esi*4],bx
+xchg bx,[esi*4]
+xlat
+xor bx,[esi*4]
diff --git a/as/asm/easlow.as b/as/asm/easlow.as
new file mode 100644
index 0000000..75d71e2
--- /dev/null
+++ b/as/asm/easlow.as
@@ -0,0 +1,1219 @@
+ MOV AL,[0]
+ MOV AH,[1]
+ MOV BL,[-1] ; illeg
+ MOV BH,[127]
+ MOV CL,[-128] ; illeg
+ MOV CH,[128]
+ MOV DL,[-129] ; illeg
+ MOV DH,[32767]
+ MOV AL,[-32768] ; illeg
+ MOV AH,[32768]
+ MOV BL,[-32769] ; illeg
+ MOV BH,[$7FFFFFFF] ; illeg
+ MOV CL,[$80000000] ; illeg
+
+ MOV AL,AL
+ MOV AL,AH
+ MOV AL,BL
+ MOV AL,BH
+ MOV AL,CL
+ MOV AL,CH
+ MOV AL,DL
+ MOV AL,DH
+
+ MOV AL,AX ; illeg
+ MOV AL,BX ; illeg
+ MOV AL,CX ; illeg
+ MOV AL,DX ; illeg
+ MOV AL,BP ; illeg
+ MOV AL,DI ; illeg
+ MOV AL,SI ; illeg
+ MOV AL,SP ; illeg
+
+ MOV AH,AL
+ MOV AH,AH
+ MOV AH,BL
+ MOV AH,BH
+ MOV AH,CL
+ MOV AH,CH
+ MOV AH,DL
+ MOV AH,DH
+
+ MOV AH,AX ; illeg
+ MOV AH,BX ; illeg
+ MOV AH,CX ; illeg
+ MOV AH,DX ; illeg
+ MOV AH,BP ; illeg
+ MOV AH,DI ; illeg
+ MOV AH,SI ; illeg
+ MOV AH,SP ; illeg
+
+ MOV BL,AL
+ MOV BL,AH
+ MOV BL,BL
+ MOV BL,BH
+ MOV BL,CL
+ MOV BL,CH
+ MOV BL,DL
+ MOV BL,DH
+
+ MOV BL,AX ; illeg
+ MOV BL,BX ; illeg
+ MOV BL,CX ; illeg
+ MOV BL,DX ; illeg
+ MOV BL,BP ; illeg
+ MOV BL,DI ; illeg
+ MOV BL,SI ; illeg
+ MOV BL,SP ; illeg
+
+ MOV BH,AL
+ MOV BH,AH
+ MOV BH,BL
+ MOV BH,BH
+ MOV BH,CL
+ MOV BH,CH
+ MOV BH,DL
+ MOV BH,DH
+
+ MOV BH,AX ; illeg
+ MOV BH,BX ; illeg
+ MOV BH,CX ; illeg
+ MOV BH,DX ; illeg
+ MOV BH,BP ; illeg
+ MOV BH,DI ; illeg
+ MOV BH,SI ; illeg
+ MOV BH,SP ; illeg
+
+ MOV CL,AL
+ MOV CL,AH
+ MOV CL,BL
+ MOV CL,BH
+ MOV CL,CL
+ MOV CL,CH
+ MOV CL,DL
+ MOV CL,DH
+
+ MOV CL,AX ; illeg
+ MOV CL,BX ; illeg
+ MOV CL,CX ; illeg
+ MOV CL,DX ; illeg
+ MOV CL,BP ; illeg
+ MOV CL,DI ; illeg
+ MOV CL,SI ; illeg
+ MOV CL,SP ; illeg
+
+ MOV CH,AL
+ MOV CH,AH
+ MOV CH,BL
+ MOV CH,BH
+ MOV CH,CL
+ MOV CH,CH
+ MOV CH,DL
+ MOV CH,DH
+
+ MOV CH,AX ; illeg
+ MOV CH,BX ; illeg
+ MOV CH,CX ; illeg
+ MOV CH,DX ; illeg
+ MOV CH,BP ; illeg
+ MOV CH,DI ; illeg
+ MOV CH,SI ; illeg
+ MOV CH,SP ; illeg
+
+ MOV DL,AL
+ MOV DL,AH
+ MOV DL,BL
+ MOV DL,BH
+ MOV DL,CL
+ MOV DL,CH
+ MOV DL,DL
+ MOV DL,DH
+
+ MOV DL,AX ; illeg
+ MOV DL,BX ; illeg
+ MOV DL,CX ; illeg
+ MOV DL,DX ; illeg
+ MOV DL,BP ; illeg
+ MOV DL,DI ; illeg
+ MOV DL,SI ; illeg
+ MOV DL,SP ; illeg
+
+ MOV DH,AL
+ MOV DH,AH
+ MOV DH,BL
+ MOV DH,BH
+ MOV DH,CL
+ MOV DH,CH
+ MOV DH,DL
+ MOV DH,DH
+
+ MOV DH,AX ; illeg
+ MOV DH,BX ; illeg
+ MOV DH,CX ; illeg
+ MOV DH,DX ; illeg
+ MOV DH,BP ; illeg
+ MOV DH,DI ; illeg
+ MOV DH,SI ; illeg
+ MOV DH,SP ; illeg
+
+ MOV AL,[AL] ; illeg
+ MOV AH,[AH] ; illeg
+ MOV BL,[BL] ; illeg
+ MOV BH,[BH] ; illeg
+ MOV CL,[CL] ; illeg
+ MOV CH,[CH] ; illeg
+ MOV DL,[DL] ; illeg
+ MOV DH,[DH] ; illeg
+
+ MOV AL,[AX] ; illeg
+ MOV AH,[BX]
+ MOV BL,[CX] ; illeg
+ MOV BH,[DX] ; illeg
+ MOV CL,[BP]
+ MOV CH,[DI]
+ MOV DL,[SI]
+ MOV DH,[SP] ; illeg
+
+ MOV AL,[AX+1] ; illeg
+ MOV AH,[BX+1]
+ MOV BL,[CX+1] ; illeg
+ MOV BH,[DX+1] ; illeg
+ MOV CL,[BP+1]
+ MOV CH,[DI+1]
+ MOV DL,[SI+1]
+ MOV DH,[SP+1] ; illeg
+
+ MOV AL,[AX-1] ; illeg
+ MOV AH,[BX-1]
+ MOV BL,[CX-1] ; illeg
+ MOV BH,[DX-1] ; illeg
+ MOV CL,[BP-1]
+ MOV CH,[DI-1]
+ MOV DL,[SI-1]
+ MOV DH,[SP-1] ; illeg
+
+ MOV AL,[AX+127] ; illeg
+ MOV AH,[BX+127]
+ MOV BL,[CX+127] ; illeg
+ MOV BH,[DX+127] ; illeg
+ MOV CL,[BP+127]
+ MOV CH,[DI+127]
+ MOV DL,[SI+127]
+ MOV DH,[SP+127] ; illeg
+
+ MOV AL,[AX-128] ; illeg
+ MOV AH,[BX-128]
+ MOV BL,[CX-128] ; illeg
+ MOV BH,[DX-128] ; illeg
+ MOV CL,[BP-128]
+ MOV CH,[DI-128]
+ MOV DL,[SI-128]
+ MOV DH,[SP-128] ; illeg
+
+ MOV AL,[AX+128] ; illeg
+ MOV AH,[BX+128]
+ MOV BL,[CX+128] ; illeg
+ MOV BH,[DX+128] ; illeg
+ MOV CL,[BP+128]
+ MOV CH,[DI+128]
+ MOV DL,[SI+128]
+ MOV DH,[SP+128] ; illeg
+
+ MOV AL,[AX-129] ; illeg
+ MOV AH,[BX-129]
+ MOV BL,[CX-129] ; illeg
+ MOV BH,[DX-129] ; illeg
+ MOV CL,[BP-129]
+ MOV CH,[DI-129]
+ MOV DL,[SI-129]
+ MOV DH,[SP-129] ; illeg
+
+ MOV AL,[AX+32767] ; illeg
+ MOV AH,[BX+32767]
+ MOV BL,[CX+32767] ; illeg
+ MOV BH,[DX+32767] ; illeg
+ MOV CL,[BP+32767]
+ MOV CH,[DI+32767]
+ MOV DL,[SI+32767]
+ MOV DH,[SP+32767] ; illeg
+
+ MOV AL,[AX-32768] ; illeg
+ MOV AH,[BX-32768]
+ MOV BL,[CX-32768] ; illeg
+ MOV BH,[DX-32768] ; illeg
+ MOV CL,[BP-32768]
+ MOV CH,[DI-32768]
+ MOV DL,[SI-32768]
+ MOV DH,[SP-32768] ; illeg
+
+ MOV AL,[AX+32768] ; illeg
+ MOV AH,[BX+32768]
+ MOV BL,[CX+32768] ; illeg
+ MOV BH,[DX+32768] ; illeg
+ MOV CL,[BP+32768]
+ MOV CH,[DI+32768]
+ MOV DL,[SI+32768]
+ MOV DH,[SP+32768] ; illeg
+
+ MOV AL,[AX-32769] ; illeg
+ MOV AH,[BX-32769]
+ MOV BL,[CX-32769] ; illeg
+ MOV BH,[DX-32769] ; illeg
+ MOV CL,[BP-32769]
+ MOV CH,[DI-32769]
+ MOV DL,[SI-32769]
+ MOV DH,[SP-32769] ; illeg
+
+ MOV AL,[AX+$7FFFFFFF] ; illeg
+ MOV AH,[BX+$7FFFFFFF] ; illeg (bounds)
+ MOV BL,[CX+$7FFFFFFF] ; illeg
+ MOV BH,[DX+$7FFFFFFF] ; illeg
+ MOV CL,[BP+$7FFFFFFF] ; illeg (bounds)
+ MOV CH,[DI+$7FFFFFFF] ; illeg (bounds)
+ MOV DL,[SI+$7FFFFFFF] ; illeg (bounds)
+ MOV DH,[SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[AX-$80000000] ; illeg
+ MOV AH,[BX-$80000000] ; illeg (bounds)
+ MOV BL,[CX-$80000000] ; illeg
+ MOV BH,[DX-$80000000] ; illeg
+ MOV CL,[BP-$80000000] ; illeg (bounds)
+ MOV CH,[DI-$80000000] ; illeg (bounds)
+ MOV DL,[SI-$80000000] ; illeg (bounds)
+ MOV DH,[SP-$80000000] ; illeg
+
+ MOV AL,[AX+AX] ; illeg
+ MOV AH,[AX+BX] ; illeg
+ MOV BL,[AX+CX] ; illeg
+ MOV BH,[AX+DX] ; illeg
+ MOV CL,[AX+BP] ; illeg
+ MOV CH,[AX+DI] ; illeg
+ MOV DL,[AX+SI] ; illeg
+ MOV DH,[AX+SP] ; illeg
+
+ MOV AL,[BX+AX] ; illeg
+ MOV AH,[BX+BX] ; illeg
+ MOV BL,[BX+CX] ; illeg
+ MOV BH,[BX+DX] ; illeg
+ MOV CL,[BX+BP] ; illeg
+ MOV CH,[BX+DI]
+ MOV DL,[BX+SI]
+ MOV DH,[BX+SP] ; illeg
+
+ MOV AL,[CX+AX] ; illeg
+ MOV AH,[CX+BX] ; illeg
+ MOV BL,[CX+CX] ; illeg
+ MOV BH,[CX+DX] ; illeg
+ MOV CL,[CX+BP] ; illeg
+ MOV CH,[CX+DI] ; illeg
+ MOV DL,[CX+SI] ; illeg
+ MOV DH,[CX+SP] ; illeg
+
+ MOV AL,[DX+AX] ; illeg
+ MOV AH,[DX+BX] ; illeg
+ MOV BL,[DX+CX] ; illeg
+ MOV BH,[DX+DX] ; illeg
+ MOV CL,[DX+BP] ; illeg
+ MOV CH,[DX+DI] ; illeg
+ MOV DL,[DX+SI] ; illeg
+ MOV DH,[DX+SP] ; illeg
+
+ MOV AL,[BP+AX] ; illeg
+ MOV AH,[BP+BX] ; illeg
+ MOV BL,[BP+CX] ; illeg
+ MOV BH,[BP+DX] ; illeg
+ MOV CL,[BP+BP] ; illeg
+ MOV CH,[BP+DI]
+ MOV DL,[BP+SI]
+ MOV DH,[BP+SP] ; illeg
+
+ MOV AL,[DI+AX] ; illeg
+ MOV AH,[DI+BX]
+ MOV BL,[DI+CX] ; illeg
+ MOV BH,[DI+DX] ; illeg
+ MOV CL,[DI+BP]
+ MOV CH,[DI+DI] ; illeg
+ MOV DL,[DI+SI] ; illeg
+ MOV DH,[DI+SP] ; illeg
+
+ MOV AL,[SI+AX] ; illeg
+ MOV AH,[SI+BX]
+ MOV BL,[SI+CX] ; illeg
+ MOV BH,[SI+DX] ; illeg
+ MOV CL,[SI+BP]
+ MOV CH,[SI+DI] ; illeg
+ MOV DL,[SI+SI] ; illeg
+ MOV DH,[SI+SP] ; illeg
+
+ MOV AL,[SP+AX] ; illeg
+ MOV AH,[SP+BX] ; illeg
+ MOV BL,[SP+CX] ; illeg
+ MOV BH,[SP+DX] ; illeg
+ MOV CL,[SP+BP] ; illeg
+ MOV CH,[SP+DI] ; illeg
+ MOV DL,[SP+SI] ; illeg
+ MOV DH,[SP+SP] ; illeg
+
+ MOV AL,[AX+AX+1] ; illeg
+ MOV AH,[AX+BX+1] ; illeg
+ MOV BL,[AX+CX+1] ; illeg
+ MOV BH,[AX+DX+1] ; illeg
+ MOV CL,[AX+BP+1] ; illeg
+ MOV CH,[AX+DI+1] ; illeg
+ MOV DL,[AX+SI+1] ; illeg
+ MOV DH,[AX+SP+1] ; illeg
+
+ MOV AL,[BX+AX+1] ; illeg
+ MOV AH,[BX+BX+1] ; illeg
+ MOV BL,[BX+CX+1] ; illeg
+ MOV BH,[BX+DX+1] ; illeg
+ MOV CL,[BX+BP+1] ; illeg
+ MOV CH,[BX+DI+1]
+ MOV DL,[BX+SI+1]
+ MOV DH,[BX+SP+1] ; illeg
+
+ MOV AL,[CX+AX+1] ; illeg
+ MOV AH,[CX+BX+1] ; illeg
+ MOV BL,[CX+CX+1] ; illeg
+ MOV BH,[CX+DX+1] ; illeg
+ MOV CL,[CX+BP+1] ; illeg
+ MOV CH,[CX+DI+1] ; illeg
+ MOV DL,[CX+SI+1] ; illeg
+ MOV DH,[CX+SP+1] ; illeg
+
+ MOV AL,[DX+AX+1] ; illeg
+ MOV AH,[DX+BX+1] ; illeg
+ MOV BL,[DX+CX+1] ; illeg
+ MOV BH,[DX+DX+1] ; illeg
+ MOV CL,[DX+BP+1] ; illeg
+ MOV CH,[DX+DI+1] ; illeg
+ MOV DL,[DX+SI+1] ; illeg
+ MOV DH,[DX+SP+1] ; illeg
+
+ MOV AL,[BP+AX+1] ; illeg
+ MOV AH,[BP+BX+1] ; illeg
+ MOV BL,[BP+CX+1] ; illeg
+ MOV BH,[BP+DX+1] ; illeg
+ MOV CL,[BP+BP+1] ; illeg
+ MOV CH,[BP+DI+1]
+ MOV DL,[BP+SI+1]
+ MOV DH,[BP+SP+1] ; illeg
+
+ MOV AL,[DI+AX+1] ; illeg
+ MOV AH,[DI+BX+1]
+ MOV BL,[DI+CX+1] ; illeg
+ MOV BH,[DI+DX+1] ; illeg
+ MOV CL,[DI+BP+1]
+ MOV CH,[DI+DI+1] ; illeg
+ MOV DL,[DI+SI+1] ; illeg
+ MOV DH,[DI+SP+1] ; illeg
+
+ MOV AL,[SI+AX+1] ; illeg
+ MOV AH,[SI+BX+1]
+ MOV BL,[SI+CX+1] ; illeg
+ MOV BH,[SI+DX+1] ; illeg
+ MOV CL,[SI+BP+1]
+ MOV CH,[SI+DI+1] ; illeg
+ MOV DL,[SI+SI+1] ; illeg
+ MOV DH,[SI+SP+1] ; illeg
+
+ MOV AL,[SP+AX+1] ; illeg
+ MOV AH,[SP+BX+1] ; illeg
+ MOV BL,[SP+CX+1] ; illeg
+ MOV BH,[SP+DX+1] ; illeg
+ MOV CL,[SP+BP+1] ; illeg
+ MOV CH,[SP+DI+1] ; illeg
+ MOV DL,[SP+SI+1] ; illeg
+ MOV DH,[SP+SP+1] ; illeg
+
+ MOV AL,[AX+AX-1] ; illeg
+ MOV AH,[AX+BX-1] ; illeg
+ MOV BL,[AX+CX-1] ; illeg
+ MOV BH,[AX+DX-1] ; illeg
+ MOV CL,[AX+BP-1] ; illeg
+ MOV CH,[AX+DI-1] ; illeg
+ MOV DL,[AX+SI-1] ; illeg
+ MOV DH,[AX+SP-1] ; illeg
+
+ MOV AL,[BX+AX-1] ; illeg
+ MOV AH,[BX+BX-1] ; illeg
+ MOV BL,[BX+CX-1] ; illeg
+ MOV BH,[BX+DX-1] ; illeg
+ MOV CL,[BX+BP-1] ; illeg
+ MOV CH,[BX+DI-1]
+ MOV DL,[BX+SI-1]
+ MOV DH,[BX+SP-1] ; illeg
+
+ MOV AL,[CX+AX-1] ; illeg
+ MOV AH,[CX+BX-1] ; illeg
+ MOV BL,[CX+CX-1] ; illeg
+ MOV BH,[CX+DX-1] ; illeg
+ MOV CL,[CX+BP-1] ; illeg
+ MOV CH,[CX+DI-1] ; illeg
+ MOV DL,[CX+SI-1] ; illeg
+ MOV DH,[CX+SP-1] ; illeg
+
+ MOV AL,[DX+AX-1] ; illeg
+ MOV AH,[DX+BX-1] ; illeg
+ MOV BL,[DX+CX-1] ; illeg
+ MOV BH,[DX+DX-1] ; illeg
+ MOV CL,[DX+BP-1] ; illeg
+ MOV CH,[DX+DI-1] ; illeg
+ MOV DL,[DX+SI-1] ; illeg
+ MOV DH,[DX+SP-1] ; illeg
+
+ MOV AL,[BP+AX-1] ; illeg
+ MOV AH,[BP+BX-1] ; illeg
+ MOV BL,[BP+CX-1] ; illeg
+ MOV BH,[BP+DX-1] ; illeg
+ MOV CL,[BP+BP-1] ; illeg
+ MOV CH,[BP+DI-1]
+ MOV DL,[BP+SI-1]
+ MOV DH,[BP+SP-1] ; illeg
+
+ MOV AL,[DI+AX-1] ; illeg
+ MOV AH,[DI+BX-1]
+ MOV BL,[DI+CX-1] ; illeg
+ MOV BH,[DI+DX-1] ; illeg
+ MOV CL,[DI+BP-1]
+ MOV CH,[DI+DI-1] ; illeg
+ MOV DL,[DI+SI-1] ; illeg
+ MOV DH,[DI+SP-1] ; illeg
+
+ MOV AL,[SI+AX-1] ; illeg
+ MOV AH,[SI+BX-1]
+ MOV BL,[SI+CX-1] ; illeg
+ MOV BH,[SI+DX-1] ; illeg
+ MOV CL,[SI+BP-1]
+ MOV CH,[SI+DI-1] ; illeg
+ MOV DL,[SI+SI-1] ; illeg
+ MOV DH,[SI+SP-1] ; illeg
+
+ MOV AL,[SP+AX-1] ; illeg
+ MOV AH,[SP+BX-1] ; illeg
+ MOV BL,[SP+CX-1] ; illeg
+ MOV BH,[SP+DX-1] ; illeg
+ MOV CL,[SP+BP-1] ; illeg
+ MOV CH,[SP+DI-1] ; illeg
+ MOV DL,[SP+SI-1] ; illeg
+ MOV DH,[SP+SP-1] ; illeg
+
+ MOV AL,[AX+AX+127] ; illeg
+ MOV AH,[AX+BX+127] ; illeg
+ MOV BL,[AX+CX+127] ; illeg
+ MOV BH,[AX+DX+127] ; illeg
+ MOV CL,[AX+BP+127] ; illeg
+ MOV CH,[AX+DI+127] ; illeg
+ MOV DL,[AX+SI+127] ; illeg
+ MOV DH,[AX+SP+127] ; illeg
+
+ MOV AL,[BX+AX+127] ; illeg
+ MOV AH,[BX+BX+127] ; illeg
+ MOV BL,[BX+CX+127] ; illeg
+ MOV BH,[BX+DX+127] ; illeg
+ MOV CL,[BX+BP+127] ; illeg
+ MOV CH,[BX+DI+127]
+ MOV DL,[BX+SI+127]
+ MOV DH,[BX+SP+127] ; illeg
+
+ MOV AL,[CX+AX+127] ; illeg
+ MOV AH,[CX+BX+127] ; illeg
+ MOV BL,[CX+CX+127] ; illeg
+ MOV BH,[CX+DX+127] ; illeg
+ MOV CL,[CX+BP+127] ; illeg
+ MOV CH,[CX+DI+127] ; illeg
+ MOV DL,[CX+SI+127] ; illeg
+ MOV DH,[CX+SP+127] ; illeg
+
+ MOV AL,[DX+AX+127] ; illeg
+ MOV AH,[DX+BX+127] ; illeg
+ MOV BL,[DX+CX+127] ; illeg
+ MOV BH,[DX+DX+127] ; illeg
+ MOV CL,[DX+BP+127] ; illeg
+ MOV CH,[DX+DI+127] ; illeg
+ MOV DL,[DX+SI+127] ; illeg
+ MOV DH,[DX+SP+127] ; illeg
+
+ MOV AL,[BP+AX+127] ; illeg
+ MOV AH,[BP+BX+127] ; illeg
+ MOV BL,[BP+CX+127] ; illeg
+ MOV BH,[BP+DX+127] ; illeg
+ MOV CL,[BP+BP+127] ; illeg
+ MOV CH,[BP+DI+127]
+ MOV DL,[BP+SI+127]
+ MOV DH,[BP+SP+127] ; illeg
+
+ MOV AL,[DI+AX+127] ; illeg
+ MOV AH,[DI+BX+127]
+ MOV BL,[DI+CX+127] ; illeg
+ MOV BH,[DI+DX+127] ; illeg
+ MOV CL,[DI+BP+127]
+ MOV CH,[DI+DI+127] ; illeg
+ MOV DL,[DI+SI+127] ; illeg
+ MOV DH,[DI+SP+127] ; illeg
+
+ MOV AL,[SI+AX+127] ; illeg
+ MOV AH,[SI+BX+127]
+ MOV BL,[SI+CX+127] ; illeg
+ MOV BH,[SI+DX+127] ; illeg
+ MOV CL,[SI+BP+127]
+ MOV CH,[SI+DI+127] ; illeg
+ MOV DL,[SI+SI+127] ; illeg
+ MOV DH,[SI+SP+127] ; illeg
+
+ MOV AL,[SP+AX+127] ; illeg
+ MOV AH,[SP+BX+127] ; illeg
+ MOV BL,[SP+CX+127] ; illeg
+ MOV BH,[SP+DX+127] ; illeg
+ MOV CL,[SP+BP+127] ; illeg
+ MOV CH,[SP+DI+127] ; illeg
+ MOV DL,[SP+SI+127] ; illeg
+ MOV DH,[SP+SP+127] ; illeg
+
+ MOV AL,[AX+AX-128] ; illeg
+ MOV AH,[AX+BX-128] ; illeg
+ MOV BL,[AX+CX-128] ; illeg
+ MOV BH,[AX+DX-128] ; illeg
+ MOV CL,[AX+BP-128] ; illeg
+ MOV CH,[AX+DI-128] ; illeg
+ MOV DL,[AX+SI-128] ; illeg
+ MOV DH,[AX+SP-128] ; illeg
+
+ MOV AL,[BX+AX-128] ; illeg
+ MOV AH,[BX+BX-128] ; illeg
+ MOV BL,[BX+CX-128] ; illeg
+ MOV BH,[BX+DX-128] ; illeg
+ MOV CL,[BX+BP-128] ; illeg
+ MOV CH,[BX+DI-128]
+ MOV DL,[BX+SI-128]
+ MOV DH,[BX+SP-128] ; illeg
+
+ MOV AL,[CX+AX-128] ; illeg
+ MOV AH,[CX+BX-128] ; illeg
+ MOV BL,[CX+CX-128] ; illeg
+ MOV BH,[CX+DX-128] ; illeg
+ MOV CL,[CX+BP-128] ; illeg
+ MOV CH,[CX+DI-128] ; illeg
+ MOV DL,[CX+SI-128] ; illeg
+ MOV DH,[CX+SP-128] ; illeg
+
+ MOV AL,[DX+AX-128] ; illeg
+ MOV AH,[DX+BX-128] ; illeg
+ MOV BL,[DX+CX-128] ; illeg
+ MOV BH,[DX+DX-128] ; illeg
+ MOV CL,[DX+BP-128] ; illeg
+ MOV CH,[DX+DI-128] ; illeg
+ MOV DL,[DX+SI-128] ; illeg
+ MOV DH,[DX+SP-128] ; illeg
+
+ MOV AL,[BP+AX-128] ; illeg
+ MOV AH,[BP+BX-128] ; illeg
+ MOV BL,[BP+CX-128] ; illeg
+ MOV BH,[BP+DX-128] ; illeg
+ MOV CL,[BP+BP-128] ; illeg
+ MOV CH,[BP+DI-128]
+ MOV DL,[BP+SI-128]
+ MOV DH,[BP+SP-128] ; illeg
+
+ MOV AL,[DI+AX-128] ; illeg
+ MOV AH,[DI+BX-128]
+ MOV BL,[DI+CX-128] ; illeg
+ MOV BH,[DI+DX-128] ; illeg
+ MOV CL,[DI+BP-128]
+ MOV CH,[DI+DI-128] ; illeg
+ MOV DL,[DI+SI-128] ; illeg
+ MOV DH,[DI+SP-128] ; illeg
+
+ MOV AL,[SI+AX-128] ; illeg
+ MOV AH,[SI+BX-128]
+ MOV BL,[SI+CX-128] ; illeg
+ MOV BH,[SI+DX-128] ; illeg
+ MOV CL,[SI+BP-128]
+ MOV CH,[SI+DI-128] ; illeg
+ MOV DL,[SI+SI-128] ; illeg
+ MOV DH,[SI+SP-128] ; illeg
+
+ MOV AL,[SP+AX-128] ; illeg
+ MOV AH,[SP+BX-128] ; illeg
+ MOV BL,[SP+CX-128] ; illeg
+ MOV BH,[SP+DX-128] ; illeg
+ MOV CL,[SP+BP-128] ; illeg
+ MOV CH,[SP+DI-128] ; illeg
+ MOV DL,[SP+SI-128] ; illeg
+ MOV DH,[SP+SP-128] ; illeg
+
+ MOV AL,[AX+AX+128] ; illeg
+ MOV AH,[AX+BX+128] ; illeg
+ MOV BL,[AX+CX+128] ; illeg
+ MOV BH,[AX+DX+128] ; illeg
+ MOV CL,[AX+BP+128] ; illeg
+ MOV CH,[AX+DI+128] ; illeg
+ MOV DL,[AX+SI+128] ; illeg
+ MOV DH,[AX+SP+128] ; illeg
+
+ MOV AL,[BX+AX+128] ; illeg
+ MOV AH,[BX+BX+128] ; illeg
+ MOV BL,[BX+CX+128] ; illeg
+ MOV BH,[BX+DX+128] ; illeg
+ MOV CL,[BX+BP+128] ; illeg
+ MOV CH,[BX+DI+128]
+ MOV DL,[BX+SI+128]
+ MOV DH,[BX+SP+128] ; illeg
+
+ MOV AL,[CX+AX+128] ; illeg
+ MOV AH,[CX+BX+128] ; illeg
+ MOV BL,[CX+CX+128] ; illeg
+ MOV BH,[CX+DX+128] ; illeg
+ MOV CL,[CX+BP+128] ; illeg
+ MOV CH,[CX+DI+128] ; illeg
+ MOV DL,[CX+SI+128] ; illeg
+ MOV DH,[CX+SP+128] ; illeg
+
+ MOV AL,[DX+AX+128] ; illeg
+ MOV AH,[DX+BX+128] ; illeg
+ MOV BL,[DX+CX+128] ; illeg
+ MOV BH,[DX+DX+128] ; illeg
+ MOV CL,[DX+BP+128] ; illeg
+ MOV CH,[DX+DI+128] ; illeg
+ MOV DL,[DX+SI+128] ; illeg
+ MOV DH,[DX+SP+128] ; illeg
+
+ MOV AL,[BP+AX+128] ; illeg
+ MOV AH,[BP+BX+128] ; illeg
+ MOV BL,[BP+CX+128] ; illeg
+ MOV BH,[BP+DX+128] ; illeg
+ MOV CL,[BP+BP+128] ; illeg
+ MOV CH,[BP+DI+128]
+ MOV DL,[BP+SI+128]
+ MOV DH,[BP+SP+128] ; illeg
+
+ MOV AL,[DI+AX+128] ; illeg
+ MOV AH,[DI+BX+128]
+ MOV BL,[DI+CX+128] ; illeg
+ MOV BH,[DI+DX+128] ; illeg
+ MOV CL,[DI+BP+128]
+ MOV CH,[DI+DI+128] ; illeg
+ MOV DL,[DI+SI+128] ; illeg
+ MOV DH,[DI+SP+128] ; illeg
+
+ MOV AL,[SI+AX+128] ; illeg
+ MOV AH,[SI+BX+128]
+ MOV BL,[SI+CX+128] ; illeg
+ MOV BH,[SI+DX+128] ; illeg
+ MOV CL,[SI+BP+128]
+ MOV CH,[SI+DI+128] ; illeg
+ MOV DL,[SI+SI+128] ; illeg
+ MOV DH,[SI+SP+128] ; illeg
+
+ MOV AL,[SP+AX+128] ; illeg
+ MOV AH,[SP+BX+128] ; illeg
+ MOV BL,[SP+CX+128] ; illeg
+ MOV BH,[SP+DX+128] ; illeg
+ MOV CL,[SP+BP+128] ; illeg
+ MOV CH,[SP+DI+128] ; illeg
+ MOV DL,[SP+SI+128] ; illeg
+ MOV DH,[SP+SP+128] ; illeg
+
+ MOV AL,[AX+AX-129] ; illeg
+ MOV AH,[AX+BX-129] ; illeg
+ MOV BL,[AX+CX-129] ; illeg
+ MOV BH,[AX+DX-129] ; illeg
+ MOV CL,[AX+BP-129] ; illeg
+ MOV CH,[AX+DI-129] ; illeg
+ MOV DL,[AX+SI-129] ; illeg
+ MOV DH,[AX+SP-129] ; illeg
+
+ MOV AL,[BX+AX-129] ; illeg
+ MOV AH,[BX+BX-129] ; illeg
+ MOV BL,[BX+CX-129] ; illeg
+ MOV BH,[BX+DX-129] ; illeg
+ MOV CL,[BX+BP-129] ; illeg
+ MOV CH,[BX+DI-129]
+ MOV DL,[BX+SI-129]
+ MOV DH,[BX+SP-129] ; illeg
+
+ MOV AL,[CX+AX-129] ; illeg
+ MOV AH,[CX+BX-129] ; illeg
+ MOV BL,[CX+CX-129] ; illeg
+ MOV BH,[CX+DX-129] ; illeg
+ MOV CL,[CX+BP-129] ; illeg
+ MOV CH,[CX+DI-129] ; illeg
+ MOV DL,[CX+SI-129] ; illeg
+ MOV DH,[CX+SP-129] ; illeg
+
+ MOV AL,[DX+AX-129] ; illeg
+ MOV AH,[DX+BX-129] ; illeg
+ MOV BL,[DX+CX-129] ; illeg
+ MOV BH,[DX+DX-129] ; illeg
+ MOV CL,[DX+BP-129] ; illeg
+ MOV CH,[DX+DI-129] ; illeg
+ MOV DL,[DX+SI-129] ; illeg
+ MOV DH,[DX+SP-129] ; illeg
+
+ MOV AL,[BP+AX-129] ; illeg
+ MOV AH,[BP+BX-129] ; illeg
+ MOV BL,[BP+CX-129] ; illeg
+ MOV BH,[BP+DX-129] ; illeg
+ MOV CL,[BP+BP-129] ; illeg
+ MOV CH,[BP+DI-129]
+ MOV DL,[BP+SI-129]
+ MOV DH,[BP+SP-129] ; illeg
+
+ MOV AL,[DI+AX-129] ; illeg
+ MOV AH,[DI+BX-129]
+ MOV BL,[DI+CX-129] ; illeg
+ MOV BH,[DI+DX-129] ; illeg
+ MOV CL,[DI+BP-129]
+ MOV CH,[DI+DI-129] ; illeg
+ MOV DL,[DI+SI-129] ; illeg
+ MOV DH,[DI+SP-129] ; illeg
+
+ MOV AL,[SI+AX-129] ; illeg
+ MOV AH,[SI+BX-129]
+ MOV BL,[SI+CX-129] ; illeg
+ MOV BH,[SI+DX-129] ; illeg
+ MOV CL,[SI+BP-129]
+ MOV CH,[SI+DI-129] ; illeg
+ MOV DL,[SI+SI-129] ; illeg
+ MOV DH,[SI+SP-129] ; illeg
+
+ MOV AL,[SP+AX-129] ; illeg
+ MOV AH,[SP+BX-129] ; illeg
+ MOV BL,[SP+CX-129] ; illeg
+ MOV BH,[SP+DX-129] ; illeg
+ MOV CL,[SP+BP-129] ; illeg
+ MOV CH,[SP+DI-129] ; illeg
+ MOV DL,[SP+SI-129] ; illeg
+ MOV DH,[SP+SP-129] ; illeg
+
+ MOV AL,[AX+AX+32767] ; illeg
+ MOV AH,[AX+BX+32767] ; illeg
+ MOV BL,[AX+CX+32767] ; illeg
+ MOV BH,[AX+DX+32767] ; illeg
+ MOV CL,[AX+BP+32767] ; illeg
+ MOV CH,[AX+DI+32767] ; illeg
+ MOV DL,[AX+SI+32767] ; illeg
+ MOV DH,[AX+SP+32767] ; illeg
+
+ MOV AL,[BX+AX+32767] ; illeg
+ MOV AH,[BX+BX+32767] ; illeg
+ MOV BL,[BX+CX+32767] ; illeg
+ MOV BH,[BX+DX+32767] ; illeg
+ MOV CL,[BX+BP+32767] ; illeg
+ MOV CH,[BX+DI+32767]
+ MOV DL,[BX+SI+32767]
+ MOV DH,[BX+SP+32767] ; illeg
+
+ MOV AL,[CX+AX+32767] ; illeg
+ MOV AH,[CX+BX+32767] ; illeg
+ MOV BL,[CX+CX+32767] ; illeg
+ MOV BH,[CX+DX+32767] ; illeg
+ MOV CL,[CX+BP+32767] ; illeg
+ MOV CH,[CX+DI+32767] ; illeg
+ MOV DL,[CX+SI+32767] ; illeg
+ MOV DH,[CX+SP+32767] ; illeg
+
+ MOV AL,[DX+AX+32767] ; illeg
+ MOV AH,[DX+BX+32767] ; illeg
+ MOV BL,[DX+CX+32767] ; illeg
+ MOV BH,[DX+DX+32767] ; illeg
+ MOV CL,[DX+BP+32767] ; illeg
+ MOV CH,[DX+DI+32767] ; illeg
+ MOV DL,[DX+SI+32767] ; illeg
+ MOV DH,[DX+SP+32767] ; illeg
+
+ MOV AL,[BP+AX+32767] ; illeg
+ MOV AH,[BP+BX+32767] ; illeg
+ MOV BL,[BP+CX+32767] ; illeg
+ MOV BH,[BP+DX+32767] ; illeg
+ MOV CL,[BP+BP+32767] ; illeg
+ MOV CH,[BP+DI+32767]
+ MOV DL,[BP+SI+32767]
+ MOV DH,[BP+SP+32767] ; illeg
+
+ MOV AL,[DI+AX+32767] ; illeg
+ MOV AH,[DI+BX+32767]
+ MOV BL,[DI+CX+32767] ; illeg
+ MOV BH,[DI+DX+32767] ; illeg
+ MOV CL,[DI+BP+32767]
+ MOV CH,[DI+DI+32767] ; illeg
+ MOV DL,[DI+SI+32767] ; illeg
+ MOV DH,[DI+SP+32767] ; illeg
+
+ MOV AL,[SI+AX+32767] ; illeg
+ MOV AH,[SI+BX+32767]
+ MOV BL,[SI+CX+32767] ; illeg
+ MOV BH,[SI+DX+32767] ; illeg
+ MOV CL,[SI+BP+32767]
+ MOV CH,[SI+DI+32767] ; illeg
+ MOV DL,[SI+SI+32767] ; illeg
+ MOV DH,[SI+SP+32767] ; illeg
+
+ MOV AL,[SP+AX+32767] ; illeg
+ MOV AH,[SP+BX+32767] ; illeg
+ MOV BL,[SP+CX+32767] ; illeg
+ MOV BH,[SP+DX+32767] ; illeg
+ MOV CL,[SP+BP+32767] ; illeg
+ MOV CH,[SP+DI+32767] ; illeg
+ MOV DL,[SP+SI+32767] ; illeg
+ MOV DH,[SP+SP+32767] ; illeg
+
+ MOV AL,[AX+AX-32768] ; illeg
+ MOV AH,[AX+BX-32768] ; illeg
+ MOV BL,[AX+CX-32768] ; illeg
+ MOV BH,[AX+DX-32768] ; illeg
+ MOV CL,[AX+BP-32768] ; illeg
+ MOV CH,[AX+DI-32768] ; illeg
+ MOV DL,[AX+SI-32768] ; illeg
+ MOV DH,[AX+SP-32768] ; illeg
+
+ MOV AL,[BX+AX-32768] ; illeg
+ MOV AH,[BX+BX-32768] ; illeg
+ MOV BL,[BX+CX-32768] ; illeg
+ MOV BH,[BX+DX-32768] ; illeg
+ MOV CL,[BX+BP-32768] ; illeg
+ MOV CH,[BX+DI-32768]
+ MOV DL,[BX+SI-32768]
+ MOV DH,[BX+SP-32768] ; illeg
+
+ MOV AL,[CX+AX-32768] ; illeg
+ MOV AH,[CX+BX-32768] ; illeg
+ MOV BL,[CX+CX-32768] ; illeg
+ MOV BH,[CX+DX-32768] ; illeg
+ MOV CL,[CX+BP-32768] ; illeg
+ MOV CH,[CX+DI-32768] ; illeg
+ MOV DL,[CX+SI-32768] ; illeg
+ MOV DH,[CX+SP-32768] ; illeg
+
+ MOV AL,[DX+AX-32768] ; illeg
+ MOV AH,[DX+BX-32768] ; illeg
+ MOV BL,[DX+CX-32768] ; illeg
+ MOV BH,[DX+DX-32768] ; illeg
+ MOV CL,[DX+BP-32768] ; illeg
+ MOV CH,[DX+DI-32768] ; illeg
+ MOV DL,[DX+SI-32768] ; illeg
+ MOV DH,[DX+SP-32768] ; illeg
+
+ MOV AL,[BP+AX-32768] ; illeg
+ MOV AH,[BP+BX-32768] ; illeg
+ MOV BL,[BP+CX-32768] ; illeg
+ MOV BH,[BP+DX-32768] ; illeg
+ MOV CL,[BP+BP-32768] ; illeg
+ MOV CH,[BP+DI-32768]
+ MOV DL,[BP+SI-32768]
+ MOV DH,[BP+SP-32768] ; illeg
+
+ MOV AL,[DI+AX-32768] ; illeg
+ MOV AH,[DI+BX-32768]
+ MOV BL,[DI+CX-32768] ; illeg
+ MOV BH,[DI+DX-32768] ; illeg
+ MOV CL,[DI+BP-32768]
+ MOV CH,[DI+DI-32768] ; illeg
+ MOV DL,[DI+SI-32768] ; illeg
+ MOV DH,[DI+SP-32768] ; illeg
+
+ MOV AL,[SI+AX-32768] ; illeg
+ MOV AH,[SI+BX-32768]
+ MOV BL,[SI+CX-32768] ; illeg
+ MOV BH,[SI+DX-32768] ; illeg
+ MOV CL,[SI+BP-32768]
+ MOV CH,[SI+DI-32768] ; illeg
+ MOV DL,[SI+SI-32768] ; illeg
+ MOV DH,[SI+SP-32768] ; illeg
+
+ MOV AL,[SP+AX-32768] ; illeg
+ MOV AH,[SP+BX-32768] ; illeg
+ MOV BL,[SP+CX-32768] ; illeg
+ MOV BH,[SP+DX-32768] ; illeg
+ MOV CL,[SP+BP-32768] ; illeg
+ MOV CH,[SP+DI-32768] ; illeg
+ MOV DL,[SP+SI-32768] ; illeg
+ MOV DH,[SP+SP-32768] ; illeg
+
+ MOV AL,[AX+AX+32768] ; illeg
+ MOV AH,[AX+BX+32768] ; illeg
+ MOV BL,[AX+CX+32768] ; illeg
+ MOV BH,[AX+DX+32768] ; illeg
+ MOV CL,[AX+BP+32768] ; illeg
+ MOV CH,[AX+DI+32768] ; illeg
+ MOV DL,[AX+SI+32768] ; illeg
+ MOV DH,[AX+SP+32768] ; illeg
+
+ MOV AL,[BX+AX+32768] ; illeg
+ MOV AH,[BX+BX+32768] ; illeg
+ MOV BL,[BX+CX+32768] ; illeg
+ MOV BH,[BX+DX+32768] ; illeg
+ MOV CL,[BX+BP+32768] ; illeg
+ MOV CH,[BX+DI+32768]
+ MOV DL,[BX+SI+32768]
+ MOV DH,[BX+SP+32768] ; illeg
+
+ MOV AL,[CX+AX+32768] ; illeg
+ MOV AH,[CX+BX+32768] ; illeg
+ MOV BL,[CX+CX+32768] ; illeg
+ MOV BH,[CX+DX+32768] ; illeg
+ MOV CL,[CX+BP+32768] ; illeg
+ MOV CH,[CX+DI+32768] ; illeg
+ MOV DL,[CX+SI+32768] ; illeg
+ MOV DH,[CX+SP+32768] ; illeg
+
+ MOV AL,[DX+AX+32768] ; illeg
+ MOV AH,[DX+BX+32768] ; illeg
+ MOV BL,[DX+CX+32768] ; illeg
+ MOV BH,[DX+DX+32768] ; illeg
+ MOV CL,[DX+BP+32768] ; illeg
+ MOV CH,[DX+DI+32768] ; illeg
+ MOV DL,[DX+SI+32768] ; illeg
+ MOV DH,[DX+SP+32768] ; illeg
+
+ MOV AL,[BP+AX+32768] ; illeg
+ MOV AH,[BP+BX+32768] ; illeg
+ MOV BL,[BP+CX+32768] ; illeg
+ MOV BH,[BP+DX+32768] ; illeg
+ MOV CL,[BP+BP+32768] ; illeg
+ MOV CH,[BP+DI+32768]
+ MOV DL,[BP+SI+32768]
+ MOV DH,[BP+SP+32768] ; illeg
+
+ MOV AL,[DI+AX+32768] ; illeg
+ MOV AH,[DI+BX+32768]
+ MOV BL,[DI+CX+32768] ; illeg
+ MOV BH,[DI+DX+32768] ; illeg
+ MOV CL,[DI+BP+32768]
+ MOV CH,[DI+DI+32768] ; illeg
+ MOV DL,[DI+SI+32768] ; illeg
+ MOV DH,[DI+SP+32768] ; illeg
+
+ MOV AL,[SI+AX+32768] ; illeg
+ MOV AH,[SI+BX+32768]
+ MOV BL,[SI+CX+32768] ; illeg
+ MOV BH,[SI+DX+32768] ; illeg
+ MOV CL,[SI+BP+32768]
+ MOV CH,[SI+DI+32768] ; illeg
+ MOV DL,[SI+SI+32768] ; illeg
+ MOV DH,[SI+SP+32768] ; illeg
+
+ MOV AL,[SP+AX+32768] ; illeg
+ MOV AH,[SP+BX+32768] ; illeg
+ MOV BL,[SP+CX+32768] ; illeg
+ MOV BH,[SP+DX+32768] ; illeg
+ MOV CL,[SP+BP+32768] ; illeg
+ MOV CH,[SP+DI+32768] ; illeg
+ MOV DL,[SP+SI+32768] ; illeg
+ MOV DH,[SP+SP+32768] ; illeg
+
+ MOV AL,[AX+AX-32769] ; illeg
+ MOV AH,[AX+BX-32769] ; illeg
+ MOV BL,[AX+CX-32769] ; illeg
+ MOV BH,[AX+DX-32769] ; illeg
+ MOV CL,[AX+BP-32769] ; illeg
+ MOV CH,[AX+DI-32769] ; illeg
+ MOV DL,[AX+SI-32769] ; illeg
+ MOV DH,[AX+SP-32769] ; illeg
+
+ MOV AL,[BX+AX-32769] ; illeg
+ MOV AH,[BX+BX-32769] ; illeg
+ MOV BL,[BX+CX-32769] ; illeg
+ MOV BH,[BX+DX-32769] ; illeg
+ MOV CL,[BX+BP-32769] ; illeg
+ MOV CH,[BX+DI-32769]
+ MOV DL,[BX+SI-32769]
+ MOV DH,[BX+SP-32769] ; illeg
+
+ MOV AL,[CX+AX-32769] ; illeg
+ MOV AH,[CX+BX-32769] ; illeg
+ MOV BL,[CX+CX-32769] ; illeg
+ MOV BH,[CX+DX-32769] ; illeg
+ MOV CL,[CX+BP-32769] ; illeg
+ MOV CH,[CX+DI-32769] ; illeg
+ MOV DL,[CX+SI-32769] ; illeg
+ MOV DH,[CX+SP-32769] ; illeg
+
+ MOV AL,[DX+AX-32769] ; illeg
+ MOV AH,[DX+BX-32769] ; illeg
+ MOV BL,[DX+CX-32769] ; illeg
+ MOV BH,[DX+DX-32769] ; illeg
+ MOV CL,[DX+BP-32769] ; illeg
+ MOV CH,[DX+DI-32769] ; illeg
+ MOV DL,[DX+SI-32769] ; illeg
+ MOV DH,[DX+SP-32769] ; illeg
+
+ MOV AL,[BP+AX-32769] ; illeg
+ MOV AH,[BP+BX-32769] ; illeg
+ MOV BL,[BP+CX-32769] ; illeg
+ MOV BH,[BP+DX-32769] ; illeg
+ MOV CL,[BP+BP-32769] ; illeg
+ MOV CH,[BP+DI-32769]
+ MOV DL,[BP+SI-32769]
+ MOV DH,[BP+SP-32769] ; illeg
+
+ MOV AL,[DI+AX-32769] ; illeg
+ MOV AH,[DI+BX-32769]
+ MOV BL,[DI+CX-32769] ; illeg
+ MOV BH,[DI+DX-32769] ; illeg
+ MOV CL,[DI+BP-32769]
+ MOV CH,[DI+DI-32769] ; illeg
+ MOV DL,[DI+SI-32769] ; illeg
+ MOV DH,[DI+SP-32769] ; illeg
+
+ MOV AL,[SI+AX-32769] ; illeg
+ MOV AH,[SI+BX-32769]
+ MOV BL,[SI+CX-32769] ; illeg
+ MOV BH,[SI+DX-32769] ; illeg
+ MOV CL,[SI+BP-32769]
+ MOV CH,[SI+DI-32769] ; illeg
+ MOV DL,[SI+SI-32769] ; illeg
+ MOV DH,[SI+SP-32769] ; illeg
+
+ MOV AL,[SP+AX-32769] ; illeg
+ MOV AH,[SP+BX-32769] ; illeg
+ MOV BL,[SP+CX-32769] ; illeg
+ MOV BH,[SP+DX-32769] ; illeg
+ MOV CL,[SP+BP-32769] ; illeg
+ MOV CH,[SP+DI-32769] ; illeg
+ MOV DL,[SP+SI-32769] ; illeg
+ MOV DH,[SP+SP-32769] ; illeg
+
+ MOV AL,[AX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[AX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[AX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[AX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[AX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[AX+DI+$7FFFFFFF] ; illeg
+ MOV DL,[AX+SI+$7FFFFFFF] ; illeg
+ MOV DH,[AX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[BX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[BX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[BX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[BX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[BX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[BX+DI+$7FFFFFFF] ; illeg (bounds)
+ MOV DL,[BX+SI+$7FFFFFFF] ; illeg (bounds)
+ MOV DH,[BX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[CX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[CX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[CX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[CX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[CX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[CX+DI+$7FFFFFFF] ; illeg
+ MOV DL,[CX+SI+$7FFFFFFF] ; illeg
+ MOV DH,[CX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[DX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[DX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[DX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[DX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[DX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[DX+DI+$7FFFFFFF] ; illeg
+ MOV DL,[DX+SI+$7FFFFFFF] ; illeg
+ MOV DH,[DX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[BP+AX+$7FFFFFFF] ; illeg
+ MOV AH,[BP+BX+$7FFFFFFF] ; illeg
+ MOV BL,[BP+CX+$7FFFFFFF] ; illeg
+ MOV BH,[BP+DX+$7FFFFFFF] ; illeg
+ MOV CL,[BP+BP+$7FFFFFFF] ; illeg
+ MOV CH,[BP+DI+$7FFFFFFF] ; illeg (bounds)
+ MOV DL,[BP+SI+$7FFFFFFF] ; illeg (bounds)
+ MOV DH,[BP+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[DI+AX+$7FFFFFFF] ; illeg
+ MOV AH,[DI+BX+$7FFFFFFF] ; illeg (bounds)
+ MOV BL,[DI+CX+$7FFFFFFF] ; illeg
+ MOV BH,[DI+DX+$7FFFFFFF] ; illeg
+ MOV CL,[DI+BP+$7FFFFFFF] ; illeg (bounds)
+ MOV CH,[DI+DI+$7FFFFFFF] ; illeg
+ MOV DL,[DI+SI+$7FFFFFFF] ; illeg
+ MOV DH,[DI+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[SI+AX+$7FFFFFFF] ; illeg
+ MOV AH,[SI+BX+$7FFFFFFF] ; illeg (bounds)
+ MOV BL,[SI+CX+$7FFFFFFF] ; illeg
+ MOV BH,[SI+DX+$7FFFFFFF] ; illeg
+ MOV CL,[SI+BP+$7FFFFFFF] ; illeg (bounds)
+ MOV CH,[SI+DI+$7FFFFFFF] ; illeg
+ MOV DL,[SI+SI+$7FFFFFFF] ; illeg
+ MOV DH,[SI+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[SP+AX+$7FFFFFFF] ; illeg
+ MOV AH,[SP+BX+$7FFFFFFF] ; illeg
+ MOV BL,[SP+CX+$7FFFFFFF] ; illeg
+ MOV BH,[SP+DX+$7FFFFFFF] ; illeg
+ MOV CL,[SP+BP+$7FFFFFFF] ; illeg
+ MOV CH,[SP+DI+$7FFFFFFF] ; illeg
+ MOV DL,[SP+SI+$7FFFFFFF] ; illeg
+ MOV DH,[SP+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[AX+AX-$80000000] ; illeg
+ MOV AH,[AX+BX-$80000000] ; illeg
+ MOV BL,[AX+CX-$80000000] ; illeg
+ MOV BH,[AX+DX-$80000000] ; illeg
+ MOV CL,[AX+BP-$80000000] ; illeg
+ MOV CH,[AX+DI-$80000000] ; illeg
+ MOV DL,[AX+SI-$80000000] ; illeg
+ MOV DH,[AX+SP-$80000000] ; illeg
+
+ MOV AL,[BX+AX-$80000000] ; illeg
+ MOV AH,[BX+BX-$80000000] ; illeg
+ MOV BL,[BX+CX-$80000000] ; illeg
+ MOV BH,[BX+DX-$80000000] ; illeg
+ MOV CL,[BX+BP-$80000000] ; illeg
+ MOV CH,[BX+DI-$80000000] ; illeg (bounds)
+ MOV DL,[BX+SI-$80000000] ; illeg (bounds)
+ MOV DH,[BX+SP-$80000000] ; illeg
+
+ MOV AL,[CX+AX-$80000000] ; illeg
+ MOV AH,[CX+BX-$80000000] ; illeg
+ MOV BL,[CX+CX-$80000000] ; illeg
+ MOV BH,[CX+DX-$80000000] ; illeg
+ MOV CL,[CX+BP-$80000000] ; illeg
+ MOV CH,[CX+DI-$80000000] ; illeg
+ MOV DL,[CX+SI-$80000000] ; illeg
+ MOV DH,[CX+SP-$80000000] ; illeg
+
+ MOV AL,[DX+AX-$80000000] ; illeg
+ MOV AH,[DX+BX-$80000000] ; illeg
+ MOV BL,[DX+CX-$80000000] ; illeg
+ MOV BH,[DX+DX-$80000000] ; illeg
+ MOV CL,[DX+BP-$80000000] ; illeg
+ MOV CH,[DX+DI-$80000000] ; illeg
+ MOV DL,[DX+SI-$80000000] ; illeg
+ MOV DH,[DX+SP-$80000000] ; illeg
+
+ MOV AL,[BP+AX-$80000000] ; illeg
+ MOV AH,[BP+BX-$80000000] ; illeg
+ MOV BL,[BP+CX-$80000000] ; illeg
+ MOV BH,[BP+DX-$80000000] ; illeg
+ MOV CL,[BP+BP-$80000000] ; illeg
+ MOV CH,[BP+DI-$80000000] ; illeg (bounds)
+ MOV DL,[BP+SI-$80000000] ; illeg (bounds)
+ MOV DH,[BP+SP-$80000000] ; illeg
+
+ MOV AL,[DI+AX-$80000000] ; illeg
+ MOV AH,[DI+BX-$80000000] ; illeg (bounds)
+ MOV BL,[DI+CX-$80000000] ; illeg
+ MOV BH,[DI+DX-$80000000] ; illeg
+ MOV CL,[DI+BP-$80000000] ; illeg (bounds)
+ MOV CH,[DI+DI-$80000000] ; illeg
+ MOV DL,[DI+SI-$80000000] ; illeg
+ MOV DH,[DI+SP-$80000000] ; illeg
+
+ MOV AL,[SI+AX-$80000000] ; illeg
+ MOV AH,[SI+BX-$80000000] ; illeg (bounds)
+ MOV BL,[SI+CX-$80000000] ; illeg
+ MOV BH,[SI+DX-$80000000] ; illeg
+ MOV CL,[SI+BP-$80000000] ; illeg (bounds)
+ MOV CH,[SI+DI-$80000000] ; illeg
+ MOV DL,[SI+SI-$80000000] ; illeg
+ MOV DH,[SI+SP-$80000000] ; illeg
+
+ MOV AL,[SP+AX-$80000000] ; illeg
+ MOV AH,[SP+BX-$80000000] ; illeg
+ MOV BL,[SP+CX-$80000000] ; illeg
+ MOV BH,[SP+DX-$80000000] ; illeg
+ MOV CL,[SP+BP-$80000000] ; illeg
+ MOV CH,[SP+DI-$80000000] ; illeg
+ MOV DL,[SP+SI-$80000000] ; illeg
+ MOV DH,[SP+SP-$80000000] ; illeg
diff --git a/as/asm/f.asm b/as/asm/f.asm
new file mode 100644
index 0000000..c067bf9
--- /dev/null
+++ b/as/asm/f.asm
@@ -0,0 +1,114 @@
+; [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st]
+ fadd qword [ebx]
+ fadd dword [ebx]
+ fadd st,st(1)
+ fadd st(1),st
+ fdiv qword [ebx]
+ fdiv dword [ebx]
+ fdiv st,st(1) ; special swapping for this
+
+; [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st
+ faddp st(1),st
+
+; [fbld fbstp] mem10r
+ fbld tbyte [ebx]
+ fbstp tbyte [ebx]
+
+; [fcom fcomp] [mem4r mem8r optional-st(i)]
+ fcom dword [ebx]
+ fcom qword [ebx]
+ fcom
+ fcom st(1)
+
+; ffree st(i)
+ ffree st(1)
+
+; [fucom fucomp fxch] optional-st(i)
+ fucom
+ fucom st(1)
+
+; [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i]
+ fiadd word [ebx]
+ fiadd dword [ebx]
+
+; [fild fistp] [mem2i mem4i mem8i]
+ fild word [ebx]
+ fild dword [ebx]
+ fild qword [ebx]
+
+; [fld fstp] [mem4r mem8r mem10r st(i)]
+ fld dword [ebx]
+ fld qword [ebx]
+ fld tbyte [ebx]
+ fld st(1)
+
+; [fldcw fnstcw] mem2i
+ fldcw word [ebx]
+ fnstcw word [ebx]
+
+; [fldenv fnsave fnstenv frstor] mem
+ fldenv [ebx]
+ fnsave [ebx]
+ fnstenv [ebx]
+ frstor [ebx]
+
+; fnstsw [mem2i ax]
+ fnstsw word [ebx]
+ fnstsw ax
+
+; fst [mem4r mem8r st(i)]
+ fst dword [ebx]
+ fst qword [ebx]
+ fst st(1)
+
+; fstcw mem2i (wait)
+ fstcw word [ebx]
+
+; fstsw [mem2i ax] (wait)
+ fstsw word [ebx]
+ fstsw ax
+
+; [fsave fstenv] mem (wait)
+ fsave [ebx]
+ fstenv [ebx]
+
+; [fxxx] (no operands)
+ fnop ; D9D0
+ fchs ; D9E0
+ fabs ; D9E1
+ ftst ; D9E4
+ fxam ; D9E5
+ fld1 ; D9E8
+ fldl2t ; D9E9
+ fldl2e ; D9EA
+ fldpi ; D9EB
+ fldlg2 ; D9EC
+ fldln2 ; D9ED
+ fldz ; D9EE
+ f2xm1 ; D9F0
+ fyl2x ; D9F1
+ fptan ; D9F2
+ fpatan ; D9F3
+ fxtract ; D9F4
+ fprem1 ; D9F5
+ fdecstp ; D9F6
+ fincstp ; D9F7
+ fprem ; D9F8
+ fyl2xp1 ; D9F9
+ fsqrt ; D9FA
+ fsincos ; D9FB
+ frndint ; D9FC
+ fscale ; D9FD
+ fsin ; D9FE
+ fcos ; D9FF
+ fucompp ; DAE9
+ feni ; 9BDBE0
+ fneni ; DBE0
+ fdisi ; 9BDBE1
+ fndisi ; DBE1
+ fclex ; 9BDBE2
+ fnclex ; DBE2
+ finit ; 9BDBE3
+ fninit ; DBE3
+ fsetpm ; DBE4
+ fcompp ; DED9
diff --git a/as/asm/fadd.asm b/as/asm/fadd.asm
new file mode 100644
index 0000000..d18f002
--- /dev/null
+++ b/as/asm/fadd.asm
@@ -0,0 +1,271 @@
+_fadd:
+ PUSH BP
+ MOV BP,SP
+ MOV EAX,DWORD PTR [BP+4]
+ MOV EDX,DWORD PTR [BP+8]
+ MOV EBX,DWORD PTR [BP+12]
+ MOV ECX,DWORD PTR [BP+16]
+ CALL faddfxfy
+ MOV DWORD PTR _facc,EAX
+ MOV DWORD PTR _facc+4,EDX
+ POP BP
+ RET
+
+fsubfxfy:
+ XOR ECX,#$80000000 ; complement sign bit, fall into add routine
+faddfxfy:
+ PUSH EBP
+ PUSH EDI
+ PUSH ESI
+ MOV EDI,ECX ; free CL for shifts
+ MOV ESI,EDX ; this mainly for consistent naming
+ AND ESI,#$7FFFFFFF ; discard sign so comparison is simple
+ AND EDI,#$7FFFFFFF
+
+ CMP ESI,EDI
+ JA XBIG
+ JB SWAP
+ CMP EAX,EBX
+ JAE XBIG
+SWAP:
+ XCHG EDX,ECX
+ XCHG ESI,EDI
+ XCHG EAX,EBX
+XBIG:
+ AND ESI,#$000FFFFF ; discard exponent
+ AND EDI,#$000FFFFF
+ OR ESI,#$00100000 ; normalize
+ OR EDI,#$00100000
+
+ SHR ECX,32-(1+11)
+ SHR EDX,32-(1+11)
+ MOV EBP,ECX ; prepare to compare signs (want high bits 0)
+ SUB CX,DX ; get difference of signs in CX
+ NEG CX ; D holds sign and exponent of both throughout
+ CMP CX,#(64-11)+2
+ JAE TO_DONE1 ; x dominates y
+ XOR BP,DX
+ AND BP,#$0800 ; see if signs are same
+ JNZ TO_SUBTRACT ; else roundoff reg EBP is 0
+
+ CMP CL,#32
+ JAE TO_ADD_BIGSHIFT
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ ADD EAX,EBX
+ ADC ESI,EDI
+ SUB EBX,EBX
+
+; result DX(1+11):SI:AX:BP:BX but needs normalization
+
+NORMALIZE:
+ MOV CX,DX
+ AND CX,#$07FF
+ TEST ESI,#$00200000
+ JZ NORMALIZE2
+ BR LOVERFLOW
+
+TO_DONE1:
+ JMP DONE1
+
+TO_SUBTRACT:
+ BR SUBTRACT
+
+TO_ADD_BIGSHIFT:
+ BR ADD_BIGSHIFT
+
+TO_NORMLITTLE:
+ BR NORMLITTLE
+
+; result DX(1):CX(11):SI:AX:BP:BX
+
+NORMALIZE2:
+ SHRD EDI,ESI,32-11
+ ; top 11 bits of ESI known 0 and BSR is slooow
+ BSR EDI,EDI ; index of leading 1 bit in EDI is 11..31 in DI
+ JZ TO_NORMLITTLE ; ESI is zero (flag wrong in Intel Manual)
+ SUB DI,#31
+ NEG DI
+ PUSH CX ; gr
+ MOV CX,DI ; rr
+ SHLD ESI,EAX,CL
+ SHLD EAX,EBP,CL
+ SHLD EBP,EBX,CL
+ SHL EBX,CL
+ POP CX ; rr
+ SUB CX,DI
+ JC UNDERFLOW
+
+ROUND:
+ CMP EBP,#$80000000 ; test roundoff register
+ JA ROUNDUP
+ JB DONE ; no rounding
+ TEST EBX,EBX
+ JNZ ROUNDUP
+ TEST AL,#1 ; ambiguous case, round to even
+ JZ DONE ; even, no rounding
+ROUNDUP:
+ ADD EAX,#1
+ ADC ESI,#0
+ SUB EBP,EBP
+ SUB EBX,EBX
+ TEST ESI,#$00200000
+ JNZ LOVERFLOW ; rounding may cause overflow!
+
+DONE:
+ AND DX,#$0800 ; extract sign of largest and result
+ OR DX,CX ; include exponent with sign
+DONE1:
+ SHL EDX,32-(1+11)
+ AND ESI,#$000FFFFF ; discard normalization bit
+ OR EDX,ESI
+ POP ESI
+ POP EDI
+ POP EBP
+ RET
+
+UNDERFLOW: ; should have error message here
+ANSWER0:
+ SUB EDX,EDX
+ MOV EAX,EDX
+ POP ESI
+ POP EDI
+ POP EBP
+ RET
+
+LOVERFLOW: ; carry bit must be right-shifted back in
+ SHR ESI,1
+ RCR EAX,1
+ RCR EBP,1
+ RCR EBX,1
+ INC CX
+ CMP CX,#$0800
+ JNZ ROUND
+
+OVERFLOW: ; should have error message here
+ MOV EDX,#$FFE00000 ; + infinity
+ SUB EAX,EAX
+ POP ESI
+ POP EDI
+ POP EBP
+ RET
+
+ADD_BIGSHIFT:
+ SUB CL,#32
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ ADD EAX,EDI
+ ADC ESI,#0
+ XCHG EBP,EBX
+ BR NORMALIZE
+
+NORMLITTLE:
+ SHLD ESI,EAX,32-(1+11)
+ SHLD EAX,EBP,32-(1+11)
+ SHLD EBP,EBX,32-(1+11)
+ SHL EBX,20
+ SUB CL,#32-(1+11)
+ JC UNDERFLOW
+ BR NORMALIZE2
+
+SUBTRACT:
+ SUB EBP,EBP ; set up roundoff register
+ CMP CL,#32
+ JAE SUBTRACT_BIGSHIFT
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ NEG EBP
+ SBB EAX,EBX
+ SBB ESI,EDI
+ SUB EBX,EBX
+ MOV CX,DX
+ AND CX,#$07FF
+ BR NORMALIZE2
+
+SUBTRACT_BIGSHIFT:
+ SUB CL,#32
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ NEG EBX
+ NEG EBP
+ SBB EBX,#0
+ SBB EAX,EDI
+ SBB ESI,#0
+ XCHG EBP,EBX
+ MOV CX,DX
+ AND CX,#$07FF
+ BR NORMALIZE2
+
+TO_ANSWER0:
+ BR ANSWER0
+
+TO_OVERFLOW:
+ JMP TO_OVERFLOW
+
+TO_UNDERFLOW:
+ BR UNDERFLOW
+
+fmulfxfy:
+ PUSH EBP
+ PUSH EDI
+ PUSH ESI
+ MOV ESI,EDX ; free DX for multiplications
+ MOV EDI,ECX ; this mainly for consistent naming
+ SHR EDX,32-(1+11)
+ SHR ECX,32-(1+11)
+ MOV BP,DX
+ XOR BP,CX
+ AND BP,#$0800 ; extract sign
+ AND DX,#$07FF ; exp(x)
+ JZ TO_ANSWER0
+ AND CX,#$07FF ; exp(y)
+ JZ TO_ANSWER0
+ ADD CX,DX
+ SUB CX,#$0400
+ JB TO_UNDERFLOW
+ CMP CX,#$07FF
+ JA TO_OVERFLOW ; probably not quite right
+
+ AND ESI,#$000FFFFF ; discard sign and exponent
+ AND EDI,#$000FFFFF
+ OR ESI,#$00100000 ; normalize
+ OR EDI,#$00100000
+
+; exponent is in CX, sign in BP, operands in ESI:EAX and EDI:EBX, DX is free
+; product to go in ESI:EAX:EBP:EBX
+; terminology: x * y = (x32:x0) * (y32:y0) = x32y32 + x32y0 + x0y32 +x0y0
+
+ PUSH CX
+ PUSH BP
+ MOV ECX,EAX
+ MUL EBX ; x0y0
+ MOV EBP,EDX ; x0y0.high in EBP
+ XCHG EBX,EAX ; x0y0.low in EBX (final), y0 in EAX
+ MUL ESI ; x32y0
+ PUSH EAX ; x32y0.low on stack
+ PUSH EDX ; x32y0.high on stack
+ MOV EAX,ESI
+ MUL EDI ; x32y32
+ MOV ESI,EDX ; x32y32.high in ESI (final except carries)
+ XCHG ECX,EAX ; x32y32.low in ECX, x0 in EAX
+ MUL EDI ; x0y32
+
+ ADD EBP,EAX ; x0y0.high + x0y32.low
+ POP EAX ; x32y0.high
+ ADC EAX,EDX ; x32y0.high + x0y32.high
+ ADC ESI,#0
+ POP EDX ; x32y0.low
+ ADD EBP,EDX ; (x0y0.high + x0y32.low) + x32y0.low
+ ADC EAX,ECX ; (x32y0.high + x0y32.high) + x32y32.low
+ ADC ESI,#0
+ POP DX ; sign
+ POP CX ; exponent
+ ADD CX,#13 ; temp fixup
+ BR NORMALIZE2
+
+_facc:
+ .word 0,0
diff --git a/as/asm/farcall.asm b/as/asm/farcall.asm
new file mode 100644
index 0000000..6a779d9
--- /dev/null
+++ b/as/asm/farcall.asm
@@ -0,0 +1,10 @@
+call 1:2
+call far [1]
+use32
+call far [1]
+
+use16
+jmp 1:2
+jmp far [1]
+use32
+jmp far [1]
diff --git a/as/asm/group1.asm b/as/asm/group1.asm
new file mode 100644
index 0000000..fe2fb45
--- /dev/null
+++ b/as/asm/group1.asm
@@ -0,0 +1,31 @@
+ ADD AL,#3
+ ADD AX,#$1234
+ ADD EAX,#$12345678
+ ADD BL,#3
+ ADD BX,#$1234
+ ADD EBX,#$12345678
+ ADD BYTE [BX],#3
+ ADD BYTE 3[BX],#4
+ ADD BYTE [BX+SI],#4
+ ADD WORD [BX],#$1234
+ ADD DWORD [BX],#$12345678
+ ADD BYTE [BX],#3
+ ADD WORD [BX],#-3
+ ADD DWORD [BX],#-3
+ ADD CL,BL
+ ADD CX,BX
+ ADD ECX,EBX
+ ADD [BX],CL
+ ADD [BX],CX
+ ADD [BX],ECX
+ ADD CL,[BX]
+ ADD CX,[BX]
+ ADD ECX,[BX]
+
+ ADC CL,BL
+ AND CL,BL
+ CMP CL,BL
+ OR CL,BL
+ SUB CL,BL
+ SBB CL,BL
+ XOR CL,BL
diff --git a/as/asm/group6.asm b/as/asm/group6.asm
new file mode 100644
index 0000000..f742672
--- /dev/null
+++ b/as/asm/group6.asm
@@ -0,0 +1,24 @@
+; group6.asm
+; 0F 00 /nnn
+
+; LLDT r/m16 nnn = 010
+; LTR r/m16 nnn = 011
+; SLDT r/m16 nnn = 000
+; STR r/m16 nnn = 001
+; VERR r/m16 nnn = 100
+; VERW r/m16 nnn = 101
+
+ LLDT AL ; illeg size
+ LLDT EAX ; illeg size
+ LLDT WORD $1234 ; immed not allowed
+ LLDT DS ; segreg not allowed
+
+ LLDT AX
+ LLDT [BX]
+ LLDT [EAX]
+
+ LTR BX
+ SLDT [BP]
+ STR [EBX]
+ VERR CX
+ VERW [SI]
diff --git a/as/asm/group7.asm b/as/asm/group7.asm
new file mode 100644
index 0000000..0df497c
--- /dev/null
+++ b/as/asm/group7.asm
@@ -0,0 +1,34 @@
+; group7.asm
+; 0F 01 /nnn
+
+; INVLPG m nnn = 111
+; LGDT m16&32 nnn = 010
+; LIDT m16&32 nnn = 011
+; LMSW r/m16 nnn = 110
+; SGDT m nnn = 000
+; SIDT m nnn = 001
+; SMSW r/m16 nnn = 100
+
+ LGDT EAX ; register not allowed
+ LGDT #$1234 ; immed not allowed
+ LGDT WORD PTR [BX] ; illegal size
+
+ LGDT [BX]
+ LGDT PWORD PTR [BX]
+ LGDT FWORD PTR [BX]
+ LGDT [EAX]
+
+ INVLPG [EDI]
+ SGDT [BP]
+ SIDT [EBX]
+
+ LMSW AL ; illeg size
+ LMSW EAX ; illeg size
+ LMSW #$1234 ; immed not allowed
+ LMSW DS ; segreg not allowed
+
+ LMSW AX
+ LMSW [BX]
+ LMSW [EAX]
+
+ SMSW BX
diff --git a/as/asm/imul.asm b/as/asm/imul.asm
new file mode 100644
index 0000000..e2772c2
--- /dev/null
+++ b/as/asm/imul.asm
@@ -0,0 +1,33 @@
+ use32
+
+ imul bl
+ imul byte ptr [esi]
+ imul bx
+ imul word ptr [esi]
+ imul ebx
+ imul dword ptr [esi]
+
+ imul ax,bx
+ imul ax,[esi]
+ imul eax,ebx
+ imul eax,[esi]
+
+ imul ax,bx,22
+ imul ax,[esi],22
+ imul eax,ebx,22
+ imul eax,[esi],22
+
+ imul ax,[22]
+ imul eax,[22]
+ imul ax,#22
+ imul eax,#22
+
+ imul ax,bx,300
+ imul ax,[esi],300
+ imul eax,ebx,300000
+ imul eax,[esi],300000
+
+ imul ax,[300]
+ imul eax,[300000]
+ imul ax,#300
+ imul eax,#300000
diff --git a/as/asm/incdec.asm b/as/asm/incdec.asm
new file mode 100644
index 0000000..573861c
--- /dev/null
+++ b/as/asm/incdec.asm
@@ -0,0 +1,83 @@
+ INC AL
+ INC AH
+ INC BL
+ INC BH
+ INC CL
+ INC CH
+ INC DL
+ INC DH
+ INC #1 ; illeg
+ INC BYTE #1 ; illeg
+ INC [BX] ; illeg
+ INC BYTE [BX]
+
+ INC AX
+ INC BX
+ INC CX
+ INC DX
+ INC SP
+ INC BP
+ INC SI
+ INC DI
+ INC CS ; illeg
+ INC DS ; illeg
+ INC ES ; illeg
+ INC FS ; illeg
+ INC GS ; illeg
+ INC #$1234 ; illeg
+ INC WORD #$1234 ; illeg
+ INC WORD [BX]
+
+ INC EAX
+ INC EBX
+ INC ECX
+ INC EDX
+ INC ESP
+ INC EBP
+ INC ESI
+ INC EDI
+ INC #$12345678 ; illeg
+ INC DWORD #$12345678 ; illeg
+ INC DWORD [BX]
+
+ DEC AL
+ DEC AH
+ DEC BL
+ DEC BH
+ DEC CL
+ DEC CH
+ DEC DL
+ DEC DH
+ DEC #1 ; illeg
+ DEC BYTE #1 ; illeg
+ DEC [BX] ; illeg
+ DEC BYTE [BX]
+
+ DEC AX
+ DEC BX
+ DEC CX
+ DEC DX
+ DEC SP
+ DEC BP
+ DEC SI
+ DEC DI
+ DEC CS ; illeg
+ DEC DS ; illeg
+ DEC ES ; illeg
+ DEC FS ; illeg
+ DEC GS ; illeg
+ DEC #$1234 ; illeg
+ DEC WORD #$1234 ; illeg
+ DEC WORD [BX]
+
+ DEC EAX
+ DEC EBX
+ DEC ECX
+ DEC EDX
+ DEC ESP
+ DEC EBP
+ DEC ESI
+ DEC EDI
+ DEC #$12345678 ; illeg
+ DEC DWORD #$12345678 ; illeg
+ DEC DWORD [BX]
diff --git a/as/asm/inher.asm b/as/asm/inher.asm
new file mode 100644
index 0000000..f1343fa
--- /dev/null
+++ b/as/asm/inher.asm
@@ -0,0 +1,127 @@
+; INHER.ASM
+
+; INHER opcodes
+
+ AAA
+ AAS
+
+ CLC
+ CLD
+ CLI
+ CLTS
+ CMC
+ CMPSB
+
+ DAA
+ DAS
+
+ HLT
+
+ INTO
+ INSB
+
+ LAHF
+ LEAVE
+ LOCK
+ LODSB
+
+ MOVSB
+
+ NOP
+
+ OUTSB
+
+ REP
+ REPE
+ REPNE
+
+ SAHF
+ SCASB
+ STC
+ STD
+ STI
+ STOSB
+
+ WAIT
+
+; INHER16 and INHER32 opcodes
+
+ USE16
+
+ CBW
+ CWD
+ CWDE
+ CDQ
+ CMPSW
+ CMPSD
+
+ INSW
+ INSD
+ IRET
+ IRETD
+
+ LODSW
+ LODSD
+
+ MOVSW
+ MOVSD
+
+ OUTSW
+ OUTSD
+
+ POPA
+ POPAD
+ POPF
+ POPFD
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+
+ SCASW
+ SCASD
+ STOSW
+ STOSW
+
+ XLAT
+ XLATB
+
+ USE32
+
+ CBW
+ CWD
+ CWDE
+ CDQ
+ CMPSW
+ CMPSD
+
+ INSW
+ INSD
+ IRET
+ IRETD
+
+ LODSW
+ LODSD
+
+ MOVSW
+ MOVSD
+
+ OUTSW
+ OUTSD
+
+ POPA
+ POPAD
+ POPF
+ POPFD
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+
+ SCASW
+ SCASD
+ STOSW
+ STOSW
+
+ XLAT
+ XLATB
diff --git a/as/asm/inout.asm b/as/asm/inout.asm
new file mode 100644
index 0000000..3f0a3f2
--- /dev/null
+++ b/as/asm/inout.asm
@@ -0,0 +1,25 @@
+ IN EAX,DX ; plain IN is no longer allowed
+ INB
+ IN AL,DX
+ INW
+ IN AX,DX
+ IN EAX,DX
+ IN AL,$20
+ IN AL,$101
+ IN AX,$20
+ IN AX,$101
+ IN EAX,$20
+ IN EAX,$101
+
+ OUTB DX,EAX ; plain OUT is no longer allowed
+ OUTB
+ OUT DX,AL
+ OUTW
+ OUT DX,AX
+ OUT DX,EAX
+ OUT $20,AL
+ OUT $101,AL
+ OUT $20,AX
+ OUT #101,AX
+ OUT $20,EAX
+ OUT $101,EAX
diff --git a/as/asm/movspec.asm b/as/asm/movspec.asm
new file mode 100644
index 0000000..a4f9c15
--- /dev/null
+++ b/as/asm/movspec.asm
@@ -0,0 +1,246 @@
+mov eax,cr0
+mov eax,cr2
+mov eax,cr3
+mov eax,dr0
+mov eax,dr1
+mov eax,dr2
+mov eax,dr3
+mov eax,dr6
+mov eax,dr7
+mov eax,tr3
+mov eax,tr4
+mov eax,tr5
+mov eax,tr6
+mov eax,tr7
+
+mov cr0,eax
+mov cr2,eax
+mov cr3,eax
+mov dr0,eax
+mov dr1,eax
+mov dr2,eax
+mov dr3,eax
+mov dr6,eax
+mov dr7,eax
+mov tr3,eax
+mov tr4,eax
+mov tr5,eax
+mov tr6,eax
+mov tr7,eax
+
+
+mov ebx,cr0
+mov ebx,cr2
+mov ebx,cr3
+mov ebx,dr0
+mov ebx,dr1
+mov ebx,dr2
+mov ebx,dr3
+mov ebx,dr6
+mov ebx,dr7
+mov ebx,tr3
+mov ebx,tr4
+mov ebx,tr5
+mov ebx,tr6
+mov ebx,tr7
+
+mov cr0,ebx
+mov cr2,ebx
+mov cr3,ebx
+mov dr0,ebx
+mov dr1,ebx
+mov dr2,ebx
+mov dr3,ebx
+mov dr6,ebx
+mov dr7,ebx
+mov tr3,ebx
+mov tr4,ebx
+mov tr5,ebx
+mov tr6,ebx
+mov tr7,ebx
+
+
+mov ecx,cr0
+mov ecx,cr2
+mov ecx,cr3
+mov ecx,dr0
+mov ecx,dr1
+mov ecx,dr2
+mov ecx,dr3
+mov ecx,dr6
+mov ecx,dr7
+mov ecx,tr3
+mov ecx,tr4
+mov ecx,tr5
+mov ecx,tr6
+mov ecx,tr7
+
+mov cr0,ecx
+mov cr2,ecx
+mov cr3,ecx
+mov dr0,ecx
+mov dr1,ecx
+mov dr2,ecx
+mov dr3,ecx
+mov dr6,ecx
+mov dr7,ecx
+mov tr3,ecx
+mov tr4,ecx
+mov tr5,ecx
+mov tr6,ecx
+mov tr7,ecx
+
+
+mov edx,cr0
+mov edx,cr2
+mov edx,cr3
+mov edx,dr0
+mov edx,dr1
+mov edx,dr2
+mov edx,dr3
+mov edx,dr6
+mov edx,dr7
+mov edx,tr3
+mov edx,tr4
+mov edx,tr5
+mov edx,tr6
+mov edx,tr7
+
+mov cr0,edx
+mov cr2,edx
+mov cr3,edx
+mov dr0,edx
+mov dr1,edx
+mov dr2,edx
+mov dr3,edx
+mov dr6,edx
+mov dr7,edx
+mov tr3,edx
+mov tr4,edx
+mov tr5,edx
+mov tr6,edx
+mov tr7,edx
+
+
+mov esi,cr0
+mov esi,cr2
+mov esi,cr3
+mov esi,dr0
+mov esi,dr1
+mov esi,dr2
+mov esi,dr3
+mov esi,dr6
+mov esi,dr7
+mov esi,tr3
+mov esi,tr4
+mov esi,tr5
+mov esi,tr6
+mov esi,tr7
+
+mov cr0,esi
+mov cr2,esi
+mov cr3,esi
+mov dr0,esi
+mov dr1,esi
+mov dr2,esi
+mov dr3,esi
+mov dr6,esi
+mov dr7,esi
+mov tr3,esi
+mov tr4,esi
+mov tr5,esi
+mov tr6,esi
+mov tr7,esi
+
+
+mov edi,cr0
+mov edi,cr2
+mov edi,cr3
+mov edi,dr0
+mov edi,dr1
+mov edi,dr2
+mov edi,dr3
+mov edi,dr6
+mov edi,dr7
+mov edi,tr3
+mov edi,tr4
+mov edi,tr5
+mov edi,tr6
+mov edi,tr7
+
+mov cr0,edi
+mov cr2,edi
+mov cr3,edi
+mov dr0,edi
+mov dr1,edi
+mov dr2,edi
+mov dr3,edi
+mov dr6,edi
+mov dr7,edi
+mov tr3,edi
+mov tr4,edi
+mov tr5,edi
+mov tr6,edi
+mov tr7,edi
+
+
+mov esp,cr0
+mov esp,cr2
+mov esp,cr3
+mov esp,dr0
+mov esp,dr1
+mov esp,dr2
+mov esp,dr3
+mov esp,dr6
+mov esp,dr7
+mov esp,tr3
+mov esp,tr4
+mov esp,tr5
+mov esp,tr6
+mov esp,tr7
+
+mov cr0,esp
+mov cr2,esp
+mov cr3,esp
+mov dr0,esp
+mov dr1,esp
+mov dr2,esp
+mov dr3,esp
+mov dr6,esp
+mov dr7,esp
+mov tr3,esp
+mov tr4,esp
+mov tr5,esp
+mov tr6,esp
+mov tr7,esp
+
+
+mov ebp,cr0
+mov ebp,cr2
+mov ebp,cr3
+mov ebp,dr0
+mov ebp,dr1
+mov ebp,dr2
+mov ebp,dr3
+mov ebp,dr6
+mov ebp,dr7
+mov ebp,tr3
+mov ebp,tr4
+mov ebp,tr5
+mov ebp,tr6
+mov ebp,tr7
+
+mov cr0,ebp
+mov cr2,ebp
+mov cr3,ebp
+mov dr0,ebp
+mov dr1,ebp
+mov dr2,ebp
+mov dr3,ebp
+mov dr6,ebp
+mov dr7,ebp
+mov tr3,ebp
+mov tr4,ebp
+mov tr5,ebp
+mov tr6,ebp
+mov tr7,ebp
diff --git a/as/asm/pushpop.asm b/as/asm/pushpop.asm
new file mode 100644
index 0000000..b45117a
--- /dev/null
+++ b/as/asm/pushpop.asm
@@ -0,0 +1,86 @@
+ PUSH AL ; illeg
+ PUSH AH ; illeg
+ PUSH BL ; illeg
+ PUSH BH ; illeg
+ PUSH CL ; illeg
+ PUSH CH ; illeg
+ PUSH DL ; illeg
+ PUSH DH ; illeg
+ PUSH #1 ; illeg
+ PUSH BYTE #1 ; illeg
+ PUSH [BX] ; illeg
+ PUSH BYTE [BX] ; illeg
+ PUSH WORD #-1 ; right way to push a signed byte value
+
+ PUSH AX
+ PUSH BX
+ PUSH CX
+ PUSH DX
+ PUSH SP
+ PUSH BP
+ PUSH SI
+ PUSH DI
+ PUSH CS
+ PUSH DS
+ PUSH ES
+ PUSH FS
+ PUSH GS
+ PUSH SS
+ PUSH #$1234 ; illeg
+ PUSH WORD #$1234
+ PUSH WORD [BX]
+
+ PUSH EAX
+ PUSH EBX
+ PUSH ECX
+ PUSH EDX
+ PUSH ESP
+ PUSH EBP
+ PUSH ESI
+ PUSH EDI
+ PUSH #$12345678 ; illeg
+ PUSH DWORD #$12345678
+ PUSH DWORD [BX]
+
+ POP AL ; illeg
+ POP AH ; illeg
+ POP BL ; illeg
+ POP BH ; illeg
+ POP CL ; illeg
+ POP CH ; illeg
+ POP DL ; illeg
+ POP DH ; illeg
+ POP #1 ; illeg
+ POP BYTE #1 ; illeg
+ POP [BX] ; illeg
+ POP BYTE [BX] ; illeg
+
+ POP AX
+ POP BX
+ POP CX
+ POP DX
+ POP SP
+ POP BP
+ POP SI
+ POP DI
+ POP CS ; illeg
+ POP DS
+ POP ES
+ POP FS
+ POP GS
+ POP SS
+ POP #$1234 ; illeg
+ POP WORD #$1234 ; illeg
+ POP WORD [BX]
+
+ POP EAX
+ POP EBX
+ POP ECX
+ POP EDX
+ POP ESP
+ POP EBP
+ POP ESI
+ POP EDI
+ POP #$12345678 ; illeg
+ POP DWORD #$12345678 ; illeg
+ POP DWORD [BX]
diff --git a/as/asm/seg.asm b/as/asm/seg.asm
new file mode 100644
index 0000000..0394615
--- /dev/null
+++ b/as/asm/seg.asm
@@ -0,0 +1,6 @@
+ SEG CS
+ SEG DS
+ SEG ES
+ SEG FS
+ SEG GS
+ SEG SS
diff --git a/as/asm/shdouble.asm b/as/asm/shdouble.asm
new file mode 100644
index 0000000..1080ece
--- /dev/null
+++ b/as/asm/shdouble.asm
@@ -0,0 +1,34 @@
+; SHDOUBLE.ASM
+
+ILLEGALS EQU 1
+
+; 0F A4 SHLD r/m16,r16,imm8 3/7
+; 0F A4 SHLD r/m32,r32,imm8 3/7
+; 0F A5 SHLD r/m16,r16,CL 3/7
+; 0F A5 SHLD r/m32,r32,CL 3/7
+
+; 0F AC SHRD r/m16,r16,imm8 3/7
+; 0F AC SHRD r/m32,r32,imm8 3/7
+; 0F AD SHRD r/m16,r16,CL 3/7
+; 0F AD SHRD r/m32,r32,CL 3/7
+
+IF ILLEGALS
+ SHLD AL,BL,8 ; byte size
+ SHLD AX,8,8 ; immediate source
+ SHLD AX,DS,8 ; segment register
+ SHLD AX,[BX],8 ; non-register source
+ SHLD AX,BX,256 ; shift count too big
+ SHLD AL,BL,8 ; byte size
+ENDIF
+
+ SHLD BX,CX,3
+ SHLD EDX,ESI,1
+ SHLD CX,BX,CL
+ SHLD ESI,EDX,1
+ SHLD [BX],CX,3
+ SHLD [BX],ECX,1
+ SHLD [SI],BX,CL
+ SHLD [SI],EBX,CL
+
+ SHRD BX,CX,3
+ SHRD CX,BX,CL
diff --git a/as/asm/shift.asm b/as/asm/shift.asm
new file mode 100644
index 0000000..35cc23f
--- /dev/null
+++ b/as/asm/shift.asm
@@ -0,0 +1,119 @@
+ RCL AL,CL
+ RCL AH,CL
+ RCL BL,CL
+ RCL BH,CL
+ RCL CL,CL
+ RCL CH,CL
+ RCL DL,CL
+ RCL DH,CL
+ RCL #1,CL ; illeg
+ RCL [BX],CL ; illeg
+ RCL BYTE [BX],CL
+
+ RCL AX,CL
+ RCL BX,CL
+ RCL CX,CL
+ RCL DX,CL
+ RCL SP,CL
+ RCL BP,CL
+ RCL SI,CL
+ RCL DI,CL
+ RCL CS,CL ; illeg
+ RCL DS,CL ; illeg
+ RCL ES,CL ; illeg
+ RCL FS,CL ; illeg
+ RCL GS,CL ; illeg
+ RCL WORD [BX],CL
+
+ RCL EAX,CL
+ RCL EBX,CL
+ RCL ECX,CL
+ RCL EDX,CL
+ RCL ESP,CL
+ RCL EBP,CL
+ RCL ESI,CL
+ RCL EDI,CL
+ RCL DWORD [BX],CL
+
+ RCL AL,1
+ RCL AH,1
+ RCL BL,1
+ RCL BH,1
+ RCL CL,1
+ RCL CH,1
+ RCL DL,1
+ RCL DH,1
+ RCL #1,1 ; illeg
+ RCL [BX],1 ; illeg
+ RCL BYTE [BX],1
+
+ RCL AX,1
+ RCL BX,1
+ RCL CX,1
+ RCL DX,1
+ RCL SP,1
+ RCL BP,1
+ RCL SI,1
+ RCL DI,1
+ RCL CS,1 ; illeg
+ RCL DS,1 ; illeg
+ RCL ES,1 ; illeg
+ RCL FS,1 ; illeg
+ RCL GS,1 ; illeg
+ RCL WORD [BX],1
+
+ RCL EAX,1
+ RCL EBX,1
+ RCL ECX,1
+ RCL EDX,1
+ RCL ESP,1
+ RCL EBP,1
+ RCL ESI,1
+ RCL EDI,1
+ RCL DWORD [BX],1
+
+ RCL AL,15
+ RCL AH,15
+ RCL BL,15
+ RCL BH,15
+ RCL CL,15
+ RCL CH,15
+ RCL DL,15
+ RCL DH,15
+ RCL #1,15 ; illeg
+ RCL [BX],15 ; illeg
+ RCL BYTE [BX],15
+ RCL AL,$1000
+
+ RCL AX,15
+ RCL BX,15
+ RCL CX,15
+ RCL DX,15
+ RCL SP,15
+ RCL BP,15
+ RCL SI,15
+ RCL DI,15
+ RCL CS,15 ; illeg
+ RCL DS,15 ; illeg
+ RCL ES,15 ; illeg
+ RCL FS,15 ; illeg
+ RCL GS,15 ; illeg
+ RCL WORD [BX],15
+
+ RCL EAX,15
+ RCL EBX,15
+ RCL ECX,15
+ RCL EDX,15
+ RCL ESP,15
+ RCL EBP,15
+ RCL ESI,15
+ RCL EDI,15
+ RCL DWORD [BX],15
+
+ RCR AX,7
+ ROL AX,7
+ ROR AX,7
+ SAL AX,7
+ SAR AX,7
+ SHL AX,7
+ SHR AX,7
diff --git a/as/asm/summary.as b/as/asm/summary.as
new file mode 100644
index 0000000..cd62e37
--- /dev/null
+++ b/as/asm/summary.as
@@ -0,0 +1,385 @@
+general:
+ ; AL,imm8
+ ; AX,imm16
+ ; EAX,imm32
+ ; r/m8,imm8
+ ; r/m16,imm16
+ ; r/m32.imm32
+ ; r/m16,signed imm8
+ ; r/m32,signed imm8
+ ; r/m8,r8
+ ; r/m16,r16
+ ; r/m32,r32
+ ; r8,r/m8
+ ; r16,r/m16
+ ; r32,r/m32
+
+shiftcount:
+ ; 1
+ ; CL
+ ; imm8
+unary alterable:
+ ; r/m8
+ ; r/m16
+ ; r/m32
+
+ AAA
+ AAD ; [unsupported base]
+ AAM ; [unsupported base]
+ AAS
+ ADC ; general
+ ADD ; general
+ AND ; general
+ ARPL ; r/m16,r16
+ BOUND ; r16,m16&16
+ BOUND ; r32,m32&32
+ BSF ; r16,r/m16
+ BSF ; r32,r/m32
+ BSR ; r16,r/m16
+ BSR ; r32,r/m32
+ BSWAP ; r32
+ BT ; r/m16,r16
+ BT ; r/m32,r32
+ BT ; r/m16,imm8
+ BT ; r/m32,imm8
+ BTC ; r/m16,r16
+ BTC ; r/m32,r32
+ BTC ; r/m16,imm8
+ BTC ; r/m32,imm8
+ BTR ; r/m16,r16
+ BTR ; r/m32,r32
+ BTR ; r/m16,imm8
+ BTR ; r/m32,imm8
+ BTS ; r/m16,r16
+ BTS ; r/m32,r32
+ BTS ; r/m16,imm8
+ BTS ; r/m32,imm8
+ CALL ; rel16
+ CALL ; r/m16
+ CALL ; ptr16:16
+ CALL ; m16:16
+ CALL ; rel32
+ CALL ; r/m32
+ CALL ; ptr16:32
+ CALL ; m16:32
+ CBW
+ CDQ
+ CLC
+ CLD
+ CLI
+ CLTS
+ CMC
+ CMP ; general
+ CMPS ; [segreg:]m8,m8
+ CMPS ; [segreg:]m16,m16
+ CMPS ; [segreg:]m32,m32
+ CMPSB
+ CMPSW
+ CMPSD
+ CMPXCHG ; r/m8,r8
+ CMPXCHG ; r/m16,r16
+ CMPXCHG ; r/m32,r32
+ CWD
+ CWDE
+ DAA
+ DAS
+ DEC ; unary alterable
+ DEC ; r16
+ DEC ; r32
+ DIV ; AL,r/m8
+ DIV ; AX,r/m16
+ DIV ; EAX,r/m32
+ ENTER ; imm16,imm8
+ HLT
+ IDIV ; AL,r/m8
+ IDIV ; AX,r/m16
+ IDIV ; EAX,r/m32
+ IMUL ; r/m8
+ IMUL ; r/m16
+ IMUL ; r/m32
+ IMUL ; r16,r/m16
+ IMUL ; r32,r/m32
+ IMUL ; r16,r/m16,imm8
+ IMUL ; r32,r/m32,imm8
+ IMUL ; r16,imm8
+ IMUL ; r32,imm8
+ IMUL ; r16,r/m16,imm16
+ IMUL ; r32,r/m32,imm32
+ IMUL ; r16,imm16
+ IMUL ; r32,imm32
+ IN ; AL,imm8
+ IN ; AX,imm8
+ IN ; EAX,imm8
+ IN ; AL,DX
+ IN ; AX,DX
+ IN ; EAX,DX
+ INC ; unary alterable
+ INC ; r16
+ INC ; r32
+ INSB
+ INSW
+ INSD
+ INT ; imm8
+ INTO
+ INVD
+ INVLPG ; m
+ IRET
+ IRETD
+ JCC ; rel8
+ JCC ; rel16/32
+ JA
+ JAE
+ JB
+ JBE
+ JC
+ JCXZ
+ JECXZ
+ JE
+ JG
+ JGE
+ JL
+ JLE
+ JNA
+ JNAE
+ JNB
+ JNBE
+ JNC
+ JNE
+ JNG
+ JNGE
+ JNL
+ JNLE
+ JNO
+ JNP
+ JNS
+ JNZ
+ JO
+ JP
+ JPE
+ JPO
+ JS
+ JZ
+ JMP ; rel8
+ JMP ; rel16
+ JMP ; r/m16
+ JMP ; ptr16:16
+ JMP ; m16:16
+ JMP ; rel32
+ JMP ; r/m32
+ JMP ; ptr16:32
+ JMP ; m16:32
+ LAHF
+ LAR ; r16,r/m16
+ LAR ; r32,r/m32
+ LEA ; r16,m
+ LEA ; r32,m
+ LEAVE
+ LGDT ; m16&32
+ LIDT ; m16&32
+ LDS ; r16,m16:16
+ LDS ; r32,m16:32
+ LES ; r16,m16:16
+ LES ; r32,m16:32
+ LFS ; r16,m16:16
+ LFS ; r32,m16:32
+ LGS ; r16,m16:16
+ LGS ; r32,m16:32
+ LSS ; r16,m16:16
+ LSS ; r32,m16:32
+ LLDT ; r/m16
+ LMSW ; r/m16
+ LOCK
+ LODS ; [segreg:]m8
+ LODS ; [segreg:]m16
+ LODS ; [segreg:]m32
+ LODSB
+ LODSW
+ LODSD
+ LOOP ; rel8
+ LOOPE ; rel8
+ LOOPZ ; rel8
+ LOOPNE ; rel8
+ LOOPNZ ; rel8
+ LSL ; r16,r/m16
+ LSL ; r32,r/m32
+ LTR ; r/m16
+ MOV ; r/m8,r8
+ MOV ; r/m16,r16
+ MOV ; r/m32,r32
+ MOV ; r8,r/m8
+ MOV ; r16,r/m16
+ MOV ; r32,r/m32
+ MOV ; r/m16,Sreg
+ MOV ; Sreg,r/m16
+ MOV ; AL,moffs8
+ MOV ; AX,moffs16
+ MOV ; EAX,moffs32
+ MOV ; moffs8,AL
+ MOV ; moffs16,AX
+ MOV ; moffs32,EAX
+ MOV ; r8,imm8
+ MOV ; r16,imm16
+ MOV ; r32,imm32
+ MOV ; r32,CR0/CR2/CR3
+ MOV ; r/m8,imm8
+ MOV ; r/m16,imm16
+ MOV ; r/m32,imm32
+ MOV ; r32,CR0/CR2/CR3
+ MOV ; CR0/CR2/CR3,r32
+ MOV ; r32,DR0/DR1/DR2/DR3/DR6/DR7
+ MOV ; DR0/DR1/DR2/DR3/DR6/DR7,r32
+ MOV ; r32,TR6/TR7
+ MOV ; TR6/TR7,r32
+ MOVS ; [segreg:]m8,m8
+ MOVS ; [segreg:]m16,m16
+ MOVS ; [segreg:]m32,m32
+ MOVSB
+ MOVSW
+ MOVSD
+ MOVSX ; r16,r/m8
+ MOVSX ; r32,r/m8
+ MOVSX ; r32,r/m16
+ MOVZX ; r16,r/m8
+ MOVZX ; r32,r/m8
+ MOVZX ; r32,r/m16
+ MUL ; AL,r/m8
+ MUL ; AX,r/m16
+ MUL ; EAX,r/m32
+ NEG ; unary alterable
+ NOP
+ NOT ; unary alterable
+ OR ; general
+ OUT ; imm8,AL
+ OUT ; imm8,AX
+ OUT ; imm8,EAX
+ OUT ; DX,AL
+ OUT ; DX,AX
+ OUT ; DX,EAX
+ OUTS ; [segreg:]m8
+ OUTS ; [segreg:]m16
+ OUTS ; [segreg:]m32
+ OUTSB
+ OUTSW
+ OUTSD
+ POP ; m16
+ POP ; m32
+ POP ; r16
+ POP ; r32
+ POP ; DS
+ POP ; ES
+ POP ; FS
+ POP ; GS
+ POP ; SS
+ POPA
+ POPAD
+ POPF
+ POPFD
+ PUSH ; m16
+ PUSH ; m32
+ PUSH ; r16
+ PUSH ; r32
+ PUSH ; imm8
+ PUSH ; imm16
+ PUSH ; imm32
+ PUSH ; CS
+ PUSH ; DS
+ PUSH ; ES
+ PUSH ; FS
+ PUSH ; GS
+ PUSH ; SS
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+ RCL ; shiftcount
+ RCR ; shiftcount
+ ROL ; shiftcount
+ ROR ; shiftcount
+ REP ; INS/MOVS/OUTS/STOS
+ REPE ; CMPS/SCAS
+ REPNE ; CMPS/SCAS
+ RET
+ RET ; imm16
+ SAHF
+ SAL ; shiftcount
+ SAR ; shiftcount
+ SHL ; shiftcount
+ SHR ; shiftcount
+ SBB ; general
+ SCASB
+ SCASW
+ SCASD
+ SETA ; r/m8
+ SETAE ; r/m8
+ SETB ; r/m8
+ SETBE ; r/m8
+ SETC ; r/m8
+ SETE ; r/m8
+ SETG ; r/m8
+ SETGE ; r/m8
+ SETL ; r/m8
+ SETLE ; r/m8
+ SETNA ; r/m8
+ SETNAE ; r/m8
+ SETNB ; r/m8
+ SETNBE ; r/m8
+ SETNC ; r/m8
+ SETNE ; r/m8
+ SETNG ; r/m8
+ SETNGE ; r/m8
+ SETNL ; r/m8
+ SETNLE ; r/m8
+ SETNO ; r/m8
+ SETNP ; r/m8
+ SETNS ; r/m8
+ SETNZ ; r/m8
+ SETO ; r/m8
+ SETP ; r/m8
+ SETPE ; r/m8
+ SETPO ; r/m8
+ SETS ; r/m8
+ SETZ ; r/m8
+ SGDT ; m
+ SHLD ; r/m16,r16,imm8
+ SHLD ; r/m32,r32,imm8
+ SHLD ; r/m16,r16,CL
+ SHLD ; r/m32,r32,CL
+ SHRD ; r/m16,r16,imm8
+ SHRD ; r/m32,r32,imm8
+ SHRD ; r/m16,r16,CL
+ SHRD ; r/m32,r32,CL
+ SIDT ; m
+ SLDT ; r/m16
+ SMSW ; r/m16
+ STC
+ STD
+ STI
+ STOSB
+ STOSW
+ STOSD
+ STR ; r/m16
+ SUB ; general
+ TEST ; AL,imm8
+ TEST ; AX,imm16
+ TEST ; EAX,imm32
+ TEST ; r/m8,imm8
+ TEST ; r/m16,imm16
+ TEST ; r/m32,imm32
+ TEST ; r/m8,r8
+ TEST ; r/m16,r16
+ TEST ; r/m32/r32
+ VERR ; r/m16
+ VERW ; r/m16
+ WAIT
+ WBINVD
+ XADD ; r/m8,r8
+ XADD ; r/m16,r16
+ XADD ; r/m32,r32
+ XCHG ; AX,r16
+ XCHG ; EAX,r32
+ XCHG ; r/m8,r8
+ XCHG ; r/m16,r16
+ XCHG ; r/m32,r32
+ XLAT ; [segreg:]m8
+ XLATB
+ XOR ; general
diff --git a/as/asm/xchg.asm b/as/asm/xchg.asm
new file mode 100644
index 0000000..f05157f
--- /dev/null
+++ b/as/asm/xchg.asm
@@ -0,0 +1,103 @@
+ XCHG AX,BL ; illeg
+ XCHG AX,BYTE [BX] ; illeg
+ XCHG AX,DS ; illeg
+ XCHG AX,#1 ; illeg
+
+ XCHG AX,AX
+ XCHG AX,BX
+ XCHG AX,CX
+ XCHG AX,DX
+ XCHG AX,SP
+ XCHG AX,BP
+ XCHG AX,SI
+ XCHG AX,DI
+
+ XCHG AX,AX
+ XCHG BX,AX
+ XCHG CX,AX
+ XCHG DX,AX
+ XCHG SP,AX
+ XCHG BP,AX
+ XCHG SI,AX
+ XCHG DI,AX
+
+ XCHG EAX,EAX
+ XCHG EAX,EBX
+ XCHG EAX,ECX
+ XCHG EAX,EDX
+ XCHG EAX,ESP
+ XCHG EAX,EBP
+ XCHG EAX,ESI
+ XCHG EAX,EDI
+
+ XCHG EAX,EAX
+ XCHG EBX,EAX
+ XCHG ECX,EAX
+ XCHG EDX,EAX
+ XCHG ESP,EAX
+ XCHG EBP,EAX
+ XCHG ESI,EAX
+ XCHG EDI,EAX
+
+ XCHG AL,AL
+ XCHG AL,AH
+ XCHG AL,BL
+ XCHG AL,BH
+ XCHG BL,CL
+ XCHG BL,CH
+ XCHG BL,DL
+ XCHG BL,DH
+
+ XCHG [BX],AL
+ XCHG [BX],AH
+ XCHG [BX],BL
+ XCHG [BX],BH
+ XCHG [BX],CL
+ XCHG [BX],CH
+ XCHG [BX],DL
+ XCHG [BX],DH
+
+ XCHG AL,[BX]
+ XCHG AH,[BX]
+ XCHG BL,[BX]
+ XCHG BH,[BX]
+ XCHG CL,[BX]
+ XCHG CH,[BX]
+ XCHG DL,[BX]
+ XCHG DH,[BX]
+
+ XCHG [BX],AX
+ XCHG [BX],BX
+ XCHG [BX],CX
+ XCHG [BX],DX
+ XCHG [BX],SP
+ XCHG [BX],BP
+ XCHG [BX],SI
+ XCHG [BX],DI
+
+ XCHG AX,[BX]
+ XCHG BX,[BX]
+ XCHG CX,[BX]
+ XCHG DX,[BX]
+ XCHG SP,[BX]
+ XCHG BP,[BX]
+ XCHG SI,[BX]
+ XCHG DI,[BX]
+
+ XCHG [BX],EAX
+ XCHG [BX],EBX
+ XCHG [BX],ECX
+ XCHG [BX],EDX
+ XCHG [BX],ESP
+ XCHG [BX],EBP
+ XCHG [BX],ESI
+ XCHG [BX],EDI
+
+ XCHG AX,[EBX]
+ XCHG BX,[EBX]
+ XCHG CX,[EBX]
+ XCHG DX,[EBX]
+ XCHG SP,[EBX]
+ XCHG BP,[EBX]
+ XCHG SI,[EBX]
+ XCHG DI,[EBX]
diff --git a/as/assemble.c b/as/assemble.c
new file mode 100644
index 0000000..c438ce6
--- /dev/null
+++ b/as/assemble.c
@@ -0,0 +1,309 @@
+/* assemble.c - main loop for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+
+PRIVATE bool_t nocolonlabel; /* set for labels not followed by ':' */
+PRIVATE void (*routine) P((void));
+PRIVATE pfv rout_table[] =
+{
+ pelse,
+ pelseif,
+ pelsifc,
+ pendif,
+ pif,
+ pifc,
+
+ /* start of non-conditionals */
+ palign,
+ pasciz,
+ pblkw,
+ pblock,
+ pbss,
+ pcomm,
+ pcomm1,
+ pdata,
+ pendb,
+ penter,
+ pentry,
+ pequ,
+ peven,
+ pexport,
+ pfail,
+ pfcb,
+ pfcc,
+ pfdb,
+ pfqb,
+ pget,
+ pglobl,
+ pident,
+ pimport,
+ plcomm,
+ plcomm1,
+ plist,
+ ploc,
+ pmaclist,
+ pmacro,
+ pmap,
+ porg,
+ pproceof,
+ prmb,
+ psect,
+ pset,
+ psetdp,
+ ptext,
+#ifdef I80386
+ puse16,
+ puse32,
+#endif
+ pwarn,
+ /* end of pseudo-ops */
+
+#ifdef I80386
+ mbcc,
+ mbswap,
+ mcall,
+ mcalli,
+ mdivmul,
+ menter,
+ mEwGw,
+ mExGx,
+ mf_inher,
+ mf_m,
+ mf_m2,
+ mf_m2_ax,
+ mf_m2_m4,
+ mf_m2_m4_m8,
+ mf_m4_m8_optst,
+ mf_m4_m8_st,
+ mf_m4_m8_stst,
+ mf_m4_m8_m10_st,
+ mf_m10,
+ mf_optst,
+ mf_st,
+ mf_stst,
+ mf_w_inher,
+ mf_w_m,
+ mf_w_m2,
+ mf_w_m2_ax,
+ mgroup1,
+ mgroup2,
+ mgroup6,
+ mgroup7,
+ mgroup8,
+ mGvEv,
+ mGvMa,
+ mGvMp,
+ mimul,
+ min,
+ mincdec,
+ minher,
+ minher16,
+ minher32,
+ minhera,
+ mint,
+ mjcc,
+ mjcxz,
+ mlea,
+ mmov,
+ mmovx,
+ mnegnot,
+ mout,
+ mpushpop,
+ mret,
+ mseg,
+ msetcc,
+ mshdouble,
+ mtest,
+ mxchg,
+#endif /* I80386 */
+
+#ifdef MC6809
+ mall, /* all address modes allowed, like LDA */
+ malter, /* all but immediate, like STA */
+ mimmed, /* immediate only (ANDCC, ORCC) */
+ mindex, /* indexed (LEA's) */
+ minher, /* inherent, like CLC or CLRA */
+ mlong, /* long branches */
+ mshort, /* short branches */
+ msstak, /* S-stack (PSHS, PULS) */
+ mswap, /* TFR, EXG */
+ mustak, /* U-stack (PSHU,PULU) */
+#endif /* MC6809 */
+};
+
+FORWARD void asline P((void));
+
+/*
+ This uses registers as follows: A is for work and is not preserved by
+ the subroutines.B holds the last symbol code, X usually points to data
+ about the last symbol, U usually holds the value of last expression
+ or symbol, and Y points to the current char. The value in Y is needed
+ by READCH and GETSYM. EXPRES needs B and Y, and returns a value in U.
+ If the expression starts with an identifier, X must point to its string.
+ LOOKUP needs a string pointer in X and length in A. It returns a table
+ pointer in X (unless not assembling and not found), symbol type in A
+ and overflow in CC.
+*/
+
+PUBLIC void assemble()
+{
+ while (TRUE)
+ {
+ asline();
+ if (label != NULL) /* must be confirmed if still set */
+ { /* it is nulled by EQU, COMM and SET */
+#ifndef MC6809
+#define NEEDENDLABEL ILLAB
+ if (nocolonlabel)
+ error(NEEDENDLABEL);
+#endif
+ label->type |= LABIT; /* confirm, perhaps redundant */
+ if (label->type & REDBIT)
+ {
+ /* REDBIT meant 'GLOBLBIT' while LABIT was not set. */
+ label->type |= EXPBIT;
+ label->type &= ~REDBIT;
+ }
+ if ((mcount | popflags) == 0)
+ /* unaccompanied label, display adr like EQU and SET */
+ showlabel();
+ label = NULL; /* reset for next line */
+ }
+ skipline();
+ listline();
+ genbin();
+ genobj();
+ binmbuf = lc += lcjump
+#ifdef I80386
+ + immcount
+#endif
+ ;
+ }
+}
+
+PRIVATE void asline()
+{
+ register struct sym_s *symptr;
+
+ postb = popflags = pcrflag =
+#ifdef I80386
+ sprefix = oprefix = aprefix =
+#endif
+ immcount = lastexp.data = lcjump = 0;
+#ifdef I80386
+ sib = NO_SIB;
+#endif
+#if SIZEOF_OFFSET_T > 2
+ fqflag =
+#endif
+ fdflag = fcflag = FALSE;
+ readline();
+ getsym();
+ if (sym != IDENT) /* expect label, mnemonic or macro */
+ return; /* anything else is a comment */
+ symptr = gsymptr;
+ if (!ifflag)
+ /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */
+ {
+ if (symptr == NULL || !(symptr->type & MNREGBIT) ||
+ symptr->data & REGBIT ||
+ symptr->value_reg_or_op.op.routine >= MIN_NONCOND)
+ return;
+ }
+ else if (!(symptr->type & (MACBIT | MNREGBIT)))
+ /* not macro, op, pseudo-op or register, expect label */
+ {
+ if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */
+ {
+ sym = COLON;
+ ++lineptr;
+ }
+ if (symptr->type & (LABIT | VARBIT))
+ {
+ if (symptr->type & REDBIT)
+ labelerror(RELAB);
+ label = symptr;
+ }
+ else if (checksegrel(symptr))
+ {
+ symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */
+#ifdef MC6809
+#if 0
+ if (sym == COLON)
+ symptr->type |= EXPBIT;
+#endif
+#endif
+ symptr->data = (symptr->data & FORBIT) | lcdata;
+ /* remember if forward referenced */
+ symptr->value_reg_or_op.value = lc;
+ /* unless changed by EQU,COMM or SET */
+ label = symptr;
+ }
+ getsym();
+ if (sym != IDENT)
+ {
+ if (sym == EQOP)
+ {
+ getsym();
+ pequ();
+ }
+ return; /* anything but ident is comment */
+ }
+ symptr = gsymptr;
+ }
+ if (symptr->type & MACBIT)
+ {
+ entermac(symptr);
+ return;
+ }
+ if (!(symptr->type & MNREGBIT))
+ {
+ error(OPEXP);
+ return;
+ }
+ if (symptr->data & REGBIT)
+ {
+ error(REGUID);
+ return;
+ }
+ mnsize = 0;
+ if ((page = (symptr->data & (PAGE1 | PAGE2))) != 0)
+ {
+#ifdef MNSIZE
+ if (page == (PAGE1 | PAGE2))
+ {
+ mnsize = 1;
+ page = 0;
+ }
+ else
+#endif
+ {
+#ifdef PAGE2_OPCODE
+ if (page == PAGE2)
+ page = PAGE2_OPCODE;
+ else
+#endif
+ page = PAGE1_OPCODE;
+ mcount = 1;
+ }
+ }
+ opcode = symptr->value_reg_or_op.op.opcode;
+ routine = rout_table[symptr->value_reg_or_op.op.routine];
+ getsym();
+ (*routine)();
+ if (sym != EOLSYM)
+ error(JUNK_AFTER_OPERANDS);
+#ifdef I80386
+ if (aprefix != 0)
+ ++mcount;
+ if (oprefix != 0)
+ ++mcount;
+ if (sprefix != 0)
+ ++mcount;
+#endif
+}
diff --git a/as/bin/calljmp.bin b/as/bin/calljmp.bin
new file mode 100644
index 0000000..90c022f
--- /dev/null
+++ b/as/bin/calljmp.bin
Binary files differ
diff --git a/as/bin/ea.bin b/as/bin/ea.bin
new file mode 100644
index 0000000..5edc0b0
--- /dev/null
+++ b/as/bin/ea.bin
Binary files differ
diff --git a/as/bin/each.bin b/as/bin/each.bin
new file mode 100644
index 0000000..211155f
--- /dev/null
+++ b/as/bin/each.bin
Binary files differ
diff --git a/as/bin/f.bin b/as/bin/f.bin
new file mode 100644
index 0000000..ce695a0
--- /dev/null
+++ b/as/bin/f.bin
Binary files differ
diff --git a/as/bin/fadd.bin b/as/bin/fadd.bin
new file mode 100644
index 0000000..9afa6fc
--- /dev/null
+++ b/as/bin/fadd.bin
Binary files differ
diff --git a/as/bin/farcall.bin b/as/bin/farcall.bin
new file mode 100644
index 0000000..797a87c
--- /dev/null
+++ b/as/bin/farcall.bin
Binary files differ
diff --git a/as/bin/group1.bin b/as/bin/group1.bin
new file mode 100644
index 0000000..64a01bf
--- /dev/null
+++ b/as/bin/group1.bin
Binary files differ
diff --git a/as/bin/group6.bin b/as/bin/group6.bin
new file mode 100644
index 0000000..22ff663
--- /dev/null
+++ b/as/bin/group6.bin
Binary files differ
diff --git a/as/bin/group7.bin b/as/bin/group7.bin
new file mode 100644
index 0000000..9570eee
--- /dev/null
+++ b/as/bin/group7.bin
Binary files differ
diff --git a/as/bin/imul.bin b/as/bin/imul.bin
new file mode 100644
index 0000000..2b8ea16
--- /dev/null
+++ b/as/bin/imul.bin
Binary files differ
diff --git a/as/bin/incdec.bin b/as/bin/incdec.bin
new file mode 100644
index 0000000..676e5fa
--- /dev/null
+++ b/as/bin/incdec.bin
Binary files differ
diff --git a/as/bin/inher.bin b/as/bin/inher.bin
new file mode 100644
index 0000000..b37b3eb
--- /dev/null
+++ b/as/bin/inher.bin
Binary files differ
diff --git a/as/bin/inout.bin b/as/bin/inout.bin
new file mode 100644
index 0000000..a215490
--- /dev/null
+++ b/as/bin/inout.bin
Binary files differ
diff --git a/as/bin/movspec.bin b/as/bin/movspec.bin
new file mode 100644
index 0000000..6a5ef0a
--- /dev/null
+++ b/as/bin/movspec.bin
Binary files differ
diff --git a/as/bin/pushpop.bin b/as/bin/pushpop.bin
new file mode 100644
index 0000000..f95d6b5
--- /dev/null
+++ b/as/bin/pushpop.bin
Binary files differ
diff --git a/as/bin/seg.bin b/as/bin/seg.bin
new file mode 100644
index 0000000..43445a6
--- /dev/null
+++ b/as/bin/seg.bin
Binary files differ
diff --git a/as/bin/shdouble.bin b/as/bin/shdouble.bin
new file mode 100644
index 0000000..91bda37
--- /dev/null
+++ b/as/bin/shdouble.bin
Binary files differ
diff --git a/as/bin/shift.bin b/as/bin/shift.bin
new file mode 100644
index 0000000..1e31fac
--- /dev/null
+++ b/as/bin/shift.bin
Binary files differ
diff --git a/as/bin/xchg.bin b/as/bin/xchg.bin
new file mode 100644
index 0000000..6455b67
--- /dev/null
+++ b/as/bin/xchg.bin
Binary files differ
diff --git a/as/byteord.h b/as/byteord.h
new file mode 100644
index 0000000..a0d14e1
--- /dev/null
+++ b/as/byteord.h
@@ -0,0 +1,18 @@
+/* byteord.h - byte order dependencies for C compiler, assembler, linker */
+
+/* These are for the targets of everything and for linker source too. */
+
+#ifdef I8086
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */
+#endif
+
+#ifdef I80386
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0
+#endif
+
+#ifdef MC6809
+# define BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
diff --git a/as/chk b/as/chk
new file mode 100755
index 0000000..89c73de
--- /dev/null
+++ b/as/chk
@@ -0,0 +1,9 @@
+for i in `ls asm/*.asm`
+do
+ j=`basename $i .asm`
+ ./as asm/$j.asm -b $j.bin -o $j.obj > /dev/null
+ cmp $j.bin bin/$j.bin
+ cmp $j.obj obj1/$j.obj
+ rm $j.bin $j.obj
+done
+
diff --git a/as/const.h b/as/const.h
new file mode 100644
index 0000000..78523e5
--- /dev/null
+++ b/as/const.h
@@ -0,0 +1,409 @@
+#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */
+#define LOW_BYTE 0 /* must be changed for big-endian */
+
+/* const.h - constants for assembler */
+
+/* major switches */
+
+#define I80386 /* generate 80386 code */
+#undef MC6809 /* generate 6809 code */
+#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */
+#undef SOS_EDOS /* source OS is EDOS */
+
+/* defaults */
+
+#define DIRCHAR '/' /* character separating filename from dir */
+#define INBUFSIZE 8192
+#define SOS_EOLSTR "\012"
+
+/* defaults modified by switches */
+
+#ifdef SOS_EDOS
+# undef INBUFSIZE
+# define INBUFSIZE 512
+# undef SOS_EOLSTR
+# define SOS_EOLSTR "\015\012"
+# define STAKSIZ 256 /* table grows up to stack less this */
+#endif
+
+/* booleans */
+
+#define FALSE 0
+#define TRUE 1
+
+/* ASCII constants */
+
+#define ETB 23
+
+/* C tricks */
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+#define NULL 0
+
+/* O/S constants */
+
+#define CREAT_PERMS 0666
+#define EOF (-1)
+#define STDIN 0
+#define STDOUT 1
+
+enum
+{
+/* Register codes (internal to assembler). */
+#ifdef I80386
+
+/* Index regs must be first. */
+ BPREG,
+ BXREG,
+ DIREG,
+ SIREG,
+#define MAX16BITINDREG SIREG
+
+ EAXREG,
+ EBPREG,
+ EBXREG,
+ ECXREG,
+ EDIREG,
+ EDXREG,
+ ESIREG,
+ ESPREG,
+#define MAXINDREG ESPREG
+
+ AXREG,
+ CXREG,
+ DXREG,
+ SPREG,
+
+ AHREG,
+ ALREG,
+ BHREG,
+ BLREG,
+ CHREG,
+ CLREG,
+ DHREG,
+ DLREG,
+
+ CSREG,
+ DSREG,
+ ESREG,
+ FSREG,
+ GSREG,
+ SSREG,
+
+ CR0REG,
+ CR2REG,
+ CR3REG,
+ DR0REG,
+ DR1REG,
+ DR2REG,
+ DR3REG,
+ DR6REG,
+ DR7REG,
+ TR3REG,
+ TR4REG,
+ TR5REG,
+ TR6REG,
+ TR7REG,
+
+ ST0REG,
+ ST1REG,
+ ST2REG,
+ ST3REG,
+ ST4REG,
+ ST5REG,
+ ST6REG,
+ ST7REG,
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* Index regs must be first, then PC. */
+ SREG,
+ UREG,
+ XREG,
+ YREG,
+#define MAXINDREG YREG
+
+ PCREG,
+ AREG,
+ BREG,
+ CCREG,
+ DPREG,
+ DREG,
+#endif /* MC6809 */
+
+ NOREG
+};
+
+#ifdef I80386
+enum
+{
+/* Type and size keywords. */
+ BYTEOP,
+ DWORDOP,
+ FWORDOP,
+ FAROP,
+ PTROP,
+ PWORDOP,
+ QWORDOP,
+ TBYTEOP,
+ WORDOP
+};
+#endif /* I80386 */
+
+/* special chars */
+
+#define EOL 0
+#define MACROCHAR '?'
+
+enum
+{
+/* Symbol codes. */
+
+/* The first 2 must be from chars in identifiers. */
+ IDENT,
+ INTCONST,
+
+/* The next few are best for other possibly-multi-char tokens. */
+ ADDOP, /* also ++ */
+ BINCONST,
+ CHARCONST,
+ GREATERTHAN, /* also >> and context-sensitive */
+ HEXCONST,
+ LESSTHAN, /* also << and context-sensitive */
+ SUBOP, /* also -- */
+ WHITESPACE,
+
+ ANDOP,
+ COMMA,
+ EOLSYM,
+ EQOP,
+ IMMEDIATE,
+ INDIRECT,
+ LBRACKET,
+ LPAREN,
+ MACROARG,
+ NOTOP,
+ OROP,
+ OTHERSYM,
+ POSTINCOP,
+ PREDECOP,
+ RBRACKET,
+ RPAREN,
+ SLASH, /* context-sensitive */
+ SLOP,
+ SROP,
+ STAR, /* context-sensitive */
+ STRINGCONST,
+ COLON
+};
+
+enum
+{
+/* Error codes. */
+
+/* Syntax errors. */
+ COMEXP,
+ DELEXP,
+ FACEXP,
+ IREGEXP,
+ LABEXP,
+ LPEXP,
+ OPEXP,
+ RBEXP,
+ REGEXP,
+ RPEXP,
+ SPEXP,
+
+/* Expression errors. */
+ ABSREQ,
+ NONIMPREQ,
+ RELBAD,
+
+/* Label errors. */
+ ILLAB,
+ MACUID,
+ MISLAB,
+ MNUID,
+ REGUID,
+ RELAB,
+ UNBLAB,
+ UNLAB,
+ VARLAB,
+
+/* Addressing errors. */
+ ABOUNDS,
+ DBOUNDS,
+ ILLMOD,
+ ILLREG,
+
+/* Control structure errors. */
+ ELSEBAD,
+#define ELSEIFBAD ELSEBAD
+ ENDBBAD,
+#define ENDIFBAD ELSEBAD
+ EOFBLOCK,
+ EOFIF,
+ EOFLC,
+ EOFMAC,
+ FAILERR,
+
+/* Overflow errors. */
+ BLOCKOV,
+ BWRAP,
+ COUNTOV,
+ COUNTUN,
+ GETOV,
+ IFOV,
+
+ LINLONG,
+ MACOV,
+ OBJSYMOV,
+ OWRITE,
+ PAROV,
+ SYMOV,
+ SYMOUTOV,
+
+/* I/O errors. */
+ OBJOUT,
+
+/* Miscellaneous errors. */
+ AL_AX_EAX_EXP,
+ CTLINS,
+ FURTHER,
+ ILL_IMM_MODE,
+ ILL_IND_TO_IND,
+ ILL_IND,
+ ILL_IND_PTR,
+ ILL_SCALE,
+ ILL_SECTION,
+ ILL_SEG_REG,
+ ILL_SOURCE_EA,
+ ILL_SIZE,
+ IMM_REQ,
+ INDEX_REG_EXP,
+ IND_REQ,
+ MISMATCHED_SIZE,
+ NOIMPORT,
+ REENTER,
+ REL_REQ,
+ REPEATED_DISPL,
+ SEGREL,
+ SEG_REG_REQ,
+ SIZE_UNK,
+ UNKNOWN_ESCAPE_SEQUENCE,
+
+ FP_REG_REQ,
+ FP_REG_NOT_ALLOWED,
+ ILL_FP_REG,
+ ILL_FP_REG_PAIR,
+ JUNK_AFTER_OPERANDS,
+
+ ALREADY,
+
+/* Warnings. */
+#define MINWARN SHORTB
+ SHORTB
+};
+
+/* symbol table entry */
+
+ /* type entry contains following flags */
+#define ENTBIT (1<<0) /* entry point (= OBJ_N_MASK) */
+#define COMMBIT (1<<1) /* common */
+#define LABIT (1<<2) /* label (a PC location or defined by EQU) */
+#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */
+#define MACBIT (1<<4) /* macro */
+#define REDBIT (1<<5) /* redefined (if with LABIT or VARBIT), to do
+ * with SA_MASK (if with COMMBIT), otherwise
+ * means globl */
+#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */
+#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */
+
+ /* data entry contains following flags, valid */
+ /* for expressions as well as syms */
+#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT | PAGE1 */
+#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT | PAGE2 */
+#define REGBIT (1<<2) /* register = MNREGBIT | REGBIT */
+#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT | SIZEBIT */
+#define SEGM 0x0F /* 1st 4 bits reused for segment if !MNREGBIT */
+#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */
+#define FORBIT (1<<5) /* forward referenced */
+#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */
+#define UNDBIT (1<<7) /* undefined */
+
+/* object code format (Introl) */
+
+#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */
+
+#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */
+
+#define OBJ_ABS 0x40 /* absolute code command */
+#define OBJ_OFFSET_REL 0x80 /* offset relocation command */
+#define OBJ_SET_SEG 0x20 /* set segment command */
+#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */
+#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */
+#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */
+#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */
+
+#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */
+#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */
+oops - RELBIT misplaced
+#endif
+#define OBJ_E_MASK 0x80 /* exported bit (symbols) */
+#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */
+oops - EXPBIT misplaced
+#endif
+#define OBJ_I_MASK 0x40 /* imported bit (symbols) */
+#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */
+oops - IMPBIT misplaced
+#endif
+#define OBJ_N_MASK 0x01 /* entry bit (symbols) */
+#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */
+oops - ENTBIT misplaced
+#endif
+#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */
+#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */
+#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */
+#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */
+
+#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */
+#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */
+
+#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */
+#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */
+
+#define SYMLIS_NAMELEN 26
+#define SYMLIS_LEN (sizeof (struct sym_listing_s))
+
+#define FILNAMLEN 64 /* max length of a file name */
+#define LINLEN 256 /* max length of input line */
+#define LINUM_LEN 5 /* length of formatted line number */
+
+#define SPTSIZ 1024 /* number of symbol ptrs */
+ /* pseudo-op flags */
+#define POPHI 1 /* set to print hi byte of adr */
+#define POPLO 2 /* to print lo byte of ADR */
+#define POPLC 4 /* to print LC */
+#define POPLONG 8 /* to print high word of ADR */
+#define MAXBLOCK 8 /* max nesting level of BLOCK stack */
+#define MAXGET 8 /* max nesting level of GET stack */
+#define MAXIF 8 /* max nesting level of IF stack */
+#define MACPSIZ (128 / sizeof (struct schain_s))
+ /* size of macro param buffer */
+#define MAXMAC 8 /* max nesting level of macro stack */
+#define NLOC 16 /* number of location counters */
+#ifdef I80386
+#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */
+#endif
+
+/* special segments */
+
+#define BSSLOC 3
+#define DATALOC 3
+#define DPLOC 2
+#define STRLOC 1
+#define TEXTLOC 0
diff --git a/as/error.c b/as/error.c
new file mode 100644
index 0000000..6cb4da7
--- /dev/null
+++ b/as/error.c
@@ -0,0 +1,106 @@
+/* error.c - error routines for assembler */
+
+#include "const.h"
+#include "type.h"
+
+#ifdef STDC_HEADERS_MISSING
+char *strcpy P((char *s1, const char *s2));
+#else
+#undef NULL
+#include <string.h>
+#endif
+
+PRIVATE char *errormessage[] =
+{
+ "comma expected",
+ "delimiter expected",
+ "factor expected",
+ "index register expected",
+ "label expected",
+ "left parentheses expected",
+ "opcode expected",
+ "right bracket expected",
+ "register expected",
+ "right parentheses expected",
+ "space expected",
+ "absolute expression required",
+ "non-imported expression required",
+ "relocation impossible",
+ "illegal label",
+ "MACRO used as identifier",
+ "missing label",
+ "opcode used as identifier",
+ "register used as identifier",
+ "redefined label",
+ "unbound label",
+ "undefined label",
+ "variable used as label",
+ "address out of bounds",
+ "data out of bounds",
+ "illegal address mode",
+ "illegal register",
+ "no matching IF",
+ "no matching BLOCK",
+ "end of file in BLOCK",
+ "end of file in IF",
+ "location counter was undefined at end",
+ "end of file in MACRO",
+ "user-generated error",
+ "BLOCK stack overflow",
+ "binary file wrap-around",
+ "counter overflow",
+ "counter underflow",
+ "GET stack overflow",
+ "IF stack overflow",
+ "line too long",
+ "MACRO stack overflow",
+ "object symbol table overflow",
+ "program overwrite",
+ "parameter table overflow",
+ "symbol table overflow",
+ "output symbol table overflow",
+ "error writing object file",
+ "al, ax or eax expected",
+ "control character in string",
+ "futher errors suppressed",
+ "illegal immediate mode",
+ "illegal indirect to indirect",
+ "illegal indirection",
+ "illegal indirection from previous 'ptr'",
+ "illegal scale",
+ "illegal section",
+ "illegal segment register",
+ "illegal source effective address",
+ "illegal size",
+ "immediate expression expected",
+ "index register expected",
+ "indirect expression required",
+ "mismatched size",
+ "no imports with binary file output",
+ "multiple ENTER pseudo-ops",
+ "relative expression required",
+ "repeated displacement",
+ "segment or relocatability redefined",
+ "segment register required",
+ "size unknown",
+ "unknown escape sequence",
+ "FP register required",
+ "FP register not allowed",
+ "illegal FP register",
+ "illegal FP register pair",
+ "junk after operands",
+ "already defined",
+ "short branch would do",
+ "unknown error",
+};
+
+/* build null-terminated error message for given error at given spot */
+
+PUBLIC char *build_error_message(errnum, buf)
+error_pt errnum;
+char *buf;
+{
+ if (errnum >= sizeof errormessage / sizeof errormessage[0])
+ errnum = sizeof errormessage / sizeof errormessage[0] - 1;
+ return strcpy(buf, errormessage[errnum]);
+}
diff --git a/as/express.c b/as/express.c
new file mode 100644
index 0000000..54dff2f
--- /dev/null
+++ b/as/express.c
@@ -0,0 +1,382 @@
+/* express.c - expression handler for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "globvar.h"
+#include "scan.h"
+#include "source.h"
+
+FORWARD void experror P((error_pt errnum));
+FORWARD void expundefined P((void));
+FORWARD void simple2 P((void));
+FORWARD void simple P((void));
+FORWARD void term P((void));
+FORWARD void factor2 P((void));
+
+PUBLIC void absexpres()
+{
+ expres();
+ chkabs();
+}
+
+/* check lastexp.data is abs */
+
+PUBLIC void chkabs()
+{
+ if (lastexp.data & RELBIT)
+ {
+ if (pass != 0)
+ error(ABSREQ);
+ expundefined();
+ }
+}
+
+PRIVATE void experror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ expundefined();
+}
+
+PRIVATE void expundefined()
+{
+ lastexp.data = FORBIT | UNDBIT;
+}
+
+PUBLIC void nonimpexpres()
+{
+ expres();
+ if (lastexp.data & IMPBIT)
+ experror(NONIMPREQ);
+}
+
+/* generate relocation error if pass 2, make lastexp.data forward&undefined */
+
+PUBLIC void showrelbad()
+{
+ if (pass != 0)
+ error(RELBAD);
+ expundefined();
+}
+
+PUBLIC void symabsexpres()
+{
+ getsym();
+ absexpres();
+}
+
+PUBLIC void symexpres()
+{
+ getsym();
+ expres();
+}
+
+/*
+ expres() parses expression = simple expression [op simple expression],
+ where op is =, < or >.
+ Parameters: sym, number in number, identifier from symname to lineptr - 1.
+ Returns value in lastexp.
+*/
+
+PUBLIC void expres()
+{
+ offset_t leftoffset;
+
+ simple();
+ leftoffset = lastexp.offset;
+ if (sym == EQOP)
+ {
+ simple2();
+ if (leftoffset == lastexp.offset)
+ lastexp.offset = -1;
+ else
+ lastexp.offset = 0;
+ }
+ else if (sym == LESSTHAN)
+ {
+ /* context-sensitive, LESSTHAN really means less than here */
+ simple2();
+ if (leftoffset < lastexp.offset)
+ lastexp.offset = -1;
+ else
+ lastexp.offset = 0;
+ }
+ else if (sym == GREATERTHAN)
+ {
+ /* context-sensitive, GREATERTHAN really means greater than here */
+ simple2();
+ if (leftoffset > lastexp.offset)
+ lastexp.offset = -1;
+ else
+ lastexp.offset = 0;
+ }
+}
+
+/* get symbol and 2nd simple expression, check both rel or both abs */
+
+PRIVATE void simple2()
+{
+ unsigned char leftdata;
+
+ leftdata = lastexp.data;
+ getsym();
+ simple();
+ if ((leftdata | lastexp.data) & IMPBIT ||
+ (leftdata ^ lastexp.data) & (RELBIT | SEGM))
+ showrelbad();
+ else
+ lastexp.data = (leftdata & lastexp.data) & ~(RELBIT | SEGM);
+}
+
+/*
+ simple() parses simple expression = [+-] term {op term},
+ where op is +, -, or \ (OR).
+*/
+
+PRIVATE void simple()
+{
+ offset_t leftoffset;
+ unsigned char leftdata;
+
+ if (sym == ADDOP || sym == SUBOP)
+ lastexp.data = lastexp.offset = 0;
+ else
+ term();
+ while (TRUE)
+ {
+ leftoffset = lastexp.offset;
+ leftdata = lastexp.data;
+ if (sym == ADDOP)
+ {
+ getsym();
+ term();
+ if (leftdata & lastexp.data & RELBIT)
+ showrelbad(); /* rel + rel no good */
+ else
+ lastexp.data |= leftdata;
+ lastexp.offset += leftoffset;
+ }
+ else if (sym == SUBOP)
+ {
+ getsym();
+ term();
+ /* check not abs - rel or rel - rel with mismatch */
+ if (lastexp.data & RELBIT &&
+ (!(leftdata & RELBIT) ||
+ (leftdata | lastexp.data) & IMPBIT ||
+ (leftdata ^ lastexp.data) & (RELBIT | SEGM)))
+ showrelbad();
+ else
+ lastexp.data = ((leftdata | lastexp.data) & ~(RELBIT | SEGM))
+ | ((leftdata ^ lastexp.data) & (RELBIT | SEGM));
+ lastexp.offset = leftoffset - lastexp.offset;
+ }
+ else if (sym == OROP)
+ {
+ getsym();
+ term();
+ lastexp.data |= leftdata;
+ chkabs(); /* both must be absolute */
+ lastexp.offset |= leftoffset;
+ }
+ else
+ return;
+ }
+}
+
+/* term() parses term = factor {op factor}, where op is *, /, &, <<, or >>. */
+
+PRIVATE void term()
+{
+ offset_t leftoffset;
+
+ factor();
+ while (TRUE)
+ {
+ leftoffset = lastexp.offset;
+ if (sym == STAR)
+ {
+ /* context-sensitive, STAR means multiplication here */
+ factor2();
+ lastexp.offset *= leftoffset;
+ }
+ else if (sym == SLASH)
+ {
+ /* context-sensitive, SLASH means division here */
+ factor2();
+ lastexp.offset = leftoffset / lastexp.offset;
+ }
+ else if (sym == ANDOP)
+ {
+ factor2();
+ lastexp.offset &= leftoffset;
+ }
+ else if (sym == SLOP)
+ {
+ factor2();
+ lastexp.offset = leftoffset << lastexp.offset;
+ }
+ else if (sym == SROP)
+ {
+ factor2();
+ lastexp.offset = leftoffset >> lastexp.offset;
+ }
+ else
+ return;
+ }
+}
+
+/* get symbol and 2nd or later factor, check both abs */
+
+PRIVATE void factor2()
+{
+ unsigned char leftdata;
+
+ leftdata = lastexp.data;
+ getsym();
+ factor();
+ lastexp.data |= leftdata;
+ chkabs();
+}
+
+/*
+ factor() parses factor = number | identifier | * | (expression) | ! factor,
+ ! is complementation. Returns value in lastexp.offset, possible flags
+ IMPBIT, FORBIT, RELBIT and UNDBIT in lastexp.data, and segment in SEGM
+ part of lastexp.data, and lastexp.sym at imported symbol if IMPBIT.
+ If the factor is an identifier, LOOKUP is used to get its value
+ (so the ident is installed in the symbol table if necessary, with
+ default flags inidata). If the identifier is not a label,
+ (could be imported, or later in the program), its FORBIT is set.
+ The expression FORBIT, IMPBIT, RELBIT, UNDBIT and SEGM are then
+ taken from the identifier.
+*/
+
+PUBLIC void factor()
+{
+ switch (sym)
+ {
+ case SLASH:
+ /* context-sensitive, SLASH means a hex number here */
+ context_hexconst();
+ case INTCONST:
+ lastexp.data = 0; /* absolute & not forward or undefined */
+ lastexp.offset = number;
+ getsym();
+ return;
+ case IDENT:
+ {
+ register struct sym_s *symptr;
+
+ symptr = gsymptr;
+ if (symptr->type & (MNREGBIT | MACBIT))
+ experror(symptr->type & MACBIT ? MACUID :
+ symptr->data & REGBIT ? REGUID : MNUID);
+ else
+ {
+ if (!(symptr->type & (LABIT | VARBIT)))
+ {
+ symptr->data |= FORBIT;
+ lastexp.sym = symptr;
+ }
+ if (pass == 0)
+ {
+ lastexp.data = symptr->data &
+ (FORBIT | RELBIT | UNDBIT | SEGM);
+ /* possible flags for pass 1 */
+ lastexp.offset = symptr->value_reg_or_op.value;
+ }
+ else
+ {
+ if ((lastexp.data = symptr->data) & IMPBIT)
+ lastexp.offset = 0; /* value != 0 for commons */
+ /* OK even if UNDBIT */
+ else
+ {
+ lastexp.offset = symptr->value_reg_or_op.value;
+ if (lastexp.data & UNDBIT)
+ experror(UNBLAB);
+ }
+ }
+ }
+ getsym();
+ return;
+ }
+ case LBRACKET:
+ if (!asld_compatible)
+ break; /* error, LPAREN is the grouping symbol */
+ getsym();
+ expres();
+ if (sym != RBRACKET)
+ error(RBEXP);
+ else
+ getsym();
+ return;
+ case LPAREN:
+ if (asld_compatible)
+ break; /* error, LBRACKET is the grouping symbol */
+ getsym();
+ expres();
+ if (sym != RPAREN)
+ error(RPEXP);
+ else
+ getsym();
+ return;
+ case NOTOP:
+ getsym();
+ factor();
+ chkabs();
+ lastexp.offset = ~lastexp.offset;
+ return;
+ case STAR:
+ /* context-sensitive, STAR means location counter here */
+ lastexp.offset = lc;
+ if ((lastexp.data = lcdata) & UNDBIT && pass != 0)
+ experror(UNBLAB);
+ getsym();
+ return;
+ }
+ experror(FACEXP);
+}
+
+/*
+ string compare for IFC/ELSEIFC
+ expects (<string1>,<string2>)
+ returns logical value in lastexp
+*/
+
+PUBLIC void scompare()
+{
+ /* prepare flags for OK, lastexp.offset for error */
+ lastexp.data = lastexp.offset = 0;
+ if (sym != LPAREN)
+ experror(LPEXP);
+ else
+ {
+ register char *string1;
+ register char *string2;
+
+ for (string2 = string1 = lineptr; *string2 != ')'; ++string2)
+ if (*string2 == 0 || *string2 == ')')
+ {
+ symname = string2;
+ experror(COMEXP);
+ return;
+ }
+ while (*string1++ == *string2++)
+ ;
+ if (string2[-1] == ')')
+ {
+ if (string1[-1] == ',')
+ lastexp.offset = TRUE; /* else leave FALSE */
+ }
+ else /* FALSE, keep reading to verify syntax */
+ for (; *string2 != ')'; ++string2)
+ if (*string2 == 0 || *string2 == ',')
+ {
+ symname = string2;
+ experror(RPEXP);
+ }
+ }
+}
diff --git a/as/file.h b/as/file.h
new file mode 100644
index 0000000..1272d47
--- /dev/null
+++ b/as/file.h
@@ -0,0 +1,12 @@
+/* file.h - global variables involving files for assembler */
+
+EXTERN fd_t binfil; /* binary output file (0 = memory) */
+EXTERN char *filnamptr; /* file name pointer */
+EXTERN fd_t infil0; /* initial input file */
+EXTERN fd_t infil; /* current input file (stacked, 0 = memory) */
+EXTERN unsigned char infiln; /* innum when file was opened */
+EXTERN unsigned char innum; /* counter for calls to open */
+EXTERN fd_t lstfil; /* list output file (0 = standard) */
+EXTERN fd_t objfil; /* object output file */
+EXTERN fd_t symfil; /* symbol table output file */
+EXTERN char *truefilename; /* in case actual source name is a tmpname */
diff --git a/as/flag.h b/as/flag.h
new file mode 100644
index 0000000..791dcc1
--- /dev/null
+++ b/as/flag.h
@@ -0,0 +1,5 @@
+/* flag.h - global structured-flag variables for assembler */
+
+EXTERN struct flags_s list; /* listing on/off */
+EXTERN struct flags_s maclist; /* list macros on/off */
+EXTERN struct flags_s warn; /* warnings on/off */
diff --git a/as/genbin.c b/as/genbin.c
new file mode 100644
index 0000000..ce16405
--- /dev/null
+++ b/as/genbin.c
@@ -0,0 +1,220 @@
+/* genbin.c - binary code generation routines for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "file.h"
+#include "globvar.h"
+
+PRIVATE char *asmbeg; /* beginning of assembler code */
+ /* for overwrite check */
+ /* bss-init to zero = NULL and not changed */
+PRIVATE offset_t binfbuf; /* binary code buffer for file (counter) */
+PRIVATE offset_t binmax; /* maximum value of binmbuf for pass 1 */
+PRIVATE offset_t binmin; /* minimum value of binmbuf for pass 1 */
+
+FORWARD void putbinoffset P((offset_t offset, count_t size));
+
+/* write header to binary file */
+
+PUBLIC void binheader()
+{
+ if ((innum = binfil) != 0x0)
+ {
+ writec(0x0); /* binary header byte */
+#ifdef LONG_BINHEADER
+ writeoff(binmax - binmin); /* program length */
+ writeoff(binfbuf = binmin); /* program start */
+#else
+ writew((unsigned) (binmax - binmin)); /* program length */
+ writew((unsigned) (binfbuf = binmin)); /* program start */
+#endif
+ }
+}
+
+/* write trailer to binary file */
+
+PUBLIC void bintrailer()
+{
+ if ((innum = binfil) != 0x0)
+ {
+ writec(0xFF); /* binary trailer byte */
+ writew(0x0); /* further trailer bytes */
+#ifdef LONG_BINHEADER
+ writeoff(pedata & UNDBIT ? binmin : progent); /* entry point */
+#else
+ writew(pedata & UNDBIT ? (unsigned) binmin : (unsigned) progent);
+#endif
+ }
+}
+
+/* generate binary code for current line */
+
+PUBLIC void genbin()
+{
+ struct address_s *adrptr;
+ char *bufptr;
+ unsigned char remaining;
+
+ if (binaryg && mcount != 0x0)
+ {
+ if (popflags)
+ {
+ if (fcflag)
+ {
+ bufptr = databuf.fcbuf;
+ remaining = mcount;
+ do
+ putbin(*bufptr++);
+ while (--remaining != 0x0);
+ }
+ if (fdflag)
+ {
+ adrptr = databuf.fdbuf;
+ remaining = mcount;
+ do
+ {
+ putbinoffset(adrptr->offset, 0x2);
+ ++adrptr;
+ }
+ while ((remaining -= 0x2) != 0x0);
+ }
+#if SIZEOF_OFFSET_T > 0x2
+ if (fqflag)
+ {
+ adrptr = databuf.fqbuf;
+ remaining = mcount;
+ do
+ {
+ putbinoffset(adrptr->offset, 0x4);
+ ++adrptr;
+ }
+ while ((remaining -= 0x4) != 0x0);
+ }
+#endif
+ }
+ else
+ {
+ remaining = mcount - 0x1; /* count opcode immediately */
+#ifdef I80386
+ if (aprefix != 0x0)
+ {
+ putbin(aprefix);
+ --remaining;
+ }
+ if (oprefix != 0x0)
+ {
+ putbin(oprefix);
+ --remaining;
+ }
+ if (sprefix != 0x0)
+ {
+ putbin(sprefix);
+ --remaining;
+ }
+#endif
+ if (page != 0x0)
+ {
+ putbin(page);
+ --remaining;
+ }
+ putbin(opcode);
+ if (remaining != 0x0)
+ {
+ if (postb != 0x0)
+ {
+ putbin(postb);
+ --remaining;
+ }
+#ifdef I80386
+ if (sib != NO_SIB)
+ {
+ putbin(sib);
+ --remaining;
+ }
+#endif
+ if (remaining != 0x0)
+ putbinoffset(lastexp.offset, remaining);
+ }
+#ifdef I80386
+ if (immcount != 0x0)
+ putbinoffset(immadr.offset, immcount);
+#endif
+ }
+ /* else no code for this instruction, or already generated */
+ }
+}
+
+/* initialise private variables */
+
+PUBLIC void initbin()
+{
+ binmin = -1; /* greater than anything */
+}
+
+/* write char to binary file or directly to memory */
+
+PUBLIC void putbin(ch)
+opcode_pt ch;
+{
+ if (binfil != 0x0)
+ {
+ if (!binaryc) /* pass 1, just record limits */
+ {
+ if (binmbuf < binmin)
+ binmin = binmbuf;
+ if (++binmbuf > binmax)
+ binmax = binmbuf;
+ }
+ else
+ {
+ if (binfbuf > binmbuf)
+ error(BWRAP); /* file buffer ahead of memory buffer */
+ else
+ {
+ innum = binfil;
+ while (binfbuf < binmbuf)
+ {
+ writec(0x0);/* pad with nulls if file buffer behind */
+ ++binfbuf;
+ }
+ writec(ch);
+ binmbuf = ++binfbuf;
+ }
+ }
+ }
+ else if (binaryc && !(lcdata & UNDBIT))
+ /* memory output, and enabled */
+ {
+ register char *bufptr;
+
+ if ((bufptr = (char *) binmbuf) >= asmbeg && bufptr < heapptr)
+ error(OWRITE);
+ else
+ *bufptr = ch;
+ ++binmbuf;
+ }
+}
+
+/* write sized offset to binary file or directly to memory */
+
+PRIVATE void putbinoffset(offset, size)
+offset_t offset;
+count_t size;
+{
+ char buf[sizeof offset];
+
+#if SIZEOF_OFFSET_T > 0x2
+ u4cn(buf, offset, size);
+#else
+ u2cn(buf, offset, size);
+#endif
+ putbin(buf[0]);
+ if (size > 0x1)
+ putbin(buf[1]);
+ if (size > 0x2)
+ {
+ putbin(buf[2]);
+ putbin(buf[3]);
+ }
+}
diff --git a/as/genlist.c b/as/genlist.c
new file mode 100644
index 0000000..e179fcf
--- /dev/null
+++ b/as/genlist.c
@@ -0,0 +1,463 @@
+/* genlist.c - generate listing and error reports for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+#include "macro.h"
+#include "scan.h"
+#include "source.h"
+
+#ifdef STDC_HEADERS_MISSING
+void *memset P((void *s, int c, unsigned n));
+unsigned strlen P((const char *s));
+#else
+#undef NULL
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#undef NULL
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#define CODE_LIST_LENGTH (sizeof (struct code_listing_s) - 1)
+ /* length of formatted code listing */
+#define MAXERR 6 /* maximum errors listed per line */
+
+struct error_s /* to record error info */
+{
+ unsigned char errnum;
+ unsigned char position;
+};
+
+/* code listing format */
+
+struct code_listing_s
+{
+ union linum_macro_u
+ {
+ char linum[LINUM_LEN];
+ struct
+ {
+ char pad[1];
+ char mark[1];
+ char level[1];
+ }
+ macro;
+ }
+ linum_or_macro;
+ char padlinum[1];
+ char lc[4];
+ char padlc[1];
+#ifdef I80386
+ char lprefix[2];
+ char aprefix[2];
+ char oprefix[2];
+ char sprefix[2];
+#endif
+ char page[2];
+ char opcode[2];
+ char postb[2];
+#ifdef I80386
+ char sib[2];
+#endif
+ char padopcode[1];
+#if SIZEOF_OFFSET_T > 2
+ char displ4[2];
+ char displ3[2];
+#endif
+ char displ2[2];
+ char displ1[2];
+ char reldispl[1];
+ char paddispl[1];
+#ifdef I80386
+ char imm4[2];
+ char imm3[2];
+ char imm2[2];
+ char imm1[2];
+ char relimm[1];
+ char padimm[1];
+#endif
+ char nullterm;
+};
+
+PRIVATE struct error_s errbuf[MAXERR]; /* error buffer */
+PRIVATE unsigned char errcount; /* # errors in line */
+PRIVATE bool_t erroverflow; /* set if too many errors on line */
+
+FORWARD char *build_1hex_number P((opcode_pt num, char *where));
+FORWARD void list1 P((fd_t fd));
+FORWARD void listcode P((void));
+FORWARD void listerrors P((void));
+FORWARD void paderrorline P((unsigned nspaces));
+
+/* format 1 byte number as 2 hex digits, return ptr to end */
+
+PRIVATE char *build_1hex_number(num, where)
+opcode_pt num;
+register char *where;
+{
+ where[0] = hexdigit[((unsigned) num % 256) / 16];
+ where[1] = hexdigit[(unsigned) num % 16];
+ return where + 2;
+}
+
+/* format 2 byte number as 4 hex digits, return ptr to end */
+
+PUBLIC char *build_2hex_number(num, where)
+unsigned num;
+char *where;
+{
+ return build_1hex_number((opcode_pt) num,
+ build_1hex_number((opcode_pt) (num / 256), where));
+}
+
+/* format 2 byte number as decimal with given width (pad with leading '0's) */
+/* return ptr to end */
+
+PUBLIC char *build_number(num, width, where)
+unsigned num;
+unsigned width;
+register char *where;
+{
+ static unsigned powers_of_10[] = {1, 10, 100, 1000, 10000,};
+ unsigned char digit;
+ unsigned char power;
+ register unsigned power_of_10;
+
+ power = 5; /* actually 1 more than power */
+ do
+ {
+ for (digit = '0', power_of_10 = (powers_of_10 - 1)[power];
+ num >= power_of_10; num -= power_of_10)
+ ++digit;
+ if (power <= width)
+ *where++ = digit;
+ }
+ while (--power != 0);
+ return where;
+}
+
+/* record number and position of error (or error buffer overflow) */
+
+PUBLIC void error(errnum)
+error_pt errnum;
+{
+ register struct error_s *errptr;
+ register struct error_s *errptrlow;
+ unsigned char position;
+
+ if ((unsigned) errnum < MINWARN || warn.current)
+ {
+ if (errcount >= MAXERR)
+ erroverflow = TRUE;
+ else
+ {
+ position = symname - linebuf;
+ for (errptr = errbuf + errcount;
+ errptr > errbuf && errptr->position > position;
+ errptr = errptrlow)
+ {
+ errptrlow = errptr - 1;
+ errptr->errnum = errptrlow->errnum;
+ errptr->position = errptrlow->position;
+ }
+ errptr->errnum = errnum;
+ errptr->position = position;
+ ++errcount;
+ if ((unsigned)errnum >= MINWARN)
+ ++totwarn;
+ else
+ ++toterr;
+ }
+ }
+}
+
+/* list 1 line to list file if any errors or flags permit */
+/* list line to console as well if any errors and list file is not console */
+
+PUBLIC void listline()
+{
+ if (!listpre)
+ {
+ if (errcount || list.current && (!macflag || mcount != 0) ||
+ macflag && maclist.current)
+ list1(lstfil);
+ if (errcount)
+ {
+ if (lstfil != STDOUT)
+ list1(STDOUT);
+ errcount = 0;
+ erroverflow = FALSE;
+ }
+ }
+}
+
+/* list 1 line unconditionally */
+
+PRIVATE void list1(fd)
+fd_t fd;
+{
+ innum = fd;
+ listcode();
+ write(innum, linebuf, (unsigned) (lineptr - linebuf));
+ writenl();
+ if (errcount != 0)
+ listerrors();
+ listpre = TRUE;
+}
+
+/* list object code for 1 line */
+
+PRIVATE void listcode()
+{
+ unsigned char count;
+ struct code_listing_s *listptr;
+ unsigned numlength;
+ char *numptr;
+
+ listptr = (struct code_listing_s *) heapptr;
+ memset((char *) listptr, ' ', sizeof *listptr);
+ listptr->nullterm = 0;
+ if (macflag)
+ {
+ listptr->linum_or_macro.macro.mark[0] = '+';
+ listptr->linum_or_macro.macro.level[0] = maclevel + ('a' - 1);
+ }
+ else
+ {
+ numlength = LINUM_LEN;
+ numptr = listptr->linum_or_macro.linum;
+ if (infiln != infil0)
+ {
+ *numptr++ = infiln - infil0 + ('a' - 1);
+ numlength = LINUM_LEN - 1;
+ }
+ build_number(linum, numlength, numptr);
+ }
+ if ((count = mcount) != 0 || popflags & POPLC)
+ build_2hex_number((u16_T) lc, listptr->lc);
+ if (popflags & POPLO)
+ {
+#if SIZEOF_OFFSET_T > 2
+ if (popflags & POPLONG)
+ build_2hex_number((u16_T) (lastexp.offset / (offset_t) 0x10000L),
+ listptr->displ4);
+#endif
+ if (popflags & POPHI)
+ build_2hex_number((u16_T) lastexp.offset, listptr->displ2);
+ else
+ build_1hex_number((opcode_pt) /* XXX */(u16_T) lastexp.offset, listptr->displ1);
+ if (lastexp.data & RELBIT)
+ listptr->reldispl[0] = '>';
+ }
+ else if (count != 0)
+ {
+#ifdef I80386
+ if (aprefix != 0)
+ {
+ --count;
+ build_1hex_number(aprefix, listptr->aprefix);
+ }
+ if (oprefix != 0)
+ {
+ --count;
+ build_1hex_number(oprefix, listptr->oprefix);
+ }
+ if (sprefix != 0)
+ {
+ --count;
+ build_1hex_number(sprefix, listptr->sprefix);
+ }
+#endif
+ if (page != 0)
+ {
+ build_1hex_number(page, listptr->page);
+ --count;
+ }
+ build_1hex_number(opcode, listptr->opcode);
+ --count;
+ if (postb != 0)
+ {
+ --count;
+ build_1hex_number(postb,
+#ifdef MC6809
+ count == 0 ? listptr->displ1 :
+#endif
+ listptr->postb);
+ }
+#ifdef I80386
+ if (sib != NO_SIB)
+ {
+ --count;
+ build_1hex_number(sib, listptr->sib);
+ }
+#endif
+ if (count > 0)
+ {
+ build_1hex_number((opcode_pt) lastexp.offset, listptr->displ1);
+ if (lastexp.data & RELBIT)
+ listptr->reldispl[0] = '>';
+ }
+ if (count > 1)
+ build_1hex_number((opcode_pt) (lastexp.offset >> 0x8),
+ listptr->displ2);
+#if SIZEOF_OFFSET_T > 2
+ if (count > 2)
+ {
+ build_1hex_number((opcode_pt) (lastexp.offset >> 0x10),
+ listptr->displ3);
+ build_1hex_number((opcode_pt) (lastexp.offset >> 0x18),
+ listptr->displ4);
+ }
+#endif
+#ifdef I80386
+ if (immcount > 0)
+ {
+ build_1hex_number((opcode_pt) immadr.offset, listptr->imm1);
+ if (immadr.data & RELBIT)
+ listptr->relimm[0] = '>';
+ }
+ if (immcount > 1)
+ build_1hex_number((opcode_pt) (immadr.offset >> 0x8),
+ listptr->imm2);
+ if (immcount > 2)
+ {
+ build_1hex_number((opcode_pt) (immadr.offset >> 0x10),
+ listptr->imm3);
+ build_1hex_number((opcode_pt) (immadr.offset >> 0x18),
+ listptr->imm4);
+ }
+#endif
+ }
+ writes((char *) listptr);
+}
+
+/* list errors, assuming some */
+
+PRIVATE void listerrors()
+{
+ unsigned char column;
+ unsigned char errcol; /* column # in error line */
+ unsigned char errcolw; /* working column in error line */
+ char *errmsg;
+ struct error_s *errptr;
+ char *linep;
+ unsigned char remaining;
+
+ paderrorline(CODE_LIST_LENGTH - LINUM_LEN);
+ remaining = errcount;
+ column = 0; /* column to match with error column */
+ errcolw = errcol = CODE_LIST_LENGTH; /* working & col number on err line */
+ errptr = errbuf;
+ linep = linebuf;
+ do
+ {
+ while (column < errptr->position)
+ {
+ ++column;
+ if (*linep++ == '\t') /* next tab (standard tabs only) */
+ errcolw = (errcolw + 8) & 0xf8;
+ else
+ ++errcolw;
+ while (errcolw > errcol)
+ {
+ writec(' ');
+ ++errcol;
+ }
+ }
+ if (errcolw < errcol) /* position under error on new line */
+ {
+ writenl();
+ paderrorline((unsigned) errcolw - LINUM_LEN);
+ }
+ writec('^');
+ writes(errmsg = build_error_message(errptr->errnum, heapptr));
+ errcol += strlen(errmsg);
+ ++errptr;
+ }
+ while (--remaining != 0);
+ writenl();
+ if (erroverflow)
+ {
+ paderrorline(CODE_LIST_LENGTH - LINUM_LEN);
+ writesn(build_error_message(FURTHER, heapptr));
+ }
+}
+
+/* pad out error line to begin under 1st char of source listing */
+
+PRIVATE void paderrorline(nspaces)
+unsigned nspaces;
+{
+ int nstars = LINUM_LEN;
+
+ while (nstars-- != 0)
+ writec('*'); /* stars under line number */
+ while (nspaces-- != 0)
+ writec(' '); /* spaces out to error position */
+}
+
+/* write 1 character */
+
+PUBLIC void writec(ch)
+char ch;
+{
+ write(innum, &ch, 1);
+}
+
+/* write newline */
+
+PUBLIC void writenl()
+{
+ writes(SOS_EOLSTR);
+}
+
+/* write 1 offset_t, order to suit target */
+
+PUBLIC void writeoff(offset)
+offset_t offset;
+{
+ char buf[sizeof offset];
+
+#if SIZEOF_OFFSET_T > 2
+ u4c4(buf, offset);
+#else
+ u2c2(buf, offset);
+#endif
+ write(innum, buf, sizeof buf);
+}
+
+/* write string */
+
+PUBLIC void writes(s)
+char *s;
+{
+ write(innum, s, strlen(s));
+}
+
+/* write string followed by newline */
+
+PUBLIC void writesn(s)
+char *s;
+{
+ writes(s);
+ writenl();
+}
+
+/* write 1 word, order to suit target */
+
+PUBLIC void writew(word)
+unsigned word;
+{
+ char buf[2];
+
+ u2c2(buf, (u16_T) word);
+ write(innum, buf, sizeof buf);
+}
diff --git a/as/genobj.c b/as/genobj.c
new file mode 100644
index 0000000..80b03ce
--- /dev/null
+++ b/as/genobj.c
@@ -0,0 +1,682 @@
+/* genobj.c - object code generation routines for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "file.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+char *strcpy P((char *s1, const char *s2));
+char *strrchr P((const char *s, int c));
+unsigned strlen P((const char *s));
+#else
+#undef NULL
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#undef NULL
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#define OBJBUFSIZE 512 /* size of object code output buffer */
+#define isge2byteoffset(offset) ((offset) >= 0x100)
+#define isge4byteoffset(offset) ((offset) >= 0x10000L)
+
+PRIVATE char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */
+PRIVATE char *absbuf; /* start */
+PRIVATE char *absbufend; /* last location + 1 */
+PRIVATE char *absbufptr; /* current location */
+PRIVATE struct sym_s **arrext; /* array of external symbol ptrs */
+PRIVATE char hid_objbuf[OBJBUFSIZE]; /* object code buffer */
+PRIVATE unsigned numext; /* number of external symbols */
+PRIVATE char *objbuf; /* start */
+PRIVATE char *objbufend; /* last location + 1 */
+PRIVATE char *objbufptr; /* current location */
+PRIVATE unsigned char relsize; /* current relocation size, 0 init */
+ /* local to genobjadr, but here */
+ /* because of static re-init bug */
+PRIVATE offset_t rmbcount; /* accumulator for repeated RMB's */
+
+FORWARD void flushabs P((void));
+FORWARD void flushrmb P((void));
+FORWARD void genobjadr P((struct address_s *adrptr, int size));
+FORWARD void putobj1 P((opcode_pt ch));
+FORWARD void putobj4 P((u32_T offset));
+FORWARD void putobjoffset P((offset_t offset, count_t size));
+FORWARD void putobjword P((unsigned word));
+FORWARD void writeobj P((char *buf, unsigned count));
+
+/* accumulate RMB requests into 1 (so + and - requests cancel) */
+
+PUBLIC void accumulate_rmb(offset)
+offset_t offset;
+{
+ if (objectc)
+ {
+ flushabs();
+ rmbcount += offset;
+ }
+}
+
+/* flush absolute object code buffer to object code buffer if necessary */
+
+PRIVATE void flushabs()
+{
+ if (absbufptr > absbuf)
+ {
+ putobj1((absbufptr - absbuf) | OBJ_ABS);
+ {
+ register char *bufptr;
+
+ bufptr = absbuf;
+ do
+ putobj1(*bufptr);
+ while (++bufptr < absbufptr);
+ absbufptr = absbuf;
+ }
+ }
+}
+
+/* flush object code buffer if necessary */
+
+PUBLIC void flushobj()
+{
+ int ntowrite;
+
+ if ((ntowrite = objbufptr - objbuf) > 0)
+ {
+ if (write(objfil, objbuf, (unsigned) ntowrite) != ntowrite)
+ {
+ error(OBJOUT);
+ listline();
+ finishup();
+ }
+ objbufptr = objbuf;
+ }
+}
+
+/* flush RMB count if necessary */
+
+PRIVATE void flushrmb()
+{
+ count_t size;
+
+ if (rmbcount != 0)
+ {
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(rmbcount))
+ {
+ putobj1(OBJ_SKIP_4);
+ size = 4;
+ }
+ else
+#endif
+ if (isge2byteoffset(rmbcount))
+ {
+ putobj1(OBJ_SKIP_2);
+ size = 2;
+ }
+ else
+ {
+ putobj1(OBJ_SKIP_1);
+ size = 1;
+ }
+ putobjoffset(rmbcount, size);
+ rmbcount = 0;
+ }
+}
+
+/* generate object code for current line */
+
+/*
+ any address parameter is (regrettably) in lastexp
+ any immediate parameter is (corectly) in immadr
+*/
+
+PUBLIC void genobj()
+{
+ struct address_s *adrptr;
+ char *bufptr;
+ unsigned char remaining;
+
+ if (objectc && mcount != 0)
+ {
+ if (popflags)
+ {
+ if (fcflag)
+ {
+ bufptr = databuf.fcbuf;
+ remaining = mcount;
+ do
+ putabs(*bufptr++);
+ while (--remaining != 0);
+ }
+ if (fdflag)
+ {
+ adrptr = databuf.fdbuf;
+ remaining = mcount;
+ do
+ genobjadr(adrptr++, 2);
+ while ((remaining -= 2) != 0);
+ }
+#if SIZEOF_OFFSET_T > 2
+ if (fqflag)
+ {
+ adrptr = databuf.fqbuf;
+ remaining = mcount;
+ do
+ genobjadr(adrptr++, 4);
+ while ((remaining -= 4) != 0);
+ }
+#endif
+ }
+ else
+ {
+ remaining = mcount - 1; /* count opcode immediately */
+#ifdef I80386
+ if (aprefix != 0)
+ {
+ putabs(aprefix);
+ --remaining;
+ }
+ if (oprefix != 0)
+ {
+ putabs(oprefix);
+ --remaining;
+ }
+ if (sprefix != 0)
+ {
+ putabs(sprefix);
+ --remaining;
+ }
+#endif
+ if (page != 0)
+ {
+ putabs(page);
+ --remaining;
+ }
+ putabs(opcode);
+ if (remaining != 0)
+ {
+ if (postb != 0)
+ {
+ putabs(postb);
+ --remaining;
+ }
+#ifdef I80386
+ if (sib != NO_SIB)
+ {
+ putabs(sib);
+ --remaining;
+ }
+#endif
+ if (remaining != 0)
+ genobjadr(&lastexp, remaining);
+ }
+ }
+#ifdef I80386
+ if (immcount != 0)
+ genobjadr(&immadr, immcount);
+#endif
+ }
+}
+
+/* generate object code for current address */
+
+PRIVATE void genobjadr(adrptr, size)
+struct address_s *adrptr;
+smallcount_t size;
+{
+ unsigned char byte;
+ unsigned symnum;
+
+ if (!(adrptr->data & RELBIT))
+ {
+ /* absolute address */
+
+ char buf[sizeof(offset_t)];
+
+#if SIZEOF_OFFSET_T > 2
+ u4cn(buf, adrptr->offset, size);
+#else
+ u2cn(buf, adrptr->offset, size);
+#endif
+ putabs(buf[0]);
+ if (size > 1)
+ putabs(buf[1]);
+ if (size > 2)
+ {
+ putabs(buf[2]);
+ putabs(buf[3]);
+ }
+ }
+ else
+ {
+ /* relocatable address */
+ if (size != relsize)
+ /* set reloc size index |00|0000xx| */
+ putobj((relsize = size) == 4 ? 0x03 : relsize);
+ if (!(adrptr->data & IMPBIT))
+ {
+ /* offset relocation (known offset) */
+ putobj((adrptr->data & SEGM) | OBJ_OFFSET_REL | pcrflag);
+ putobjoffset(adrptr->offset, size);
+ }
+ else
+ {
+ /* symbol relocation (imported symbol + offset) */
+ {
+ register struct sym_s **copyptr;
+
+ for (copyptr = arrext, symnum = 0;
+ symnum < numext && *copyptr++ != adrptr->sym; ++symnum)
+ ;
+ }
+ byte = OBJ_SYMBOL_REL;
+ if (isge2byteoffset(symnum))
+ byte = OBJ_SYMBOL_REL | OBJ_S_MASK;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(adrptr->offset))
+ {
+ byte |= 0x03; /* 4 byte offset */
+ size = 4;
+ }
+ else
+#endif
+ if (isge2byteoffset(adrptr->offset))
+ {
+ byte |= 0x02; /* 2 byte offset */
+ size = 2;
+ }
+ else if (adrptr->offset != 0)
+ {
+ byte |= 0x01; /* 1 byte offset */
+ size = 1;
+ }
+ else
+ size = 0;
+ putobj(byte | pcrflag);
+ if (isge2byteoffset(symnum))
+ putobjword(symnum);
+ else
+ putobj1((opcode_pt) symnum);
+ if (adrptr->offset != 0)
+ putobjoffset(adrptr->offset, size);
+ }
+ }
+}
+
+/* initialise private variables */
+
+PUBLIC void initobj()
+{
+ absbufend = (absbufptr = absbuf = hid_absbuf) + sizeof hid_absbuf;
+ objbufend = (objbufptr = objbuf = hid_objbuf) + sizeof hid_objbuf;
+}
+
+/*
+ write header to object file
+ also build array of imported/exported symbols
+*/
+
+PUBLIC void objheader()
+{
+ static char module_header[] =
+ {
+#ifdef I80386
+ 0xA3, 0x86,
+ 1, 0,
+ (char) (0xA3 + 0x86 + 1 + 0),
+#endif
+#ifdef MC6809
+ 'S', '1', /* 2 byte magic number */
+ 0, 1, /* 2 byte number of modules in file */
+ 'S' + '1' + 0 + 1, /* 1 byte checksum */
+#endif
+ };
+ static char seg_max_sizes[] =
+ {
+ 0x55, /* all segments have maximum size 2^16 */
+ 0x55, /* this is encoded by 0b01 4 times per byte */
+ 0x55, /* other codes are 0b00 = max size 2^8 */
+ 0x55, /* 0b10 = max size 2^24, 0b11 = max 2^32 */
+ };
+ unsigned char byte;
+ register struct sym_s **copyptr;
+ struct sym_s **copytop;
+ struct sym_s **hashptr;
+ struct lc_s *lcp;
+ char module_name[FILNAMLEN + 1];
+ char *nameptr;
+ unsigned offset;
+ unsigned segsizebytes;
+ unsigned size;
+ unsigned char sizebits;
+ unsigned strsiz; /* size of object string table */
+ unsigned symosiz; /* size of object symbol table */
+ register struct sym_s *symptr;
+ u32_T textlength;
+
+ if ((objectc = objectg) == 0)
+ return;
+ writeobj(module_header, sizeof module_header);
+
+ /* calculate number of imported/exported symbols */
+ /* and lengths of symbol and string tables */
+ /* build array of imported/exported symbols */
+
+ symosiz = 0;
+ if (truefilename == NULL)
+ truefilename = filnamptr;
+ nameptr = strrchr(truefilename, DIRCHAR);
+ strcpy(module_name, nameptr != NULL ? nameptr + 1 : truefilename);
+ if ((nameptr = strrchr(module_name, '.')) != NULL)
+ *nameptr = 0;
+ strsiz = strlen(module_name) + 1;
+ align(heapptr);
+ for (hashptr = spt, arrext = copyptr = (struct sym_s **) heapptr;
+ hashptr < spt_top;)
+ if ((symptr = *hashptr++) != NULL)
+ do
+ {
+ if ((symptr->type & EXPBIT || symptr->data & IMPBIT) ||
+ !globals_only_in_obj && symptr->name[0] != '.' &&
+ !(symptr->type & (MNREGBIT | MACBIT | VARBIT)))
+ {
+ if (copyptr >= (struct sym_s **) heapend)
+ {
+ heapptr = (char *) copyptr;
+ fatalerror(OBJSYMOV);
+ }
+ *copyptr++ = symptr;
+ strsiz += symptr->length + 1;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(symptr->value_reg_or_op.value))
+ size = 4 + 4;
+ /* 4 is size of offset into string table and flags */
+ /* 2nd 4 is for 4 byte offset */
+ else
+#endif
+ if (isge2byteoffset(symptr->value_reg_or_op.value))
+ size = 4 + 2;
+ else if (symptr->value_reg_or_op.value != 0)
+ size = 4 + 1;
+ else
+ size = 4;
+ symosiz += size;
+ ++numext;
+ }
+ }
+ while ((symptr = symptr->next) != NULL);
+ heapptr = (char *) (copytop = copyptr);
+
+ /* calculate length of text, and number of seg size bytes in header */
+
+ textlength = segsizebytes = 0;
+ lcp = lctab;
+ do
+ if (lcp->lc != 0)
+ {
+ textlength += lcp->lc; /* assuming text starts at 0 */
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(lcp->lc))
+ segsizebytes += 4;
+ else
+#endif
+ segsizebytes += 2; /* use 2 byte size if possible */
+ }
+ while (++lcp < lctabtop);
+
+/*
+ offset to text = length of header since only 1 module
+ header consists of:
+ module header sizeof module_header
+ offset to start of text 4
+ length of text 4
+ length of string area 2
+ class 1
+ revision 1
+ seg max sizes sizeof seg_max_sizes
+ seg size descriptors 4
+ seg sizes segsizebytes
+ symbol count 2
+ symbol offsets and types symosiz
+ strings strsiz
+*/
+
+ /* offset to start of text */
+
+ putobj4((u32_T) (sizeof module_header + 4 + 4 + 2 + 1 + 1 +
+ sizeof seg_max_sizes + 4 + segsizebytes + 2 +
+ symosiz) + strsiz);
+
+ /* length of text */
+
+ putobj4((u32_T) textlength);
+
+ /* length of string area */
+
+ putobjword(strsiz);
+
+ /* class and revision */
+
+ putobj1(0);
+ putobj1(0);
+
+ /* segment max sizes (constant) */
+
+ writeobj(seg_max_sizes, sizeof seg_max_sizes);
+
+ /* segment size descriptors */
+ /* produce only 0 and 2 byte sizes */
+
+ lcp = lctabtop;
+ byte = 0;
+ sizebits = OBJ_SEGSZ_TWO << 6;
+ do
+ {
+ --lcp;
+ if (lcp->lc != 0)
+ {
+ byte |= sizebits;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(lcp->lc))
+ byte |= sizebits >> 1; /* XXX - convert size 2 to size 4 */
+#endif
+ }
+ if ((sizebits >>= 2) == 0)
+ {
+ putobj1(byte);
+ byte = 0;
+ sizebits = OBJ_SEGSZ_TWO << 6;
+ }
+ }
+ while (lcp > lctab);
+
+ /* segment sizes */
+
+ do /* lcp starts at lctab */
+ if (lcp->lc != 0)
+ {
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(lcp->lc))
+ putobj4(lcp->lc);
+ else
+#endif
+ putobjword((unsigned) lcp->lc);
+ }
+ while (++lcp < lctabtop);
+
+ /* symbol count */
+
+ putobjword(numext);
+
+ /* symbol offsets and types */
+
+ offset = strlen(module_name) + 1; /* 1st symbol begins after name */
+ for (copyptr = arrext; copyptr < copytop;)
+ {
+ putobjword(offset);
+ symptr = *copyptr++;
+ byte = symptr->type & OBJ_N_MASK;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(symptr->value_reg_or_op.value))
+ {
+ byte |= OBJ_SZ_FOUR;
+ size = 4;
+ }
+ else
+#endif
+ if (isge2byteoffset(symptr->value_reg_or_op.value))
+ {
+ byte |= OBJ_SZ_TWO;
+ size = 2;
+ }
+ else if (symptr->value_reg_or_op.value != 0)
+ {
+ byte |= OBJ_SZ_ONE;
+ size = 1;
+ }
+ else
+ size = 0;
+ if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
+ {
+ byte |= OBJ_SA_MASK;
+ symptr->data &= ~OBJ_I_MASK;
+ }
+ putobjword((unsigned)
+ (byte << 0x8) |
+ (symptr->type & OBJ_E_MASK) | /* |E|0000000| */
+ ((symptr->data & (OBJ_I_MASK | OBJ_A_MASK | OBJ_SEGM_MASK)) ^
+ /* |0|I|0|A|SEGM| */
+ RELBIT)); /* RELBIT by negative logic */
+ if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
+ symptr->data |= OBJ_I_MASK;
+ if (size != 0)
+ putobjoffset(symptr->value_reg_or_op.value, size);
+ offset += symptr->length + 1;
+ }
+
+ /* strings */
+
+ writeobj(module_name, strlen(module_name));
+ putobj1(0);
+ for (copyptr = arrext; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writeobj(symptr->name, symptr->length);
+ putobj1(0);
+ }
+ putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */
+}
+
+/* write trailer to object file */
+
+PUBLIC void objtrailer()
+{
+ if (objectc)
+ {
+ putobj(0); /* end of object file */
+ flushobj();
+ }
+}
+
+/* write char to absolute object code buffer, flush if necessary */
+
+PUBLIC void putabs(ch)
+opcode_pt ch;
+{
+ if (objectc)
+ {
+ if (rmbcount != 0)
+ flushrmb();
+ if (absbufptr >= absbufend)
+ flushabs();
+ *absbufptr++ = ch;
+ }
+}
+
+/* write char to object code buffer, flush if necessary */
+
+PUBLIC void putobj(ch)
+opcode_pt ch;
+{
+ if (objectc)
+ {
+ flushabs();
+ flushrmb();
+ putobj1(ch);
+ }
+}
+
+/* write char to object code buffer assuming nothing in absolute & rmb bufs */
+
+PRIVATE void putobj1(ch)
+opcode_pt ch;
+{
+ if (objbufptr >= objbufend)
+ flushobj();
+ *objbufptr++ = ch;
+}
+
+/* write 32 bit offset to object code buffer assuming ... */
+
+PRIVATE void putobj4(offset)
+u32_T offset;
+{
+ char buf[sizeof offset];
+
+ u4c4(buf, offset);
+ writeobj(buf, sizeof buf);
+}
+
+/* write sized offset to object code buffer assuming ... */
+
+PRIVATE void putobjoffset(offset, size)
+offset_t offset;
+count_t size;
+{
+ char buf[sizeof offset];
+
+#if SIZEOF_OFFSET_T > 2
+ u4cn(buf, offset, size);
+#else
+ u2cn(buf, offset, size);
+#endif
+ putobj1(buf[0]);
+ if (size > 1)
+ putobj1(buf[1]);
+ if (size > 2)
+ {
+ putobj1(buf[2]);
+ putobj1(buf[3]);
+ }
+}
+
+/* write word to object code buffer assuming ... */
+
+PRIVATE void putobjword(word)
+unsigned word;
+{
+ char buf[sizeof word];
+
+ u2c2(buf, word);
+ putobj1(buf[0]);
+ putobj1(buf[1]);
+}
+
+/* write several bytes to object code buffer assuming ... */
+
+PRIVATE void writeobj(buf, count)
+char *buf;
+unsigned count;
+{
+ do
+ putobj1(*buf++);
+ while (--count);
+}
diff --git a/as/gensym.c b/as/gensym.c
new file mode 100644
index 0000000..bc773db
--- /dev/null
+++ b/as/gensym.c
@@ -0,0 +1,212 @@
+/* gensym.c - generate symbol table for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void *memset P((void *s, int c, unsigned n));
+int strcmp P((const char *s1, const char *s2));
+#else
+#undef NULL
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#undef NULL
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+FORWARD int printsym P((register struct sym_s *symptr, unsigned column));
+FORWARD void sort P((struct sym_s **array, struct sym_s **top,
+ bool_pt nameflag));
+
+/* sort labels in symbol table on name and value */
+/* if listing, write human-readable table to list file */
+/* if symbol file, write machine-readable tables to it */
+/* pointers become relative to start of file */
+
+PUBLIC void gensym()
+{
+ unsigned column;
+ struct sym_s **copyptr;
+ struct sym_s **copytop;
+ register struct sym_s **hashptr;
+ unsigned label_count; /* number of labels */
+ unsigned labels_length; /* length of all label strings */
+ unsigned label_stringptr; /* offset of label str from start of file */
+ register struct sym_s *symptr;
+ struct sym_s **symlptr; /* start of symbol output list */
+
+ labels_length = label_count = 0;
+
+ /* make copy of all relavant symbol ptrs on heap */
+ /* original ptrs can now be modified, but need to be an array for sort */
+
+ align(heapptr);
+ for (hashptr = spt, symlptr = copyptr = (struct sym_s **) heapptr;
+ hashptr < spt_top;)
+ if ((symptr = *hashptr++) != NULL)
+ do
+ if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT)))
+ {
+ if (copyptr >= (struct sym_s **) heapend)
+ {
+ heapptr = (char *) copyptr;
+ error(SYMOUTOV); /* avoid recursive fatalerror */
+ listline(); /* the main job is OK if here */
+ goto sort_symbols;
+ }
+ *copyptr++ = symptr;
+ ++label_count;
+ labels_length += symptr->length + 3; /* 3 for type, value */
+ }
+ while ((symptr = symptr->next) != NULL);
+
+sort_symbols:
+ sort(symlptr, copyptr, TRUE); /* sort on name */
+ heapptr = (char *) (copytop = copyptr);
+ if (list.global)
+ {
+ innum = lstfil;
+ writenl();
+ writesn("Symbols:");
+ for (copyptr = symlptr, column = 0; copyptr < copytop;)
+ column = printsym(*copyptr++, column);
+ if (column != 0)
+ writenl();
+ }
+ if ((innum = symfil) != 0)
+ {
+ writew(mapnum);
+ label_count *= 2; /* now length of ptr table (2 bytes per ptr) */
+ label_stringptr = label_count + 6;
+ /* offset to current string in symbol file */
+ /* 6 is length of header */
+ labels_length += label_stringptr;
+ /* offset to ptr table sorted on value */
+ writew(labels_length + label_count);
+ /* total length of symbol file */
+ writew(label_count);
+ for (copyptr = symlptr; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writew((unsigned)
+ (symptr->next = (struct sym_s *) label_stringptr));
+ /* reuse "next" to record string position */
+ label_stringptr += symptr->length + 3;
+ }
+ for (copyptr = symlptr; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writew((unsigned) symptr->value_reg_or_op.value);
+ writec(symptr->type);
+ write(innum, symptr->name, (unsigned) (symptr->length - 1));
+ writec(symptr->name[symptr->length - 1] | 0x80);
+ }
+ sort(symlptr, copyptr, FALSE);
+ /* sort on value */
+ for (copyptr = symlptr; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writew((unsigned) symptr->next); /* now has string position */
+ }
+ }
+}
+
+/* print symbol nicely formatted for given column */
+
+PRIVATE int printsym(symptr, column)
+register struct sym_s *symptr;
+unsigned column;
+{
+ unsigned char length;
+ register struct sym_listing_s *listptr;
+ char *outname;
+ char *symname;
+
+ listptr = (struct sym_listing_s *) heapptr;
+ memset((char *) listptr, ' ', SYMLIS_LEN);
+ listptr->nullterm = 0;
+ if ((length = symptr->length) > SYMLIS_NAMELEN)
+ {
+ outname = listptr->name;
+ outname[length = SYMLIS_NAMELEN] = '+';
+ }
+ else
+ outname = (listptr->name + SYMLIS_NAMELEN) - length;
+ symname = symptr->name;
+ do
+ *outname++ = *symname++;
+ while (--length != 0);
+ listptr->ar[0] = symptr->data & RELBIT ? 'R' : 'A';
+ listptr->segm[0] = hexdigit[symptr->data & SEGM];
+ if (symptr->type & COMMBIT)
+ listptr->cein[0] = 'C';
+ else if (symptr->type & ENTBIT)
+ listptr->cein[0] = 'N';
+ else if (symptr->type & EXPBIT)
+ listptr->cein[0] = 'E';
+ else if (symptr->data & IMPBIT)
+ listptr->cein[0] = 'I';
+#if SIZEOF_OFFSET_T > 2
+ build_2hex_number((unsigned) (symptr->value_reg_or_op.value >> 16),
+ listptr->value);
+#endif
+ build_2hex_number((unsigned) symptr->value_reg_or_op.value,
+ listptr->value);
+ writes((char *) listptr);
+ if ((column += SYMLIS_LEN) > (80 - SYMLIS_LEN))
+ {
+ writenl();
+ column = 0;
+ }
+ return column;
+}
+
+/* shell sort symbols */
+
+PRIVATE void sort(array, top, nameflag)
+struct sym_s **array;
+struct sym_s **top;
+bool_pt nameflag;
+{
+ int gap;
+ int i;
+ int j;
+ register struct sym_s **left;
+ register struct sym_s **right;
+ int size;
+ struct sym_s *swap;
+
+ size = top - array;
+ /* choose gaps according to Knuth V3 p95 */
+ for (gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j)
+ ;
+ do
+ {
+ for (j = gap; j < size; ++j)
+ for (i = j - gap; i >= 0; i -= gap)
+ {
+ left = &array[i];
+ right = &array[i + gap];
+ if ((bool_t) nameflag)
+ {
+ if (strcmp((*left)->name, (*right)->name) <= 0)
+ break;
+ }
+ else if ((unsigned) (*left)->value_reg_or_op.value <=
+ (*right)->value_reg_or_op.value)
+ break;
+ swap = *left;
+ *left = *right;
+ *right = swap;
+ }
+ }
+ while ((gap /= 3) != 0);
+}
diff --git a/as/globvar.h b/as/globvar.h
new file mode 100644
index 0000000..f2896fb
--- /dev/null
+++ b/as/globvar.h
@@ -0,0 +1,93 @@
+/* globvar.h - global variables for assembler */
+
+/* global control and bookkeeping */
+
+EXTERN bool_t binaryc; /* current binary code flag */
+EXTERN bool_t binaryg; /* global binary code flag */
+EXTERN offset_t binmbuf; /* offset in binary code buffer for memory */
+
+EXTERN unsigned char dirpag; /* direct page */
+
+EXTERN bool_t globals_only_in_obj; /* global symbols only in object file */
+
+EXTERN bool_t jumps_long; /* make all jumps long */
+
+EXTERN unsigned char mapnum; /* global map number */
+
+EXTERN bool_t objectc; /* current object code flag */
+EXTERN bool_t objectg; /* global object code flag */
+
+EXTERN bool_t pass; /* pass, FALSE means 0, TRUE means 1 */
+
+EXTERN offset_t progent; /* program entry point */
+
+EXTERN bool_t symgen; /* generate symbol table flag */
+
+EXTERN unsigned toterr; /* total errors */
+EXTERN unsigned totwarn; /* total warnings */
+
+/* bookeeping for current line */
+
+EXTERN char *linebuf; /* buffer */
+
+/* for symbol table routines */
+
+EXTERN char *heapend; /* end of free space for symbol list */
+EXTERN char *heapptr; /* next free space in symbol list */
+EXTERN unsigned char inidata; /* init sym entry data governed by "u" flag */
+EXTERN struct sym_s **spt; /* symbol pointer table */
+EXTERN struct sym_s **spt_top; /* top of symbol ptr table */
+
+/* for translator */
+
+EXTERN struct sym_s *label; /* non-null if valid label starts line */
+EXTERN unsigned char pedata; /* shows how PROGENT bound, flags like LCDATA*/
+EXTERN unsigned char popflags; /* pseudo-op flags */
+
+/* for BLOCK stack */
+
+EXTERN struct block_s *blockstak; /* stack ptr */
+EXTERN unsigned char blocklevel; /* nesting level */
+
+/* for IF stack */
+
+EXTERN struct if_s *ifstak; /* stack ptr */
+EXTERN unsigned char iflevel; /* nesting level */
+EXTERN bool_t ifflag; /* set if assembling */
+
+/* location counters for various segments */
+
+EXTERN offset_t lc; /* location counter */
+EXTERN unsigned char lcdata; /* shows how lc is bound */
+ /* FORBIT is set if lc is forward referenced */
+ /* RELBIT is is if lc is relocat. (not ASEG) */
+EXTERN offset_t lcjump; /* lc jump between lines */
+#define mcount (((unsigned char *) &lcjump)[LOW_BYTE])
+ /* low byte of lcjump */
+EXTERN struct lc_s *lcptr; /* top of current spot in lctab */
+EXTERN struct lc_s *lctab; /* start of lctab */
+EXTERN struct lc_s *lctabtop; /* top of lctab */
+
+/* for code generator */
+
+EXTERN opsize_t mnsize; /* 1 if forced byte operand size, else 0 */
+EXTERN opcode_t page;
+EXTERN opcode_t opcode;
+EXTERN opcode_t postb; /* postbyte, 0 if none */
+EXTERN unsigned char pcrflag; /* OBJ_RMASK set if addressing is PC-relative */
+
+#ifdef I80386
+
+EXTERN opcode_t aprefix; /* address size prefix or 0 */
+EXTERN bool_t asld_compatible; /* asld compatibility flag */
+EXTERN opsize_t defsize; /* current default size */
+EXTERN opsize_t idefsize; /* initial default size */
+EXTERN opcode_t oprefix; /* operand size prefix or 0 */
+EXTERN opcode_t sprefix; /* segment prefix or 0 */
+EXTERN opcode_t sib; /* scale-index-base byte */
+
+#endif
+
+/* miscellaneous */
+
+extern char hexdigit[];
diff --git a/as/macro.c b/as/macro.c
new file mode 100644
index 0000000..9363947
--- /dev/null
+++ b/as/macro.c
@@ -0,0 +1,175 @@
+/* macro.c - expand macros for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "macro.h"
+
+#ifdef STDC_HEADERS_MISSING
+int strncmp P((const char *s1, const char *s2, unsigned n));
+#else
+#undef NULL
+#include <string.h>
+#endif
+
+/*
+ Enter macro: stack macro and get its parameters.
+ Parameters form a linked list of null-terminated strings of form
+ next:string. The first string is the macro number in 4 bytes.
+*/
+
+PUBLIC void entermac(symptr)
+struct sym_s *symptr;
+{
+ if (maclevel >= MAXMAC)
+ error(MACOV);
+ else if (macpar + 2 > macptop)
+ error(PAROV); /* no room for 0th param */
+ /* (2 structs to fit it!) */
+ else
+ {
+ char ch;
+ struct schain_s *param1;
+ register char *reglineptr;
+ register char *stringptr;
+
+ ++maclevel;
+ (--macstak)->text = (char *) symptr->value_reg_or_op.value;
+ macstak->parameters = param1 = macpar;
+ param1->next = NULL;
+ *(stringptr = build_number(++macnum, 3, param1->string)) = 0;
+ macpar = (struct schain_s *) (stringptr + 1);
+ /* TODO: alignment */
+ getsym();
+ if (sym != LPAREN)
+ return; /* no other params */
+ reglineptr = lineptr;
+ stringptr = macpar->string;
+ while (TRUE)
+ {
+ if (stringptr >= (char *) macptop)
+ {
+ symname = reglineptr;
+ error(PAROV);
+ return;
+ }
+ ch = *reglineptr++;
+ if (ch == '/')
+ /* escaped means no special meaning for slash, comma, paren */
+ ch = *reglineptr++;
+ else if (ch == ',' || ch == ')')
+ {
+ if (stringptr >= (char *) macptop)
+ {
+ symname = reglineptr;
+ error(PAROV); /* no room for null */
+ return;
+ }
+ *stringptr = 0;
+ param1->next = macpar; /* ptr from previous */
+ (param1 = macpar)->next = NULL;
+ /* this goes nowhere */
+ macpar = (struct schain_s *) (stringptr + 1);
+ /* but is finished OK - TODO align */
+ stringptr = macpar->string;
+ if (ch == ')')
+ return;
+ continue;
+ }
+ if ((*stringptr++ = ch) == 0)
+ {
+ symname = reglineptr;
+ error(RPEXP);
+ return;
+ }
+ }
+ }
+}
+
+/* MACRO pseudo-op */
+
+PUBLIC void pmacro()
+{
+ bool_t saving;
+ bool_t savingc;
+ struct sym_s *symptr;
+
+ saving = /* prepare for bad macro */
+ savingc = FALSE; /* normally don't save comments */
+ macload = TRUE; /* show loading */
+ if (label != NULL)
+ error(ILLAB);
+ else if (sym != IDENT)
+ error(LABEXP);
+ else
+ {
+ symptr = gsymptr;
+ if (symptr->type & MNREGBIT)
+ error(LABEXP);
+ else if (symptr->type & LABIT || symptr->data & FORBIT)
+ error(RELAB);
+ else if (pass == 0 || symptr->type & REDBIT)
+ /* copy on pass 0, also pass 1 if redefined */
+ {
+ saving = TRUE;
+ if (symptr->type & MACBIT)
+ symptr->type |= REDBIT;
+ else
+ symptr->type |= MACBIT;
+ symptr->data = UNDBIT; /* undefined till end */
+ symptr->value_reg_or_op.value = (unsigned) heapptr;
+ /* beginning of store for macro */
+ /* value s.b. (char *) */
+ getsym_nolookup(); /* test for "C" */
+ if (sym == IDENT && lineptr == symname + 1 && *symname == 'C')
+ savingc = TRUE;
+ }
+ }
+ while (TRUE)
+ {
+ skipline();
+ listline();
+ readline();
+ if (!macload)
+ break; /* macload cleared to show eof */
+ getsym_nolookup();
+ if (sym == IDENT)
+ {
+ if (lineptr == symname + 4 && strncmp(symname, "MEND", 4) == 0)
+ break;
+ }
+ else if (sym != MACROARG)
+ {
+ if (!savingc)
+ continue; /* don't save comment */
+ }
+ if (!saving)
+ continue;
+ {
+ register char *reglineptr;
+ register char *regheapptr;
+
+ reglineptr = linebuf;
+ regheapptr = heapptr;
+ do
+ {
+ if (regheapptr >= heapend)
+ {
+ heapptr = regheapptr;
+ fatalerror(SYMOV); /* won't fit */
+ }
+ }
+ while ((*regheapptr++ = *reglineptr++) != EOLCHAR);
+ heapptr = regheapptr;
+ }
+ }
+ macload = FALSE;
+ if (saving)
+ {
+ *heapptr++ = ETB;
+ symptr->data = 0;
+ }
+}
diff --git a/as/macro.h b/as/macro.h
new file mode 100644
index 0000000..c37bd00
--- /dev/null
+++ b/as/macro.h
@@ -0,0 +1,10 @@
+/* macro.h - global variables for macro expansion for assembler */
+
+EXTERN bool_t macflag; /* inside macro flag */
+EXTERN bool_t macload; /* loading macro flag */
+EXTERN unsigned macnum; /* macro call counter */
+
+EXTERN unsigned char maclevel; /* nesting level */
+EXTERN struct schain_s *macpar; /* parameter save buffer */
+EXTERN struct schain_s *macptop; /* top of param buffer (+1) */
+EXTERN struct macro_s *macstak; /* stack ptr */
diff --git a/as/mops.c b/as/mops.c
new file mode 100644
index 0000000..209f0c8
--- /dev/null
+++ b/as/mops.c
@@ -0,0 +1,2835 @@
+/* mops.c - handle pseudo-ops */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "address.h"
+
+#define is8bitadr(offset) ((offset_t) offset < 0x100)
+#define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100)
+#define pass2 pass
+
+FORWARD void mshort2 P((void));
+FORWARD reg_pt regchk P((void));
+FORWARD void reldata P((void));
+
+#ifdef I80386
+
+#define iswordadr(offset) ((offset_t) (offset) < 0x10000L)
+#define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L)
+#define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL)
+
+#define BYTE_SEGWORD 0x00
+#define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG)
+
+#define BASE_MASK 0x07
+#define BASE_SHIFT 0
+#define INDEX_MASK 0x38
+#define INDEX_SHIFT 3
+#define MOD_MASK 0xC0
+# define REG_MOD 0xC0
+# define MEM0_MOD 0x00
+# define MEM1_MOD 0x40
+# define MEM2_MOD 0x80
+#define REG_MASK 0x38
+#define REG_SHIFT 3
+#define RM_MASK 0x07
+#define RM_SHIFT 0
+# define D16_RM 0x06
+# define D32_RM 0x05
+# define SIB_NOBASE 0x05
+# define SIB_RM 0x04
+#define SREG_MASK 0x38
+#define SREG_SHIFT 3
+#define SS_MASK 0xC0
+#define SS_SHIFT 6
+
+#define SEGMOV 0x04
+#define SIGNBIT 0x02
+#define TOREGBIT 0x02
+#define WORDBIT 0x01
+
+PRIVATE opcode_t baseind16[] =
+{
+ 0x00, /* BP + BP, illegal */
+ 0x00, /* BX + BP, illegal */
+ 0x03, /* DI + BP */
+ 0x02, /* SI + BP */
+ 0x00, /* BP + BX, illegal */
+ 0x00, /* BX + BX, illegal */
+ 0x01, /* DI + BX */
+ 0x00, /* SI + BX */
+ 0x03, /* BP + DI */
+ 0x01, /* BX + DI */
+ 0x00, /* DI + DI, illegal */
+ 0x00, /* SI + DI, illegal */
+ 0x02, /* BP + SI */
+ 0x00, /* BX + SI */
+ 0x00, /* DI + SI, illegal */
+ 0x00, /* SI + SI, illegal */
+};
+
+PRIVATE opcode_t regbits[] =
+{
+ 0x05 << REG_SHIFT, /* BP */
+ 0x03 << REG_SHIFT, /* BX */
+ 0x07 << REG_SHIFT, /* DI */
+ 0x06 << REG_SHIFT, /* SI */
+
+ 0x00 << REG_SHIFT, /* EAX */
+ 0x05 << REG_SHIFT, /* EBP */
+ 0x03 << REG_SHIFT, /* EBX */
+ 0x01 << REG_SHIFT, /* ECX */
+ 0x07 << REG_SHIFT, /* EDI */
+ 0x02 << REG_SHIFT, /* EDX */
+ 0x06 << REG_SHIFT, /* ESI */
+ 0x04 << REG_SHIFT, /* ESP */
+
+ 0x00 << REG_SHIFT, /* AX */
+ 0x01 << REG_SHIFT, /* CX */
+ 0x02 << REG_SHIFT, /* DX */
+ 0x04 << REG_SHIFT, /* SP */
+
+ 0x04 << REG_SHIFT, /* AH */
+ 0x00 << REG_SHIFT, /* AL */
+ 0x07 << REG_SHIFT, /* BH */
+ 0x03 << REG_SHIFT, /* BL */
+ 0x05 << REG_SHIFT, /* CH */
+ 0x01 << REG_SHIFT, /* CL */
+ 0x06 << REG_SHIFT, /* DH */
+ 0x02 << REG_SHIFT, /* DL */
+
+ 0x01 << REG_SHIFT, /* CS */
+ 0x03 << REG_SHIFT, /* DS */
+ 0x00 << REG_SHIFT, /* ES */
+ 0x04 << REG_SHIFT, /* FS */
+ 0x05 << REG_SHIFT, /* GS */
+ 0x02 << REG_SHIFT, /* SS */
+
+ 0x00 << REG_SHIFT, /* CR0 */
+ 0x02 << REG_SHIFT, /* CR2 */
+ 0x03 << REG_SHIFT, /* CR3 */
+
+ 0x00 << REG_SHIFT, /* DR0 */
+ 0x01 << REG_SHIFT, /* DR1 */
+ 0x02 << REG_SHIFT, /* DR2 */
+ 0x03 << REG_SHIFT, /* DR3 */
+ 0x06 << REG_SHIFT, /* DR6 */
+ 0x07 << REG_SHIFT, /* DR7 */
+
+ 0x03 << REG_SHIFT, /* TR3 */
+ 0x04 << REG_SHIFT, /* TR4 */
+ 0x05 << REG_SHIFT, /* TR5 */
+ 0x06 << REG_SHIFT, /* TR6 */
+ 0x07 << REG_SHIFT, /* TR7 */
+
+ 0x00 << REG_SHIFT, /* ST(0) */
+ 0x01 << REG_SHIFT, /* ST(1) */
+ 0x02 << REG_SHIFT, /* ST(2) */
+ 0x03 << REG_SHIFT, /* ST(3) */
+ 0x04 << REG_SHIFT, /* ST(4) */
+ 0x05 << REG_SHIFT, /* ST(5) */
+ 0x06 << REG_SHIFT, /* ST(6) */
+ 0x07 << REG_SHIFT, /* ST(7) */
+};
+
+PRIVATE opsize_t regsize[] =
+{
+ 2, /* BP */
+ 2, /* BX */
+ 2, /* DI */
+ 2, /* SI */
+
+ 4, /* EAX */
+ 4, /* EBP */
+ 4, /* EBX */
+ 4, /* ECX */
+ 4, /* EDI */
+ 4, /* EDX */
+ 4, /* ESI */
+ 4, /* ESP */
+
+ 2, /* AX */
+ 2, /* CX */
+ 2, /* DX */
+ 2, /* SP */
+
+ 1, /* AH */
+ 1, /* AL */
+ 1, /* BH */
+ 1, /* BL */
+ 1, /* CH */
+ 1, /* CL */
+ 1, /* DH */
+ 1, /* DL */
+
+ 2, /* CS */
+ 2, /* DS */
+ 2, /* ES */
+ 2, /* FS */
+ 2, /* GS */
+ 2, /* SS */
+
+ 4, /* CR0 */
+ 4, /* CR2 */
+ 4, /* CR3 */
+
+ 4, /* DR0 */
+ 4, /* DR1 */
+ 4, /* DR2 */
+ 4, /* DR3 */
+ 4, /* DR6 */
+ 4, /* DR7 */
+
+ 4, /* TR3 */
+ 4, /* TR4 */
+ 4, /* TR5 */
+ 4, /* TR6 */
+ 4, /* TR7 */
+
+ 10, /* ST(0) */
+ 10, /* ST(1) */
+ 10, /* ST(2) */
+ 10, /* ST(3) */
+ 10, /* ST(4) */
+ 10, /* ST(5) */
+ 10, /* ST(6) */
+ 10, /* ST(7) */
+
+ 0, /* NOREG */
+};
+
+PRIVATE opcode_t regsegword[] =
+{
+ WORDBIT, /* BP */
+ WORDBIT, /* BX */
+ WORDBIT, /* DI */
+ WORDBIT, /* SI */
+
+ WORDBIT, /* EAX */
+ WORDBIT, /* EBP */
+ WORDBIT, /* EBX */
+ WORDBIT, /* ECX */
+ WORDBIT, /* EDI */
+ WORDBIT, /* EDX */
+ WORDBIT, /* ESI */
+ WORDBIT, /* ESP */
+
+ WORDBIT, /* AX */
+ WORDBIT, /* CX */
+ WORDBIT, /* DX */
+ WORDBIT, /* SP */
+
+ BYTE_SEGWORD, /* AH */
+ BYTE_SEGWORD, /* AL */
+ BYTE_SEGWORD, /* BH */
+ BYTE_SEGWORD, /* BL */
+ BYTE_SEGWORD, /* CH */
+ BYTE_SEGWORD, /* CL */
+ BYTE_SEGWORD, /* DH */
+ BYTE_SEGWORD, /* DL */
+
+ SEGMOV, /* CS */
+ SEGMOV, /* DS */
+ SEGMOV, /* ES */
+ SEGMOV, /* FS */
+ SEGMOV, /* GS */
+ SEGMOV, /* SS */
+
+ 0x20, /* CR0 */
+ 0x20, /* CR2 */
+ 0x20, /* CR3 */
+
+ 0x21, /* DR0 */
+ 0x21, /* DR1 */
+ 0x21, /* DR2 */
+ 0x21, /* DR3 */
+ 0x21, /* DR6 */
+ 0x21, /* DR7 */
+
+ 0x24, /* TR3 */
+ 0x24, /* TR4 */
+ 0x24, /* TR5 */
+ 0x24, /* TR6 */
+ 0x24, /* TR7 */
+
+ 0x00, /* ST(0) */
+ 0x00, /* ST(1) */
+ 0x00, /* ST(2) */
+ 0x00, /* ST(3) */
+ 0x00, /* ST(4) */
+ 0x00, /* ST(5) */
+ 0x00, /* ST(6) */
+ 0x00, /* ST(7) */
+
+ 0x00, /* NOREG */
+};
+
+PRIVATE opcode_t rm[] =
+{
+ 0x05, /* BP */
+ 0x03, /* BX */
+ 0x07, /* DI */
+ 0x06, /* SI */
+
+ 0x00, /* EAX */
+ 0x05, /* EBP */
+ 0x03, /* EBX */
+ 0x01, /* ECX */
+ 0x07, /* EDI */
+ 0x02, /* EDX */
+ 0x06, /* ESI */
+ 0x04, /* ESP */
+
+ 0x00, /* AX */
+ 0x01, /* CX */
+ 0x02, /* DX */
+ 0x04, /* SP */
+
+ 0x04, /* AH */
+ 0x00, /* AL */
+ 0x07, /* BH */
+ 0x03, /* BL */
+ 0x05, /* CH */
+ 0x01, /* CL */
+ 0x06, /* DH */
+ 0x02, /* DL */
+
+ 0x01, /* CS */
+ 0x03, /* DS */
+ 0x00, /* ES */
+ 0x04, /* FS */
+ 0x05, /* GS */
+ 0x02, /* SS */
+
+ 0x00, /* CR0 */
+ 0x00, /* CR2 */
+ 0x00, /* CR3 */
+
+ 0x00, /* DR0 */
+ 0x00, /* DR1 */
+ 0x00, /* DR2 */
+ 0x00, /* DR3 */
+ 0x00, /* DR6 */
+ 0x00, /* DR7 */
+
+ 0x00, /* TR3 */
+ 0x00, /* TR4 */
+ 0x00, /* TR5 */
+ 0x00, /* TR6 */
+ 0x00, /* TR7 */
+
+ 0x00, /* ST(0) */
+ 0x00, /* ST(1) */
+ 0x00, /* ST(2) */
+ 0x00, /* ST(3) */
+ 0x00, /* ST(4) */
+ 0x00, /* ST(5) */
+ 0x00, /* ST(6) */
+ 0x00, /* ST(7) */
+
+ 0x04, /* null index reg for sib only */
+};
+
+PRIVATE opcode_t rmfunny[] =
+{
+ 0x06, /* BP */
+ 0x07, /* BX */
+ 0x05, /* DI */
+ 0x04, /* SI */
+};
+
+PRIVATE opcode_t segoverride[] =
+{
+ 0x2E, /* CS */
+ 0x3E, /* DS */
+ 0x26, /* ES */
+ 0x64, /* FS */
+ 0x65, /* GS */
+ 0x36, /* SS */
+};
+
+PRIVATE opcode_t ss[] = /* scale to ss bits */
+{
+ 0x00, /* x0, illegal */
+ 0x00 << SS_SHIFT, /* x1 */
+ 0x01 << SS_SHIFT, /* x2 */
+ 0x00, /* x3, illegal */
+ 0x02 << SS_SHIFT, /* x4 */
+ 0x00, /* x5, illegal */
+ 0x00, /* x6, illegal */
+ 0x00, /* x7, illegal */
+ 0x03 << SS_SHIFT, /* x8 */
+};
+
+PRIVATE unsigned char calljmp_kludge;
+PRIVATE opcode_t direction;
+PRIVATE bool_t fpreg_allowed;
+PRIVATE opcode_t segword;
+/*
+ Values of segword:
+ BYTE_SEGWORD for byte ea's.
+ SEGMOV for segment registers
+ opcode for special registers
+ WORDBIT for other word and dword ea's
+*/
+
+PRIVATE struct ea_s source;
+PRIVATE struct ea_s source2;
+PRIVATE struct ea_s target;
+
+FORWARD void Eb P((struct ea_s *eap));
+FORWARD void Ew P((struct ea_s *eap));
+FORWARD void Ev P((struct ea_s *eap));
+FORWARD void Ex P((struct ea_s *eap));
+FORWARD void Gd P((struct ea_s *eap));
+FORWARD void Gw P((struct ea_s *eap));
+FORWARD void Gv P((struct ea_s *eap));
+FORWARD void Gx P((struct ea_s *eap));
+FORWARD void buildea P((struct ea_s *eap));
+FORWARD void buildfloat P((void));
+FORWARD void buildfreg P((void));
+FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag));
+FORWARD void buildregular P((void));
+FORWARD void buildsegword P((struct ea_s *eap));
+FORWARD void buildunary P((opcode_pt opc));
+FORWARD opsize_pt displsize P((struct ea_s *eap));
+FORWARD reg_pt fpregchk P((void));
+FORWARD bool_pt getaccumreg P((struct ea_s *eap));
+FORWARD void getbinary P((void));
+FORWARD bool_pt getdxreg P((struct ea_s *eap));
+FORWARD void getea P((struct ea_s *eap));
+FORWARD void getimmed P((struct ea_s *eap, count_t immed_count));
+FORWARD void getindirect P((struct ea_s *eap));
+FORWARD void getshift P((struct ea_s *eap));
+FORWARD reg_pt indregchk P((reg_pt matchreg));
+FORWARD void kgerror P((error_pt errnum));
+FORWARD void lbranch P((int backamount));
+FORWARD void notbytesize P((struct ea_s *eap));
+FORWARD void notimmed P((struct ea_s *eap));
+FORWARD void notindirect P((struct ea_s *eap));
+FORWARD void notsegorspecreg P((struct ea_s *eap));
+FORWARD void yesimmed P((struct ea_s *eap));
+FORWARD void yes_samesize P((void));
+
+PRIVATE void Eb(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ if (eap->size != 0x1)
+ {
+#ifndef NODEFAULTSIZE
+ if (eap->size == 0x0)
+ eap->size = 0x1;
+ else
+#endif
+ kgerror(ILL_SIZE);
+ }
+}
+
+PRIVATE void Ew(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ if (eap->size != 0x2)
+ {
+#ifndef NODEFAULTSIZE
+ if (eap->size == 0x0)
+ eap->size = 0x2;
+ else
+#endif
+ kgerror(ILL_SIZE);
+ }
+}
+
+PRIVATE void Ev(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ notbytesize(eap);
+}
+
+PRIVATE void Ex(eap)
+register struct ea_s *eap;
+{
+ getea(eap);
+ notimmed(eap);
+ notsegorspecreg(eap);
+}
+
+PRIVATE void Gd(eap)
+register struct ea_s *eap;
+{
+ Gx(eap);
+ if (eap->size != 0x4)
+ kgerror(ILL_SIZE);
+}
+
+PRIVATE void Gw(eap)
+register struct ea_s *eap;
+{
+ Gx(eap);
+ if (eap->size != 0x2)
+ kgerror(ILL_SIZE);
+}
+
+PRIVATE void Gv(eap)
+register struct ea_s *eap;
+{
+ Gx(eap);
+ notbytesize(eap);
+}
+
+PRIVATE void Gx(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ notindirect(eap);
+}
+
+PRIVATE void buildea(eap)
+register struct ea_s *eap;
+{
+ opsize_t asize;
+
+ ++mcount;
+ lastexp = eap->displ;
+ if (eap->indcount == 0x0)
+ postb = REG_MOD | rm[eap->base];
+ else
+ {
+ if (eap->base == NOREG)
+ {
+ if (eap->index == NOREG)
+ {
+ if ((asize = displsize(eap)) > 0x2)
+ postb = D32_RM;
+ else
+ postb = D16_RM;
+ }
+ else
+ {
+ asize = 0x4;
+ postb = SIB_NOBASE; /* for sib later */
+ }
+ }
+ else
+ {
+ if (eap->base > MAX16BITINDREG)
+ {
+ asize = 0x4;
+ postb = rm[eap->base];
+ }
+ else
+ {
+ asize = 0x2;
+ if (!(lastexp.data & UNDBIT) &&
+ !iswordorswordoffset(lastexp.offset))
+ error(ABOUNDS);
+ if (eap->index == NOREG)
+ postb = rmfunny[eap->base];
+ else if (eap->base <= MAX16BITINDREG)
+ postb = baseind16[eap->base + 0x4 * eap->index];
+ }
+ }
+ if (asize != defsize)
+ aprefix = 0x67;
+ if (eap->base == NOREG)
+ mcount += asize;
+ else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
+ !is8bitsignedoffset(lastexp.offset))
+ {
+ postb |= MEM2_MOD;
+ mcount += asize;
+ }
+ else if (lastexp.offset != 0x0 ||
+ eap->base == BPREG && eap->index == NOREG ||
+ eap->base == EBPREG)
+ {
+ postb |= MEM1_MOD;
+ ++mcount;
+ }
+ if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG))
+ {
+ sib = ss[eap->scale] |
+ (rm[eap->index] << INDEX_SHIFT) |
+ (postb & RM_MASK);
+ postb = (postb & MOD_MASK) | SIB_RM;
+ ++mcount;
+ }
+ }
+}
+
+PRIVATE void buildfloat()
+{
+ if (mcount != 0x0)
+ {
+ buildea(&source);
+ oprefix = 0x0;
+ postb |= (opcode & 0x07) << REG_SHIFT;
+ opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
+ }
+}
+
+PRIVATE void buildfreg()
+{
+ mcount += 0x2;
+ oprefix = 0x0;
+ postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG);
+ opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
+}
+
+PRIVATE void buildimm(eap, signflag)
+register struct ea_s *eap;
+bool_pt signflag;
+{
+ immadr = eap->displ;
+ immcount = eap->size;
+ if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)))
+ {
+ if (immcount == 0x1)
+ {
+ if ((offset_t) (immadr.offset + 0x80) >= 0x180)
+ datatoobig();
+ }
+ else if (signflag && is8bitsignedoffset(immadr.offset))
+ {
+ opcode |= SIGNBIT;
+ immcount = 0x1;
+ }
+ else if (immcount == 0x2)
+ {
+ if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L)
+ datatoobig();
+ }
+ }
+}
+
+PRIVATE void buildregular()
+{
+ if (mcount != 0x0)
+ {
+ buildea(&target);
+ postb |= regbits[source.base];
+ }
+}
+
+/* Check size and build segword. */
+
+PRIVATE void buildsegword(eap)
+register struct ea_s *eap;
+{
+ if (eap->size == 0x0)
+#ifdef NODEFAULTSIZE
+ kgerror(SIZE_UNK);
+#else
+ eap->size = defsize;
+#endif
+ if (eap->indcount != 0x0 || eap->base == NOREG)
+ {
+ segword = WORDBIT;
+ if (eap->size == 0x1)
+ segword = BYTE_SEGWORD;
+ }
+ else
+ segword = regsegword[eap->base];
+}
+
+PRIVATE void buildunary(opc)
+opcode_pt opc;
+{
+ if (mcount != 0x0)
+ {
+ buildea(&target);
+ postb |= opcode;
+ opcode = opc;
+ }
+}
+
+PRIVATE opsize_pt displsize(eap)
+register struct ea_s *eap;
+{
+ opsize_t asize;
+
+ asize = defsize;
+ if (!(eap->displ.data & UNDBIT))
+ {
+ if (asize > 0x2)
+ {
+ if (!(eap->displ.data & (FORBIT | RELBIT)) &&
+ iswordadr(eap->displ.offset))
+ asize = 0x2;
+ }
+ else if (!iswordorswordoffset(eap->displ.offset))
+ /* should really use iswordadr() */
+ /* but compiler generates signed offsets */
+ {
+ if (!(eap->displ.data & (FORBIT | RELBIT)))
+ asize = 0x4;
+ else if (pass2)
+ error(ABOUNDS);
+ }
+ }
+ return asize;
+}
+
+PRIVATE reg_pt fpregchk()
+{
+ reg_pt fpreg;
+
+ fpreg_allowed = TRUE;
+ fpreg = regchk();
+ fpreg_allowed = FALSE;
+ if (fpreg != ST0REG)
+ return NOREG;
+ getsym();
+ if (sym == LPAREN)
+ {
+ getsym();
+ if (sym != INTCONST || (unsigned) number >= 0x8)
+ error(ILL_FP_REG);
+ else
+ {
+ fpreg += number;
+ getsym();
+ if (sym != RPAREN)
+ error(RPEXP);
+ else
+ getsym();
+ }
+ }
+ return fpreg;
+}
+
+PRIVATE bool_pt getaccumreg(eap)
+register struct ea_s *eap;
+{
+ if ((eap->base = regchk()) != AXREG && eap->base != ALREG
+ && eap->base != EAXREG)
+ return FALSE;
+ getsym();
+ if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
+ oprefix = 0x66;
+ return TRUE;
+}
+
+/*
+ Get binary ea's in target & source (flipped if direction is set).
+ Put size in source if not already.
+ Initialise direction, segword, bump mcount.
+*/
+
+PRIVATE void getbinary()
+{
+ ++mcount;
+ getea(&target);
+ if (target.indcount == 0x0 && target.base == NOREG)
+ {
+ error(ILL_IMM_MODE);
+ target.base = AXREG;
+ target.size = defsize;
+ }
+ getcomma();
+ getea(&source);
+ if (source.size == 0x0)
+ source.size = target.size;
+ else if (target.size != 0x0 && target.size != source.size)
+ {
+ kgerror(MISMATCHED_SIZE);
+ return;
+ }
+ if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV)
+ direction = 0x0;
+ else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV)
+ {
+ struct ea_s swap;
+
+ direction = TOREGBIT;
+ swap = source;
+ source = target;
+ target = swap;
+ }
+ else if (target.indcount != 0x0)
+ {
+ kgerror(ILL_IND_TO_IND);
+ return;
+ }
+ else
+ {
+ kgerror(ILL_SEG_REG);
+ return;
+ }
+ buildsegword(&source);
+}
+
+PRIVATE bool_pt getdxreg(eap)
+register struct ea_s *eap;
+{
+ if ((eap->base = regchk()) != DXREG)
+ return FALSE;
+ getsym();
+ return TRUE;
+}
+
+/* parse effective address */
+
+/*
+ Syntax is restrictive in that displacements must be in the right spots
+ and will not be added up.
+
+ optional size-type prefix, which is
+ BYTE
+ BYTE PTR
+ WORD
+ WORD PTR
+ DWORD
+ DWORD PTR
+ PTR
+ reg
+ segreg
+ [scaled index]
+ where scaled index =
+ indreg
+ indreg*scale
+ indreg+indreg
+ indreg+indreg*scale
+ [scaled index+displ]
+ [scaled index-displ]
+ optional-immediate-prefix displ[scaled index]
+ [displ]
+ optional-imediate-prefix displ
+ (scaled index) -- anachronism
+ optional-imediate-prefix displ(scaled index) -- anachronism
+*/
+
+PRIVATE void getea(eap)
+register struct ea_s *eap;
+{
+ bool_t leading_displ;
+ bool_t leading_immed;
+ register struct sym_s *symptr;
+
+ leading_immed = leading_displ = lastexp.data = eap->indcount
+ = lastexp.offset = 0x0;
+ eap->index = eap->base = NOREG;
+ eap->scale = 0x1;
+ eap->size = mnsize; /* 0x1 for byte ops, else 0x0 */
+
+ if (sym == IDENT)
+ {
+ if ((symptr = gsymptr)->type & MNREGBIT)
+ {
+ if (symptr->data & SIZEBIT)
+ {
+ getsym();
+ if (symptr->value_reg_or_op.op.opcode == 0x0)
+ eap->indcount = 0x2 - calljmp_kludge;
+ else
+ {
+ if (eap->size != 0x0)
+ {
+ if (eap->size != symptr->value_reg_or_op.op.opcode)
+ error(MISMATCHED_SIZE);
+ }
+ else
+ eap->size = symptr->value_reg_or_op.op.opcode;
+ if (eap->size > 0x1 && eap->size != defsize)
+ oprefix = 0x66;
+ if (sym == IDENT &&
+ (symptr = gsymptr)->type & MNREGBIT &&
+ symptr->data & SIZEBIT &&
+ symptr->value_reg_or_op.op.routine == PTROP)
+ {
+ getsym();
+ eap->indcount = 0x2 - calljmp_kludge;
+ }
+ }
+ }
+ }
+ if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT)))
+ symptr->data |= FORBIT; /* show seen in advance */
+ }
+ if ((eap->base = regchk()) != NOREG)
+ {
+ getsym();
+ if (eap->indcount != 0x0)
+ {
+ error(ILL_IND_PTR);
+ eap->indcount = 0x0;
+ }
+ if (eap->size != 0x0 && eap->size != regsize[eap->base])
+ error(MISMATCHED_SIZE);
+ if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
+ oprefix = 0x66;
+ eap->displ = lastexp;
+ return;
+ }
+ if (sym != lindirect)
+ {
+ if (sym == IMMEDIATE || sym == STAR)
+ {
+ /* context-sensitive, STAR means signed immediate here */
+ leading_immed = TRUE;
+ getsym();
+ }
+ leading_displ = TRUE;
+ expres();
+ eap->displ = lastexp;
+ }
+ if (sym == lindirect)
+ {
+ getsym();
+ eap->indcount = 0x2 - calljmp_kludge;
+ if ((eap->base = indregchk((reg_pt) NOREG)) != NOREG)
+ {
+ if (eap->indcount == 0x0 && leading_displ)
+ error(IND_REQ);
+ getsym();
+ if (sym == ADDOP)
+ {
+ getsym();
+ if ((eap->index = indregchk(eap->base)) != NOREG)
+ getsym();
+ else
+ {
+ if (eap->indcount == 0x0)
+ error(IND_REQ);
+ if (leading_displ)
+ error(REPEATED_DISPL);
+ expres(); /* this eats ADDOP, SUBOP, MULOP */
+ }
+ }
+ if (sym == STAR)
+ {
+ /* context-sensitive, STAR means scaled here*/
+ if (eap->index == NOREG && eap->base == ESPREG)
+ {
+ error(INDEX_REG_EXP);
+ eap->base = EAXREG;
+ }
+ getsym();
+ factor();
+ chkabs();
+ if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1)
+ {
+ if (eap->base <= MAX16BITINDREG ||
+ lastexp.offset != 0x2 && lastexp.offset != 0x4 &&
+ lastexp.offset != 0x8)
+ error(ILL_SCALE);
+ else
+ {
+ eap->scale = lastexp.offset;
+ if (eap->index == NOREG)
+ {
+ eap->index = eap->base;
+ eap->base = NOREG;
+ }
+ }
+ }
+ lastexp.data = lastexp.offset = 0x0;
+ }
+ if ((sym == ADDOP || sym == SUBOP))
+ {
+ if (eap->indcount == 0x0)
+ error(IND_REQ);
+ if (leading_displ)
+ error(REPEATED_DISPL);
+ expres();
+ }
+ }
+ else
+ {
+ if (leading_displ)
+ error(REPEATED_DISPL);
+ expres();
+ }
+ if (sym != rindirect)
+ error(rindexp);
+ else
+ getsym();
+ }
+ else if (!leading_immed && idefsize <= 0x2)
+ eap->indcount = 0x1; /* compatibility kludge */
+ if (!leading_displ)
+ eap->displ = lastexp;
+}
+
+PRIVATE void getimmed(eap, immed_count)
+struct ea_s *eap;
+count_t immed_count;
+{
+ getea(eap);
+ yesimmed(eap);
+ if (mcount != 0x0)
+ {
+ eap->size = immed_count;
+ buildimm(eap, FALSE);
+ }
+}
+
+PRIVATE void getindirect(eap)
+register struct ea_s *eap;
+{
+ getea(eap);
+ if (eap->indcount == 0x0)
+ kgerror(IND_REQ);
+}
+
+PRIVATE void getshift(eap)
+register struct ea_s *eap;
+{
+ getcomma();
+ getea(eap);
+ if (eap->base != CLREG)
+ yesimmed(eap);
+}
+
+/*
+ Check if current symbol is a compatible index register.
+ Generate error if it is a reg but not a compatible index.
+ Return register number (adjusted if necessary to a legal index) or NOREG.
+*/
+
+PRIVATE reg_pt indregchk(matchreg)
+reg_pt matchreg;
+{
+ reg_pt reg;
+
+ if ((reg = regchk()) != NOREG)
+ {
+ switch (matchreg)
+ {
+ case BPREG:
+ case BXREG:
+ if (reg != DIREG && reg != SIREG)
+ {
+ reg = SIREG;
+ error(INDEX_REG_EXP);
+ }
+ break;
+ case DIREG:
+ case SIREG:
+ if (reg != BPREG && reg != BXREG)
+ {
+ reg = BXREG;
+ error(INDEX_REG_EXP);
+ }
+ break;
+ case NOREG:
+ break;
+ default:
+ if (reg <= MAX16BITINDREG || reg == ESPREG)
+ {
+ reg = EAXREG;
+ error(INDEX_REG_EXP);
+ }
+ break;
+ }
+ if (reg > MAXINDREG && calljmp_kludge == 0x0)
+ {
+ if (matchreg != NOREG)
+ reg = EAXREG;
+ else
+ reg = BXREG;
+ error(INDEX_REG_EXP);
+ }
+ }
+ return reg;
+}
+
+PRIVATE void kgerror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ sprefix = oprefix = aprefix = mcount = 0x0;
+}
+
+PRIVATE void lbranch(backamount)
+int backamount;
+{
+ mcount += defsize + 0x1;
+ if (pass2)
+ {
+ reldata();
+ if (!(lastexp.data & (RELBIT | UNDBIT)))
+ {
+ lastexp.offset = lastexp.offset - lc - lcjump;
+ if (backamount != 0x0 && !(lastexp.data & IMPBIT) &&
+ lastexp.offset + backamount < 0x80 + backamount)
+ error(SHORTB); /* -0x8? to 0x7F, warning */
+ }
+ }
+}
+
+/* BCC (long branches emulated by short branch over & long jump) */
+
+PUBLIC void mbcc()
+{
+ getea(&target);
+ if (target.indcount >= 0x2 || target.base != NOREG)
+ kgerror(REL_REQ);
+ else
+ {
+ if (defsize != 0x2)
+ {
+ page = PAGE1_OPCODE;
+ ++mcount;
+ opcode += 0x10;
+ lbranch(0x84);
+ }
+ else
+ {
+ aprefix = opcode ^ 0x1; /* kludged storage for short branch
+ over */
+ oprefix = defsize + 0x1;
+ mcount += 0x2;
+ opcode = JMP_OPCODE;
+ lbranch(0x83);
+ mcount -= 0x2;
+ }
+ }
+}
+
+/* bswap r32 */
+
+PUBLIC void mbswap()
+{
+ ++mcount;
+ Gd(&target);
+ opcode |= rm[target.base];
+}
+
+/* BR, CALL, J, JMP */
+
+PUBLIC void mcall()
+{
+ opcode_pt far;
+ bool_t indirect;
+ register struct sym_s *symptr;
+
+ far = 0x0;
+ if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT &&
+ symptr->data & SIZEBIT &&
+ symptr->value_reg_or_op.op.routine == FAROP)
+ {
+ far = 0x8;
+ getsym();
+ }
+ indirect = FALSE;
+ if (asld_compatible && idefsize <= 0x2)
+ {
+ calljmp_kludge = 0x2;
+ if (sym == INDIRECT)
+ {
+ calljmp_kludge = 0x0;
+ indirect = TRUE;
+ getsym();
+ }
+ }
+ getea(&target);
+ if (indirect && target.indcount == 0x1)
+ target.indcount = 0x2;
+ calljmp_kludge = 0x0;
+ if (sym == COLON)
+ {
+ if (opcode == JMP_SHORT_OPCODE)
+ opcode = JMP_OPCODE;
+ ++mcount;
+ yesimmed(&target);
+ getsym();
+ getea(&source);
+ yesimmed(&source);
+ if (mcount != 0x0)
+ {
+ if (opcode == JMP_OPCODE)
+ opcode = 0xEA;
+ else
+ opcode = 0x9A;
+ lastexp = source.displ;
+ if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
+ defsize == 0x2 &&
+ (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
+ datatoobig();
+ mcount += defsize;
+ target.size = 0x2;
+ buildimm(&target, FALSE);
+ }
+ }
+ else if (target.indcount >= 0x2 || target.base != NOREG)
+ {
+ ++mcount;
+ notsegorspecreg(&target);
+ if (target.indcount == 0)
+ notbytesize(&target);
+ if (mcount != 0x0)
+ {
+ if (opcode == JMP_SHORT_OPCODE)
+ opcode = JMP_OPCODE;
+ buildea(&target);
+ if (opcode == JMP_OPCODE)
+ opcode = 0x20;
+ else
+ opcode = 0x10;
+ postb |= opcode + far;
+ opcode = 0xFF;
+ }
+ }
+ else if (opcode == JMP_SHORT_OPCODE)
+ {
+ if (jumps_long)
+ {
+ opcode = JMP_OPCODE;
+ lbranch(0x83);
+ }
+ else
+ {
+ lastexp = target.displ;
+ if (lastexp.data & IMPBIT)
+ {
+ error(NONIMPREQ);
+ lastexp.data = FORBIT | UNDBIT;
+ }
+ mshort2();
+ }
+ }
+ else
+ lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0);
+}
+
+/* CALLI, JMPI */
+
+PUBLIC void mcalli()
+{
+ bool_t indirect;
+
+ ++mcount;
+ indirect = FALSE;
+ if (sym == INDIRECT)
+ {
+ getsym();
+ indirect = TRUE;
+ }
+ getea(&target);
+ if (target.indcount >= 0x2 || target.base != NOREG)
+ indirect = TRUE;
+ if (indirect)
+ {
+ buildea(&target);
+ if (opcode == 0xEA)
+ opcode = 0x28;
+ else
+ opcode = 0x18;
+ postb |= opcode;
+ opcode = 0xFF;
+ }
+ else
+ {
+ getcomma();
+ getea(&source);
+ yesimmed(&source);
+ if (mcount != 0x0)
+ {
+ lastexp = target.displ;
+ if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
+ defsize == 0x2 &&
+ (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
+ datatoobig();
+ mcount += defsize;
+ source.size = 0x2;
+ buildimm(&source, FALSE);
+ }
+ }
+}
+
+/* DIV, IDIV, MUL */
+
+PUBLIC void mdivmul()
+{
+ if (getaccumreg(&source))
+ {
+ ++mcount;
+ getcomma();
+ Ex(&target);
+ yes_samesize();
+ buildunary(0xF6 | regsegword[source.base]);
+ }
+ else
+ mnegnot();
+}
+
+/* ENTER */
+
+PUBLIC void menter()
+{
+ ++mcount;
+ getimmed(&target, 0x2);
+ getcomma();
+ getimmed(&source, 0x1);
+ if (mcount != 0x0)
+ {
+ mcount += 2;
+ lastexp = target.displ; /* getimmed(&source) wiped it out */
+ }
+}
+
+/* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */
+
+PUBLIC void mEwGw()
+{
+ ++mcount;
+ Ew(&target);
+ getcomma();
+ Gw(&source);
+ oprefix = 0x0;
+ buildregular();
+}
+
+/* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */
+
+PUBLIC void mExGx()
+{
+ ++mcount;
+ Ex(&target);
+ getcomma();
+ Gx(&source);
+ yes_samesize();
+ opcode |= segword;
+ buildregular();
+}
+
+PUBLIC void mf_inher()
+{
+ mcount += 0x2;
+ postb = REG_MOD | (opcode & ~REG_MOD);
+ opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6);
+ if (opcode == ESCAPE_OPCODE_BASE)
+ opcode = ESCAPE_OPCODE_BASE | 0x6; /* fix up encoding of fcompp */
+}
+
+/* [fldenv fnsave fnstenv frstor] mem */
+
+PUBLIC void mf_m()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size != 0x0)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* [fldcw fnstcw] mem2i */
+
+PUBLIC void mf_m2()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size != 0x0 && source.size != 0x2)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* fnstsw [mem2i ax] */
+
+PUBLIC void mf_m2_ax()
+{
+ if (getaccumreg(&target))
+ {
+ if (target.base != AXREG)
+ kgerror(ILLREG);
+ else
+ {
+ opcode = 0x74;
+ target.base = ST0REG; /* fake, really ax */
+ buildfreg();
+ }
+ }
+ else
+ mf_m2();
+}
+
+/* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */
+
+PUBLIC void mf_m2_m4()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x2)
+ opcode |= 0x40;
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* [fild fistp] [mem2i mem4i mem8i] */
+
+PUBLIC void mf_m2_m4_m8()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x2)
+ opcode |= 0x40;
+ else if (source.size == 0x8)
+ opcode |= 0x45; /* low bits 0 -> 5 and 3 -> 7 */
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* [fcom fcomp] [mem4r mem8r optional-st(i)] */
+
+PUBLIC void mf_m4_m8_optst()
+{
+ if (sym == EOLSYM)
+ {
+ target.base = ST1REG;
+ buildfreg();
+ }
+ else
+ mf_m4_m8_st();
+}
+
+/* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */
+
+PUBLIC void mf_m4_m8_stst()
+{
+ target.base = fpregchk();
+ if (target.base != NOREG)
+ {
+ getcomma();
+ source.base = fpregchk();
+ if (source.base == NOREG)
+ {
+ error(FP_REG_REQ);
+ source.base = ST0REG;
+ }
+ if (target.base == ST0REG)
+ target.base = source.base;
+ else
+ {
+ if (source.base != ST0REG)
+ error(ILL_FP_REG_PAIR);
+ opcode |= 0x40;
+ if ((opcode & 0x07) >= 0x4)
+ opcode ^= 0x01; /* weird swap of fdiv/fdivr, fsub/fsubr */
+ }
+ buildfreg();
+ }
+ else
+ {
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x8)
+ opcode |= 0x40;
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+ }
+}
+
+/* fst [mem4r mem8r st(i)] */
+
+PUBLIC void mf_m4_m8_st()
+{
+ target.base = fpregchk();
+ if (target.base != NOREG)
+ {
+ if (opcode == FST_ENCODED)
+ opcode |= 0x40;
+ buildfreg();
+ }
+ else
+ {
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x8)
+ opcode |= 0x40;
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+ }
+}
+
+/* [fld fstp] [mem4r mem8r mem10r st(i)] */
+
+PUBLIC void mf_m4_m8_m10_st()
+{
+ target.base = fpregchk();
+ if (target.base != NOREG)
+ {
+ if (opcode == FSTP_ENCODED)
+ opcode |= 0x40;
+ buildfreg();
+ }
+ else
+ {
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x8)
+ opcode |= 0x40;
+ else if (source.size == 0xA)
+ opcode |= 0x25; /* low bits 0 -> 5 and 3 -> 7 */
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+ }
+}
+
+/* [fbld fbstp] mem10r */
+
+PUBLIC void mf_m10()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size != 0xA)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* ffree st(i) */
+
+PUBLIC void mf_st()
+{
+ target.base = fpregchk();
+ if (target.base == NOREG)
+ kgerror(FP_REG_REQ);
+ buildfreg();
+}
+
+/* [fucom fucomp fxch] optional-st(i) */
+
+PUBLIC void mf_optst()
+{
+ if (sym == EOLSYM)
+ {
+ target.base = ST1REG;
+ buildfreg();
+ }
+ else
+ mf_st();
+}
+
+/* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */
+
+PUBLIC void mf_stst()
+{
+ target.base = fpregchk();
+ if (target.base == NOREG)
+ {
+ kgerror(FP_REG_REQ);
+ return;
+ }
+ getcomma();
+ source.base = fpregchk();
+ if (source.base == NOREG)
+ {
+ kgerror(FP_REG_REQ);
+ return;
+ }
+ if (source.base != ST0REG)
+ {
+ kgerror(ILL_FP_REG);
+ return;
+ }
+ buildfreg();
+}
+
+PUBLIC void mf_w_inher()
+{
+ sprefix = WAIT_OPCODE;
+ mf_inher();
+}
+
+/* [fsave fstenv] mem */
+
+PUBLIC void mf_w_m()
+{
+ sprefix = WAIT_OPCODE;
+ mf_m();
+}
+
+/* fstcw mem2i */
+
+PUBLIC void mf_w_m2()
+{
+ sprefix = WAIT_OPCODE;
+ mf_m2();
+}
+
+/* fstsw [mem2i ax] */
+
+PUBLIC void mf_w_m2_ax()
+{
+ sprefix = WAIT_OPCODE;
+ mf_m2_ax();
+}
+
+/* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */
+
+PUBLIC void mgroup1()
+{
+ getbinary();
+ notsegorspecreg(&source);
+ if (mcount != 0x0)
+ {
+ if (source.base == NOREG)
+ {
+ if (target.indcount == 0x0 && (target.base == ALREG ||
+ target.base == AXREG ||
+ target.base == EAXREG &&
+ (source.displ.data & (FORBIT | RELBIT | UNDBIT) ||
+ !is8bitsignedoffset(source.displ.offset))))
+ {
+ opcode |= 0x04 | segword;
+ buildimm(&source, FALSE);
+ }
+ else
+ {
+ buildunary(0x80 | segword);
+ buildimm(&source, TRUE);
+ }
+ }
+ else
+ {
+ opcode |= direction | segword;
+ buildregular();
+ }
+ }
+}
+
+/* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */
+
+PUBLIC void mgroup2()
+{
+ ++mcount;
+ Ex(&target);
+ buildsegword(&target);
+ getshift(&source);
+ if (mcount != 0x0)
+ {
+ buildunary(0xD0 | segword);
+ if (source.base == CLREG)
+ opcode |= 0x2;
+ else if (source.displ.offset != 0x1)
+ {
+ opcode -= 0x10;
+ source.size = 0x1;
+ buildimm(&source, FALSE);
+ }
+ }
+}
+
+/* LLDT, LTR, SLDT, STR, VERR, VERW */
+
+PUBLIC void mgroup6()
+{
+ ++mcount;
+ Ew(&target);
+ oprefix = 0x0;
+ buildunary(0x0);
+}
+
+/* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */
+
+PUBLIC void mgroup7()
+{
+ ++mcount;
+ if (opcode == 0x20 || opcode == 0x30)
+ {
+ Ew(&target);
+ oprefix = 0x0;
+ }
+ else
+ {
+ getindirect(&target);
+ oprefix = 0x0;
+ if (target.size != 0x0 && target.size != 0x6)
+ error(MISMATCHED_SIZE); /* XXX - size 6 wrong for INVLPG? */
+ }
+ buildunary(0x1);
+}
+
+/* BT, BTR, BTS, BTC */
+
+PUBLIC void mgroup8()
+{
+ ++mcount;
+ Ev(&target);
+ getcomma();
+ /* Gv or Ib */
+ getea(&source);
+ notindirect(&source);
+ notsegorspecreg(&source);
+ if (mcount != 0x0)
+ {
+ if (source.base == NOREG)
+ {
+ buildunary(0xBA);
+ source.size = 0x1;
+ buildimm(&source, TRUE);
+ }
+ else
+ {
+ yes_samesize();
+ opcode += 0x83;
+ buildregular();
+ }
+ }
+}
+
+/* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */
+
+PUBLIC void mGvEv()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ Ev(&target);
+ yes_samesize();
+ buildregular();
+}
+
+/* bound [r16,m16&16 r32,m32&32] */
+
+PUBLIC void mGvMa()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ getindirect(&target);
+ yes_samesize();
+ buildregular();
+}
+
+/* LDS, LES, LFS, LGS, LSS */
+
+PUBLIC void mGvMp()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ getindirect(&target);
+ if (target.size != 0x0 && target.size != 0x2 + source.size)
+ error(MISMATCHED_SIZE);
+ buildregular();
+}
+
+/* IMUL */
+
+PUBLIC void mimul()
+{
+ ++mcount;
+ Ex(&target);
+ if (sym != COMMA)
+ {
+ buildsegword(&target);
+ buildunary(0xF6 | segword);
+ return;
+ }
+ getcomma();
+ notindirect(&target);
+ source = target; /* direction is swapped */
+ getea(&target);
+ notsegorspecreg(&target);
+ yes_samesize();
+ if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG))
+ {
+ page = PAGE1_OPCODE;
+ ++mcount;
+ opcode = 0xAF;
+ buildregular();
+ }
+ else
+ {
+ if (sym == COMMA)
+ {
+ getsym();
+ getea(&source2);
+ yesimmed(&source2);
+ }
+ else
+ {
+ source2 = target;
+ target = source;
+ }
+ source2.size = target.size;
+ if (is8bitsignedoffset(source2.displ.offset))
+ {
+ source2.size = 0x1;
+ opcode = 0x6B;
+ }
+ else
+ {
+ source2.size = target.size;
+ opcode = 0x69;
+ }
+ buildregular();
+ if (mcount != 0x0)
+ buildimm(&source2, FALSE);
+ }
+}
+
+/* IN */
+
+PUBLIC void min()
+{
+ ++mcount;
+ if (opcode & WORDBIT) /* inw; ind not supported */
+ mnsize = 0x2;
+ if (sym == EOLSYM && mnsize != 0x0)
+ target.size = mnsize;
+ else
+ {
+ if (getaccumreg(&target))
+ {
+ if (mnsize != 0x0 && regsize[target.base] != mnsize)
+ error(MISMATCHED_SIZE);
+ getcomma();
+ }
+ else
+ target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG];
+ opcode |= regsegword[target.base];
+ if (!getdxreg(&source))
+ {
+ getimmed(&source, 0x1);
+ opcode -= 0x8;
+ }
+ }
+ if (target.size > 0x1 && target.size != defsize)
+ oprefix = 0x66;
+}
+
+/* DEC, INC */
+
+PUBLIC void mincdec()
+{
+ ++mcount;
+ Ex(&target);
+ buildsegword(&target);
+ if (target.indcount == 0x0 && segword == WORDBIT)
+ opcode |= 0x40 | rm[target.base];
+ else
+ buildunary(0xFE | segword);
+}
+
+/* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */
+/* MOVSW, OUTSW, SCASW, STOSW */
+
+PUBLIC void minher16()
+{
+ minher();
+ if (defsize != 0x2)
+ oprefix = 0x66;
+}
+
+/* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */
+/* MOVSD, OUTSD, SCASD, STOSD */
+
+PUBLIC void minher32()
+{
+ minher();
+ if (defsize != 0x4)
+ oprefix = 0x66;
+}
+
+/* AAD, AAM */
+
+PUBLIC void minhera()
+{
+ ++mcount;
+ if (sym == EOLSYM)
+ {
+ target.displ.offset = 0xA;
+ target.size = 0x1;
+ buildimm(&target, FALSE);
+ }
+ else
+ getimmed(&target, 0x1);
+}
+
+/* INT */
+
+PUBLIC void mint()
+{
+ ++mcount;
+ getimmed(&target, 0x1);
+ if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) &&
+ (opcode_t) immadr.offset == 0x3)
+ {
+ immcount = 0x0;
+ opcode = 0xCC;
+ }
+}
+
+/* JCC */
+
+PUBLIC void mjcc()
+{
+ if (jumps_long && opcode < 0x80) /* above 0x80 means loop - not long */
+ mbcc();
+ else
+ mshort();
+}
+
+/* JCXZ, JECXZ */
+
+PUBLIC void mjcxz()
+{
+ if (opcode != defsize)
+ {
+ aprefix = 0x67;
+ ++mcount; /* quick fix - mshort() needs to know */
+ }
+ opcode = 0xE3;
+ mshort();
+ if (aprefix != 0x0)
+ --mcount; /* quick fix - main routine bumps it again */
+}
+
+/* LEA */
+
+PUBLIC void mlea()
+{
+ Gv(&source); /* back to front */
+ getcomma();
+ ++mcount;
+ getindirect(&target);
+ yes_samesize();
+ buildregular();
+}
+
+/* MOV */
+
+PUBLIC void mmov()
+{
+ getbinary();
+ if (segword >= SEGMOV)
+ {
+ oprefix = 0x0;
+ notimmed(&target); /* target is actually the source */
+ if (segword > SEGMOV) /* special reg */
+ notindirect(&target);
+ }
+ if (mcount != 0x0)
+ {
+ if (target.base == NOREG && target.index == NOREG &&
+ (source.base == ALREG || source.base == AXREG ||
+ source.base == EAXREG))
+ {
+ opcode = 0xA0 | (direction ^ TOREGBIT) | segword;
+ lastexp = target.displ;
+ if ((source.size = displsize(&target)) != defsize)
+ aprefix = 0x67;
+ mcount += source.size;
+ }
+ else if (source.base == NOREG)
+ {
+ if (target.indcount == 0x0)
+ opcode = 0xB0 | (segword << 0x3) | rm[target.base];
+ else
+ {
+ buildea(&target);
+ opcode = 0xC6 | segword;
+ }
+ buildimm(&source, FALSE);
+ }
+ else
+ {
+ if (isspecreg(source.base))
+ {
+ page = PAGE1_OPCODE;
+ ++mcount;
+ opcode = 0x0;
+ }
+ opcode |= direction | segword;
+ buildregular();
+ }
+ }
+}
+
+/* MOVSX, MOVZX */
+
+PUBLIC void mmovx()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ Ex(&target);
+ if (target.size == 0x0)
+ kgerror(SIZE_UNK);
+ if (target.size > 0x2)
+ kgerror(ILL_SIZE);
+ oprefix = 0x0;
+ if (source.size != defsize)
+ oprefix = 0x66;
+ buildsegword(&target);
+ opcode |= segword;
+ buildregular();
+}
+
+/* NEG, NOT */
+
+PUBLIC void mnegnot()
+{
+ ++mcount;
+ Ex(&target);
+ buildsegword(&target);
+ buildunary(0xF6 | segword);
+}
+
+/* OUT */
+
+PUBLIC void mout()
+{
+ ++mcount;
+ if (opcode & WORDBIT) /* outw; outd not supported */
+ mnsize = 0x2;
+ if (sym == EOLSYM && mnsize != 0x0)
+ source.size = mnsize;
+ else
+ {
+ if (!getdxreg(&target))
+ {
+ getimmed(&target, 0x1);
+ opcode -= 0x8;
+ }
+ if (sym == COMMA)
+ {
+ getsym();
+ if (!getaccumreg(&source))
+ kgerror(AL_AX_EAX_EXP);
+ else if (mnsize != 0x0 && regsize[source.base] != mnsize)
+ error(MISMATCHED_SIZE);
+ }
+ else
+ source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG];
+ opcode |= regsegword[source.base];
+ }
+ if (source.size > 0x1 && source.size != defsize)
+ oprefix = 0x66;
+}
+
+/* POP, PUSH */
+
+PUBLIC void mpushpop()
+{
+ opcode_t oldopcode;
+
+ ++mcount;
+ getea(&target);
+ buildsegword(&target);
+ notbytesize(&target);
+ if ((oldopcode = opcode) == POP_OPCODE)
+ {
+ notimmed(&target);
+ if (target.base == CSREG)
+ kgerror(ILL_SEG_REG);
+ }
+ if (mcount != 0x0)
+ {
+ if (target.indcount == 0x0)
+ {
+ if (segword == SEGMOV)
+ {
+ switch (target.base)
+ {
+ case CSREG:
+ opcode = 0x0E;
+ break;
+ case DSREG:
+ opcode = 0x1E;
+ break;
+ case ESREG:
+ opcode = 0x06;
+ break;
+ case SSREG:
+ opcode = 0x16;
+ break;
+ case FSREG:
+ opcode = 0xA0;
+ page = PAGE1_OPCODE;
+ ++mcount;
+ break;
+ case GSREG:
+ opcode = 0xA8;
+ page = PAGE1_OPCODE;
+ ++mcount;
+ break;
+ }
+ if (oldopcode == POP_OPCODE)
+ ++opcode;
+ }
+ else if (target.base != NOREG)
+ {
+ opcode = 0x50 | rm[target.base];
+ if (oldopcode == POP_OPCODE)
+ opcode |= 0x8;
+ }
+ else
+ {
+ opcode = 0x68;
+ if (oldopcode == POP_OPCODE)
+ ++opcode;
+ buildimm(&target, TRUE);
+ }
+ }
+ else
+ {
+ buildea(&target);
+ if (oldopcode == PUSH_OPCODE)
+ postb |= 0x6 << REG_SHIFT;
+ }
+ }
+}
+
+/* RET, RETF */
+
+PUBLIC void mret()
+{
+ ++mcount;
+ if (sym != EOLSYM)
+ {
+ --opcode;
+ getimmed(&target, 0x2);
+ }
+}
+
+/* SEG CS/DS/ES/FS/GS/SS */
+
+PUBLIC void mseg()
+{
+ reg_pt reg;
+
+ if (regsegword[reg = regchk()] != SEGMOV)
+ error(SEG_REG_REQ);
+ else
+ {
+ getsym();
+ ++mcount;
+ opcode = (segoverride - CSREG)[reg];
+ }
+}
+
+/* SETCC */
+
+PUBLIC void msetcc()
+{
+ ++mcount;
+ Eb(&target);
+ if (mcount != 0x0)
+ buildea(&target);
+}
+
+/* SHLD, SHRD */
+
+PUBLIC void mshdouble()
+{
+ ++mcount;
+ Ev(&target);
+ getcomma();
+ Gv(&source);
+ yes_samesize();
+ buildregular();
+ getshift(&source2);
+ lastexp = target.displ; /* getshift() wiped it out */
+ if (mcount != 0x0)
+ {
+ if (source2.base == CLREG)
+ opcode |= 0x1;
+ else
+ {
+ source2.size = 0x1;
+ buildimm(&source2, FALSE);
+ }
+ }
+}
+
+/*
+ TEST
+ Similar to the regular group1 operators.
+ It does not allow the sign extended immediate byte forms
+ and does not use the relevant direction bit.
+*/
+
+PUBLIC void mtest()
+{
+ getbinary();
+ notsegorspecreg(&source);
+ if (source.base == NOREG)
+ {
+ if (mcount != 0x0)
+ {
+ if (target.indcount == 0x0
+ && (target.base == ALREG || target.base == AXREG
+ || target.base == EAXREG))
+ opcode = 0xA8 | segword;
+ else
+ {
+ buildea(&target);
+ opcode = 0xF6 | segword;
+ }
+ }
+ buildimm(&source, FALSE);
+ }
+ else
+ {
+ opcode |= segword;
+ buildregular();
+ }
+}
+
+/*
+ XCHG
+ Similar to the regular group1 operators.
+ It does not allow any of the immediate forms
+ and does not use the irrelevant direction bit.
+*/
+
+PUBLIC void mxchg()
+{
+ getbinary();
+ notimmed(&source);
+ notsegorspecreg(&source);
+ if (target.indcount == 0x0)
+ {
+ if (target.base == AXREG || target.base == EAXREG)
+ {
+ opcode = 0x90 + rm[source.base];
+ return;
+ }
+ if (source.base == AXREG || source.base == EAXREG)
+ {
+ opcode = 0x90 + rm[target.base];
+ return;
+ }
+ }
+ opcode |= segword;
+ buildregular();
+}
+
+PRIVATE void notbytesize(eap)
+register struct ea_s *eap;
+{
+ if (eap->size == 0x1)
+ kgerror(ILL_SIZE);
+}
+
+PRIVATE void notimmed(eap)
+register struct ea_s *eap;
+{
+ if (eap->indcount == 0x0 && eap->base == NOREG)
+ kgerror(ILL_IMM_MODE);
+}
+
+PRIVATE void notindirect(eap)
+register struct ea_s *eap;
+{
+ if (eap->indcount != 0x0)
+ kgerror(ILL_IND);
+}
+
+PRIVATE void notsegorspecreg(eap)
+register struct ea_s *eap;
+{
+ if (regsegword[eap->base] >= SEGMOV)
+ kgerror(ILLREG);
+}
+
+PRIVATE void yesimmed(eap)
+register struct ea_s *eap;
+{
+ if (eap->indcount == 0x1)
+ eap->indcount = 0x0;
+ if (eap->indcount != 0x0 || eap->base != NOREG)
+ kgerror(IMM_REQ);
+}
+
+PRIVATE void yes_samesize()
+{
+ if (target.size == 0x0)
+ target.size = source.size;
+ else if (source.size != 0x0 && target.size != source.size)
+ kgerror(MISMATCHED_SIZE);
+}
+
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* 6809 opcode constants */
+
+/* bits for indexed addressing */
+
+#define INDIRECTBIT 0x10
+#define INDEXBIT 0x80 /* except 5 bit offset */
+#define PCRELBIT 0x04 /* PC relative (in certain cases) */
+#define RRBITS 0x60 /* register select bits */
+
+PRIVATE opcode_t rrindex[] = /* register and index bits for indexed adr */
+{
+ 0x60 | INDEXBIT, /* S */
+ 0x40 | INDEXBIT, /* U */
+ 0x00 | INDEXBIT, /* X */
+ 0x20 | INDEXBIT, /* Y */
+ PCRELBIT | INDEXBIT, /* PC */
+};
+
+PRIVATE opcode_t pushpull[] = /* push/pull codes */
+{
+ 0x40, /* S */
+ 0x40, /* U */
+ 0x10, /* X */
+ 0x20, /* Y */
+ 0x80, /* PC */
+ 0x02, /* A */
+ 0x04, /* B */
+ 0x01, /* CC */
+ 0x08, /* DP */
+ 0x06, /* D */
+};
+
+PRIVATE opcode_t tfrexg1[] = /* transfer/exchange codes for source reg */
+{
+ 0x40, /* S */
+ 0x30, /* U */
+ 0x10, /* X */
+ 0x20, /* Y */
+ 0x50, /* PC */
+ 0x80, /* A */
+ 0x90, /* B */
+ 0xA0, /* CC */
+ 0xB0, /* DP */
+ 0x00, /* D */
+};
+
+PRIVATE opcode_t tfrexg2[] = /* transfer/exchange codes for target reg */
+{
+ 0x04, /* S */
+ 0x03, /* U */
+ 0x01, /* X */
+ 0x02, /* Y */
+ 0x05, /* PC */
+ 0x08, /* A */
+ 0x09, /* B */
+ 0x0A, /* CC */
+ 0x0B, /* DP */
+ 0x00, /* D */
+};
+
+FORWARD void checkpostinc P((void));
+FORWARD void doaltind P((void));
+FORWARD void do1altind P((void));
+FORWARD void fixupind P((void));
+FORWARD void getindexnopost P((void));
+FORWARD void inderror P((error_pt errnum));
+FORWARD reg_pt indreg P((reg_pt maxindex));
+FORWARD void predec1 P((void));
+FORWARD void sustack P((reg_pt stackreg));
+
+PRIVATE void checkpostinc()
+{
+ if (sym == ADDOP)
+ {
+ if (postb & INDIRECTBIT)
+ inderror(ILLMOD); /* single-inc indirect illegal */
+ else
+ {
+ lastexp.offset &= 0xFF00; /* for printing if postbyte is 0: ,X+ */
+ getsym();
+ }
+ }
+ else if (sym == POSTINCOP)
+ {
+ postb |= 0x1;
+ getsym();
+ }
+ else
+ postb |= 0x4;
+ fixupind();
+}
+
+/* common code for all-mode ops, alterable-mode ops, indexed ops */
+
+PRIVATE void doaltind()
+{
+ mcount += 0x2;
+ if (sym == LBRACKET)
+ {
+ postb = INDIRECTBIT;
+ getsym();
+ do1altind();
+ if (sym != RBRACKET)
+ error(RBEXP);
+ }
+ else
+ do1altind();
+}
+
+PRIVATE void do1altind()
+{
+ bool_t byteflag; /* set if direct or short indexed adr forced */
+ char *oldlineptr;
+ char *oldsymname;
+ reg_pt reg;
+ bool_t wordflag; /* set if extended or long indexed adr forced*/
+
+ if ((reg = regchk()) != NOREG)
+ {
+ switch (reg)
+ {
+ case AREG:
+ postb |= 0x86;
+ break;
+ case BREG:
+ postb |= 0x85;
+ break;
+ case DREG:
+ postb |= 0x8B;
+ break;
+ default:
+ if (indreg(MAXINDREG) != NOREG)
+ checkpostinc();
+ return;
+ }
+ getsym();
+ if (sym != COMMA)
+ inderror(COMEXP);
+ else
+ getindexnopost();
+ return;
+ }
+ else if (sym == SUBOP) /* could be -R or - in expression */
+ {
+ oldlineptr = lineptr; /* save state */
+ oldsymname = symname;
+ getsym();
+ reg = regchk();
+ lineptr = oldlineptr;
+ symname = oldsymname;
+ if (reg != NOREG)
+ {
+ predec1(); /* it's -R */
+ return;
+ }
+ sym = SUBOP;
+ }
+ else if (sym == COMMA)
+ {
+ postb |= INDEXBIT;
+ getsym();
+ if (sym == SUBOP)
+ {
+ predec1();
+ return;
+ }
+ else if (sym != PREDECOP)
+ {
+ if (indreg(MAXINDREG) != NOREG)
+ checkpostinc();
+ return;
+ }
+ }
+ if (sym == PREDECOP)
+ {
+ postb |= 0x83;
+ getindexnopost();
+ return;
+ }
+
+ /* should have expression */
+
+ wordflag = byteflag = FALSE;
+ if (sym == LESSTHAN)
+ {
+ /* context-sensitive, LESSTHAN means byte-sized here */
+ byteflag = TRUE;
+ getsym();
+ }
+ else if (sym == GREATERTHAN)
+ {
+ /* context-sensitive, GREATERTHAN means word-sized here */
+ wordflag = TRUE;
+ getsym();
+ }
+ expres();
+ if (sym == COMMA)
+ { /* offset from register */
+ getsym();
+ if ((reg = indreg(PCREG)) == NOREG)
+ return;
+ postb |= 0x8; /* default 8 bit offset */
+ if (reg == PCREG)
+ {
+ reldata();
+ if (!(lastexp.data & (RELBIT | UNDBIT)))
+ {
+ lastexp.offset = lastexp.offset - lc;
+ if (page != 0x0)
+ lastexp.offset -= 0x4; /* extra for instruction */
+ else
+ lastexp.offset -= 0x3; /* 3 byte instruction
+ assuming 8 bit offset */
+ }
+ }
+ if (byteflag)
+ {
+ if (!(lastexp.data & (RELBIT | UNDBIT)) &&
+ !is8bitsignedoffset(lastexp.offset))
+ error(ABOUNDS); /* forced short form is impossible */
+ ++mcount;
+ }
+ else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
+ !is8bitsignedoffset(lastexp.offset))
+ { /* 16 bit offset */
+ if (postb & PCRELBIT && !(lastexp.data & RELBIT))
+ --lastexp.offset; /* instruction 1 longer than already
+ allowed */
+ postb |= 0x1;
+ mcount += 0x2;
+ }
+ else if (!(postb & PCRELBIT) &&
+ (offset_t) (lastexp.offset + 0x10) < 0x20 &&
+ !(postb & INDIRECTBIT && lastexp.offset != 0x0))
+ { /* 5 bit offset */
+ postb &= RRBITS | INDIRECTBIT;
+ if (lastexp.offset == 0x0)
+ postb |= 0x84; /* index with zero offset */
+ else
+ postb |= (lastexp.offset & 0x1F);
+ }
+ else /* 8 bit offset */
+ ++mcount;
+ fixupind();
+ }
+ else if (postb & INDIRECTBIT)
+ { /* extended indirect */
+ postb = 0x9F;
+ mcount += 0x2;
+ fixupind();
+ }
+ else if (postb & INDEXBIT)
+ inderror(ILLMOD); /* e.g. LEAX $10 */
+ else
+ {
+ if (byteflag || !wordflag && !(lastexp.data & (FORBIT | RELBIT)) &&
+ (lastexp.offset >> 0x8) == dirpag)
+ { /* direct addressing */
+ if (opcode >= 0x80)
+ opcode |= 0x10;
+ }
+ else /* extended addressing */
+ {
+ if (opcode < 0x80)
+ opcode |= 0x70;
+ else
+ opcode |= 0x30;
+ ++mcount;
+ if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) &&
+ !(lastexp.data & IMPBIT) &&
+ lastexp.offset + (0x81 - 0x3) < 0x101)
+ /* JSR or JMP could be done with BSR or BRA */
+ error(SHORTB);
+ }
+ }
+}
+
+PRIVATE void fixupind()
+{
+ if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */
+ {
+ if (opcode < 0x80)
+ opcode |= 0x60;
+ else
+ opcode |= 0x20;
+ }
+}
+
+PRIVATE void getindexnopost()
+{
+ getsym();
+ if (indreg(MAXINDREG) != NOREG)
+ fixupind();
+}
+
+PRIVATE void inderror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ if (postb & INDIRECTBIT)
+ sym = RBRACKET; /* fake right bracket to kill further errors */
+ fixupind();
+}
+
+/* check current symbol is an index register (possibly excepting PC) */
+/* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */
+/* otherwise generate error, return FALSE */
+
+PRIVATE reg_pt indreg(maxindex)
+reg_pt maxindex;
+{
+ reg_pt reg;
+
+ if ((reg = regchk()) == NOREG)
+ inderror(IREGEXP);
+ else if (reg > maxindex)
+ {
+ inderror(ILLREG);
+ reg = NOREG;
+ }
+ else
+ {
+ postb |= rrindex[reg];
+ getsym();
+ }
+ return reg;
+}
+
+/* all-mode ops */
+
+PUBLIC void mall()
+{
+ if (sym == IMMEDIATE)
+ mimmed();
+ else
+ malter();
+}
+
+/* alterable mode ops */
+
+PUBLIC void malter()
+{
+ postb = 0x0; /* not yet indexed or indirect */
+ doaltind();
+}
+
+/* indexed mode ops */
+
+PUBLIC void mindex()
+{
+ postb = INDEXBIT; /* indexed but not yet indirect */
+ doaltind();
+}
+
+/* immediate ops */
+
+PUBLIC void mimmed()
+{
+ opcode_t nybble;
+
+ mcount += 0x2;
+ if (sym != IMMEDIATE)
+ error(ILLMOD);
+ else
+ {
+ if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 ||
+ nybble == 0xC || nybble >= 0xE))
+ ++mcount; /* magic for long immediate */
+ symexpres();
+ if (pass2 && mcount <= 0x2)
+ {
+ chkabs();
+ checkdatabounds();
+ }
+ }
+}
+
+/* long branches */
+
+PUBLIC void mlong()
+{
+ mcount += 0x3; /* may be 0x0 or 0x1 here */
+ expres();
+ if (pass2)
+ {
+ reldata();
+ if (!(lastexp.data & (RELBIT | UNDBIT)))
+ {
+ lastexp.offset = lastexp.offset - lc - lcjump;
+ if (!(lastexp.data & IMPBIT) &&
+ lastexp.offset + 0x81 < 0x101)
+ error(SHORTB); /* -0x81 to 0x7F, warning */
+ }
+ }
+}
+
+/* PSHS and PULS */
+
+PUBLIC void msstak()
+{
+ sustack(SREG);
+}
+
+/* TFR and EXG */
+
+PUBLIC void mswap()
+{
+ reg_pt reg;
+
+ mcount = 0x2;
+ if ((reg = regchk()) == NOREG)
+ error(REGEXP);
+ else
+ {
+ postb = tfrexg1[reg];
+ getsym();
+ if (sym != COMMA)
+ error(COMEXP);
+ else
+ {
+ getsym();
+ if ((reg = regchk()) == NOREG)
+ error(REGEXP);
+ else if ((postb |= tfrexg2[reg])
+ & 0x88 && (postb & 0x88) != 0x88)
+ error(ILLREG); /* registers not of same size */
+ }
+ }
+}
+
+/* PSHU and PULU */
+
+PUBLIC void mustak()
+{
+ sustack(UREG);
+}
+
+PRIVATE void predec1()
+{
+ if (postb & INDIRECTBIT)
+ inderror(ILLMOD); /* single-dec indirect illegal */
+ else
+ {
+ postb |= 0x82;
+ getindexnopost();
+ }
+}
+
+/* common routine for PSHS/PULS/PSHU/PULU */
+
+PRIVATE void sustack(stackreg)
+reg_pt stackreg;
+{
+ reg_pt reg;
+
+ mcount = 0x2;
+ while ((reg = regchk()) != NOREG)
+ {
+ if (reg == stackreg)
+ {
+ error(ILLREG); /* cannot stack self */
+ break;
+ }
+ postb |= pushpull[reg];
+ getsym();
+ if (sym != COMMA)
+ break;
+ getsym();
+ }
+}
+
+#endif /* MC6809 */
+
+/* routines common to all processors */
+
+PUBLIC void getcomma()
+{
+ if (sym != COMMA)
+ error(COMEXP);
+ else
+ getsym();
+}
+
+/* inherent ops */
+
+/* for I80386 */
+/* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */
+/* INVD, */
+/* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */
+/* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */
+
+PUBLIC void minher()
+{
+ ++mcount;
+}
+
+/* short branches */
+
+PUBLIC void mshort()
+{
+ nonimpexpres();
+ mshort2();
+}
+
+PRIVATE void mshort2()
+{
+ mcount += 0x2;
+ if (pass2)
+ {
+ reldata();
+ if (lastexp.data & RELBIT)
+ showrelbad();
+ else if (!(lastexp.data & UNDBIT))
+ {
+ lastexp.offset = lastexp.offset - lc - mcount;
+ if (!is8bitsignedoffset(lastexp.offset))
+ error(ABOUNDS);
+ }
+ }
+}
+
+/* check if current symbol is a register, return register number or NOREG */
+
+PRIVATE reg_pt regchk()
+{
+ register struct sym_s *symptr;
+
+ if (sym == IDENT)
+ {
+ if ((symptr = gsymptr)->type & MNREGBIT)
+ {
+ if (symptr->data & REGBIT)
+ {
+#ifdef I80386
+ if (symptr->value_reg_or_op.reg == ST0REG && !fpreg_allowed)
+ error(FP_REG_NOT_ALLOWED);
+#endif
+ return symptr->value_reg_or_op.reg;
+ }
+ }
+ else if (!(symptr->type & (LABIT | MACBIT | VARBIT)))
+ symptr->data |= FORBIT; /* show seen in advance */
+ }
+ return NOREG;
+}
+
+/* convert lastexp.data for PC relative */
+
+PRIVATE void reldata()
+{
+ if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM))
+ {
+ if ((lastexp.data ^ lcdata) & RELBIT)
+ showrelbad(); /* rel - abs is weird, abs - rel is bad */
+ else
+ {
+ pcrflag = OBJ_R_MASK;
+ lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT;
+ /* segment is that of lastexp.data */
+ }
+ }
+ else /* same file, segment and relocation */
+ lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM);
+}
diff --git a/as/obj1/calljmp.obj b/as/obj1/calljmp.obj
new file mode 100644
index 0000000..522d6f7
--- /dev/null
+++ b/as/obj1/calljmp.obj
Binary files differ
diff --git a/as/obj1/ea.obj b/as/obj1/ea.obj
new file mode 100644
index 0000000..6b53beb
--- /dev/null
+++ b/as/obj1/ea.obj
Binary files differ
diff --git a/as/obj1/each.obj b/as/obj1/each.obj
new file mode 100644
index 0000000..5426253
--- /dev/null
+++ b/as/obj1/each.obj
Binary files differ
diff --git a/as/obj1/f.obj b/as/obj1/f.obj
new file mode 100644
index 0000000..4dbe2d9
--- /dev/null
+++ b/as/obj1/f.obj
Binary files differ
diff --git a/as/obj1/fadd.obj b/as/obj1/fadd.obj
new file mode 100644
index 0000000..28b3dd4
--- /dev/null
+++ b/as/obj1/fadd.obj
Binary files differ
diff --git a/as/obj1/farcall.obj b/as/obj1/farcall.obj
new file mode 100644
index 0000000..259703c
--- /dev/null
+++ b/as/obj1/farcall.obj
Binary files differ
diff --git a/as/obj1/group1.obj b/as/obj1/group1.obj
new file mode 100644
index 0000000..26d4a8c
--- /dev/null
+++ b/as/obj1/group1.obj
Binary files differ
diff --git a/as/obj1/group6.obj b/as/obj1/group6.obj
new file mode 100644
index 0000000..27e81ae
--- /dev/null
+++ b/as/obj1/group6.obj
Binary files differ
diff --git a/as/obj1/group7.obj b/as/obj1/group7.obj
new file mode 100644
index 0000000..37af051
--- /dev/null
+++ b/as/obj1/group7.obj
Binary files differ
diff --git a/as/obj1/imul.obj b/as/obj1/imul.obj
new file mode 100644
index 0000000..34ef370
--- /dev/null
+++ b/as/obj1/imul.obj
Binary files differ
diff --git a/as/obj1/incdec.obj b/as/obj1/incdec.obj
new file mode 100644
index 0000000..03f583a
--- /dev/null
+++ b/as/obj1/incdec.obj
Binary files differ
diff --git a/as/obj1/inher.obj b/as/obj1/inher.obj
new file mode 100644
index 0000000..aaea0b9
--- /dev/null
+++ b/as/obj1/inher.obj
Binary files differ
diff --git a/as/obj1/inout.obj b/as/obj1/inout.obj
new file mode 100644
index 0000000..58aa820
--- /dev/null
+++ b/as/obj1/inout.obj
Binary files differ
diff --git a/as/obj1/movspec.obj b/as/obj1/movspec.obj
new file mode 100644
index 0000000..15eab78
--- /dev/null
+++ b/as/obj1/movspec.obj
Binary files differ
diff --git a/as/obj1/pushpop.obj b/as/obj1/pushpop.obj
new file mode 100644
index 0000000..2ff789e
--- /dev/null
+++ b/as/obj1/pushpop.obj
Binary files differ
diff --git a/as/obj1/seg.obj b/as/obj1/seg.obj
new file mode 100644
index 0000000..2ba948c
--- /dev/null
+++ b/as/obj1/seg.obj
Binary files differ
diff --git a/as/obj1/shdouble.obj b/as/obj1/shdouble.obj
new file mode 100644
index 0000000..ab75750
--- /dev/null
+++ b/as/obj1/shdouble.obj
Binary files differ
diff --git a/as/obj1/shift.obj b/as/obj1/shift.obj
new file mode 100644
index 0000000..520be81
--- /dev/null
+++ b/as/obj1/shift.obj
Binary files differ
diff --git a/as/obj1/xchg.obj b/as/obj1/xchg.obj
new file mode 100644
index 0000000..c39b703
--- /dev/null
+++ b/as/obj1/xchg.obj
Binary files differ
diff --git a/as/opcode.h b/as/opcode.h
new file mode 100644
index 0000000..385c096
--- /dev/null
+++ b/as/opcode.h
@@ -0,0 +1,157 @@
+/* opcode.h - routine numbers and special opcodes for assembler */
+
+enum
+{
+/* Pseudo-op routine numbers.
+ * Conditionals are first - this is used to test if op is a conditional.
+ */
+ ELSEOP,
+ ELSEIFOP,
+ ELSEIFCOP,
+ ENDIFOP,
+ IFOP,
+ IFCOP,
+
+#define MIN_NONCOND ALIGNOP
+ ALIGNOP,
+ ASCIZOP,
+ BLKWOP,
+ BLOCKOP,
+ BSSOP,
+ COMMOP,
+ COMMOP1,
+ DATAOP,
+ ENDBOP,
+ ENTEROP,
+ ENTRYOP,
+ EQUOP,
+ EVENOP,
+ EXPORTOP,
+ FAILOP,
+ FCBOP,
+ FCCOP,
+ FDBOP,
+ FQBOP,
+ GETOP,
+ GLOBLOP,
+ IDENTOP,
+ IMPORTOP,
+ LCOMMOP,
+ LCOMMOP1,
+ LISTOP,
+ LOCOP,
+ MACLISTOP,
+ MACROOP,
+ MAPOP,
+ ORGOP,
+ PROCEOFOP,
+ RMBOP,
+ SECTOP,
+ SETOP,
+ SETDPOP,
+ TEXTOP,
+#ifdef I80386
+ USE16OP,
+ USE32OP,
+#endif
+ WARNOP,
+
+/* Machine-op routine numbers. */
+#ifdef I80386
+ BCC,
+ BSWAP,
+ CALL,
+ CALLI,
+ DIVMUL,
+ ENTER,
+ EwGw,
+ ExGx,
+ F_INHER,
+ F_M,
+ F_M2,
+ F_M2_AX,
+ F_M2_M4,
+ F_M2_M4_M8,
+ F_M4_M8_OPTST,
+ F_M4_M8_ST,
+ F_M4_M8_STST,
+ F_M4_M8_M10_ST,
+ F_M10,
+ F_OPTST,
+ F_ST,
+ F_STST,
+ F_W_INHER,
+ F_W_M,
+ F_W_M2,
+ F_W_M2_AX,
+ GROUP1,
+ GROUP2,
+ GROUP6,
+ GROUP7,
+ GROUP8,
+ GvEv,
+ GvMa,
+ GvMp,
+ IMUL,
+ IN,
+ INCDEC,
+ INHER,
+ INHER16,
+ INHER32,
+ INHER_A,
+ INT,
+ JCC,
+ JCXZ,
+ LEA,
+ MOV,
+ MOVX,
+ NEGNOT,
+ OUT,
+ PUSHPOP,
+ RET,
+ SEG,
+ SETCC,
+ SH_DOUBLE,
+ TEST,
+ XCHG
+#endif /* I80386 */
+
+#ifdef MC6809
+ ALL, /* all address modes allowed, like LDA */
+ ALTER, /* all but immediate, like STA */
+ IMMED, /* immediate only (ANDCC, ORCC) */
+ INDEXD, /* indexed (LEA's) */
+ INHER, /* inherent, like CLC or CLRA */
+ LONG, /* long branches */
+ SHORT, /* short branches */
+ SSTAK, /* S-stack (PSHS, PULS) */
+ SWAP, /* TFR, EXG */
+ USTAK /* U-stack (PSHU,PULU) */
+#endif /* MC6809 */
+};
+
+/* Special opcodes. */
+#ifdef I80386
+# define CMP_OPCODE_BASE 0x38
+# define CMPSB_OPCODE 0xA6
+# define CMPSW_OPCODE 0xA7
+# define ESCAPE_OPCODE_BASE 0xD8
+# define FST_ENCODED 0x12
+# define FSTP_ENCODED 0x13
+# define JMP_OPCODE 0xE9
+# define JMP_SHORT_OPCODE 0xEB
+# define JSR_OPCODE 0xE8
+# define MOVSB_OPCODE 0xA4
+# define MOVSW_OPCODE 0xA5
+# define PAGE1_OPCODE 0x0F
+# define POP_OPCODE 0x8F
+# define PUSH_OPCODE 0xFF
+# define WAIT_OPCODE 0x9B
+#endif
+
+#ifdef MC6809
+# define JMP_OPCODE 0x7E
+# define JSR_OPCODE 0xBD
+# define PAGE1_OPCODE 0x10
+# define PAGE2_OPCODE 0x11
+#endif
diff --git a/as/pops.c b/as/pops.c
new file mode 100644
index 0000000..aca4841
--- /dev/null
+++ b/as/pops.c
@@ -0,0 +1,1048 @@
+/* pops.c - handle pseudo-ops for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "flag.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+
+PRIVATE bool_t elseflag; /* set if ELSE/ELSEIF are enabled */
+ /* depends on zero = FALSE init */
+PRIVATE bool_t lcommflag;
+
+FORWARD void bumpsem P((struct flags_s *flagptr));
+FORWARD void constdata P((unsigned size));
+FORWARD void docomm P((void));
+FORWARD void doelseif P((pfv func));
+FORWARD void doequset P((int labits));
+FORWARD void doentexp P((int entbits, int impbits));
+FORWARD void dofcc P((void));
+FORWARD void doif P((pfv func));
+FORWARD struct sym_s *needlabel P((void));
+FORWARD void showredefinedlabel P((void));
+FORWARD void setloc P((unsigned seg));
+
+PRIVATE void bumpsem(flagptr)
+register struct flags_s *flagptr;
+{
+ int newcount;
+
+ if (flagptr->global &&pass != 0)
+ {
+ /* bump semaphore count by an expression (default 1), */
+ /* then set currentflag iff semaphore count is plus */
+ if (sym == EOLSYM)
+ lastexp.offset = 1;
+ else
+ {
+ absexpres();
+ if (lastexp.data & UNDBIT)
+ return;
+ }
+ newcount = (int) lastexp.offset;
+#ifdef I80386 /* really sizeof (offset_t) != sizeof (int) */
+ if (newcount != lastexp.offset)
+ datatoobig();
+#endif
+ newcount += flagptr->semaphore;
+ if ((int) lastexp.offset >= 0)
+ {
+ if (newcount < flagptr->semaphore)
+ {
+ error(COUNTOV);
+ newcount = 0x7fff;
+ }
+ }
+ else if (newcount >= flagptr->semaphore)
+ {
+ error(COUNTUN);
+ newcount = -0x8000;
+ }
+ flagptr->semaphore = newcount;
+ flagptr->current = newcount >= 0;
+ }
+}
+
+/* check symbol is either undefined */
+/* or has the same segment & relocatability as lc */
+
+PUBLIC bool_pt checksegrel(symptr)
+register struct sym_s *symptr;
+{
+ if ((symptr->type & LABIT ||
+ symptr->data & IMPBIT && !(symptr->data & UNDBIT)) &&
+ ((symptr->data ^ lcdata) & (RELBIT | SEGM)))
+ {
+ error(SEGREL);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* check address fits in 1 byte (possibly with sign truncated) */
+
+PUBLIC void checkdatabounds()
+{
+ if (!(lastexp.data & UNDBIT) &&
+ (offset_t) (lastexp.offset + 0x80) >= 0x180)
+ datatoobig();
+}
+
+/* allocate constant data (zero except for size 1), default zero for size 1 */
+
+PRIVATE void constdata(size)
+unsigned size;
+{
+ offset_t remaining;
+
+ absexpres();
+ if (!((lcdata |= lastexp.data) & UNDBIT))
+ {
+ lcjump = lastexp.offset * size;
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ if (size == 1 && sym == COMMA)
+ {
+ symabsexpres();
+ checkdatabounds();
+ for (remaining = lcjump; remaining != 0; --remaining)
+ {
+ putbin((opcode_pt) lastexp.offset); /* fill byte */
+ putabs((opcode_pt) lastexp.offset);
+ }
+ lastexp.offset = lcjump;
+ }
+ else
+ accumulate_rmb(lastexp.offset * size);
+ }
+}
+
+PUBLIC void datatoobig()
+{
+ error(DBOUNDS);
+}
+
+/* common routine for COMM/.COMM */
+
+PRIVATE void docomm()
+{
+ register struct sym_s *labptr;
+
+ absexpres(); /* if undefined, value 0 and size unchanged */
+ labptr = label;
+ if (checksegrel(labptr))
+ {
+ if (labptr->type & (EXPBIT | LABIT))
+ labelerror(ALREADY);
+ else
+ {
+ if (!(labptr->type & COMMBIT) ||
+ lastexp.offset > labptr->value_reg_or_op.value)
+ labptr->value_reg_or_op.value = lastexp.offset;
+ labptr->type |= COMMBIT;
+ if (lcommflag)
+ labptr->type |= REDBIT; /* kludge - COMMBIT | REDBIT => SA */
+ labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT);
+ showlabel();
+ }
+ }
+ lcommflag = FALSE;
+}
+
+/* common routine for ELSEIF/ELSEIFC */
+
+PRIVATE void doelseif(func)
+pfv func;
+{
+ if (iflevel == 0)
+ error(ELSEIFBAD);
+ else
+ {
+ ifflag = FALSE;
+ if (elseflag)
+ {
+ (*func) ();
+ if (!(lastexp.data & UNDBIT) && lastexp.offset != 0)
+ /* expression valid and TRUE, enable assembling */
+ {
+ ifflag = TRUE;
+ elseflag = FALSE;
+ }
+ }
+ }
+}
+
+/* common routine for EQU/SET */
+
+PRIVATE void doequset(labits)
+unsigned char labits;
+{
+ register struct sym_s *labptr;
+ unsigned char olddata;
+ unsigned char oldtype;
+
+ labptr = label;
+ /* set up new label flags in case labe isl used in expression */
+ labptr->type = (oldtype = labptr->type) | labits;
+ labptr->data = (olddata = labptr->data) & ~IMPBIT;
+ /* non-imported now */
+ nonimpexpres();
+ lastexp.data |= olddata & FORBIT; /* take all but FORBIT from
+ expression */
+ if (oldtype & LABIT && !(olddata & UNDBIT))
+ /* this is a previously defined label */
+
+ /*
+ redefinition only allowed if same relocatability, segment and
+ value
+ */
+ {
+ if ((olddata ^ lastexp.data) & (RELBIT | UNDBIT) ||
+ labptr->value_reg_or_op.value != lastexp.offset)
+ {
+ showredefinedlabel();
+ return;
+ }
+ }
+ labptr->data = lastexp.data;
+ labptr->value_reg_or_op.value = lastexp.offset;
+ showlabel();
+}
+
+/* common routine for ENTRY/EXPORT */
+
+PRIVATE void doentexp(entbits, impbits)
+unsigned char entbits;
+unsigned char impbits;
+{
+ struct sym_s *symptr;
+
+ while (TRUE)
+ {
+ if ((symptr = needlabel()) != NULL)
+ {
+ if (symptr->type & COMMBIT)
+ error(ALREADY);
+ else if (impbits != 0)
+ {
+ if (pass != 0)
+ ;
+ else if (symptr->type & (EXPBIT | LABIT))
+ symptr->type |= EXPBIT;
+ else
+ {
+ symptr->type |= REDBIT;
+ if (!(symptr->data & IMPBIT))
+ symptr->data |= IMPBIT | SEGM;
+ }
+ }
+ else
+ {
+ if (pass != 0)
+ {
+ if (!(symptr->type & LABIT))
+ error(UNLAB);
+ }
+ else
+ {
+ symptr->type |= entbits | EXPBIT;
+ symptr->data &= ~IMPBIT;
+ }
+ }
+ }
+ getsym();
+ if (sym != COMMA)
+ break;
+ getsym();
+ }
+}
+
+/* common routine for FCC (== .ASCII) and .ASCIZ */
+
+PRIVATE void dofcc()
+{
+ register char *bufptr;
+ char byte;
+ char delimiter;
+ register char *reglineptr;
+
+ bufptr = databuf.fcbuf;
+ reglineptr = symname;
+ if ((delimiter = *reglineptr) != EOLCHAR)
+ ++reglineptr;
+ while (TRUE)
+ {
+ if ((byte = *reglineptr) == EOLCHAR)
+ {
+ symname = reglineptr;
+ error(DELEXP);
+ break;
+ }
+ if (byte == delimiter)
+ {
+ if ((byte = *++reglineptr) != delimiter)
+ break;
+ }
+ else if (byte == '\\')
+ {
+ switch (byte = *++reglineptr)
+ {
+ case '"':
+ case '\'':
+ case '\\':
+ case '?':
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ byte -= '0';
+ if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8')
+ {
+ byte = 8 * byte + *++reglineptr - '0';
+ if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8')
+ byte = 8 * byte + *++reglineptr - '0';
+ }
+ break;
+ case 'a':
+ byte = 7;
+ break;
+ case 'b':
+ byte = 8;
+ break;
+ case 'f':
+ byte = 12;
+ break;
+ case 'n':
+ byte = 10;
+ break;
+ case 'r':
+ byte = 13;
+ break;
+ case 't':
+ byte = 9;
+ break;
+ case 'v':
+ byte = 11;
+ break;
+ case 'x':
+ byte = '0';
+ while (TRUE)
+ {
+ ++reglineptr;
+ if (*reglineptr >= '0' && *reglineptr <= '9')
+ byte = 16 * byte + *reglineptr - '0';
+ else if (*reglineptr >= 'F' && *reglineptr <= 'F')
+ byte = 16 * byte + *reglineptr - 'A';
+ else if (*reglineptr >= 'a' && *reglineptr <= 'f')
+ byte = 16 * byte + *reglineptr - 'F';
+ else
+ break;
+ }
+ --reglineptr;
+ break;
+ default:
+ symname = reglineptr;
+ error(UNKNOWN_ESCAPE_SEQUENCE);
+ break;
+ }
+ }
+ else if (byte < ' ' && byte >= 0)
+ {
+ symname = reglineptr;
+ error(CTLINS);
+ byte = ' ';
+ }
+ ++reglineptr;
+ *bufptr++ = byte;
+ }
+ lineptr = reglineptr;
+ getsym();
+ lastexp.offset = databuf.fcbuf[0]; /* show only 1st char (if any) */
+ mcount = bufptr - databuf.fcbuf;
+ /* won't overflow, line length limits it */
+ /* XXX - but now line length is unlimited */
+}
+
+/* common routine for IF/IFC */
+
+PRIVATE void doif(func)
+pfv func;
+{
+ if (iflevel >= MAXIF)
+ error(IFOV);
+ else
+ {
+ ++iflevel;
+ --ifstak;
+ ifstak->elseflag = elseflag;
+ elseflag = FALSE; /* prepare */
+ if ((ifstak->ifflag = ifflag) != FALSE)
+ /* else not assembling before, so not now & no ELSE's */
+ {
+ (*func) ();
+ if (!(lastexp.data & UNDBIT) && lastexp.offset == 0)
+ /* else expression invalid or FALSE, don't change flags */
+ {
+ ifflag = FALSE; /* not assembling */
+ elseflag = TRUE;/* but ELSE will change that */
+ }
+ }
+ }
+}
+
+PUBLIC void fatalerror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ skipline();
+ listline();
+ finishup();
+}
+
+/* swap position with label position, do error, put back posn */
+/* also clear label ptr */
+
+PUBLIC void labelerror(errnum)
+error_pt errnum;
+{
+ struct sym_s *oldgsymptr;
+ char *oldlineptr;
+ unsigned char oldsym;
+ char *oldsymname;
+
+ oldgsymptr = gsymptr;
+ oldlineptr = lineptr;
+ oldsym = sym;
+ oldsymname = symname;
+ lineptr = linebuf;
+ getsym(); /* 1st symbol is label or symbol after
+ * missing one */
+ error(errnum);
+ gsymptr = oldgsymptr;
+ lineptr = oldlineptr;
+ sym = oldsym;
+ symname = oldsymname;
+ label = NULL;
+}
+
+PRIVATE struct sym_s *needlabel()
+{
+ register struct sym_s *symptr;
+
+ if (sym != IDENT ||
+ (symptr = gsymptr)->type & (MACBIT | MNREGBIT | VARBIT))
+ {
+ error(LABEXP);
+ return NULL;
+ }
+ return symptr;
+}
+
+/* .ALIGN pseudo-op */
+
+PUBLIC void palign()
+{
+ absexpres();
+ if (!((lcdata |= lastexp.data) & UNDBIT))
+ {
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ if (lastexp.offset != 0 &&
+ (lcjump = lc % lastexp.offset) != 0)
+ accumulate_rmb(lcjump = lastexp.offset - lcjump);
+ }
+}
+
+/* .ASCIZ pseudo-op */
+
+PUBLIC void pasciz()
+{
+ dofcc();
+ databuf.fcbuf[mcount++] = 0;
+ fcflag = TRUE;
+ popflags = POPLO | POPLC;
+}
+
+/* .BLKW pseudo-op */
+
+PUBLIC void pblkw()
+{
+ constdata(2);
+}
+
+/* BLOCK pseudo-op */
+
+PUBLIC void pblock()
+{
+ if (blocklevel >= MAXBLOCK)
+ error(BLOCKOV);
+ else
+ {
+ register struct block_s *blockp;
+
+ ++blocklevel;
+ blockp = blockstak;
+ blockstak = --blockp;
+ blockp->data = lcdata;
+ blockp->dp = dirpag;
+ blockp->lc = lc;
+ porg(); /* same as ORG apart from stacking */
+ }
+}
+
+/* .BSS pseudo-op */
+
+PUBLIC void pbss()
+{
+ setloc(BSSLOC);
+}
+
+/* COMM pseudo-op */
+
+PUBLIC void pcomm()
+{
+ if (label == NULL)
+ labelerror(MISLAB);
+ else if (label->type & VARBIT)
+ labelerror(VARLAB); /* variable cannot be COMM'd */
+ else
+ docomm();
+}
+
+/* .COMM pseudo-op */
+
+PUBLIC void pcomm1()
+{
+ unsigned oldseg;
+
+ if (label != NULL)
+ labelerror(ILLAB);
+ oldseg = lcdata & SEGM;
+ setloc(BSSLOC);
+ if ((label = needlabel()) != NULL && checksegrel(label))
+ {
+ /* Like import. */
+ if (label->type & (EXPBIT | LABIT))
+ error(ALREADY);
+ else
+ label->data = lcdata | (FORBIT | IMPBIT | RELBIT);
+ getsym();
+ getcomma();
+ if (label->type & (EXPBIT | LABIT))
+ absexpres(); /* just to check it */
+ else
+ docomm();
+ }
+ setloc(oldseg);
+}
+
+/* .DATA pseudo-op */
+
+PUBLIC void pdata()
+{
+ setloc(DATALOC);
+}
+
+/* ELSE pseudo-op */
+
+PUBLIC void pelse()
+{
+ if (iflevel == 0)
+ error(ELSEBAD);
+ else
+ {
+ ifflag = FALSE; /* assume ELSE disabled */
+ if (elseflag)
+ {
+ ifflag = TRUE; /* ELSE enabled */
+ elseflag = FALSE;
+ }
+ }
+}
+
+/* ELSEIF pseudo-op */
+
+PUBLIC void pelseif()
+{
+ doelseif(absexpres);
+}
+
+/* ELSEIFC pseudo-op */
+
+PUBLIC void pelsifc()
+{
+ doelseif(scompare);
+}
+
+/* ENDB pseudo-op */
+
+PUBLIC void pendb()
+{
+ if (label != NULL)
+ labelerror(ILLAB);
+ if (blocklevel == 0)
+ error(ENDBBAD);
+ else
+ {
+ register struct block_s *blockp;
+
+ blockp = blockstak;
+ lcdata = blockp->data;
+ dirpag = blockp->dp;
+ accumulate_rmb(blockp->lc - lc);
+ lc = blockp->lc;
+ --blocklevel;
+ blockstak = blockp + 1;
+ }
+}
+
+/* ENDIF pseudo-op */
+
+PUBLIC void pendif()
+{
+ if (iflevel == 0)
+ error(ENDIFBAD);
+ else
+ {
+ ifflag = ifstak->ifflag;
+ elseflag = ifstak->elseflag;
+ ++ifstak;
+ --iflevel;
+ }
+}
+
+/* ENTER pseudo-op */
+
+PUBLIC void penter()
+{
+ if (!(pedata & UNDBIT))
+ error(REENTER);
+ else
+ {
+ if (!((pedata = (pedata & ~UNDBIT) | lcdata) & UNDBIT))
+ {
+ progent = lc;
+ popflags = POPLC;
+ }
+ }
+}
+
+/* ENTRY pseudo-op */
+
+PUBLIC void pentry()
+{
+ doentexp(ENTBIT, 0);
+}
+
+/* EQU pseudo-op */
+
+PUBLIC void pequ()
+{
+ register struct sym_s *labptr;
+
+ if ((labptr = label) == NULL)
+ labelerror(MISLAB);
+ else if (labptr->type & COMMBIT)
+ showredefinedlabel(); /* common cannot be EQU'd */
+ else if (labptr->type & VARBIT)
+ labelerror(VARLAB); /* variable cannot be EQU'd */
+ else
+ doequset(LABIT);
+}
+
+/* .EVEN pseudo-op */
+
+PUBLIC void peven()
+{
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ accumulate_rmb(lcjump = lastexp.data = lc & 1);
+}
+
+/* EXPORT pseudo-op */
+
+PUBLIC void pexport()
+{
+ doentexp(0, 0);
+}
+
+/* FAIL pseudo-op */
+
+PUBLIC void pfail()
+{
+ error(FAILERR);
+}
+
+/* FCB pseudo-op */
+
+PUBLIC void pfcb()
+{
+ char *bufptr;
+ offset_t firstbyte;
+
+ bufptr = databuf.fcbuf;
+ absexpres();
+ firstbyte = lastexp.offset;
+ while (TRUE)
+ {
+ checkdatabounds();
+ *bufptr++ = lastexp.offset;
+ ++mcount; /* won't overflow, line length limits it */
+ if (sym != COMMA)
+ break;
+ symabsexpres();
+ }
+ lastexp.offset = firstbyte;
+ popflags = POPLO | POPLC;
+ fcflag = TRUE;
+}
+
+/* FCC pseudo-op */
+
+PUBLIC void pfcc()
+{
+ dofcc();
+ if (mcount != 0)
+ {
+ fcflag = TRUE;
+ popflags = POPLO | POPLC;
+ }
+}
+
+/* FDB pseudo-op */
+
+PUBLIC void pfdb()
+{
+ struct address_s *adrptr;
+ unsigned firstdata;
+ offset_t firstword;
+
+ adrptr = databuf.fdbuf;
+ expres();
+ firstword = lastexp.offset;
+ firstdata = lastexp.data;
+ while (TRUE)
+ {
+ *adrptr++ = lastexp;
+ mcount += 2; /* won't overflow, line length limits it */
+ if (sym != COMMA)
+ break;
+ symexpres();
+ }
+ lastexp.offset = firstword;
+ lastexp.data = firstdata;
+ popflags = POPHI | POPLO | POPLC;
+ fdflag = TRUE;
+}
+
+#if SIZEOF_OFFSET_T > 2
+
+/* FQB pseudo-op */
+
+PUBLIC void pfqb()
+{
+ struct address_s *adrptr;
+ offset_t firstdata;
+ offset_t firstword;
+
+ adrptr = databuf.fqbuf;
+ expres();
+ firstword = lastexp.offset;
+ firstdata = lastexp.data;
+ while (TRUE)
+ {
+ *adrptr++ = lastexp;
+ mcount += 4; /* won't overflow, line length limits it */
+ if (sym != COMMA)
+ break;
+ symexpres();
+ }
+ lastexp.offset = firstword;
+ lastexp.data = firstdata;
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ fqflag = TRUE;
+}
+
+#endif /* SIZEOF_OFFSET_T > 2 */
+
+/* .GLOBL pseudo-op */
+
+PUBLIC void pglobl()
+{
+ if (binaryg)
+ error(NOIMPORT);
+ doentexp(0, IMPBIT);
+}
+
+/* IDENT pseudo-op (not complete) */
+
+PUBLIC void pident()
+{
+ if (sym != IDENT)
+ error(LABEXP);
+ else
+ getsym_nolookup(); /* should save ident string */
+}
+
+/* IF pseudo-op */
+
+PUBLIC void pif()
+{
+ doif(absexpres);
+}
+
+/* IFC pseudo-op */
+
+PUBLIC void pifc()
+{
+ doif(scompare);
+}
+
+/* IMPORT pseudo-op */
+
+PUBLIC void pimport()
+{
+ struct sym_s *symptr;
+
+ if (binaryg)
+ error(NOIMPORT);
+ while (TRUE)
+ {
+ if ((symptr = needlabel()) != NULL && checksegrel(symptr))
+ {
+ if (symptr->type & (COMMBIT | EXPBIT | LABIT))
+ /* IMPORT is null if label (to be) declared */
+ error(ALREADY);
+ else
+ /* get current segment from lcdata, no need to mask rest */
+ symptr->data = lcdata | (FORBIT | IMPBIT | RELBIT);
+ }
+ getsym();
+ if (sym != COMMA)
+ break;
+ getsym();
+ }
+}
+
+/* LCOMM pseudo-op */
+
+PUBLIC void plcomm()
+{
+ lcommflag = TRUE;
+ pcomm();
+}
+
+/* .LCOMM pseudo-op */
+
+PUBLIC void plcomm1()
+{
+ lcommflag = TRUE;
+ pcomm1();
+}
+
+/* .LIST pseudo-op */
+
+PUBLIC void plist()
+{
+ bumpsem(&list);
+}
+
+/* LOC pseudo-op */
+
+PUBLIC void ploc()
+{
+ if (label != NULL)
+ labelerror(ILLAB);
+ absexpres();
+ if (!(lastexp.data & UNDBIT))
+ {
+ if (lastexp.offset >= NLOC)
+ datatoobig();
+ else
+ setloc((unsigned) lastexp.offset);
+ }
+}
+
+/* .MACLIST pseudo-op */
+
+PUBLIC void pmaclist()
+{
+ bumpsem(&maclist);
+}
+
+/* .MAP pseudo-op */
+
+PUBLIC void pmap()
+{
+ absexpres();
+ if (!(lastexp.data & UNDBIT))
+ {
+ mapnum = lastexp.offset;
+ popflags = POPLO;
+ if (lastexp.offset >= 0x100)
+ datatoobig();
+ }
+}
+
+/* ORG pseudo-op */
+
+PUBLIC void porg()
+{
+ if (label != NULL)
+ labelerror(ILLAB);
+ absexpres();
+ if (!((lcdata = lastexp.data) & UNDBIT))
+ {
+ accumulate_rmb(lastexp.offset - lc);
+ binmbuf = lc = lastexp.offset;
+ popflags = POPLC;
+ }
+}
+
+/* RMB pseudo-op */
+
+PUBLIC void prmb()
+{
+ constdata(1);
+}
+
+/* .SECT pseudo-op */
+
+PUBLIC void psect()
+{
+ if (label != NULL)
+ labelerror(ILLAB);
+ while (sym == IDENT)
+ {
+ if (!(gsymptr->type & MNREGBIT))
+ error(ILL_SECTION);
+ else switch (gsymptr->value_reg_or_op.op.routine)
+ {
+ case BSSOP:
+ pbss();
+ break;
+ case DATAOP:
+ pdata();
+ break;
+ case TEXTOP:
+ ptext();
+ break;
+ default:
+ error(ILL_SECTION);
+ break;
+ }
+ getsym();
+ if (sym == COMMA)
+ getsym();
+ }
+}
+
+/* SET pseudo-op */
+
+PUBLIC void pset()
+{
+ register struct sym_s *labptr;
+
+ if ((labptr = label) == NULL)
+ labelerror(MISLAB);
+ else if (labptr->type & COMMBIT)
+ labelerror(RELAB); /* common cannot be SET'd */
+ else
+ doequset(labptr->type & LABIT ? 0 : VARBIT);
+}
+
+/* SETDP pseudo-op */
+
+PUBLIC void psetdp()
+{
+ absexpres();
+ if (!(lastexp.data & UNDBIT))
+ {
+ dirpag = lastexp.offset;
+ popflags = POPLO;
+ if (lastexp.offset >= 0x100)
+ datatoobig();
+ }
+}
+
+/* .TEXT pseudo-op */
+
+PUBLIC void ptext()
+{
+ setloc(TEXTLOC);
+}
+
+/* .WARN pseudo-op */
+
+PUBLIC void pwarn()
+{
+ bumpsem(&warn);
+}
+
+#ifdef I80386
+
+/* USE16 pseudo-op */
+
+PUBLIC void puse16()
+{
+ defsize = 2;
+}
+
+/* USE16 pseudo-op */
+
+PUBLIC void puse32()
+{
+ defsize = 4;
+}
+
+#endif
+
+/* show redefined label and error, and set REDBIT */
+
+PRIVATE void showredefinedlabel()
+{
+ register struct sym_s *labptr;
+
+ labptr = label; /* showlabel() will kill label prematurely */
+ showlabel();
+ if (!(labptr->type & REDBIT))
+ {
+ labptr->type |= REDBIT;
+ labelerror(RELAB);
+ }
+}
+
+PUBLIC void showlabel()
+{
+ register struct sym_s *labptr;
+
+ labptr = label;
+ lastexp.data = labptr->data;
+ lastexp.offset = labptr->value_reg_or_op.value;
+ popflags = POPLONG | POPHI | POPLO;
+ label = NULL; /* show handled by COMM, EQU or SET */
+}
+
+/* set location segment */
+
+PRIVATE void setloc(seg)
+unsigned seg;
+{
+ if (pass != 0 && seg != (lcdata & SEGM))
+ putobj((opcode_pt) (seg | OBJ_SET_SEG));
+ {
+ register struct lc_s *lcp;
+
+ lcp = lcptr;
+ lcp->data = lcdata;
+ lcp->lc = lc;
+ lcptr = lcp = lctab + (unsigned char) seg;
+ lcdata = (lcp->data & ~SEGM) | (unsigned char) seg;
+ binmbuf = lc = lcp->lc;
+ popflags = POPLC;
+ }
+}
diff --git a/as/proto.h b/as/proto.h
new file mode 100644
index 0000000..e348413
--- /dev/null
+++ b/as/proto.h
@@ -0,0 +1,218 @@
+/* extern functions */
+
+#if __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+/* as.c */
+int main P((int argc, char **argv));
+void as_abort P((char *message));
+void finishup P((void));
+void initp1p2 P((void));
+
+/* assemble.c */
+void assemble P((void));
+
+/* error.c */
+char *build_error_message P((error_pt errnum, char *buf));
+
+/* express.c */
+void absexpres P((void));
+void chkabs P((void));
+void nonimpexpres P((void));
+void showrelbad P((void));
+void symabsexpres P((void));
+void symexpres P((void));
+void expres P((void));
+void factor P((void));
+void scompare P((void));
+
+/* genbin.c */
+void binheader P((void));
+void bintrailer P((void));
+void genbin P((void));
+void initbin P((void));
+void putbin P((int ch));
+
+/* genlist.c */
+char *build_2hex_number P((unsigned num, char *where));
+char *build_number P((unsigned num, unsigned width, char *where));
+void error P((error_pt errnum));
+void listline P((void));
+void writec P((int ch));
+void writenl P((void));
+void writeoff P((offset_t offset));
+void writes P((char *s));
+void writesn P((char *s));
+void writew P((unsigned word));
+
+/* genobj.c */
+void accumulate_rmb P((offset_t offset));
+void flushobj P((void));
+void genobj P((void));
+void initobj P((void));
+void objheader P((void));
+void objtrailer P((void));
+void putabs P((opcode_pt ch));
+void putobj P((opcode_pt ch));
+
+/* gensym.c */
+void gensym P((void));
+
+/* macro.c */
+void entermac P((struct sym_s *symptr));
+void pmacro P((void));
+
+/* mops.c */
+#ifdef I80386
+void mbcc P((void));
+void mbswap P((void));
+void mcall P((void));
+void mcalli P((void));
+void mdivmul P((void));
+void menter P((void));
+void mEwGw P((void));
+void mExGx P((void));
+void mf_inher P((void));
+void mf_m P((void));
+void mf_m2 P((void));
+void mf_m2_ax P((void));
+void mf_m2_m4 P((void));
+void mf_m2_m4_m8 P((void));
+void mf_m4_m8_optst P((void));
+void mf_m4_m8_st P((void));
+void mf_m4_m8_stst P((void));
+void mf_m4_m8_m10_st P((void));
+void mf_m10 P((void));
+void mf_optst P((void));
+void mf_st P((void));
+void mf_stst P((void));
+void mf_w_inher P((void));
+void mf_w_m P((void));
+void mf_w_m2 P((void));
+void mf_w_m2_ax P((void));
+void mgroup1 P((void));
+void mgroup2 P((void));
+void mgroup6 P((void));
+void mgroup7 P((void));
+void mgroup8 P((void));
+void mGvEv P((void));
+void mGvMa P((void));
+void mGvMp P((void));
+void mimul P((void));
+void min P((void));
+void mincdec P((void));
+void minher P((void));
+void minher16 P((void));
+void minher32 P((void));
+void minhera P((void));
+void mint P((void));
+void mjcc P((void));
+void mjcxz P((void));
+void mlea P((void));
+void mmov P((void));
+void mmovx P((void));
+void mnegnot P((void));
+void mout P((void));
+void mpushpop P((void));
+void mret P((void));
+void mseg P((void));
+void msetcc P((void));
+void mshdouble P((void));
+void mtest P((void));
+void mxchg P((void));
+#endif /* I80386 */
+
+#ifdef MC6809
+void mall P((void));
+void malter P((void));
+void mimmed P((void));
+void mindex P((void));
+void minher P((void));
+void mlong P((void));
+void msstak P((void));
+void mswap P((void));
+void mustak P((void));
+#endif /* MC6809 */
+
+void getcomma P((void));
+void mshort P((void));
+
+/* pops.c */
+bool_pt checksegrel P((struct sym_s *symptr));
+void checkdatabounds P((void));
+void datatoobig P((void));
+void fatalerror P((error_pt errnum));
+void labelerror P((error_pt errnum));
+void palign P((void));
+void pasciz P((void));
+void pblkw P((void));
+void pblock P((void));
+void pbss P((void));
+void pcomm P((void));
+void pcomm1 P((void));
+void pdata P((void));
+void pelse P((void));
+void pelseif P((void));
+void pelsifc P((void));
+void pendb P((void));
+void pendif P((void));
+void penter P((void));
+void pentry P((void));
+void pequ P((void));
+void peven P((void));
+void pexport P((void));
+void pfail P((void));
+void pfcb P((void));
+void pfcc P((void));
+void pfdb P((void));
+void pfqb P((void));
+void pglobl P((void));
+void pident P((void));
+void pif P((void));
+void pifc P((void));
+void pimport P((void));
+void plcomm P((void));
+void plcomm1 P((void));
+void plist P((void));
+void ploc P((void));
+void pmaclist P((void));
+void pmap P((void));
+void porg P((void));
+void prmb P((void));
+void psect P((void));
+void pset P((void));
+void psetdp P((void));
+void ptext P((void));
+void puse16 P((void));
+void puse32 P((void));
+void pwarn P((void));
+void showlabel P((void));
+
+/* readsrc.c */
+void initsource P((void));
+fd_t open_input P((char *name));
+void pget P((void));
+void pproceof P((void));
+void readline P((void));
+void skipline P((void));
+
+/* scan.c */
+void context_hexconst P((void));
+void getsym P((void));
+void getsym_nolookup P((void));
+void initscan P((void));
+
+/* table.c */
+void inst_keywords P((void));
+struct sym_s *lookup P((void));
+void statistics P((void));
+
+/* type.c */
+void u2c2 P((char *buf, u16_pt offset));
+void u4c4 P((char *buf, u32_T offset));
+void u2cn P((char *buf, u16_pt offset, unsigned count));
+void u4cn P((char *buf, u32_T offset, unsigned count));
+bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian));
diff --git a/as/readsrc.c b/as/readsrc.c
new file mode 100644
index 0000000..39bd063
--- /dev/null
+++ b/as/readsrc.c
@@ -0,0 +1,341 @@
+#define MAXLINE 256 /* when this is made bigger, fix pfcc not
+ * to store the string length in a byte-
+ * sized variable */
+
+/* readsrc.c - read source files for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+#include "macro.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "source.h"
+
+#ifdef POSIX_HEADERS_MISSING
+#define O_RDONLY 0
+typedef long off_t;
+int close P((int fd));
+off_t lseek P((int fd, off_t offset, int whence));
+int open P((const char *path, int oflag, ...));
+int read P((int fd, void *buf, unsigned nbytes));
+#else
+#undef NULL
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+struct fcbstruct /* file control block structure */
+{
+ fd_t fd; /* file descriptor */
+ char *lineptr; /* current spot in line */
+ char *buf; /* start of buffer (after partial line) */
+ char *first; /* start of partial line before buf */
+ char *limit; /* end of used part of input buffer */
+ int blocksize; /* chars from last read and partial line flag */
+ struct fbufstruct *includer;/* buffer of file which included current one */
+};
+
+struct fbufstruct /* file buffer structure */
+{
+ struct fcbstruct fcb; /* status after opening an include sub-file */
+ char fpartline[MAXLINE + 1];/* buffer for partial line */
+ char fbuf[INBUFSIZE + 1]; /* buffer to read into */
+ char fname[1]; /* file name (variable length), 1 for null */
+};
+
+struct get_s /* to record included files */
+{
+ fd_t fd;
+ unsigned line;
+ off_t position;
+};
+
+PRIVATE char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */
+
+PRIVATE struct get_s hid_getstak[MAXGET]; /* GET stack */
+PRIVATE struct get_s *getstak; /* ptr */
+
+PRIVATE struct fcbstruct input; /* current input file control block */
+ /* input.lineptr is not kept up to date */
+ /* input.fd depends on zero init */
+PRIVATE struct fbufstruct xyz;
+PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */
+ /* its fcb only to date in includes */
+
+PRIVATE char hid_linebuf[LINLEN]; /* line buffer */
+PRIVATE char *maclinebuf;
+PRIVATE char *maclineptr;
+
+FORWARD void clearsource P((void));
+FORWARD void line_too_long P((void));
+
+PRIVATE void clearsource()
+{
+ input.includer = inputbuf;
+ inputbuf = &xyz;
+ input.first = input.limit = input.buf = inputbuf->fbuf;
+ *(lineptr = linebuf = input.first - 1) = EOLCHAR;
+ input.blocksize = 0;
+}
+
+PRIVATE void line_too_long()
+{
+ symname = linebuf + (LINLEN - 1); /* spot for the error */
+ error(LINLONG); /* so error is shown in column LINLEN - 1 */
+}
+
+/* initialise private variables */
+
+PUBLIC void initsource()
+{
+ filnamptr = hid_filnambuf;
+ getstak = hid_getstak + MAXGET;
+ clearsource(); /* sentinel to invoke blank skipping */
+}
+
+PUBLIC fd_t open_input(name)
+char *name;
+{
+ fd_t fd;
+
+ if ((unsigned) (fd = open(name, O_RDONLY)) > 255)
+ as_abort("error opening input file");
+ clearsource();
+ return fd;
+}
+
+/*
+ handle GET pseudo_op
+ stack state of current file, open new file and reset global state vars
+ file must be seekable for the buffer discard/restore method to work
+*/
+
+PUBLIC void pget()
+{
+#if OLD
+ if (infiln >= MAXGET)
+ error(GETOV);
+ else
+ {
+ skipline();
+ listline();
+ if (infiln != 0)
+ {
+ --getstak;
+ getstak->fd = infil;
+ getstak->line = linum;
+ getstak->position = lseek(infil, 0L, 1) - (inbufend - inbufptr);
+ ++infiln;
+ linum = 0;
+ infil = open_input(lineptr - 1);
+ }
+ }
+#else
+ as_abort("get/include pseudo-op not implemented");
+#endif
+}
+
+/* process end of file */
+/* close file, unstack old file if current one is included */
+/* otherwise switch pass 0 to pass 1 or exit on pass 2 */
+/* end of file may be from phyical end of file or an END statement */
+
+PUBLIC void pproceof()
+{
+ if (infiln != 0)
+ close(infil);
+ if (lineptr == linebuf)
+ list.current = FALSE; /* don't list line after last unless error */
+ if (infiln == infil0)
+ /* all conditionals must be closed before end of main file (not GETs) */
+ {
+ if (blocklevel != 0)
+ error(EOFBLOCK);
+ if (iflevel != 0)
+ error(EOFIF);
+ if (lcdata & UNDBIT)
+ error(EOFLC);
+ lcptr->data = lcdata;
+ lcptr->lc = lc;
+ }
+ /* macros must be closed before end of all files */
+ if (macload)
+ error(EOFMAC);
+ listline(); /* last line or line after last if error */
+ if (infiln != infil0)
+ {
+ infil = getstak->fd;
+ linum = getstak->line;
+ if (--infiln != 0)
+ lseek(infil, getstak->position, 0);
+ ++getstak;
+ }
+ else if (!pass)
+ {
+ pass = TRUE;
+ objheader(); /* while pass 1 data all valid */
+ binmbuf = 0; /* reset zero variables */
+ maclevel = iflevel = blocklevel =
+ totwarn = toterr = linum = macnum = 0;
+ initp1p2(); /* reset other varaiables */
+ binaryc = binaryg;
+#ifdef I80386
+ defsize = idefsize;
+#endif
+ list.current = list.global;
+ maclist.current = maclist.global;
+
+ warn.current = TRUE;
+ if (warn.semaphore < 0)
+ warn.current = FALSE;
+ if (infiln != 0)
+ infil = open_input(filnamptr);
+ binheader();
+ }
+ else
+ finishup();
+}
+
+/*
+ read 1 line of source.
+ Source line ends with '\n', line returned is null terminated without '\n'.
+ Control characters other than blank, tab and newline are discarded.
+ Long lines (length > LINLEN) are truncated, and an error is generated.
+ On EOF, calls pproceof(), and gets next line unless loading a macro.
+ This is where macro lines are recursively expanded.
+*/
+
+PUBLIC void readline()
+{
+ listpre = FALSE; /* not listed yet */
+ if (maclevel != 0)
+ {
+ register char *bufptr; /* hold *bufptr in a reg char variable */
+ register char *reglineptr; /* if possible (not done here) */
+ char *oldbufptr;
+ struct schain_s *parameters;
+ char paramnum;
+ unsigned char remaining; /* space remaining in line + 2 */
+ /* value 0 not used except for temp predec */
+ /* value 1 means error already gen */
+ /* values 1 and 2 mean no space */
+
+ for (; maclevel != 0;
+ macpar = macstak->parameters, ++macstak, --maclevel)
+ if (*(bufptr = macstak->text) != ETB)
+ /* nonempty macro, process it and return without continuing the for loop */
+ {
+ if (!macflag)
+ {
+ maclinebuf = linebuf;
+ maclineptr = lineptr;
+ macflag = TRUE;
+ }
+ remaining = LINLEN + 2;
+ lineptr = linebuf = reglineptr = hid_linebuf;
+ while (*bufptr++ != EOLCHAR)
+ {
+ if (bufptr[-1] == MACROCHAR && *bufptr >= '0' && *bufptr <= '9')
+ {
+ parameters = macstak->parameters;
+ for (paramnum = *bufptr++; paramnum-- != '0';)
+ if ((parameters = parameters->next) == NULL)
+ break;
+ if (parameters != NULL)
+ {
+ for (oldbufptr = bufptr, bufptr = parameters->string;
+ *bufptr++ != 0;)
+ {
+ if (--remaining <= 1)
+ {
+ if (remaining != 0)
+ line_too_long();
+ remaining = 1;
+ break; /* forget rest, param on 1 line */
+ }
+ *reglineptr++ = bufptr[-1];
+ }
+ bufptr = oldbufptr;
+ }
+ }
+ else
+ {
+ if (--remaining <= 1)
+ {
+ if (remaining != 0)
+ line_too_long();
+ remaining = 1;
+ }
+ else
+ *reglineptr++ = bufptr[-1];
+ }
+ }
+ macstak->text = bufptr;
+ *reglineptr = EOLCHAR;
+ return;
+ }
+ }
+ if (macflag)
+ {
+ linebuf = maclinebuf;
+ lineptr = maclineptr;
+ macflag = FALSE;
+ }
+again:
+ ++linum;
+ ++lineptr; /* if eof, this is input.limit + 1 */
+ if (input.blocksize != 0) /* and this routine just resets eof */
+ {
+ if (lineptr < input.limit) /* move back partial line */
+ {
+ register char *col;
+
+ col = input.buf;
+ while ((*--col = *--input.limit) != EOLCHAR)
+ ;
+ input.first = col + 1;
+ ++input.limit;
+ input.blocksize = 0;
+ }
+ else /* may be non-terminated line, don't stop */
+ lineptr = input.limit;
+ }
+ if (lineptr == input.limit)
+ {
+ lineptr = input.first;
+ input.blocksize = read(infil, input.buf, INBUFSIZE);
+ if (input.blocksize < 0)
+ as_abort("error reading input");
+ if (input.blocksize == 0)
+ {
+ clearsource();
+ pproceof();
+ if (macload)
+ {
+ symname = lineptr;
+ return; /* macro not allowed across eof */
+ }
+ goto again;
+ }
+ input.first = input.buf;
+ *(input.limit = input.buf + input.blocksize) = EOLCHAR;
+ }
+ linebuf = lineptr;
+ if (lineptr >= input.limit)
+ *(lineptr = input.limit = input.buf) = EOLCHAR;
+}
+
+PUBLIC void skipline()
+{
+ register char *reglineptr;
+
+ reglineptr = lineptr - 1;
+ while (*reglineptr != EOLCHAR)
+ ++reglineptr;
+ lineptr = reglineptr;
+}
diff --git a/as/scan.c b/as/scan.c
new file mode 100644
index 0000000..56c6bf3
--- /dev/null
+++ b/as/scan.c
@@ -0,0 +1,247 @@
+/* scan.c - lexical analyser for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#undef EXTERN
+#define EXTERN
+#include "scan.h"
+
+PRIVATE int numbase; /* base for number */
+
+PRIVATE char symofchar[256] = /* table to convert chars to their symbols */
+{
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, EOLSYM, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, EOLSYM, STRINGCONST, IMMEDIATE, /* !"# */
+ HEXCONST, BINCONST, ANDOP, CHARCONST, /* $%&' */
+ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */
+ COMMA, SUBOP, IDENT, SLASH, /* ,-./ */
+
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */
+ INTCONST, INTCONST, COLON, EOLSYM, /* 89:; */
+ LESSTHAN, EQOP, GREATERTHAN, MACROARG, /* <=>? */
+
+ INDIRECT, IDENT, IDENT, IDENT, /* @ABC */
+ IDENT, IDENT, IDENT, IDENT, /* DEFG */
+ IDENT, IDENT, IDENT, IDENT, /* HIJK */
+ IDENT, IDENT, IDENT, IDENT, /* LMNO */
+ IDENT, IDENT, IDENT, IDENT, /* PQRS */
+ IDENT, IDENT, IDENT, IDENT, /* TUVW */
+ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */
+ OTHERSYM, RBRACKET, OTHERSYM, IDENT, /* \]^_ */
+
+ OTHERSYM, IDENT, IDENT, IDENT, /* `abc */
+ IDENT, IDENT, IDENT, IDENT, /* defg */
+ IDENT, IDENT, IDENT, IDENT, /* hijk */
+ IDENT, IDENT, IDENT, IDENT, /* lmno */
+ IDENT, IDENT, IDENT, IDENT, /* pqrs */
+ IDENT, IDENT, IDENT, IDENT, /* tuvw */
+ IDENT, IDENT, IDENT, OTHERSYM, /* xyz{ */
+ OROP, OTHERSYM, NOTOP, OTHERSYM, /* |}~ */
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE
+};
+
+FORWARD void intconst P((void));
+
+PUBLIC void context_hexconst()
+{
+ numbase = 16;
+ intconst();
+}
+
+PUBLIC void getsym()
+{
+ register char *reglineptr;
+
+ reglineptr = lineptr;
+advance:
+ symname = reglineptr;
+ switch (sym = symofchar[(unsigned char) *reglineptr++])
+ {
+ case WHITESPACE:
+ goto advance;
+ case ADDOP:
+ if (*reglineptr == '+')
+ {
+ sym = POSTINCOP;
+ ++reglineptr;
+ }
+ break;
+ case BINCONST:
+ numbase = 2;
+ lineptr = reglineptr;
+ intconst();
+ return;
+ case CHARCONST:
+ if ((number = *reglineptr) < ' ')
+ number = ' ';
+ if (*reglineptr != EOL)
+ ++reglineptr;
+ sym = INTCONST;
+ break;
+ case GREATERTHAN: /* context-sensitive */
+ if (*reglineptr == '>')
+ {
+ sym = SROP;
+ ++reglineptr;
+ }
+ break;
+ case HEXCONST:
+ numbase = 16;
+ lineptr = reglineptr;
+ intconst();
+ return;
+ case IDENT:
+ /* walk to end of identifier - magic INTCONST is max of INT, IDENT */
+ while (symofchar[(unsigned char) *reglineptr] <= INTCONST)
+ ++reglineptr;
+ lineptr = reglineptr;
+ gsymptr = lookup();
+ return;
+ case INTCONST:
+ if (*(reglineptr - 1) == '0')
+ {
+ if (*reglineptr != 'x' && *reglineptr != 'X')
+ numbase = 8;
+ else
+ {
+ numbase = 16;
+ ++reglineptr;
+ }
+ }
+ else
+ {
+ --reglineptr;
+ numbase = 10;
+ }
+ lineptr = reglineptr;
+ intconst();
+ return;
+ case LESSTHAN: /* context-sensitive */
+ if (*reglineptr == '<')
+ {
+ sym = SLOP;
+ ++reglineptr;
+ }
+ break;
+ case SUBOP:
+ if (*reglineptr == '-')
+ {
+ sym = PREDECOP;
+ ++reglineptr;
+ }
+ break;
+ }
+ lineptr = reglineptr;
+ return;
+}
+
+PUBLIC void getsym_nolookup()
+{
+ bool_t old_ifflag;
+
+ old_ifflag = ifflag;
+ ifflag = FALSE;
+ getsym();
+ ifflag = old_ifflag;
+}
+
+PRIVATE void intconst()
+{
+ register char *reglineptr;
+
+ number = 0;
+ reglineptr = lineptr;
+ for (; *reglineptr >= '0'; ++reglineptr)
+ {
+ if (*reglineptr > '9')
+ {
+ if (numbase != 16)
+ break;
+ if (*reglineptr >= 'a' && *reglineptr <= 'f')
+ {
+ if (number != 0)
+ number = numbase * number + (*reglineptr - 'a' + 10);
+ else
+ number = *reglineptr - 'a' + 10;
+ }
+ else if (*reglineptr >= 'A' && *reglineptr <= 'F')
+ {
+ if (number != 0)
+ number = numbase * number + (*reglineptr - 'A' + 10);
+ else
+ number = *reglineptr - 'A' + 10;
+ }
+ else
+ break;
+ }
+ else if (number != 0)
+ number = numbase * number + (*reglineptr - '0');
+ else
+ number = *reglineptr - '0';
+ }
+ if (*reglineptr == 'L' || *reglineptr == 'l')
+ ++reglineptr;
+ sym = INTCONST;
+ lineptr = reglineptr;
+}
+
+PUBLIC void initscan()
+{
+ if (asld_compatible)
+ {
+ lindirect = LPAREN;
+ rindexp = RPEXP;
+ rindirect = RPAREN;
+ }
+ else
+ {
+ lindirect = LBRACKET;
+ rindexp = RBEXP;
+ rindirect = RBRACKET;
+ }
+}
diff --git a/as/scan.h b/as/scan.h
new file mode 100644
index 0000000..22def98
--- /dev/null
+++ b/as/scan.h
@@ -0,0 +1,12 @@
+/* scan.h - global variables for scanner for assembler */
+
+#define EOLCHAR '\n'
+
+EXTERN struct sym_s *gsymptr; /* global symbol ptr */
+EXTERN char lindirect; /* left symbol for indirect addressing */
+EXTERN char *lineptr; /* current line position */
+EXTERN offset_t number; /* constant number */
+EXTERN int rindexp; /* error code for missing rindirect */
+EXTERN char rindirect; /* right symbol for indirect addressing */
+EXTERN char sym; /* current symbol */
+EXTERN char *symname; /* current symbol name */
diff --git a/as/source.h b/as/source.h
new file mode 100644
index 0000000..0181e54
--- /dev/null
+++ b/as/source.h
@@ -0,0 +1,4 @@
+/* source.h - global variables for source handlers for assembler */
+
+EXTERN unsigned linum; /* line # */
+EXTERN bool_t listpre; /* flag to show line has already been listed */
diff --git a/as/table.c b/as/table.c
new file mode 100644
index 0000000..66d9332
--- /dev/null
+++ b/as/table.c
@@ -0,0 +1,945 @@
+/* table.c - keyword tables and symbol table lookup for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+
+#ifdef STDC_HEADERS_MISSING
+int memcmp P((const void *s1, const void *s2, unsigned n));
+#else
+#undef NULL
+#include <string.h>
+#endif
+
+#define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */
+
+#ifdef DEBUG
+unsigned nhash;
+unsigned nlookup;
+unsigned nsym;
+unsigned nx[30];
+FORWARD void printchain P((void));
+#endif
+
+/* --- start of keywords --- */
+
+/* registers */
+/* the register code (internal to assembler) is given in 1 byte */
+/* the "opcode" field is not used */
+
+PUBLIC char regs[] =
+{
+#ifdef I80386
+ 2, 'B', 'P', BPREG, 0,
+ 2, 'B', 'X', BXREG, 0,
+ 2, 'D', 'I', DIREG, 0,
+ 2, 'S', 'I', SIREG, 0,
+
+ 3, 'E', 'A', 'X', EAXREG, 0,
+ 3, 'E', 'B', 'P', EBPREG, 0,
+ 3, 'E', 'B', 'X', EBXREG, 0,
+ 3, 'E', 'C', 'X', ECXREG, 0,
+ 3, 'E', 'D', 'I', EDIREG, 0,
+ 3, 'E', 'D', 'X', EDXREG, 0,
+ 3, 'E', 'S', 'I', ESIREG, 0,
+ 3, 'E', 'S', 'P', ESPREG, 0,
+
+ 2, 'A', 'X', AXREG, 0,
+ 2, 'C', 'X', CXREG, 0,
+ 2, 'D', 'X', DXREG, 0,
+ 2, 'S', 'P', SPREG, 0,
+
+ 2, 'A', 'H', AHREG, 0,
+ 2, 'A', 'L', ALREG, 0,
+ 2, 'B', 'H', BHREG, 0,
+ 2, 'B', 'L', BLREG, 0,
+ 2, 'C', 'H', CHREG, 0,
+ 2, 'C', 'L', CLREG, 0,
+ 2, 'D', 'H', DHREG, 0,
+ 2, 'D', 'L', DLREG, 0,
+
+ 2, 'C', 'S', CSREG, 0,
+ 2, 'D', 'S', DSREG, 0,
+ 2, 'E', 'S', ESREG, 0,
+ 2, 'F', 'S', FSREG, 0,
+ 2, 'G', 'S', GSREG, 0,
+ 2, 'S', 'S', SSREG, 0,
+
+ 3, 'C', 'R', '0', CR0REG, 0,
+ 3, 'C', 'R', '2', CR2REG, 0,
+ 3, 'C', 'R', '3', CR3REG, 0,
+ 3, 'D', 'R', '0', DR0REG, 0,
+ 3, 'D', 'R', '1', DR1REG, 0,
+ 3, 'D', 'R', '2', DR2REG, 0,
+ 3, 'D', 'R', '3', DR3REG, 0,
+ 3, 'D', 'R', '6', DR6REG, 0,
+ 3, 'D', 'R', '7', DR7REG, 0,
+ 3, 'T', 'R', '3', TR3REG, 0,
+ 3, 'T', 'R', '4', TR4REG, 0,
+ 3, 'T', 'R', '5', TR5REG, 0,
+ 3, 'T', 'R', '6', TR6REG, 0,
+ 3, 'T', 'R', '7', TR7REG, 0,
+
+ 2, 'S', 'T', ST0REG, 0,
+#endif /* I80386 */
+
+#ifdef MC6809
+ 1, 'A', AREG, 0,
+ 1, 'B', BREG, 0,
+ 2, 'C', 'C', CCREG, 0,
+ 1, 'D', DREG, 0,
+ 2, 'D', 'P', DPREG, 0,
+ 2, 'P', 'C', PCREG, 0,
+ 3, 'P', 'C', 'R', PCREG, 0,
+ 1, 'S', SREG, 0,
+ 1, 'U', UREG, 0,
+ 1, 'X', XREG, 0,
+ 1, 'Y', YREG, 0,
+#endif
+ 0 /* end of register list */
+};
+
+#ifdef I80386
+
+/* type sizes */
+/* the "opcode" field gives the type size */
+
+PUBLIC char typesizes[] =
+{
+ 4, 'B', 'Y', 'T', 'E', BYTEOP, 1,
+ 5, 'D', 'W', 'O', 'R', 'D', DWORDOP, 4,
+ 5, 'F', 'W', 'O', 'R', 'D', FWORDOP, 6,
+ 3, 'F', 'A', 'R', FAROP, 0,
+ 3, 'P', 'T', 'R', PTROP, 0,
+ 5, 'P', 'W', 'O', 'R', 'D', PWORDOP, 6,
+ 5, 'Q', 'W', 'O', 'R', 'D', QWORDOP, 8,
+ 5, 'T', 'B', 'Y', 'T', 'E', TBYTEOP, 10,
+ 4, 'W', 'O', 'R', 'D', WORDOP, 2,
+ 0 /* end of typesize list */
+};
+
+#endif
+
+/* ops */
+/* the routine number is given in 1 byte */
+/* the opcode is given in 1 byte (it is not used for pseudo-ops) */
+
+PUBLIC char ops[] =
+{
+ /* pseudo-ops. The "opcode" field is unused and padded with a null byte */
+ /* conditionals - must be first */
+ 4, 'E', 'L', 'S', 'E', ELSEOP, 0,
+ 6, 'E', 'L', 'S', 'E', 'I', 'F', ELSEIFOP, 0,
+ 7, 'E', 'L', 'S', 'E', 'I', 'F', 'C', ELSEIFCOP, 0,
+ 5, 'E', 'N', 'D', 'I', 'F', ENDIFOP, 0,
+ 2, 'I', 'F', IFOP, 0,
+ 3, 'I', 'F', 'C', IFCOP, 0,
+
+ /* unconditionals */
+ 6, '.', 'A', 'L', 'I', 'G', 'N', ALIGNOP, 0,
+ 6, '.', 'A', 'S', 'C', 'I', 'I', FCCOP, 0,
+ 6, '.', 'A', 'S', 'C', 'I', 'Z', ASCIZOP, 0,
+ 5, '.', 'B', 'L', 'K', 'B', RMBOP, 0,
+ 5, '.', 'B', 'L', 'K', 'W', BLKWOP, 0,
+ 5, 'B', 'L', 'O', 'C', 'K', BLOCKOP, 0,
+ 4, '.', 'B', 'S', 'S', BSSOP, 0,
+ 5, '.', 'B', 'Y', 'T', 'E', FCBOP, 0,
+ 4, 'C', 'O', 'M', 'M', COMMOP, 0,
+ 5, '.', 'C', 'O', 'M', 'M', COMMOP1, 0,
+ 5, '.', 'D', 'A', 'T', 'A', DATAOP, 0,
+ 6, '.', 'D', 'A', 'T', 'A', '1', FCBOP, 0,
+ 6, '.', 'D', 'A', 'T', 'A', '2', FDBOP, 0,
+ 6, '.', 'D', 'A', 'T', 'A', '4', FQBOP, 0,
+ 2, 'D', 'B', FCBOP, 0,
+ 2, 'D', 'D', FQBOP, 0,
+ 7, '.', 'D', 'E', 'F', 'I', 'N', 'E', EXPORTOP, 0,
+ 2, 'D', 'W', FDBOP, 0,
+ 3, 'E', 'N', 'D', PROCEOFOP, 0,
+ 4, 'E', 'N', 'D', 'B', ENDBOP, 0,
+ 5, 'E', 'N', 'T', 'E', 'R', ENTEROP, 0,
+ 5, 'E', 'N', 'T', 'R', 'Y', ENTRYOP, 0,
+ 3, 'E', 'Q', 'U', EQUOP, 0,
+ 5, '.', 'E', 'V', 'E', 'N', EVENOP, 0,
+ 6, 'E', 'X', 'P', 'O', 'R', 'T', EXPORTOP, 0,
+ 6, 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0,
+ 7, '.', 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0,
+ 5, 'E', 'X', 'T', 'R', 'N', IMPORTOP, 0,
+ 4, 'F', 'A', 'I', 'L', FAILOP, 0,
+ 5, '.', 'F', 'A', 'I', 'L', FAILOP, 0,
+ 3, 'F', 'C', 'B', FCBOP, 0,
+ 3, 'F', 'C', 'C', FCCOP, 0,
+ 3, 'F', 'D', 'B', FDBOP, 0,
+ 3, 'G', 'E', 'T', GETOP, 0,
+ 6, '.', 'G', 'L', 'O', 'B', 'L', GLOBLOP, 0,
+ 5, 'I', 'D', 'E', 'N', 'T', IDENTOP, 0,
+ 6, 'I', 'M', 'P', 'O', 'R', 'T', IMPORTOP, 0,
+ 7, 'I', 'N', 'C', 'L', 'U', 'D', 'E', GETOP, 0,
+ 5, 'L', 'C', 'O', 'M', 'M', LCOMMOP, 0,
+ 6, '.', 'L', 'C', 'O', 'M', 'M', LCOMMOP1, 0,
+ 5, '.', 'L', 'I', 'S', 'T', LISTOP, 0,
+ 3, 'L', 'O', 'C', LOCOP, 0,
+ 5, '.', 'L', 'O', 'N', 'G', FQBOP, 0,
+ 8, '.', 'M', 'A', 'C', 'L', 'I', 'S', 'T', MACLISTOP, 0,
+ 5, 'M', 'A', 'C', 'R', 'O', MACROOP, 0,
+ 4, '.', 'M', 'A', 'P', MAPOP, 0,
+ 3, 'O', 'R', 'G', ORGOP, 0,
+ 4, '.', 'O', 'R', 'G', ORGOP, 0,
+ 6, 'P', 'U', 'B', 'L', 'I', 'C', EXPORTOP, 0,
+ 3, 'R', 'M', 'B', RMBOP, 0,
+ 4, '.', 'R', 'O', 'M', DATAOP, 0,
+ 5, '.', 'S', 'E', 'C', 'T', SECTOP, 0,
+ 3, 'S', 'E', 'T', SETOP, 0,
+ 5, 'S', 'E', 'T', 'D', 'P', SETDPOP, 0,
+ 6, '.', 'S', 'H', 'O', 'R', 'T', FDBOP, 0,
+ 6, '.', 'S', 'P', 'A', 'C', 'E', RMBOP, 0,
+ 5, '.', 'T', 'E', 'X', 'T', TEXTOP, 0,
+ 5, 'U', 'S', 'E', '1', '6', USE16OP, 0,
+ 5, 'U', 'S', 'E', '3', '2', USE32OP, 0,
+ 5, '.', 'W', 'A', 'R', 'N', WARNOP, 0,
+ 5, '.', 'W', 'O', 'R', 'D', FDBOP, 0,
+ 6, '.', 'Z', 'E', 'R', 'O', 'W', BLKWOP, 0,
+
+ /* hardware ops. The opcode field is now used */
+#ifdef I80386
+ 3, 'A', 'A', 'A', INHER, 0x37,
+ 3, 'A', 'A', 'D', INHER_A, 0xD5,
+ 3, 'A', 'A', 'M', INHER_A, 0xD4,
+ 3, 'A', 'A', 'S', INHER, 0x3F,
+ 3, 'A', 'D', 'C', GROUP1, 0x10,
+ 3, 'A', 'D', 'D', GROUP1, 0x00,
+ 3, 'A', 'N', 'D', GROUP1, 0x20,
+ 4, 'A', 'R', 'P', 'L', EwGw, 0x63,
+ 3, 'B', 'C', 'C', BCC, 0x73,
+ 3, 'B', 'C', 'S', BCC, 0x72,
+ 3, 'B', 'E', 'Q', BCC, 0x74,
+ 3, 'B', 'G', 'E', BCC, 0x7D,
+ 3, 'B', 'G', 'T', BCC, 0x7F,
+ 3, 'B', 'H', 'I', BCC, 0x77,
+ 4, 'B', 'H', 'I', 'S', BCC, 0x73,
+ 3, 'B', 'L', 'E', BCC, 0x7E,
+ 3, 'B', 'L', 'O', BCC, 0x72,
+ 4, 'B', 'L', 'O', 'S', BCC, 0x76,
+ 3, 'B', 'L', 'T', BCC, 0x7C,
+ 3, 'B', 'M', 'I', BCC, 0x78,
+ 3, 'B', 'N', 'E', BCC, 0x75,
+ 5, 'B', 'O', 'U', 'N', 'D', GvMa, 0x62,
+ 3, 'B', 'P', 'C', BCC, 0x7B,
+ 3, 'B', 'P', 'L', BCC, 0x79,
+ 3, 'B', 'P', 'S', BCC, 0x7A,
+ 2, 'B', 'R', CALL, JMP_OPCODE,
+ 3, 'B', 'V', 'C', BCC, 0x71,
+ 3, 'B', 'V', 'S', BCC, 0x70,
+ 4, 'C', 'A', 'L', 'L', CALL, JSR_OPCODE,
+ 5, 'C', 'A', 'L', 'L', 'F', CALLI, 0x9A,
+ 5, 'C', 'A', 'L', 'L', 'I', CALLI, 0x9A,
+ 3, 'C', 'B', 'W', INHER16, 0x98,
+ 3, 'C', 'L', 'C', INHER, 0xF8,
+ 3, 'C', 'L', 'D', INHER, 0xFC,
+ 3, 'C', 'L', 'I', INHER, 0xFA,
+ 3, 'C', 'M', 'C', INHER, 0xF5,
+ 3, 'C', 'M', 'P', GROUP1, CMP_OPCODE_BASE,
+ 4, 'C', 'M', 'P', 'S', INHER, CMPSW_OPCODE,
+ 5, 'C', 'M', 'P', 'S', 'B', INHER, CMPSB_OPCODE,
+ 5, 'C', 'M', 'P', 'S', 'D', INHER32, CMPSW_OPCODE,
+ 5, 'C', 'M', 'P', 'S', 'W', INHER16, CMPSW_OPCODE,
+ 4, 'C', 'M', 'P', 'W', INHER16, CMPSW_OPCODE,
+ 4, 'C', 'S', 'E', 'G', INHER, 0x2E,
+ 3, 'C', 'W', 'D', INHER16, 0x99,
+ 4, 'C', 'W', 'D', 'E', INHER32, 0x98,
+ 3, 'C', 'D', 'Q', INHER32, 0x99,
+ 3, 'D', 'A', 'A', INHER, 0x27,
+ 3, 'D', 'A', 'S', INHER, 0x2F,
+ 4, 'D', 'S', 'E', 'G', INHER, 0x3E,
+ 3, 'D', 'E', 'C', INCDEC, 0x08,
+ 3, 'D', 'I', 'V', DIVMUL, 0x30,
+ 5, 'E', 'N', 'T', 'E', 'R', ENTER, 0xC8,
+ 4, 'E', 'S', 'E', 'G', INHER, 0x26,
+ 4, 'F', 'S', 'E', 'G', INHER, 0x64,
+ 4, 'G', 'S', 'E', 'G', INHER, 0x65,
+ 3, 'H', 'L', 'T', INHER, 0xF4,
+ 4, 'I', 'D', 'I', 'V', DIVMUL, 0x38,
+ 4, 'I', 'M', 'U', 'L', IMUL, 0x28,
+ 2, 'I', 'N', IN, 0xEC,
+ 3, 'I', 'N', 'C', INCDEC, 0x00,
+ 3, 'I', 'N', 'S', INHER, 0x6D,
+ 4, 'I', 'N', 'S', 'B', INHER, 0x6C,
+ 4, 'I', 'N', 'S', 'D', INHER32, 0x6D,
+ 4, 'I', 'N', 'S', 'W', INHER16, 0x6D,
+ 3, 'I', 'N', 'T', INT, 0xCD,
+ 4, 'I', 'N', 'T', 'O', INHER, 0xCE,
+ 3, 'I', 'N', 'W', IN, 0xED,
+ 4, 'I', 'R', 'E', 'T', INHER16, 0xCF,
+ 5, 'I', 'R', 'E', 'T', 'D', INHER32, 0xCF,
+ 1, 'J', CALL, JMP_SHORT_OPCODE,
+ 2, 'J', 'A', JCC, 0x77,
+ 3, 'J', 'A', 'E', JCC, 0x73,
+ 2, 'J', 'B', JCC, 0x72,
+ 3, 'J', 'B', 'E', JCC, 0x76,
+ 2, 'J', 'C', JCC, 0x72,
+ 4, 'J', 'C', 'X', 'E', JCXZ, 0x2,
+ 4, 'J', 'C', 'X', 'Z', JCXZ, 0x2,
+ 5, 'J', 'E', 'C', 'X', 'E', JCXZ, 0x4,
+ 5, 'J', 'E', 'C', 'X', 'Z', JCXZ, 0x4,
+ 2, 'J', 'E', JCC, 0x74,
+ 2, 'J', 'G', JCC, 0x7F,
+ 3, 'J', 'G', 'E', JCC, 0x7D,
+ 2, 'J', 'L', JCC, 0x7C,
+ 3, 'J', 'L', 'E', JCC, 0x7E,
+ 3, 'J', 'M', 'P', CALL, JMP_SHORT_OPCODE,
+ 4, 'J', 'M', 'P', 'F', CALLI, 0xEA,
+ 4, 'J', 'M', 'P', 'I', CALLI, 0xEA,
+ 3, 'J', 'N', 'A', JCC, 0x76,
+ 4, 'J', 'N', 'A', 'E', JCC, 0x72,
+ 3, 'J', 'N', 'B', JCC, 0x73,
+ 4, 'J', 'N', 'B', 'E', JCC, 0x77,
+ 3, 'J', 'N', 'C', JCC, 0x73,
+ 3, 'J', 'N', 'E', JCC, 0x75,
+ 3, 'J', 'N', 'G', JCC, 0x7E,
+ 4, 'J', 'N', 'G', 'E', JCC, 0x7C,
+ 3, 'J', 'N', 'L', JCC, 0x7D,
+ 4, 'J', 'N', 'L', 'E', JCC, 0x7F,
+ 3, 'J', 'N', 'O', JCC, 0x71,
+ 3, 'J', 'N', 'P', JCC, 0x7B,
+ 3, 'J', 'N', 'S', JCC, 0x79,
+ 3, 'J', 'N', 'Z', JCC, 0x75,
+ 2, 'J', 'O', JCC, 0x70,
+ 2, 'J', 'P', JCC, 0x7A,
+ 3, 'J', 'P', 'E', JCC, 0x7A,
+ 3, 'J', 'P', 'O', JCC, 0x7B,
+ 2, 'J', 'S', JCC, 0x78,
+ 2, 'J', 'Z', JCC, 0x74,
+ 4, 'L', 'A', 'H', 'F', INHER, 0x9F,
+ 3, 'L', 'D', 'S', GvMp, 0xC5,
+ 3, 'L', 'E', 'A', LEA, 0x8D,
+ 5, 'L', 'E', 'A', 'V', 'E', INHER, 0xC9,
+ 3, 'L', 'E', 'S', GvMp, 0xC4,
+ 4, 'L', 'O', 'C', 'K', INHER, 0xF0,
+ 4, 'L', 'O', 'D', 'B', INHER, 0xAC,
+ 4, 'L', 'O', 'D', 'S', INHER, 0xAD,
+ 5, 'L', 'O', 'D', 'S', 'B', INHER, 0xAC,
+ 5, 'L', 'O', 'D', 'S', 'D', INHER32, 0xAD,
+ 5, 'L', 'O', 'D', 'S', 'W', INHER16, 0xAD,
+ 4, 'L', 'O', 'D', 'W', INHER16, 0xAD,
+ 4, 'L', 'O', 'O', 'P', JCC, 0xE2,
+ 5, 'L', 'O', 'O', 'P', 'E', JCC, 0xE1,
+ 6, 'L', 'O', 'O', 'P', 'N', 'E', JCC, 0xE0,
+ 6, 'L', 'O', 'O', 'P', 'N', 'Z', JCC, 0xE0,
+ 5, 'L', 'O', 'O', 'P', 'Z', JCC, 0xE1,
+ 3, 'M', 'O', 'V', MOV, 0x88,
+ 4, 'M', 'O', 'V', 'S', INHER, MOVSW_OPCODE,
+ 5, 'M', 'O', 'V', 'S', 'B', INHER, MOVSB_OPCODE,
+ 5, 'M', 'O', 'V', 'S', 'D', INHER32, MOVSW_OPCODE,
+ 5, 'M', 'O', 'V', 'S', 'W', INHER16, MOVSW_OPCODE,
+ 4, 'M', 'O', 'V', 'W', INHER16, MOVSW_OPCODE,
+ 3, 'M', 'U', 'L', DIVMUL, 0x20,
+ 3, 'N', 'E', 'G', NEGNOT, 0x18,
+ 3, 'N', 'O', 'P', INHER, 0x90,
+ 3, 'N', 'O', 'T', NEGNOT, 0x10,
+ 2, 'O', 'R', GROUP1, 0x08,
+ 3, 'O', 'U', 'T', OUT, 0xEE,
+ 4, 'O', 'U', 'T', 'S', INHER, 0x6F,
+ 5, 'O', 'U', 'T', 'S', 'B', INHER, 0x6E,
+ 5, 'O', 'U', 'T', 'S', 'D', INHER32, 0x6F,
+ 5, 'O', 'U', 'T', 'S', 'W', INHER16, 0x6F,
+ 4, 'O', 'U', 'T', 'W', OUT, 0xEF,
+ 3, 'P', 'O', 'P', PUSHPOP, POP_OPCODE,
+ 4, 'P', 'O', 'P', 'A', INHER16, 0x61,
+ 5, 'P', 'O', 'P', 'A', 'D', INHER32, 0x61,
+ 4, 'P', 'O', 'P', 'F', INHER16, 0x9D,
+ 5, 'P', 'O', 'P', 'F', 'D', INHER32, 0x9D,
+ 4, 'P', 'U', 'S', 'H', PUSHPOP, PUSH_OPCODE,
+ 5, 'P', 'U', 'S', 'H', 'A', INHER16, 0x60,
+ 6, 'P', 'U', 'S', 'H', 'A', 'D', INHER32, 0x60,
+ 5, 'P', 'U', 'S', 'H', 'F', INHER16, 0x9C,
+ 6, 'P', 'U', 'S', 'H', 'F', 'D', INHER32, 0x9C,
+ 3, 'R', 'C', 'L', GROUP2, 0x10,
+ 3, 'R', 'C', 'R', GROUP2, 0x18,
+ 3, 'R', 'O', 'L', GROUP2, 0x00,
+ 3, 'R', 'O', 'R', GROUP2, 0x08,
+ 3, 'R', 'E', 'P', INHER, 0xF3,
+ 4, 'R', 'E', 'P', 'E', INHER, 0xF3,
+ 5, 'R', 'E', 'P', 'N', 'E', INHER, 0xF2,
+ 5, 'R', 'E', 'P', 'N', 'Z', INHER, 0xF2,
+ 4, 'R', 'E', 'P', 'Z', INHER, 0xF3,
+ 3, 'R', 'E', 'T', RET, 0xC3,
+ 4, 'R', 'E', 'T', 'F', RET, 0xCB,
+ 4, 'R', 'E', 'T', 'I', RET, 0xCB,
+ 4, 'S', 'A', 'H', 'F', INHER, 0x9E,
+ 3, 'S', 'A', 'L', GROUP2, 0x20,
+ 3, 'S', 'A', 'R', GROUP2, 0x38,
+ 3, 'S', 'B', 'B', GROUP1, 0x18,
+ 4, 'S', 'C', 'A', 'B', INHER, 0xAE,
+ 4, 'S', 'C', 'A', 'S', INHER, 0xAF,
+ 5, 'S', 'C', 'A', 'S', 'B', INHER, 0xAE,
+ 5, 'S', 'C', 'A', 'S', 'D', INHER32, 0xAF,
+ 5, 'S', 'C', 'A', 'S', 'W', INHER16, 0xAF,
+ 4, 'S', 'C', 'A', 'W', INHER16, 0xAF,
+ 3, 'S', 'E', 'G', SEG, 0x06,
+ 3, 'S', 'H', 'L', GROUP2, 0x20,
+ 3, 'S', 'H', 'R', GROUP2, 0x28,
+ 4, 'S', 'S', 'E', 'G', INHER, 0x36,
+ 3, 'S', 'T', 'C', INHER, 0xF9,
+ 3, 'S', 'T', 'D', INHER, 0xFD,
+ 3, 'S', 'T', 'I', INHER, 0xFB,
+ 4, 'S', 'T', 'O', 'B', INHER, 0xAA,
+ 4, 'S', 'T', 'O', 'S', INHER, 0xAB,
+ 5, 'S', 'T', 'O', 'S', 'B', INHER, 0xAA,
+ 5, 'S', 'T', 'O', 'S', 'D', INHER32, 0xAB,
+ 5, 'S', 'T', 'O', 'S', 'W', INHER16, 0xAB,
+ 4, 'S', 'T', 'O', 'W', INHER16, 0xAB,
+ 3, 'S', 'U', 'B', GROUP1, 0x28,
+ 4, 'T', 'E', 'S', 'T', TEST, 0x84,
+ 4, 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE,
+ 4, 'X', 'C', 'H', 'G', XCHG, 0x86,
+ 4, 'X', 'L', 'A', 'T', INHER, 0xD7,
+ 5, 'X', 'L', 'A', 'T', 'B', INHER, 0xD7,
+ 3, 'X', 'O', 'R', GROUP1, 0x30,
+
+ /* floating point */
+ 5, 'F', '2', 'X', 'M', '1', F_INHER, 0x70,
+ 4, 'F', 'A', 'B', 'S', F_INHER, 0x61,
+ 4, 'F', 'A', 'D', 'D', F_M4_M8_STST, 0x00,
+ 5, 'F', 'A', 'D', 'D', 'P', F_STST, 0x60,
+ 4, 'F', 'B', 'L', 'D', F_M10, 0x74,
+ 5, 'F', 'B', 'S', 'T', 'P', F_M10, 0x76,
+ 4, 'F', 'C', 'H', 'S', F_INHER, 0x60,
+ 5, 'F', 'C', 'L', 'E', 'X', F_W_INHER, 0xE2,
+ 4, 'F', 'C', 'O', 'M', F_M4_M8_OPTST, 0x02,
+ 5, 'F', 'C', 'O', 'M', 'P', F_M4_M8_OPTST, 0x03,
+ 6, 'F', 'C', 'O', 'M', 'P', 'P', F_INHER, 0x19,
+ 4, 'F', 'C', 'O', 'S', F_INHER, 0x7F,
+ 7, 'F', 'D', 'E', 'C', 'S', 'T', 'P', F_INHER, 0x76,
+ 5, 'F', 'D', 'I', 'S', 'I', F_W_INHER, 0xE1,
+ 4, 'F', 'D', 'I', 'V', F_M4_M8_STST, 0x06,
+ 5, 'F', 'D', 'I', 'V', 'P', F_STST, 0x67,
+ 5, 'F', 'D', 'I', 'V', 'R', F_M4_M8_STST, 0x07,
+ 6, 'F', 'D', 'I', 'V', 'R', 'P', F_STST, 0x66,
+ 4, 'F', 'E', 'N', 'I', F_W_INHER, 0xE0,
+ 5, 'F', 'F', 'R', 'E', 'E', F_ST, 0x50,
+ 5, 'F', 'I', 'A', 'D', 'D', F_M2_M4, 0x20,
+ 5, 'F', 'I', 'C', 'O', 'M', F_M2_M4, 0x22,
+ 6, 'F', 'I', 'C', 'O', 'M', 'P', F_M2_M4, 0x23,
+ 5, 'F', 'I', 'D', 'I', 'V', F_M2_M4, 0x26,
+ 6, 'F', 'I', 'D', 'I', 'V', 'R', F_M2_M4, 0x27,
+ 4, 'F', 'I', 'L', 'D', F_M2_M4_M8, 0x30,
+ 5, 'F', 'I', 'M', 'U', 'L', F_M2_M4, 0x21,
+ 7, 'F', 'I', 'N', 'C', 'S', 'T', 'P', F_INHER, 0x77,
+ 5, 'F', 'I', 'N', 'I', 'T', F_W_INHER, 0xE3,
+ 4, 'F', 'I', 'S', 'T', F_M2_M4, 0x32,
+ 5, 'F', 'I', 'S', 'T', 'P', F_M2_M4_M8, 0x33,
+ 5, 'F', 'I', 'S', 'U', 'B', F_M2_M4, 0x24,
+ 6, 'F', 'I', 'S', 'U', 'B', 'R', F_M2_M4, 0x25,
+ 3, 'F', 'L', 'D', F_M4_M8_M10_ST, 0x10,
+ 4, 'F', 'L', 'D', '1', F_INHER, 0x68,
+ 6, 'F', 'L', 'D', 'L', '2', 'E', F_INHER, 0x6A,
+ 6, 'F', 'L', 'D', 'L', '2', 'T', F_INHER, 0x69,
+ 5, 'F', 'L', 'D', 'C', 'W', F_M2, 0x15,
+ 6, 'F', 'L', 'D', 'E', 'N', 'V', F_M, 0x14,
+ 6, 'F', 'L', 'D', 'L', 'G', '2', F_INHER, 0x6C,
+ 6, 'F', 'L', 'D', 'L', 'N', '2', F_INHER, 0x6D,
+ 5, 'F', 'L', 'D', 'P', 'I', F_INHER, 0x6B,
+ 4, 'F', 'L', 'D', 'Z', F_INHER, 0x6E,
+ 4, 'F', 'M', 'U', 'L', F_M4_M8_STST, 0x01,
+ 5, 'F', 'M', 'U', 'L', 'P', F_STST, 0x61,
+ 6, 'F', 'N', 'C', 'L', 'E', 'X', F_INHER, 0xE2,
+ 6, 'F', 'N', 'D', 'I', 'S', 'I', F_INHER, 0xE1,
+ 5, 'F', 'N', 'E', 'N', 'I', F_INHER, 0xE0,
+ 6, 'F', 'N', 'I', 'N', 'I', 'T', F_INHER, 0xE3,
+ 4, 'F', 'N', 'O', 'P', F_INHER, 0x50,
+ 6, 'F', 'N', 'S', 'A', 'V', 'E', F_M, 0x56,
+ 6, 'F', 'N', 'S', 'T', 'C', 'W', F_M2, 0x17,
+ 7, 'F', 'N', 'S', 'T', 'E', 'N', 'V', F_M, 0x16,
+ 6, 'F', 'N', 'S', 'T', 'S', 'W', F_M2_AX, 0x57,
+ 6, 'F', 'P', 'A', 'T', 'A', 'N', F_INHER, 0x73,
+ 5, 'F', 'P', 'R', 'E', 'M', F_INHER, 0x78,
+ 6, 'F', 'P', 'R', 'E', 'M', '1', F_INHER, 0x75,
+ 5, 'F', 'P', 'T', 'A', 'N', F_INHER, 0x72,
+ 7, 'F', 'R', 'N', 'D', 'I', 'N', 'T', F_INHER, 0x7C,
+ 6, 'F', 'R', 'S', 'T', 'O', 'R', F_M, 0x54,
+ 5, 'F', 'S', 'A', 'V', 'E', F_W_M, 0x56,
+ 6, 'F', 'S', 'C', 'A', 'L', 'E', F_INHER, 0x7D,
+ 6, 'F', 'S', 'E', 'T', 'P', 'M', F_INHER, 0xE4,
+ 4, 'F', 'S', 'I', 'N', F_INHER, 0x7E,
+ 7, 'F', 'S', 'I', 'N', 'C', 'O', 'S', F_INHER, 0x7B,
+ 5, 'F', 'S', 'Q', 'R', 'T', F_INHER, 0x7A,
+ 3, 'F', 'S', 'T', F_M4_M8_ST, FST_ENCODED,
+ 5, 'F', 'S', 'T', 'C', 'W', F_W_M2, 0x17,
+ 6, 'F', 'S', 'T', 'E', 'N', 'V', F_W_M, 0x16,
+ 4, 'F', 'S', 'T', 'P', F_M4_M8_M10_ST, FSTP_ENCODED,
+ 5, 'F', 'S', 'T', 'S', 'W', F_W_M2_AX, 0x57,
+ 4, 'F', 'S', 'U', 'B', F_M4_M8_STST, 0x04,
+ 5, 'F', 'S', 'U', 'B', 'P', F_STST, 0x65,
+ 5, 'F', 'S', 'U', 'B', 'R', F_M4_M8_STST, 0x05,
+ 6, 'F', 'S', 'U', 'B', 'R', 'P', F_STST, 0x64,
+ 4, 'F', 'T', 'S', 'T', F_INHER, 0x64,
+ 5, 'F', 'U', 'C', 'O', 'M', F_OPTST, 0x54,
+ 6, 'F', 'U', 'C', 'O', 'M', 'P', F_OPTST, 0x55,
+ 7, 'F', 'U', 'C', 'O', 'M', 'P', 'P', F_INHER, 0xA9,
+ 5, 'F', 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE,
+ 4, 'F', 'X', 'A', 'M', F_INHER, 0x65,
+ 4, 'F', 'X', 'C', 'H', F_OPTST, 0x11,
+ 7, 'F', 'X', 'T', 'R', 'A', 'C', 'T', F_INHER, 0x74,
+ 5, 'F', 'Y', 'L', '2', 'X', F_INHER, 0x71,
+ 7, 'F', 'Y', 'L', '2', 'X', 'P', '1', F_INHER, 0x79,
+#endif /* I80386 */
+
+#ifdef MC6809
+ 3, 'A', 'B', 'X', INHER, 0x3A,
+ 4, 'A', 'D', 'C', 'A', ALL, 0x89,
+ 4, 'A', 'D', 'C', 'B', ALL, 0xC9,
+ 4, 'A', 'D', 'D', 'A', ALL, 0x8B,
+ 4, 'A', 'D', 'D', 'B', ALL, 0xCB,
+ 4, 'A', 'D', 'D', 'D', ALL, 0xC3,
+ 4, 'A', 'N', 'D', 'A', ALL, 0x84,
+ 4, 'A', 'N', 'D', 'B', ALL, 0xC4,
+ 5, 'A', 'N', 'D', 'C', 'C', IMMED, 0x1C,
+ 3, 'A', 'S', 'L', ALTER, 0x08,
+ 4, 'A', 'S', 'L', 'A', INHER, 0x48,
+ 4, 'A', 'S', 'L', 'B', INHER, 0x58,
+ 3, 'A', 'S', 'R', ALTER, 0x07,
+ 4, 'A', 'S', 'R', 'A', INHER, 0x47,
+ 4, 'A', 'S', 'R', 'B', INHER, 0x57,
+ 3, 'B', 'C', 'C', SHORT, 0x24,
+ 3, 'B', 'C', 'S', SHORT, 0x25,
+ 3, 'B', 'E', 'Q', SHORT, 0x27,
+ 3, 'B', 'G', 'E', SHORT, 0x2C,
+ 3, 'B', 'G', 'T', SHORT, 0x2E,
+ 3, 'B', 'H', 'I', SHORT, 0x22,
+ 3, 'B', 'H', 'S', SHORT, 0x24,
+ 4, 'B', 'I', 'T', 'A', ALL, 0X85,
+ 4, 'B', 'I', 'T', 'B', ALL, 0XC5,
+ 3, 'B', 'L', 'E', SHORT, 0x2F,
+ 3, 'B', 'L', 'O', SHORT, 0x25,
+ 3, 'B', 'L', 'S', SHORT, 0x23,
+ 3, 'B', 'L', 'T', SHORT, 0x2D,
+ 3, 'B', 'M', 'I', SHORT, 0x2B,
+ 3, 'B', 'N', 'E', SHORT, 0x26,
+ 3, 'B', 'P', 'L', SHORT, 0x2A,
+ 3, 'B', 'R', 'A', SHORT, 0x20,
+ 4, 'L', 'B', 'R', 'A', LONG, 0x16,
+ 3, 'B', 'R', 'N', SHORT, 0x21,
+ 3, 'B', 'S', 'R', SHORT, 0x8D,
+ 4, 'L', 'B', 'S', 'R', LONG, 0x17,
+ 3, 'B', 'V', 'C', SHORT, 0x28,
+ 3, 'B', 'V', 'S', SHORT, 0x29,
+ 3, 'C', 'L', 'R', ALTER, 0x0F,
+ 4, 'C', 'L', 'R', 'A', INHER, 0x4F,
+ 4, 'C', 'L', 'R', 'B', INHER, 0x5F,
+ 4, 'C', 'M', 'P', 'A', ALL, 0x81,
+ 4, 'C', 'M', 'P', 'B', ALL, 0xC1,
+ 4, 'C', 'M', 'P', 'X', ALL, 0x8C,
+ 3, 'C', 'O', 'M', ALTER, 0x03,
+ 4, 'C', 'O', 'M', 'A', INHER, 0x43,
+ 4, 'C', 'O', 'M', 'B', INHER, 0x53,
+ 4, 'C', 'W', 'A', 'I', IMMED, 0x3C,
+ 3, 'D', 'A', 'A', INHER, 0x19,
+ 3, 'D', 'E', 'C', ALTER, 0x0A,
+ 4, 'D', 'E', 'C', 'A', INHER, 0x4A,
+ 4, 'D', 'E', 'C', 'B', INHER, 0x5A,
+ 4, 'E', 'O', 'R', 'A', ALL, 0x88,
+ 4, 'E', 'O', 'R', 'B', ALL, 0xC8,
+ 3, 'E', 'X', 'G', SWAP, 0x1E,
+ 3, 'I', 'N', 'C', ALTER, 0x0C,
+ 4, 'I', 'N', 'C', 'A', INHER, 0x4C,
+ 4, 'I', 'N', 'C', 'B', INHER, 0x5C,
+ 3, 'J', 'M', 'P', ALTER, 0x0E,
+ 3, 'J', 'S', 'R', ALTER, 0x8D,
+ 3, 'L', 'D', 'A', ALL, 0x86,
+ 3, 'L', 'D', 'B', ALL, 0xC6,
+ 3, 'L', 'D', 'D', ALL, 0xCC,
+ 3, 'L', 'D', 'U', ALL, 0xCE,
+ 3, 'L', 'D', 'X', ALL, 0x8E,
+ 4, 'L', 'E', 'A', 'S', INDEXD, 0x32,
+ 4, 'L', 'E', 'A', 'U', INDEXD, 0x33,
+ 4, 'L', 'E', 'A', 'X', INDEXD, 0x30,
+ 4, 'L', 'E', 'A', 'Y', INDEXD, 0x31,
+ 3, 'L', 'S', 'L', ALTER, 0x08,
+ 4, 'L', 'S', 'L', 'A', INHER, 0x48,
+ 4, 'L', 'S', 'L', 'B', INHER, 0x58,
+ 3, 'L', 'S', 'R', ALTER, 0x04,
+ 4, 'L', 'S', 'R', 'A', INHER, 0x44,
+ 4, 'L', 'S', 'R', 'B', INHER, 0x54,
+ 3, 'M', 'U', 'L', INHER, 0x3D,
+ 3, 'N', 'E', 'G', ALTER, 0x00,
+ 4, 'N', 'E', 'G', 'A', INHER, 0x40,
+ 4, 'N', 'E', 'G', 'B', INHER, 0x50,
+ 3, 'N', 'O', 'P', INHER, 0x12,
+ 3, 'O', 'R', 'A', ALL, 0x8A,
+ 3, 'O', 'R', 'B', ALL, 0xCA,
+ 4, 'O', 'R', 'C', 'C', IMMED, 0x1A,
+ 4, 'P', 'S', 'H', 'S', SSTAK, 0x34,
+ 4, 'P', 'S', 'H', 'U', USTAK, 0x36,
+ 4, 'P', 'U', 'L', 'S', SSTAK, 0x35,
+ 4, 'P', 'U', 'L', 'U', USTAK, 0x37,
+ 3, 'R', 'O', 'L', ALTER, 0x09,
+ 4, 'R', 'O', 'L', 'A', INHER, 0x49,
+ 4, 'R', 'O', 'L', 'B', INHER, 0x59,
+ 3, 'R', 'O', 'R', ALTER, 0x06,
+ 4, 'R', 'O', 'R', 'A', INHER, 0x46,
+ 4, 'R', 'O', 'R', 'B', INHER, 0x56,
+ 3, 'R', 'T', 'I', INHER, 0x3B,
+ 3, 'R', 'T', 'S', INHER, 0x39,
+ 4, 'S', 'B', 'C', 'A', ALL, 0x82,
+ 4, 'S', 'B', 'C', 'B', ALL, 0xC2,
+ 3, 'S', 'E', 'X', INHER, 0x1D,
+ 3, 'S', 'T', 'A', ALTER, 0x87,
+ 3, 'S', 'T', 'B', ALTER, 0xC7,
+ 3, 'S', 'T', 'D', ALTER, 0xCD,
+ 3, 'S', 'T', 'U', ALTER, 0xCF,
+ 3, 'S', 'T', 'X', ALTER, 0x8F,
+ 4, 'S', 'U', 'B', 'A', ALL, 0x80,
+ 4, 'S', 'U', 'B', 'B', ALL, 0xC0,
+ 4, 'S', 'U', 'B', 'D', ALL, 0x83,
+ 3, 'S', 'W', 'I', INHER, 0x3F,
+ 4, 'S', 'Y', 'N', 'C', INHER, 0x13,
+ 3, 'T', 'F', 'R', SWAP, 0x1F,
+ 3, 'T', 'S', 'T', ALTER, 0x0D,
+ 4, 'T', 'S', 'T', 'A', INHER, 0x4D,
+ 4, 'T', 'S', 'T', 'B', INHER, 0x5D,
+#endif /* MC6809 */
+ 0 /* end of ops */
+};
+
+PUBLIC char page1ops[] =
+{
+#ifdef I80386
+ 3, 'B', 'S', 'F', GvEv, 0xBC,
+ 3, 'B', 'S', 'R', GvEv, 0xBD,
+ 5, 'B', 'S', 'W', 'A', 'P', BSWAP, 0xC8,
+ 2, 'B', 'T', GROUP8, 0x20,
+ 3, 'B', 'T', 'C', GROUP8, 0x38,
+ 3, 'B', 'T', 'R', GROUP8, 0x30,
+ 3, 'B', 'T', 'S', GROUP8, 0x28,
+ 4, 'C', 'L', 'T', 'S', INHER, 0x06,
+ 7, 'C', 'M', 'P', 'X', 'C', 'H', 'G', ExGx, 0xA6,
+ 4, 'I', 'N', 'V', 'D', INHER, 0x08,
+ 6, 'I', 'N', 'V', 'L', 'P', 'G', GROUP7, 0x38,
+ 3, 'L', 'A', 'R', GvEv, 0x02,
+ 3, 'L', 'F', 'S', GvMp, 0xB4,
+ 4, 'L', 'G', 'D', 'T', GROUP7, 0x10,
+ 3, 'L', 'G', 'S', GvMp, 0xB5,
+ 4, 'L', 'I', 'D', 'T', GROUP7, 0x18,
+ 4, 'L', 'L', 'D', 'T', GROUP6, 0x10,
+ 4, 'L', 'M', 'S', 'W', GROUP7, 0x30,
+ 3, 'L', 'S', 'L', GvEv, 0x03,
+ 3, 'L', 'S', 'S', GvMp, 0xB2,
+ 3, 'L', 'T', 'R', GROUP6, 0x18,
+ 5, 'M', 'O', 'V', 'S', 'X', MOVX, 0xBE,
+ 5, 'M', 'O', 'V', 'Z', 'X', MOVX, 0xB6,
+ 4, 'S', 'E', 'T', 'A', SETCC, 0x97,
+ 5, 'S', 'E', 'T', 'A', 'E', SETCC, 0x93,
+ 4, 'S', 'E', 'T', 'B', SETCC, 0x92,
+ 5, 'S', 'E', 'T', 'B', 'E', SETCC, 0x96,
+ 4, 'S', 'E', 'T', 'C', SETCC, 0x92,
+ 4, 'S', 'E', 'T', 'E', SETCC, 0x94,
+ 4, 'S', 'E', 'T', 'G', SETCC, 0x9F,
+ 5, 'S', 'E', 'T', 'G', 'E', SETCC, 0x9D,
+ 4, 'S', 'E', 'T', 'L', SETCC, 0x9C,
+ 5, 'S', 'E', 'T', 'L', 'E', SETCC, 0x9E,
+ 5, 'S', 'E', 'T', 'N', 'A', SETCC, 0x96,
+ 6, 'S', 'E', 'T', 'N', 'A', 'E', SETCC, 0x92,
+ 5, 'S', 'E', 'T', 'N', 'B', SETCC, 0x93,
+ 6, 'S', 'E', 'T', 'N', 'B', 'E', SETCC, 0x97,
+ 5, 'S', 'E', 'T', 'N', 'C', SETCC, 0x93,
+ 5, 'S', 'E', 'T', 'N', 'E', SETCC, 0x95,
+ 5, 'S', 'E', 'T', 'N', 'G', SETCC, 0x9E,
+ 6, 'S', 'E', 'T', 'N', 'G', 'E', SETCC, 0x9C,
+ 5, 'S', 'E', 'T', 'N', 'L', SETCC, 0x9D,
+ 6, 'S', 'E', 'T', 'N', 'L', 'E', SETCC, 0x9F,
+ 5, 'S', 'E', 'T', 'N', 'O', SETCC, 0x91,
+ 5, 'S', 'E', 'T', 'N', 'P', SETCC, 0x9B,
+ 5, 'S', 'E', 'T', 'N', 'S', SETCC, 0x99,
+ 5, 'S', 'E', 'T', 'N', 'Z', SETCC, 0x95,
+ 4, 'S', 'E', 'T', 'O', SETCC, 0x90,
+ 4, 'S', 'E', 'T', 'P', SETCC, 0x9A,
+ 5, 'S', 'E', 'T', 'P', 'E', SETCC, 0x9A,
+ 5, 'S', 'E', 'T', 'P', 'O', SETCC, 0x9B,
+ 4, 'S', 'E', 'T', 'S', SETCC, 0x98,
+ 4, 'S', 'E', 'T', 'Z', SETCC, 0x94,
+ 4, 'S', 'G', 'D', 'T', GROUP7, 0x00,
+ 4, 'S', 'I', 'D', 'T', GROUP7, 0x08,
+ 4, 'S', 'H', 'L', 'D', SH_DOUBLE, 0xA4,
+ 4, 'S', 'H', 'R', 'D', SH_DOUBLE, 0xAC,
+ 4, 'S', 'L', 'D', 'T', GROUP6, 0x00,
+ 4, 'S', 'M', 'S', 'W', GROUP7, 0x20,
+ 3, 'S', 'T', 'R', GROUP6, 0x08,
+ 4, 'V', 'E', 'R', 'R', GROUP6, 0x20,
+ 4, 'V', 'E', 'R', 'W', GROUP6, 0x28,
+ 6, 'W', 'B', 'I', 'N', 'V', 'D', INHER, 0x09,
+ 4, 'X', 'A', 'D', 'D', ExGx, 0xC0,
+#endif /* I80386 */
+
+#ifdef MC6809
+ 4, 'L', 'B', 'C', 'C', LONG, 0x24,
+ 4, 'L', 'B', 'C', 'S', LONG, 0x25,
+ 4, 'L', 'B', 'E', 'Q', LONG, 0x27,
+ 4, 'L', 'B', 'G', 'E', LONG, 0x2C,
+ 4, 'L', 'B', 'G', 'T', LONG, 0x2E,
+ 4, 'L', 'B', 'H', 'I', LONG, 0x22,
+ 4, 'L', 'B', 'H', 'S', LONG, 0x24,
+ 4, 'L', 'B', 'L', 'E', LONG, 0x2F,
+ 4, 'L', 'B', 'L', 'O', LONG, 0x25,
+ 4, 'L', 'B', 'L', 'S', LONG, 0x23,
+ 4, 'L', 'B', 'L', 'T', LONG, 0x2D,
+ 4, 'L', 'B', 'M', 'I', LONG, 0x2B,
+ 4, 'L', 'B', 'N', 'E', LONG, 0x26,
+ 4, 'L', 'B', 'P', 'L', LONG, 0x2A,
+ 4, 'L', 'B', 'R', 'N', LONG, 0x21,
+ 4, 'L', 'B', 'V', 'C', LONG, 0x28,
+ 4, 'L', 'B', 'V', 'S', LONG, 0x29,
+ 4, 'C', 'M', 'P', 'D', ALL, 0x83,
+ 4, 'C', 'M', 'P', 'Y', ALL, 0x8C,
+ 3, 'L', 'D', 'S', ALL, 0xCE,
+ 3, 'L', 'D', 'Y', ALL, 0x8E,
+ 3, 'S', 'T', 'S', ALTER, 0xCF,
+ 3, 'S', 'T', 'Y', ALTER, 0x8F,
+ 4, 'S', 'W', 'I', '2', INHER, 0x3F,
+#endif /* MC6809 */
+ 0 /* end of page 1 ops */
+};
+
+PUBLIC char page2ops[] =
+{
+#ifdef MC6809
+ 4, 'C', 'M', 'P', 'S', ALL, 0x8C,
+ 4, 'C', 'M', 'P', 'U', ALL, 0x83,
+ 4, 'S', 'W', 'I', '3', INHER, 0x3F,
+#endif
+ 0 /* end of page 2 ops */
+};
+
+#ifdef I80386
+# ifdef MNSIZE
+PUBLIC char bytesizeops[] =
+{
+ 4, 'A', 'D', 'C', 'B', GROUP1, 0x10,
+ 4, 'A', 'D', 'D', 'B', GROUP1, 0x00,
+ 4, 'A', 'N', 'D', 'B', GROUP1, 0x20,
+ 4, 'C', 'M', 'P', 'B', GROUP1, CMP_OPCODE_BASE,
+ 4, 'D', 'E', 'C', 'b', INCDEC, 0x08,
+ 4, 'D', 'I', 'V', 'B', DIVMUL, 0x30,
+ 5, 'I', 'D', 'I', 'V', 'B', DIVMUL, 0x38,
+ 5, 'I', 'M', 'U', 'L', 'B', IMUL, 0x28,
+ 3, 'I', 'N', 'B', IN, 0xEC,
+ 4, 'I', 'N', 'C', 'B', INCDEC, 0x00,
+ 4, 'M', 'O', 'V', 'B', MOV, 0x88,
+ 4, 'M', 'U', 'L', 'B', DIVMUL, 0x20,
+ 4, 'N', 'E', 'G', 'B', NEGNOT, 0x18,
+ 4, 'N', 'O', 'T', 'B', NEGNOT, 0x10,
+ 3, 'O', 'R', 'B', GROUP1, 0x08,
+ 4, 'O', 'U', 'T', 'B', OUT, 0xEE,
+ 4, 'R', 'C', 'L', 'B', GROUP2, 0x10,
+ 4, 'R', 'C', 'R', 'B', GROUP2, 0x18,
+ 4, 'R', 'O', 'L', 'B', GROUP2, 0x00,
+ 4, 'R', 'O', 'R', 'B', GROUP2, 0x08,
+ 4, 'S', 'A', 'L', 'B', GROUP2, 0x20,
+ 4, 'S', 'A', 'R', 'B', GROUP2, 0x38,
+ 4, 'S', 'H', 'L', 'B', GROUP2, 0x20,
+ 4, 'S', 'H', 'R', 'B', GROUP2, 0x28,
+ 4, 'S', 'B', 'B', 'B', GROUP1, 0x18,
+ 4, 'S', 'U', 'B', 'B', GROUP1, 0x28,
+ 5, 'T', 'E', 'S', 'T', 'B', TEST, 0x84,
+ 5, 'X', 'C', 'H', 'G', 'B', XCHG, 0x86,
+ 4, 'X', 'O', 'R', 'B', GROUP1, 0x30,
+ 0 /* end of byte size ops */
+};
+# endif /* MNSIZE */
+#endif /* I80386 */
+
+/* --- end of keywords --- */
+
+FORWARD void install P((register char *keyptr, int data));
+
+PUBLIC void inst_keywords()
+{
+ install(regs, REGBIT);
+#ifdef I80386
+ install(typesizes, SIZEBIT);
+#endif
+ install(ops, 0);
+ install(page1ops, PAGE1);
+ install(page2ops, PAGE2);
+#ifdef I80386
+# ifdef MNSIZE
+ install(bytesizeops, PAGE1 | PAGE2);
+# endif
+#endif
+}
+
+PRIVATE void install(keyptr, data)
+register char *keyptr;
+unsigned char data;
+{
+ char lowcasebuf[20];
+ unsigned namelength;
+ char *nameptr;
+ char *namend;
+ register struct sym_s *symptr;
+
+ while (*keyptr != 0)
+ {
+ namelength = *keyptr++;
+ lineptr = (symname = keyptr) + namelength;
+ for (nameptr = lowcasebuf, namend = lowcasebuf + namelength;
+ nameptr < namend;)
+ {
+ if (*keyptr < 'A' || *keyptr > 'Z')
+ *nameptr++ = *keyptr++;
+ else
+ *nameptr++ = *keyptr++ + ('a' - 'A');
+ }
+ symptr = lookup();
+ symptr->type = MNREGBIT;
+ symptr->data = data;
+ symptr->value_reg_or_op.op.routine = *keyptr;
+ symptr->value_reg_or_op.op.opcode = keyptr[1];
+ lineptr = (symname = lowcasebuf) + namelength;
+ symptr = lookup();
+ symptr->type = MNREGBIT;
+ symptr->data = data;
+ symptr->value_reg_or_op.op.routine = *keyptr;
+ symptr->value_reg_or_op.op.opcode = keyptr[1];
+ keyptr += 2;
+ }
+}
+
+/* Lookup() searches symbol table for the string from symname to lineptr - 1.
+ * If string is not found and ifflag is TRUE, string is added to table, with
+ * type = 0
+ * data = inidata (RELBIT | UNDBIT, possibly with IMPBIT | SEGM)
+ * Returns pointer to symbol entry (NULL if not found and not installed)
+ * unless symbol table overflows, when routine aborts.
+ */
+
+PUBLIC struct sym_s *lookup()
+{
+ struct sym_s **hashptr;
+ register char *nameptr;
+ register struct sym_s *symptr;
+ register unsigned hashval;
+ register unsigned length;
+#ifdef DEBUG
+ int tries;
+
+ ++nlookup;
+ tries = 0;
+#endif
+
+ /* Hash function is a weighted xor of 1 to 4 chars in the string.
+ * This works seems to work better than looking at all the chars.
+ * It is important that the function be fast.
+ * The string comparision function should also be fast and it helps
+ * if it is optimized for mostly identical comparisions.
+ * The multiplication by MULTIPLIER should compile as a shift.
+ */
+
+#define MULTIPLIER (SPTSIZ / (1 << USEFUL_BITS_IN_ASCII))
+#define USEFUL_BITS_IN_ASCII 6
+
+ nameptr = lineptr;
+ length = nameptr - symname;
+ if (length <= 3)
+ {
+ if (length <= 2)
+ hashval = hconv(nameptr[-1]) * MULTIPLIER;
+ else
+ hashval = hconv(nameptr[-2]) * MULTIPLIER,
+ hashval ^= hconv(nameptr[-1]);
+ }
+ else
+ hashval = hconv(nameptr[-(length / 2)]) * MULTIPLIER,
+ hashval ^= hconv(nameptr[-2]) << 2,
+ hashval ^= hconv(nameptr[-1]);
+ nameptr = symname;
+ if ((symptr = *(hashptr = spt +
+ (hashval ^ (hconv(nameptr[0]) << 1)) % SPTSIZ))
+ != NULL)
+ {
+ do
+ {
+#ifdef DEBUG
+ if (tries != 0)
+ --nx[tries];
+ ++tries;
+ if (tries < sizeof nx / sizeof nx[0])
+ ++nx[tries];
+ if (tries >= 5)
+ printchain(hashptr - spt)
+#endif
+ if ((unsigned char) length != symptr->length)
+ continue;
+ if (memcmp(symptr->name, nameptr, length) == 0)
+ return symptr;
+ }
+ while ((symptr = symptr->next) != NULL);
+
+ /* Calculate last non-NULL hash ptr.
+ * This is faster than keeping hashptr up to date in previous loop
+ * since most lookups are successful and hash ptr is not needed.
+ */
+ do
+ {
+ symptr = *hashptr;
+ hashptr = &symptr->next;
+ }
+ while (symptr->next != NULL);
+ }
+ if (!ifflag)
+ return NULL;
+ align(heapptr);
+ if (heapptr >= heapend)
+ fatalerror(SYMOV);
+#ifdef DEBUG
+ ++nsym;
+ if (hashptr >= spt && hashptr < spt + SPTSIZ)
+ ++nhash;
+#endif
+ *hashptr = symptr = (struct sym_s *) heapptr;
+ symptr->type = 0;
+ symptr->data = inidata;
+ symptr->length = length;
+ symptr->value_reg_or_op.value = (unsigned) (symptr->next = NULL);
+ heapptr = symptr->name;
+ do
+ *heapptr++ = *nameptr++;
+ while (--length != 0);
+ *heapptr++ = 0;
+ return symptr;
+}
+
+#ifdef DEBUG
+
+static void printchain(hashval)
+unsigned hashval;
+{
+ register struct sym_s *symptr;
+
+ printf("%04x ", hashval);
+ for (symptr = spt[hashval]; symptr != NULL; symptr = symptr->next)
+ printf("%s ", symptr->name);
+ printf("\n");
+}
+
+#endif
+
+PUBLIC void statistics()
+{
+#ifdef DEBUG
+ int i;
+ int weight;
+
+ for (i = 0; i < SPTSIZ; ++i)
+ printchain(i);
+ printf("nhash = %d, nsym = %d, nlookup = %d nx =\n", nhash, nsym, nlookup);
+ weight = 0;
+ for (i = 0; i < 30; ++i)
+ {
+ printf("%5d", nx[i]);
+ weight += nx[i] * i;
+ }
+ printf("\n");
+ printf("weight = %d%d\n", w;
+#endif
+}
diff --git a/as/todo b/as/todo
new file mode 100644
index 0000000..e85cb6c
--- /dev/null
+++ b/as/todo
@@ -0,0 +1,14 @@
+Check why `chk' fails.
+
+Update 6809/const.h.
+
+Produce bsd symbol tables.
+
+Accept gas format.
+
+Decide how to choose between 8-bit and 32-bit branches. 16-bit branches in
+32-bit mode are unusable because top 16 bits of PC are messed up.
+
+Limit insns to specified processor (warn for 386 insns on 8086).
+
+Buffer for printing of listing.
diff --git a/as/type.h b/as/type.h
new file mode 100644
index 0000000..978c7d8
--- /dev/null
+++ b/as/type.h
@@ -0,0 +1,167 @@
+/* type.h - types for assembler */
+
+/* redefine foo_t's because their use has become non-portable */
+
+#define bool_t bool_T
+#define count_t count_T
+#define fd_t fd_T
+#define indcount_t indcount_T
+#define offset_t offset_T
+#define opcode_t opcode_T
+#define opsize_t opsize_T
+#define scale_t scale_T
+#define sem_t sem_T
+#define smallcount_t smallcount_T
+#define soffset_t soffset_T
+
+typedef unsigned char bool_t;
+typedef int bool_pt;
+typedef unsigned count_t;
+typedef int error_pt;
+typedef int fd_t;
+typedef unsigned char indcount_t;
+#ifdef I80386
+typedef unsigned long offset_t;
+typedef long soffset_t;
+# define SIZEOF_OFFSET_T 4 /* non-portable */
+#endif
+#ifdef MC6809
+typedef unsigned offset_t;
+typedef int soffset_t;
+# define SIZEOF_OFFSET_T 2 /* but sizeof (offset_t) often breaks cpp */
+#endif
+typedef int opcode_pt;
+typedef unsigned char opcode_t;
+typedef int opsize_pt;
+typedef unsigned char opsize_t;
+typedef unsigned reg_pt;
+typedef unsigned char scale_t;
+typedef unsigned char smallcount_t;
+typedef /* signed */ char sem_t;
+typedef unsigned u16_pt;
+typedef unsigned short u16_T;
+typedef unsigned long u32_T;
+
+/* symbol table entry */
+
+struct sym_s
+{
+ struct sym_s *next; /* next symbol in hash chain (NULL if none) */
+ /* zero offset because it is accessed most */
+ unsigned char type;
+ unsigned char data; /* flags valid for expressions as well as syms*/
+ union
+ {
+ offset_t value; /* value, if sym is a label */
+ unsigned char reg; /* register code, if sym is a register */
+ struct
+ {
+ unsigned char routine; /* routine number */
+ opcode_t opcode; /* opcode, if sym is a hardware op */
+ }
+ op; /* if sym is pseudo-op or hardware op */
+ }
+ value_reg_or_op;
+ unsigned char length; /* length of symbol string */
+ char name[1]; /* string of variable length */
+};
+
+/* address */
+
+struct address_s
+{
+ offset_t offset;
+ unsigned char data;
+ struct sym_s *sym;
+};
+
+#ifdef I80386
+
+/* effective address */
+
+struct ea_s
+{
+ indcount_t indcount;
+ opsize_t size;
+ reg_pt base;
+ reg_pt index;
+ scale_t scale;
+ struct address_s displ;
+};
+
+#endif
+
+/* flags */
+
+struct flags_s
+{
+ bool_t global;
+ bool_t current;
+ int semaphore;
+};
+
+/* location counter */
+
+struct lc_s
+{
+ unsigned char data;
+ offset_t lc;
+};
+
+/* string chain */
+
+struct schain_s
+{
+ struct schain_s *next;
+ char string[2]; /* variable length */
+};
+
+/* block stack */
+
+struct block_s
+{
+ unsigned char data;
+ unsigned char dp;
+ offset_t lc;
+};
+
+/* if stack */
+
+struct if_s
+{
+ bool_t ifflag;
+ bool_t elseflag;
+};
+
+/* macro stack */
+
+struct macro_s
+{
+ char *text;
+ struct schain_s *parameters;
+};
+
+/* symbol listing format */
+
+struct sym_listing_s
+{
+ char name[SYMLIS_NAMELEN];
+ char zname[2];
+ char segm[1];
+ char pad1[1];
+ char value[4];
+ char pad2[1];
+ char ar[1];
+ char pad3[1];
+ char cein[1];
+ char pad4[1];
+ char nullterm;
+};
+
+#if __STDC__
+typedef void (*pfv)(void);
+#else
+typedef void (*pfv)();
+#endif
+
+#include "proto.h"
diff --git a/bcc-bruce/6809/const.h b/bcc-bruce/6809/const.h
new file mode 100644
index 0000000..559680c
--- /dev/null
+++ b/bcc-bruce/6809/const.h
@@ -0,0 +1,52 @@
+/* const.h - constants for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* switches for code generation */
+
+#define DEBUG /* generate compiler-debugging code */
+/*#define I8088*/ /* target processor is Intel 8088 thru 80386 */
+#define MC6809 /* target processor is Motorola 6809 */
+#define SELFTYPECHECK /* check calculated type = runtime type */
+
+#ifdef I8088
+# define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */
+# define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */
+# define HOLDSTRINGS /* hold strings for dumping at end
+ * since assembler has only 1 data seg */
+#endif
+
+#ifdef MC6809
+# define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */
+# define OP1 /* logical operators only use 1 byte */
+# define POSINDEPENDENT /* position indep code can (also) be gen */
+#endif
+
+/* switches for source and target operating system dependencies */
+
+/*#define SOS_EDOS*/ /* source O/S is EDOS */
+/*#define SOS_MSDOS*/ /* source O/S is MSDOS */
+#define TOS_EDOS /* target O/S is EDOS */
+
+/* switches for source machine dependencies */
+
+#ifndef SOS_EDOS
+# define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */
+#endif
+
+#ifndef SOS_MSDOS /* need portable alignment for large model */
+# define UNPORTABLE_ALIGNMENT
+#endif
+
+/* local style */
+
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
diff --git a/bcc-bruce/Makefile b/bcc-bruce/Makefile
new file mode 100644
index 0000000..6a507fe
--- /dev/null
+++ b/bcc-bruce/Makefile
@@ -0,0 +1,27 @@
+#
+# Build bcc
+#
+
+all: bcc bcc-cc1
+
+CFLAGS = -DLOCALPREFIX="\"/usr/local\"" -O2
+
+SRCS =assign.c declare.c gencode.c label.c preserve.c type.c \
+ bcc-cc1.c express.c genloads.c loadexp.c scan.c \
+ exptree.c glogcode.c longop.c softop.c codefrag.c \
+ floatop.c hardop.c output.c state.c debug.c function.c \
+ input.c preproc.c table.c
+
+OBJS =assign.o declare.o gencode.o label.o preserve.o type.o \
+ bcc-cc1.o express.o genloads.o loadexp.o scan.o \
+ exptree.o glogcode.o longop.o softop.o codefrag.o \
+ floatop.o hardop.o output.o state.o debug.o function.o \
+ input.o preproc.o table.o
+
+
+bcc: bcc.c
+ $(CC) $(CFLAGS) -o bcc bcc.c
+
+bcc-cc1: $(OBJS)
+ $(CC) $(CFLAGS) -o bcc-cc1 $(OBJS)
+
diff --git a/bcc-bruce/align.h b/bcc-bruce/align.h
new file mode 100644
index 0000000..3c8971b
--- /dev/null
+++ b/bcc-bruce/align.h
@@ -0,0 +1,16 @@
+/* align.h - memory alignment requirements for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifndef S_ALIGNMENT
+# define align(x) (x)
+#else
+# ifdef UNPORTABLE_ALIGNMENT
+typedef unsigned pointerint_t;
+# define align(x) (((pointerint_t) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))
+# else
+# define align(x) ((char *) (x) + (- (int) (x) & (S_ALIGNMENT-1)))
+# endif
+#endif
+
+extern uoffset_t alignmask; /* general alignment mask */
diff --git a/bcc-bruce/assign.c b/bcc-bruce/assign.c
new file mode 100644
index 0000000..6814f64
--- /dev/null
+++ b/bcc-bruce/assign.c
@@ -0,0 +1,387 @@
+/* assign.c - assignment and casting operations for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "sizes.h"
+#include "type.h"
+
+FORWARD void blockmove P((struct symstruct *source, struct symstruct *target));
+FORWARD void call3 P((char *funcname, struct symstruct *target,
+ struct symstruct *source, uoffset_t size));
+FORWARD void fconvert P((struct symstruct *source, struct typestruct *type));
+
+PUBLIC void assign(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt regpushed;
+ store_pt sourcereg;
+ scalar_t tscalar;
+
+ if (target->type->constructor & (ARRAY | FUNCTION) ||
+ target->flags == TEMP || target->flags == (LABELLED | STRING) ||
+ target->indcount == 0 && target->flags != REGVAR)
+ {
+ bugerror("botched lvalue");
+ return;
+ }
+ if (source->storage != target->storage
+ || source->indcount != target->indcount
+ || source->level != target->level
+ || source->offset.offi != target->offset.offi /* kludge union cmp */
+ || source->type != target->type
+ || (source->storage & (LOCAL | GLOBAL)
+ || source->level == OFFKLUDGELEVEL)
+ && ((source->flags ^ target->flags) & LABELLED
+ || source->flags & LABELLED
+ && source->name.label != target->name.label
+ || !(source->flags & LABELLED)
+ && strcmp(source->name.namep, target->name.namep) != 0))
+ {
+ tscalar = target->type->scalar;
+ if (tscalar & CHAR && source->storage == CONSTANT)
+ {
+ source->offset.offv &= CHMASKTO;
+ source->type = target->type;
+ }
+ regpushed = preslval(source, target);
+ if (!(tscalar & CHAR) || source->flags != TEMP ||
+ source->offset.offi != sp || source->type->typesize > itypesize)
+ cast(target->type, source);
+ if (tscalar & RSCALAR)
+ {
+ if (source->storage == CONSTANT && (!reguse & doubleregs))
+ load(source, doubleregs & ~DREG);
+ if (source->storage != CONSTANT && source->indcount == 0)
+ {
+ /* XXX - 386 only */
+ storereg(DREG, target);
+ if (tscalar & DOUBLE)
+ {
+ target->indcount = 1; /* XXX - outnnadr clobbers this */
+ target->offset.offi += accregsize;
+ storereg(doubleregs & ~DREG, target);
+ }
+ target->storage = source->storage;
+ target->offset.offi = 0;
+ }
+ else if (f_indirect(source) && tscalar & DOUBLE
+ && (!(reguse & OPREG) || target->storage == OPREG))
+ {
+ struct symstruct temptarg;
+
+ temptarg = *target;
+ pointat(&temptarg);
+ call("Fpull");
+ outntypechar(temptarg.type);
+ sp += dtypesize;
+ }
+ else
+ blockmove(source, target);
+ }
+ else if (target->type->constructor & STRUCTU)
+ blockmove(source, target);
+ else
+ {
+ if (tscalar & CHAR)
+ load(source, DREG);
+ else if (target->indcount == 0 && target->storage & regregs)
+ load(source, target->storage);
+ else
+ loadany(source);
+ if (tscalar & DLONG)
+ {
+ storereg(DREG, target);
+ target->indcount = 1;
+ target->offset.offi += accregsize;
+ }
+ if ((store_t) (sourcereg = source->storage) == DREG &&
+ target->type->scalar & CHAR)
+ sourcereg = BREG;
+ storereg(sourcereg, target);
+ if ((store_t) regpushed != 0)
+ {
+ /* DLONG */
+ target->indcount = 1;
+ target->offset.offi -= accregsize;
+ recovlist(regpushed);
+ }
+ else
+ {
+ target->storage = sourcereg;
+ target->offset.offi = 0;
+ if (target->level == OFFKLUDGELEVEL)
+ target->level = EXPRLEVEL;
+ }
+ }
+ }
+}
+
+/* block move assumes itypesize == accregsize && BREG size == 1 */
+
+PRIVATE void blockmove(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ struct symstruct oldtarget;
+ uoffset_t typesize;
+ struct symstruct worksource;
+
+ oldtarget = *target;
+ if ((typesize = target->type->typesize) >= 16 * itypesize ||
+ source->indcount + target->indcount != 2)
+ {
+ address(source);
+ address(target);
+ call3("_memcpy", target, source, typesize);
+ }
+ else
+ {
+ if (source->level == OFFKLUDGELEVEL)
+ addoffset(source); /* else kludge is lost and offsets big */
+ if (target->level == OFFKLUDGELEVEL)
+ addoffset(target);
+ worksource = *source;
+ for (; typesize >= itypesize; typesize -= itypesize)
+ {
+ loadreg(source, DREG);
+ worksource.offset.offi += itypesize;
+ *source = worksource;
+ storereg(DREG, target);
+ target->indcount = 1;
+ target->offset.offi += accregsize;
+ }
+ while (typesize-- != 0)
+ {
+ outload();
+ outregname(BREG);
+ outopsep();
+ outadr(source);
+ worksource.offset.offi += 1;
+ *source = worksource;
+ storereg(BREG, target);
+ target->indcount = 1;
+ target->offset.offi += 1;
+ }
+ }
+ *target = oldtarget;
+}
+
+PRIVATE void call3(funcname, target, source, size)
+char *funcname;
+struct symstruct *target;
+struct symstruct *source;
+uoffset_t size;
+{
+ store_pt regpushed;
+ offset_t spmark;
+ struct symstruct *length;
+
+ pushlist(regpushed = reguse & ~calleemask);
+ spmark = sp;
+ length = constsym((value_t) size);
+ length->type = uitype;
+ push(length);
+ push(source);
+ push(target);
+ call(funcname);
+ outnl();
+ if (regpushed)
+ {
+ modstk(spmark);
+ recovlist(regpushed);
+ }
+}
+
+PUBLIC void cast(type, target)
+struct typestruct *type;
+struct symstruct *target;
+{
+ scalar_t newscalar;
+ uoffset_t newsize;
+ scalar_t oldscalar;
+ uoffset_t oldsize;
+ store_pt targreg;
+
+ if (type->constructor & (ARRAY | FUNCTION)
+ || type->constructor & STRUCTU && target->type != type)
+ {
+ bugerror("botched implicit cast");
+ return;
+ }
+ if (target->type == type)
+ return;
+ if (target->type->constructor == ARRAY)
+ oldsize = ptypesize;
+ else
+ oldsize = target->type->typesize;
+ newscalar = type->scalar;
+ oldscalar = target->type->scalar;
+ if ((newsize = type->typesize) == oldsize &&
+ !((newscalar | oldscalar) & RSCALAR))
+ ;
+ else if (newsize == ctypesize) /* char only */
+ {
+ if (oldscalar & RSCALAR)
+ fconvert(target, type);
+ else if (target->indcount == 1)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+# if BIG_ENDIAN
+ target->offset.offi += oldsize - ctypesize;
+# else
+ {
+ if (oldscalar & DLONG)
+ target->offset.offi += itypesize; /* discard msword */
+ }
+# endif
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+# if BIG_ENDIAN
+ target->offset.offi += ctypesize;
+# else
+ ;
+# endif
+#endif
+ }
+ else if (target->storage != CONSTANT)
+ {
+ load(target, DREG);
+ target->storage = BREG;
+ }
+ }
+ else if (newscalar & (SHORT | INT | LONG) && !(newscalar & DLONG)
+ || type->constructor & POINTER)
+ {
+ if (oldscalar & RSCALAR)
+ fconvert(target, type);
+ else if (oldsize < newsize)
+ extend(target);
+ else if (target->indcount == 1)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ {
+ if (oldscalar & DLONG)
+ target->offset.offi += itypesize; /* discard msword */
+ }
+#endif
+ }
+ else
+ load(target, DREG);
+ }
+ else if (newscalar & DLONG)
+ {
+ if (oldscalar & RSCALAR)
+ fconvert(target, type);
+ else if (target->storage != CONSTANT)
+ {
+ extend(target);
+ load(target, DREG);
+ target->storage = targreg = getindexreg();
+ if (oldscalar & (UNSIGNED | CHAR) ||
+ target->type->constructor & (ARRAY | FUNCTION | POINTER))
+ uitol(targreg);
+ else
+ itol(targreg);
+ }
+ }
+ else if (newscalar & RSCALAR)
+ {
+ saveopreg(); /* XXX */
+ if (oldscalar & (ISCALAR | FLOAT))
+ fpush(target);
+ if (newscalar & FLOAT)
+ {
+ pointat(target);
+ call("dto");
+ outntypechar(type);
+ justpushed(target); /* XXX - sets dtype wrong (harmless) and
+ * wastes (dtypesize - ftypesize) stack */
+ }
+ restoreopreg();
+ }
+ target->type = type;
+}
+
+/* extend char or short to int (unsigned if from unsigned) */
+
+PUBLIC void extend(target)
+struct symstruct *target;
+{
+ scalar_t tscalar;
+
+ if ((tscalar = target->type->scalar) & (CHAR | SHORT))
+ {
+ if (target->storage != CONSTANT &&
+ target->type->typesize < itypesize)
+ {
+ load(target, DREG);
+ if (target->type == sctype)
+ sctoi();
+#ifdef I8088
+ else if (tscalar & SHORT)
+ {
+ if (tscalar & UNSIGNED)
+ ustoi();
+ else
+ stoi();
+ }
+#endif
+ else
+ ctoi();
+ target->storage = DREG;
+ }
+ if (tscalar & UNSIGNED)
+ target->type = uitype;
+ else
+ target->type = itype;
+ }
+}
+
+PRIVATE void fconvert(source, type)
+struct symstruct *source;
+struct typestruct *type;
+{
+ offset_t spmark;
+
+ pushlist(reguse & OPREG);
+ spmark = sp;
+ pointat(source);
+ if (source->type->scalar & DOUBLE)
+ call("dto");
+ else
+ call("fto");
+ if (type->scalar & UNSIGNED)
+ outbyte('u');
+ outntypechar(type);
+ if (type->scalar & DLONG)
+ {
+ if (reguse & OPREG)
+ bugerror("loading long into used reg");
+ source->storage = OPREG;
+ }
+ else if (type->scalar & CHAR)
+ source->storage = BREG;
+ else
+ source->storage = DREG;
+ source->offset.offi =
+ source->flags =
+ source->indcount = 0;
+ modstk(spmark); /* could adjust later (load instead of pop) */
+ poplist(reguse & OPREG);
+}
diff --git a/bcc-bruce/bcc-cc1.c b/bcc-bruce/bcc-cc1.c
new file mode 100644
index 0000000..d6fece3
--- /dev/null
+++ b/bcc-bruce/bcc-cc1.c
@@ -0,0 +1,25 @@
+/* bcc-cc1.c - "pass 1" for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ growheap(0); /* init order is important */
+ syminit();
+ etreeinit();
+ ifinit();
+ predefine();
+ openio(argc, argv);
+ codeinit();
+ typeinit();
+ program();
+ finishup();
+
+ /* NOTREACHED */
+ return 0;
+}
diff --git a/bcc-bruce/bcc.bugs b/bcc-bruce/bcc.bugs
new file mode 100644
index 0000000..52f6958
--- /dev/null
+++ b/bcc-bruce/bcc.bugs
@@ -0,0 +1,169 @@
+compiler limitations
+--------------------
+
+These are not implemented:
+
+a. bit fields
+ kludgily implemented (everything padded to char, int or long; can store
+ values wider than the specified field width)
+
+g. signed char type, other ANSI extensions
+
+compiler bugs
+-------------
+
+6. weird but doable casts are not always done for initializers
+
+15. calls to a (casted) absolute address produce an immediate prefix. as386
+ doesn't mind this but complains about the absolute address. as09 complains
+ about the prefix but can handle the absolute address
+
+23. char *f(); &f() is accepted as f() but produces botched nodetype
+ (calc char **).
+
+31. null byte in string initialiser should be ignored if it doesn't fit
+ Non-null bytes which don't fit should be ignored with a warning
+
+32. static char c = "xyz"; is allowed, and bad FCB is generated
+
+37. init of union will store multiple comma-separated entries
+
+38. arrays sizes larger than the amount of memory are accepted
+
+40. structure and union definitions are confused with each other. So
+ struct foo may be used in a declaration like "union foo bar;"
+
+42. pointer arithmetic is performed on pointers to undefined structures
+ (of unknown size). Size is taken as 0 although alignmask is set early
+
+59. preprocessor stuff (# lines or macro names) between the identifier for
+ a label and the colon for the label messes up the label
+
+60. some things involving switches are now broken for 6809 due to lack of
+ frame pointer
+
+61. assembler may get lost on lines of length exactly (?) 256
+
+65. expressions in emum lists or not properly checked for overflow. They
+ should fit in ints. The ordinal number is allowed to overflow
+
+66. sizeof has type int instead of size_t
+
+68. "return expr;" in a function returning a void is reported as a compiler
+ bug not as a semantic error
+
+69. an argument declared as float is (correctly) promoted to double, but
+ not demoted to float when it is used
+
+71. identifiers longer than 64 are botched (scanning of the identifier is
+ stopped but the remaining characters in the identifier are left to
+ mess up the input stream
+
+72. check for too many macro parameters is not working
+
+74. union { char a, b; } foo; gives the wrong offset for b. Unions work OK
+ if the declaration lists have length 1
+
+75. stack gets cleaned up too early in bee = foo ? bar : baz() where baz()
+ returns a struct although there is kludge to make plain bee = baz() work
+
+76. have reintroduced reduced-type bugs, so sizeof(1 ? 1 : 2) is 1
+
+78. fix to require comma in arg list may be half-baked
+
+79. compiler starts trying to load the void expression (i ? (void)0 : (void)0)
+
+80. (unsigned char *) - (char *) causes error and message is obscure
+
+81. 'defined' is a reserved word
+
+82. conditionals with voids don't work
+
+83. float = 1e100 gets overflow exception
+
+84. #endif seems to be seen in
+#if 1
+foo #endif bar
+
+85. line numbers from cpp are not quite right.
+
+bugs that may be fixed
+----------------------
+
+41. typedef's are not scoped properly
+
+nonstandard things that are not done quite right
+------------------------------------------------
+
+3. arguments declared as register are not being dumped by #asm, register
+ vars anyway not being passed to #asm
+
+26. should clear label ptrs when starting #asm
+
+things that have to be be done better
+-------------------------------------
+
+11. push order reversed in genloads.c (temp) - might try to get DP order right
+
+12. need to clean up handling of sc specs (maybe rename flags to sc)
+ And local statics and externs
+
+24. gvarsc is not returned properly for struct/union since the members
+ affect gvarsc (incorrectly). There should be a flag set when
+ inside a struct/union definition to disable sc specs. This could
+ replace the tests in abdeclarator and declselt
+ Best may be to carry the sc along with the type a bit more (in a
+ global symbol structure). Also, the symbol should record sc in a better
+ way than now
+
+25. need to check stack sometimes. Xenix cc does it when allocating >= 100
+ bytes locals and this is essential in Xenix as the stack is grown
+ dynamically
+
+68. overflow checking for constants
+
+things that could be done better
+--------------------------------
+
+4. install new 6809 code for branch patching (after redundancy checks)
+
+5. can improve code for compare with global adr in non-posindependent case
+
+6. char *s; long *pl;
+ code for *s += *pl is poor, for *s += (int) *pl is good
+
+7. most mov's from to ax would be faster and smaller done by xchg's
+
+7a. check ptr add/sub operations earlier
+
+8. tests for against 1 and -1 can sometimes be done with dec's and inc's
+
+9. __opreg is used unnec when the ptr is already in it
+
+9a. double indirect ptrs should maybe be made direct rather than singly
+ indirect by makelessindirect
+
+10. in cmpsmallconst(), the comparison constant should be incorporated in
+ the offset if the indcount is 0 and lea() called. It is harmless to
+ use the lea() trick for non-small constants
+
+20. when saved registers are popped in assign() they may overwrite the
+ expression value, anywhere else? May be fixed now
+
+27. better if loadexpression returned the register used
+
+28. better if source.c did not #include storage.h - it only references
+ DEFINITION, in some blank-skipping code which could be moved to
+ scan.c or preproc.c. preproc.c, scan.c and type.c also #include
+ storage.h, just to get at the DEFINITION and KEYWORD definitions
+
+29. need nodetype() to know about all optimisations in advance, including
+ int % small power of 2 (including 0, 1). Need to delete all type
+ assignments in final code gen, specially the one that convert short
+ to int
+
+30. overflow checking at runtime
+
+31. Use more than the first char from multiple character constants
+
+56. --i++ is not detected as an error in the parser
diff --git a/bcc-bruce/bcc.c b/bcc-bruce/bcc.c
new file mode 100644
index 0000000..bb89bf7
--- /dev/null
+++ b/bcc-bruce/bcc.c
@@ -0,0 +1,875 @@
+/* bcc.c - driver for Bruce's C compiler (bcc) and for CvW's C compiler */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define _POSIX_SOURCE 1
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FALSE 0
+#define FORWARD static
+#ifndef NULL
+#define NULL 0
+#endif
+#define PRIVATE static
+#define PUBLIC
+#define TRUE 1
+
+#if __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+#define AS "as86"
+#define BAS86
+#define BCC86
+#define CC1 "bcc-cc1"
+#define CC1_MINUS_O_BROKEN FALSE
+#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */
+#define CPPFLAGS "-E"
+#define CRT0 "crt0.o"
+#define GCC "gcc"
+#define LD "ld86"
+#define STANDARD_CRT0_0_PREFIX LOCALPREFIX "/lib/bcc/i86/"
+#define STANDARD_CRT0_3_PREFIX LOCALPREFIX "/lib/bcc/i386/"
+#define STANDARD_EXEC_PREFIX LOCALPREFIX "/lib/bcc/"
+#define STANDARD_EXEC_PREFIX_2 LOCALPREFIX "/bin/"
+
+#ifdef CCC
+#undef BCC86
+#undef CC1
+#define CC1 "c386"
+#undef CC1_MINUS_O_BROKEN
+#define CC1_MINUS_O_BROKEN TRUE
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#define STANDARD_CRT0_PREFIX "/usr/local/lib/i386/"
+#endif /* CCC */
+
+#ifdef MC6809
+#undef BAS86
+#undef BCC86
+#undef CRT0
+#undef GCC
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#undef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX "/usr/local/libexec/m09/bcc/"
+#endif /* MC6809 */
+
+#define ALLOC_UNIT 16 /* allocation unit for arg arrays */
+#define DIRCHAR '/'
+#define START_ARGS 4 /* number of reserved args */
+
+typedef unsigned char bool_T; /* boolean: TRUE if nonzero */
+
+struct arg_s
+{
+ char *prog;
+ bool_T minus_O_broken;
+ int argc;
+ char **argv;
+ unsigned nr_allocated;
+};
+
+struct prefix_s
+{
+ char *name;
+ struct prefix_s *next;
+};
+
+PRIVATE struct arg_s asargs = { AS, };
+PRIVATE struct arg_s ccargs = { CC1, CC1_MINUS_O_BROKEN, };
+PRIVATE struct arg_s cppargs = { CPP, };
+#ifdef STANDARD_CRT0_PREFIX
+PRIVATE struct prefix_s crt0_prefix = { STANDARD_CRT0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_0_PREFIX
+PRIVATE struct prefix_s crt0_0_prefix = { STANDARD_CRT0_0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_3_PREFIX
+PRIVATE struct prefix_s crt0_3_prefix = { STANDARD_CRT0_3_PREFIX, };
+#endif
+PRIVATE struct prefix_s exec_prefix;
+PRIVATE struct arg_s ldargs = { LD, };
+#ifdef BAS86
+PRIVATE struct arg_s ldrargs = { LD, };
+#endif
+PRIVATE char *progname;
+PRIVATE bool_T runerror; /* = FALSE */
+PRIVATE struct arg_s tmpargs; /* = empty */
+PRIVATE char *tmpdir;
+PRIVATE unsigned verbosity; /* = 0 */
+
+#ifndef DONT_REDECLARE_STDC_FUNCTIONS
+void exit P((int status));
+char *getenv P((const char *name));
+void *malloc P((size_t size));
+void *realloc P((void *ptr, size_t size));
+void (*signal P((int sig, void (*func) P((int sig))))) P((int sig));
+char *strcpy P((char *dest, const char *src));
+size_t strlen P((const char *s));
+char *strrchr P((const char *s, int c));
+#endif
+
+#ifndef DONT_REDECLARE_POSIX_FUNCTIONS
+int access P((const char *path, int amode));
+int execv P((const char *path, char * const *argv));
+pid_t fork P((void));
+pid_t getpid P((void));
+int unlink P((const char *path));
+pid_t wait P((int *status));
+ssize_t write P((int fd, const void *buf, size_t nbytes));
+#endif
+
+int main P((int argc, char **argv));
+
+FORWARD void addarg P((struct arg_s *argp, char *arg));
+FORWARD void addprefix P((struct prefix_s *prefix, char *name));
+FORWARD void fatal P((char *message));
+FORWARD char *fixpath P((char *path, struct prefix_s *prefix, int mode));
+FORWARD void killtemps P((void));
+FORWARD void *my_malloc P((unsigned size, char *where));
+FORWARD char *my_mktemp P((void));
+FORWARD void my_unlink P((char *name));
+FORWARD void outofmemory P((char *where));
+FORWARD int run P((char *in_name, char *out_name, struct arg_s *argp));
+FORWARD void set_trap P((void));
+FORWARD void show_who P((char *message));
+FORWARD void startarg P((struct arg_s *argp));
+FORWARD char *stralloc P((char *s));
+FORWARD char *stralloc2 P((char *s1, char *s2));
+FORWARD void trap P((int signum));
+FORWARD void unsupported P((char *option, char *message));
+FORWARD void writen P((void));
+FORWARD void writes P((char *s));
+FORWARD void writesn P((char *s));
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+ int argcount = argc;
+ bool_T *argdone = my_malloc((unsigned) argc * sizeof *argdone, "argdone");
+ bool_T as_only = FALSE;
+ char *basename;
+#ifdef BCC86
+ bool_T bits32 = sizeof (char *) >= 4;
+ char *bits_arg;
+#endif
+ bool_T cc_only = FALSE;
+#ifdef CCC
+ bool_T cpp_pass = TRUE;
+#else
+ bool_T cpp_pass = FALSE;
+#endif
+#ifdef BCC86
+ char *crt0;
+#endif
+ bool_T debug = FALSE;
+ bool_T echo = FALSE;
+ unsigned errcount = 0;
+ char ext;
+ char *f_out = NULL;
+ bool_T float_emulation = FALSE;
+#ifdef BAS86
+ bool_T gnu_objects = FALSE;
+#endif
+ char *in_name;
+ int length;
+ unsigned ncisfiles = 0;
+ unsigned nifiles = 0;
+ unsigned npass_specs;
+ bool_T optimize = FALSE;
+ char *out_name;
+ bool_T profile = FALSE;
+ bool_T prep_only = FALSE;
+ bool_T prep_line_numbers = FALSE;
+ int status;
+ char *temp;
+
+ progname = argv[0];
+ addarg(&cppargs, CPPFLAGS);
+#ifdef CCC
+ addarg(&asargs, "-j");
+#endif
+ addarg(&asargs, "-u");
+ addarg(&asargs, "-w");
+#ifdef BCC86
+ addarg(&ldargs, "-i");
+#endif
+#ifdef BAS86
+ addarg(&ldrargs, "-r");
+#endif
+
+ /* Pass 1 over argv to gather compile options. */
+ for (; --argc != 0;)
+ {
+ arg = *++argv;
+ *++argdone = TRUE;
+ if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0)
+ switch (arg[1])
+ {
+#ifdef BCC86
+ case '0':
+ bits32 = FALSE;
+ break;
+ case '3':
+ bits32 = TRUE;
+ break;
+#endif
+ case 'E':
+ prep_only = prep_line_numbers = cpp_pass = TRUE;
+ break;
+#ifdef BAS86
+ case 'G':
+ gnu_objects = TRUE;
+ break;
+#endif
+ case 'P':
+ prep_only = cpp_pass = TRUE;
+ prep_line_numbers = FALSE;
+ break;
+ case 'O':
+ optimize = TRUE; /* unsupported( arg, "optimize" ); */
+ break;
+ case 'S':
+ cc_only = TRUE;
+ break;
+ case 'V':
+ echo = TRUE;
+ break;
+ case 'c':
+ as_only = TRUE;
+ break;
+ case 'e':
+ cpp_pass = TRUE;
+ break;
+ case 'f':
+ float_emulation = TRUE;
+ ++errcount;
+ unsupported(arg, "float emulation");
+ break;
+ case 'g':
+ debug = TRUE; /* unsupported( arg, "debug" ); */
+ break;
+ case 'o':
+ if (--argc < 1)
+ {
+ ++errcount;
+ show_who("output file missing after -o\n");
+ }
+ else
+ {
+ if (f_out != NULL)
+ show_who("more than one output file\n");
+ f_out = *++argv;
+ *++argdone = TRUE;
+ }
+ break;
+ case 'p':
+ profile = TRUE;
+ ++errcount;
+ unsupported(arg, "profile");
+ break;
+ case 'v':
+ ++verbosity;
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else if (arg[0] == '-')
+ switch (arg[1])
+ {
+ case 'A':
+ addarg(&asargs, arg + 2);
+ break;
+ case 'B':
+ addprefix(&exec_prefix, arg + 2);
+ break;
+ case 'C':
+ addarg(&ccargs, arg + 2);
+ break;
+ case 'D':
+ case 'I':
+ case 'U':
+#ifndef CCC
+ addarg(&ccargs, arg);
+#endif
+ addarg(&cppargs, arg);
+ break;
+ case 'L':
+ addarg(&ldargs, arg + 2);
+ break;
+ case 'P':
+ addarg(&cppargs, arg + 2);
+ break;
+#ifdef CCC
+ case 'Q':
+ addarg(&ccargs, arg);
+ break;
+#endif
+ case 'T':
+ tmpdir = arg + 2;
+ break;
+ case 't':
+ ++errcount;
+ unsupported(arg, "pass number");
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else
+ {
+ ++nifiles;
+ *argdone = FALSE;
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ ++ncisfiles;
+ }
+ }
+ npass_specs = prep_only + cc_only + as_only;
+ if (npass_specs != 0)
+ {
+ if (npass_specs > 1)
+ {
+ ++errcount;
+ show_who("more than 1 option from -E -P -S -c\n");
+ }
+ if (f_out != NULL && ncisfiles > 1)
+ {
+ ++errcount;
+ show_who("cannot have more than 1 input with non-linked output\n");
+ }
+ }
+ if (nifiles == 0)
+ {
+ ++errcount;
+ show_who("no input files\n");
+ }
+ if (errcount != 0)
+ exit(1);
+
+ if ((temp = getenv("BCC_EXEC_PREFIX")) != NULL)
+ addprefix(&exec_prefix, temp);
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX);
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX_2);
+ cppargs.prog = fixpath(cppargs.prog, &exec_prefix, X_OK);
+ ccargs.prog = fixpath(ccargs.prog, &exec_prefix, X_OK);
+ asargs.prog = fixpath(asargs.prog, &exec_prefix, X_OK);
+ ldargs.prog = fixpath(ldargs.prog, &exec_prefix, X_OK);
+ ldrargs.prog = fixpath(ldrargs.prog, &exec_prefix, X_OK);
+ if (tmpdir == NULL && (tmpdir = getenv("TMPDIR")) == NULL)
+ tmpdir = "/tmp";
+
+ if (prep_only && !prep_line_numbers)
+ addarg(&cppargs, "-P");
+#ifdef BCC86
+ if (bits32)
+ {
+ bits_arg = "-3";
+ crt0 = fixpath(CRT0, &crt0_3_prefix, R_OK);
+ }
+ else
+ {
+ bits_arg = "-0";
+ crt0 = fixpath(CRT0, &crt0_0_prefix, R_OK);
+ }
+ addarg(&ccargs, bits_arg);
+ addarg(&cppargs, bits_arg);
+ addarg(&asargs, bits_arg);
+#ifdef BAS86
+ if (!gnu_objects)
+ {
+ addarg(&ldargs, bits_arg);
+ addarg(&ldrargs, bits_arg);
+ addarg(&ldargs, crt0);
+ }
+#endif /* BAS86 */
+#endif /* BCC86 */
+#if defined(BAS86) && !defined(BCC86)
+ if (!gnu_objects)
+ addarg(&ldargs, fixpath(CRT0, &crt0_prefix, R_OK));
+#endif
+ set_trap();
+
+ /* Pass 2 over argv to compile and assemble .c, .i, .S and .s files and
+ * gather arguments for linker.
+ */
+ for (argv -= (argc = argcount) - 1, argdone -= argcount - 1; --argc != 0;)
+ {
+ arg = *++argv;
+ if (!*++argdone)
+ {
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ {
+ if (echo || verbosity != 0)
+ {
+ writes(arg);
+ writesn(":");
+ }
+ if ((basename = strrchr(arg, DIRCHAR)) == NULL)
+ basename = arg;
+ else
+ ++basename;
+ in_name = arg;
+ if (ext == 'c')
+ {
+ if (cpp_pass)
+ {
+ if (prep_only)
+ out_name = f_out;
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+ }
+ ext = 'i';
+ }
+ if (ext == 'i')
+ {
+ if (prep_only)
+ continue;
+ if (cc_only)
+ {
+ if (f_out != NULL)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &ccargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 'S')
+ {
+ if (prep_only)
+ out_name = f_out;
+ else if (cc_only)
+ {
+ if (f_out != NULL)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 's')
+ {
+ if (prep_only || cc_only)
+ continue;
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ if (as_only)
+ {
+ if (f_out != NULL)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ addarg(&asargs, "-n");
+ arg[length - 1] = 's';
+ addarg(&asargs, arg);
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ char *tmp_out_name;
+
+ tmp_out_name = my_mktemp();
+ status = run(in_name, tmp_out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ if (run(tmp_out_name, out_name, &ldrargs) != 0)
+ continue;
+ }
+ else
+#endif
+ {
+ status = run(in_name, out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ }
+ ext = 'o';
+ in_name = out_name;
+ }
+ if (ext == 'o')
+ {
+ if (prep_only || cc_only || as_only)
+ continue;
+ addarg(&ldargs, in_name);
+ }
+ }
+ else
+ addarg(&ldargs, arg);
+ }
+ }
+
+ if (!prep_only && !cc_only && !as_only && !runerror)
+ {
+ if (f_out == NULL)
+ f_out = "a.out";
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ /* Remove -i and -i-. */
+ for (argc = ldargs.argc - 1; argc >= START_ARGS; --argc)
+ {
+ arg = ldargs.argv[argc];
+ if (arg[0] == '-' && arg[1] == 'i'
+ && (arg[2] == 0 || arg[2] == '-' && arg[3] == 0))
+ {
+ --ldargs.argc;
+ memmove(ldargs.argv + argc, ldargs.argv + argc + 1,
+ (ldargs.argc - argc) * sizeof ldargs.argv[0]);
+ ldargs.argv[ldargs.argc] = NULL;
+ }
+ }
+
+ ldargs.prog = fixpath(GCC, &exec_prefix, X_OK);
+ run((char *) NULL, f_out, &ldargs);
+ }
+ else
+#endif
+ {
+ addarg(&ldargs, "-lc");
+ run((char *) NULL, f_out, &ldargs);
+ }
+ }
+ killtemps();
+ return runerror ? 1 : 0;
+}
+
+PRIVATE void addarg(argp, arg)
+register struct arg_s *argp;
+char *arg;
+{
+ int new_argc;
+ char **new_argv;
+
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ new_argc = argp->argc + 1;
+ if (new_argc >= argp->nr_allocated)
+ {
+ argp->nr_allocated += ALLOC_UNIT;
+ new_argv = realloc(argp->argv, argp->nr_allocated * sizeof *argp->argv);
+ if (new_argv == NULL)
+ outofmemory("addarg");
+ argp->argv = new_argv;
+ }
+ argp->argv[argp->argc] = arg;
+ argp->argv[argp->argc = new_argc] = NULL;
+}
+
+PRIVATE void addprefix(prefix, name)
+struct prefix_s *prefix;
+char *name;
+{
+ struct prefix_s *new_prefix;
+
+ if (prefix->name == NULL)
+ prefix->name = name;
+ else
+ {
+ new_prefix = my_malloc(sizeof *new_prefix, "addprefix");
+ new_prefix->name = name;
+ new_prefix->next = NULL;
+ while (prefix->next != NULL)
+ prefix = prefix->next;
+ prefix->next = new_prefix;
+ }
+}
+
+PRIVATE void fatal(message)
+char *message;
+{
+ writesn(message);
+ killtemps();
+ exit(1);
+}
+
+PRIVATE char *fixpath(path, prefix, mode)
+char *path;
+struct prefix_s *prefix;
+int mode;
+{
+ char *ppath;
+
+ for (; prefix != NULL; prefix = prefix->next)
+ {
+ if (verbosity > 2)
+ {
+ show_who("searching for ");
+ if (mode == R_OK)
+ writes("readable file ");
+ else
+ writes("executable file ");
+ writes(path);
+ writes(" in ");
+ writesn(prefix->name);
+ }
+ ppath = stralloc2(prefix->name, path);
+ if (access(ppath, mode) == 0)
+ return ppath;
+ free(ppath);
+ }
+ return path;
+}
+
+PRIVATE void killtemps()
+{
+ while (tmpargs.argc > START_ARGS)
+ my_unlink(tmpargs.argv[--tmpargs.argc]);
+}
+
+PRIVATE void *my_malloc(size, where)
+unsigned size;
+char *where;
+{
+ void *block;
+
+ if ((block = malloc(size)) == NULL)
+ outofmemory(where);
+ return block;
+}
+
+PRIVATE char *my_mktemp()
+{
+ char *p;
+ unsigned digit;
+ unsigned digits;
+ char *template;
+ static unsigned tmpnum;
+
+ p = template = stralloc2(tmpdir, "/bccYYYYXXXX");
+ p += strlen(p);
+ digits = getpid();
+ while (*--p == 'X')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p = digit + '0';
+ digits /= 16;
+ }
+ digits = tmpnum;
+ while (*p == 'Y')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p-- = digit + '0';
+ digits /= 16;
+ }
+ ++tmpnum;
+ addarg(&tmpargs, template);
+ return template;
+}
+
+PRIVATE void my_unlink(name)
+char *name;
+{
+ if (verbosity > 1)
+ {
+ show_who("unlinking ");
+ writesn(name);
+ }
+ if (unlink(name) < 0)
+ {
+ show_who("error unlinking ");
+ writesn(name);
+ }
+}
+
+PRIVATE void outofmemory(where)
+char *where;
+{
+ show_who("out of memory in ");
+ fatal(where);
+}
+
+PRIVATE int run(in_name, out_name, argp)
+char *in_name;
+char *out_name;
+struct arg_s *argp;
+{
+ int arg0;
+ int i;
+ int status;
+
+ arg0 = 0;
+ if (in_name == NULL)
+ ++arg0;
+ if (out_name == NULL)
+ arg0 += 2;
+ else if (argp->minus_O_broken)
+ ++arg0;
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ argp->argv[arg0] = argp->prog;
+ i = arg0 + 1;
+ if (in_name != NULL)
+ argp->argv[i++] = in_name;
+ if (out_name != NULL)
+ {
+ if (!argp->minus_O_broken)
+ argp->argv[i++] = "-o";
+ argp->argv[i++] = out_name;
+ }
+ if (verbosity != 0)
+ {
+ for (i = arg0; i < argp->argc; ++i)
+ {
+ writes(argp->argv[i]);
+ writes(" ");
+ }
+ writen();
+ }
+ switch (fork())
+ {
+ case -1:
+ show_who("fork failed");
+ fatal("");
+ case 0:
+ execv(argp->prog, argp->argv + arg0);
+ show_who("exec of ");
+ writes(argp->prog);
+ fatal(" failed");
+ default:
+ wait(&status);
+ for (i = tmpargs.argc - 1; i >= START_ARGS; --i)
+ if (in_name == tmpargs.argv[i])
+ {
+ my_unlink(in_name);
+ --tmpargs.argc;
+ memmove(tmpargs.argv + i, tmpargs.argv + i + 1,
+ (tmpargs.argc - i) * sizeof tmpargs.argv[0]);
+ tmpargs.argv[tmpargs.argc] = NULL;
+ break;
+ }
+ if (status != 0)
+ {
+ killtemps();
+ runerror = TRUE;
+ }
+ return status;
+ }
+}
+
+PRIVATE void set_trap()
+{
+ int signum;
+
+#ifndef _NSIG
+#define _NSIG NSIG
+#endif
+ for (signum = 0; signum <= _NSIG; ++signum)
+#ifdef SIGCHLD
+ if (signum != SIGCHLD)
+#endif
+ if (signal(signum, SIG_IGN) != SIG_IGN)
+ signal(signum, trap);
+}
+
+PRIVATE void show_who(message)
+char *message;
+{
+ writes(progname);
+ writes(": ");
+ writes(message);
+}
+
+PRIVATE void startarg(argp)
+struct arg_s *argp;
+{
+ argp->argv = my_malloc((argp->nr_allocated = ALLOC_UNIT)
+ * sizeof *argp->argv, "startarg");
+ argp->argc = START_ARGS;
+ argp->argv[START_ARGS] = NULL;
+}
+
+PRIVATE char *stralloc(s)
+char *s;
+{
+ return strcpy(my_malloc(strlen(s) + 1, "stralloc"), s);
+}
+
+PRIVATE char *stralloc2(s1, s2)
+char *s1;
+char *s2;
+{
+ return strcat(strcpy(my_malloc(
+ strlen(s1) + strlen(s2) + 1, "stralloc2"), s1), s2);
+}
+
+PRIVATE void trap(signum)
+int signum;
+{
+ signal(signum, SIG_IGN);
+ show_who("caught signal");
+ fatal("");
+}
+
+PRIVATE void unsupported(option, message)
+char *option;
+char *message;
+{
+ show_who("compiler option ");
+ writes(option);
+ writes(" (");
+ writes(message);
+ writesn(") not supported yet");
+}
+
+PRIVATE void writen()
+{
+ writes("\n");
+}
+
+PRIVATE void writes(s)
+char *s;
+{
+ write(2, s, strlen(s));
+}
+
+PRIVATE void writesn(s)
+char *s;
+{
+ writes(s);
+ writen();
+}
diff --git a/bcc-bruce/bcc.doc b/bcc-bruce/bcc.doc
new file mode 100644
index 0000000..61ccd04
--- /dev/null
+++ b/bcc-bruce/bcc.doc
@@ -0,0 +1,173 @@
+bcc options
+-----------
+
+bcc [-03EGOPSVcegv] [-Aas_option] [-Bexecutable_prefix] [-Ccc1_option]
+ [-Ddefine] [-Iinclude_dir] [-Lld_option] [-Qc386_option] [-Ttmpdir]
+ [-Uundef] [-o outfile] [-fpt error] [ld_options] [infiles]
+
+The 6809 version does not support -0, -3 or -G.
+Only the c386 version supports -Q.
+
+defaults (off or none except for these):
+-03 native
+outfile stdout for preprocessor output
+ somewhere/file.[ci] -> file.s for compiler output
+ somewhere/file.[cis] -> file.o for assembler output
+ a.out for ld output
+
+-0 8086 target (works even on 80386 host)
+-3 80386 target (works even on 8086 host)
+-A pass remainder of option to assembler (e.g. -A-l -Alistfile for a listing)
+-B prefix for executable search path (as usual; the search order is all paths
+ specified using -B, in order, then the path given in the environment
+ variable BCC_EXEC_PREFIX if that is set, then the compiled-in defaults
+ (something like /usr/libexec/i386/bcc/ followed by /usr/bin/))
+-C pass remainder of option to cc1 (e.g. -C-c for caller-saves)
+-D define (as usual)
+-E produce preprocessor output (as usual)
+-G produce gnu-Minix objects (link with gnu ld)
+-I include search path (as usual)
+-L pass remainder of option to linker
+-O optimize (does nothing)
+-P produce preprocessor output with no line numbers (as usual)
+-Q pass full option to c386
+-S produce assembler file (as usual)
+-T temporary directory (overrides previous value and default; default is
+ from the environment variable TMPDIR if that is set, otherwise /tmp)
+-U undefine (as usual)
+-V print names of files being compiled
+-c produce object file (as usual)
+-e run the preprocess pass separately. This takes less memory, and may help
+ or harm by giving more traditional semantics like token pasting with /**/.
+-f error (float emulation not supported)
+-g produce debugging info (does nothing)
+-o output file name follows (assembler, object or executable) (as usual)
+-p error (profiling not supported)
+-t error (substitution of some cc passes not supported)
+-v print names and args of subprocesses being run. Two or more -v's:
+ print names of files being unlinked. Three or more -v's:
+ print names of paths being searched.
+
+Other options are passed to the linker, in particular -i-, -lx, -M, -m, -s.
+The -i option is always passed to the linker but can be cancelled using -i-.
+
+This is supposed to match the V7 manual except for -0, -3, -A, -C, -G, -L,
+-T, -V, -e, -v and where not supported.
+
+cc1 options
+----------
+
+cc1 [-03EPcdfltw[-]] [-Ddefine] [-Iinclude_dir] [-Uundef] [-o outfile] [infile]
+
+The 6809 version does not support -0 or -3 but it supports -p.
+
+defaults (off or none except for these):
+-03 native
+-c on for 6809
+-f on for 6809
+outfile stdout
+infile stdin
+
+-0 8086 target (works even on 80386 host)
+-3 80386 target (works even on 8086 host)
+-D define (as usual)
+-E produce preprocessor output (as usual)
+-I include search path (as usual)
+-P produce preprocessor output with no line numbers (as usual)
+-c produce code with caller saving regs before function calls
+-d print debugging information in assembly output
+-f produce code with 1st argument passed in a register
+-l produce code for 2 3 1 0 long byte order (only works in 16-bit versions)
+-o assembler output file name follows
+-p produce (almost) position-independent code
+-t print source code in assemby output
+-w print what cc1 thinks is the location counter in assembly output
+
+All the options except -D, -I and -o may be turned off by following the
+option letter by a '-'. Options are processed left to right so the last
+setting has precedence.
+
+The following is defined before option processing:
+
+__BCC__ 1
+
+The following may be defined after option processing:
+
+__AS09__ 1 if 6809 version
+__AS386_16__ 1 if -0 option on 80*86
+__AS386_32__ 1 if -3 option on 80*86
+__CALLER_SAVES__ 1 if -c option
+__FIRST_ARG_IN_AX__ 1 if -f option on 80*86
+__FIRST_ARG_IN_X__ 1 if -f option on 6809
+__LONG_BIG_ENDIAN__ 1 if -l option
+__POS_INDEPENDENT__ 1 if -p option on 6809
+
+The following are standard builtins:
+
+__FILE__ stringized name of current input file
+__LINE__ current line number
+
+as options
+----------
+
+as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src
+
+The 6809 version does not support -0, -3, -a or -j.
+
+defaults (off or none except for these; no output is produced without a flag):
+-03 native
+list stdout (beware of clobbering next arg)
+name basename of the source name
+
+-0 start with 16-bit code segment
+-3 start with 32-bit code segment
+-a enable partial compatibility with asld
+-b produce binary file, filename may follow (obsolete)
+-g only put global symbols in object file
+-j force all jumps to be long
+-l produce list file, filename may follow
+-m print macro expansions in listing
+-n name of module follows (goes in object instead of source name)
+-o produce object file, filename follows
+-s produce symbol file, filename follows (obsolete)
+-u take undefined symbols as imported-with-unspecified segment
+-w don't print warnings
+
+The -u and -w options are perhaps back to front because they are needed for
+cc1 output and Minix's make does the wrong thing with .s files left around.
+However, all assembler code not written by compilers should assemble with
+them turned off.
+
+ld options
+----------
+
+ld [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]
+ [-Llibdir] [-Olibfile] [-T textaddr] infile...
+
+The version that produces old Minix a.out format does not support -r.
+
+The 6809 version does not support -i or -r.
+
+defaults (off or none except for these):
+-03 native
+-L/usr/local/lib/m/ (m is machine-dependent)
+outfile a.out
+
+-0 produce header with 16-bit magic and use library subdir i86 for -lx
+-3 produce header with 32-bit magic and use library subdir i386 for -lx
+-Cx add file libdir-from-search/crtx.o to list of files linked
+-Lx add dir name x to the head of the list of library dirs searched
+-M print symbols linked on stdout
+-Ox add library libdir-from-search/x to list of files linked
+-T text base address follows (in format suitable for strtoul)
+-i separate I&D output
+-lx add library libdir-from-search/libx.a to list of files linked
+-m print modules linked on stdout
+-o output file name follows
+-r produce output suitable for further relocation
+-s strip symbols
+-t trace modules being looked at on stdout
+-z produce "unmapped zero page" executables
+
+All the options not taking an argument may be turned off by following the
+option letter by a '-', as for cc1.
diff --git a/bcc-bruce/byteord.h b/bcc-bruce/byteord.h
new file mode 100644
index 0000000..e7b19e0
--- /dev/null
+++ b/bcc-bruce/byteord.h
@@ -0,0 +1,13 @@
+/* byteord.h - byte order dependencies for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef I8088
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 1 /* longs are back to front for Xenix */
+#endif
+
+#ifdef MC6809
+# define BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
diff --git a/bcc-bruce/codefrag.c b/bcc-bruce/codefrag.c
new file mode 100644
index 0000000..e98dac4
--- /dev/null
+++ b/bcc-bruce/codefrag.c
@@ -0,0 +1,1843 @@
+/* codefrag.c - code fragments for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "label.h"
+#include "output.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+
+#define DEFSTR_BYTEMAX 10
+#define DEFSTR_DELIMITER '"'
+#define DEFSTR_STRINGMAX 40
+#define EOS_TEXT '0'
+#define MAXPRINTCHAR '~'
+#define MINPRINTCHAR ' '
+
+/* segment numbers */
+
+#ifdef I8088
+# define CSEG 0
+# define outcseg() outop0str(".text\n")
+# define DSEG 1
+# define outdseg() outop0str(".data\n")
+# define BSSSEG 2
+# define outbssseg() outop0str(".bss\n")
+#endif
+
+#ifdef MC6809
+# define CSEG 0
+# define outcseg() outop0str("LOC\t0\n")
+# define DPSEG 2
+# define outdpseg() outop0str("LOC\t2\n")
+# define DSEG 3
+# define outdseg() outop0str("LOC\t3\n")
+# define STRSEG 1
+# define outstrseg() outop0str("LOC\t1\n")
+#endif
+
+#ifdef I8088
+FORWARD void adjcarry P((void));
+#endif
+FORWARD void clr P((store_pt reg));
+FORWARD bool_pt lowregisDreg P((void));
+#ifdef I8088
+FORWARD void outand P((void));
+FORWARD void outequate P((void));
+# ifdef XENIX_AS
+FORWARD void outexport P((void));
+# endif
+FORWARD void outmovsx P((void));
+FORWARD void outmovzx P((void));
+FORWARD void tfrhilo P((void));
+FORWARD void tfrlohi P((void));
+#endif
+#ifdef MC6809
+FORWARD void negBsbcA P((void));
+#endif
+FORWARD void outaccum P((void));
+FORWARD void outstackreg P((void));
+FORWARD void opregadr P((void));
+
+/* operator and miscellaneous strings */
+
+#ifdef I8088
+
+# define ACCHISTR "ah"
+# define ANDSTRING "and\t"
+# define DEFSTR_QUOTER '\\'
+# define EORSTRING "xor\t"
+# define MAX_INLINE_SHIFT 2 /* better 3 for 88, 1 for 186 and above */
+# define ORSTRING "or\t"
+# define TARGET_FIRST
+# define addfactor(reg) (outadd(), outregname(reg), outncregname(DXREG))
+# define defstorage() outop0str(".blkb\t")
+# define extBnegD() (ctoi(), negDreg())
+# define finishfactor() /* save/add/subfactor() ended already */
+# define outadc() outop3str("adc\t")
+# define outandac() (outand(), outaccum(), bumplc())
+# define outandlo() (outand(), outstr(acclostr))
+# define outbimmed() outbyte('*')
+# define outcommon() outop0str(".comm\t")
+# define outcwd() outnop1str("cwd")
+# define outdefstr() outop0str(".ascii\t\"")
+# define outexchange() outop1str("xchg\t")
+# define outglobl() outop0str(".globl\t")
+# ifdef XENIX_AS
+# define outimport() outexport()
+# else
+# define outexport() outop0str("export\t")
+# define outimport() outop0str("import\t")
+# endif
+# ifdef XENIX_AS
+# define outj1switch() outop3str("seg\tcs\nbr\t@");
+# else
+# define outj1switch() outop3str("seg\tcs\nbr\t");
+# endif
+# define outj2switch() \
+ (outindleft(), outstr(ireg0str), outindright(), bumplc2(), outnl())
+# define outlcommon() outop0str("\tlcomm\t")
+# define outlswitch() (outload(), outstr(ireg0str), outncregname(DREG))
+# define outnc1() outnstr(",*1")
+# define outsbc() outop3str("sbb\t")
+# define outset() outstr ("\tset\t")
+# define outsl() outop2str("shl\t")
+# define outsr() outop2str("sar\t")
+# define outtransfer() outload()
+# define outusr() outop2str("shr\t")
+# define outxor() outop2str(EORSTRING)
+# define reclaimfactor() /* factor in DXREG, DXREG now junk */
+# define savefactor(reg) regtransfer((reg), DXREG)
+# define smiDreg() (outcwd(), regexchange(DREG, DXREG))
+# define sr1() (outsr(), outaccum(), outnc1())
+# define subfactor(reg) (outsub(), outregname(reg), outncregname(DXREG))
+# define usr1() (outusr(), outaccum(), outnc1())
+PRIVATE void adjcarry()
+{
+ outop3str("rcl\t");
+ outregname(DXREG);
+ outncimmadr((offset_t) 9);
+ outand();
+ bumplc2();
+ bumplc2();
+ outregname(DXREG);
+ outncimmadr((offset_t) 0x100);
+}
+PUBLIC void clrBreg()
+{
+ outxor();
+ outstr(acclostr);
+ outncregname(BREG);
+}
+PUBLIC void comment()
+{
+ outstr("! ");
+}
+PUBLIC void ctoi()
+{
+ if (i386_32)
+ {
+ outmovzx();
+ outaccum();
+ outncregname(BREG);
+ }
+ else
+ {
+ outxor();
+ outhiaccum();
+ outcomma();
+ outhiaccum();
+ outnl();
+ }
+}
+PUBLIC void defbyte()
+{
+ outop0str(".byte\t");
+}
+#ifdef XENIX_AS
+PUBLIC void defword()
+{
+} /* don't have to print ".word\t" */
+#else
+PUBLIC void defword()
+{
+ outop0str(".word\t");
+}
+#endif
+PUBLIC void defdword()
+{
+ outop0str("dd\t");
+}
+PUBLIC void even()
+{
+ outop0str(".even\n");
+}
+PUBLIC void negDreg()
+{
+ outop2str("neg\t");
+ outnregname(DREG);
+}
+PUBLIC void comDreg()
+{
+ outop2str("not\t");
+ outnregname(DREG);
+}
+PUBLIC void outadd()
+{
+ outop2str("add\t");
+}
+PUBLIC void outaddsp()
+{
+ outadd();
+ outstackreg();
+ outcomma();
+ outimmed();
+ bumplc2();
+}
+PRIVATE void outand()
+{
+ outop2str(ANDSTRING);
+}
+#ifdef XENIX_AS
+PUBLIC void outcalladr()
+{
+ outop2str("call\t@");
+}
+#else
+PUBLIC void outcalladr()
+{
+ outop2str("call\t");
+}
+#endif
+PUBLIC void outcmp()
+{
+ outop2str("cmp\t");
+}
+PUBLIC void outdec()
+{
+ outop1str("dec\t");
+}
+PUBLIC void outdword()
+{
+ outstr("dword ");
+}
+PRIVATE void outequate()
+{
+ outop0str("\t=\t");
+}
+#ifdef XENIX_AS
+PRIVATE void outexport()
+{
+ outop0str(".globl\t");
+}
+#endif
+PUBLIC void outfail()
+{
+ outop0str(".fail\t");
+}
+PUBLIC void outinc()
+{
+ outop1str("inc\t");
+}
+#ifdef XENIX_AS
+PUBLIC void outindleft()
+{
+ outbyte('(');
+}
+PUBLIC void outindright()
+{
+ outbyte(')');
+}
+#else
+PUBLIC void outindleft()
+{
+ outbyte('[');
+}
+PUBLIC void outindright()
+{
+ outbyte(']');
+}
+#endif
+#ifndef FRAMEPOINTER
+PUBLIC void outindstackreg()
+{
+ outindleft();
+ outregname(STACKREG);
+ outindright();
+}
+#endif
+PUBLIC void outldaccum()
+{
+ outload();
+ outaccum();
+ outcomma();
+}
+PUBLIC void outldmulreg()
+{
+ outload();
+ outregname(MULREG);
+ outcomma();
+}
+PUBLIC void outlea()
+{
+ outop2str("lea\t");
+}
+PUBLIC void outleasp()
+{
+ outlea();
+ outstackreg();
+ outcomma();
+}
+PUBLIC void outload()
+{
+ outop2str("mov\t");
+}
+PRIVATE void outmovsx()
+{
+ outop3str("movsx\t");
+}
+PRIVATE void outmovzx()
+{
+ outop3str("movzx\t");
+}
+PUBLIC void outmulmulreg()
+{
+ outop2str("mul\t");
+ outnregname(MULREG);
+}
+PUBLIC void outopsep()
+{
+ outcomma();
+}
+PUBLIC void outpshs()
+{
+ outop1str("push");
+}
+PUBLIC void outpuls()
+{
+ outop1str("pop");
+}
+PUBLIC void outreturn()
+{
+ outnop1str("ret");
+}
+PUBLIC void outstore()
+{
+ outload();
+}
+PUBLIC void outsub()
+{
+ outop2str("sub\t");
+}
+PUBLIC void outtest()
+{
+ outop2str("test\t");
+}
+PUBLIC void outword()
+{
+ outstr("word ");
+}
+PUBLIC void sctoi()
+{
+ if (i386_32)
+ {
+ outmovsx();
+ outncregname(BREG);
+ }
+ else
+ outnop1str("cbw");
+}
+PUBLIC void stoi()
+{
+ outnop1str("cwde");
+}
+PRIVATE void tfrhilo()
+{
+ outload();
+ outstr(acclostr);
+ outcomma();
+ outhiaccum();
+ outnl();
+}
+PRIVATE void tfrlohi()
+{
+ outload();
+ outhiaccum();
+ outncregname(BREG);
+}
+PUBLIC void ustoi()
+{
+ outmovzx();
+ outaccum();
+ outcomma();
+ outshortregname(DREG);
+ outnl();
+}
+#endif /* I8088 */
+
+#ifdef MC6809
+
+# define ACCHISTR "A"
+# define ANDSTRING "AND"
+# define DEFSTR_QUOTER '"'
+# define EORSTRING "EOR"
+# define MAX_INLINE_SHIFT 16
+# define ORSTRING "OR"
+# define addfactor(reg) outop2str("ADDD\t,S")
+# define defstorage() outop0str("RMB\t")
+# define extBnegD() (ctoi(), negBsbcA())
+# define finishfactor() outnl()
+# define outadc() outop2str("ADC")
+# define outandhi() outop2str("ANDA")
+# define outandlo() outop2str("ANDB")
+# define outcommon() outop0str("\tCOMM\t")
+# define outdefstr() outop0str("FCC\t\"")
+# define outequate() outop0str("\tEQU\t")
+# define outexchange() outop2str("EXG\t")
+# define outexport() outop0str("EXPORT\t")
+# define outglobl() outop0str("GLOBL\t")
+# define outimport() outop0str("IMPORT\t")
+# define outjswitch() outnop2str("JMP\t[D,X]")
+# define outlcommon() outop0str("\tLCOMM\t")
+# define outlswitch() outop3str("LDX\t#")
+# define outpijswitch() outnop2str("JMP\tD,X")
+# define outpil1switch() outop3str("LEAX\t<")
+# define outpil2switch() outnop2str("LDD\tD,X")
+# define outrolhi() outnop1str("ROLA");
+# define outsbc() outop2str("SBC")
+# define outset() outstr ("\tSET\t")
+# define outsl() outop1str("LSL")
+# define outtransfer() outop2str("TFR\t")
+# define reclaimfactor() outnstr ("++") /* discard factor from stack */
+# define savefactor(reg) outop2str("PSHS\tD")
+# define smiDreg() (clrBreg(), outnop1str("ROLA"), \
+ outnop2str("SBCB\t#0"), sctoi())
+ /* this tricky sequence is twice as fast as TFR A,B; SEX; TFR A,B */
+ /* it gets the sign bit of A in the carry */
+ /* then subtracts it from 0 in D (effectively) */
+# define sr1() (outnop1str("ASRA"), outnop1str("RORB"))
+# define stackregstr "S"
+# define subfactor(reg) outop2str("SUBD\t,S")
+# define testhi() outnop1str("TSTA")
+# define tfrhilo() outnop2str("TFR\tA,B")
+# define tfrlohi() outnop2str("TFR\tB,A")
+# define usr1() (outnop1str("LSRA"), outnop1str("RORB"))
+PUBLIC void clrBreg()
+{
+ outnop1str("CLRB");
+}
+PUBLIC void comment()
+{
+ outstr("| ");
+}
+PUBLIC void defbyte()
+{
+ outop0str("FCB\t");
+}
+PUBLIC void defword()
+{
+ outop0str("FDB\t");
+}
+PUBLIC void negDreg()
+{
+ outnop1str("NEGA");
+ negBsbcA();
+}
+PRIVATE void negBsbcA()
+{
+ outnop1str("NEGB");
+ sbc0();
+}
+PUBLIC void comDreg()
+{
+ outnop1str("COMA");
+ outnop1str("COMB");
+}
+PUBLIC void outABX()
+{
+ outnop1str("ABX");
+}
+PUBLIC void outadd()
+{
+ outop2str("ADD");
+}
+PUBLIC void outaddsp()
+{
+ outleasp();
+ bumplc2();
+}
+PUBLIC void outcalladr()
+{
+ outop2str("JSR");
+}
+PUBLIC void outcmp()
+{
+ outop2str("CMP");
+}
+PUBLIC void outdec()
+{
+ outop1str("DEC");
+}
+PUBLIC void outdirectpage()
+{
+ outbyte('<');
+}
+PUBLIC void outextended()
+{
+ outbyte('>');
+}
+PUBLIC void outfail()
+{
+ outop0str("FAIL\t");
+}
+PUBLIC void outinc()
+{
+ outop1str("INC");
+}
+PUBLIC void outindleft()
+{
+ outbyte('[');
+}
+PUBLIC void outindright()
+{
+ outbyte(']');
+}
+PUBLIC void outldaccum()
+{
+ outload();
+ outaccum();
+}
+PUBLIC void outldmulreg()
+{
+ outop2str("LDA");
+}
+PUBLIC void outlea()
+{
+ outop2str("LEA");
+}
+PUBLIC void outleasp()
+{
+ outop2str("LEAS\t");
+}
+PUBLIC void outload()
+{
+ outop2str("LD");
+}
+PUBLIC void outmulmulreg()
+{
+ outnop1str("MUL");
+}
+PUBLIC void outncspregname()
+{
+ outcomma();
+ outstackreg();
+ outnl();
+}
+PUBLIC void outopsep()
+{
+} /* is tab, but already done by outadr() */
+PUBLIC void outpshs()
+{
+ outop2str("PSHS");
+}
+PUBLIC void outpuls()
+{
+ outop2str("PULS");
+}
+PUBLIC void outreturn()
+{
+ outnop1str("RTS");
+}
+PUBLIC void outstore()
+{
+ outop2str("ST");
+}
+PUBLIC void outsub()
+{
+ outop2str("SUB");
+}
+PUBLIC void outtest()
+{
+ outop1str("TST");
+}
+PUBLIC void sctoi()
+{
+ outnop1str("SEX");
+}
+PUBLIC void ctoi()
+{
+ outnop1str("CLRA");
+}
+#endif /* MC6809 */
+#ifdef FRAMEREG
+PUBLIC void outindframereg()
+{
+ outindleft();
+ outregname(FRAMEREG);
+ outindright();
+}
+#endif
+
+typedef fastin_t seg_t; /* range 0..3 */
+
+PRIVATE seg_t segment; /* current seg, depends on init to CSEG = 0 */
+
+/* add carry resulting from char addition */
+
+PUBLIC void adc0()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ adjcarry();
+ outadd();
+ outaccum();
+ outncregname(DXREG);
+ }
+ else
+#endif
+ {
+ outadc();
+ outhiaccum();
+ outncimmadr((offset_t) 0);
+ }
+}
+
+/* add constant to register */
+
+PUBLIC void addconst(offset, reg)
+offset_t offset;
+store_pt reg;
+{
+#ifdef I8088
+ if (i386_32 && (uoffset_t) offset + 1 <= 2 /* do -1 to 1 by dec/inc */
+ || !i386_32 && (uoffset_t) offset + 2 <= 4) /* do -2 to 2 */
+ {
+ if (reg == ALREG)
+ reg = AXREG; /* shorter and faster */
+ do
+ {
+ if (offset < 0)
+ {
+ outdec();
+ ++offset;
+ }
+ else /* if offset == 0, do inc + dec */
+ {
+ outinc();
+ --offset; /* shouldn't happen and harmless */
+ }
+ outnregname(reg);
+ }
+ while (offset);
+ }
+ else
+#endif
+#ifdef MC6809
+ if (!(reg & ALLDATREGS))
+ lea(offset, reg, reg);
+ else if (reg == BREG && (offset == 1 || offset == -1))
+ {
+ if (offset < 0)
+ outdec();
+ else
+ outinc();
+ outnregname(reg);
+ }
+ else
+#endif
+ {
+ outadd();
+ outimadj(offset, reg);
+ }
+}
+
+/* adjust lc for signed offset */
+
+PUBLIC void adjlc(offset, reg)
+offset_t offset;
+store_pt reg;
+{
+ if (!(reg & CHARREGS))
+ {
+ bumplc();
+ if (!isbyteoffset(offset))
+ {
+#ifdef I8088
+ if ((store_t) reg != AXREG)
+#endif
+ bumplc();
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ }
+ }
+}
+
+/* adjust stack ptr by adding a labelled constant less current sp */
+
+PUBLIC void adjsp(label)
+label_t label;
+{
+ outaddsp();
+ outbyte(LOCALSTARTCHAR);
+ outlabel(label);
+ if (switchnow != NULL)
+ {
+ outminus();
+ outswstacklab();
+ }
+ else
+ {
+ outplus();
+ outhex((uoffset_t) - sp);
+ }
+#ifdef MC6809
+ outcregname(LOCAL);
+#endif
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ outnl();
+}
+
+/* and accumulator with constant */
+
+PUBLIC void andconst(offset)
+offset_t offset;
+{
+ char_t botbits;
+ uoffset_t topbits;
+
+ if ((topbits = offset & ~(uoffset_t) CHMASKTO & intmaskto) != 0 &&
+ topbits != (~(uoffset_t) CHMASKTO & intmaskto))
+ /* if topbits == 0, callers reduce the type */
+ {
+#ifdef OP1
+ outandhi();
+ outncimmadr((offset_t) (topbits >> (INT16BITSTO - CHBITSTO)));
+#else
+ outandac();
+ if (i386_32)
+ bumplc2();
+ outncimmadr(offset);
+ return;
+#endif
+ }
+ if ((botbits = (char_t) offset & CHMASKTO) == 0)
+ clrBreg();
+ else if (botbits != CHMASKTO)
+ {
+ outandlo();
+ outncimmadr((offset_t) botbits);
+ }
+}
+
+#ifdef I8088
+
+/* set bss segment */
+
+PUBLIC void bssseg()
+{
+ if (segment != BSSSEG)
+ {
+ segment = BSSSEG;
+ outbssseg();
+ }
+}
+
+#endif
+
+/* jump to case of switch */
+
+PUBLIC label_t casejump()
+{
+ label_t jtablelab;
+
+#ifdef I8088
+ outlswitch();
+ outj1switch();
+ outlabel(jtablelab = getlabel());
+ outj2switch();
+ if (i386_32)
+ bumplc2();
+#endif
+#ifdef MC6809
+ if (posindependent)
+ {
+ outpil1switch();
+ outlabel(jtablelab = getlabel());
+ outncregname(GLOBAL);
+ outpil2switch();
+ outpijswitch();
+ }
+ else
+ {
+ outlswitch();
+ outnlabel(jtablelab = getlabel());
+ outjswitch();
+ }
+#endif
+ return jtablelab;
+}
+
+/* clear register to 0 */
+
+PRIVATE void clr(reg)
+store_pt reg;
+{
+ loadconst((offset_t) 0, reg);
+}
+
+/* define common storage */
+
+PUBLIC void common(name)
+char *name;
+{
+#ifdef I8088
+ outcommon();
+ outccname(name);
+ outcomma();
+#endif
+#ifdef MC6809
+ outccname(name);
+ outcommon();
+#endif
+}
+
+/* set code segment */
+
+PUBLIC void cseg()
+{
+ if (segment != CSEG)
+ {
+ segment = CSEG;
+ outcseg();
+ }
+}
+
+/* define long */
+
+PUBLIC void deflong(value)
+uoffset_t value;
+{
+ uoffset_t longhigh;
+ uoffset_t longlow;
+
+ longlow = value & (uoffset_t) intmaskto;
+#ifdef I8088
+ if (i386_32)
+ defdword();
+ else
+#endif
+ {
+ longhigh = (value >> INT16BITSTO) & (uoffset_t) intmaskto;
+ defword();
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ outnhex(longhigh);
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ {
+ outnhex(longlow);
+ longlow = longhigh;
+ }
+#endif
+ defword();
+ }
+ outnhex(longlow);
+}
+
+/* define null storage */
+
+PUBLIC void defnulls(nullcount)
+uoffset_t nullcount;
+{
+ if (nullcount != 0)
+ {
+ defstorage();
+ outnhex(nullcount);
+ }
+}
+
+/* define string */
+
+PUBLIC label_t defstr(sptr, stop, dataflag)
+char *sptr;
+char *stop;
+bool_pt dataflag;
+{
+ int byte; /* promoted char for output */
+ label_t strlab;
+ seg_t oldsegment;
+ fastin_t count; /* range 0..max(DEFSTR_BYTEMAX,DEFSTR_STRMAX) */
+
+#ifdef HOLDSTRINGS
+ if (!(bool_t) dataflag)
+ return holdstr(sptr, stop);
+#endif
+ oldsegment = segment;
+#ifdef I8088
+ dseg();
+#endif
+#ifdef MC6809
+ if (dataflag)
+ dseg();
+ else
+ {
+ segment = STRSEG; /* could use dseg() */
+ outstrseg(); /* this brings strings together */
+ }
+#endif
+ outnlabel(strlab = getlabel());
+ byte = (unsigned char) *sptr++;
+ while (sptr <= stop)
+ {
+ if ((unsigned char) byte >= MINPRINTCHAR
+ && (unsigned char) byte <= MAXPRINTCHAR)
+ {
+ outdefstr();
+ count = DEFSTR_STRINGMAX;
+ while (count-- > 0 && (unsigned char) byte >= MINPRINTCHAR
+ && (unsigned char) byte <= MAXPRINTCHAR && sptr <= stop)
+ {
+#if DEFSTR_DELIMITER - DEFSTR_QUOTER
+ if ((unsigned char) byte == DEFSTR_DELIMITER
+ || (unsigned char) byte == DEFSTR_QUOTER)
+#else
+ if ((unsigned char) byte == DEFSTR_DELIMITER)
+#endif
+ outbyte(DEFSTR_QUOTER);
+ outbyte(byte);
+ byte = (unsigned char) *sptr++;
+ }
+ outnbyte(DEFSTR_DELIMITER);
+ }
+ else
+ {
+ defbyte();
+ count = DEFSTR_BYTEMAX;
+ while (count-- > 0 && ((unsigned char) byte < MINPRINTCHAR
+ || (unsigned char) byte > MAXPRINTCHAR) && sptr <= stop)
+ {
+ if (count < DEFSTR_BYTEMAX - 1)
+ outcomma(); /* byte separator */
+ outhex((uoffset_t) byte);
+ byte = (unsigned char) *sptr++;
+ }
+ outnl();
+ }
+ }
+ defbyte();
+ outnbyte(EOS_TEXT);
+ switch (oldsegment)
+ {
+ case CSEG:
+ cseg();
+ break;
+ case DSEG:
+ dseg();
+ break;
+#ifdef I8088
+ case BSSSEG:
+ bssseg();
+ break;
+#endif
+#ifdef MC6809
+ case DPSEG:
+ dpseg();
+ break;
+#endif
+ }
+ return strlab;
+}
+
+/* divide D register by a constant if it is easy to do with shifts */
+
+PUBLIC bool_pt diveasy(divisor, uflag)
+value_t divisor;
+bool_pt uflag;
+{
+ bool_t sign;
+
+ sign = FALSE;
+ if (divisor < 0 && !(bool_t) uflag)
+ {
+ sign = TRUE;
+ divisor = -divisor;
+ }
+ if (bitcount((uvalue_t) divisor) > 1)
+ return FALSE;
+ if (divisor == 0)
+ clr(DREG);
+ else
+ {
+ if (sign)
+ negDreg();
+ srconst((value_t) highbit((uvalue_t) divisor), uflag);
+ }
+ return TRUE;
+}
+
+#ifdef MC6809
+
+/* set direct page segment */
+
+PUBLIC void dpseg()
+{
+ if (segment != DPSEG)
+ {
+ segment = DPSEG;
+ outdpseg();
+ }
+}
+
+#endif
+
+/* set data segment */
+
+PUBLIC void dseg()
+{
+ if (segment != DSEG)
+ {
+ segment = DSEG;
+ outdseg();
+ }
+}
+
+/* equate a name to an EOL-terminated string */
+
+PUBLIC void equ(name, string)
+char *name;
+char *string;
+{
+ outstr(name);
+ outequate();
+ outline(string);
+}
+
+/* equate a local label to a value */
+
+PUBLIC void equlab(label, offset)
+label_t label;
+offset_t offset;
+{
+ outbyte(LOCALSTARTCHAR);
+ outlabel(label);
+ outequate();
+ outshex(offset);
+ outnl();
+}
+
+/* import or export a variable */
+
+PUBLIC void globl(name)
+char *name;
+{
+ outglobl();
+ outnccname(name);
+}
+
+/* import a variable */
+
+PUBLIC void import(name)
+char *name;
+{
+ outimport();
+ outnccname(name);
+}
+
+/* extend an int to a long */
+
+PUBLIC void itol(reg)
+store_pt reg;
+{
+#define TEMP_LABEL_FOR_REGRESSION_TESTS
+#ifdef TEMP_LABEL_FOR_REGRESSION_TESTS
+ getlabel();
+#endif
+
+ if (lowregisDreg())
+ {
+#ifdef I8088
+ outcwd();
+ regtransfer(DXREG, reg);
+#else
+ label_t exitlab;
+
+ clr(reg);
+ testhi();
+ sbranch(GE, exitlab = getlabel());
+ loadconst((offset_t) - 1, reg);
+ outnlabel(exitlab);
+#endif
+ }
+ else
+ {
+ regtransfer(DREG, reg);
+ smiDreg();
+ }
+}
+
+/* define local common storage */
+
+PUBLIC void lcommlab(label)
+label_t label;
+{
+ outlabel(label);
+ outlcommon();
+}
+
+PUBLIC void lcommon(name)
+char *name;
+{
+ outccname(name);
+ outlcommon();
+}
+
+#ifdef MC6809
+
+/* load effective address */
+
+PUBLIC void lea(offset, sourcereg, targreg)
+offset_t offset;
+store_pt sourcereg;
+store_pt targreg;
+{
+ outlea();
+ outregname(targreg);
+ outtab();
+ outshex(offset);
+ outncregname(sourcereg);
+}
+
+#endif
+
+/* load constant into given register */
+
+PUBLIC void loadconst(offset, reg)
+offset_t offset;
+store_pt reg;
+{
+#ifdef I8088
+ if (offset == 0)
+ {
+ outxor();
+ outregname(reg);
+ outncregname(reg);
+ }
+ else
+#endif
+#ifdef MC6809
+ if (offset == 0 && reg == BREG)
+ clrBreg();
+ else
+#endif
+ {
+ outload();
+ outregname(reg);
+#ifdef MC6809
+ if (reg == YREG)
+ bumplc2();
+ else
+#endif
+ if (reg != BREG)
+ {
+ bumplc();
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ }
+ outncimmadr(offset);
+ }
+}
+
+/* convert index half of long reg pair into low half of pair */
+
+PRIVATE bool_pt lowregisDreg()
+{
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ return FALSE;
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ return TRUE;
+#endif
+}
+
+/* partially long shift left register by a constant (negative = infinity) */
+
+PUBLIC int lslconst(shift, reg)
+value_t shift;
+store_pt reg;
+{
+ if ((uvalue_t) shift >= INT16BITSTO)
+ {
+ slconst(shift - INT16BITSTO, lowregisDreg() ? DREG : reg);
+ regexchange(reg, DREG);
+ clr(lowregisDreg() ? DREG : reg);
+ return 0;
+ }
+#ifdef I8088
+ if (shift >= CHBITSTO)
+ {
+ if (long_big_endian)
+ {
+ tfrlohi();
+ outnop2str("mov\tal,bh");
+ outnop2str("mov\tbh,bl");
+ outnop2str("sub\tbl,bl");
+ }
+ else
+ {
+ outnop2str("mov\tbh,bl");
+ outnop2str("mov\tbl,ah");
+ tfrlohi();
+ clrBreg();
+ }
+ return (int) shift - CHBITSTO;
+ }
+#endif
+ return (int) shift;
+}
+
+/* partially long shift right register by a constant (negative = infinity) */
+
+PUBLIC int lsrconst(shift, reg, uflag)
+value_t shift;
+store_pt reg;
+bool_pt uflag;
+{
+ if ((uvalue_t) shift >= INT16BITSTO)
+ {
+ if (lowregisDreg())
+ regexchange(reg, DREG);
+ srconst(shift - INT16BITSTO, uflag);
+ if ((bool_t) uflag)
+ uitol(reg);
+ else
+ itol(reg);
+ return 0;
+ }
+#ifdef I8088
+ if (shift >= CHBITSTO)
+ {
+ if (long_big_endian)
+ {
+ outnop2str("mov\tbl,bh");
+ outnop2str("mov\tbh,al");
+ tfrhilo();
+ if ((bool_t) uflag)
+ ctoi();
+ else
+ sctoi();
+ }
+ else
+ {
+ tfrhilo();
+ outnop2str("mov\tah,bl");
+ outnop2str("mov\tbl,bh");
+ if ((bool_t) uflag)
+ outnop2str("sub\tbh,bh");
+ else
+ {
+ regexchange(reg, DREG);
+ sctoi();
+ regexchange(reg, DREG);
+ }
+ }
+ return (int) shift - CHBITSTO;
+ }
+#endif
+ return (int) shift;
+}
+
+/* take D register modulo a constant if it is easy to do with a mask */
+
+PUBLIC bool_pt modeasy(divisor, uflag)
+value_t divisor;
+bool_pt uflag;
+{
+ bool_t sign;
+
+ sign = FALSE;
+ if (divisor < 0 && !(bool_t) uflag)
+ {
+ sign = TRUE;
+ divisor = -divisor;
+ }
+ if (bitcount((uvalue_t) divisor) > 1)
+ return FALSE;
+ if (--divisor == 0)
+ clrBreg(); /* original divisor 1 or -1 yields 0 */
+ else
+ {
+ if (sign)
+ negDreg();
+ andconst((offset_t) divisor); /* if original divisor 0, this is
+ null */
+ if (sign)
+ negDreg();
+ }
+ return TRUE;
+}
+
+/* multiply register by a constant if it is easy to do with shifts */
+
+PUBLIC bool_pt muleasy(factor, reg)
+uvalue_t factor;
+store_pt reg;
+{
+ int mulstack[MAXINTBITSTO / 2 + 1]; /* must be signed, not a fastin_t */
+ fastin_pt count;
+ fastin_t single1skip;
+ fastin_t lastcount;
+ fastin_t mulsp;
+ int stackentry; /* signed */
+
+ if (factor == 0)
+ {
+ clr(reg);
+ return TRUE;
+ }
+ single1skip = 0;
+ mulsp = -1; /* may be unsigned, but bumps to 0 */
+ while (factor != 0)
+ {
+ for (lastcount = single1skip; (factor & 1) == 0; factor >>= 1)
+ ++lastcount;
+ mulstack[++mulsp] = lastcount;
+ /* first time bumps mulsp to 0 even if an unsigned char */
+ for (count = 0; (factor & 1) != 0; factor >>= 1)
+ ++count;
+ single1skip = 1;
+ if (count == 2 && factor == 0)
+ /* 3 = 2 + 1 better than 3 = 4 - 1 */
+ /* but rest of algorithm messed up unless factor now 0 */
+ mulstack[++mulsp] = 1;
+ else if (count > 1)
+ {
+ single1skip = 0;
+ if (lastcount == 1 && mulsp != 0)
+ mulstack[mulsp] = -1 - count;
+ else
+ mulstack[++mulsp] = -count;
+ }
+ }
+ if (mulsp > 3)
+ return FALSE;
+ if (mulsp != 0)
+ {
+ savefactor(reg); /* on stack or in reg as nec */
+ do
+ {
+ finishfactor(); /* finish save/add/subfactor() if nec */
+ stackentry = mulstack[mulsp--];
+ if (stackentry < 0)
+ {
+#ifdef I8088
+ if (stackentry == -INT32BITSTO)
+ clr(reg); /* shifting would do nothing */
+ else
+#endif
+ slconst((value_t) - stackentry, reg);
+ subfactor(reg); /* from wherever put by savefactor() */
+ }
+ else
+ {
+ slconst((value_t) stackentry, reg);
+ addfactor(reg); /* from wherever put by savefactor() */
+ }
+ }
+ while (mulsp != 0);
+ reclaimfactor(); /* reclaim storage if nec */
+ }
+ slconst((value_t) mulstack[0], reg);
+ return TRUE;
+}
+
+/* negate a register */
+
+PUBLIC void negreg(reg)
+store_pt reg;
+{
+ if ((store_t) reg == BREG)
+ extBnegD();
+ else
+ negDreg();
+}
+
+/* return string of operator */
+
+PUBLIC char *opstring(op)
+op_pt op;
+{
+ switch (op)
+ {
+ case ANDOP:
+ return ANDSTRING;
+ case EOROP:
+ return EORSTRING;
+ case OROP:
+ return ORSTRING;
+ }
+ return "badop";
+}
+
+/* print DREG (accumulator) */
+
+PRIVATE void outaccum()
+{
+ outstr(accumstr);
+}
+
+/* print a c compiler name with leading CCNAMEPREXFIX */
+
+PUBLIC void outccname(name)
+char *name;
+{
+ outbyte(CCNAMEPREFIX);
+ outstr(name);
+}
+
+/* print high byte of word accumulator */
+
+PUBLIC void outhiaccum()
+{
+ outstr(ACCHISTR);
+}
+
+/* print immediate address */
+
+PUBLIC void outimmadr(offset)
+offset_t offset;
+{
+#ifdef I8088
+ if (!isbyteoffset(offset))
+ outimmed();
+ else
+ outbimmed();
+#else
+ outimmed();
+#endif
+ outshex(offset);
+}
+
+/* print register, comma, immediate address and adjust lc */
+
+PUBLIC void outimadj(offset, targreg)
+offset_t offset;
+store_pt targreg;
+{
+ outregname(targreg);
+ adjlc(offset, targreg);
+ outncimmadr(offset);
+}
+
+/* print immediate address designator */
+
+PUBLIC void outimmed()
+{
+ outbyte('#');
+}
+
+PUBLIC void outjumpstring()
+{
+ outop3str(jumpstring);
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+/* print cc name, then newline */
+
+PUBLIC void outnccname(name)
+char *name;
+{
+ outccname(name);
+ outnl();
+}
+
+/* print separator, immediate address, newline */
+
+PUBLIC void outncimmadr(offset)
+offset_t offset;
+{
+#ifdef I8088
+ outcomma();
+#endif
+#ifdef MC6809
+ outtab();
+#endif
+ outimmadr(offset);
+ outnl();
+}
+
+/* print signed offset and adjust lc */
+
+PUBLIC void outoffset(offset)
+offset_t offset;
+{
+#ifdef MC6809
+ if (!is5bitoffset(offset))
+#endif
+ adjlc(offset, INDREG0);
+ outshex(offset);
+}
+
+/* print stack register */
+
+PRIVATE void outstackreg()
+{
+ outstr(stackregstr);
+}
+
+PUBLIC void public(name)
+char *name;
+{
+#ifndef AS09
+ outexport();
+ outnccname(name);
+#endif
+ outccname(name);
+ outnbyte(PUBLICENDCHAR);
+}
+
+/* print cc name as a private label */
+
+PUBLIC void private(name)
+char *name;
+{
+#ifdef LABELENDCHAR
+ outccname(name);
+ outnbyte(LABELENDCHAR);
+#else
+ outnccname(name);
+#endif
+}
+
+/* exchange registers */
+
+PUBLIC void regexchange(sourcereg, targreg)
+store_pt sourcereg;
+store_pt targreg;
+{
+ outexchange();
+ outregname(sourcereg);
+ outncregname(targreg);
+#ifdef I8088
+ if (!((sourcereg | targreg) & AXREG))
+ bumplc();
+#endif
+}
+
+/* transfer a register */
+
+PUBLIC void regtransfer(sourcereg, targreg)
+store_pt sourcereg;
+store_pt targreg;
+{
+ outtransfer();
+#ifdef TARGET_FIRST
+ outregname(targreg);
+ outncregname(sourcereg);
+#else
+ outregname(sourcereg);
+ outncregname(targreg);
+#endif
+}
+
+/* subtract carry resulting from char addition */
+
+PUBLIC void sbc0()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ adjcarry();
+ outsub();
+ outaccum();
+ outncregname(DXREG);
+ }
+ else
+#endif
+ {
+ outsbc();
+ outhiaccum();
+ outncimmadr((offset_t) 0);
+ }
+}
+
+/* set a name to a value */
+
+PUBLIC void set(name, value)
+char *name;
+offset_t value;
+{
+ outccname(funcname);
+ outbyte(LOCALSTARTCHAR);
+ outstr(name);
+ outset();
+ outshex(value);
+ outnl();
+}
+
+/* shift left register by 1 */
+
+PUBLIC void sl1(reg)
+store_pt reg;
+{
+ outsl();
+#ifdef I8088
+ outregname(reg);
+ outnc1();
+#endif
+#ifdef MC6809
+ outnregname(BREG);
+ outrolhi();
+#endif
+}
+
+/* shift left register by a constant (negative = infinity) */
+
+PUBLIC void slconst(shift, reg)
+value_t shift;
+store_pt reg;
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ if ((shift = (uvalue_t) shift % INT32BITSTO) != 0)
+ {
+ outsl();
+ if (shift != 1)
+ bumplc();
+ outregname(reg);
+ outncimmadr((offset_t) shift);
+ }
+ return;
+ }
+#endif
+ if ((uvalue_t) shift >= INT16BITSTO)
+ clr(reg);
+ else
+ {
+ if (shift >= CHBITSTO && reg == DREG)
+ {
+ tfrlohi();
+ clrBreg();
+ shift -= CHBITSTO;
+ }
+#ifdef I8088
+# if MAX_INLINE_SHIFT < INT16BITSTO
+ if (shift > MAX_INLINE_SHIFT)
+ {
+ outload();
+ outregname(SHIFTREG);
+ outcomma();
+ outimmadr((offset_t) shift);
+ outnl();
+ outsl();
+ outregname(reg);
+ outncregname(SHIFTREG);
+ }
+ else
+# endif
+#endif
+ while (shift--)
+ sl1(reg);
+ }
+}
+
+/* shift right D register by a constant (negative = infinity) */
+
+PUBLIC void srconst(shift, uflag)
+value_t shift;
+bool_pt uflag;
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ if ((shift = (uvalue_t) shift % INT32BITSTO) != 0)
+ {
+ if (uflag)
+ outusr();
+ else
+ outsr();
+ if (shift != 1)
+ bumplc();
+ outaccum();
+ outncimmadr((offset_t) shift);
+ }
+ return;
+ }
+#endif
+ if ((uvalue_t) shift >= INT16BITSTO) /* covers negatives too */
+ {
+ if ((bool_t) uflag)
+ clr(DREG);
+ else /* make D == 0 if D >= 0, else D == -1 */
+ smiDreg(); /* special case of 68020 Scc instruction */
+ }
+ else
+ {
+ if (shift >= CHBITSTO)
+ {
+ tfrhilo();
+ if ((bool_t) uflag)
+ ctoi();
+ else
+ sctoi();
+ shift -= CHBITSTO;
+ }
+#ifdef I8088
+# if MAX_INLINE_SHIFT < INT16BITSTO
+ if (shift > MAX_INLINE_SHIFT)
+ {
+ outload();
+ outregname(SHIFTREG);
+ outcomma();
+ outimmadr((offset_t) shift);
+ outnl();
+ if ((bool_t) uflag)
+ outusr();
+ else
+ outsr();
+ outaccum();
+ outncregname(SHIFTREG);
+ }
+ else
+# endif
+#endif
+ while (shift--)
+ {
+ if ((bool_t) uflag)
+ usr1();
+ else
+ sr1();
+ }
+ }
+}
+
+/* extend an unsigned in DREG to a long */
+
+PUBLIC void uitol(reg)
+store_pt reg;
+{
+ if (lowregisDreg())
+ clr(reg);
+ else
+ {
+ regexchange(DREG, reg);
+ clr(DREG);
+ }
+}
+
+PRIVATE char opregstr[] = "_opreg";
+
+/*-----------------------------------------------------------------------------
+ opregadr()
+ outputs address of variable opreg where OPREG is saved
+-----------------------------------------------------------------------------*/
+
+PRIVATE void opregadr()
+{
+#ifdef I8088
+ outindleft();
+ outccname(opregstr);
+ outindright();
+ bumplc2();
+ if (i386_32)
+ bumplc2();
+#endif
+#ifdef MC6809
+ outregname(OPREG);
+ outtab();
+ if (posindependent)
+ {
+ outccname(opregstr);
+ outncregname(GLOBAL);
+ bumplc();
+ }
+ else
+ {
+ outextended();
+ outnccname(opregstr);
+ }
+ bumplc();
+#endif
+}
+
+/*-----------------------------------------------------------------------------
+ restoreopreg()
+ restores register OPREG from static location >opreg if it is was use
+-----------------------------------------------------------------------------*/
+
+PUBLIC void restoreopreg()
+{
+ if (reguse & OPREG)
+ {
+#ifdef I8088
+ outload();
+ outregname(OPREG);
+ outopsep();
+ opregadr();
+ outnl();
+#endif
+#ifdef MC6809
+ outload();
+ opregadr();
+#endif
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ saveopreg()
+ saves register OPREG to static location >opreg if it is in use
+ this makes the flop routines non-reentrant. It is too messy to
+ push it because the flop routines leave results on the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC void saveopreg()
+{
+ if (reguse & OPREG)
+ {
+#ifdef I8088
+ bssseg();
+ common(opregstr);
+ outnhex(opregsize);
+ cseg();
+ outstore();
+ opregadr();
+ outncregname(OPREG);
+#endif
+#ifdef MC6809
+ dseg();
+ common(opregstr);
+ outnhex(opregsize);
+ cseg();
+ outstore();
+ opregadr();
+#endif
+ }
+}
diff --git a/bcc-bruce/condcode.h b/bcc-bruce/condcode.h
new file mode 100644
index 0000000..9b047df
--- /dev/null
+++ b/bcc-bruce/condcode.h
@@ -0,0 +1,16 @@
+/* condcode.h - condition codes for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define EQ 0
+#define NE 1
+#define RA 2
+#define RN 3
+#define LT 4
+#define GE 5
+#define LE 6
+#define GT 7
+#define LO 8
+#define HS 9
+#define LS 10
+#define HI 11
diff --git a/bcc-bruce/const.h b/bcc-bruce/const.h
new file mode 100644
index 0000000..8df8bcb
--- /dev/null
+++ b/bcc-bruce/const.h
@@ -0,0 +1,52 @@
+/* const.h - constants for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* switches for code generation */
+
+#define DEBUG /* generate compiler-debugging code */
+#define I8088 /* target processor is Intel 8088 thru 80386 */
+/*#define MC6809*/ /* target processor is Motorola 6809 */
+#define SELFTYPECHECK /* check calculated type = runtime type */
+
+#ifdef I8088
+# define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */
+# define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */
+# define HOLDSTRINGS /* hold strings for dumping at end
+ * since assembler has only 1 data seg */
+#endif
+
+#ifdef MC6809
+# define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */
+# define OP1 /* logical operators only use 1 byte */
+# define POSINDEPENDENT /* position indep code can (also) be gen */
+#endif
+
+/* switches for source and target operating system dependencies */
+
+/*#define SOS_EDOS*/ /* source O/S is EDOS */
+/*#define SOS_MSDOS*/ /* source O/S is MSDOS */
+/*#define TOS_EDOS*/ /* target O/S is EDOS */
+
+/* switches for source machine dependencies */
+
+#ifndef SOS_EDOS
+# define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */
+#endif
+
+#ifndef SOS_MSDOS /* need portable alignment for large model */
+# define UNPORTABLE_ALIGNMENT
+#endif
+
+/* local style */
+
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
diff --git a/bcc-bruce/debug.c b/bcc-bruce/debug.c
new file mode 100644
index 0000000..26f7bf8
--- /dev/null
+++ b/bcc-bruce/debug.c
@@ -0,0 +1,202 @@
+/* debug.c - print debug messages for operators for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+
+#ifdef DEBUG
+
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+PRIVATE char *opname[LASTOP - FIRSTOP + 1] = /* operator names */
+{ /* order must agree with op.h */
+ "cond?",
+ "or",
+ "eor",
+ "and",
+ "gt", "lt",
+ "add",
+ "div", "mod",
+ "lognot", "not",
+ "strucelt", "strucptr",
+ "eq",
+ "addab", "andab", "divab", "eorab", "modab", "mulab", "orab",
+ "slab", "srab", "subab",
+ "comma",
+ "cond:",
+ "logor",
+ "logand",
+ "logeq",
+ "ne",
+ "ge", "le",
+ "sl", "sr",
+ "sub",
+ "mul",
+ "address", "cast", "indirect", "neg",
+ "predec", "preinc", "postdec", "postinc",
+ "func", "list", "rootlist",
+ "leaf",
+ "ptraddab", "ptradd", "ptrsub",
+};
+
+FORWARD void outindchars P((int byte, indn_pt count));
+
+PUBLIC void dbitem(item)
+struct symstruct *item;
+{
+ dbtype(item->type);
+ if (item->storage == NOSTORAGE)
+ {
+ outbyte(' ');
+ outstr(item->name.namep + 2);
+ outstr(" (offset ");
+ outshex(item->offset.offi);
+ outbyte(')');
+ return;
+ }
+ if (item->storage == LOCAL)
+ {
+ outbyte(' ');
+ if (item->flags == TEMP)
+ outstr("(temp)");
+ else
+ outstr(item->name.namep);
+ }
+ outstr(" = ");
+ outindchars('[', item->indcount);
+ switch (item->storage)
+ {
+ case CONSTANT:
+ outstr("const ");
+ if (item->type->scalar & RSCALAR)
+ outstr("(whatever)");
+ else if (item->type->scalar & UNSIGNED)
+ outuvalue((uvalue_t) item->offset.offv);
+ else
+ outvalue(item->offset.offv);
+ break;
+ case BREG:
+ case DREG:
+ case INDREG0:
+ case INDREG1:
+ case INDREG2:
+#ifdef DATREG1
+ case DATREG1:
+#endif
+#ifdef DATREG2
+ case DATREG2:
+#endif
+ outregname(item->storage);
+ if (item->level == OFFKLUDGELEVEL)
+ {
+ outplus();
+ if (item->flags & LABELLED)
+ outlabel(item->name.label);
+ else
+ outccname(item->name.namep);
+ }
+ break;
+ case LOCAL:
+ outbyte('S');
+ if (sp <= 0)
+ outplus();
+ outshex(-sp);
+ break;
+ case GLOBAL:
+ if (item->flags & LABELLED)
+ outlabel(item->name.label);
+ else
+ outstr(item->name.namep);
+ break;
+ default:
+ outstr("bad storage (");
+ outhex((uoffset_t) item->storage);
+ outbyte(')');
+ outstr(" offset ");
+ }
+ if (item->storage != CONSTANT)
+ {
+ if (item->offset.offi >= 0)
+ outplus();
+ outshex(item->offset.offi);
+ }
+ outindchars(']', item->indcount);
+}
+
+PUBLIC void dbtype(type)
+struct typestruct *type;
+{
+ for ( ; type != NULL; type = type->nexttype)
+ {
+ outbyte(' ');
+ switch (type->constructor)
+ {
+ case ARRAY:
+ outbyte('[');
+ outhex(type->typesize / type->nexttype->typesize);
+ outbyte(']');
+ break;
+ case FUNCTION:
+ outstr("()");
+ break;
+ case POINTER:
+ outbyte('*');
+ break;
+ case STRUCTU:
+ outstr("struct ");
+ default:
+ if (type->scalar & UNSIGNED)
+ outstr("unsigned ");
+ outstr(type->tname);
+ break;
+ }
+ }
+}
+
+PUBLIC void debug(exp) /* sub-nodes must be leaves */
+struct nodestruct *exp;
+{
+ if (!debugon)
+ return;
+ comment();
+ if (exp->tag < FIRSTOP && exp->tag > LASTOP)
+ outstr("unknown op");
+ else
+ outstr(opname[exp->tag - FIRSTOP]);
+ if (exp->right != NULL && exp->tag != FUNCOP &&
+ exp->tag != LISTOP && exp->tag != ROOTLISTOP)
+ {
+ dbitem(exp->right->left.symptr);
+ outstr(" to");
+ }
+ dbitem(exp->left.nodeptr->left.symptr);
+ outstr(" (used reg = ");
+ if (reguse & INDREG0)
+ outregname(INDREG0);
+ if (reguse & INDREG1)
+ outregname(INDREG1);
+ if (reguse & INDREG2)
+ outregname(INDREG2);
+ outnstr(")");
+}
+
+PUBLIC void debugswap()
+{
+ if (debugon)
+ outnstr("* swapping");
+}
+
+PRIVATE void outindchars(byte, count)
+int byte;
+indn_pt count;
+{
+ while (count--)
+ outbyte(byte);
+}
+
+#endif /* DEBUG */
diff --git a/bcc-bruce/declare.c b/bcc-bruce/declare.c
new file mode 100644
index 0000000..e6b464c
--- /dev/null
+++ b/bcc-bruce/declare.c
@@ -0,0 +1,1124 @@
+/* declare.c - declaration routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "input.h" /* just for orig_cppmode */
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "parse.h"
+
+PRIVATE bool_t argsallowed; /* nonzero to allow args in declarator */
+PRIVATE sym_t gvarsc; /* sc flags of last identifier declared */
+PRIVATE char gvar2name[2 + NAMESIZE]; /* space for structure keys and .. */
+
+#define gvarname (gvar2name + 2) /* last identifier declared */
+PRIVATE struct typestruct *gvartype; /* type of last identifier declared */
+PRIVATE bool_t initlistflag; /* remembers whether initializer is a list */
+
+FORWARD struct typestruct *chainprefix P((struct typestruct *pretype,
+ struct typestruct *sufftype));
+FORWARD void declaf P((void));
+FORWARD void declarator P((void));
+FORWARD void declarg P((void));
+FORWARD struct typestruct *declenum P((void));
+FORWARD void declfunc P((void));
+FORWARD void declselt P((struct typestruct *structype, offset_t *psoffset,
+ struct typelist ** ptypelist));
+FORWARD bool_pt declspec P((void));
+FORWARD struct typestruct *declsu P((void));
+FORWARD void idecllist P((void));
+FORWARD void initarray P((struct typestruct *type));
+FORWARD void inititem P((struct typestruct *type));
+FORWARD void initstruct P((struct typestruct *type));
+FORWARD void lbrace P((void));
+FORWARD void multidecl P((char *sname));
+FORWARD void need P((int charneeded));
+FORWARD void rdeclarator P((void));
+FORWARD bool_pt regdecl P((void));
+
+PRIVATE struct typestruct *chainprefix(pretype, sufftype)
+struct typestruct *pretype;
+struct typestruct *sufftype;
+{
+ if (pretype->nexttype != NULL)
+ {
+ sufftype = chainprefix(pretype->nexttype, sufftype);
+ if (pretype->constructor != ARRAY)
+ return prefix(pretype->constructor, pretype->typesize, sufftype);
+ else
+ return prefix(ARRAY,
+ pretype->typesize / pretype->nexttype->typesize
+ * sufftype->typesize, sufftype);
+ }
+ return sufftype;
+}
+
+PUBLIC void colon()
+{
+ if (sym != COLON)
+ need(':');
+ else
+ nextsym();
+}
+
+/* decllist() - list of local declarations */
+/* this does the non-terminal symbols declaration-list, type-declaration */
+/* list and declaration */
+/* the different cases are and ";" at the end are decided by idecllist() */
+
+PUBLIC void decllist()
+{
+ while (declspec())
+ {
+ if (gvarsc == NULLDECL)
+ gvarsc = AUTODECL;
+ idecllist();
+ }
+}
+
+PRIVATE void declaf()
+{
+ uoffset_t asize;
+ bool_t levelnew;
+#ifdef TESTING_PROTOTYPES
+ char ogvarname[NAMESIZE];
+ sym_t ogvarsc;
+ struct symstruct *ogvarsymptr;
+ struct typestruct *ogvartype;
+#endif
+
+ if (sym == LPAREN) /* function */
+ {
+ nextsym();
+ if (argsallowed && level == GLBLEVEL)
+ {
+ newlevel();
+ levelnew = TRUE;
+ }
+ else
+ levelnew = FALSE;
+#ifdef TESTING_PROTOTYPES
+ strcpy(ogvarname, gvarname);
+ ogvarsc = gvarsc;
+ ogvarsymptr = gvarsymptr;
+ ogvartype = gvartype;
+ if (declspec())
+ {
+ if (level == ARGLEVEL)
+ outstr(gvarname);
+ outbyte('(');
+ do
+ {
+ declarator();
+ dbtype(gvartype);
+ outbyte(' ');
+#if 0
+ if (gvarname[0] != 0 && gsymptr != NULL
+ && gsymptr->level == level)
+ error("repeated argument");
+#endif
+ outstr(gvarname);
+ if (levelnew)
+ addloc(gsname, gvartype); /* adjust offsets later */
+ if (sym != COMMA)
+ break;
+ outcomma();
+ nextsym();
+ }
+ while (declspec());
+ if (sym == STRUCELTOP)
+ {
+ /* ... should be lexed. */
+ nextsym();
+ if (sym == STRUCELTOP)
+ {
+ nextsym();
+ if (sym == STRUCELTOP)
+ {
+ nextsym();
+ outstr(" ...");
+ }
+ }
+ }
+ outbyte(')');
+ if (level == ARGLEVEL)
+ outnl();
+ }
+ else
+ {
+#endif /* TESTING_PROTOTYPES */
+ while (sym == IDENT)
+ {
+ if (gsymptr != NULL && gsymptr->level == level)
+ error("repeated argument");
+ if (levelnew)
+ addloc(gsname, itype); /* adjust types and offsets later */
+ nextsym();
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+#ifdef TESTING_PROTOTYPES
+ }
+ strcpy(gvarname, ogvarname);
+ gvarsc = ogvarsc;
+ gvarsymptr = ogvarsymptr;
+ gvartype = ogvartype;
+#endif /* TESTING_PROTOTYPES */
+ rparen();
+ declaf();
+ switch (gvartype->constructor)
+ {
+ case ARRAY:
+ error("function returning array is illegal");
+ break;
+ case FUNCTION:
+ error("function returning function is illegal");
+ break;
+ }
+ gvartype = prefix(FUNCTION, ftypesize, gvartype);
+ }
+ else if (sym == LBRACKET)
+ {
+ nextsym();
+ if (sym == RBRACKET)
+ asize = 0;
+ else
+ asize = constexpression() & intmaskto; /* FIXME: warn overflow */
+ rbracket();
+ declaf();
+ if (gvartype->typesize == 0)
+ switch (gvartype->constructor)
+ {
+ case FUNCTION:
+ error("array of functions is illegal");
+ break;
+ case STRUCTU:
+ error("undefined structure");
+ break;
+ default: /* array */
+ error("null dimension");
+ gvartype->typesize = 1;
+ }
+ gvartype = prefix(ARRAY, asize * gvartype->typesize, gvartype);
+ }
+}
+
+PRIVATE void declarator()
+{
+ rdeclarator();
+ if (gvartype->constructor == STRUCTU && gvartype->typesize == 0 &&
+ gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL)
+ error("undefined structure");
+}
+
+PRIVATE void declarg()
+{
+ if (gvarsymptr->level != ARGLEVEL)
+ error2error(gvarname, " not in argument list");
+ else if (gvarsymptr->flags & INITIALIZED && gvarsymptr->type != gvartype)
+ multidecl(gvarname);
+ else
+ {
+ gvarsymptr->flags = INITIALIZED; /* flag otherwise unused for locals */
+ if (gvartype->constructor & (ARRAY | POINTER))
+ gvartype = pointype(gvartype->nexttype);
+ gvarsymptr->type = gvartype;
+ if (gvarsc == REGDECL && regdecl())
+ regarg = TRUE;
+ }
+}
+
+/*
+enum-specifier =
+ "enum" [identifier] "{" enumerator {, enumerator} "}"
+ | "enum" identifier.
+enumerator =
+ identifier
+ | identifier = constant-expression.
+*/
+
+PRIVATE struct typestruct *declenum()
+{
+ register struct symstruct *esymptr;
+ register struct typestruct *enumtype;
+ offset_t ordinal;
+
+ nextsym();
+ if (sym != IDENT && sym != TYPEDEFNAME)
+ enumtype = addstruct("");
+ else if ((esymptr = findstruct(gsname)) == NULL)
+ {
+ enumtype = addstruct(gsname);
+ nextsym();
+ }
+ else
+ {
+ nextsym();
+ enumtype = esymptr->type;
+ if (sym != LBRACE)
+ return enumtype;
+ if (esymptr->level != level)
+ enumtype = addstruct(esymptr->name.namea);
+ }
+ lbrace();
+ if (enumtype->typesize != 0)
+ multidecl(enumtype->tname);
+ else
+ {
+ enumtype->typesize = itypesize;
+ enumtype->alignmask = itype->alignmask;
+ }
+ if (sym != IDENT)
+ error("empty enumerator list");
+ ordinal = 0;
+ while (sym == IDENT)
+ {
+ if ((esymptr = gsymptr) != NULL && esymptr->level == level)
+ multidecl(gsname);
+ else
+ {
+ (esymptr = addlorg(gsname, itype))->storage = CONSTANT;
+ esymptr->indcount = 0;
+ }
+ nextsym();
+ if (sym == ASSIGNOP)
+ {
+ nextsym();
+ ordinal = constexpression() & intmaskto; /* FIXME: warn ovflo */
+ if (ordinal > maxintto)
+ ordinal -= (maxuintto + 1);
+ }
+ if (esymptr->storage == CONSTANT)
+ esymptr->offset.offv = ordinal++;
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+ rbrace();
+ return enumtype;
+}
+
+/* declselt - get list of declarations for a structure/union member */
+
+PRIVATE void declselt(structype, psoffset, ptypelist)
+struct typestruct *structype;
+offset_t *psoffset;
+struct typelist **ptypelist;
+{
+ struct typestruct *basetype;
+ value_t fieldwidth;
+ value_t fwidth;
+ offset_t offset;
+ scalar_t scalar;
+
+ offset = *psoffset;
+ declspec();
+ if (gvarsc != NULLDECL)
+ error("illegal type name");
+ basetype = gvartype;
+ while (sym != SEMICOLON && sym != EOFSYM)
+ {
+ gvartype = basetype;
+ declarator();
+ fieldwidth = -1;
+ if (sym == COLON)
+ {
+ scalar = gvartype->scalar;
+ if (!(scalar & ISCALAR))
+ error("bitfield has non-integral type");
+ nextsym();
+ fwidth = constexpression();
+ if (fwidth < 0)
+ error("bitfield has negative width");
+ else if (fwidth > INT32BITSTO) /* XXX */
+ error("bitfield is too wide");
+ else
+ fieldwidth = fwidth;
+ }
+ if (gvarname[0] == 0)
+ {
+ if (fieldwidth == 0)
+ offset = (offset + ~gvartype->alignmask) & gvartype->alignmask;
+ else
+ /* XXX - should really align to fieldwidth'th bit. */
+ offset = (offset + ~gvartype->alignmask) & gvartype->alignmask;
+ }
+ else
+ {
+ if (fieldwidth == 0)
+ error("bitfield has zero width");
+ else if (fieldwidth > 0 && scalar & ISCALAR)
+ {
+ if (fieldwidth <= CHBITSTO) /* XXX! */
+ gvartype = ctype;
+ else if (fieldwidth <= INT32BITSTO) /* XXX */
+ gvartype = itype;
+ else
+ gvartype = ltype;
+ if (scalar & UNSIGNED)
+ gvartype = tounsigned(gvartype);
+ }
+ gvar2name[0] = structype->structkey[0];
+ gvar2name[1] = structype->structkey[1];
+ /* key provides unique name space */
+ if (findlorg(gvar2name) != NULL)
+ multidecl(gvarname);
+ else
+ {
+ (gvarsymptr = addlorg(gvar2name, gvartype))->storage
+ = NOSTORAGE;
+ structype->alignmask &= gvartype->alignmask;
+ offset = (gvarsymptr->offset.offi =
+ (offset+ ~gvartype->alignmask) & gvartype->alignmask)
+ + gvartype->typesize;
+ {
+ register struct typelist *newtypelist;
+
+ newtypelist = qmalloc(sizeof *newtypelist);
+#ifdef TS
+++ts_n_newtypelist;
+ts_s_newtypelist += sizeof *newtypelist;
+#endif
+ newtypelist->tlnext = NULL;
+ newtypelist->tltype = gvartype;
+ if (*ptypelist == NULL)
+ structype->listtype = newtypelist;
+ else
+ (*ptypelist)->tlnext = newtypelist;
+ *ptypelist = newtypelist;
+ }
+ }
+ }
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+ semicolon();
+ *psoffset = offset;
+}
+
+PRIVATE bool_pt declspec()
+{
+ unsigned nsc;
+ unsigned ntype;
+ unsigned nunsigned;
+
+ gvarsc = NULLDECL;
+ gvartype = itype;
+ nunsigned = ntype = nsc = 0;
+ while (TRUE)
+ {
+ switch (sym)
+ {
+ case AUTODECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case ENUMDECL:
+ ++ntype;
+ declenum();
+ gvartype = itype; /* kludge - ignore type of enum */
+ break;
+ case EXTERNDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case REGDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case STATICDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case STRUCTDECL:
+ case UNIONDECL:
+ ++ntype;
+ gvartype = declsu();
+ break;
+ case TYPEDECL:
+ if (ntype == 1)
+ {
+ /* allow short int and long int */
+ if (gvartype == itype
+ && (gsymptr->type == stype || gsymptr->type == ltype))
+ ntype = 0;
+
+ /* allow int short and int long, blech */
+ if (gsymptr->type == itype
+ && (gvartype == stype || gvartype == ltype))
+ {
+ nextsym();
+ break;
+ }
+ }
+ ++ntype;
+ gvartype = gsymptr->type;
+ nextsym();
+ break;
+ case TYPEDEFDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case TYPEDEFNAME:
+ if (ntype != 0)
+ goto break2;
+ ++ntype;
+ gvartype = gsymptr->type;
+ nextsym();
+ break;
+ case UNSIGNDECL:
+ ++nunsigned;
+ nextsym();
+ break;
+ default:
+ goto break2;
+ }
+ }
+break2:
+ if (nunsigned > 0)
+ {
+ if (ntype == 0)
+ {
+ gvartype = uitype;
+ ntype = 1;
+ }
+ gvartype = tounsigned(gvartype);
+ if (nunsigned > 1)
+ ntype = 2;
+ }
+ if (nsc > 0)
+ {
+ if (ntype == 0)
+ ntype = 1;
+ if (nsc > 1)
+ error("multiple storage classes in declaration");
+ }
+ if (ntype > 1)
+ error("multiple types in declaration");
+ return nsc > 0 || ntype > 0;
+}
+
+/* declsu - get structure or union name and/or declaration, return type */
+
+PRIVATE struct typestruct *declsu()
+{
+ sym_t ogvarsc;
+ offset_t soffset;
+ offset_t struclength;
+ sym_t susym;
+ struct typelist *typelist;
+ struct typestruct *structype;
+
+ susym = sym;
+ nextsym();
+ if (sym != IDENT && sym != TYPEDEFNAME)
+ structype = addstruct("");
+ else if ((gvarsymptr = findstruct(gsname)) == NULL)
+ {
+ structype = addstruct(gsname);
+ nextsym();
+ }
+ else
+ {
+ nextsym();
+ if (sym == LBRACE && gvarsymptr->level != level)
+ structype = addstruct(gvarsymptr->name.namea);
+ else
+ structype = gvarsymptr->type;
+ }
+ if (sym != LBRACE)
+ return structype;
+ if (structype->typesize != 0)
+ multidecl(structype->tname);
+ nextsym();
+ ogvarsc = gvarsc;
+ struclength = soffset = 0;
+ typelist = NULL;
+ while (sym != RBRACE && sym != EOFSYM)
+ {
+ declselt(structype, &soffset, &typelist);
+ if (susym == STRUCTDECL)
+ struclength = soffset;
+ else
+ {
+ if (struclength < soffset)
+ struclength = soffset;
+ soffset = 0;
+ }
+ }
+ structype->typesize = (struclength + ~structype->alignmask) &
+ structype->alignmask;
+ rbrace();
+ gvarsc = ogvarsc;
+ return structype;
+}
+
+/* declfunc() - function name and parameter list */
+
+PRIVATE void declfunc()
+{
+ offset_t argsp;
+ uoffset_t argsize;
+ struct symstruct *symptr;
+
+ strcpy(funcname, gvarname);
+ if (gvarsymptr == NULL)
+ gvarsymptr = addglb(gvarname, gvartype);
+ else if (gvarsymptr->type != gvartype ||
+ (gvarsymptr->flags & INITIALIZED))
+ multidecl(gvarname); /* different type or full declare */
+ gvarsymptr->flags = INITIALIZED; /* show full declare */
+ cseg();
+ if (gvarsc == STATICDECL)
+ private(gvarname); /* don't need to put STATIC in flags */
+ else
+ public(gvarname);
+ callee1mask = calleemask;
+#ifdef FRAMEPOINTER
+ frame1list = framelist;
+#endif
+ func1saveregsize = funcsaveregsize;
+#if 0
+ if ((returntype = gvartype->nexttype)->scalar & RSCALAR)
+#else
+ if ((returntype = gvartype->nexttype)->scalar & DOUBLE)
+#endif
+ {
+ callee1mask &= ~doublreturnregs;
+#ifdef FRAMEPOINTER
+ frame1list &= ~doublreturnregs;
+#endif
+ func1saveregsize = funcdsaveregsize;
+ }
+
+ arg1size = /* would already be 0 unless last function empty */
+#ifdef FRAMEPOINTER
+ framep =
+ stackarg =
+#endif
+ reguse = 0; /* would already be 0 unless last f had reg vars */
+ decllist();
+ argsp = returnadrsize;
+ if (returntype->constructor & STRUCTU)
+ argsp += ptypesize;
+ softsp = -func1saveregsize;
+ for (symptr = &locsyms[0];
+ symptr < locptr && symptr->flags != STRUCTNAME &&
+ *symptr->name.namea >= 'A';
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ {
+ /* convert arg sizes to offsets */
+ if (symptr->type == fltype)
+ symptr->type = dtype;
+ argsize = symptr->type->typesize;
+#ifdef FRAMEPOINTER
+ if (!arg1inreg || symptr != &locsyms[0] || symptr->flags != REGVAR)
+ stackarg = TRUE;
+#endif
+ if (arg1inreg && symptr == &locsyms[0] && symptr->flags != REGVAR)
+ {
+ if ((arg1size = argsize) < itypesize)
+ arg1size = itypesize;
+ argsp = softsp -= arg1size;
+ }
+#if BIG_ENDIAN
+ if (argsize < itypesize)
+ argsp += itypesize - argsize;
+ symptr->offset.offi = argsp;
+ argsp += argsize;
+#else
+ symptr->offset.offi = argsp;
+ if (argsize > itypesize)
+ argsp += argsize;
+ else
+ argsp += itypesize;
+#endif
+ if (arg1inreg && symptr == &locsyms[0])
+ argsp = returnadrsize; /* skip return adr after 1st arg */
+ }
+ lbrace();
+ compound();
+ clearfunclabels();
+}
+
+/* idecllist() - list of init-declarations with a given base type */
+/* this does the non-terminal symbols list( init-declarator ) ";" */
+/* and list( type-declaration ) ";" */
+/* and complete declarations of functions */
+
+PRIVATE void idecllist()
+{
+ struct typestruct *basetype;
+ struct typestruct *inittype;
+ scopelev_t levelmark;
+ uoffset_t newoffset;
+
+ argsallowed = level == GLBLEVEL;
+ levelmark = level;
+ basetype = gvartype;
+ while (sym != SEMICOLON)
+ {
+ gvartype = basetype;
+ declarator();
+ if (gvarname[0] == 0)
+ needvarname();
+ if (gvartype->constructor == FUNCTION)
+ {
+ if (sym != COMMA && sym != SEMICOLON)
+ {
+ if (level == ARGLEVEL && gvarsc != TYPEDEFDECL)
+ declfunc();
+ else
+ error("illegal non-external function");
+ if (level != levelmark)
+ {
+ oldlevel();
+ locptr = &locsyms[0];
+ }
+ argsallowed = FALSE;
+ return;
+ }
+ }
+ if (level != levelmark)
+ {
+ oldlevel();
+ locptr = &locsyms[0];
+ }
+ argsallowed = FALSE;
+ if (level == ARGLEVEL)
+ {
+ if (gvarsymptr == NULL)
+ gvarsymptr = addglb(gvarname, gvartype); /* error soon */
+ declarg();
+ }
+ else if (gvarsymptr != NULL && (gvarsymptr->level == level ||
+ gvartype->constructor == FUNCTION ||
+ gvarsc == EXTERNDECL &&
+ gvarsymptr->level == GLBLEVEL))
+ {
+ if (gvarsymptr->level != GLBLEVEL || gvarsymptr->flags == KEYWORD)
+ multidecl(gvarname);
+ else if (gvarsymptr->type != gvartype)
+ {
+ if (gvartype->constructor != ARRAY ||
+ gvarsymptr->type->constructor != ARRAY ||
+ gvartype->nexttype != gvarsymptr->type->nexttype ||
+ gvartype->typesize != 0 &&
+ gvarsymptr->type->typesize != 0)
+ multidecl(gvarname);
+ else if (gvartype->typesize != 0)
+ gvarsymptr->type = gvartype;
+ }
+ if (gvarsc == NULLDECL)
+ gvarsymptr->flags &= ~EXTERNAL;
+ }
+ else if (level == GLBLEVEL || gvartype->constructor == FUNCTION ||
+ gvarsc == EXTERNDECL)
+ {
+ gvarsymptr = addglb(gvarname, gvartype);
+#ifdef DIRECTPAGE /* make all global scalar and pointer variables DIRECTPAGE */
+ if (!(gvartype->constructor & ~POINTER))
+ gvarsymptr->flags = DIRECTPAGE;
+#endif
+ if (gvarsc == EXTERNDECL)
+ gvarsymptr->flags |= EXTERNAL;
+ }
+ else
+ {
+ gvarsymptr = addloc(gvarname, gvartype);
+ if ((gvarsc != REGDECL || !regdecl()) &&
+ gvartype->constructor != FUNCTION && gvarsc != STATICDECL &&
+ gvarsc != TYPEDEFDECL)
+ gvarsymptr->offset.offi = softsp =
+ (softsp & gvartype->alignmask) - gvartype->typesize;
+ }
+ if (gvarsc == STATICDECL)
+ {
+ gvarsymptr->flags &= ~EXTERNAL;
+ gvarsymptr->flags |= STATIC;
+ if (gvarsymptr->level != GLBLEVEL)
+ {
+ gvarsymptr->storage = GLOBAL;
+ gvarsymptr->offset.offlabel = getlabel();
+ /* must leave gvarsymptr->name.label alone */
+ /* since name is required for findlorg() */
+ /* label is activated by expression() */
+ }
+ }
+ if (gvarsc == TYPEDEFDECL)
+ {
+ gvarsymptr->flags = KEYWORD;
+ gvarsymptr->offset.offsym = TYPEDEFNAME;
+ }
+ if (sym == ASSIGNOP)
+ {
+ if (gvarsymptr->flags & INITIALIZED)
+ multidecl(gvarname);
+ nextsym();
+ if (level == GLBLEVEL || gvarsc == STATICDECL)
+ {
+#ifndef DIRECTPAGE
+ dseg();
+#else
+ if (gvarsymptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ if ((inittype = gvartype)->constructor == ARRAY)
+ inittype = inittype->nexttype;
+ newoffset = (dataoffset + ~inittype->alignmask)
+ & inittype->alignmask;
+ defnulls(newoffset - dataoffset);
+ dataoffset = newoffset;
+ if (gvarsc == STATICDECL)
+ {
+ if (level == GLBLEVEL)
+ private(gvarname);
+ else
+ outnlabel(gvarsymptr->offset.offlabel);
+ }
+ else
+ public(gvarname);
+ initlistflag = TRUE;
+ if (sym != LBRACE)
+ initlistflag = FALSE;
+ inititem(gvartype);
+ dataoffset += (gvarsymptr->type = gvartype)->typesize;
+ if (gvarsymptr->level == GLBLEVEL)
+ gvarsymptr->flags |= INITIALIZED;
+ if (level != GLBLEVEL)
+ cseg();
+ }
+ else
+ {
+ if (gvarsc == EXTERNDECL)
+ error("initialization of externs is illegal");
+ switch (gvartype->constructor)
+ {
+ case ARRAY:
+ error("initialization of auto arrays is illegal");
+ break;
+ case FUNCTION:
+ error("initialization of functions is illegal");
+ break;
+ default:
+ initexpression(gvartype);
+ break;
+ }
+ }
+ }
+ else if (level != GLBLEVEL && gvarsc == STATICDECL &&
+ gvartype->constructor != FUNCTION)
+ {
+#ifndef DIRECTPAGE
+ bssseg();
+#else
+ if (gvarsymptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ lcommlab(gvarsymptr->offset.offlabel);
+ outnhex(gvartype->typesize);
+ cseg();
+ }
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+ semicolon();
+ argsallowed = FALSE;
+}
+
+PRIVATE void initarray(type)
+struct typestruct *type;
+{
+ uoffset_t basesize;
+ struct typestruct *basetype;
+ uoffset_t dimension;
+ char *stringend;
+ uoffset_t stringlength;
+ uoffset_t remaining;
+
+ if ((basesize = (basetype = type->nexttype)->typesize) == 0)
+ dimension = remaining = 0;
+ else
+ dimension = remaining = type->typesize / basesize;
+ if (sym == STRINGCONST && (basetype->scalar & CHAR))
+ {
+ stringlength = (stringend = charptr) - constant.value.s;
+ if (remaining != 0 && stringlength >= remaining)
+ /* same dim should be allowed but defstr always nullterms */
+ {
+ error("string longer than dimension");
+ stringend = constant.value.s + (/* size_t */ unsigned)
+ (stringlength = remaining - 1);
+ }
+ defstr(constant.value.s, stringend, TRUE);
+ remaining -= (stringlength + 1);
+ nextsym();
+ }
+ else
+ do
+ inititem(basetype);
+ while (--remaining != 0 && sym == COMMA && initlistflag &&
+ (nextsym(), sym != RBRACE));
+ if (dimension == 0)
+ {
+ if (type == gvartype)
+ gvartype = prefix(ARRAY, -remaining * basesize, basetype);
+ }
+ else
+ defnulls(remaining * basesize);
+}
+
+PRIVATE void inititem(type)
+struct typestruct *type;
+{
+ sym_t startsym;
+
+ if ((startsym = sym) == LBRACE)
+ nextsym();
+ switch (type->constructor)
+ {
+ case ARRAY:
+ initarray(type);
+ break;
+ case STRUCTU:
+ initstruct(type);
+ break;
+ case FUNCTION:
+ error("initialization of functions is illegal");
+ break;
+ default:
+ initexpression(type);
+ }
+ if (startsym == LBRACE)
+ {
+ if (sym == COMMA)
+ {
+ nextsym();
+ if (sym != RBRACE)
+ error("too many initializers");
+ }
+ rbrace();
+ }
+}
+
+PRIVATE void initstruct(type)
+struct typestruct *type;
+{
+ struct typestruct *memtype;
+ uoffset_t newoffset;
+ uoffset_t offset;
+ struct typelist *typelist;
+
+ offset = 0;
+ if ((typelist = type->listtype) != NULL)
+ do
+ {
+ memtype = typelist->tltype;
+ newoffset = (offset + ~memtype->alignmask) & memtype->alignmask;
+ defnulls(newoffset - offset);
+ offset = newoffset + memtype->typesize;
+ inititem(memtype);
+ }
+ while ((typelist = typelist->tlnext) != NULL && sym == COMMA &&
+ initlistflag && (nextsym(), sym != RBRACE));
+ /* eof here will break next time */
+ defnulls(type->typesize - offset);
+}
+
+PRIVATE void lbrace()
+{
+ if (sym != LBRACE)
+ need('{');
+ else
+ nextsym();
+}
+
+PUBLIC void lparen()
+{
+ if (sym != LPAREN)
+ need('(');
+ else
+ nextsym();
+}
+
+PRIVATE void multidecl(sname)
+char *sname;
+{
+ error2error(sname, " already declared");
+}
+
+PRIVATE void need(charneeded)
+int charneeded;
+{
+ static char message[] = "need 'x'";
+
+ message[6] = charneeded;
+ error(message);
+}
+
+PUBLIC void needvarname()
+{
+ error("need variable name");
+ nextsym();
+}
+
+PUBLIC void program()
+{
+ if (orig_cppmode)
+ cppscan();
+ else
+ {
+ nextsym();
+ while (sym != EOFSYM)
+ {
+ declspec();
+ idecllist();
+ }
+ }
+}
+
+PUBLIC void rbrace()
+{
+ if (sym != RBRACE)
+ need('}');
+ else
+ nextsym();
+}
+
+PUBLIC void rbracket()
+{
+ if (sym != RBRACKET)
+ need(']');
+ else
+ nextsym();
+}
+
+PRIVATE void rdeclarator()
+{
+ while (sym == STAR)
+ {
+ nextsym();
+ gvartype = pointype(gvartype);
+ }
+ if (sym == LPAREN)
+ {
+ struct typestruct *pretype;
+ struct typestruct *sufftype;
+
+ nextsym();
+ sufftype = gvartype;
+ gvartype = ctype;
+ rdeclarator();
+ rparen();
+ pretype = gvartype;
+ gvartype = sufftype;
+ declaf();
+ gvartype = chainprefix(pretype, gvartype);
+ }
+ else if (sym == IDENT || sym == TYPEDEFNAME)
+ {
+ strcpy(gvarname, gsname);
+ gvarsymptr = gsymptr;
+ nextsym();
+ }
+ else
+ {
+ gvarname[0] = 0;
+ gvarsymptr = NULL;
+ }
+ declaf();
+}
+
+PRIVATE bool_pt regdecl()
+{
+ store_t regavail;
+
+#if !NOTFINISHED
+ if (gvarsymptr->type->constructor != POINTER)
+ return FALSE;
+#endif
+#ifdef MC6809
+ if (gvarsymptr->type->constructor != POINTER)
+ return FALSE;
+#endif
+ if (!(regavail = regregs & ~reguse))
+ return FALSE;
+ gvarsymptr->flags = REGVAR;
+ gvarsymptr->indcount = 0;
+#define LOWBITMASK(bits) (bits - (bits & (bits - 1))) /* & chops low bit */
+ reguse |= gvarsymptr->storage = LOWBITMASK(regavail);
+ return TRUE;
+}
+
+PUBLIC void rparen()
+{
+ if (sym != RPAREN)
+ need(')');
+ else
+ nextsym();
+}
+
+PUBLIC void semicolon()
+{
+ if (sym != SEMICOLON)
+ need(';');
+ else
+ nextsym();
+}
+
+PUBLIC struct typestruct *typename()
+{
+ char ogvarname[NAMESIZE];
+ sym_t ogvarsc;
+ struct symstruct *ogvarsymptr;
+ struct typestruct *ogvartype;
+ struct typestruct *type;
+
+ /* the global variable data must be preserved */
+ /* although this is only called for casts and sizeof, */
+ /* the casts can be in initialisers */
+ /* and the sizeof in an array size expression */
+ strcpy(ogvarname, gvarname);
+ ogvarsc = gvarsc;
+ ogvarsymptr = gvarsymptr;
+ ogvartype = gvartype;
+ if (declspec())
+ {
+ declarator();
+ if (gvarsc != NULLDECL || gvarname[0] != 0)
+ error("illegal type name");
+ type = gvartype;
+ }
+ else
+ type = NULL;
+ strcpy(gvarname, ogvarname);
+ gvarsc = ogvarsc;
+ gvarsymptr = ogvarsymptr;
+ gvartype = ogvartype;
+ return type;
+}
diff --git a/bcc-bruce/express.c b/bcc-bruce/express.c
new file mode 100644
index 0000000..e6ee64c
--- /dev/null
+++ b/bcc-bruce/express.c
@@ -0,0 +1,466 @@
+/* express.c - expression parsing routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "table.h" /* just for charptr for string constant */
+#include "type.h"
+
+PRIVATE unsigned insizeof; /* nest level for getsizeof */
+ /* used to avoid aborting undefined idents */
+ /* to 0 when they appear in a cpp expression */
+ /* under sizeof */
+
+/* names of expression functions are related to the 15 precedence levels */
+/* on p49 of K & R */
+
+FORWARD struct nodestruct *cast_exp P((void));
+FORWARD struct nodestruct *exp2 P((void));
+FORWARD struct nodestruct *exp3to12 P((fastin_pt lprecedence));
+FORWARD struct nodestruct *listargs P((void));
+FORWARD struct nodestruct *postfix_exp P((bool_pt seenlp));
+FORWARD struct nodestruct *primary_exp P((void));
+FORWARD struct nodestruct *unary_exp P((void));
+
+PRIVATE struct nodestruct *cast_exp()
+{
+ struct nodestruct *nodeptr;
+ scalar_t scalar;
+ struct typestruct *vartype;
+
+ if (sym != LPAREN)
+ return unary_exp();
+ nextsym();
+ if ((vartype = typename()) == NULL)
+ return postfix_exp(TRUE);
+ rparen();
+ scalar = (nodeptr = cast_exp())->nodetype->scalar;
+ if (vartype->scalar & INT && scalar & (CHAR | SHORT | INT)
+ && !((vartype->scalar ^ scalar) & UNSIGNED))
+ {
+ nodeptr->flags &= ~LVALUE;
+ return nodeptr; /* skip casts that are default promotions */
+ }
+ return castnode(vartype, nodeptr);
+}
+
+PUBLIC struct nodestruct *assignment_exp()
+{
+ struct nodestruct *lhs;
+ op_pt op;
+
+ lhs = exp2();
+ if (sym >= ASSIGNOP && sym <= SUBABOP) /* assign-op syms in order! */
+ {
+ op = sym;
+ nextsym();
+ lhs = node(op, lhs, assignment_exp());
+ }
+ return lhs;
+}
+
+PUBLIC struct nodestruct *expression()
+{
+ struct nodestruct *lhs;
+
+ lhs = assignment_exp();
+ while (sym == COMMA)
+ {
+ nextsym();
+ lhs = node(COMMAOP, lhs, assignment_exp());
+ }
+ return lhs;
+}
+
+PRIVATE struct nodestruct *exp2()
+{
+ struct nodestruct *lhs;
+ struct nodestruct *rhs;
+
+ lhs = exp3to12(0);
+ if (sym == CONDOP)
+ {
+ nextsym();
+ rhs = expression();
+ colon();
+ lhs = node(CONDOP, lhs, node(COLONOP, rhs, exp2()));
+ }
+ return lhs;
+}
+
+PRIVATE struct nodestruct *exp3to12(lprecedence)
+fastin_pt lprecedence;
+{
+ struct nodestruct *lhs;
+ op_pt op;
+ fastin_t rprecedence;
+
+ lhs = cast_exp();
+ while (TRUE)
+ {
+ rprecedence = 0;
+ switch (sym)
+ {
+ case LOGOROP:
+ if ((fastin_t) lprecedence <= 1)
+ rprecedence = 2;
+ break;
+ case LOGANDOP:
+ if ((fastin_t) lprecedence <= 3)
+ rprecedence = 4;
+ break;
+ case OROP:
+ if ((fastin_t) lprecedence <= 5)
+ rprecedence = 6;
+ break;
+ case EOROP:
+ if ((fastin_t) lprecedence <= 7)
+ rprecedence = 8;
+ break;
+ case AMPERSAND:
+ if ((fastin_t) lprecedence <= 9)
+ {
+ sym = ANDOP;
+ rprecedence = 10;
+ }
+ break;
+ case EQOP:
+ case NEOP:
+ if ((fastin_t) lprecedence <= 11)
+ rprecedence = 12;
+ break;
+ case GEOP:
+ case GTOP:
+ case LEOP:
+ case LTOP:
+ if ((fastin_t) lprecedence <= 13)
+ rprecedence = 14;
+ break;
+ case SLOP:
+ case SROP:
+ if ((fastin_t) lprecedence <= 15)
+ rprecedence = 16;
+ break;
+ case HYPHEN:
+ if ((fastin_t) lprecedence <= 17)
+ {
+ sym = SUBOP;
+ rprecedence = 18;
+ }
+ break;
+ case ADDOP:
+ if ((fastin_t) lprecedence <= 17)
+ rprecedence = 18;
+ break;
+ case STAR:
+ if ((fastin_t) lprecedence <= 19)
+ {
+ sym = MULOP;
+ rprecedence = 20;
+ }
+ break;
+ case DIVOP:
+ case MODOP:
+ if ((fastin_t) lprecedence <= 19)
+ rprecedence = 20;
+ break;
+ }
+ if (rprecedence == 0)
+ break;
+ op = sym;
+ nextsym();
+ lhs = node(op, lhs, exp3to12(rprecedence));
+ }
+ return lhs;
+}
+
+PRIVATE struct nodestruct *listargs()
+{
+ struct nodestruct *parent;
+ struct nodestruct *nextright;
+
+ if (sym == RPAREN)
+ {
+ nextsym();
+ return NULLNODE;
+ }
+ parent = node(arg1op, assignment_exp(), NULLNODE);
+ nextright = parent;
+ while (sym == COMMA)
+ {
+ nextsym();
+ nextright = nextright->right
+ = node(LISTOP, assignment_exp(), NULLNODE);
+ }
+ rparen();
+ return parent;
+}
+
+PRIVATE struct nodestruct *postfix_exp(seenlp)
+bool_pt seenlp;
+{
+ struct nodestruct *nodeptr;
+ struct symstruct *symptr;
+
+ if (seenlp)
+ {
+ nodeptr = expression();
+ rparen();
+ }
+ else
+ nodeptr = primary_exp();
+ while (TRUE)
+ {
+ switch (sym)
+ {
+ case DECSYM:
+ nextsym();
+ nodeptr = node(POSTDECOP, nodeptr, NULLNODE);
+ continue;
+ case INCSYM:
+ nextsym();
+ nodeptr = node(POSTINCOP, nodeptr, NULLNODE);
+ continue;
+ case LBRACKET:
+ nextsym();
+ nodeptr = node(INDIRECTOP, node(ADDOP, nodeptr, expression()),
+ NULLNODE);
+ rbracket();
+ continue;
+ case LPAREN:
+ nextsym();
+ nodeptr = node(FUNCOP, nodeptr, listargs());
+ {
+ register struct nodestruct *np;
+
+ for (np = nodeptr->right; np != NULL; np = np->right)
+ {
+ if (np->nodetype->scalar & RSCALAR)
+ {
+ np = nodeptr->left.nodeptr;
+ if (np->tag != LEAF)
+ printf_fp = TRUE;
+ else
+ {
+ unsigned len;
+ register char *name;
+
+ name = np->left.symptr->name.namep;
+ if ((len = strlen(name)) >= 6
+ && strcmp(name + len - 6, "printf") == 0)
+ printf_fp = TRUE;
+ }
+ break;
+ }
+ }
+ for (np = nodeptr->right; np != NULL; np = np->right)
+ {
+ if (np->nodetype->constructor & POINTER
+ && np->nodetype->nexttype->scalar & RSCALAR)
+ {
+ np = nodeptr->left.nodeptr;
+ if (np->tag != LEAF)
+ scanf_fp = TRUE;
+ else
+ {
+ unsigned len;
+ register char *name;
+
+ name = np->left.symptr->name.namep;
+ if ((len = strlen(name)) >= 5
+ && strcmp(name + len - 5, "scanf") == 0)
+ scanf_fp = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ continue;
+ case STRUCPTROP:
+ nodeptr = node(INDIRECTOP, nodeptr, NULLNODE);
+ case STRUCELTOP:
+ nextsym();
+ gs2name[0] = nodeptr->nodetype->structkey[0];
+ gs2name[1] = nodeptr->nodetype->structkey[1];
+ if ((gsymptr = findlorg(gs2name)) == NULL)
+ {
+ error("undefined structure element");
+ gsymptr = addglb(gs2name, itype);
+ }
+ symptr = exprsym(gsymptr);
+ nextsym();
+ nodeptr = node(STRUCELTOP, nodeptr, leafnode(symptr));
+ continue;
+ default:
+ return nodeptr;
+ }
+ }
+}
+
+PRIVATE struct nodestruct *primary_exp()
+{
+ bool_t isdefined;
+ struct nodestruct *nodeptr;
+ uoffset_t stringlen;
+ struct symstruct *symptr;
+ struct symstruct *symptr1;
+ bool_t waslparen;
+
+ switch (sym)
+ {
+ case IDENT:
+ if (incppexpr && !insizeof)
+ {
+cpp_ident:
+ nextsym();
+ return leafnode(constsym((value_t) 0));
+ }
+ if ((symptr = gsymptr) != NULL)
+ nextsym();
+ else
+ {
+ symptr = addglb(gsname, fitype);
+ nextsym();
+ if (sym != LPAREN)
+ {
+ error2error(symptr->name.namea, " undeclared");
+ symptr->indcount = 1;
+ symptr->type = itype;
+ }
+ }
+ symptr1 = exprsym(symptr);
+ if (symptr->flags & STATIC && symptr->level != GLBLEVEL)
+ {
+ symptr1->flags |= LABELLED;
+ symptr1->offset.offi = 0;
+ symptr1->name.label = symptr->offset.offlabel;
+ }
+ nodeptr = leafnode(symptr1);
+ if (!(nodeptr->nodetype->constructor & (ARRAY | FUNCTION | VOID)))
+ nodeptr->flags = LVALUE;
+ return nodeptr;
+ case TYPEDEFNAME:
+ if (incppexpr && !insizeof)
+ goto cpp_ident; /* else fall through */
+ default:
+ error("bad expression");
+ constant.value.v = 0;
+ constant.type = itype;
+ case CHARCONST:
+ case INTCONST: /* this includes enumeration-constants */
+ symptr = constsym(constant.value.v);
+ symptr->type = constant.type;
+ if (!(ltype->scalar & LONG))
+ {
+ if (symptr->type == ltype)
+ symptr->type = itype;
+ else if (symptr->type == ultype)
+ symptr->type = uitype;
+ }
+ nextsym();
+ return leafnode(symptr);
+ case DEFINEDSYM:
+ waslparen = isdefined = FALSE;
+ if (!blanksident())
+ {
+ nextsym();
+ if (sym != LPAREN)
+ lparen();
+ else
+ waslparen = TRUE;
+ }
+ if (waslparen && !blanksident())
+ needvarname();
+ else
+ {
+ if ((symptr = findlorg(gsname)) != NULL &&
+ symptr->flags == DEFINITION)
+ isdefined = TRUE;
+ nextsym();
+ }
+ if (waslparen)
+ rparen();
+ return leafnode(constsym((value_t) isdefined));
+ case FLOATCONST:
+ symptr = constsym((value_t) 0);
+ symptr->type = constant.type;
+ symptr->offset.offd = qmalloc(sizeof *symptr->offset.offd);
+ *symptr->offset.offd = constant.value.d;
+ nextsym();
+ return leafnode(symptr);
+ case LPAREN:
+ nextsym();
+ nodeptr = expression();
+ rparen();
+ return nodeptr;
+ case STRINGCONST:
+ symptr = constsym((value_t) 0);
+ symptr->storage = GLOBAL;
+ symptr->flags = LABELLED | STRING;
+ /* string length before defstr() or prefix() updates charptr */
+ stringlen = charptr - constant.value.s + 1;
+ symptr->name.label = defstr(constant.value.s, charptr, FALSE);
+ symptr->type = prefix(ARRAY, stringlen, ctype);
+ nextsym();
+ return leafnode(symptr);
+ }
+}
+
+PRIVATE struct nodestruct *unary_exp()
+{
+ value_t size;
+ struct typestruct *vartype;
+
+ switch (sym)
+ {
+ case ADDOP:
+ nextsym();
+ return cast_exp();
+ case AMPERSAND:
+ nextsym();
+ return node(ADDRESSOP, cast_exp(), NULLNODE); /* maybe unary_exp */
+ case DECSYM:
+ nextsym();
+ return node(PREDECOP, unary_exp(), NULLNODE);
+ case HYPHEN:
+ nextsym();
+ return node(NEGOP, cast_exp(), NULLNODE);
+ case INCSYM:
+ nextsym();
+ return node(PREINCOP, unary_exp(), NULLNODE);
+ case LOGNOTOP:
+ nextsym();
+ return node(LOGNOTOP, cast_exp(), NULLNODE);
+ case NOTOP:
+ nextsym();
+ return node(NOTOP, cast_exp(), NULLNODE);
+ case SIZEOFSYM:
+ nextsym();
+ ++insizeof;
+ if (sym != LPAREN)
+ size = unary_exp()->nodetype->typesize;
+ else
+ {
+ nextsym();
+ if ((vartype = typename()) != NULL)
+ {
+ rparen();
+ size = vartype->typesize;
+ }
+ else
+ size = postfix_exp(TRUE)->nodetype->typesize;
+ }
+ --insizeof;
+ return leafnode(constsym(size));
+ case STAR:
+ nextsym();
+ return node(INDIRECTOP, cast_exp(), NULLNODE); /* maybe unary_exp */
+ }
+ return postfix_exp(FALSE);
+}
diff --git a/bcc-bruce/exptree.c b/bcc-bruce/exptree.c
new file mode 100644
index 0000000..32d9386
--- /dev/null
+++ b/bcc-bruce/exptree.c
@@ -0,0 +1,1086 @@
+/* exptree.c - expression tree routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#define ETREESIZE 1200
+#define errtype itype
+#define redtype ctype
+#define uredtype uctype
+
+PRIVATE struct nodestruct etree[ETREESIZE]; /* expression tree */
+PRIVATE struct nodestruct *ettop;
+
+FORWARD void badlvalue P((struct nodestruct *nodeptr));
+FORWARD void binconvert P((struct nodestruct *nodeptr));
+FORWARD void castiright P((struct nodestruct *nodeptr));
+FORWARD void etreefull P((void));
+FORWARD void fixnode P((struct nodestruct *nodeptr));
+FORWARD bool_pt isconst0 P((struct nodestruct *nodeptr));
+FORWARD bool_pt isnodecharconst P((struct nodestruct *nodeptr));
+FORWARD void needint P((struct nodestruct *nodeptr));
+FORWARD void neednonstruct P((struct nodestruct *nodeptr));
+FORWARD void needscalar P((struct nodestruct *nodeptr));
+FORWARD void needspv P((struct nodestruct *nodeptr));
+FORWARD struct typestruct *nodetype P((struct nodestruct *nodeptr));
+FORWARD int redscalar P((struct nodestruct *nodeptr));
+FORWARD struct nodestruct *unconvert P((struct nodestruct *nodeptr));
+
+PRIVATE void badlvalue(nodeptr)
+struct nodestruct *nodeptr;
+{
+ error("invalid lvalue");
+ fixnode(nodeptr);
+}
+
+PRIVATE void binconvert(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ bool_t bothscalar;
+ value_t divisor;
+ scalar_t lscalar;
+ register struct nodestruct *right;
+ scalar_t rscalar;
+
+ rscalar = (right = nodeptr->right)->nodetype->scalar;
+ lscalar = nodeptr->left.nodeptr->nodetype->scalar;
+ if ((bothscalar = lscalar | rscalar) & RSCALAR)
+ {
+ nodeptr->nodetype = dtype;
+ if (!(lscalar & DOUBLE))
+ nodeptr->left.nodeptr = castnode(dtype, nodeptr->left.nodeptr);
+ if (!(rscalar & DOUBLE))
+ nodeptr->right = castnode(dtype, right);
+ }
+ else if (!(bothscalar & DLONG) && (nodeptr->tag == ANDOP &&
+ (redscalar(nodeptr->left.nodeptr) | redscalar(right)) & CHAR ||
+ (nodeptr->tag == EOROP || nodeptr->tag == OROP) &&
+ redscalar(nodeptr->left.nodeptr) & redscalar(right) & CHAR ||
+ nodeptr->tag == MODOP && right->tag == LEAF &&
+ right->left.symptr->storage == CONSTANT &&
+ (divisor = right->left.symptr->offset.offv,
+ (uvalue_t) divisor <= MAXUCHTO + 1) &&
+ bitcount((uvalue_t) divisor) <= 1))
+ {
+ /* result fits in char and extends correctly */
+ if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = uredtype;
+ else
+ nodeptr->nodetype = redtype;
+ }
+ else if (bothscalar & LONG)
+ {
+ nodeptr->nodetype = ltype;
+ if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = ultype;
+ if (bothscalar & (DLONG | SHORT | INT))
+ {
+ /* XXX - otherwise both are long, or one is long with the same
+ * size as int and the other is char, and we want the lower level
+ * routines to handle the char.
+ */
+ if (!(lscalar & LONG))
+ nodeptr->left.nodeptr = castnode(nodeptr->nodetype,
+ nodeptr->left.nodeptr);
+ if (!(rscalar & LONG))
+ nodeptr->right = castnode(nodeptr->nodetype, right);
+ }
+ }
+#ifdef I8088
+ else if (i386_32 && bothscalar & SHORT)
+ {
+ nodeptr->nodetype = itype;
+ if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = uitype;
+ if (lscalar & SHORT)
+ nodeptr->left.nodeptr = castnode(nodeptr->nodetype,
+ nodeptr->left.nodeptr);
+ if (rscalar & SHORT)
+ nodeptr->right = castnode(nodeptr->nodetype, right);
+ }
+#endif
+ else if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = uitype;
+ else
+ nodeptr->nodetype = itype;
+}
+
+PRIVATE void castiright(nodeptr)
+struct nodestruct *nodeptr;
+{
+ nodeptr->right = castnode(itype, nodeptr->right);
+}
+
+PUBLIC struct nodestruct *castnode(type, nodeptr)
+struct typestruct *type;
+struct nodestruct *nodeptr;
+{
+ struct symstruct *symptr;
+
+ (symptr = constsym((value_t) 0))->type = type;
+ return node(CASTOP, nodeptr, leafnode(symptr));
+}
+
+PRIVATE void etreefull()
+{
+ limiterror("expression too complex (1201 nodes)");
+}
+
+PUBLIC void etreeinit()
+{
+ ettop = (etptr = etree) + ETREESIZE;
+}
+
+PRIVATE void fixnode(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ nodeptr->tag = LEAF;
+ nodeptr->flags = nodeptr->weight = 0;
+ nodeptr->left.symptr = constsym((value_t) 0); /* this has type errtype */
+ nodeptr->nodetype = errtype;
+}
+
+PRIVATE bool_pt isconst0(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ register struct symstruct *symptr;
+
+ return nodeptr->tag == LEAF &&
+ (symptr = nodeptr->left.symptr)->storage == CONSTANT &&
+ symptr->offset.offv == 0 &&
+ symptr->type->scalar & ISCALAR;
+}
+
+PRIVATE bool_pt isnodecharconst(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ register struct symstruct *symptr;
+
+ if (nodeptr->tag == LEAF &&
+ (symptr = nodeptr->left.symptr)->storage == CONSTANT &&
+ ischarconst(symptr->offset.offv) &&
+ symptr->type->scalar & ISCALAR)
+ return TRUE;
+ return FALSE;
+}
+
+PUBLIC struct nodestruct *leafnode(source)
+struct symstruct *source;
+{
+ register struct nodestruct *leafptr;
+
+ if ((leafptr = etptr++) >= ettop)
+ etreefull();
+ leafptr->tag = LEAF;
+ leafptr->flags = leafptr->weight = 0;
+ leafptr->nodetype = source->type;
+ leafptr->left.symptr = source;
+ leafptr->right = NULL;
+ return leafptr;
+}
+
+PRIVATE void needint(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (!(nodeptr->nodetype->scalar & ISCALAR))
+ {
+ error("need integral type");
+ fixnode(nodeptr);
+ }
+}
+
+PRIVATE void neednonstruct(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (nodeptr->nodetype->constructor & STRUCTU)
+ {
+ error("need non-structure type");
+ fixnode(nodeptr);
+ }
+}
+
+PRIVATE void needscalar(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (!nodeptr->nodetype->scalar)
+ {
+ error("need scalar");
+ fixnode(nodeptr);
+ }
+}
+
+PRIVATE void needspv(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION | STRUCTU))
+ {
+ error("need scalar or pointer or void");
+ fixnode(nodeptr);
+ }
+}
+
+PUBLIC struct nodestruct *node(t, p1, p2)
+op_pt t;
+struct nodestruct *p1;
+struct nodestruct *p2;
+{
+#if MAXREGS != 1
+ weight_t rightweight;
+#endif
+ double dsourceval;
+ double dtargval;
+ bool_t lflag;
+ scalar_t lscalar;
+ struct nodestruct *pswap;
+ struct symstruct *source;
+ value_t sourceval;
+ struct symstruct *target;
+ offset_t targszdelta;
+ value_t targval;
+ scalar_t rscalar;
+ bool_t uflag;
+
+ switch ((op_t) t)
+ {
+ case ADDABOP:
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ t = PTRADDABOP;
+ break;
+ case ADDOP:
+ if (p2->nodetype->constructor & (ARRAY | POINTER))
+ {
+ pswap = p1;
+ p1 = p2;
+ p2 = pswap;
+ }
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ t = PTRADDOP;
+ break;
+ case CONDOP:
+ /* Change structs to struct pointers so condop() doesn't have to know
+ * about structs.
+ */
+ if (p2->nodetype->constructor & STRUCTU)
+ {
+ p2 = node(COLONOP, node(ADDRESSOP, p2->left.nodeptr, NULLNODE),
+ node(ADDRESSOP, p2->right, NULLNODE));
+ return node(INDIRECTOP, node(CONDOP, p1, p2), NULLNODE);
+ }
+ break;
+ case FUNCOP:
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ p1 = node(INDIRECTOP, p1, NULLNODE);
+ break;
+ case SUBABOP:
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ {
+ t = PTRADDABOP;
+ p2 = node(NEGOP, p2, NULLNODE);
+ break;
+ }
+ case SUBOP:
+#if 0
+ /* This works but sometimes pessimizes the code by converting small
+ * constants into large negative constants. It makes the most
+ * difference for longs by avoiding stack tangles. longop could be
+ * more careful. Only the case (regpair) - constant is naturally
+ * tangled.
+ */
+ if (p2->tag == LEAF && p2->nodetype->scalar
+ && (source = p2->left.symptr)->storage == CONSTANT)
+ {
+ if (source->type->scalar & RSCALAR)
+ *source->offset.offd = -*source->offset.offd;
+ else
+ source->offset.offv = -source->offset.offv;
+ return node((op_t) t == SUBOP ? ADDOP : ADDABOP, p1, p2);
+ }
+#endif
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ {
+ if (p2->nodetype->nexttype == p1->nodetype->nexttype)
+ t = PTRSUBOP;
+ else
+ {
+ t = PTRADDOP;
+ p2 = node(NEGOP, p2, NULLNODE);
+ }
+ }
+ break;
+ }
+ if (((op_t) t == PTRADDABOP || (op_t) t == PTRADDOP) &&
+ p1->nodetype->nexttype->constructor & (FUNCTION | VOID))
+ error("arithmetic on pointer to function or void");
+ if (p1->tag != LEAF)
+ goto node1;
+ target = p1->left.symptr;
+ switch ((op_t) t)
+ {
+ case ADDRESSOP:
+ if (target->indcount == 0 && target->flags == REGVAR)
+ error("register variable addressed");
+ else if (target->type->constructor & ARRAY)
+ {
+ if (target->indcount != 0)
+ bugerror("botched array indirection count");
+ target->type = pointype(target->type);
+ }
+ else if (!(p1->flags & LVALUE))
+ badlvalue(p1);
+ else
+ {
+ address(target); /* change p1, no code generated */
+ if (target->indcount == 2) /* XXX - MAXINDIRECT? */
+ /* just became direct enough */
+ p1->weight = 1;
+ }
+ p1->flags &= ~LVALUE;
+ p1->nodetype = target->type;
+ return p1;
+ case CASTOP:
+ needspv(p2);
+ if (p1->nodetype == p2->nodetype)
+ {
+ p1->flags &= ~LVALUE;
+ return p1;
+ }
+ if ((rscalar = p2->nodetype->scalar) & ISCALAR)
+ neednonstruct(p1);
+ else if (rscalar & RSCALAR)
+ needscalar(p1);
+ else /* POINTER */
+ neednonstruct(p1); /* H & S say functions & arrays must match */
+ if (((lscalar = p1->nodetype->scalar) | rscalar) & RSCALAR)
+ {
+ if (target->storage != CONSTANT)
+ goto node1;
+ if (lscalar & RSCALAR && !(rscalar & RSCALAR))
+ {
+ double val;
+
+ val = *target->offset.offd;
+ if (val > maxlongto)
+ val -= (double) (unsigned long) 0xFFFFFFFF + 1; /* XXX */
+ target->offset.offv = (value_t) val;
+ }
+ if (!(lscalar & RSCALAR) && rscalar & RSCALAR)
+ {
+ value_t val;
+
+ val = target->offset.offv;
+ target->offset.offd = qmalloc(sizeof *target->offset.offd);
+ if (lscalar & UNSIGNED)
+ *target->offset.offd = (uvalue_t) val;
+ else
+ *target->offset.offd = val;
+ }
+ }
+ if (target->storage == CONSTANT)
+ {
+ if (rscalar & CHAR)
+ target->offset.offv &= CHMASKTO;
+ else if (rscalar & SHORT)
+ {
+ target->offset.offv &= shortmaskto;
+ if (!(rscalar & UNSIGNED) && target->offset.offv > maxshortto)
+ target->offset.offv -= (maxushortto + 1);
+ }
+ else if (rscalar & INT)
+ {
+ target->offset.offv &= intmaskto;
+ if (!(rscalar & UNSIGNED) && target->offset.offv > maxintto)
+ target->offset.offv -= (maxuintto + 1);
+ }
+ else if (rscalar & FLOAT)
+ *target->offset.offd = (float) *target->offset.offd;
+ }
+ else if ((targszdelta =
+ ((p1->nodetype->constructor & (ARRAY | POINTER)) ?
+ ptypesize : p1->nodetype->typesize) -
+ p2->nodetype->typesize) == 0)
+ ;
+ else if (target->indcount == 1 && targszdelta > 0 &&
+ target->flags != REGVAR)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+# if BIG_ENDIAN
+ target->offset.offi += targszdelta;
+# else
+ {
+ if (lscalar & DLONG)
+ target->offset.offi += itypesize; /* discard msword */
+ }
+# endif
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+# if BIG_ENDIAN
+ {
+ if (rscalar & CHAR)
+ target->offset.offi += ctypesize;
+ }
+# else
+ ;
+# endif
+#endif
+ }
+ else
+ goto node1;
+ p1->flags &= ~LVALUE;
+ p1->nodetype = target->type = p2->nodetype;
+ return p1;
+ case INDIRECTOP:
+ if (!(target->type->constructor & (ARRAY | POINTER)))
+ error("illegal indirection");
+ else
+ {
+ indirec(target);
+ if (target->indcount == 3) /* XXX - MAXINDIRECT + 1? */
+ /* just became too indirect */
+ p1->weight = 1;
+ p1->flags |= LVALUE;
+ p1->nodetype = target->type;
+ }
+ return p1;
+ case STRUCELTOP: /* p2 known leaf */
+ if (target->indcount != 1)
+ break; /* struc() would generate code */
+ struc(p2->left.symptr, target);
+ p1->flags |= LVALUE;
+ p1->nodetype = target->type;
+ return p1;
+ }
+ if (target->indcount != 0)
+ goto node1;
+ lscalar = target->type->scalar;
+ if (target->storage == CONSTANT)
+ {
+ if (lscalar & RSCALAR)
+ dtargval = *target->offset.offd;
+ else
+ targval = target->offset.offv;
+ switch ((op_t) t)
+ {
+ case COMMAOP:
+ return p2;
+ case CONDOP:
+ if (lscalar & RSCALAR && dtargval != FALSE
+ || !(lscalar & RSCALAR) && targval != FALSE)
+ {
+ p2->left.nodeptr->nodetype = p2->nodetype;
+ return p2->left.nodeptr;
+ }
+ p2->right->nodetype = p2->nodetype;
+ return p2->right;
+ case LOGANDOP:
+ if (lscalar & RSCALAR && dtargval != FALSE
+ || !(lscalar & RSCALAR) && targval != FALSE)
+ break;
+ p1->nodetype = target->type = itype;
+ return p1;
+ case LOGOROP:
+ if (lscalar & RSCALAR && dtargval == FALSE
+ || !(lscalar & RSCALAR) && targval == FALSE)
+ break;
+ target->offset.offv = TRUE;
+ p1->nodetype = target->type = itype;
+ return p1;
+ }
+ }
+ switch ((op_t) t)
+ {
+ case COLONOP:
+ case FUNCOP:
+ case LISTOP:
+ case ROOTLISTOP:
+ goto node1;
+ case PTRADDOP:
+ if (p2->tag == LEAF &&
+ (source = p2->left.symptr)->storage == CONSTANT &&
+ source->type->scalar & ISCALAR)
+ {
+ indexadr(source, target);
+ p1->flags &= ~LVALUE;
+ p1->nodetype = target->type;
+ return p1;
+ }
+ }
+ if (target->storage != CONSTANT ||
+ !(lscalar & (ISCALAR | RSCALAR)) && (op_t) t != PTRSUBOP ||
+ p2 != NULL &&
+ (p2->tag != LEAF || (source = p2->left.symptr)->storage != CONSTANT ||
+ !((rscalar = source->type->scalar) & (ISCALAR | RSCALAR))
+ && (op_t) t != PTRSUBOP))
+ goto node1;
+ lflag = lscalar & LONG;
+ uflag = lscalar & UNSIGNED;
+ if (p2 != NULL)
+ {
+ if (rscalar & RSCALAR)
+ dsourceval = *source->offset.offd;
+ else
+ {
+ sourceval = source->offset.offv;
+ lflag |= rscalar & LONG;
+ uflag |= rscalar & UNSIGNED;
+ }
+ }
+ if (lscalar & RSCALAR || p2 != NULL && rscalar & RSCALAR)
+ {
+ if (!(lscalar & RSCALAR))
+ {
+ if (uflag)
+ dtargval = (uvalue_t) targval;
+ else
+ dtargval = targval;
+ }
+ if (p2 != NULL && !(rscalar & RSCALAR))
+ {
+ if (rscalar & UNSIGNED)
+ dsourceval = (uvalue_t) sourceval;
+ else
+ dsourceval = sourceval;
+ }
+ switch ((op_t) t)
+ {
+ case ADDOP:
+ dtargval += dsourceval;
+ break;
+ case DIVOP:
+ if (dsourceval == 0)
+ {
+ error("divison by 0");
+ dsourceval = 1;
+ }
+ dtargval /= dsourceval;
+ break;
+ case EQOP:
+ targval = dtargval == dsourceval;
+ goto intconst;
+ case GEOP:
+ targval = dtargval >= dsourceval;
+ goto intconst;
+ case GTOP:
+ targval = dtargval > dsourceval;
+ goto intconst;
+ case LEOP:
+ targval = dtargval <= dsourceval;
+ goto intconst;
+ case LOGANDOP:
+ targval = dtargval && dsourceval;
+ goto intconst;
+ case LOGNOTOP:
+ targval = !dtargval;
+ goto intconst;
+ case LOGOROP:
+ targval = dtargval || dsourceval;
+ goto intconst;
+ case LTOP:
+ targval = dtargval < dsourceval;
+ goto intconst;
+ case MULOP:
+ dtargval *= dsourceval;
+ break;
+ case NEGOP:
+ dtargval = -dtargval;
+ break;
+ case NEOP:
+ targval = dtargval != dsourceval;
+ goto intconst;
+ case SUBOP:
+ dtargval -= dsourceval;
+ break;
+ }
+ /* XXX - leaks memory */
+ target->offset.offd = qmalloc(sizeof *target->offset.offd);
+ *target->offset.offd = dtargval;
+ p1->nodetype = target->type = dtype;
+ return p1;
+ }
+ switch ((op_t) t)
+ {
+ case ADDOP:
+ targval += sourceval;
+ break;
+ case ANDOP:
+ targval &= sourceval;
+ break;
+ case DIVOP:
+ if (sourceval == 0)
+ {
+ error("divison by 0");
+ sourceval = 1;
+ }
+ if (uflag)
+ targval = (uvalue_t) targval / sourceval;
+ else
+ targval /= sourceval;
+ break;
+ case EOROP:
+ targval ^= sourceval;
+ break;
+ case EQOP:
+ targval = targval == sourceval;
+ break;
+ case GEOP:
+ if (uflag)
+ targval = (uvalue_t) targval >= sourceval;
+ else
+ targval = targval >= sourceval;
+ goto intconst;
+ case GTOP:
+ if (uflag)
+ targval = (uvalue_t) targval > sourceval;
+ else
+ targval = targval > sourceval;
+ goto intconst;
+ case LEOP:
+ if (uflag)
+ targval = (uvalue_t) targval <= sourceval;
+ else
+ targval = targval <= sourceval;
+ goto intconst;
+ case LOGANDOP:
+ targval = targval && sourceval;
+ goto intconst;
+ case LOGNOTOP:
+ targval = !targval;
+ goto intconst;
+ case LOGOROP:
+ targval = targval || sourceval;
+ goto intconst;
+ case LTOP:
+ if (uflag)
+ targval = (uvalue_t) targval < sourceval;
+ else
+ targval = targval < sourceval;
+ goto intconst;
+ break;
+ case MODOP:
+ if (sourceval == 0)
+ {
+ error("modulo by 0");
+ sourceval = 1;
+ }
+ if (uflag)
+ targval = (uvalue_t) targval % sourceval;
+ else
+ targval %= sourceval;
+ break;
+ case MULOP:
+ targval *= sourceval;
+ break;
+ case NEGOP:
+ targval = -targval;
+ break;
+ case NEOP:
+ targval = targval != sourceval;
+ goto intconst;
+ case NOTOP:
+ targval = ~targval;
+ break;
+ case OROP:
+ targval |= sourceval;
+ break;
+ case PTRSUBOP:
+ if (targval < sourceval)
+ targval = -((uvalue_t) (sourceval - targval) /
+ target->type->nexttype->typesize);
+ else
+ targval = (uvalue_t) (targval - sourceval) /
+ target->type->nexttype->typesize;
+ uflag = FALSE;
+ break;
+ case SLOP:
+ targval <<= sourceval; /* assume shiftcount treated as unsigned */
+ lflag = lscalar & LONG;
+ uflag = lscalar & UNSIGNED;
+ break;
+ case SROP:
+ if (uflag)
+ targval = (uvalue_t) targval >> sourceval;
+ else
+ targval >>= sourceval;
+ lflag = lscalar & LONG;
+ uflag = lscalar & UNSIGNED;
+ break;
+ case SUBOP:
+ targval -= sourceval;
+ break;
+ }
+ if (lflag)
+ {
+ target->type = ltype;
+ if (uflag)
+ target->type = ultype;
+ }
+ else
+ {
+ targval &= intmaskto;
+ if (uflag)
+ target->type = uitype;
+ else
+ {
+ target->type = itype;
+ if (targval > maxintto)
+ targval -= (maxuintto + 1);
+ }
+ }
+ target->offset.offv = targval;
+ p1->nodetype = target->type;
+ return p1;
+
+intconst:
+ target->offset.offv = targval;
+ p1->nodetype = target->type = itype;
+ return p1;
+
+node1:
+ {
+ register struct nodestruct *nodeptr;
+ register struct nodestruct *regp2;
+
+ if ((nodeptr = etptr++) >= ettop)
+ etreefull();
+ regp2 = p2;
+ nodeptr->tag = t;
+ nodeptr->left.nodeptr = p1;
+ nodeptr->right = regp2;
+ if ((op_t) t == FUNCOP)
+ nodeptr->weight = MAXREGS + 1;
+ else
+ {
+#if MAXREGS == 1
+ if ((nodeptr->weight = p1->weight) <= MAXREGS &&
+ (regp2 == NULL ||
+ (nodeptr->weight = regp2->weight) < MAXREGS))
+ nodeptr->weight = MAXREGS;
+#else
+ nodeptr->weight = p1->weight;
+ if (regp2 == NULL)
+ rightweight = 1; /* could do POST-ops with 0 */
+ else /* 0 more approp for LIST-ops but 1 OK */
+ rightweight = regp2->weight;
+ if (nodeptr->weight < rightweight)
+ nodeptr->weight = rightweight;
+ else if (nodeptr->weight == rightweight &&
+ nodeptr->weight < MAXREGS)
+ ++nodeptr->weight;
+#endif
+ }
+ nodeptr->nodetype = nodetype(nodeptr);
+ return nodeptr;
+ }
+}
+
+PRIVATE struct typestruct *nodetype(nodeptr)
+struct nodestruct *nodeptr;
+{
+ scalar_t bothscalar;
+ scalar_t lscalar;
+ scalar_t rscalar;
+ struct nodestruct *left;
+ struct nodestruct *right;
+ struct typestruct *targtype;
+
+ if (nodeptr->tag == LEAF)
+ return nodeptr->left.symptr->type;
+ targtype = (left = nodeptr->left.nodeptr)->nodetype;
+ right = nodeptr->right;
+ switch (nodeptr->tag)
+ {
+ case FUNCOP:
+ if (!(targtype->constructor & FUNCTION))
+ {
+ error("call of non-function");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ return targtype->nexttype;
+ case INDIRECTOP:
+ if (!(targtype->constructor & (ARRAY | POINTER)))
+ {
+ error("illegal indirection");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ nodeptr->flags |= LVALUE;
+ return targtype->nexttype;
+ case LISTOP:
+ case ROOTLISTOP:
+ nodeptr->left.nodeptr = unconvert(left);
+ return promote(targtype);
+ case CASTOP:
+ needspv(right);
+ case COMMAOP:
+ case CONDOP:
+ return right->nodetype;
+
+ case STRUCELTOP:
+ nodeptr->flags |= LVALUE;
+ return right->nodetype;
+
+ case ADDRESSOP:
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ return pointype(targtype);
+ case LOGNOTOP:
+ neednonstruct(left);
+ return redtype;
+ case NEGOP:
+ needscalar(left);
+ return promote(left->nodetype);
+ case NOTOP:
+ needint(left);
+ return promote(left->nodetype);
+ case PREDECOP:
+ case PREINCOP:
+ case POSTDECOP:
+ case POSTINCOP:
+ neednonstruct(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ break;
+
+ case ANDOP:
+ case EOROP:
+ case MODOP:
+ case OROP:
+ needint(left);
+ needint(right);
+ /* fall through to redundant check and code to cast to same types */
+ case ADDOP:
+ case DIVOP:
+ case MULOP:
+ case SUBOP:
+ needscalar(left);
+ needscalar(right);
+ binconvert(nodeptr);
+ return nodeptr->nodetype;
+
+ case PTRADDABOP:
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ case PTRADDOP: /* right type conversion to same size as ptr */
+ needint(right);
+ if (right->nodetype->scalar & LONG)
+ castiright(nodeptr);
+ break;
+ case PTRSUBOP: /* already checked */
+ return itype;
+ case SLOP: /* right type conversion always to int */
+ case SROP: /* ulong strictly to unsigned but no matter */
+ needint(left);
+ needint(right);
+ if (right->nodetype->scalar & LONG)
+ castiright(nodeptr);
+ return promote(left->nodetype);
+
+ case LTOP:
+ case LEOP:
+ case GTOP:
+ case GEOP:
+ case EQOP:
+ case LOGOROP:
+ case LOGANDOP:
+ case NEOP:
+ neednonstruct(left);
+ neednonstruct(right);
+ nodeptr->left.nodeptr = left = unconvert(left);
+ nodeptr->right = right = unconvert(right);
+#ifdef MAYBE_DO_LATER /* OK if pointers fit in uitype */
+ if (left->nodetype->constructor & POINTER)
+ nodeptr->left.nodeptr = left = castnode(uitype, left);
+ if (right->nodetype->constructor & POINTER)
+ nodeptr->right = right = castnode(uitype, right);
+#endif
+ binconvert(nodeptr);
+ return redtype;
+
+ case COLONOP:
+ if (isnodecharconst(left) && isnodecharconst(right))
+ {
+ targtype = (targtype->scalar | right->nodetype->scalar) & UNSIGNED
+ ? uctype : ctype;
+ left = castnode(targtype, left);
+ right = castnode(targtype, right);
+ }
+ nodeptr->left.nodeptr = left = unconvert(left);
+ nodeptr->right = right = unconvert(right);
+ if ((targtype = left->nodetype) == right->nodetype)
+ return targtype; /* XXX - reduced from promote(targtype) */
+ if ((lscalar = targtype->scalar) != 0 &&
+ (rscalar = right->nodetype->scalar) != 0)
+ {
+ /* promote minimally without using binconvert for char/short */
+ if ((bothscalar = lscalar | rscalar) & (LONG | RSCALAR))
+ {
+ binconvert(nodeptr);
+ return nodeptr->nodetype;
+ }
+ if (bothscalar & INT || (lscalar ^ rscalar) & UNSIGNED)
+ targtype = itype;
+ else if (bothscalar & SHORT)
+ targtype = stype;
+ else
+ targtype = ctype;
+ if (bothscalar & UNSIGNED)
+ targtype = tounsigned(targtype);
+ if (!(bothscalar & INT) || left->tag == LEAF && lscalar & INT ||
+ right->tag == LEAF && rscalar & INT)
+ {
+ /* this is correct even when the if fails (the casts have to */
+ /* be considered at a lower level) but gives worse code */
+ if (left->nodetype != targtype)
+ nodeptr->left.nodeptr = castnode(targtype, left);
+ if (right->nodetype != targtype)
+ nodeptr->right = castnode(targtype, right);
+ }
+ return targtype; /* XXX - reduced from promote(targtype) */
+ }
+ if (targtype->constructor & POINTER &&
+ (isconst0(right) || right->nodetype->constructor & POINTER &&
+ right->nodetype->nexttype->constructor & VOID))
+ return targtype;
+ if (right->nodetype->constructor & POINTER &&
+ (isconst0(left) || targtype->constructor & POINTER &&
+ targtype->nexttype->constructor & VOID))
+ return right->nodetype;
+ error("mismatched types");
+ fixnode(left); /* XXX - better to fix the CONDOP */
+ fixnode(right);
+ return errtype;
+
+ case ASSIGNOP:
+ if (right->nodetype->constructor & VOID)
+ {
+ error("assignment of void");
+ fixnode(right);
+ }
+ if (targtype->constructor & (ARRAY | FUNCTION | VOID))
+ {
+ error("assignment to array, function or void");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ if ((targtype->constructor | right->nodetype->constructor)
+ & STRUCTU && targtype != right->nodetype)
+ {
+ error("assignment to/from struct/union of a different type");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+#if 0
+ /* XXX - this is done at the lowest levels, with too many chances for
+ * errors.
+ */
+ if (targtype != right->nodetype)
+ nodeptr->right = castnode(left->nodetype, right);
+#endif
+ break;
+ case ANDABOP:
+ case EORABOP:
+ case MODABOP:
+ case ORABOP:
+ needint(right);
+ needint(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ /* fall through to redundant check and code to cast to same types */
+ case ADDABOP:
+ case SUBABOP:
+ case DIVABOP:
+ case MULABOP:
+ needscalar(right);
+ needscalar(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ rscalar = right->nodetype->scalar;
+ if ((lscalar = (targtype = left->nodetype)->scalar) & RSCALAR)
+ {
+ if (!(rscalar & DOUBLE))
+ nodeptr->right = castnode(dtype, right);
+ }
+ else if (lscalar & LONG)
+ {
+ if (!(rscalar & LONG))
+ nodeptr->right = castnode(rscalar & UNSIGNED
+ ? ultype : targtype, right);
+ }
+#ifdef I8088
+ else if (i386_32 && lscalar & INT)
+ {
+ if (rscalar & SHORT)
+ nodeptr->right = castnode(rscalar & UNSIGNED
+ ? uitype : targtype, right);
+ }
+#endif
+ break;
+ case SLABOP:
+ case SRABOP:
+ needint(right);
+ needint(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ if (!(right->nodetype->scalar & INT))
+ castiright(nodeptr);
+ break;
+ }
+ return left->nodetype;
+}
+
+PRIVATE int redscalar(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ if (isnodecharconst(nodeptr))
+ return CHAR;
+ return nodeptr->nodetype->scalar;
+}
+
+PRIVATE struct nodestruct *unconvert(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION))
+ return castnode(pointype(nodeptr->nodetype->constructor & ARRAY ?
+ nodeptr->nodetype->nexttype :
+ nodeptr->nodetype), nodeptr);
+ return nodeptr;
+}
diff --git a/bcc-bruce/floatop.c b/bcc-bruce/floatop.c
new file mode 100644
index 0000000..fb9c54d
--- /dev/null
+++ b/bcc-bruce/floatop.c
@@ -0,0 +1,173 @@
+/* floatop.c - software operations on floats and doubles for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ f_indirect(target leaf)
+ make the float or double target indirect if it is not already
+ return nonzero iff the result is a temp double on the base of the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC bool_pt f_indirect(target)
+struct symstruct *target;
+{
+ if (target->indcount == 0)
+ {
+ if (target->storage == CONSTANT)
+ {
+ /* XXX - more for non-386 */
+ if (target->type->scalar & FLOAT)
+ {
+ float val;
+
+ val = *target->offset.offd;
+ push(constsym(((value_t *) &val)[0]));
+ }
+ else
+ {
+ push(constsym(((value_t *) target->offset.offd)[1]));
+ push(constsym(((value_t *) target->offset.offd)[0]));
+ }
+ }
+ else if (target->type->scalar & FLOAT)
+ pushlist(target->storage); /* XXX - floatregs */
+ else
+ pushlist(doubleregs);
+ onstack(target);
+ }
+ return target->flags == TEMP && target->type->scalar & DOUBLE
+ && target->offset.offi == sp;
+}
+
+/*-----------------------------------------------------------------------------
+ float1op(operation code, source leaf)
+ handles all flop unary operations except inc/dec
+ result is double on stack (or in condition codes for EQOP)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void float1op(op, source)
+op_pt op;
+struct symstruct *source;
+{
+ saveopreg();
+ pointat(source);
+ if ((op_t) op == NEGOP)
+ call("Fneg");
+ else /* op == EQOP */
+ call("Ftst");
+ outntypechar(source->type);
+ if ((op_t) op != EQOP)
+ justpushed(source);
+ restoreopreg();
+}
+
+/*-----------------------------------------------------------------------------
+ floatop(operation code, source leaf, target leaf)
+ handles all flop binary operations
+ result is double on stack (or in condition codes for EQOP)
+----------------------------------------------------------------------------*/
+
+PUBLIC void floatop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regmark;
+ bool_t sflag;
+
+ regmark = reguse;
+ saveopreg();
+ (void) f_indirect(source);
+ if (!(reguse & OPREG) && (source->storage == OPREG))
+ {
+ reguse |= source->storage;
+ saveopreg();
+ }
+ fpush(target);
+ sflag = TRUE;
+ if (source->flags != TEMP || source->offset.offi != sp + dtypesize)
+ {
+ sflag = FALSE;
+ if (source->storage == OPREG)
+ restoreopreg();
+ pointat(source);
+ }
+ switch ((op_t) op)
+ {
+ case ADDOP:
+ call("Fadd");
+ break;
+ case DIVOP:
+ call("Fdiv");
+ break;
+ case EQOP:
+ call("Fcomp");
+ sp += dtypesize; /* target is popped */
+ break; /* target symbol now invalid but is not used */
+ case MULOP:
+ call("Fmul");
+ break;
+ case SUBOP:
+ call("Fsub");
+ break;
+ }
+ if (sflag)
+ {
+ outnl();
+ sp += dtypesize; /* source is popped */
+ }
+ else
+ outntypechar(source->type);
+ onstack(target);
+ reguse = regmark; /* early so opreg is not reloaded if source */
+ restoreopreg();
+}
+
+/*-----------------------------------------------------------------------------
+ fpush(source leaf of scalar type)
+ converts source to double and pushes it to stack
+ OPREG must be free
+-----------------------------------------------------------------------------*/
+
+PUBLIC void fpush(source)
+struct symstruct *source;
+{
+ scalar_t scalar;
+
+ if ((scalar = source->type->scalar) & RSCALAR)
+ {
+ if (f_indirect(source))
+ return;
+ pointat(source);
+ }
+ else if (scalar & DLONG)
+ load(source, OPREG);
+ else
+ load(source, DREG);
+ call("Fpush");
+ if (scalar & UNSIGNED)
+ outbyte('u');
+ outntypechar(source->type);
+ justpushed(source);
+}
+
+/*-----------------------------------------------------------------------------
+ justpushed(target leaf)
+ records that target has just been pushed to a double on the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC void justpushed(target)
+struct symstruct *target;
+{
+ sp -= dtypesize;
+ onstack(target);
+ target->type = dtype;
+}
diff --git a/bcc-bruce/function.c b/bcc-bruce/function.c
new file mode 100644
index 0000000..1d48a19
--- /dev/null
+++ b/bcc-bruce/function.c
@@ -0,0 +1,413 @@
+/* function.c - function call protocol for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "table.h"
+#include "type.h"
+
+#ifdef I8088
+# define ADJUSTLONGRETURN
+# define CANHANDLENOFRAME
+# undef CANHANDLENOFRAME
+# define STUPIDFRAME
+#endif
+
+FORWARD void out_callstring P((void));
+
+/* call a named (assembly interface) procedure, don't print newline after */
+
+PUBLIC void call(name)
+char *name;
+{
+ out_callstring();
+ outstr(name);
+}
+
+PUBLIC void function(source)
+struct symstruct *source;
+{
+ if (source->indcount == 0 && source->storage == GLOBAL &&
+ !(source->flags & LABELLED) && *source->name.namep != 0)
+ {
+ out_callstring();
+ outnccname(source->name.namep);
+ }
+ else
+ {
+#ifdef XENIX_AS
+ if (source->indcount == 0) /* fix call fixed address */
+ out_callstring();
+ else
+#endif
+ outcalladr();
+#ifdef MC6809
+ if (source->indcount == 1)
+ ++source->indcount; /* fake for outadr */
+#endif
+ outadr(source);
+ }
+ source->type = source->type->nexttype;
+#ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
+ if (source->type->scalar & DLONG)
+ {
+# ifdef ADJUSTLONGRETURN
+# if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ {
+ regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2);
+ regexchange(LONGREG2, DXREG);
+ }
+# endif
+# if DYNAMIC_LONG_ORDER
+ else
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ regtransfer(DXREG, LONGRETURNREGS & ~LONGREG2);
+# endif
+# endif
+ source->storage = LONGRETURNREGS & ~LONGREG2;
+ }
+ else
+#endif
+ if (source->type->scalar & CHAR)
+ {
+#if RETURNREG != DREG
+ transfer(source, DREG);
+#endif
+ source->storage = BREG;
+ }
+ else if (source->type->scalar & DOUBLE)
+ source->storage = doublreturnregs & ~DREG;
+#if 0
+ else if (source->type->scalar & FLOAT)
+ source->storage = floatreturnregs /* XXX? & ~DREG */;
+#endif
+ else
+ source->storage = RETURNREG;
+ source->offset.offi = source->indcount = 0;
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ if (source->type->constructor & STRUCTU)
+ {
+ transfer(source, getindexreg()); /* so it can be indirected
+ * and/or preserved in blockmove() */
+ source->indcount = 1;
+ source->flags = TEMP; /* kludge so blockpush can be avoided */
+ }
+}
+
+PUBLIC void ldregargs()
+{
+ register struct symstruct *symptr;
+ store_pt targreg;
+ struct symstruct temptarg;
+
+ for (symptr = &locsyms[0]; symptr < locptr && symptr->level == ARGLEVEL;
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ {
+ if ((store_t) (targreg = symptr->storage) & allregs)
+ {
+
+ /* load() is designed to work on expression symbols, so don't
+ * trust it on reg variables although it almost works.
+ */
+ temptarg = *symptr;
+ if (arg1inreg && symptr == &locsyms[0])
+ {
+ temptarg.storage = ARGREG;
+ temptarg.offset.offi = 0;
+ }
+ else
+ {
+ temptarg.storage = LOCAL;
+ temptarg.indcount = 1;
+ }
+ load(&temptarg, targreg);
+ symptr->offset.offi = 0;
+ }
+ }
+ regarg = FALSE;
+}
+
+PUBLIC void loadretexpression()
+{
+ if (returntype->constructor & STRUCTU)
+ {
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+ struct symstruct *structarg;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ exp = expression();
+ makeleaf(exp);
+ structarg = constsym((value_t) 0);
+ structarg->type = pointype(returntype);
+ onstack(structarg);
+ indirec(structarg);
+ structarg->flags = 0; /* assign() doesn't like TEMP even for indir */
+ structarg->offset.offi = returnadrsize;
+ assign(exp->left.symptr, structarg);
+ etptr = etmark;
+ exprptr = exprmark;
+ }
+#ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
+ else if (returntype->scalar & DLONG)
+ {
+ loadexpression(LONGRETURNREGS & ~LONGREG2, returntype);
+# ifdef ADJUSTLONGRETURN
+# if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ {
+ regexchange(LONGREG2, DXREG);
+ regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2);
+ }
+# endif
+# if DYNAMIC_LONG_ORDER
+ else
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ regtransfer(LONGRETURNREGS & ~LONGREG2, DXREG);
+# endif
+# endif
+ }
+ else
+#endif
+ if (returntype->scalar & DOUBLE)
+ loadexpression(doublreturnregs & ~DREG, returntype);
+#if 0
+ else if (returntype->scalar & FLOAT)
+ loadexpression(floatreturnregs /* XXX? & ~DREG */, returntype);
+#endif
+ else
+ loadexpression(RETURNREG, returntype);
+}
+
+PUBLIC void listo(target, lastargsp)
+struct symstruct *target;
+offset_t lastargsp;
+{
+ extend(target);
+ push(target);
+ if (lastargsp != 0 && sp != lastargsp - target->type->typesize)
+ {
+ loadany(target);
+ modstk(lastargsp);
+ push(target);
+ if (sp != lastargsp - target->type->typesize)
+ {
+ bugerror("botched push of arg");
+#ifdef DEBUG
+ outstr("arg type is ");
+ dbtype(target->type);
+ outnl();
+#endif
+ }
+ }
+}
+
+PUBLIC void listroot(target)
+struct symstruct *target;
+{
+ extend(target);
+ /* necessary regs are free since they were saved for function */
+ if (target->type->scalar & DLONG)
+ load(target, LONGARGREGS & ~LONGREG2);
+ else
+ load(target, ARGREG);
+}
+
+PRIVATE void out_callstring()
+{
+ outop3str(callstring);
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+#ifdef FRAMEPOINTER
+
+PUBLIC void popframe()
+{
+ poplist(frame1list);
+}
+
+#endif
+
+/* reserve storage for locals if necessary */
+/* also push 1st function arg and load register args if necessary */
+
+PUBLIC void reslocals()
+{
+#ifdef FRAMEPOINTER
+# ifndef STUPIDFRAME
+ bool_t loadframe = FALSE;
+
+# endif
+#endif
+
+ if (switchnow != NULL)
+ {
+#ifdef FRAMEPOINTER
+ if (framep == 0 && softsp != sp)
+ bugerror("local variables in switch statement messed up, sorry");
+#else
+ if (sp != softsp)
+ bugerror("local variables in switch statement don't work, sorry");
+#endif
+ if (lowsp > softsp)
+ lowsp = softsp;
+ sp = softsp;
+ return;
+ }
+#ifdef FRAMEPOINTER
+ if (framep == 0)
+ {
+# ifdef STUPIDFRAME
+ pushreg(FRAMEREG);
+ regtransfer(STACKREG, FRAMEREG);
+ framep = sp;
+ pushlist(callee1mask);
+# else /* not STUPIDFRAME */
+# ifdef CANHANDLENOFRAME
+ if (stackarg || softsp != -frameregsize) /* args or locals */
+# endif
+ {
+ pushlist(frame1list);
+ loadframe = TRUE;
+ }
+# endif /* not STUPIDFRAME */
+ }
+#else
+ if (sp == 0)
+ pushlist(callee1mask);
+#endif /* FRAMEPOINTER */
+ if (arg1size)
+ {
+ switch ((fastin_t) arg1size)
+ {
+ case 8:
+ pushlist(doubleargregs);
+ break;
+ case 4:
+# ifdef I8088
+ if (!i386_32)
+# endif
+ {
+ pushlist(LONGARGREGS);
+ break;
+ }
+ case 2:
+# ifdef I8088
+ pushlist(ARGREG);
+# endif
+# ifdef MC6809
+ switch (sp - softsp)
+ {
+ case 3:
+ pushlist(LOC1REGS | ARGREG);
+ break;
+ case 4:
+ pushlist(LOC2REGS | ARGREG);
+ break;
+ case 5:
+ pushlist(LOC3REGS | ARGREG);
+ break;
+ case 6:
+ pushlist(LOC4REGS | ARGREG);
+ break;
+ default:
+ pushlist(ARGREG);
+ break;
+ }
+# endif /* MC6809 */
+ }
+ arg1size = 0; /* show 1st arg allocated */
+ }
+#ifdef FRAMEPOINTER
+# ifndef STUPIDFRAME /* else this moved above for compat with Xenix cc frame */
+ if (loadframe || softsp != -frameregsize)
+ modstk(softsp);
+ /* else avoid modstk() because softsp holds space for frame pointer only) */
+ /* but pointer has not been pushed (must keep softsp for later levels) */
+ if (loadframe)
+ {
+ regtransfer(STACKREG, FRAMEREG);
+ framep = sp;
+ }
+# else /* STUPIDFRAME */
+ modstk(softsp);
+# endif /* STUPIDFRAME */
+#else /* no FRAMEPOINTER */
+ modstk(softsp);
+#endif /* FRAMEPOINTER */
+ if (regarg)
+ ldregargs();
+}
+
+/* clean up stack and return from a function */
+
+PUBLIC void ret()
+{
+#ifdef FRAMEPOINTER
+ offset_t newsp;
+
+ if (framep != 0)
+ {
+ newsp = -(offset_t) func1saveregsize;
+ if (switchnow != NULL || newsp - sp >= 0x80)
+ changesp(newsp, TRUE);
+ else
+ modstk(newsp);
+ popframe();
+ }
+ outreturn();
+#else /* no FRAMEPOINTER */
+# ifdef MC6809
+ store_pt reglist;
+
+ switch (sp)
+ {
+ case -1:
+ reglist = JUNK1REGS | PCREG;
+ break;
+ case -2:
+ reglist = JUNK2REGS | PCREG;
+ break;
+ case -3:
+ reglist = JUNK3REGS | PCREG;
+ break;
+ case -4:
+ reglist = JUNK4REGS | PCREG;
+ break;
+ default:
+ modstk(0);
+ outreturn();
+ return;
+ }
+ poplist(reglist);
+#else
+ if (sp != 0)
+ {
+ modstk(-(offset_t) func1saveregsize);
+ poplist(callee1mask);
+ }
+ outreturn();
+# endif /* no MC6809 */
+#endif /* no FRAMEPOINTER */
+}
diff --git a/bcc-bruce/gencode.c b/bcc-bruce/gencode.c
new file mode 100644
index 0000000..55f36df
--- /dev/null
+++ b/bcc-bruce/gencode.c
@@ -0,0 +1,736 @@
+/* gencode.c - generate code for an expression tree for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define islvalop(op) \
+ ((op) >= ASSIGNOP && (op) <= SUBABOP || (op) == PTRADDABOP)
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "condcode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "gencode.h"
+#include "sizes.h"
+
+#define FIRSTOPDATA GTOP
+
+#if MAXINDIRECT <= 1
+# define istooindirect(t) ((t)->indcount > MAXINDIRECT)
+#else
+# define istooindirect(t) ((t)->indcount >= MAXINDIRECT && \
+ ((t)->indcount > MAXINDIRECT || \
+ (t)->type->typesize > maxregsize || \
+ (t)->type->constructor & FUNCTION))
+#endif
+
+#ifdef I8088
+#if NOTFINISHED
+PUBLIC store_pt allregs = BREG | DREG | DATREG1 | DATREG2
+ | INDREG0 | INDREG1 | INDREG2;
+#else
+PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2;
+#endif
+PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2;
+PUBLIC uoffset_t alignmask = ~(uoffset_t) 0x0001;
+PUBLIC bool_t arg1inreg = FALSE;
+PUBLIC store_pt calleemask = INDREG1 | INDREG2;
+PUBLIC bool_t callersaves = FALSE;
+PUBLIC char *callstring = "call\t";
+PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC offset_t jcclonger = 3;
+PUBLIC offset_t jmplonger = 1;
+PUBLIC char *jumpstring = "br \t";
+PUBLIC char *regpulllist = "f2ax2ax2bx2si2di2bp2qx2qx2cx2dx2";
+PUBLIC char *regpushlist = "dx2cx2qx2qx2bp2di2si2bx2ax2ax2f2";
+#if NOTFINISHED
+PUBLIC store_pt regregs = INDREG1 | INDREG2 | DATREG1 | DATREG2;
+#else
+PUBLIC store_pt regregs = INDREG1 | INDREG2;
+#endif
+
+PUBLIC char *acclostr = "al";
+PUBLIC char *accumstr = "ax";
+PUBLIC char *badregstr = "qx";
+PUBLIC char *dreg1str = "cx";
+PUBLIC char *dreg1bstr = "cl";
+PUBLIC char *dreg2str = "dx";
+PUBLIC char *ireg0str = "bx";
+PUBLIC char *ireg1str = "si";
+PUBLIC char *ireg2str = "di";
+#ifdef FRAMEPOINTER
+PUBLIC char *localregstr = "bp";
+#else
+PUBLIC char *localregstr = "sp";
+#endif
+PUBLIC char *stackregstr = "sp";
+#endif
+
+#ifdef MC6809
+PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2;
+PUBLIC uoffset_t alignmask = ~(uoffset_t) 0x0000;
+PUBLIC bool_t arg1inreg = TRUE;
+PUBLIC store_pt calleemask = INDREG1 | INDREG2;
+PUBLIC bool_t callersaves = TRUE;
+PUBLIC char *callstring = "JSR\t>";
+PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC offset_t jcclonger = 2;
+PUBLIC offset_t jmplonger = 1;
+PUBLIC char *jumpstring = "JMP\t>";
+PUBLIC char *regpulllist = "CC1B1D2X2U2Y2DP1PC2";
+PUBLIC char *regpushlist = "PC2DP1Y2U2X2D2B1CC1";
+PUBLIC store_pt regregs = INDREG1 | INDREG2;
+
+PUBLIC char *acclostr = "B";
+PUBLIC char *accumstr = "D";
+PUBLIC char *badregstr = "Q";
+PUBLIC char *ireg0str = "X";
+PUBLIC char *ireg1str = "U";
+PUBLIC char *ireg2str = "Y";
+PUBLIC char *localregstr = "S";
+#endif
+
+PUBLIC uoffset_t accregsize = 2;
+#ifdef FRAMEPOINTER
+PUBLIC uoffset_t frameregsize = 2;
+#endif
+PUBLIC uoffset_t maxregsize = 2;
+PUBLIC uoffset_t opregsize = 2;
+PUBLIC uoffset_t pshregsize = 2;
+PUBLIC uoffset_t returnadrsize = 2;
+
+#ifndef MC6809
+PUBLIC uvalue_t intmaskto = 0xFFFFL;
+PUBLIC uvalue_t maxintto = 0x7FFFL;
+PUBLIC uvalue_t maxlongto = 0x7FFFFFFFL;
+PUBLIC uvalue_t maxoffsetto = 0x7FFFL;
+PUBLIC uvalue_t maxshortto = 0x7FFFL;
+PUBLIC uvalue_t maxuintto = 0xFFFFL;
+PUBLIC uvalue_t maxushortto = 0xFFFFL;
+PUBLIC uvalue_t shortmaskto = 0xFFFFL;
+#endif
+
+PRIVATE store_pt callermask;
+PRIVATE offset_t lastargsp;
+
+PRIVATE smalin_t opdata[] =
+{
+/* GTOP, LTOP, ADDOP, DIVOP, */
+ GT, LT, 0, 0,
+/* MODOP, LOGNOTOP, NOTOP, STRUCELTOP, */
+ 0, 0, 0, 0,
+/* STRUCPTROP, ASSIGNOP, ADDABOP, ANDABOP, */
+ 0, 0, 0, ANDOP,
+/* DIVABOP, EORABOP, MODABOP, MULABOP, */
+ DIVOP, EOROP, MODOP, MULOP,
+/* ORABOP, SLABOP, SRABOP, SUBABOP, */
+ OROP, SLOP, SROP, 0,
+/* COMMAOP, COLONOP, LOGOROP, LOGANDOP, */
+ 0, 0, 0, 0,
+/* EQOP, NEOP, GEOP, LEOP, */
+ EQ, NE, GE, LE,
+};
+
+FORWARD void abop P((op_pt op, struct symstruct *source,
+ struct symstruct *target));
+FORWARD void smakeleaf P((struct nodestruct *exp));
+FORWARD void tcheck P((struct nodestruct *exp));
+
+PRIVATE void abop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt regmark;
+ store_pt regpushed;
+ store_pt regtemp;
+ struct symstruct temptarg;
+
+ regpushed = preslval(source, target);
+ temptarg = *target;
+ if ((source->type->scalar ^ target->type->scalar) & (DLONG | RSCALAR)
+ && op != SLABOP && op != SRABOP) /* XXX - perhaps not float */
+ {
+ pres2(target, source);
+ cast(source->type, &temptarg);
+ }
+ switch (op)
+ {
+ case ADDABOP:
+ add(source, &temptarg);
+ break;
+ case ANDABOP:
+ case EORABOP:
+ case ORABOP:
+ op1((opdata - FIRSTOPDATA)[op], source, &temptarg);
+ break;
+ case DIVABOP:
+ case MODABOP:
+ case MULABOP:
+ case SLABOP:
+ case SRABOP:
+ softop((opdata - FIRSTOPDATA)[op], source, &temptarg);
+ break;
+ case PTRADDABOP:
+ regtemp = 0;
+ if ((reguse & allindregs) == allindregs)
+ {
+ /* free a temporary index not used for source or target */
+
+ regmark = reguse;
+ reguse = source->storage | temptarg.storage;
+ pushreg(regtemp = getindexreg());
+ reguse = regmark & ~regtemp;
+ }
+ indexadr(source, &temptarg);
+ if (regtemp)
+ {
+ load(&temptarg, DREG);
+ recovlist(regtemp);
+ }
+ break;
+ case SUBABOP:
+ sub(source, &temptarg);
+ break;
+ }
+ assign(&temptarg, target);
+ recovlist(regpushed);
+}
+
+PUBLIC void bileaf(exp)
+struct nodestruct *exp;
+{
+ bool_t commutop;
+ bool_t tookaddress;
+ store_t regmark;
+ struct nodestruct *indchase;
+ struct nodestruct *left;
+ struct nodestruct *right;
+ struct symstruct *source;
+ struct symstruct *target;
+
+ left = exp->left.nodeptr;
+ if ((right = exp->right) == NULL)
+ {
+ makeleaf(left);
+#ifdef DEBUG
+ debug(exp);
+#endif
+ return;
+ }
+ switch (exp->tag)
+ {
+ case ADDOP:
+ case ANDOP:
+ case EOROP:
+ case OROP:
+ case EQOP:
+ case NEOP:
+ case MULOP:
+ commutop = TRUE;
+ break;
+ case FUNCOP:
+ makeleaf(left);
+ if ((target = left->left.symptr)->storage & allregs
+ && right->tag != LEAF && target->flags != REGVAR)
+ {
+ if (target->indcount == 0)
+ push(target);
+ else
+ {
+ --target->indcount;
+ push(target);
+ ++target->indcount;
+ }
+ }
+ default:
+ commutop = FALSE;
+ break;
+ }
+ regmark = reguse;
+ if (right->tag != LEAF)
+ {
+ if (left->tag != LEAF && commutop && left->weight > right->weight)
+ {
+ exp->left.nodeptr = right;
+ right = exp->right = left;
+ left = exp->left.nodeptr;
+#ifdef DEBUG
+ debugswap();
+#endif
+ }
+ makeleaf(right);
+ }
+ else if (left->tag != LEAF)
+ makeleaf(left);
+ source = right->left.symptr;
+ if (left->tag != LEAF)
+ {
+ for (indchase = left;
+ indchase->tag == INDIRECTOP || indchase->tag == STRUCELTOP;
+ indchase = indchase->left.nodeptr)
+ ;
+ tookaddress = FALSE;
+ if (source->storage & allindregs || indchase->tag != LEAF)
+ {
+ if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP)
+ {
+ address(source);
+ tookaddress = TRUE;
+ }
+ if (source->storage & allindregs && source->indcount == 0 &&
+ (source->type->scalar & (DLONG | RSCALAR) ||
+ left->tag == FUNCOP && source->flags != REGVAR))
+ push(source); /* XXX - perhaps not float */
+ else
+ preserve(source);
+ }
+ makeleaf(left);
+ if (tookaddress)
+ indirec(source);
+ }
+ target = left->left.symptr;
+ if (istooindirect(source))
+ {
+ /* want to makelessindirect(source) */
+ /* this uses source->storage if that is a free index */
+ /* otherwise, must preserve target if that is an index */
+
+ tookaddress = FALSE;
+ if (!(source->storage & ~reguse & allindregs) &&
+ target->storage & allindregs)
+ {
+ /* want to pres2(source, target) */
+ /* this requires target to be < MAXINDIRECT indirect */
+ /* it is safe to makelessindirect(target) */
+ /* since source is not a free index */
+
+ if (islvalop(exp->tag) && target->indcount != 0)
+ {
+ address(target);
+ tookaddress = TRUE;
+ }
+ if (istooindirect(target))
+ makelessindirect(target);
+ pres2(source, target);
+ }
+ makelessindirect(source);
+ if (tookaddress)
+ indirec(target);
+ }
+ if (istooindirect(target))
+ {
+ tookaddress = FALSE;
+ if (!(target->storage & ~reguse & allindregs) &&
+ source->storage & allindregs)
+ {
+ if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP)
+ {
+ address(source);
+ tookaddress = TRUE;
+ }
+ pres2(target, source);
+ }
+ makelessindirect(target);
+ if (tookaddress)
+ indirec(source);
+ }
+ reguse = regmark;
+#ifdef DEBUG
+ debug(exp);
+#endif
+ if (commutop
+ && (target->storage == CONSTANT
+ && !(target->type->scalar & (DLONG | RSCALAR))
+ || source->storage & ALLDATREGS
+ || source->type->scalar & (DLONG | RSCALAR)
+ && source->indcount == 0 && target->indcount != 0))
+ {
+ exp->left.nodeptr = right;
+ exp->right = left;
+#ifdef DEBUG
+ debugswap();
+#endif
+ }
+}
+
+PUBLIC fastin_pt bitcount(number)
+register uvalue_t number;
+{
+ register fastin_pt count;
+
+ for (count = 0; number != 0; number >>= 1)
+ if (number & 1)
+ ++count;
+ return count;
+}
+
+PUBLIC void codeinit()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ /* Need DATREG2 for doubles although handling of extra data regs is
+ * not finished.
+ * XXX - might need more regs for 16-bit mode doubles or floats.
+ */
+ allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2
+ | DATREG1 | DATREG1B | DATREG2;
+#if NOTFINISHED
+ allindregs = INDREG0 | INDREG1 | INDREG2 | DATREG1 | DATREG2;
+#else
+ allindregs = INDREG0 | INDREG1 | INDREG2;
+#endif
+ alignmask = ~(uoffset_t) 0x00000003;
+ calleemask = INDREG0 | INDREG1 | INDREG2;
+ doubleargregs = DREG | DATREG2;
+ doubleregs = DREG | DATREG2;
+ doublreturnregs = DREG | DATREG2;
+ jcclonger = 4;
+ jmplonger = 3;
+ regpulllist = "fd4eax4eax4ebx4esi4edi4ebp4qx4qx4ecx4edx4";
+ regpushlist = "edx4ecx4qx4qx4ebp4edi4esi4ebx4eax4eax4fd4";
+
+ accumstr = "eax";
+ dreg1str = "ecx";
+ dreg2str = "edx";
+ ireg0str = "ebx";
+ ireg1str = "esi";
+ ireg2str = "edi";
+#ifdef FRAMEPOINTER
+ localregstr = "ebp";
+#else
+ localregstr = "esp";
+#endif
+ stackregstr = "esp";
+
+ opregsize =
+ returnadrsize =
+ pshregsize =
+ maxregsize =
+#ifdef FRAMEPOINTER
+ frameregsize =
+#endif
+ accregsize = 4;
+
+ intmaskto = (unsigned long) 0xFFFFFFFFL;
+ maxintto = 0x7FFFFFFFL;
+ maxoffsetto = 0x7FFFFFFFL;
+ maxuintto = (unsigned long) 0xFFFFFFFFL;
+ }
+#endif
+#ifdef POSINDEPENDENT
+ if (posindependent)
+ {
+# ifdef MC6809
+ callstring = "LBSR\t";
+ jumpstring = "LBRA\t";
+# endif
+ }
+#endif
+ if (callersaves)
+ calleemask = 0;
+ callermask = ~calleemask;
+#ifdef FRAMEPOINTER
+ funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize
+ + frameregsize;
+ funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs)
+ * maxregsize + frameregsize;
+ framelist = FRAMEREG | calleemask;
+#else
+ funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize;
+ funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs)
+ * maxregsize;
+#endif
+}
+
+PUBLIC fastin_pt highbit(number)
+register uvalue_t number;
+{
+ register fastin_pt bit;
+
+ for (bit = -1; number != 0; number >>= 1)
+ ++bit;
+ return bit;
+}
+
+PUBLIC void makeleaf(exp)
+struct nodestruct *exp;
+{
+ ccode_t condtrue;
+ op_pt op;
+ store_t regmark;
+ offset_t saveargsp;
+ store_t savelist;
+ offset_t saveoffset;
+ struct symstruct *source;
+ offset_t spmark;
+ struct symstruct *structarg;
+ struct symstruct *target;
+
+ if ((op_t) (op = exp->tag) == LEAF)
+ {
+ target = exp->left.symptr;
+ if (istooindirect(target))
+ makelessindirect(target);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == INDIRECTOP || (op_t) op == STRUCELTOP)
+ {
+ smakeleaf(exp);
+ target = exp->left.symptr;
+ if (istooindirect(target))
+ makelessindirect(target);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == COMMAOP)
+ {
+ spmark = sp;
+ makeleaf(exp->left.nodeptr);
+ modstk(spmark);
+ makeleaf(exp->right);
+ exp->tag = LEAF;
+ exp->left.symptr = exp->right->left.symptr;
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == CONDOP)
+ {
+ condop(exp);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == LOGANDOP || (op_t) op == LOGNOTOP
+ || (op_t) op == LOGOROP)
+ {
+ logop(exp);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ regmark = reguse;
+ if ((op_t) op == FUNCOP)
+ {
+ saveargsp = lastargsp;
+ lastargsp = savelist = 0;
+ if (exp->nodetype->constructor & STRUCTU)
+ {
+ modstk(sp - (offset_t) exp->nodetype->typesize);
+ onstack(structarg = constsym((value_t) 0));
+ }
+ else
+ {
+ if (exp->nodetype->scalar & DOUBLE)
+ {
+ if (regmark & doublreturnregs)
+ savelist = doublreturnregs;
+ }
+ else if (regmark & RETURNREG)
+ savelist = exp->nodetype->scalar & DLONG
+ ? LONGRETURNREGS : RETURNREG;
+ if (savelist != 0)
+ modstk(saveoffset = sp - exp->nodetype->typesize);
+ }
+ pushlist(regmark & callermask);
+ }
+ spmark = sp;
+ bileaf(exp);
+ if (exp->right != NULL)
+ source = exp->right->left.symptr;
+ else
+ source = NULL;
+ target = exp->left.nodeptr->left.symptr;
+ switch ((op_t) op)
+ {
+ case ADDABOP:
+ case ANDABOP:
+ case DIVABOP:
+ case EORABOP:
+ case SUBABOP:
+ case MODABOP:
+ case MULABOP:
+ case ORABOP:
+ case PTRADDABOP:
+ case SLABOP:
+ case SRABOP:
+ abop(op, source, target);
+ break;
+ case ADDOP:
+ add(source, target);
+ break;
+ case ADDRESSOP:
+ address(target);
+ break;
+ case ANDOP:
+ case EOROP:
+ case OROP:
+ op1(op, source, target);
+ break;
+ case ASSIGNOP:
+ assign(source, target);
+ break;
+ case CASTOP:
+ cast(source->type, target);
+ break;
+ case DIVOP:
+ case MODOP:
+ case MULOP:
+ case SLOP:
+ case SROP:
+ softop(op, source, target);
+ break;
+ case EQOP:
+ case GEOP:
+ case GTOP:
+ case LEOP:
+ case LTOP:
+ case NEOP:
+ condtrue = (opdata - FIRSTOPDATA)[op];
+ cmp(source, target, &condtrue);
+ break;
+ case FUNCOP:
+ /* kludge update pushed regs */
+ /* may only work for si, di */
+ /* -2 skips for ax and bx */
+ /* need dirtymask to mostly avoid this */
+ savereturn(regmark & callermask & regregs,
+ spmark - 2 * (offset_t) pshregsize);
+ if (exp->nodetype->constructor & STRUCTU)
+ {
+ address(structarg);
+ push(structarg);
+ }
+ function(target);
+ break;
+ case INDIRECTOP:
+ indirec(target);
+ break;
+ case LISTOP:
+ listo(target, lastargsp);
+ lastargsp = sp;
+ break;
+ case NEGOP:
+ neg(target);
+ break;
+ case NOTOP:
+ not(target);
+ break;
+ case POSTDECOP:
+ case POSTINCOP:
+ case PREDECOP:
+ case PREINCOP:
+ incdec(op, target);
+ break;
+ case PTRADDOP:
+ indexadr(source, target);
+ break;
+ case PTRSUBOP:
+ ptrsub(source, target);
+ break;
+ case ROOTLISTOP:
+ listroot(target);
+ lastargsp = sp;
+ break;
+ case STRUCELTOP:
+ struc(source, target);
+ break;
+ case SUBOP:
+ sub(source, target);
+ break;
+ }
+ if (target->storage == LOCAL && target->offset.offi < spmark &&
+ target->flags == TEMP)
+ spmark = target->offset.offi;
+#if 1 /* XXX - why does sp get changed without this? */
+ if ((op_t) op != ROOTLISTOP)
+#endif
+ modstk(spmark);
+ if ((op_t) op == FUNCOP)
+ {
+ lastargsp = saveargsp;
+ if (savelist != 0)
+ {
+ savereturn(savelist, saveoffset);
+ onstack(target);
+ target->offset.offi = saveoffset;
+ }
+ recovlist(regmark & callermask);
+ }
+ reguse = regmark;
+ exp->tag = LEAF;
+ exp->left.symptr = target;
+ if (istooindirect(target))
+ makelessindirect(target);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+}
+
+PRIVATE void smakeleaf(exp)
+struct nodestruct *exp;
+{
+ struct nodestruct *left;
+
+ left = exp->left.nodeptr;
+ if (left->tag == INDIRECTOP || left->tag == STRUCELTOP)
+ smakeleaf(left);
+ else if (left->tag != LEAF)
+ makeleaf(left);
+ if (exp->tag == INDIRECTOP)
+ indirec(left->left.symptr);
+ else
+ {
+ if (left->left.symptr->indcount > MAXINDIRECT + 1)
+ makelessindirect(left->left.symptr);
+ struc(exp->right->left.symptr, left->left.symptr);
+ }
+ exp->tag = LEAF;
+ exp->left.symptr = left->left.symptr;
+}
+
+#ifdef SELFTYPECHECK
+
+PRIVATE void tcheck(exp)
+register struct nodestruct *exp;
+{
+ register struct symstruct *target;
+
+ if (exp->nodetype != (target = exp->left.symptr)->type)
+ {
+ {
+ bugerror("botched nodetype calculation");
+#ifdef DEBUG
+ comment();
+ outstr("runtime type is ");
+ dbtype(target->type);
+ outstr(", calculated type is ");
+ dbtype(exp->nodetype);
+ outnl();
+#endif
+ }
+ }
+}
+
+#endif /* SELFTYPECHECK */
diff --git a/bcc-bruce/gencode.h b/bcc-bruce/gencode.h
new file mode 100644
index 0000000..370817a
--- /dev/null
+++ b/bcc-bruce/gencode.h
@@ -0,0 +1,101 @@
+/* gencode.h - code generation for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef MC6809
+# define CANABXCUTOFF 7 /* favour ABX over MUL before this */
+#endif
+#define EXPRLEVEL 126 /* level for symbols in exptree, > real levs */
+#define OFFKLUDGELEVEL 127 /* level for expr sym with offset from name */
+#define OPERANDSEPARATOR ',' /* char separating operands */
+#define OPSEPARATOR '\t' /* char separating op string and operand */
+
+EXTERN uoffset_t arg1size; /* size of 1st arg to function */
+ /* zero after allocation of 1st arg */
+EXTERN store_pt callee1mask; /* calleemask with doubleregs masked if nec */
+EXTERN uoffset_t dataoffset; /* amount of initialized data so far */
+#ifdef DEBUG
+EXTERN bool_t debugon; /* nonzero to print debugging messages */
+ /* depends on zero init */
+#endif
+#ifdef FRAMEPOINTER
+EXTERN store_pt framelist; /* bit pattern for frame and saved regs */
+EXTERN store_pt frame1list; /* framelist with doubleregs masked if nec */
+EXTERN offset_t framep; /* hardware relative frame ptr */
+#endif
+EXTERN uoffset_t func1saveregsize; /* choice of next two values */
+EXTERN uoffset_t funcdsaveregsize; /* funcsaveregsize adjusted for doubles */
+EXTERN uoffset_t funcsaveregsize; /* tot size of framelist/calleemask regs */
+#ifdef I8088
+EXTERN bool_t i386_32; /* nonzero to generate 386 32 bit code */
+ /* depends on zero init */
+#endif
+#ifdef DYNAMIC_LONG_ORDER
+EXTERN bool_t long_big_endian; /* nonzero if high long word is first */
+ /* depends on zero init */
+#endif
+EXTERN offset_t lowsp; /* low water sp (collects locals in switch) */
+#ifdef POSINDEPENDENT
+EXTERN bool_t posindependent; /* nonzero to generate pos-independent code */
+ /* depends on zero init */
+#endif
+EXTERN bool_t printf_fp; /* nonzero if *printf called with FP arg */
+EXTERN bool_t regarg; /* nonzero to show unloaded register arg */
+ /* depends on zero init */
+EXTERN store_t reguse; /* registers in use */
+EXTERN bool_t scanf_fp; /* nonzero if *scanf called with ptr-to-FP */
+EXTERN offset_t softsp; /* software sp (leads sp during declares) */
+EXTERN offset_t sp; /* hardware relative stack ptr */
+ /* depends on zero init */
+#ifdef FRAMEPOINTER
+EXTERN bool_t stackarg; /* nonzero to show function has arg on stack */
+#endif
+EXTERN struct switchstruct *switchnow; /* currently active switch */
+ /* depends on NULL init */
+
+/* variables to be initialised to nonzero */
+
+extern store_pt allindregs; /* mask (in) for index registers */
+extern store_pt allregs; /* mask (in) for registers */
+extern bool_t arg1inreg; /* nonzero to pass 1st arg in reg */
+extern store_pt calleemask; /* mask (in) for regs to be saved by callee */
+extern bool_t callersaves; /* nonzero to make caller save regs */
+extern char *callstring; /* opcode string for call */
+extern store_pt doubleargregs; /* mask (in) for regs for 1st arg if double */
+extern store_pt doubleregs; /* mask (in) for regs to temp contain double */
+extern store_pt doublreturnregs; /* mask (in) for regs for returning double */
+extern offset_t jcclonger; /* amount jcc long jumps are longer */
+extern offset_t jmplonger; /* amount long jumps is longer */
+extern char *jumpstring; /* opcode string for jump */
+extern char *regpulllist; /* reg names and sizes (0 store_t bit first) */
+extern char *regpushlist; /* reg names and sizes (0 store_t bit last) */
+extern store_pt regregs; /* mask (in) for regs which can be reg vars */
+
+/* register names */
+
+extern char *acclostr;
+extern char *accumstr;
+extern char *badregstr;
+#ifdef I8088
+extern char *dreg1str;
+extern char *dreg1bstr;
+extern char *dreg2str;
+#endif
+extern char *ireg0str;
+extern char *ireg1str;
+extern char *ireg2str;
+extern char *localregstr;
+#ifdef I8088
+extern char *stackregstr;
+#endif
+
+/* register sizes */
+
+extern uoffset_t accregsize;
+#ifdef FRAMEPOINTER
+extern uoffset_t frameregsize;
+#endif
+extern uoffset_t maxregsize;
+extern uoffset_t opregsize;
+extern uoffset_t pshregsize;
+extern uoffset_t returnadrsize;
diff --git a/bcc-bruce/genloads.c b/bcc-bruce/genloads.c
new file mode 100644
index 0000000..9e4f6be
--- /dev/null
+++ b/bcc-bruce/genloads.c
@@ -0,0 +1,1254 @@
+/* genloads.c - generate loads of registers and memory for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+FORWARD void badaddress P((void));
+FORWARD void blockpush P((struct symstruct *source));
+FORWARD void loadadr P((struct symstruct *source, store_pt targreg));
+FORWARD void loadlongindirect P((struct symstruct *source, store_pt targreg));
+FORWARD void outnamoffset P((struct symstruct *adr));
+FORWARD void outnnadr P((struct symstruct *adr));
+FORWARD fastin_pt pushpull P((store_pt reglist, bool_pt pushflag));
+
+PUBLIC void addoffset(source)
+struct symstruct *source;
+{
+#ifdef I8088
+ if (source->level == OFFKLUDGELEVEL)
+ {
+ outadd();
+ outregname(source->storage);
+ outcomma();
+ outnamoffset(source);
+ outnl();
+ if (source->storage & (AXREG | ALREG))
+ unbumplc();
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ source->offset.offi = 0;
+ }
+ else
+#endif
+ if (source->offset.offi != 0)
+ {
+ addconst(source->offset.offi, source->storage);
+ source->offset.offi = 0;
+ }
+}
+
+PUBLIC void address(source)
+struct symstruct *source;
+{
+ if (source->indcount == 0)
+ bugerror("taking address of non-lvalue");
+ else
+ {
+ if (source->type->constructor & (ARRAY | FUNCTION))
+ bugerror("botched indirect array or function");
+ else if (--source->indcount == 0 && source->storage == GLOBAL &&
+ !(source->flags & LABELLED) && *source->name.namep == 0)
+ source->storage = CONSTANT;
+ source->type = pointype(source->type);
+ }
+}
+
+PRIVATE void badaddress()
+{
+ bugerror("bad address");
+}
+
+PRIVATE void blockpush(source)
+struct symstruct *source;
+{
+ struct symstruct *length;
+ offset_t spmark;
+ uoffset_t typesize;
+
+ typesize = source->type->typesize;
+ length = constsym((value_t) typesize);
+ length->type = uitype;
+ address(source);
+ modstk(spmark = sp - (offset_t) typesize);
+#ifdef STACKREG
+ regtransfer(STACKREG, DREG);
+#else
+#ifdef MC6809 /* XXX ? */
+ regtransfer(LOCAL, DREG);
+#else
+#include "need STACKREG and stackregstr"
+#endif
+#endif
+ push(length);
+ push(source);
+ pushreg(DREG);
+ call("_memcpy");
+ outnl();
+ modstk(spmark);
+ indirec(source);
+}
+
+PUBLIC void exchange(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t tempreg;
+
+ regexchange(source->storage, target->storage);
+ tempreg = target->storage;
+ target->storage = source->storage;
+ source->storage = tempreg;
+}
+
+/*-----------------------------------------------------------------------------
+ getindexreg()
+ returns the "best" available index register
+-----------------------------------------------------------------------------*/
+
+PUBLIC store_pt getindexreg()
+{
+ if (!(reguse & INDREG0))
+ return INDREG0;
+ if (!(reguse & INDREG1))
+ return INDREG1;
+ if (!(reguse & INDREG2))
+ return INDREG2;
+#if NOTFINISHED
+#ifdef I8088
+ if (i386_32)
+ {
+ if (!(reguse & DATREG1))
+ return DATREG1;
+ if (!(reguse & DATREG2))
+ return DATREG2;
+ }
+#endif
+#endif
+ bugerror("out of index regs");
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ indexadr(index leaf, pointer leaf)
+ is used by the index and add and subtract (pointer) routines
+ it handles expressions like
+ pointer + index
+ &array[index]
+ the target becomes register direct with offset
+ (except for index = 0, when nothing is changed)
+ constant indexes are optimised by leaving them as offsets
+ register direct pointers are optimised by leaving the offset alone
+ (except for PC register direct, since there is no LEAX D,PC)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void indexadr(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+#ifdef MC6809
+ bool_t canABX;
+#endif
+ uoffset_t size;
+ store_pt sourcereg;
+ struct typestruct *targtype;
+ store_pt targreg;
+
+ if (!(target->type->constructor & (ARRAY | POINTER)))
+ {
+ bugerror("cannot index");
+ return;
+ }
+ size = target->type->nexttype->typesize;
+ if (source->storage == CONSTANT)
+ {
+ if (source->offset.offv != 0)
+ {
+ if (target->indcount != 0)
+ loadany(target);
+ target->offset.offi += source->offset.offv * size;
+ }
+ return;
+ }
+ if (target->storage & ALLDATREGS)
+ push(target);
+ if ((store_t) (sourcereg = target->storage) & ~reguse & allindregs)
+ targreg = sourcereg;
+ else
+ targreg = getindexreg();
+#ifdef I8088
+ if ((store_t) sourcereg == GLOBAL && target->indcount == 0 &&
+ !(source->type->scalar & CHAR) && source->storage != DREG)
+ load(source, targreg);
+ else
+#endif
+ load(source, DREG);
+
+#ifdef I8088
+ softop(MULOP, constsym((value_t) size), source);
+#endif
+#ifdef MC6809
+
+/*-----------------------------------------------------------------------------
+ do some calculations in advance to decide if index can be done with ABX
+-----------------------------------------------------------------------------*/
+
+ if ((store_t) targreg == XREG && source->type->scalar & CHAR &&
+ size < CANABXCUTOFF)
+ canABX = TRUE;
+ else
+ {
+ canABX = FALSE;
+ softop(MULOP, constsym((value_t) size), source);
+ }
+
+#endif
+
+/*-----------------------------------------------------------------------------
+ deal with constant target - constant becomes offset, result in DREG
+-----------------------------------------------------------------------------*/
+
+ if (target->storage == CONSTANT)
+ {
+ target->storage = DREG;
+ return;
+ }
+
+/*-----------------------------------------------------------------------------
+ load target if it is indirect or GLOBAL or canABX so D or B can be added
+ otherwise, it is register direct (maybe S register, maybe with offset)
+ and the offset can be left after adding DREG
+-----------------------------------------------------------------------------*/
+
+#ifdef I8088
+ if (target->indcount != 0)
+ {
+ targtype = target->type;
+ target->type = itype;
+ add(source, target);
+ target->type = targtype;
+ return;
+ }
+ if ((store_t) sourcereg == GLOBAL)
+ {
+ target->storage = source->storage;
+ target->level = OFFKLUDGELEVEL;
+ return;
+ }
+#endif
+#ifdef MC6809
+ if (canABX || (store_t) sourcereg == GLOBAL)
+ {
+ load(target, targreg);
+ sourcereg = targreg;
+ }
+ else if (target->indcount != 0)
+ {
+ targtype = target->type;
+ target->type = itype;
+ add(source, target);
+ target->type = targtype;
+ return;
+ }
+ if (canABX)
+ while (size--)
+ outABX();
+ else
+#endif
+ {
+#ifdef I8088
+ if ((store_t) targreg != (store_t) sourcereg)
+ regtransfer(sourcereg, targreg);
+ outadd();
+ outregname(targreg);
+ outncregname(DREG);
+#endif
+#ifdef MC6809
+ outlea();
+ outregname(targreg);
+ outtab();
+ outregname(DREG);
+ outncregname(sourcereg);
+#endif
+ }
+ if ((store_t) sourcereg == LOCAL)
+#ifdef FRAMEPOINTER
+ target->offset.offi -= framep;
+#else
+ target->offset.offi -= sp;
+#endif
+ target->storage = targreg;
+}
+
+PUBLIC void indirec(source)
+struct symstruct *source;
+{
+ if (!(source->type->constructor & (ARRAY | POINTER)))
+ bugerror("illegal indirection");
+ else if (source->indcount == (indn_t) - 1)
+ limiterror("too many indirections (256)");
+ else
+ {
+ if (source->storage & ALLDATREGS)
+ transfer(source, getindexreg());
+ if (!((source->type = source->type->nexttype)->constructor &
+ (ARRAY | FUNCTION)))
+ ++source->indcount;
+ if (source->storage == CONSTANT)
+ source->storage = GLOBAL;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ load(source leaf, target register)
+ loads the specified register without changing any others (except CC)
+ if the type is long or float, DREG is paired with the target register
+ the result has no offset
+-----------------------------------------------------------------------------*/
+
+PUBLIC void load(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ if (source->type->scalar & DLONG)
+ {
+ if (source->storage == CONSTANT)
+ loadreg(source, targreg);
+ else if (source->indcount == 0)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (!long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ {
+ if ((store_t) targreg == DREG)
+ source->storage = DREG;
+ }
+#endif
+ if (source->storage != (store_t) targreg)
+ transfer(source, targreg);
+ if (source->offset.offi != 0)
+ bugerror("loading direct long with offset not implemented");
+ }
+ else
+ loadlongindirect(source, targreg);
+ }
+ else if (source->type->scalar & DOUBLE)
+ {
+ if (source->storage == targreg && source->indcount == 0)
+ return;
+ if (source->storage == CONSTANT)
+ {
+ /* XXX - more for non-386 */
+ loadconst(((offset_t *) source->offset.offd)[0], DREG);
+ loadconst(((offset_t *) source->offset.offd)[1], targreg);
+ }
+ else
+ {
+ push(source);
+ poplist(targreg | DREG); /* actually it's the full reg list */
+ }
+ source->storage = targreg; /* XXX - multi for non-386 */
+ source->indcount = 0;
+ source->flags = 0;
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ source->offset.offi = 0;
+ }
+ else if (source->type->scalar & FLOAT && source->storage == CONSTANT)
+ {
+ float val;
+
+ val = *source->offset.offd;
+ loadconst(((offset_t *) &val)[0], targreg);
+ }
+ else if (source->indcount == 0 && source->storage != CONSTANT)
+ loadadr(source, targreg);
+ else if (source->type->scalar ||
+ source->type->constructor & (ARRAY | POINTER))
+ loadreg(source, targreg);
+ else
+ bugerror("attempting to load non-scalar non-pointer");
+}
+
+PRIVATE void loadadr(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ if ((store_t) targreg & ALLDATREGS)
+ {
+ if (source->storage == GLOBAL)
+ {
+#ifdef MC6809
+ if (posindependent)
+ {
+ pushreg(INDREG0);
+ loadreg(source, INDREG0);
+ transfer(source, DREG);
+ recovlist(INDREG0);
+ }
+ else
+#endif
+ loadreg(source, targreg);
+ }
+ if (source->storage == LOCAL)
+#ifdef FRAMEPOINTER
+ source->offset.offi -= framep;
+#else
+ source->offset.offi -= sp;
+#endif
+ if (source->type->scalar & CHAR)
+ targreg = BREG;
+#ifdef I8088
+ if (source->storage == DREG)
+ addoffset(source);
+#endif
+ if (source->storage != (store_t) targreg)
+ transfer(source, targreg);
+ addoffset(source);
+ }
+ else if (source->storage & ALLDATREGS)
+ {
+ addoffset(source);
+ transfer(source, targreg);
+ }
+ else if (source->storage != (store_t) targreg ||
+ source->offset.offi != 0 || source->level == OFFKLUDGELEVEL)
+ loadreg(source, targreg);
+}
+
+PUBLIC void loadany(source)
+struct symstruct *source;
+{
+ if (source->indcount != 0 || source->offset.offi != 0 || /* kludge u cmp */
+ source->level == OFFKLUDGELEVEL || !(source->storage & allregs))
+ {
+ if (source->type->scalar & RSCALAR)
+ load(source, doubleregs & ~DREG);
+ else if (source->storage == CONSTANT && !(source->type->scalar & DLONG)
+ || source->type->scalar & CHAR)
+ load(source, DREG);
+ else if (source->storage & ~reguse & allregs)
+ load(source, source->storage);
+ else if (((reguse & allindregs) == allindregs ||
+ !(source->type->constructor & (ARRAY | POINTER)) &&
+ source->indcount != 0) &&
+ !(source->type->scalar & DLONG))
+ load(source, DREG);
+ else
+ load(source, getindexreg());
+ }
+}
+
+PRIVATE void loadlongindirect(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ sc_t flags;
+ offset_t offset;
+ store_t reg;
+ struct typestruct *type;
+
+ if (source->level == OFFKLUDGELEVEL)
+ addoffset(source); /* else kludge is lost and offsets big */
+ flags = source->flags;
+ offset = source->offset.offi;
+ reg = source->storage;
+ type = source->type;
+ source->type = itype;
+ loadreg(source, DREG);
+ source->flags = flags;
+ source->storage = reg;
+ source->indcount = 1;
+ source->offset.offi = offset + accregsize;
+ loadreg(source, targreg);
+ source->type = type;
+}
+
+PUBLIC void loadreg(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ offset_t longhigh;
+ offset_t longlow;
+
+ if (source->storage == CONSTANT)
+ {
+ if (source->type->scalar & CHAR && (store_t) targreg & ALLDATREGS)
+ targreg = BREG;
+ longlow = (offset_t) source->offset.offv;
+ if (source->type->scalar & DLONG)
+ {
+ longlow &= (offset_t) intmaskto;
+ longhigh = (offset_t) (source->offset.offv >> INT16BITSTO)
+ & (offset_t) intmaskto;
+ if ((store_t) targreg != LONGREG2) /* loading the whole long */
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ loadconst(longhigh, DREG);
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ {
+ loadconst(longlow, DREG);
+ longlow = longhigh;
+ }
+#endif
+ }
+ }
+ loadconst(longlow, targreg);
+ source->storage = targreg;
+ source->offset.offi = 0;
+ }
+ else
+ {
+#ifdef I8088
+ if (source->indcount == 0 && source->storage != GLOBAL &&
+ (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL))
+ {
+ if ((store_t) targreg == source->storage)
+ {
+ addoffset(source);
+ return;
+ }
+ source->indcount = 1; /* fake for outadr() to produce "()" */
+ outlea();
+ }
+ else
+ {
+ outload();
+ if (source->storage == GLOBAL && source->indcount != 0 &&
+ (store_t) targreg & (AXREG | ALREG))
+ unbumplc();
+ }
+#endif
+#ifdef MC6809
+ if (source->indcount == 0 &&
+ (source->storage != GLOBAL || posindependent))
+ outlea();
+ else
+ {
+ outload();
+ if ((store_t) targreg == YREG)
+ bumplc();
+ }
+#endif
+ movereg(source, targreg);
+ }
+}
+
+PUBLIC void makelessindirect(source)
+struct symstruct *source;
+{
+ store_pt lreg;
+
+ if (!((store_t) (lreg = source->storage) & ~reguse & allindregs))
+ lreg = getindexreg();
+ while (source->indcount > MAXINDIRECT)
+ loadreg(source, lreg);
+#if MAXINDIRECT > 1
+ if (source->indcount == MAXINDIRECT &&
+ (source->type->typesize > maxregsize ||
+ source->type->constructor & FUNCTION))
+ {
+ source->indcount = 1;
+ loadreg(source, lreg);
+ source->indcount = 1;
+ }
+#endif
+}
+
+PUBLIC void movereg(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ if ((store_t) targreg & ALLDATREGS && source->type->scalar & CHAR)
+ targreg = BREG;
+#ifdef I8088
+ if (i386_32 && source->type->scalar & SHORT &&
+ source->indcount <= 1)
+ {
+ outshortregname(targreg);
+ bumplc();
+ }
+ else
+#endif
+ outregname(targreg);
+ if (source->storage == CONSTANT)
+ adjlc((offset_t) source->offset.offv, targreg);
+#ifdef I8088
+ outcomma();
+#endif
+ outadr(source);
+ source->storage = targreg; /* in register for further use */
+ source->flags = 0;
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ source->offset.offi = 0; /* indcount was adjusted by outadr */
+}
+
+PUBLIC void onstack(target)
+register struct symstruct *target;
+{
+ target->storage = LOCAL;
+ target->flags = TEMP;
+ if (target->level == OFFKLUDGELEVEL)
+ target->level = EXPRLEVEL;
+ target->indcount = 1;
+ target->offset.offi = sp;
+}
+
+PUBLIC void outadr(adr)
+struct symstruct *adr;
+{
+ outnnadr(adr);
+ outnl();
+}
+
+PUBLIC void outcregname(reg)
+store_pt reg;
+{
+ outcomma();
+ outregname(reg);
+}
+
+PRIVATE void outnamoffset(adr)
+struct symstruct *adr;
+{
+ outimmed();
+ if (adr->flags & LABELLED)
+ outlabel(adr->name.label);
+ else
+ outccname(adr->name.namep);
+ if (adr->offset.offi != 0)
+ {
+ if (adr->offset.offi > 0)
+ outplus();
+ outshex(adr->offset.offi);
+ }
+ bumplc2();
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+/* print comma, then register name, then newline */
+
+PUBLIC void outncregname(reg)
+store_pt reg;
+{
+ outcomma();
+ outnregname(reg);
+}
+
+PRIVATE void outnnadr(adr)
+struct symstruct *adr;
+{
+ bool_t indflag;
+
+ indflag = FALSE;
+#ifdef I8088
+ if (adr->indcount >= MAXINDIRECT)
+ indflag = TRUE;
+#endif
+#ifdef MC6809
+ outtab();
+ if (adr->indcount >= MAXINDIRECT && (adr->indcount & 1) == 0)
+ {
+ indflag = TRUE; /* indirection means double indirect */
+ outindleft();
+ }
+#endif
+ switch (adr->storage)
+ {
+ case CONSTANT:
+ outimmadr((offset_t) adr->offset.offv);
+ break;
+#ifdef I8088
+ case DREG:
+ if (indflag || adr->offset.offi != 0 || adr->level == OFFKLUDGELEVEL)
+ badaddress();
+ else
+ outregname(DREG);
+ break;
+#endif
+#ifdef I8088
+ case DATREG1:
+ case DATREG2:
+ if (indflag && !i386_32)
+ {
+ outnl();
+ badaddress();
+ break;
+ }
+#endif
+ case INDREG0:
+ case INDREG1:
+ case INDREG2:
+ if (adr->level == OFFKLUDGELEVEL)
+ outnamoffset(adr);
+#ifndef MC6809
+ else if (adr->offset.offi != 0)
+#endif
+ outoffset(adr->offset.offi);
+#ifdef I8088
+ if (indflag)
+ outindleft();
+ outregname(adr->storage);
+# ifdef XENIX_AS
+ if (indflag)
+ outindright();
+# endif
+#endif
+#ifdef MC6809
+ if (indflag && adr->offset.offi != 0 && is5bitoffset(adr->offset.offi))
+ bumplc();
+ outcregname(adr->storage);
+#endif
+ break;
+ case LOCAL:
+#ifdef I8088
+# ifdef FRAMEPOINTER
+ if (framep == 0)
+ bugerror("no frame pointer");
+ if (indflag)
+ {
+ if (adr->offset.offi == framep)
+ bumplc();
+ else
+ {
+ if (switchnow != NULL && adr->flags == TEMP)
+ outswoffset(adr->offset.offi);
+ else
+ outoffset(adr->offset.offi - framep);
+ }
+ outindleft();
+ }
+ else if (adr->offset.offi != framep)
+ badaddress();
+ outregname(LOCAL);
+# else
+ if (indflag)
+ {
+ bumplc();
+ if (adr->offset.offi != sp)
+ outoffset(adr->offset.offi - sp);
+ outindleft();
+ }
+ else if (adr->offset.offi != sp)
+ badaddress();
+ outregname(LOCAL);
+# endif /* FRAMEPOINTER */
+# ifdef XENIX_AS
+ if (indflag)
+ outindright();
+# endif
+#endif /* I8088 */
+#ifdef MC6809
+ if (adr->flags == TEMP && adr->offset.offi == sp &&
+ adr->indcount == 1)
+ {
+ outcregname(LOCAL);
+ outplus();
+ ++sp;
+ if (adr->type->typesize != 1)
+ {
+ outplus();
+ ++sp;
+ }
+ break;
+ }
+ outoffset(adr->offset.offi - sp);
+ if (indflag && adr->offset.offi != sp &&
+ is5bitoffset(adr->offset.offi - sp))
+ bumplc();
+ outcregname(LOCAL);
+#endif /* MC6809 */
+ break;
+ case GLOBAL:
+#ifdef I8088
+ bumplc();
+ if (i386_32)
+ bumplc2();
+ if (!indflag)
+ outimmed();
+ else
+ {
+# ifndef XENIX_AS
+ outindleft();
+# endif
+ bumplc();
+ }
+#endif
+#ifdef MC6809
+ if (!posindependent)
+ {
+ if (adr->indcount == 0)
+ {
+ outimmed();
+ bumplc();
+ }
+ else if (indflag)
+ {
+ outextended();
+ bumplc2();
+ }
+ else if (adr->flags & DIRECTPAGE)
+ outdirectpage();
+ else
+ {
+ outextended();
+ bumplc();
+ }
+ }
+#endif
+ if (adr->flags & LABELLED)
+ outlabel(adr->name.label);
+ else if (*adr->name.namep == 0) /* constant address */
+ {
+ outhex((uoffset_t) adr->offset.offi);
+ break;
+ }
+ else
+ outccname(adr->name.namep);
+ if (adr->offset.offi != 0)
+ {
+ if (adr->offset.offi > 0)
+ outplus();
+ outshex(adr->offset.offi);
+ }
+#ifdef MC6809
+ if (posindependent)
+ {
+ outcregname(GLOBAL);
+ bumplc2();
+ }
+#endif
+ break;
+ default:
+ outnl();
+ badaddress();
+ break;
+ }
+#ifdef I8088
+ if (indflag)
+ {
+ --adr->indcount;
+# ifndef XENIX_AS
+ outindright();
+# endif
+ }
+#endif
+#ifdef MC6809
+ if (indflag)
+ {
+ outindright();
+ adr->indcount -= MAXINDIRECT;
+ }
+ else if (adr->indcount != 0)
+ --adr->indcount;
+#endif
+}
+
+/* print register name, then newline */
+
+PUBLIC void outnregname(reg)
+store_pt reg;
+{
+ outregname(reg);
+ outnl();
+}
+
+/* print register name */
+
+PUBLIC void outregname(reg)
+store_pt reg;
+{
+ switch ((store_t) reg)
+ {
+ case BREG:
+ outstr(acclostr);
+ break;
+ case DREG:
+ outstr(accumstr);
+ break;
+#ifdef MC6809
+ case GLOBAL:
+ outstr("PC");
+ break;
+#endif
+ case INDREG0:
+ outstr(ireg0str);
+ break;
+ case INDREG1:
+ outstr(ireg1str);
+ break;
+ case INDREG2:
+ outstr(ireg2str);
+ break;
+ case LOCAL:
+ outstr(localregstr);
+ break;
+#ifdef STACKREG
+ case STACKREG:
+ outstr(stackregstr);
+ break;
+#endif
+#ifdef DATREG1
+ case DATREG1:
+ outstr(dreg1str);
+ break;
+#endif
+#ifdef DATREG1B
+ case DATREG1B:
+ outstr(dreg1bstr);
+ break;
+#endif
+#ifdef DATREG2
+ case DATREG2:
+ outstr(dreg2str);
+ break;
+#endif
+ default:
+ outstr(badregstr);
+ break;
+ }
+}
+
+#ifdef I8088
+/* print register name for short type */
+
+PUBLIC void outshortregname(reg)
+store_pt reg;
+{
+ switch ((store_t) reg)
+ {
+ case DREG:
+ outstr(accumstr + 1);
+ break;
+ case INDREG0:
+ outstr(ireg0str + 1);
+ break;
+ case INDREG1:
+ outstr(ireg1str + 1);
+ break;
+ case INDREG2:
+ outstr(ireg2str + 1);
+ break;
+ case DATREG1:
+ outstr(dreg1str + 1);
+ break;
+ case DATREG2:
+ outstr(dreg2str + 1);
+ break;
+ default:
+ outstr(badregstr);
+ break;
+ }
+}
+
+#endif
+
+/*-----------------------------------------------------------------------------
+ pointat(target leaf)
+ point OPREG at target
+ target must be singly indirect or float or double
+-----------------------------------------------------------------------------*/
+
+PUBLIC void pointat(target)
+struct symstruct *target;
+{
+ if (target->type->scalar & RSCALAR)
+ (void) f_indirect(target);
+ address(target);
+ load(target, OPREG);
+ target->type = target->type->nexttype;
+}
+
+PUBLIC void poplist(reglist)
+store_pt reglist;
+{
+ if (reglist)
+ sp += pushpull(reglist, FALSE);
+}
+
+PUBLIC void push(source)
+struct symstruct *source;
+{
+ store_t reg;
+#ifdef I8088
+ uoffset_t size;
+#endif
+ scalar_t sscalar;
+
+ if (source->type->constructor & STRUCTU)
+ {
+ if (source->flags != TEMP) /* TEMP must be from last function */
+ blockpush(source);
+ }
+ else if ((sscalar = source->type->scalar) & RSCALAR)
+ {
+ if (!f_indirect(source))
+ {
+ saveopreg();
+ fpush(source);
+ restoreopreg();
+ }
+ }
+#ifdef I8088
+ else if (source->indcount == 1 &&
+ (sscalar & (SHORT | INT | LONG | FLOAT) ||
+ source->type->constructor & POINTER) ||
+ source->storage == CONSTANT && i386_32)
+ {
+ size = source->type->typesize;
+ if (size == 1)
+ size = 2;
+ if (sscalar & DLONG)
+ {
+ source->offset.offi += itypesize;
+ outpshs();
+ bumplc();
+ outtab();
+ outadr(source);
+ source->indcount = 1;
+ source->offset.offi -= itypesize;
+ }
+ outpshs();
+ bumplc();
+ outtab();
+ if (i386_32)
+ {
+ if (source->storage == CONSTANT)
+ {
+ unbumplc();
+ adjlc((offset_t) source->offset.offv, INDREG0);
+ }
+ if (size == 2)
+ {
+ outword();
+ bumplc();
+ }
+ else
+ outdword();
+ }
+ outadr(source);
+ sp -= size;
+ }
+#endif
+ else
+ {
+ reg = source->storage;
+ loadany(source);
+ if (sscalar & DLONG)
+ pushlist(DREG | source->storage);
+ else if (sscalar & CHAR)
+ pushchar();
+ else
+ pushreg(source->storage);
+ if (source->flags != REGVAR)
+ reguse &= ~(reg | source->storage);
+ }
+ onstack(source);
+}
+
+PUBLIC void pushlist(reglist)
+store_pt reglist;
+{
+ if ((store_t) reglist)
+ sp -= pushpull(reglist, TRUE);
+}
+
+PRIVATE fastin_pt pushpull(reglist, pushflag)
+store_pt reglist;
+bool_pt pushflag;
+{
+ store_pt lastregbit;
+ void (*ppfunc) P((void));
+ char *regptr;
+
+#ifdef MC6809
+ int separator; /* promoted char for output */
+
+#endif
+ fastin_t bytespushed;
+ store_pt regbit;
+
+ if ((bool_t) pushflag)
+ {
+ ppfunc = outpshs;
+#ifdef I8088
+ regbit = 1 << 10;
+#else
+ regbit = 1 << 7;
+#endif
+ regptr = regpushlist;
+ lastregbit = 1;
+ }
+ else
+ {
+ ppfunc = outpuls;
+ regbit = 1;
+ regptr = regpulllist;
+#ifdef I8088
+ lastregbit = 1 << 10;
+#else
+ lastregbit = 1 << 7;
+#endif
+ }
+#ifdef MC6809 /* temp use pull strings to keep old order */
+ regbit = 1;
+ regptr = regpulllist;
+ lastregbit = 1 << 7;
+#endif
+#ifdef MC6809
+ separator = OPSEPARATOR;
+ (*ppfunc) ();
+#endif
+ bytespushed = 0;
+ while (TRUE)
+ {
+ if (regbit & reglist)
+ {
+#ifdef I8088
+ (*ppfunc)();
+ if (*regptr != FLAGSREGCHAR)
+ outtab();
+#endif
+#ifdef MC6809
+ outbyte(separator);
+#endif
+ do
+ outbyte(*regptr++);
+ while (*regptr >= MINREGCHAR);
+ bytespushed += *regptr++ - '0';
+#ifdef I8088
+ outnl();
+#endif
+#ifdef MC6809
+ separator = OPERANDSEPARATOR;
+#endif
+ }
+ else
+ do
+ ;
+ while (*regptr++ >= MINREGCHAR);
+ if (regbit == lastregbit)
+ break;
+#ifdef MC6809 /* temp use pull strings to keep old order */
+ regbit <<= 1;
+#else /* this should normally be unconditional */
+ if ((bool_t) pushflag)
+ regbit >>= 1;
+ else
+ regbit <<= 1;
+#endif
+ }
+#ifdef MC6809
+ outnl();
+#endif
+ return bytespushed;
+}
+
+PUBLIC void pushreg(reg)
+store_pt reg;
+{
+ outpshs();
+ outtab();
+ outnregname(reg);
+ sp -= pshregsize;
+}
+
+PUBLIC void storereg(sourcereg, target)
+store_pt sourcereg;
+struct symstruct *target;
+{
+ store_pt targreg;
+
+ if (target->indcount == 0)
+ {
+ if (target->offset.offi != 0 || target->level == OFFKLUDGELEVEL ||
+ !(target->storage & allregs) || target->storage & CHARREGS)
+ bugerror("bad register store");
+ else if ((store_t) (targreg = target->storage) != (store_t) sourcereg)
+ {
+ target->storage = sourcereg;
+ loadadr(target, targreg); /* do LEA or TFR */
+ }
+ }
+ else
+ {
+ outstore();
+#ifdef I8088
+ if (target->storage == GLOBAL && (store_t) sourcereg & (AXREG | ALREG))
+ unbumplc();
+ outnnadr(target);
+ outcomma();
+#ifdef I8088
+ if (i386_32 && target->type->scalar & SHORT)
+ {
+ outshortregname(sourcereg);
+ bumplc();
+ outnl();
+ }
+ else
+#endif
+ outnregname(sourcereg);
+#endif
+#ifdef MC6809
+ if ((store_t) sourcereg == YREG)
+ bumplc();
+ outregname(sourcereg);
+ outadr(target);
+#endif
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ struc(element leaf, structure leaf)
+ evaluates the expression
+ structure.element
+-----------------------------------------------------------------------------*/
+
+PUBLIC void struc(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ address(target);
+ if (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL)
+ {
+ if (target->indcount != 0 || target->level == OFFKLUDGELEVEL)
+ load(target, getindexreg());
+ target->offset.offi += source->offset.offi;
+ }
+ if (source->indcount == 0)
+ target->type = source->type;
+ else
+ {
+ target->type = pointype(source->type); /* lost by = */
+ indirec(target);
+ }
+}
+
+PUBLIC void transfer(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ regtransfer(source->storage, targreg);
+ source->storage = targreg;
+}
diff --git a/bcc-bruce/glogcode.c b/bcc-bruce/glogcode.c
new file mode 100644
index 0000000..edbedcd
--- /dev/null
+++ b/bcc-bruce/glogcode.c
@@ -0,0 +1,560 @@
+/* glogcode.c - generate code for logical expressions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#define cc_signed(cc) ((cc) >= 4 && (cc) < 8)
+
+PRIVATE char oppcc[] = /* opposite condition codes LT --> GE etc */
+/* EQ, NE, RA, RN, LT, GE, LE, GT, LO, HS, LS, HI, indices */
+{
+ NE, EQ, RN, RA, GE, LT, GT, LE, HS, LO, HI, LS,
+};
+
+PRIVATE char reverscc[] = /* reverse condition codes LT --> GT etc */
+{
+ EQ, NE, RN, RA, GT, LE, GE, LT, HI, LS, HS, LO,
+};
+
+PRIVATE char testcc[] = /* test condition codes LS --> EQ etc */
+{
+ EQ, NE, RA, RN, LT, GE, LE, GT, RN, RA, EQ, NE,
+};
+
+PRIVATE char unsigncc[] = /* unsigned condition codes LT --> LO etc */
+{
+ EQ, NE, RA, RN, LO, HS, LS, HI, LO, HS, LS, HI,
+};
+
+FORWARD void cmplocal P((struct symstruct *source, struct symstruct *target,
+ ccode_t *pcondtrue));
+#ifdef MC6809
+FORWARD void cmporsub P((struct symstruct *target));
+FORWARD bool_pt cmpsmallconst P((value_t intconst, struct symstruct *target,
+ ccode_t *pcondtrue));
+#endif
+FORWARD void comparecond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void jumpcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void loadlogical P((struct symstruct *source, label_t falselab));
+FORWARD void logandcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void logorcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void reduceconst P((struct symstruct *source));
+FORWARD void test P((struct symstruct *target, ccode_t *pcondtrue));
+FORWARD void testcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+
+PUBLIC void cmp(source, target, pcondtrue)
+struct symstruct *source;
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+ label_t falselab;
+
+ cmplocal(source, target, pcondtrue);
+#if 0
+#ifdef I8088
+ if (i386_32)
+ {
+ if (*pcondtrue == LO)
+ {
+ getlabel();
+ getlabel();
+ outnop2str("sbb\teax,eax");
+ outnop1str("inc eax");
+ target->storage = BREG;
+ target->type = ctype;
+ return;
+ }
+ if (*pcondtrue == HS)
+ {
+ getlabel();
+ getlabel();
+ outnop2str("sbb\teax,eax");
+ outnop2str("neg eax");
+ target->storage = BREG;
+ target->type = ctype;
+ return;
+ }
+ }
+#endif
+#endif
+ sbranch(oppcc[*pcondtrue], falselab = getlabel());
+ loadlogical(target, falselab);
+}
+
+PRIVATE void cmplocal(source, target, pcondtrue)
+struct symstruct *source;
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+ scalar_t sscalar;
+ scalar_t tempscalar;
+ scalar_t tscalar;
+
+ reduceconst(source);
+ reduceconst(target);
+ sscalar = source->type->scalar;
+ tscalar = target->type->scalar;
+ if (source->storage != CONSTANT &&
+ (target->storage == CONSTANT ||
+ sscalar & CHAR && !(tscalar & CHAR) ||
+ (sscalar & CHAR || !(tscalar & CHAR)) &&
+ source->indcount == 0 && target->indcount != 0) ||
+ tscalar & DLONG && target->indcount != 0)
+ {
+ swapsym(target, source);
+ *pcondtrue = reverscc[*pcondtrue];
+ tempscalar = sscalar;
+ sscalar = tscalar;
+ tscalar = tempscalar;
+ }
+ if (sscalar & CHAR && tscalar & CHAR &&
+ (source->type != sctype || target->type != sctype) ||
+ (sscalar | tscalar) & UNSIGNED ||
+ (source->type->constructor | target->type->constructor) &
+ (ARRAY | POINTER))
+ *pcondtrue = unsigncc[*pcondtrue];
+ if (source->type->scalar & DLONG)
+ {
+ longop(EQOP, source, target);
+ return;
+ }
+ if (source->type->scalar & RSCALAR)
+ {
+ floatop(EQOP, source, target);
+ return;
+ }
+ if (source->storage == CONSTANT)
+ {
+ if (sscalar & CHAR)
+ {
+ if (tscalar & CHAR)
+ *pcondtrue = unsigncc[*pcondtrue];
+ else
+ {
+ source->type = iscalartotype(sscalar);
+ sscalar = source->type->scalar;
+ }
+ }
+ if (source->offset.offv == 0)
+ {
+ test(target, pcondtrue);
+ return;
+ }
+#ifdef MC6809
+ if (cmpsmallconst(source->offset.offv, target, pcondtrue))
+ return;
+#endif
+ }
+ if (!(sscalar & CHAR) && tscalar & CHAR)
+ {
+ loadpres(target, source);
+ extend(target);
+ }
+#ifndef MC6809
+# define posindependent 0
+#endif
+ if (source->indcount == 0 && source->storage != CONSTANT &&
+ (posindependent || source->storage != GLOBAL))
+ {
+ loadpres(source, target);
+#ifdef MC6809
+ push(source);
+#endif
+ }
+ loadpres(target, source);
+#ifdef MC6809
+ cmporsub(target);
+#else
+ outcmp();
+#endif
+#ifdef I8088
+ if (source->storage == GLOBAL && source->indcount == 0 &&
+ !(target->storage & (AXREG | ALREG)))
+ bumplc();
+#endif
+ movereg(source, target->storage);
+}
+
+#ifdef MC6809
+
+PRIVATE void cmporsub(target)
+struct symstruct *target;
+{
+ if (target->storage & ALLDATREGS)
+ outsub();
+ else
+ {
+ outcmp();
+ if (target->storage != XREG)
+ bumplc();
+ }
+}
+
+PRIVATE bool_pt cmpsmallconst(intconst, target, pcondtrue)
+value_t intconst;
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+ store_pt targreg;
+
+ if ((*pcondtrue == EQ || *pcondtrue == NE) &&
+ !(target->storage & ALLDATREGS) && !(target->type->scalar & CHAR) &&
+ isnegbyteoffset(intconst) &&
+ (reguse & (XREG | YREG)) != (XREG | YREG))
+ {
+ targreg = XREG;
+ if (reguse & XREG)
+ targreg = YREG;
+ if (target->indcount != 0)
+ load(target, targreg);
+ target->offset.offi -= (offset_t) intconst;
+ loadreg(target, targreg);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#endif
+
+PRIVATE void comparecond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ ccode_t condtrue;
+ store_t regmark;
+ struct symstruct *source;
+ offset_t spmark;
+ struct symstruct *target;
+
+ regmark = reguse;
+ spmark = sp;
+ bileaf(exp);
+ target = exp->left.nodeptr->left.symptr;
+ source = exp->right->left.symptr; /* exp->right != NULL since cond */
+ switch (exp->tag)
+ {
+ case GEOP:
+ condtrue = GE;
+ break;
+ case GTOP:
+ condtrue = GT;
+ break;
+ case LEOP:
+ condtrue = LE;
+ break;
+ case EQOP:
+ condtrue = EQ;
+ break;
+ case LTOP:
+ condtrue = LT;
+ break;
+ case NEOP:
+ condtrue = NE;
+ break;
+ }
+ cmplocal(source, target, &condtrue);
+ changesp(spmark, FALSE);
+ reguse = regmark;
+ if ((bool_t) nojump)
+ lbranch(oppcc[condtrue], falselab);
+ else
+ lbranch(condtrue, truelab);
+}
+
+PUBLIC void condop(exp)
+struct nodestruct *exp;
+{
+ label_t exitlab;
+ label_t falselab;
+ struct nodestruct *falsenode;
+ struct symstruct *falsesym;
+ label_t truelab;
+ struct nodestruct *truenode;
+ struct symstruct *truesym;
+
+ jumpcond(exp->left.nodeptr, truelab = getlabel(),
+ falselab = getlabel(), ~0);
+ deflabel(truelab);
+ makeleaf(truenode = exp->right->left.nodeptr);
+ loadany(truesym = truenode->left.symptr);
+ if (truesym->storage & reguse)
+ {
+ /* This can happen if truesym was a reg variable. */
+ if (truesym->type->scalar & RSCALAR)
+ /* XXX - always happens for non-386 with 2 regs vars assigned. */
+ bugerror("loaded float or double into used reg");
+ load(truesym, DREG);
+ }
+ falsenode = exp->right->right;
+ if (/* falsenode->tag != LEAF || XXX */
+ truesym->type != falsenode->left.symptr->type)
+ cast(truenode->nodetype == falsenode->nodetype ?
+ truenode->nodetype : exp->nodetype, truesym);
+ jump(exitlab = getlabel());
+ deflabel(falselab);
+ makeleaf(falsenode);
+ falsesym = falsenode->left.symptr;
+ if (falsesym->type != truesym->type)
+ cast(truesym->type, falsesym);
+ load(falsesym, truesym->storage);
+ deflabel(exitlab);
+ exp->tag = LEAF;
+ exp->left.symptr = truesym;
+}
+
+PRIVATE void jumpcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ switch (exp->tag)
+ {
+ case GEOP:
+ case GTOP:
+ case LEOP:
+ case EQOP:
+ case LTOP:
+ case NEOP:
+ comparecond(exp, truelab, falselab, nojump);
+ break;
+ case LOGANDOP:
+ logandcond(exp, truelab, falselab, nojump);
+ break;
+ case LOGNOTOP:
+ jumpcond(exp->left.nodeptr, falselab, truelab, ~nojump);
+ break;
+ case LOGOROP:
+ logorcond(exp, truelab, falselab, nojump);
+ break;
+ default:
+ testcond(exp, truelab, falselab, nojump);
+ break;
+ }
+}
+
+PUBLIC void jumpfalse(exp, label)
+struct nodestruct *exp;
+label_t label;
+{
+ label_t truelab;
+
+ jumpcond(exp, truelab = getlabel(), label, ~0);
+ deflabel(truelab);
+}
+
+PUBLIC void jumptrue(exp, label)
+struct nodestruct *exp;
+label_t label;
+{
+ label_t falselab;
+
+ jumpcond(exp, label, falselab = getlabel(), 0);
+ deflabel(falselab);
+}
+
+PRIVATE void loadlogical(source, falselab)
+struct symstruct *source;
+label_t falselab;
+{
+ label_t exitlab;
+ struct symstruct *target;
+
+ target = constsym((value_t) TRUE);
+ target->type = ctype;
+ loadreg(target, DREG);
+ sbranch(RA, exitlab = getlabel());
+ deflabel(falselab);
+ target = constsym((value_t) FALSE);
+ target->type = ctype;
+ *source = *target;
+ loadreg(source, DREG);
+ outnlabel(exitlab);
+}
+
+PRIVATE void logandcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ label_t andlab;
+
+ andlab = getlabel();
+ jumpcond(exp->left.nodeptr, andlab, falselab, ~0);
+ deflabel(andlab);
+ jumpcond(exp->right, truelab, falselab, nojump);
+}
+
+PUBLIC void logop(exp)
+struct nodestruct *exp;
+{
+ label_t falselab;
+ struct symstruct *target;
+ label_t truelab;
+
+ jumpcond(exp, truelab = getlabel(), falselab = getlabel(), ~0);
+ deflabel(truelab);
+ target = constsym((value_t) 0); /* anything, loadlogical makes B reg */
+ target->type = ctype;
+ loadlogical(target, falselab);
+ exp->tag = LEAF;
+ exp->left.symptr = target;
+}
+
+PRIVATE void logorcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ label_t orlab;
+
+ orlab = getlabel();
+ jumpcond(exp->left.nodeptr, truelab, orlab, 0);
+ deflabel(orlab);
+ jumpcond(exp->right, truelab, falselab, nojump);
+}
+
+PRIVATE void reduceconst(source)
+struct symstruct *source;
+{
+ if (source->storage == CONSTANT && ischarconst(source->offset.offv) &&
+ (source->type->scalar & (CHAR | SHORT | INT | DLONG)) != DLONG)
+ {
+ if (source->type->scalar & UNSIGNED)
+ source->type = uctype;
+ else
+ source->type = ctype;
+ }
+}
+
+PRIVATE void test(target, pcondtrue)
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+#ifdef I8088
+ store_t targreg;
+#endif
+
+ *pcondtrue = testcc[*pcondtrue];
+ if (target->type->scalar & DLONG)
+ {
+ long1op(EQOP, target);
+ return;
+ }
+ if (target->type->scalar & RSCALAR)
+ {
+ float1op(EQOP, target);
+ return;
+ }
+#ifdef I8088
+ if (target->indcount != 0 ||
+ target->storage == LOCAL && target->offset.offi != sp)
+ load(target, DREG);
+ if (target->storage == GLOBAL)
+ load(target, getindexreg());
+ if (target->type->scalar & CHAR)
+ load(target, DREG);
+ targreg = target->storage;
+ if (target->offset.offi != 0 && cc_signed(*pcondtrue))
+ load(target, targreg);
+
+ /* Extension was not done in exptree for the == 0 case, to allow
+ * optimization here - which we don't do for shorts. (foo--) is
+ * newfoo == -1 here and used to be missed.
+ */
+ if (i386_32 && target->type->scalar & SHORT)
+ extend(target);
+
+ if (target->offset.offi == 0)
+ {
+ outtest();
+ outregname(targreg);
+ outcomma();
+ outnregname(targreg);
+ return;
+ }
+ outcmp();
+ outimadj(-target->offset.offi, targreg);
+#endif
+#ifdef MC6809
+ if (target->indcount != 0 ||
+ target->storage == LOCAL && target->offset.offi != sp)
+ {
+ load(target, DREG);
+ return;
+ }
+ if (cmpsmallconst(0, target, pcondtrue))
+ return;
+ if (target->storage == GLOBAL)
+ load(target, getindexreg());
+ if (target->type->scalar & CHAR)
+ load(target, DREG);
+ if (target->offset.offi != 0 && cc_signed(*pcondtrue))
+ load(target, target->storage);
+ if (target->type->scalar & CHAR)
+ {
+ if (target->offset.offi == 0)
+ {
+ outtest();
+ outnregname(BREG);
+ return;
+ }
+ outcmp();
+ outimadj(-target->offset.offi, BREG);
+ }
+ else
+ {
+ cmporsub(target);
+ outimadj(-target->offset.offi, target->storage);
+ }
+#endif
+}
+
+/* test expression and jump depending on NE/EQ */
+
+PRIVATE void testcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ ccode_t condtrue;
+ struct symstruct *source;
+
+ makeleaf(exp);
+ source = exp->left.symptr;
+ reduceconst(source);
+ if (source->storage != CONSTANT)
+ {
+ condtrue = NE;
+ test(source, &condtrue);
+ if ((bool_t) nojump)
+ lbranch(oppcc[condtrue], falselab);
+ else
+ lbranch(condtrue, truelab);
+ }
+ else if (source->offset.offi == 0)
+ {
+ if ((bool_t) nojump)
+ jump(falselab);
+ }
+ else if (!(bool_t) nojump)
+ jump(truelab);
+}
diff --git a/bcc-bruce/hardop.c b/bcc-bruce/hardop.c
new file mode 100644
index 0000000..8121484
--- /dev/null
+++ b/bcc-bruce/hardop.c
@@ -0,0 +1,510 @@
+/* hardop.c - hardware operations for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+FORWARD void sub1 P((struct symstruct *source, struct symstruct *target));
+
+PUBLIC void add(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ scalar_t sscalar;
+
+ if (source->indcount == 0 && source->storage != CONSTANT &&
+ (target->indcount != 0 || target->storage & ALLDATREGS))
+ swapsym(target, source);
+ if ((sscalar = source->type->scalar) & DLONG)
+ {
+ longop(ADDOP, source, target);
+ return;
+ }
+ if (sscalar & RSCALAR)
+ {
+ floatop(ADDOP, source, target);
+ return;
+ }
+ if (source->storage == CONSTANT)
+ {
+ extend(target);
+ if (target->indcount != 0 || target->storage & reguse)
+ loadany(target);
+ target->offset.offi += (offset_t) source->offset.offv;
+ }
+ else if (source->indcount == 0)
+ {
+ /* target is also direct */
+ sscalar |= target->type->scalar; /* remember if unsigned/long */
+ target->type = pctype; /* fake to use indexadr() */
+ indexadr(source, target);
+ }
+ else
+ {
+ /* source is indirect and not DREG */
+ extend(target);
+ load(target, DREG);
+ outadd();
+ movereg(source, DREG);
+ if (source->type->scalar & CHAR)
+ adc0();
+ }
+ target->type = iscalartotype(target->type->scalar | sscalar);
+}
+
+PUBLIC void incdec(op, source)
+op_pt op;
+struct symstruct *source;
+{
+ offset_t bump;
+ bool_t postflag;
+ store_t regmark;
+ struct symstruct *target;
+ struct symstruct targ;
+#ifdef MC6809
+ store_pt targreg;
+#endif
+
+ *(target = &targ) = *source;
+ bump = 1;
+ if (targ.type->constructor & POINTER)
+ bump = targ.type->nexttype->typesize;
+ if (op == PREDECOP || op == POSTDECOP)
+ bump = -bump;
+ postflag = FALSE;
+ if (op == POSTDECOP || op == POSTINCOP)
+ postflag = TRUE;
+ reguse |= targ.storage;
+ if (targ.type->scalar & DLONG) /* cannot be direct */
+ {
+ if (postflag)
+ {
+ regmark = reguse;
+ if (((reguse |= OPREG) & allindregs) == allindregs)
+ {
+ saveopreg();
+ load(source, OPREG);
+ pushreg(source->storage);
+ restoreopreg();
+ }
+ else
+ {
+ loadany(source);
+ reguse = regmark | source->storage;
+ saveopreg();
+ }
+ }
+ else
+ saveopreg();
+ pointat(target);
+ switch (op)
+ {
+ case PREDECOP:
+ case POSTDECOP:
+ call("ldec");
+ break;
+ case PREINCOP:
+ case POSTINCOP:
+ call("linc");
+ break;
+ }
+ outlongendian();
+ restoreopreg();
+ if (postflag && source->storage == OPREG)
+ poplist(OPREG);
+ return;
+ }
+ if (targ.type->scalar & RSCALAR)
+ {
+ saveopreg();
+ pointat(target);
+ switch (op)
+ {
+ case PREDECOP:
+ call("Fpredec");
+ break;
+ case PREINCOP:
+ call("Fpreinc");
+ break;
+ case POSTDECOP:
+ call("Fpostdec");
+ break;
+ case POSTINCOP:
+ call("Fpostinc");
+ break;
+ }
+ outntypechar(targ.type);
+ restoreopreg();
+ if (postflag)
+ {
+ justpushed(source);
+ source->type = targ.type;
+ }
+ return;
+ }
+ loadany(source);
+#ifdef MC6809
+ if (postflag && targ.flags != REGVAR &&
+ !(source->storage & ALLDATREGS) &&
+ ((reguse |= source->storage) & allindregs) != allindregs)
+ {
+ targreg = getindexreg();
+ outlea();
+ outregname(targreg);
+ outtab();
+ outshex(bump);
+ outncregname(source->storage);
+ }
+ else
+ {
+ addconst(bump, targreg = source->storage);
+ if (postflag)
+ source->offset.offi = -bump;
+ }
+ storereg(targreg, target);
+ target->storage = targreg;
+ target->offset.offi = 0;
+#else
+ addconst(bump, source->storage);
+ if (postflag)
+ source->offset.offi = -bump;
+ storereg(source->storage, target);
+ target->storage = source->storage;
+ target->offset.offi = 0;
+#endif
+}
+
+PUBLIC void neg(target)
+struct symstruct *target;
+{
+ scalar_t scalar;
+ struct symstruct *source;
+
+ if ((scalar = target->type->scalar) & DLONG)
+ long1op(NEGOP, target);
+ else if (scalar & RSCALAR)
+ float1op(NEGOP, target);
+ else
+ {
+ if (scalar & SHORT)
+ extend(target);
+ if (!(target->storage & ALLDATREGS))
+ {
+ /* load 0, subtract is shorter than load, negate */
+ /* if no hardware integer negate; about the same if there is */
+ sub1(target, source = constsym((value_t) 0));
+ *target = *source;
+ }
+ else
+ {
+ load(target, DREG);
+ negreg(target->storage);
+ target->storage = DREG;
+ }
+ target->type = iscalartotype(scalar);
+ }
+}
+
+PUBLIC void not(target)
+struct symstruct *target;
+{
+ if (target->type->scalar & DLONG)
+ long1op(NOTOP, target);
+ else
+ {
+ extend(target);
+ load(target, DREG);
+ comDreg();
+ }
+}
+
+/* 1-byte ops like AND acting on integers (not both constant) */
+
+PUBLIC void op1(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ char *opstr;
+#ifdef OP1
+# if MAXINDIRECT > 1
+ indn_t indcount;
+# endif
+#endif
+ bool_t resultchar;
+ scalar_t resultscalar;
+ scalar_t sscalar;
+ scalar_t tscalar;
+
+ if ((sscalar = source->type->scalar) & DLONG)
+ {
+ longop(op, source, target);
+ return;
+ }
+ /* Emergency fix. The types of constants should be reduced here and in
+ * other low-level routines anyway, and not in exptree.c and table.c,
+ * and for the 80386 and maybe the 8086 they would be better not
+ * reduced.
+ */
+ if (source->storage == CONSTANT && ischarconst(source->offset.offv))
+ {
+ if (sscalar & UNSIGNED)
+ source->type = uctype;
+ else
+ source->type = ctype;
+ sscalar = source->type->scalar;
+ }
+ tscalar = target->type->scalar;
+ if (target->storage == CONSTANT && ischarconst(target->offset.offv))
+ {
+ if (sscalar & UNSIGNED)
+ target->type = uctype;
+ else
+ target->type = ctype;
+ tscalar = target->type->scalar;
+ }
+ resultscalar = sscalar | tscalar;
+ if (op != ANDOP)
+ resultchar = sscalar & tscalar & CHAR;
+ else if ((resultchar = (sscalar | tscalar) & CHAR) != 0 &&
+ source->storage == CONSTANT)
+ {
+ source->offset.offv &= CHMASKTO;
+ if (sscalar & UNSIGNED)
+ source->type = uctype;
+ else
+ source->type = ctype;
+ sscalar = source->type->scalar;
+ }
+ if (target->indcount != 0 &&
+ (tscalar & CHAR && !(sscalar & CHAR) &&
+ op != ANDOP || source->indcount == 0 && source->storage != CONSTANT))
+ {
+ swapsym(target, source);
+ sscalar = tscalar;
+ tscalar = target->type->scalar;
+ }
+ if (source->indcount == 0 && source->storage != CONSTANT)
+ {
+ loadpres(source, target);
+ push(source);
+ }
+#if MAXINDIRECT > 1
+ else if (source->indcount >= MAXINDIRECT && !(sscalar & CHAR))
+ {
+ address(source);
+ if (!(target->storage & ALLDATREGS))
+ preserve(target);
+ load(source, getindexreg());
+ indirec(source);
+ }
+#endif
+ if (!(tscalar & CHAR) &&
+ op == ANDOP && sscalar & CHAR && target->indcount == 1)
+ cast(ctype, target);
+ if (!(target->storage & ALLDATREGS) || target->indcount != 0)
+ pres2(target, source);
+ load(target, DREG);
+ opstr = opstring(op);
+ if (source->storage == CONSTANT && op == ANDOP)
+ andconst((offset_t) source->offset.offv);
+#ifdef OP1
+ else if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP)
+ outload();
+ else
+ outop2str(opstr);
+#else /* OP1 */
+ else
+ {
+ if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP)
+ extend(target);
+ outop2str(opstr);
+ }
+#endif /* OP1 */
+ if (source->storage == CONSTANT)
+ {
+ if (op != ANDOP)
+ {
+#ifdef OP1
+ if (!(sscalar & CHAR))
+ {
+ outhiaccum();
+ outncimmadr((offset_t) ((uoffset_t) source->offset.offv
+ >> (INT16BITSTO - CHBITSTO)));
+ outop2str(opstr);
+ }
+ outregname(BREG);
+ outncimmadr((offset_t) source->offset.offv & CHMASKTO);
+#else /* OP1 */
+ if (!(sscalar & CHAR))
+ {
+ outregname(DREG);
+ bumplc();
+ }
+ else
+ outregname(BREG);
+# ifdef I8088
+ if (i386_32 && !(sscalar & CHAR))
+ bumplc2();
+# endif
+ outncimmadr((offset_t) source->offset.offv);
+
+#endif /* OP1 */
+ }
+ }
+ else if (sscalar & CHAR)
+ {
+ outregname(BREG);
+ outopsep();
+ outadr(source);
+ }
+ else
+ {
+#ifdef MC6809
+ source->type = ctype; /* fool outadr to avoid ,S++ */
+#endif
+#ifdef OP1
+ if (!(tscalar & CHAR) || op != ANDOP)
+ {
+ outhiaccum();
+# if MAXINDIRECT > 1
+ indcount = source->indcount;
+# endif
+ outopsep();
+# if BIG_ENDIAN == 0
+ ++source->offset.offi;
+# endif
+ outadr(source);
+# if BIG_ENDIAN == 0
+ --source->offset.offi;
+# endif
+# if MAXINDIRECT > 1
+ source->indcount = indcount;
+# else
+ source->indcount = 1;
+# endif
+ outop2str(opstr);
+ }
+ outregname(BREG);
+ outopsep();
+# if BIG_ENDIAN
+ ++source->offset.offi;
+# endif
+ outadr(source);
+ }
+#else /* OP1 */
+ if (!(tscalar & CHAR) || op != ANDOP)
+ outregname(DREG);
+ else
+ outregname(BREG);
+ outopsep();
+ outadr(source);
+ }
+#endif /* OP1 */
+ if (resultchar)
+ {
+ target->storage = BREG;
+ if (resultscalar & UNSIGNED)
+ target->type = uctype;
+ else
+ target->type = ctype;
+ }
+ else
+ {
+ target->storage = DREG;
+ target->type = iscalartotype(resultscalar);
+ }
+}
+
+PUBLIC void ptrsub(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ label_t exitlab;
+ uoffset_t factor;
+ label_t usignlab;
+
+ if (source->indcount == 0 && source->storage != CONSTANT)
+ {
+ loadpres(source, target);
+ push(source);
+ }
+ if (target->indcount == 0)
+ {
+ pres2(target, source);
+ load(target, DREG);
+ }
+ factor = target->type->nexttype->typesize;
+ source->type = target->type = itype;
+ sub1(source, target);
+ if (factor != 1)
+ {
+ pushlist(CCREG);
+ sbranch(HS, usignlab = getlabel()); /* HS == no carry */
+ negDreg();
+ outnlabel(usignlab);
+ target->type = uitype;
+ softop(DIVOP, constsym((value_t) factor), target);
+ target->type = itype;
+ poplist(CCREG);
+ sbranch(HS, exitlab = getlabel());
+ negDreg();
+ outnlabel(exitlab);
+ }
+}
+
+PUBLIC void sub(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ scalar_t sscalar;
+
+ if ((sscalar = source->type->scalar) & DLONG)
+ {
+ longop(SUBOP, source, target);
+ return;
+ }
+ if (sscalar & RSCALAR)
+ {
+ floatop(SUBOP, source, target);
+ return;
+ }
+ if (source->storage == CONSTANT)
+ {
+ extend(target);
+ if (target->indcount != 0 || target->storage & reguse)
+ loadany(target);
+ target->offset.offi -= (offset_t) source->offset.offv;
+ }
+ else
+ sub1(source, target);
+ target->type = iscalartotype(target->type->scalar | sscalar);
+}
+
+PRIVATE void sub1(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ if (source->storage == CONSTANT)
+ source->type = itype;
+ else if (source->indcount == 0)
+ {
+ loadpres(source, target);
+ push(source);
+ }
+ extend(target);
+ load(target, DREG);
+ outsub();
+ movereg(source, DREG);
+ if (source->type->scalar & CHAR)
+ sbc0();
+}
diff --git a/bcc-bruce/input.c b/bcc-bruce/input.c
new file mode 100644
index 0000000..f321a9d
--- /dev/null
+++ b/bcc-bruce/input.c
@@ -0,0 +1,729 @@
+/* input.c - input for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define ARBITRARY_BACKSLASH_NEWLINES_NOT
+#define INSERT_BACKSLASH_NEWLINES_NOT
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "output.h"
+#include "os.h"
+#include "sc.h"
+#include "scan.h"
+#include "table.h"
+
+#undef EXTERN
+#define EXTERN
+#include "input.h"
+
+#define INBUFSIZE 2048
+
+struct fbufstruct /* file buffer structure */
+{
+ struct fcbstruct fcb; /* status after opening an include sub-file */
+ char *fname; /* file name */
+ bool_t fname_malloced; /* nonzero if fname was malloced */
+ char pushback[3]; /* allows pushback to 2 before start of fbuf
+ * XXX 3 chars before?
+ * XXX should do everything in fbuf */
+ char fbuf[INBUFSIZE + 1]; /* buffer to read into */
+};
+
+struct inclist /* list of include file directories */
+{
+ char *incdirname;
+ struct inclist *incnext;
+};
+
+PRIVATE char filemacro[] = "__FILE__";
+PRIVATE struct inclist incabsolute; /* dummy list for absolute names */
+ /* depends on zero (NULL) init */
+PRIVATE struct inclist incfirst;
+ /* begin include searches here for "" */
+ /* at next in list for <> */
+ /* -I directories are put in list */
+ /* between first and last */
+PRIVATE struct inclist inclast =
+{
+ DEFAULT_INCLUDE_DIR,
+ NULL,
+};
+PRIVATE fastin_t inclevel; /* nest level of include files */
+ /* depends on zero init */
+PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */
+ /* its fcb only to date in includes */
+ /* depends on zero (NULL) init */
+PRIVATE bool_t suppress_line_numbers;
+
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+FORWARD void backslash P((void));
+#endif
+FORWARD void definefile P((char *fname));
+FORWARD void inputinit P((char *fname, fd_t fd));
+FORWARD void leaveinclude P((void));
+FORWARD void usage P((void));
+
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+PRIVATE void backslash()
+{
+ static unsigned nbackslash;
+
+ if (nbackslash != 0)
+ --nbackslash;
+more:
+ ++nbackslash;
+ while (*(lineptr + 1) == '\\')
+ {
+ ++nbackslash;
+ ++lineptr;
+ }
+ if (*(lineptr + 1) != EOL)
+ {
+ if (--nbackslash != 0)
+ *--lineptr = '\\'; /* force look at current backslash again */
+ return;
+ }
+ ch = *++lineptr;
+more1:
+ if (!eof && lineptr >= input.limit)
+ skipeol();
+ if (ch == EOL)
+ {
+ --nbackslash;
+ if (eof)
+ eofin("backslash-newline");
+ else
+ {
+ skipeol();
+ if (ch == EOL && !eof && lineptr >= input.limit)
+ skipeol();
+#ifdef COEOL /* XXX - this should go through specialchar() */
+ if (ch == COEOL)
+ {
+ ch = *++lineptr;
+ if (ch == EOL && !eof && lineptr >= input.limit)
+ skipeol();
+ }
+#endif
+ }
+ if (ch == '\\')
+ goto more;
+ if (nbackslash != 0 && ch == EOL && !eof)
+ goto more1;
+ if (nbackslash != 0)
+ {
+ ch = *--lineptr = '\\';
+ if (--nbackslash != 0)
+ ch = *--lineptr = '\\';
+ }
+ return;
+ }
+ if (ch == '\\')
+ goto more;
+ if (ch == EOL && !eof)
+ goto more1;
+ ch = *--lineptr = '\\'; /* pushback */
+ if (--nbackslash != 0)
+ ch = *--lineptr = '\\';
+}
+#endif
+
+PUBLIC void closein()
+{
+#ifdef FAKE_INBUFSIZE_1
+ fclose(input.fp);
+#else
+ close(input.fd);
+#endif
+ while (inclevel != 0)
+ leaveinclude();
+}
+
+PRIVATE void definefile(fname)
+char *fname;
+{
+ char *def;
+
+ def = ourmalloc(sizeof filemacro - 1 + 2 + strlen(fname) + 1 + 1);
+ strcpy(def, filemacro);
+ strcat(def, "=\"");
+ strcat(def, fname);
+ strcat(def, "\"");
+ definestring(def);
+ ourfree(def);
+}
+
+PUBLIC void errorloc()
+{
+ register struct fbufstruct *infbuf;
+
+ if ((infbuf = inputbuf) == NULL)
+ return;
+ outstr(infbuf->fname);
+ outbyte(':');
+ if (eof)
+ outstr("eof");
+ else
+ {
+ outudec(input.linenumber);
+ outbyte('.');
+ if (maclevel == 0)
+ outudec((unsigned) (lineptr - inputbuf->fbuf) - input.lineoffset);
+ else
+ {
+ outudec((unsigned) (savedlineptr() - inputbuf->fbuf)
+ - input.lineoffset);
+ outstr(" (macro level ");
+ outudec((unsigned) maclevel);
+ outbyte(')');
+ }
+ }
+ infbuf->fcb.includer = input.includer;
+ while ((infbuf = infbuf->fcb.includer) != NULL)
+ {
+ outstr(" (from ");
+ outstr(infbuf->fname);
+ outbyte(':');
+ outudec(infbuf->fcb.linenumber);
+ outbyte(')');
+ }
+ outstr(": ");
+}
+
+/* gch1() - get next char, advance ptr (only works on current line) */
+
+PUBLIC void gch1()
+{
+ if (SYMOFCHAR(ch = *++lineptr) != SPECIALCHAR)
+ return;
+ specialchar();
+}
+
+/* process #include */
+
+PUBLIC void include()
+{
+ char *dirnameptr;
+ char *dirnamend;
+ unsigned dirnamelen;
+ fd_t fd;
+ char *fnameptr;
+ char *fullnameptr;
+ struct inclist *incptr;
+ char terminator;
+
+ while (blanksident())
+ {
+ if ((gsymptr = findlorg(gsname)) == NULL ||
+ gsymptr->flags != DEFINITION)
+ break;
+ entermac();
+ }
+ if ((terminator = ch) == '<')
+ terminator = '>';
+ else if (terminator != '"')
+ {
+ error("bad file name");
+ return;
+ }
+ gch1();
+ fnameptr = charptr;
+ while (TRUE)
+ {
+ if (ch == EOL) /* no escapes in file names */
+ break;
+ if (ch == terminator)
+ {
+ gch1();
+ break;
+ }
+ if (charptr >= chartop)
+ fnameptr = growobject(fnameptr, 1);
+#ifdef TS
+++ts_n_filename;
+++ts_s_filename;
+++ts_s_filename_tot;
+#endif
+ *charptr++ = ch;
+ gch1();
+ }
+ if (charptr >= chartop)
+ fnameptr = growobject(fnameptr, 1);
+#ifdef TS
+++ts_n_filename_term;
+++ts_s_filename_term;
+++ts_s_filename_tot;
+#endif
+ *charptr++ = 0;
+ dirnamend = NULL;
+ if (isabspath(fnameptr, &ch))
+ incptr = &incabsolute;
+ else
+ {
+ incptr = &incfirst;
+ if (terminator == '>')
+ incptr = incptr->incnext;
+ else
+ {
+ dirnameptr = inputbuf->fname;
+ if ((dirnamend = strrchr(dirnameptr, DIRCHAR)) == NULL)
+ incptr->incdirname = NULL;
+ else
+ {
+ *dirnamend = 0;
+ incptr->incdirname = dirnameptr;
+ }
+ }
+ }
+ do
+ {
+ if (incptr->incdirname == NULL)
+ {
+ fullnameptr = ourmalloc(strlen(fnameptr) + 1);
+#ifdef TS
+++ts_n_pathname;
+ts_s_pathname += strlen(fnameptr) + 1;
+ts_s_pathname_tot += strlen(fnameptr) + 1;
+#endif
+ strcpy(fullnameptr, fnameptr);
+ }
+ else
+ {
+ dirnamelen = strlen(incptr->incdirname);
+ fullnameptr = ourmalloc(dirnamelen + (int) (charptr - fnameptr)
+ + 2);
+ /* 2 extra for null and maybe DIRCHAR */
+#ifdef TS
+++ts_n_pathname;
+ts_s_pathname += dirnamelen + (charptr - fnameptr) + 2;
+ts_s_pathname_tot += dirnamelen + (charptr - fnameptr) + 2;
+#endif
+ dirnameptr = fullnameptr + dirnamelen;
+ strcpy(fullnameptr, incptr->incdirname);
+ if (*fullnameptr != 0 && *(dirnameptr - 1) != DIRCHAR)
+ strcat(fullnameptr, DIRSTRING);
+ strcat(fullnameptr, fnameptr);
+ if (dirnamend != NULL)
+ {
+ *dirnamend = DIRCHAR;
+ dirnamend = NULL;
+ }
+ }
+ fd = open(fullnameptr, 0);
+ if (fd >= 0)
+ {
+#ifdef TS
+ts_s_filename_tot -= charptr - fnameptr;
+#endif
+ charptr = fnameptr;
+ input.lineptr = lineptr;
+ inputbuf->fcb = input;
+ ++inclevel; /* XXX - will run out of memory before overflow */
+ inputinit(fullnameptr, fd);
+ inputbuf->fname_malloced = TRUE;
+ return;
+ }
+#ifdef TS
+ts_s_pathname_tot -= strlen(fullnameptr) + 1;
+#endif
+ ourfree(fullnameptr);
+ }
+ while ((incptr = incptr->incnext) != NULL);
+ error("cannot find include file");
+#ifdef TS
+ts_s_filename_tot -= charptr - fnameptr;
+#endif
+ charptr = fnameptr;
+}
+
+/* initialise current input file */
+
+PRIVATE void inputinit(fname, fd)
+char *fname;
+fd_t fd;
+{
+ register struct fbufstruct *newinputbuf;
+
+ /* don't allocate after saying input.includer = inputbuf (to save a reg)
+ * or an error in the alloc would cycle trying to print the include list
+ */
+ newinputbuf = (struct fbufstruct *) ourmalloc(sizeof *inputbuf);
+#ifdef TS
+++ts_n_inputbuf;
+ts_s_inputbuf += sizeof *inputbuf;
+ts_s_inputbuf_tot += sizeof *inputbuf;
+#endif
+ input.fd = fd;
+#ifdef FAKE_INBUFSIZE_1
+ input.fp = fdopen(fd, "r");
+#endif
+ input.linenumber = 0;
+ input.lineoffset = 0;
+ input.includer = inputbuf;
+ inputbuf = newinputbuf;
+ newinputbuf->fname = fname;
+ newinputbuf->fname_malloced = FALSE;
+ undefinestring(filemacro);
+ definefile(fname);
+ if (orig_cppmode && !suppress_line_numbers)
+ outcpplinenumber(1, fname, input.includer == NULL ? "" : " 1");
+ *(input.limit = newinputbuf->fbuf) = EOL;
+
+ /* dummy line so #include processing can start with skipline() */
+ ch = *(lineptr = newinputbuf->fbuf - 1) = EOL;
+}
+
+/* switch from include file to file which included it */
+
+PRIVATE void leaveinclude()
+{
+ --inclevel;
+ if (inputbuf->fname_malloced)
+{
+#ifdef TS
+ts_s_pathname_tot -= strlen(inputbuf->fname) + 1;
+#endif
+ ourfree(inputbuf->fname);
+}
+#ifdef TS
+ts_s_inputbuf_tot -= sizeof *inputbuf;
+#endif
+ ourfree((char *) inputbuf);
+ close(input.fd);
+#ifdef FAKE_INBUFSIZE_1
+ fclose(input.fp);
+#endif
+ inputbuf = input.includer;
+ input = inputbuf->fcb;
+ undefinestring(filemacro);
+ definefile(inputbuf->fname);
+ ch = *(lineptr = input.lineptr);
+ skipline();
+ if (orig_cppmode && !suppress_line_numbers)
+ outcpplinenumber(input.linenumber, inputbuf->fname, " 2");
+}
+
+/* open input and output files and get options */
+
+PUBLIC void openio(argc, argv)
+int argc;
+char *argv[];
+{
+ register char *arg;
+ int argn;
+ fd_t fd;
+ char *fname;
+ struct inclist *incnew;
+ struct inclist *incptr;
+ bool_t flag[128];
+
+#if 0
+ lineptr = "\n"; /* empty line in case error message */
+#endif
+ fd = 0; /* standard input */
+ memset(flag, 0, sizeof flag);
+ flag['3'] = sizeof (int) >= 4;
+ fname = "stdin";
+ (incptr = &incfirst)->incnext = &inclast;
+ initout();
+ for (argn = 1; argn < argc; ++argn)
+ {
+ arg = argv[argn];
+ if (*arg != '-')
+ {
+ if (fd != 0)
+ fatalerror("more than one input file");
+ fname = arg;
+ if ((fd = open(arg, 0)) < 0)
+ fatalerror("cannot open input");
+ }
+ else
+ switch (arg[1])
+ {
+#ifdef I8088
+ case '0': /* generate 16-bit code */
+ case '3': /* generate 32-bit code */
+#endif
+ case 'c': /* caller saves */
+#ifdef DEBUG
+ case 'd': /* print debugging information in asm output */
+#endif
+ case 'E': /* acting as cpp */
+ case 'f': /* pass first argument in register */
+#ifdef DYNAMIC_LONG_ORDER
+ case 'l': /* long big-endian */
+#endif
+ case 'P': /* if acting as cpp, suppress line numbers */
+#ifdef POSINDEPENDENT
+ case 'p': /* generate almost-position-independent code */
+#endif
+ case 't': /* print source code in asm output */
+ case 'w': /* watch location counter */
+ if (arg[2] == 0)
+ flag[arg[1]] = TRUE;
+ else if (arg[2] == '-' && arg[3] == 0)
+ flag[arg[1]] = FALSE;
+ else
+ usage();
+ if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
+ flag['3'] = TRUE + FALSE - flag['0'];
+ break;
+ case 'D':
+ definestring(arg + 2);
+ break;
+ case 'I':
+ (incnew = (struct inclist *) ourmalloc(sizeof *incnew))
+ ->incdirname = arg + 2;
+#ifdef TS
+++ts_n_includelist;
+ts_s_includelist += sizeof *incnew;
+#endif
+ incnew->incnext = incptr->incnext;
+ incptr = incptr->incnext = incnew;
+ break;
+ case 'U':
+ undefinestring(arg + 2);
+ break;
+ case 'o':
+ if (arg[2] != 0 || ++argn >= argc)
+ usage();
+ openout(argv[argn]);
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+#ifdef I8088
+ if (flag['3'])
+ {
+ i386_32 = TRUE;
+ definestring("__AS386_32__");
+ }
+ else
+ definestring("__AS386_16__");
+#endif
+#ifdef MC6809
+ definestring("__AS09__");
+#endif
+ if (flag['c'])
+ {
+ callersaves = TRUE;
+ definestring("__CALLER_SAVES__");
+ }
+#ifdef DEBUG
+ debugon = flag['d'];
+#endif
+ orig_cppmode = cppmode = flag['E'];
+ if (flag['f'])
+ {
+ arg1inreg = TRUE;
+#ifdef I8088
+ definestring("__FIRST_ARG_IN_AX__");
+#endif
+#ifdef MC6808
+ definestring("__FIRST_ARG_IN_X__");
+#endif
+ }
+ arg1op = arg1inreg ? ROOTLISTOP : LISTOP;
+#ifdef DYNAMIC_LONG_ORDER
+ if (flag['l'])
+ {
+ long_big_endian = TRUE;
+ definestring("__LONG_BIG_ENDIAN__");
+ }
+#endif
+ suppress_line_numbers = flag['P'];
+#ifdef POSINDEPENDENT
+ if (flag['p'])
+ {
+ posindependent = TRUE;
+ definestring("__POS_INDEPENDENT__");
+ }
+#endif
+ ctext = flag['t'];
+ watchlc = flag['w'];
+ setoutbufs();
+ inputinit(fname, fd);
+}
+
+/* advance over EOL sentinel to new line */
+
+PUBLIC void skipeol()
+{
+#ifdef FAKE_INBUFSIZE_1
+ static int ich;
+#endif
+#ifdef INSERT_BACKSLASH_NEWLINES
+ static int bs_state;
+ static bool_t skip_printing_nl;
+#endif
+ int nread;
+
+ if (eof)
+ return;
+ if (lineptr < input.limit)
+ {
+ ++input.linenumber;
+ ch = *++lineptr;
+ if (ctext && !asmmode)
+ {
+ comment();
+ outudec(input.linenumber);
+ outbyte(' ');
+ outline(lineptr);
+ }
+ if (orig_cppmode && !asmmode)
+#ifdef INSERT_BACKSLASH_NEWLINES
+ if (!skip_printing_nl)
+#endif
+
+ outbyte('\n');
+#ifdef INSERT_BACKSLASH_NEWLINES
+ if (bs_state == 1 && *(lineptr - 1) == EOL)
+#endif
+ input.lineoffset = (int) (lineptr - inputbuf->fbuf);
+ return;
+ }
+ input.lineoffset -= (int) (lineptr - inputbuf->fbuf);
+#ifdef FAKE_INBUFSIZE_1
+ lineptr = inputbuf->fbuf;
+#ifdef INSERT_BACKSLASH_NEWLINES
+ switch (bs_state)
+ {
+case0:
+ case 0:
+ bs_state = nread = (ich = getc(input.fp)) == EOF ? 0 : 1;
+ skip_printing_nl = FALSE;
+ break;
+ case 1:
+ if (ich == '\\')
+ goto case0; /* avoid chance of splitting \EOL */
+ ich = '\\';
+ nread = 1;
+ bs_state = 2;
+ ++input.lineoffset;
+ break;
+ case 2:
+ ich = EOL;
+ nread = 1;
+ bs_state = 0;
+ skip_printing_nl = TRUE;
+ ++input.lineoffset;
+ --input.linenumber;
+ break;
+ }
+#else
+ nread = (ich = getc(input.fp)) == EOF ? 0 : 1;
+#endif
+ *lineptr = ich;
+#else
+ nread = read(input.fd, lineptr = inputbuf->fbuf, INBUFSIZE);
+#endif
+ if (nread < 0)
+ fatalerror("input error");
+ *(input.limit = lineptr + nread) = EOL;
+ ch = *lineptr;
+ if (nread == 0)
+ {
+ if (inclevel == 0)
+ {
+ eof = TRUE;
+ checknotinif();
+ }
+ else
+ {
+ leaveinclude();
+ skipeol();
+ }
+ return;
+ }
+ if (ctext && !asmmode)
+ {
+ comment();
+ outudec(input.linenumber);
+ outbyte(' ');
+ outline(lineptr);
+ }
+}
+
+PUBLIC void specialchar()
+{
+ if (maclevel != 0)
+ {
+ if (ch == EOL) /* it might also be backslash or COEOL */
+ leavemac();
+ if (ch != EOL)
+ return;
+ }
+more:
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+ if (ch == '\\')
+ backslash();
+#endif
+ if (!eof && lineptr >= input.limit)
+ {
+ skipeol();
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+ if (ch == '\\')
+ backslash();
+#endif
+ }
+#ifndef ARBITRARY_BACKSLASH_NEWLINES
+ if (ch == '\\')
+ {
+ if (*(lineptr + 1) == EOL)
+ {
+ if (lineptr + 1 >= input.limit)
+ {
+ ++lineptr;
+ skipeol();
+ ch = *--lineptr = '\\'; /* pushback */
+ }
+ if (*(lineptr + 1) == EOL)
+ {
+ if (eof)
+ eofin("backslash-newline");
+ else
+ {
+ ++lineptr;
+ skipeol();
+ if (SYMOFCHAR(ch) == SPECIALCHAR)
+ {
+#ifdef COEOL
+ if (ch != COEOL
+ || SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR)
+#endif
+ goto more;
+ }
+ }
+ }
+ }
+#endif
+ }
+#ifdef COEOL
+ if (ch == EOL && !eof)
+ {
+ if (*(lineptr + 1) == EOL && lineptr + 1 >= input.limit)
+ {
+ ++lineptr;
+ skipeol(); /* refill buffer */
+ ch = *--lineptr = EOL; /* pushback */
+ }
+ if (*(lineptr + 1) == COEOL)
+ *++lineptr = EOL; /* discard COEOL */
+ }
+#endif
+}
+
+PRIVATE void usage()
+{
+ fatalerror(
+#ifdef MC6809
+"usage: cc1 [-cdfptw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]");
+#else
+"usage: cc1 [-03cdfltw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]");
+#endif
+}
diff --git a/bcc-bruce/input.h b/bcc-bruce/input.h
new file mode 100644
index 0000000..0563059
--- /dev/null
+++ b/bcc-bruce/input.h
@@ -0,0 +1,37 @@
+/* input.h - input for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define FAKE_INBUFSIZE_1_NOT
+
+#ifdef FAKE_INBUFSIZE_1
+#include <stdio.h>
+FILE *fdopen();
+#endif
+
+struct fcbstruct /* file control block structure */
+{
+ fd_t fd; /* file descriptor */
+#ifdef FAKE_INBUFSIZE_1
+ FILE *fp;
+#endif
+ unsigned linenumber; /* current line in file */
+ int lineoffset; /* offset to start of current line in buf */
+ char *lineptr; /* current spot in line */
+ char *limit; /* end of used part of input buffer */
+ struct fbufstruct *includer;
+ /* buffer of file which included current one */
+};
+
+EXTERN bool_t asmmode; /* nonzero when processing assembler code */
+ /* depends on zero init */
+EXTERN char ch; /* current char */
+EXTERN bool_t cppmode; /* nonzero if acting as cpp not as compiler */
+EXTERN bool_t eof; /* nonzero after end of main file reached */
+ /* depends on zero init */
+EXTERN struct fcbstruct input; /* current input file control block */
+ /* input.lineptr is not kept up to date */
+EXTERN char *lineptr; /* ptr to current char */
+EXTERN maclev_t maclevel; /* nest level of #defined identifiers */
+ /* depends on zero init */
+EXTERN bool_t orig_cppmode; /* same as cppmode ex. not varied while in # */
diff --git a/bcc-bruce/label.c b/bcc-bruce/label.c
new file mode 100644
index 0000000..8489230
--- /dev/null
+++ b/bcc-bruce/label.c
@@ -0,0 +1,429 @@
+/* label.c - label handling routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "label.h"
+#include "output.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#ifdef I8088
+# define outlbranch() outop3str( "b")
+# define outsbranch() outop2str( "j")
+#endif
+#ifdef MC6809
+# define outlbranch() outop3str( "LB")
+# define outsbranch() outop2str( "B")
+#endif
+
+#define MAXVISLAB 32
+
+struct labdatstruct
+{
+ label_t labnum; /* 0 if not active */
+ offset_t lablc; /* location counter for branch or label */
+ char *labpatch; /* buffer ptr for branch, NULL for label */
+ ccode_t labcond; /* condition code for branch */
+};
+
+#ifdef I8088
+PRIVATE char lcondnames[][2] = /* names of long condition codes */
+{
+ { 'e', 'q', }, { 'n', 'e', }, { 'r', ' ', }, { 'r', 'n', },
+ { 'l', 't', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', 't', },
+ { 'l', 'o', }, { 'h', 'i', }, { 'l', 'o', }, { 'h', 'i' },
+};
+PRIVATE char scondnames[][2] = /* names of short condition codes */
+{
+ { 'e', ' ', }, { 'n', 'e', }, { 'm', 'p', }, { 'n', 0, },
+ { 'l', ' ', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', ' ', },
+ { 'b', ' ', }, { 'a', 'e', }, { 'b', 'e', }, { 'a', ' ', },
+};
+#endif
+
+#ifdef MC6809
+PRIVATE char condnames[][2] = /* names of condition codes */
+{
+ { 'E', 'Q', }, { 'N', 'E', }, { 'R', 'A', }, { 'R', 'N', },
+ { 'L', 'T', }, { 'G', 'E', }, { 'L', 'E', }, { 'G', 'T', },
+ { 'L', 'O', }, { 'H', 'S', }, { 'L', 'S', }, { 'H', 'I', },
+};
+#endif
+
+PRIVATE label_t lasthighlab = 0xFFFF+1; /* temp & temp init so labels fixed */
+ /* lint */
+PRIVATE label_t lastlab; /* bss init to 0 */
+PRIVATE offset_t lc; /* bss init to 0 */
+
+PRIVATE struct labdatstruct vislab[MAXVISLAB]; /* bss, all labnum's init 0 */
+PRIVATE smalin_t nextvislab; /* bss init to NULL */
+PRIVATE struct symstruct *namedfirst; /* bss init to NULL */
+PRIVATE struct symstruct *namedlast; /* bss init to NULL */
+
+FORWARD void addlabel P((ccode_pt cond, label_t label, char *patch));
+FORWARD struct labdatstruct *findlabel P((label_t label));
+
+/* add label to circular list */
+
+PRIVATE void addlabel(cond, label, patch)
+ccode_pt cond;
+label_t label;
+char *patch;
+{
+ register struct labdatstruct *labptr;
+
+ labptr = &vislab[nextvislab];
+ labptr->labcond = cond;
+ labptr->labnum = label;
+ labptr->lablc = lc;
+ labptr->labpatch = patch;
+ if (++nextvislab == MAXVISLAB)
+ nextvislab = 0;
+}
+
+/* bump location counter */
+
+PUBLIC void bumplc()
+{
+ ++lc;
+}
+
+/* bump location counter by 2 */
+
+PUBLIC void bumplc2()
+{
+ lc += 2;
+}
+
+/* bump location counter by 3 */
+
+PUBLIC void bumplc3()
+{
+ lc += 3;
+}
+
+/* clear out labels in function */
+
+PUBLIC void clearfunclabels()
+{
+ register struct symstruct *symptr;
+ register struct symstruct *tmp;
+
+ for (symptr = namedfirst; symptr != NULL;)
+ {
+ if (symptr->indcount == 2)
+ error("undefined label");
+ symptr->indcount = 0;
+ tmp = symptr;
+ symptr = (struct symstruct *) symptr->type;
+ tmp->type = NULL;
+ }
+ namedlast = namedfirst = NULL;
+}
+
+/* clear out labels no longer in buffer */
+
+PUBLIC void clearlabels(patchbuf, patchtop)
+char *patchbuf;
+char *patchtop;
+{
+ register struct labdatstruct *labptr;
+ struct labdatstruct *labtop;
+ register char *labpatch;
+
+ for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
+ labptr < labtop; ++labptr)
+ if ((labpatch = labptr->labpatch) >= patchbuf && labpatch < patchtop)
+ labptr->labnum = 0;
+}
+
+/* clear out labels in switch statement */
+
+PUBLIC void clearswitchlabels()
+{
+ register struct symstruct *symptr;
+
+ for (symptr = namedfirst; symptr != NULL;
+ symptr = (struct symstruct *) symptr->type)
+ if (symptr->indcount == 3)
+ {
+ equlab(symptr->offset.offlabel, lowsp);
+ symptr->indcount = 4;
+ }
+}
+
+/* return location counter */
+
+PUBLIC uoffset_t getlc()
+{
+ return (uoffset_t) lc;
+}
+
+/* define location of label and backpatch references to it */
+
+PUBLIC void deflabel(label)
+label_t label;
+{
+ char *cnameptr;
+ struct labdatstruct *labmin;
+ struct labdatstruct *labmax;
+ struct labdatstruct *labmid;
+ struct labdatstruct *labptrsave;
+ offset_t nlonger;
+
+ outnlabel(label);
+ {
+ register struct labdatstruct *labptr;
+ register char *labpatch;
+
+ labmin = &vislab[0];
+ labmax = &vislab[MAXVISLAB];
+ labptr = labmid = &vislab[nextvislab];
+ if (!watchlc)
+ do
+ {
+ if (labptr == labmin)
+ labptr = &vislab[MAXVISLAB];
+ --labptr;
+ if (labptr->labnum == label)
+ {
+ if ((labpatch = labptr->labpatch) != NULL &&
+ isshortbranch(lc - labptr->lablc))
+ {
+#ifdef I8088 /* patch "bcc(c) to j(c)(c)( ) */
+ *labpatch = 'j';
+ *(labpatch + 1) =
+ *(cnameptr = scondnames[labptr->labcond]);
+#endif
+#ifdef MC6809
+# ifdef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
+ *labpatch = 'B';
+ *(labpatch + 4) = '\t'; /* redundant unless JMP */
+ *(labpatch + 1) =
+ *(cnameptr = condnames[labptr->labcond]);
+# else
+ if (labptr->labcond == RA)
+ strncpy(labpatch, "BRA\t\t", 5);
+ else
+ *labpatch = '\t';
+ goto over;
+# endif
+#endif
+ *(labpatch + 2) = *(cnameptr + 1);
+ *(labpatch + 3) = ' ';
+#ifdef MC6809
+# ifndef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
+ over: ; /* temp regression test kludge */
+# endif
+#endif
+ nlonger = jcclonger;
+ if (labptr->labcond == RA)
+ nlonger = jmplonger;
+ lc -= nlonger;
+ labptrsave = labptr;
+ while (++labptr != labmid)
+ if (labptr == labmax)
+ labptr = &vislab[-1];
+ else
+ labptr->lablc -= nlonger;
+ labptr = labptrsave;
+ }
+ }
+ }
+ while (labptr != labmid);
+ }
+ addlabel((ccode_pt) 0, label, (char *) NULL);
+}
+
+PRIVATE struct labdatstruct *findlabel(label)
+label_t label;
+{
+ register struct labdatstruct *labptr;
+ struct labdatstruct *labtop;
+
+ for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
+ labptr < labtop; ++labptr)
+ if (labptr->labnum == label)
+ {
+ if (labptr->labpatch != 0)
+ break;
+ return labptr;
+ }
+ return (struct labdatstruct *) NULL;
+}
+
+/* reserve a new label, from top down to temp avoid renumbering low labels */
+
+PUBLIC label_t gethighlabel()
+{
+ return --lasthighlab;
+}
+
+/* reserve a new label */
+
+PUBLIC label_t getlabel()
+{
+ return ++lastlab;
+}
+
+/* jump to label */
+
+PUBLIC void jump(label)
+label_t label;
+{
+ lbranch(RA, label);
+}
+
+/* long branch on condition to label */
+
+PUBLIC void lbranch(cond, label)
+ccode_pt cond;
+label_t label;
+{
+#ifdef I8088
+ char *cnameptr;
+
+#endif
+ struct labdatstruct *labptr;
+ char *oldoutptr;
+
+ if ((ccode_t) cond == RN)
+ return;
+ if ((labptr = findlabel(label)) != NULL &&
+ isshortbranch(lc - labptr->lablc + 2))
+ {
+ sbranch(cond, label);
+ return;
+ }
+ oldoutptr = outbufptr;
+ if (cond == RA)
+ outjumpstring();
+ else
+ {
+ outlbranch();
+#ifdef I8088
+ outbyte(*(cnameptr = lcondnames[(ccode_t) cond]));
+ outbyte(*(cnameptr + 1));
+ if ((ccode_t) cond == LS || (ccode_t) cond == HS)
+ outbyte('s'); /* "blos" or "bhis" */
+ else
+ outbyte(' ');
+ outtab();
+ bumplc2();
+ if (i386_32)
+ bumplc();
+#endif
+#ifdef MC6809
+ outcond(cond);
+ bumplc();
+#endif
+ }
+ outlabel(label);
+ outnl();
+ if (labptr == NULL && oldoutptr < outbufptr) /* no wrap-around */
+ addlabel(cond, label, oldoutptr);
+}
+
+/* look up the name gsname in label space, install it if new */
+
+PUBLIC struct symstruct *namedlabel()
+{
+ struct symstruct *symptr;
+
+ gs2name[1] = 0xFF;
+ if ((symptr = findlorg(gs2name + 1)) == NULL)
+ {
+ symptr = addglb(gs2name + 1, vtype);
+ symptr->flags = LABELLED;
+ }
+ if (symptr->indcount < 2)
+ {
+ symptr->indcount = 2;
+ symptr->offset.offlabel = gethighlabel();
+ if (namedfirst == NULL)
+ namedfirst = symptr;
+ else
+ namedlast->type = (struct typestruct *) symptr;
+ namedlast = symptr;
+ symptr->type = NULL;
+ }
+ return symptr;
+}
+
+#ifdef MC6809
+
+/* print condition code name */
+
+PUBLIC void outcond(cond)
+ccode_pt cond;
+{
+ char *cnameptr;
+
+ outbyte(*(cnameptr = condnames[(ccode_t) cond]));
+ outbyte(*(cnameptr + 1));
+ outtab();
+}
+
+#endif
+
+/* print label */
+
+PUBLIC void outlabel(label)
+label_t label;
+{
+ outbyte(LABELSTARTCHAR);
+ outhexdigs((uoffset_t) label);
+}
+
+/* print label and newline */
+
+PUBLIC void outnlabel(label)
+label_t label;
+{
+ outlabel(label);
+#ifdef LABELENDCHAR
+ outnbyte(LABELENDCHAR);
+#else
+ outnl();
+#endif
+}
+
+/* short branch on condition to label */
+
+PUBLIC void sbranch(cond, label)
+ccode_pt cond;
+label_t label;
+{
+#ifdef I8088
+ char *cnameptr;
+
+ if ((ccode_t) cond != RN)
+ {
+ outsbranch();
+ outbyte(*(cnameptr = scondnames[(ccode_t) cond]));
+ outbyte(*(cnameptr + 1));
+ outtab();
+ outlabel(label);
+ outnl();
+ }
+#endif
+#ifdef MC6809
+ outsbranch();
+ outcond(cond);
+ outlabel(label);
+ outnl();
+#endif
+}
+
+/* reverse bump location counter */
+
+PUBLIC void unbumplc()
+{
+ --lc;
+}
diff --git a/bcc-bruce/label.h b/bcc-bruce/label.h
new file mode 100644
index 0000000..89c83d7
--- /dev/null
+++ b/bcc-bruce/label.h
@@ -0,0 +1,24 @@
+/* label.h - assembler-specific label characters for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* defaults */
+
+#define CCNAMEPREFIX '_'
+# define LABELENDCHAR ':' /* last char of ALL labels */
+#define LABELSTARTCHAR '.' /* first char of names of generated labels */
+#define LOCALSTARTCHAR '.' /* first char of local names */
+#define PUBLICENDCHAR ':'
+
+/* adjustments for other assemblers */
+
+#ifdef AS09
+# undef LABELENDCHAR
+#endif
+
+#ifdef XENIX_AS
+# undef LABELSTARTCHAR
+# define LABELSTARTCHAR 'L'
+# undef LOCALSTARTCHAR
+# define LOCALSTARTCHAR 'L'
+#endif
diff --git a/bcc-bruce/loadexp.c b/bcc-bruce/loadexp.c
new file mode 100644
index 0000000..781dca0
--- /dev/null
+++ b/bcc-bruce/loadexp.c
@@ -0,0 +1,180 @@
+/* loadexp.c - load expressions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+PUBLIC value_t constexpression()
+{
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+ struct symstruct *symptr;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ exp = assignment_exp();
+ etptr = etmark;
+ exprptr = exprmark;
+ if (exp->tag == LEAF && (symptr = exp->left.symptr)->storage == CONSTANT
+ && symptr->type->scalar & ISCALAR)
+ return symptr->offset.offv;
+ error("constant expression required");
+ return 1;
+}
+
+PUBLIC void initexpression(type)
+struct typestruct *type;
+{
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+ struct nodestruct *lhs;
+ struct symstruct *symptr;
+ uoffset_t value;
+
+ if (gvarsymptr->storage != GLOBAL)
+ reslocals();
+ exprmark = exprptr;
+ etmark = etptr;
+ exp = assignment_exp();
+ if (gvarsymptr->storage != GLOBAL)
+ {
+ lhs = leafnode(exprsym(gvarsymptr));
+ if (!(lhs->nodetype->constructor & (ARRAY | FUNCTION | VOID)))
+ lhs->flags = LVALUE;
+ makeleaf(node(ASSIGNOP, lhs, exp));
+ }
+ else if (exp->tag != LEAF ||
+ (symptr = exp->left.symptr)->storage != CONSTANT &&
+ (symptr->storage != GLOBAL || symptr->indcount != 0 ||
+ type->scalar & DLONG) ||
+ (type->constructor | (symptr->type->constructor & ~FUNCTION)) &
+ ~(ARRAY | POINTER))
+ error("initializer too complicated");
+ else
+ {
+ if ((symptr->type->scalar | type->scalar) & RSCALAR)
+ {
+ /* Can only afford castnode if result known constant. */
+ exp = castnode(type, exp);
+ symptr = exp->left.symptr;
+ }
+ if (type->scalar & RSCALAR)
+ {
+ if (type->scalar & FLOAT)
+ {
+ float val;
+
+ val = *symptr->offset.offd;
+ deflong(((uoffset_t *) &val)[0]);
+ }
+ else
+ {
+ deflong(((uoffset_t *) symptr->offset.offd)[0]);
+ deflong(((uoffset_t *) symptr->offset.offd)[1]);
+ }
+ etptr = etmark; /* XXX - stuff from end of function */
+ exprptr = exprmark;
+ return;
+ }
+ if (type->typesize == 1)
+ defbyte();
+ else if (type->typesize == 2)
+ defword();
+#ifdef I8088
+ else if (!(type->scalar & DLONG))
+ defdword();
+#endif
+ switch (symptr->storage)
+ {
+ case CONSTANT:
+ value = (uoffset_t) symptr->offset.offv;
+ if (type->scalar & DLONG)
+ {
+ deflong(value);
+ break;
+ }
+ /* XXX - put sizes in type struct to avoid tests */
+ if (type->scalar & CHAR)
+ value &= CHMASKTO;
+ else if (type->scalar & SHORT)
+ value &= shortmaskto;
+ else if (type->scalar & INT)
+ value &= intmaskto;
+ /* XXX - no longmaskto */
+ outnhex(value);
+ break;
+ case GLOBAL:
+ if (symptr->flags & LABELLED)
+ {
+ outlabel(symptr->name.label);
+ outplus();
+ outnhex((uoffset_t) symptr->offset.offi);
+ break;
+ }
+ if (*symptr->name.namep == 0) /* constant address */
+ {
+ outnhex((uoffset_t) symptr->offset.offi);
+ break;
+ }
+ outccname(symptr->name.namep);
+ if (symptr->offset.offi != 0)
+ {
+ if (symptr->offset.offi > 0)
+ outplus();
+ outshex(symptr->offset.offi);
+ }
+ outnl();
+ break;
+ }
+ }
+ etptr = etmark;
+ exprptr = exprmark;
+}
+
+PUBLIC struct typestruct *loadexpression(targreg, targtype)
+store_pt targreg;
+struct typestruct *targtype;
+{
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ exp = expression();
+ if (targtype != NULL)
+ exp = castnode(targtype, exp);
+ makeleaf(exp);
+ if (targtype == NULL) /* this is for a switch */
+ {
+ targtype = exp->left.symptr->type;
+ if (!(targtype->scalar & (CHAR | INT))
+ && (targtype->scalar & (LONG | DLONG)) != LONG)
+ {
+ if (targtype->scalar & SHORT)
+ targtype = promote(targtype);
+ else
+ {
+ error("non-integral selector in switch");
+ targtype = itype;
+ }
+ makeleaf(exp = castnode(targtype, exp));
+ }
+ }
+ load(exp->left.symptr, targreg); /* resets stack if value was there */
+ etptr = etmark;
+ exprptr = exprmark;
+ return exp->left.symptr->type;
+}
diff --git a/bcc-bruce/longop.c b/bcc-bruce/longop.c
new file mode 100644
index 0000000..8396392
--- /dev/null
+++ b/bcc-bruce/longop.c
@@ -0,0 +1,169 @@
+/* longop.c - software operations on longs for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "reg.h"
+#include "scan.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ longop(operation code, source leaf, target leaf)
+ handles all binary operations on longs
+ source and target must already have been converted to long,
+ (except source is int for shifts) and not more than singly indirect
+ hence they must be direct (in an index reg paired with DREG),
+ or singly indirect (local, global, or from an index reg)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void longop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt reglist;
+ store_t regmark;
+ bool_t shiftflag;
+ scalar_t scalar;
+ offset_t spmark;
+
+ pushlist(reglist = (regmark = reguse) & (OPREG | OPWORKREG));
+ reguse &= ~reglist;
+ spmark = sp;
+ shiftflag = FALSE;
+ scalar = target->type->scalar;
+ if ((op_t) op == SLOP || (op_t) op == SROP)
+ shiftflag = TRUE;
+ else
+ scalar |= source->type->scalar;
+ if (source->indcount == 0 && !shiftflag ||
+ source->storage & (DREG | OPREG | OPWORKREG))
+ {
+ pres2(source, target);
+ push(source);
+ }
+ if (!shiftflag)
+ address(source);
+ load(target, OPREG);
+ if (source->storage == CONSTANT && shiftflag)
+ {
+ if (scalar & UNSIGNED)
+ target->type = ultype;
+ if ((op_t) op == SLOP)
+ source->offset.offv = lslconst(source->offset.offv,
+ target->storage);
+ else
+ source->offset.offv = lsrconst(source->offset.offv,
+ target->storage, scalar & UNSIGNED);
+ if (source->offset.offv == 0)
+ goto shiftdone;
+ }
+ load(source, OPWORKREG);
+ switch ((op_t) op)
+ {
+ case ADDOP:
+ call("ladd");
+ break;
+ case ANDOP:
+ call("land");
+ break;
+ case DIVOP:
+ call("ldiv");
+ break;
+ case EOROP:
+ call("leor");
+ break;
+ case EQOP:
+ call("lcmp");
+ break;
+ case MODOP:
+ call("lmod");
+ break;
+ case MULOP:
+ call("lmul");
+ break;
+ case OROP:
+ call("lor");
+ break;
+ case SLOP:
+ call("lsl");
+ break;
+ case SROP:
+ call("lsr");
+ break;
+ case SUBOP:
+ call("lsub");
+ break;
+ }
+ if (scalar & UNSIGNED)
+ {
+ outbyte('u');
+ target->type = ultype;
+ }
+ outlongendian();
+
+shiftdone:
+ if ((reguse = regmark) & OPREG && op != EQOP)
+ load(target, getindexreg());
+ if (reglist)
+ {
+#ifdef I8088
+ if (op == EQOP)
+ changesp(spmark, FALSE);
+ else
+#endif
+ modstk(spmark);
+ poplist(reglist);
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ long1op(operation code, target leaf)
+ handles all unary operations on longs except inc/dec
+ target must be not more than singly indirect
+ hence it must be direct (in an index reg paired with DREG),
+ or singly indirect (local, global, or from an index reg)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void long1op(op, target)
+op_pt op;
+struct symstruct *target;
+{
+ pushlist(reguse & OPREG);
+ load(target, OPREG);
+ if (op == NOTOP)
+ call("lcom");
+ else if (op == NEGOP)
+ call("lneg");
+ else
+ call("ltst");
+ outlongendian();
+ if (reguse & OPREG)
+ {
+ if (op != EQOP)
+ load(target, getindexreg());
+ poplist(reguse & OPREG);
+ }
+}
+
+PUBLIC void outlongendian()
+{
+#ifdef MC6809
+ outbyte('_');
+#endif
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ outnbyte('b');
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ outnbyte('l');
+#endif
+}
diff --git a/bcc-bruce/misc/sformat b/bcc-bruce/misc/sformat
new file mode 100644
index 0000000..3dcb0c4
--- /dev/null
+++ b/bcc-bruce/misc/sformat
@@ -0,0 +1,56 @@
+int x;
+.comm _x,2
+
+int x = 1;
+.global _x
+.data
+_x:
+1
+
+static int x;
+.bss
+_x:
+.=.+2
+
+static int x = 1;
+.bss | implicit
+.data
+_x:
+1
+
+char x[10];
+.comm _x,12
+
+char x[10] = "1";
+.globl _x
+.data
+_x:
+.byte 61,0
+.=.+10
+
+static char x[10];
+.bss;
+_cc:
+.=.+12
+
+static char x[10] = "1";
+.data
+_x:
+.byte 61,0
+.=.+10
+
+test()
+.globl _test
+.text
+_test:
+
+{
+static int x;
+.bss
+L3:
+.=.+2
+
+static int x = 1;
+.bss
+.data
+L5:1
diff --git a/bcc-bruce/misc/test/8queens.pas b/bcc-bruce/misc/test/8queens.pas
new file mode 100644
index 0000000..f4f1b47
--- /dev/null
+++ b/bcc-bruce/misc/test/8queens.pas
@@ -0,0 +1,33 @@
+program eightqueens;
+
+var i: integer;
+ a: array[ 1..8 ] of boolean;
+ b: array[ 2..16] of boolean;
+ c: array[-7..7 ] of boolean;
+ x: array[ 1..8 ] of integer;
+
+procedure print;
+var k: integer;
+begin
+ for k:= 1 to 8 do write(x[k]:4);
+ writeln;
+end;
+
+procedure try(i: integer);
+var j: integer;
+begin
+ for j:= 1 to 8 do if a[j] and b[i+j] and c[i-j] then
+ begin
+ x[i]:= j;
+ a[j]:= false; b[i+j]:= false; c[i-j]:= false;
+ if i < 8 then try(i+1) else print;
+ a[j]:= true; b[i+j]:= true; c[i-j]:= true;
+ end;
+end;
+
+begin
+ for i:= 1 to 8 do a[i]:= true;
+ for i:= 2 to 16 do b[i]:= true;
+ for i:= -7 to 7 do c[i]:= true;
+ try(1);
+end.
diff --git a/bcc-bruce/misc/test/8queens.t b/bcc-bruce/misc/test/8queens.t
new file mode 100644
index 0000000..8d20a4d
--- /dev/null
+++ b/bcc-bruce/misc/test/8queens.t
@@ -0,0 +1,74 @@
+/* 8queens - straightforward translation of pascal version */
+
+#define TRUE 1
+#define FALSE 0
+
+int i;
+char a[8],b[15],c[15],x[8];
+
+main()
+{
+ for (i=0;i<8;i++)
+ a[i]=TRUE;
+ for (i=0;i<15;i++)
+ b[i]=TRUE;
+ for (i=0;i<15;i++)
+ c[i]=TRUE;
+ try(0);
+}
+
+print()
+{
+ int k;
+
+ for (k=0;k<8;k++)
+ write(x[k]);
+ writeln();
+}
+
+write(i)
+int i;
+{
+ {
+#asm
+ LDA #$20
+ JSR $E820
+ LDD .i,S
+ JSR $C682
+#endasm
+ }
+}
+
+writeln()
+{
+ {
+#asm
+ LDA #13
+ JSR $E820
+ LDA #10
+ JSR $E820
+#endasm
+ }
+}
+
+try(i)
+int i;
+{
+ int j;
+
+ for(j=0;j<8;j++)
+ if (a[j] && b[i+j] && c[7+i-j])
+ {
+ x[i]=j;
+ a[j]=FALSE;
+ b[i+j]=FALSE;
+ c[7+i-j]=FALSE;
+ if (i<7)
+ try(i+1);
+ else
+ print();
+ a[j]=TRUE;
+ b[i+j]=TRUE;
+ c[7+i-j]=TRUE;
+ }
+}
diff --git a/bcc-bruce/misc/test/atol.t b/bcc-bruce/misc/test/atol.t
new file mode 100644
index 0000000..79c78b7
--- /dev/null
+++ b/bcc-bruce/misc/test/atol.t
@@ -0,0 +1,29 @@
+/* atol.c - long atol( char *s ) */
+
+/* atol converts s to a long */
+/* leading spaces and tabs are ignored, an optional sign is recognised, */
+/* and the digits (0 to 9) following determine the long */
+
+long atol( s )
+register char *s;
+{
+ char signflag;
+ long number;
+
+ while ( *s == ' ' || *s == '\t')
+ s++;
+ signflag = 0;
+ if ( *s == '+' )
+ s++;
+ else if ( *s == '-' )
+ {
+ signflag = 1;
+ s++;
+ }
+ number = 0;
+ while ( *s >= '0' && *s <= '9' )
+ number = 10 * number + *s++ - '0';
+ if ( signflag )
+ return -number;
+ return number;
+}
diff --git a/bcc-bruce/misc/test/bigsievec.t b/bcc-bruce/misc/test/bigsievec.t
new file mode 100644
index 0000000..f3f76b2
--- /dev/null
+++ b/bcc-bruce/misc/test/bigsievec.t
@@ -0,0 +1,29 @@
+#define TRUE 1
+#define FALSE 0
+#define NITER 10
+#define SIZE 100000
+
+char flags[SIZE+1];
+
+main()
+{
+ int i,prime,k,count,iter;
+
+ for (iter=0;iter<NITER;iter++)
+ {
+ count=0;
+ for (i=0;i<=SIZE;i++)
+ flags[i]=TRUE;
+ for (i=0;i<=SIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ for (k=i+prime;k<=SIZE;k=k+prime)
+ flags[k]=FALSE;
+ count++;
+ }
+ }
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc-bruce/misc/test/bt.t b/bcc-bruce/misc/test/bt.t
new file mode 100644
index 0000000..b88836c
--- /dev/null
+++ b/bcc-bruce/misc/test/bt.t
@@ -0,0 +1,373 @@
+/* bt.t - bug tests */
+
+test1()
+{
+ char *p, *q;
+
+ q += *p++;
+}
+
+test2()
+{
+ int i,j,k,a[2],b[2],c[2];
+
+ i = a[i] + b[j] + c[k];
+}
+
+test3()
+{
+ int *p, *q;
+ int i;
+
+ i = p - q;
+}
+
+test4()
+{
+ int a[2];
+ int *p;
+
+ p = a;
+ test4(a);
+}
+
+test5()
+{
+ char c;
+
+ test4(c);
+}
+
+test6(a,b)
+int b,a;
+{
+ int i;
+
+ i = b;
+ i = a;
+}
+
+test7()
+{
+ int a[2];
+ int *p;
+
+ p = a + 1;
+}
+
+int *test8();
+
+int *test8()
+{
+ int i;
+
+ if ( test8() == i )
+ ;
+ i = *test8();
+}
+
+test9()
+{
+ int i,j,k,n;
+
+ if ((i < 0 || j > 100) && (k < 0 || n > 50))
+ i = 1;
+}
+
+struct complex
+{
+ int re;
+ int im;
+}
+ znum, *zptr, zarr[10], *zptrarr[10];
+
+test10()
+{
+ int i;
+
+ znum.re = i;
+ znum.im = 1;
+ zptr -> re = 1;
+ zptr -> im = i;
+ zarr[3].im = i;
+ zptrarr[4] -> im = 1;
+}
+
+test11()
+{
+ char symtab[100];
+
+ char *p;
+
+ if (p > symtab)
+ ;
+}
+
+test12()
+{
+char symtab[100];
+
+ char *p;
+
+ p = symtab - 21;
+}
+
+test13()
+{
+ char a[10];
+ int i;
+
+ i = a - 1;
+}
+
+test14()
+{
+ int i, **pi;
+
+ **pi = i;
+}
+
+test15()
+{
+ int i, j;
+
+ if ( (i = j ) == 2 )
+ test();
+}
+
+test16()
+{
+ struct cx3
+ {
+ int re3;
+ char im3;
+ }
+ z[10], *pz, *pz1;
+ int i;
+
+ i = z[i].re3;
+ i = pz1 - pz;
+}
+
+test17()
+{
+ int i;
+ char c;
+
+ c &= ~i;
+}
+
+test18()
+{
+ typedef int (*PFI)();
+ PFI h();
+
+ (*h())( 0 );
+}
+
+test19()
+{
+ register int *p, *q;
+ int ***z,i,a[10];
+
+ test(***z + a[i]);
+}
+
+char a[2][3][5];
+
+char *p = a;
+char *q = a[1];
+char *r = a[1][2];
+
+char test20();
+char (*test21)();
+
+test22()
+{
+ char i,k;
+ char *p;
+
+ p = a;
+ p = a[1];
+ p = a[1][2];
+ p = a[k];
+ p = a[k][k];
+ i = sizeof a;
+ i = sizeof a[k];
+ i = sizeof a[k][k];
+ i = sizeof test20;
+ i = sizeof test21;
+ i = sizeof test20();
+ i = sizeof (*test21)();
+}
+
+test23()
+{
+ long *pl;
+ int i;
+ char *s;
+
+ *pl += i;
+ *s += *pl;
+}
+
+test24()
+{
+ float f;
+ double *dp1(), *dp2();
+
+ f = *dp1()++; /* illegal */
+ f = *++dp1(); /* illegal */
+ f = *dp1() + *dp2(); /* bad code (pushes ptr to doubly indirect) */
+}
+
+test25()
+{
+ test25( "2"[1] ); /* added 1 to label number, not label address */
+}
+
+struct stat
+{
+ int st_dev;
+};
+
+test26( buf )
+struct stat buf; /* wrong declare, s.b. struct stat *buf */
+{
+ buf->st_dev = 1; /* error caused null pointer to be dereferenced */
+}
+
+union
+{
+ long l;
+}
+ test27;
+
+test28()
+{
+ test27.l = test27.l + 1; /* produced poor code */
+}
+
+int test29 = (char) 1; /* cast was clobbering the global symptr */
+
+struct { int i; } test30;
+
+test31()
+{
+ return test30; /* a structure cannot be returned (yet) */
+}
+
+int *test32, test33() {} /* this is illegal */
+
+test35()
+{
+ char a[1];
+ char b[1];
+ int i;
+
+ i = i == 1 ? a : b; /* arrays were not converted to ptrs */
+}
+
+test36()
+{
+ struct fp
+ {
+ struct filp *fp_filp[1];
+ };
+ struct filp
+ {
+ int filp_int;
+ long filp_long;
+ };
+ int i;
+ register char *junk;
+ register struct fp *cp;
+
+ cp->fp_filp[i]->filp_int++; /* used to push lvalue */
+ cp->fp_filp[i]->filp_long++; /* used to push lvalue */
+ cp->fp_filp[i]->filp_int += 1; /* was OK */
+ cp->fp_filp[i]->filp_long += 1; /* used to load long into DREG:DREG */
+}
+
+test37()
+{
+ unsigned u;
+
+ u = -u; /* used to give botched nodetype */
+}
+
+test38()
+{
+ char c;
+ int i;
+
+ i = -c; /* did i = (char) -c for a time */
+}
+
+test39()
+{
+ int i;
+
+ i = (char) 1000; /* the constant wasn't being truncated */
+}
+
+#define test40(x) (x)
+
+test41()
+{
+ int i;
+ int j;
+ int k;
+
+ i = test40( j + /* was confused by EOL in macro argument */
+ k );
+}
+
+test42()
+{
+ register char *junk1;
+ register char *junk2;
+ long *longptr;
+ long longfn();
+
+ *longptr = longfn(); /* used to run out of index regs */
+}
+
+test43()
+{
+ register char *jnk1, *junk2;
+ unsigned char *bp;
+ struct FILE_BUF
+ {
+ char *bufp;
+ } *op;
+
+ *op->bufp++ = *bp; /* used to push lvalue */
+}
+
+test44()
+{
+ register char *x, *y;
+ int i;
+ char a[2];
+ char **p;
+
+ a[**p] = **p; /* used to push lvalue */
+}
+
+struct test45
+{
+ int i;
+ int j;
+} test45[10];
+
+test46()
+{
+ register char *p, *q;
+ int i;
+ int j;
+
+ test45[i] = test45[j]; /* used to push lvalue */
+}
+
+int (*test100( x )() {} /* this is legal, keep last avoid swallowing */
diff --git a/bcc-bruce/misc/test/cast.t b/bcc-bruce/misc/test/cast.t
new file mode 100644
index 0000000..554cb93
--- /dev/null
+++ b/bcc-bruce/misc/test/cast.t
@@ -0,0 +1,144 @@
+/* cast.t */
+
+char c;
+unsigned char uc;
+short s;
+unsigned short us;
+int i;
+unsigned int ui;
+long l;
+unsigned long ul;
+float f;
+double d;
+int *p;
+
+cast()
+{
+ c = (char) c;
+ uc = (unsigned char) c;
+ s = (short) c;
+ us = (unsigned short) c;
+ i = (int) c;
+ ui = (unsigned int) c;
+ l = (long) c;
+ ul = (unsigned long) c;
+ f = (float) c;
+ d = (double) c;
+ p = (int *) c;
+
+ c = (char) uc;
+ uc = (unsigned char) uc;
+ s = (short) uc;
+ us = (unsigned short) uc;
+ i = (int) uc;
+ ui = (unsigned int) uc;
+ l = (long) uc;
+ ul = (unsigned long) uc;
+ f = (float) uc;
+ d = (double) uc;
+ p = (int *) uc;
+
+ c = (char) s;
+ uc = (unsigned char) s;
+ s = (short) s;
+ us = (unsigned short) s;
+ i = (int) s;
+ ui = (unsigned int) s;
+ l = (long) s;
+ ul = (unsigned long) s;
+ f = (float) s;
+ d = (double) s;
+ p = (int *) s;
+
+ c = (char) us;
+ uc = (unsigned char) us;
+ s = (short) us;
+ us = (unsigned short) us;
+ i = (int) us;
+ ui = (unsigned int) us;
+ l = (long) us;
+ ul = (unsigned long) us;
+ f = (float) us;
+ d = (double) us;
+ p = (int *) us;
+
+ c = (char) i;
+ uc = (unsigned char) i;
+ s = (short) i;
+ us = (unsigned short) i;
+ i = (int) i;
+ ui = (unsigned int) i;
+ l = (long) i;
+ ul = (unsigned long) i;
+ f = (float) i;
+ d = (double) i;
+ p = (int *) i;
+
+ c = (char) ui;
+ uc = (unsigned char) ui;
+ s = (short) ui;
+ us = (unsigned short) ui;
+ i = (int) ui;
+ ui = (unsigned int) ui;
+ l = (long) ui;
+ ul = (unsigned long) ui;
+ f = (float) ui;
+ d = (double) ui;
+ p = (int *) ui;
+
+ c = (char) l;
+ uc = (unsigned char) l;
+ s = (short) l;
+ us = (unsigned short) l;
+ i = (int) l;
+ ui = (unsigned int) l;
+ l = (long) l;
+ ul = (unsigned long) l;
+ f = (float) l;
+ d = (double) l;
+ p = (int *) l;
+
+ c = (char) ul;
+ uc = (unsigned char) ul;
+ s = (short) ul;
+ us = (unsigned short) ul;
+ i = (int) ul;
+ ui = (unsigned int) ul;
+ l = (long) ul;
+ ul = (unsigned long) ul;
+ f = (float) ul;
+ d = (double) ul;
+ p = (int *) ul;
+
+ c = (char) f;
+ uc = (unsigned char) f;
+ s = (short) f;
+ us = (unsigned short) f;
+ i = (int) f;
+ ui = (unsigned int) f;
+ l = (long) f;
+ ul = (unsigned long) f;
+ f = (float) f;
+ d = (double) f;
+
+ c = (char) d;
+ uc = (unsigned char) d;
+ s = (short) d;
+ us = (unsigned short) d;
+ i = (int) d;
+ ui = (unsigned int) d;
+ l = (long) d;
+ ul = (unsigned long) d;
+ f = (float) d;
+ d = (double) d;
+
+ c = (char) p;
+ uc = (unsigned char) p;
+ s = (short) p;
+ us = (unsigned short) p;
+ i = (int) p;
+ ui = (unsigned int) p;
+ l = (long) p;
+ ul = (unsigned long) p;
+ p = (int *) p;
+}
diff --git a/bcc-bruce/misc/test/cast1.t b/bcc-bruce/misc/test/cast1.t
new file mode 100644
index 0000000..a4c15d5
--- /dev/null
+++ b/bcc-bruce/misc/test/cast1.t
@@ -0,0 +1,144 @@
+/* cast1.t */
+
+char c;
+unsigned char uc;
+short s;
+unsigned short us;
+int i;
+unsigned int ui;
+long l;
+unsigned long ul;
+float f;
+double d;
+int *p;
+
+cast()
+{
+ c = c;
+ uc = c;
+ s = c;
+ us = c;
+ i = c;
+ ui = c;
+ l = c;
+ ul = c;
+ f = c;
+ d = c;
+ p = c;
+
+ c = uc;
+ uc = uc;
+ s = uc;
+ us = uc;
+ i = uc;
+ ui = uc;
+ l = uc;
+ ul = uc;
+ f = uc;
+ d = uc;
+ p = uc;
+
+ c = s;
+ uc = s;
+ s = s;
+ us = s;
+ i = s;
+ ui = s;
+ l = s;
+ ul = s;
+ f = s;
+ d = s;
+ p = s;
+
+ c = us;
+ uc = us;
+ s = us;
+ us = us;
+ i = us;
+ ui = us;
+ l = us;
+ ul = us;
+ f = us;
+ d = us;
+ p = us;
+
+ c = i;
+ uc = i;
+ s = i;
+ us = i;
+ i = i;
+ ui = i;
+ l = i;
+ ul = i;
+ f = i;
+ d = i;
+ p = i;
+
+ c = ui;
+ uc = ui;
+ s = ui;
+ us = ui;
+ i = ui;
+ ui = ui;
+ l = ui;
+ ul = ui;
+ f = ui;
+ d = ui;
+ p = ui;
+
+ c = l;
+ uc = l;
+ s = l;
+ us = l;
+ i = l;
+ ui = l;
+ l = l;
+ ul = l;
+ f = l;
+ d = l;
+ p = l;
+
+ c = ul;
+ uc = ul;
+ s = ul;
+ us = ul;
+ i = ul;
+ ui = ul;
+ l = ul;
+ ul = ul;
+ f = ul;
+ d = ul;
+ p = ul;
+
+ c = f;
+ uc = f;
+ s = f;
+ us = f;
+ i = f;
+ ui = f;
+ l = f;
+ ul = f;
+ f = f;
+ d = f;
+
+ c = d;
+ uc = d;
+ s = d;
+ us = d;
+ i = d;
+ ui = d;
+ l = d;
+ ul = d;
+ f = d;
+ d = d;
+
+ c = p;
+ uc = p;
+ s = p;
+ us = p;
+ i = p;
+ ui = p;
+ l = p;
+ ul = p;
+ p = p;
+}
diff --git a/bcc-bruce/misc/test/castest.t b/bcc-bruce/misc/test/castest.t
new file mode 100644
index 0000000..ae27f7b
--- /dev/null
+++ b/bcc-bruce/misc/test/castest.t
@@ -0,0 +1,74 @@
+/* castest.c */
+
+/*
+#define signedchar
+#define bigints
+*/
+#define unsigchar
+#define unsigshort
+#define unsiglong
+
+#define TEST(u,c) if ( (u) != (c) )\
+ { printf( "u != c\n" ); ++bad; } ++possible
+
+main()
+{
+ int bad;
+ int possible;
+ char c;
+#ifdef signedchar
+ signed char sc;
+#endif
+#ifdef unsigchar
+ unsigned char uc;
+#endif
+ short s;
+#ifdef unsigshort
+ unsigned short us;
+#endif
+ int i;
+ unsigned u;
+ long l;
+#ifdef unsiglong
+ unsigned long ul;
+#endif
+
+ bad = possible = 0;
+ u = 0x1ff;
+ c = (char) u;
+ if ( c < 0 )
+ printf( "characters are signed\n" );
+ TEST((char)u,c);
+ i = (int)(char) u;
+ TEST(i,(int)c);
+ TEST((int)(char)u,i);
+
+#ifdef signedchar
+ sc = (signed char) u;
+ if ( sc >= 0 )
+ printf( "??? signed char not signed\n" );
+ TEST((signed char)u,sc);
+ TEST((int)(signed char)u,(int)sc);
+ i = (int) sc;
+ TEST((int)(signed char)u,i);
+#endif
+
+#ifdef bigints
+ u = 0x1ffff;
+ s = (short) u;
+ TEST((short)u,s);
+ TEST((int)(short)u,(int)s);
+ i = (int) s;
+ TEST((int)(short)u,i);
+
+#ifdef unsigshort
+ us = (unsigned short) u;
+ TEST((unsigned short)u,us);
+ TEST((int)(unsigned short)u,(int)us);
+ i = (int) us;
+ TEST((int)(unsigned short)u,i);
+#endif
+#endif
+
+ printf( "%d bad out of a possible %d\n", bad, possible );
+}
diff --git a/bcc-bruce/misc/test/ctype.t b/bcc-bruce/misc/test/ctype.t
new file mode 100644
index 0000000..93b3e4f
--- /dev/null
+++ b/bcc-bruce/misc/test/ctype.t
@@ -0,0 +1,38 @@
+/* ctype.h */
+
+#define _C 1 /* control */
+#define _D 2 /* digit */
+#define _L 4 /* lower */
+#define _P 8 /* punctuation */
+#define _S 16 /* space */
+#define _U 32 /* upper */
+#define _UN 64 /* underline */
+#define _X '\200' /* hex digit, not digit */
+
+extern char _ctype_[];
+
+#define _ct1_ (_ctype_+1)
+
+#define isalnum(c) (_ct1_[c]&(_U|_L|_D))
+#define isalpha(c) (_ct1_[c]&(_U|_L))
+#define isascii(i) ((unsigned)(i)<=0x7f)
+#define isalpha(c) (_ct1_[c]&(_U|_L))
+#define iscntrl(c) (_ct1_[c]&_C)
+#define iscsym(c) (_ct1_[c]&(_U|_L|_D|_UN))
+#define iscsymf(c) (_ct1_[c]&(_U|_L|_UN))
+#define isdigit(c) (_ct1_[c]&_D)
+#define isgraph(c) (_ct1_[c]&(_U|_L|_D|_P))
+#define islower(c) (_ct1_[c]&_L)
+/* isodigit(i) is a function */
+/* isprint(i) is a function */
+#define ispunct(c) (_ct1_[c]&_P)
+#define isspace(c) (_ct1_[c]&_S)
+#define isupper(c) (_ct1_[c]&_U)
+#define isxdigit(c) (_ct1_[c]&(_D|_X))
+
+#define toascii(i) ((i)&0x7f)
+/* toint(i) is a function */
+/* tolower(i) is a function */
+#define _tolower(c) ((c)+('a'-'A'))
+/* toupper(i) is a function */
+#define _toupper(c) ((c)+('A'-'a'))
diff --git a/bcc-bruce/misc/test/error.t b/bcc-bruce/misc/test/error.t
new file mode 100644
index 0000000..24e302a
--- /dev/null
+++ b/bcc-bruce/misc/test/error.t
@@ -0,0 +1,78 @@
+static char *errorstring[] =
+{
+ "# in a macro: not preprocessed",
+ "already declared",
+ "array of functions is illegal",
+ "bad address",
+ "bad case label",
+ "bad character constant",
+ "bad character",
+ "bad control",
+ "bad default label",
+ "bad expression",
+ "bad file name",
+ "bad indirection count",
+ "bad initializer address",
+ "bad register store",
+ "call of non-function",
+ "can't continue in switch",
+ "can't index",
+ "can't load char to index reg",
+ "can't open",
+ "can't open input",
+ "can't open output",
+ "case can't be reached with char switch",
+ "constant expression expected",
+ "else without if",
+ "end of file in #asm",
+ "end of file in #define",
+ "end of file in comment",
+ "end of file in failed #if",
+ "end of file in macro parameter expansion",
+ "end of file in string constant",
+ "end of line in string constant",
+ "endif without if",
+ "function returning array is illegal",
+ "function returning function is illegal",
+ "function returning structure is illegal",
+ "if stack overflow",
+ "illegal indirection",
+ "illegal macro name",
+ "illegal non-external function",
+ "illegal symbol name",
+ "illegal type conversion",
+ "illegal type name",
+ "initializer too complicated",
+ "input error",
+ "load of long constants not implemented",
+ "loading direct long with offset not implemented",
+ "local symbol table overflow",
+ "macro stack overflow",
+ "missing '('",
+ "missing while at end of do-while",
+ "need '",
+ "need int or char",
+ "need lvalue",
+ "need scalar or ptr type",
+ "need structure",
+ "no active fors, switches or whiles",
+ "not in a compound statement",
+ "null dimension",
+ "out of index registers",
+ "redefined macro",
+ "repeated argument",
+ "repeated default label",
+ "repeated parameter",
+ "table full",
+ "too few macro parameters",
+ "too many active whiles",
+ "too many cases",
+ "too many macro parameters",
+ "too many open compound statements",
+ "too many parameters",
+ "undeclared variable",
+ "undefined structure element",
+ "undefined structure",
+ "unsigned ints only",
+ "variable not in argument list"
+};
diff --git a/bcc-bruce/misc/test/extern.t b/bcc-bruce/misc/test/extern.t
new file mode 100644
index 0000000..dac5f5c
--- /dev/null
+++ b/bcc-bruce/misc/test/extern.t
@@ -0,0 +1,236 @@
+/* extern.c - external declarations (K & R p218-9) */
+
+#include "def.h"
+#include "globvar.h"
+#include "symbol.h"
+
+struct typestruct *declarator();
+struct typestruct *extypespec();
+int paramlist();
+struct typestruct *typespec();
+
+/*=============================================================================
+ -- notation is 1st attempt at EBNF (see Modula-2 book)
+ program = { type-definition | function-or-data-definition }.
+ type-definition = "typedef" type-definition-list.
+=============================================================================*/
+
+program()
+{
+ nextsym();
+ while ( sym != EOFSYM )
+ {
+ if ( sym = TYPEDEFDECL )
+ deftypes();
+ else
+ functordata();
+ }
+}
+
+/*=============================================================================
+ type-definition-list. -- not implemented
+=============================================================================*/
+
+deftypes()
+{}
+
+/*=============================================================================
+ function-or-data-definition = external-type-specification
+ ( function-definition | init-declarators ).
+ function-definition = "(" parameter-list ")" arg-list compound-statement.
+ -- this is different from K & R who omit typedefs and static functions
+=============================================================================*/
+
+functordata()
+{
+ struct typestruct *type;
+ int nargs;
+
+ type = extypespec();
+ if ( sym == LPAREN )
+ {
+ nextsym();
+ nargs = paramlist();
+ need( RPAREN );
+ arglist( nargs );
+ need( LBRACE );
+ compound( 1 + locptr-pstartloc );/* 1 = function flag, rest = nargs */
+ oldlevel();
+ }
+ else
+ initdecl( type );
+}
+
+/*=============================================================================
+ external-type-specification = extern-sc type-specifier declarator.
+ extern-sc = [ extern | static ].
+=============================================================================*/
+
+struct typestruct *extypespec()
+{
+ int sc;
+
+ switch( sym )
+ {
+ case EXTERNDECL:
+ case STATICDECL:
+ sc = sym; nextsym(); break;
+ default:
+ sc = EXTERNDECL; break;
+ }
+ return declarator( typespec() );
+}
+
+/*=============================================================================
+ parameter-list = [identifier { "," identifier }].
+=============================================================================*/
+
+int paramlist()
+{
+ int nargs;
+
+ locptr = pstartloc;
+ newlevel();
+ nargs = 0;
+ while ( sym == IDENT )
+ {
+ addloc( gsname, itype, 0 ); /* fix up types and offsets later */
+ nextsym();
+ ++nargs;
+ if ( sym != COMMA )
+ break;
+ nextsym();
+ }
+ return nargs;
+}
+
+/*=============================================================================
+ arg-list =
+=============================================================================*/
+
+arglist( nargs )
+int nargs;
+{
+ struct symstruct *symptr;
+ int argsize, argsp;
+ int lastsym;
+ struct typestruct *basetype;
+ char declflag;
+
+ declflag = TRUE;
+ do
+ {
+ switch( sym )
+ {
+ case TYPEDECL:
+ basetype = gsymptr->type;
+ nextsym();
+ getarg1( basetype );
+ break;
+ case STRUCTDECL:
+ case UNIONDECL:
+ lastsym = sym;
+ nextsym();
+ getarg( declsu( lastsym ) );
+ break;
+ case AUTODECL:
+ case EXTERNDECL:
+ case REGDECL:
+ case STATICDECL:
+ case SEMICOLON:
+ nextsym();
+ break;
+ default:
+ declflag = FALSE;
+ break;
+ }
+ }
+ while ( declflag );
+ argsp = -2;
+ symptr = pstartloc;
+ while ( nargs && symptr < locptr ) /* convert arg sizes to offsets */
+ {
+ argsize = symptr->offset;
+ if ( symptr->type == ctype )
+ {
+ ++argsp;
+ --argsize;
+ }
+ symptr->offset = argsp;
+ argsp += argsize;
+ if ( symptr == pstartloc )
+ argsp += 2;
+ --nargs;
+ ++symptr;
+ }
+ if ( nargs )
+ error( "arguments not all declared" );
+}
+
+/* getarg( basetype ) - fill in argument types and sizes */
+
+getarg1( basetype )
+struct typestruct *basetype;
+{
+ char sname[NAMESIZE];
+ struct typestruct *type;
+ int size;
+ struct symstruct *symptr;
+
+ if ( sym != SEMICOLON )
+ while ( TRUE )
+ {
+ type = basetype;
+ size = getvar( sname, &type );
+ if ( (symptr = findlorg( sname )) == NULL || symptr->level != ARGLEVEL )
+ error( "variable not in argument list" );
+ else if ( symptr->offset != 0 ) /* already in arg list */
+ multidecl( sname, type, symptr );
+ else
+ {
+ if ( size < 2 || type->typeop == ATYPEOP )
+ size = 2;
+ symptr->offset = size;
+ symptr->type = type;
+ }
+ if ( sym == COMMA )
+ nextsym();
+ else
+ break;
+ }
+ ns();
+}
+
+struct typestruct *declarator( basetype )
+struct typestruct *basetype;
+{
+ char sname[NAMESIZE];
+ int size;
+ struct symstruct *multi;
+
+ size = getvar( sname, &type );
+ if ( multi = findlorg( sname ) )
+ multidecl( sname, type, multi );
+ else
+ addglb( sname, type, size );
+ nextsym();
+}
+
+struct typestruct *typespec()
+{
+ int lastsym;
+
+ switch( sym )
+ {
+ case TYPEDECL:
+ nextsym();
+ return gsymptr->type;
+ case STRUCTDECL:
+ case UNIONDECL:
+ lastsym = sym;
+ nextsym();
+ return declsu( lastsym );
+ default:
+ return itype;
+ }
+}
diff --git a/bcc-bruce/misc/test/hilbert.t b/bcc-bruce/misc/test/hilbert.t
new file mode 100644
index 0000000..e18dc63
--- /dev/null
+++ b/bcc-bruce/misc/test/hilbert.t
@@ -0,0 +1,169 @@
+/* hilbert.c */
+
+/* S1 stuff
+
+#define PIFBUF ( *(struct IFBUF **) 0xf010 )
+#define PSET 2
+
+struct IFBUF
+{
+ char ERR;
+ char COMMAND;
+ char COLOR;
+ char PLOTOPTION;
+ int LINESTYLE;
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char BFFLAG;
+};
+end of S1 stuff */
+
+/* L3 stuff */
+
+#define PIFBUF ( (struct IFBUF *) 0xa1 )
+#define PSET 1
+
+struct IFBUF
+{
+ char PLOTOPTION;
+ char junk1[0xa8-0xa2];
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char junk2[0xf0-0xb0];
+ char ERR; /* this to BFFLAG are dummies to keep S1 code */
+ char COMMAND;
+ int LINESTYLE;
+ char BFFLAG;
+ char junk3[0x3ea-0xf5];
+ char COLOR;
+};
+
+#define H0 512 /* square size */
+#define XOFFS 80 /* offset to centre square */
+#define XNUM 15 /* scale 512 * 15/16 = 480 */
+#define XDENOM 16
+#define YNUM 25 /* scale 512 * 25/64 = 200 */
+#define YDENOM 64 /* to give max height, dot ratio 480/200 = 2.4 */
+
+int h, x, y;
+
+main()
+{
+ int i, x0, y0;
+ char color;
+
+ PIFBUF->PLOTOPTION = PSET;
+ PIFBUF->LINESTYLE = /* normal */
+ PIFBUF->COMMAND = /* ?? */
+ PIFBUF->BFFLAG = 0; /* not a box */
+ color = i = 0;
+ x0 = y0 = (h = H0)/2;
+ while ( h > 1 )
+ {
+ ++i;
+ h = h/2;
+ if ( ++color > 7 )
+ color = 1;
+ gcolor( color );
+ x = x0 += h/2;
+ y = y0 += h/2;
+ glocate();
+ a( i );
+ }
+}
+
+a( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ d( i ); x -= h; plot();
+ a( i ); y -= h; plot();
+ a( i ); x += h; plot();
+ b( i );
+ }
+}
+
+b( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ c( i ); y += h; plot();
+ b( i ); x += h; plot();
+ b( i ); y -= h; plot();
+ a( i );
+ }
+}
+
+c( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ b( i ); x += h; plot();
+ c( i ); y += h; plot();
+ c( i ); x -= h; plot();
+ d( i );
+ }
+}
+
+d( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ a( i ); y -= h; plot();
+ d( i ); x -= h; plot();
+ d( i ); y += h; plot();
+ c( i );
+ }
+}
+
+glocate()
+{
+ PIFBUF->X2 = x - x * (XDENOM - XNUM) / XDENOM + XOFFS;
+ PIFBUF->Y2 = (y * YNUM) / YDENOM;
+}
+
+/* S1 gcolor and plot
+
+gcolor( color )
+int color;
+{
+ PIFBUF->COLOR = color;
+}
+
+plot()
+{
+ PIFBUF->X1 = PIFBUF->X2;
+ PIFBUF->Y1 = PIFBUF->Y2;
+ glocate();
+#asm
+ SWI2
+ FDB $4201 call LINEMA
+#endasm
+}
+
+end S1 plot */
+
+gcolor( color )
+int color;
+{
+ PIFBUF->COLOR = color | 0x10;
+}
+
+plot()
+{
+ PIFBUF->X1 = PIFBUF->X2;
+ PIFBUF->Y1 = PIFBUF->Y2;
+ glocate();
+#asm
+ JSR $D709
+ JSR $D79A
+#endasm
+}
diff --git a/bcc-bruce/misc/test/longtest.c b/bcc-bruce/misc/test/longtest.c
new file mode 100644
index 0000000..0c0bfe0
--- /dev/null
+++ b/bcc-bruce/misc/test/longtest.c
@@ -0,0 +1,24 @@
+int i,j;
+long m,n;
+
+main()
+{
+ while ( 1 )
+ {
+ if ( scanf( "%ld %ld", &m, &n ) <= 0 )
+ exit( 0 );
+ printf( "m = %ld n = %ld m + n = %ld m - n = %ld m * n = %ld\n",
+ m, n, m + n, m - n, m * n );
+ printf( "m = %ld n = %ld m / n = %ld m %% n = %ld\n",
+ m, n, m / n, m % n );
+ printf( "m = %ld n = %ld m&n = %ld m | n = %ld m^n = %ld\n",
+ m, n, m & n, m | n, m ^ n );
+ printf( "m = %ld n = %ld m << n = %ld m >> n = %ld\n",
+ m, n, m << (int) n, m >> (int) n );
+ printf(
+ "m = %ld n = %ld m < n is %d m == n is %d m > n is %d m == 0 is %d\n",
+ m, n, m < n, m == n, m > n, m == 0 );
+ printf( "m = %ld n = %ld -m = %ld ~m = %ld ++m = %ld --n = %ld\n",
+ m, n, -m, ~m, ++m, --n );
+ }
+}
diff --git a/bcc-bruce/misc/test/longtest.dat b/bcc-bruce/misc/test/longtest.dat
new file mode 100644
index 0000000..a1c7998
--- /dev/null
+++ b/bcc-bruce/misc/test/longtest.dat
@@ -0,0 +1,15 @@
+1 1
+-1 1
+1 -1
+-1 -1
+2 3
+4 5
+234234 34554
+4534534 34535
+345324523 3245325
+345435345 319755
+34534 345
+-352351235 23535
+533512351 -3535345
+-351351313 -12235
+123456789 987654321
diff --git a/bcc-bruce/misc/test/longtest.mak b/bcc-bruce/misc/test/longtest.mak
new file mode 100755
index 0000000..454a4e8
--- /dev/null
+++ b/bcc-bruce/misc/test/longtest.mak
@@ -0,0 +1,3 @@
+cc -o cclongtest longtest.c
+sc longtest.c sclongtest.s
+cc -o sclongtest sclongtest.s $HOME/lib/libcb.a $HOME/lib/liblb.a
diff --git a/bcc-bruce/misc/test/longtest.sh b/bcc-bruce/misc/test/longtest.sh
new file mode 100755
index 0000000..e76f98a
--- /dev/null
+++ b/bcc-bruce/misc/test/longtest.sh
@@ -0,0 +1,4 @@
+./sclongtest < longtest.dat >scl.out
+./cclongtest < longtest.dat >ccl.out
+diff scl.out ccl.out >longtest.diff
+cat longtest.diff
diff --git a/bcc-bruce/misc/test/miniltest.t b/bcc-bruce/misc/test/miniltest.t
new file mode 100644
index 0000000..78097d4
--- /dev/null
+++ b/bcc-bruce/misc/test/miniltest.t
@@ -0,0 +1,72 @@
+long x;
+int i;
+unsigned u;
+
+long test1(x)
+long x;
+{
+ return x;
+}
+
+long test2(x)
+int x;
+{
+ return x;
+}
+
+main()
+{
+ printlong( "x=1 is ", x = 1 );
+ printlong( "test1(x) is ", test1(x) );
+ printlong( "test1(1L) is ", test1(1L) );
+ printlong( "x = test1(1L) is ", x = test1(1L) );
+ printlong( "x = test1(x=1) is ", x = test1(x=1) );
+ printlong( "i=1 is ", (long) (i = 1) );
+ printlong( "test2(i) is ", test2(i) );
+ printlong( "test2(1) is ", test2(1) );
+ printlong( "i = test2(1) is ", (long) (i = test2(1)) );
+ printlong( "i = test2(i=1) is ", (long) (i = test2(i=1)) );
+ printlong( "(long) (i = -1) is ", (long) (i=-1) );
+ printlong( "(long) (u = -1) is ", (long) (u=-1) );
+ printlong( "x = -1 is ", x = -1 );
+}
+
+printlong( s, x )
+char *s;
+long x;
+{
+ printf( "%s", s );
+ if ( x & 0x80000000 )
+ {
+ putchar( '-' );
+ x = -x;
+ }
+ printf( "%08lx", (x >> 16) + (x << 16) );
+ putchar( '\n' );
+}
+
+outulhex( pnum )
+char *pnum;
+{
+ int i;
+
+ for ( i = 3; i >=0; --i )
+ p2( pnum[i] );
+}
+
+p2(i)
+int i;
+{
+ p1(i>>4);
+ p1(i);
+}
+
+p1(num)
+int num;
+{
+ int digit;
+
+ if ( (digit = num & 0xf) >= 10 )
+ digit += 'A' - ('9' + 1);
+ putchar( digit + '0' );
+}
diff --git a/bcc-bruce/misc/test/op1.t b/bcc-bruce/misc/test/op1.t
new file mode 100644
index 0000000..614e093
--- /dev/null
+++ b/bcc-bruce/misc/test/op1.t
@@ -0,0 +1,120 @@
+/* op1.t - test and, or (eor same as or ) */
+
+char cfn();
+int ifn();
+
+char *op1()
+{
+ char c, *pc, **ppc;
+ int i, *pi, **ppi;
+
+ i = c & 1;
+ i = 1 & c;
+ i = i & 1;
+ i = 1 & i;
+
+ i = c & 500;
+ i = 500 & c;
+ i = i & 500;
+ i = 500 & i;
+
+ i = c | 1;
+ i = 1 | c;
+ i = i | 1;
+ i = 1 | i;
+
+ i = c | 500;
+ i = 500 | c;
+ i = i | 500;
+ i = 500 | i;
+
+ i = c & c;
+ i = c & i;
+ i = i & c;
+ i = i & i;
+
+ i = c | c;
+ i = c | i;
+ i = i | c;
+ i = i | i;
+
+ i = c & c++;
+ i = c & i++;
+ i = i & c++;
+ i = i & i++;
+
+ i = c++ & c;
+ i = i++ & c;
+ i = c++ & i;
+ i = i++ & i;
+
+ i = c | c++;
+ i = c | i++;
+ i = i | c++;
+ i = i | i++;
+
+ i = c++ | c;
+ i = i++ | c;
+ i = c++ | i;
+ i = i++ | i;
+
+ i = c & cfn();
+ i = c & ifn();
+ i = i & cfn();
+ i = i & ifn();
+
+ i = cfn() & c;
+ i = ifn() & c;
+ i = cfn() & i;
+ i = ifn() & i;
+
+ i = c | cfn();
+ i = c | ifn();
+ i = i | cfn();
+ i = i | ifn();
+
+ i = cfn() | c;
+ i = ifn() | c;
+ i = cfn() | i;
+ i = ifn() | i;
+
+ i = *pc & c++;
+ i = *pc & i++;
+ i = *pi & c++;
+ i = *pi & i++;
+
+ i = c++ & *pc;
+ i = i++ & *pc;
+ i = c++ & *pi;
+ i = i++ & *pi;
+
+ i = *pc | c++;
+ i = *pc | i++;
+ i = *pi | c++;
+ i = *pi | i++;
+
+ i = c++ | *pc;
+ i = i++ | *pc;
+ i = c++ | *pi;
+ i = i++ | *pi;
+
+ i = **ppc & c++;
+ i = **ppc & i++;
+ i = **ppi & c++;
+ i = **ppi & i++;
+
+ i = c++ & **ppc;
+ i = i++ & **ppc;
+ i = c++ & **ppi;
+ i = i++ & **ppi;
+
+ i = **ppc | c++;
+ i = **ppc | i++;
+ i = **ppi | c++;
+ i = **ppi | i++;
+
+ i = c++ | **ppc;
+ i = i++ | **ppc;
+ i = c++ | **ppi;
+ i = i++ | **ppi;
+}
diff --git a/bcc-bruce/misc/test/opcmp.t b/bcc-bruce/misc/test/opcmp.t
new file mode 100644
index 0000000..28bd1a2
--- /dev/null
+++ b/bcc-bruce/misc/test/opcmp.t
@@ -0,0 +1,106 @@
+/* opcmp.t - test logical compare operations */
+
+/* only doing chars, shorts, ints and unsigneds */
+/* not doing longs, floats or doubles */
+
+/* short = int, so only a few examples */
+/* unsigned like int, so only a few examples */
+/* all examples < */
+
+op1()
+{
+ char c, *pc, **ppc, cfn();
+ short s, *ps, **pps, sfn();
+ int i, *pi, **ppi, ifn();
+ unsigned u, *pu, **ppu, ufn();
+
+ c < 0;
+ 0 < c;
+ i < 0;
+ 0 < i;
+
+ s < 0;
+ 0 < s;
+
+ 0 < u;
+ u < 0;
+ 1 < u;
+ u < 1;
+
+ c < 1;
+ 1 < c;
+ c < 500;
+ 500 < c;
+
+ c < c;
+ c < i;
+ i < c;
+ i < i;
+
+ s < c;
+ i < u;
+
+ c < c++;
+ c < i++;
+ i < c++;
+ i < i++;
+
+ s < i++;
+ c < u++;
+
+ c++ < c;
+ i++ < c;
+ c++ < i;
+ i++ < i;
+
+ s++ < c;
+ i++ < u;
+
+ c < cfn();
+ c < ifn();
+ i < cfn();
+ i < ifn();
+
+ s < cfn();
+ c < ufn();
+
+ cfn() < c;
+ ifn() < c;
+ cfn() < i;
+ ifn() < i;
+
+ sfn() < c;
+ ifn() < u;
+
+ *pc < c++;
+ *pc < i++;
+ *pi < c++;
+ *pi < i++;
+
+ *ps < c++;
+ *pi < u++;
+
+ c++ < *pc;
+ i++ < *pc;
+ c++ < *pi;
+ i++ < *pi;
+
+ s++ < *pc;
+ i++ < *pu;
+
+ **ppc < c++;
+ **ppc < i++;
+ **ppi < c++;
+ **ppi < i++;
+
+ **pps < c++;
+ **ppi < u++;
+
+ c++ < **ppc;
+ i++ < **ppc;
+ c++ < **ppi;
+ i++ < **ppi;
+
+ s++ < **ppc;
+ i++ < **ppu;
+}
diff --git a/bcc-bruce/misc/test/oplong.t b/bcc-bruce/misc/test/oplong.t
new file mode 100644
index 0000000..b452243
--- /dev/null
+++ b/bcc-bruce/misc/test/oplong.t
@@ -0,0 +1,264 @@
+/* oplong.t - test long operations */
+
+/* this is just opsoft.t with int defined as long */
+
+#define int long
+#define UNSIGNED unsigned long
+
+/* only doing chars, shorts, ints and unsigneds */
+/* not doing longs, floats or doubles */
+
+/* short = int, so only a few examples */
+/* unsigned like int, so only a few examples */
+/* most examples for DIVOP */
+/* only (all) special cases of MULOP, MODOP, SLOP and SROP are tried */
+
+op1()
+{
+ char c, *pc, **ppc, cfn();
+ short s, *ps, **pps, sfn();
+ int i, *pi, **ppi, ifn();
+ UNSIGNED u, *pu, **ppu, ufn();
+
+ i = c / 0;
+ i = 0 / c;
+ i = i / 0;
+ i = 0 / i;
+
+ i = s / 0;
+ i = 0 / u;
+
+ i = c / 1;
+ i = 1 / c;
+ i = i / 1;
+ i = 1 / i;
+
+ i = s / 1;
+ i = 1 / u;
+
+ i = c / 2;
+ i = 2 / c;
+ i = i / 2;
+ i = 2 / i;
+
+ i = s / 2;
+ i = 2 / u;
+
+ i = c / 500;
+ i = 500 / c;
+ i = i / 500;
+ i = 500 / i;
+
+ i = s / 500;
+ i = 500 / u;
+
+ i = c / c;
+ i = c / i;
+ i = i / c;
+ i = i / i;
+
+ i = s / c;
+ i = i / u;
+
+ i = c / c++;
+ i = c / i++;
+ i = i / c++;
+ i = i / i++;
+
+ i = s / i++;
+ i = c / u++;
+
+ i = c++ / c;
+ i = i++ / c;
+ i = c++ / i;
+ i = i++ / i;
+
+ i = s++ / c;
+ i = i++ / u;
+
+ i = c / cfn();
+ i = c / ifn();
+ i = i / cfn();
+ i = i / ifn();
+
+ i = s / cfn();
+ i = c / ufn();
+
+ i = cfn() / c;
+ i = ifn() / c;
+ i = cfn() / i;
+ i = ifn() / i;
+
+ i = sfn() / c;
+ i = ifn() / u;
+
+ i = *pc / c++;
+ i = *pc / i++;
+ i = *pi / c++;
+ i = *pi / i++;
+
+ i = *ps / c++;
+ i = *pi / u++;
+
+ i = c++ / *pc;
+ i = i++ / *pc;
+ i = c++ / *pi;
+ i = i++ / *pi;
+
+ i = s++ / *pc;
+ i = i++ / *pu;
+
+ i = **ppc / c++;
+ i = **ppc / i++;
+ i = **ppi / c++;
+ i = **ppi / i++;
+
+ i = **pps / c++;
+ i = **ppi / u++;
+
+ i = c++ / **ppc;
+ i = i++ / **ppc;
+ i = c++ / **ppi;
+ i = i++ / **ppi;
+
+ i = s++ / **ppc;
+ i = i++ / **ppu;
+
+ i = c * 0;
+ i = 0 * c;
+ i = i * 0;
+ i = 0 * i;
+
+ i = s * 0;
+ i = 0 * u;
+
+ i = c * 1;
+ i = 1 * c;
+ i = i * 1;
+ i = 1 * i;
+
+ i = s * 1;
+ i = 1 * u;
+
+ i = c * 2;
+ i = 2 * c;
+ i = i * 2;
+ i = 2 * i;
+
+ i = s * 2;
+ i = 2 * u;
+
+ i = c * 500;
+ i = 500 * c;
+ i = i * 500;
+ i = 500 * i;
+
+ i = s * 500;
+ i = 500 * u;
+
+ i = c * c;
+ i = c * c++;
+ i = c++ * c;
+ i = c * cfn();
+ i = cfn() * c;
+ i = *pc * c++;
+ i = c++ * *pc;
+ i = **ppc * c++;
+ i = c++ * **ppc;
+
+ i = c % 0;
+ i = 0 % c;
+ i = i % 0;
+ i = 0 % i;
+
+ i = s % 0;
+ i = 0 % u;
+
+ i = c % 1;
+ i = 1 % c;
+ i = i % 1;
+ i = 1 % i;
+
+ i = s % 1;
+ i = 1 % u;
+
+ i = c % 2;
+ i = 2 % c;
+ i = i % 2;
+ i = 2 % i;
+
+ i = s % 2;
+ i = 2 % u;
+
+ i = c % 500;
+ i = 500 % c;
+ i = i % 500;
+ i = 500 % i;
+
+ i = s % 500;
+ i = 500 % u;
+
+ i = c << 0;
+ i = 0 << c;
+ i = i << 0;
+ i = 0 << i;
+
+ i = s << 0;
+ i = 0 << u;
+
+ i = c << 1;
+ i = 1 << c;
+ i = i << 1;
+ i = 1 << i;
+
+ i = s << 1;
+ i = 1 << u;
+
+ i = c << 8;
+ i = 8 << c;
+ i = i << 8;
+ i = 8 << i;
+
+ i = s << 8;
+ i = 8 << u;
+
+ i = c << 9;
+ i = 9 << c;
+ i = i << 9;
+ i = 9 << i;
+
+ i = s << 9;
+ i = 9 << u;
+
+ i = c >> 0;
+ i = 0 >> c;
+ i = i >> 0;
+ i = 0 >> i;
+
+ i = s >> 0;
+ i = 0 >> u;
+
+ i = c >> 1;
+ i = 1 >> c;
+ i = i >> 1;
+ i = 1 >> i;
+
+ i = s >> 1;
+ i = 1 >> u;
+
+ i = c >> 8;
+ i = 8 >> c;
+ i = i >> 8;
+ i = 8 >> i;
+
+ i = s >> 8;
+ i = 8 >> u;
+
+ i = c >> 9;
+ i = 9 >> c;
+ i = i >> 9;
+ i = 9 >> i;
+
+ i = s >> 9;
+ i = 9 >> u;
+}
diff --git a/bcc-bruce/misc/test/opplus.t b/bcc-bruce/misc/test/opplus.t
new file mode 100644
index 0000000..88e31e9
--- /dev/null
+++ b/bcc-bruce/misc/test/opplus.t
@@ -0,0 +1,122 @@
+/* op+-.t - test plus, minus operators */
+
+/* only doing chars and ints, not shorts, longs, floats, doubles */
+/* not doing pointer arithmetic */
+
+op1()
+{
+ char cfn();
+ int ifn();
+ char c, *pc, **ppc;
+ int i, *pi, **ppi;
+
+ i = c + 1;
+ i = 1 + c;
+ i = i + 1;
+ i = 1 + i;
+
+ i = c + 500;
+ i = 500 + c;
+ i = i + 500;
+ i = 500 + i;
+
+ i = c - 1;
+ i = 1 - c;
+ i = i - 1;
+ i = 1 - i;
+
+ i = c - 500;
+ i = 500 - c;
+ i = i - 500;
+ i = 500 - i;
+
+ i = c + c;
+ i = c + i;
+ i = i + c; /* -2 cycles, +1 byte different from c + i, lhs loaded 1st */
+ i = i + i;
+
+ i = c - c;
+ i = c - i;
+ i = i - c;
+ i = i - i;
+
+ i = c + c++;
+ i = c + i++;
+ i = i + c++;
+ i = i + i++;
+
+ i = c++ + c;
+ i = i++ + c;
+ i = c++ + i;
+ i = i++ + i;
+
+ i = c - c++;
+ i = c - i++;
+ i = i - c++;
+ i = i - i++;
+
+ i = c++ - c;
+ i = i++ - c;
+ i = c++ - i;
+ i = i++ - i;
+
+ i = c + cfn();
+ i = c + ifn();
+ i = i + cfn();
+ i = i + ifn();
+
+ i = cfn() + c;
+ i = ifn() + c;
+ i = cfn() + i;
+ i = ifn() + i;
+
+ i = c - cfn();
+ i = c - ifn();
+ i = i - cfn();
+ i = i - ifn();
+
+ i = cfn() - c;
+ i = ifn() - c;
+ i = cfn() - i;
+ i = ifn() - i;
+
+ i = *pc + c++;
+ i = *pc + i++;
+ i = *pi + c++;
+ i = *pi + i++;
+
+ i = c++ + *pc;
+ i = i++ + *pc;
+ i = c++ + *pi;
+ i = i++ + *pi;
+
+ i = *pc - c++;
+ i = *pc - i++;
+ i = *pi - c++;
+ i = *pi - i++;
+
+ i = c++ - *pc;
+ i = i++ - *pc;
+ i = c++ - *pi;
+ i = i++ - *pi;
+
+ i = **ppc + c++;
+ i = **ppc + i++;
+ i = **ppi + c++;
+ i = **ppi + i++;
+
+ i = c++ + **ppc;
+ i = i++ + **ppc;
+ i = c++ + **ppi;
+ i = i++ + **ppi;
+
+ i = **ppc - c++;
+ i = **ppc - i++;
+ i = **ppi - c++;
+ i = **ppi - i++;
+
+ i = c++ - **ppc;
+ i = i++ - **ppc;
+ i = c++ - **ppi;
+ i = i++ - **ppi;
+}
diff --git a/bcc-bruce/misc/test/opsoft.t b/bcc-bruce/misc/test/opsoft.t
new file mode 100644
index 0000000..346df4d
--- /dev/null
+++ b/bcc-bruce/misc/test/opsoft.t
@@ -0,0 +1,259 @@
+/* opsoft.t - test software operations */
+
+/* only doing chars, shorts, ints and unsigneds */
+/* not doing longs, floats or doubles */
+
+/* short = int, so only a few examples */
+/* unsigned like int, so only a few examples */
+/* most examples for DIVOP */
+/* only (all) special cases of MULOP, MODOP, SLOP and SROP are tried */
+
+op1()
+{
+ char c, *pc, **ppc, cfn();
+ short s, *ps, **pps, sfn();
+ int i, *pi, **ppi, ifn();
+ unsigned u, *pu, **ppu, ufn();
+
+ i = c / 0;
+ i = 0 / c;
+ i = i / 0;
+ i = 0 / i;
+
+ i = s / 0;
+ i = 0 / u;
+
+ i = c / 1;
+ i = 1 / c;
+ i = i / 1;
+ i = 1 / i;
+
+ i = s / 1;
+ i = 1 / u;
+
+ i = c / 2;
+ i = 2 / c;
+ i = i / 2;
+ i = 2 / i;
+
+ i = s / 2;
+ i = 2 / u;
+
+ i = c / 500;
+ i = 500 / c;
+ i = i / 500;
+ i = 500 / i;
+
+ i = s / 500;
+ i = 500 / u;
+
+ i = c / c;
+ i = c / i;
+ i = i / c;
+ i = i / i;
+
+ i = s / c;
+ i = i / u;
+
+ i = c / c++;
+ i = c / i++;
+ i = i / c++;
+ i = i / i++;
+
+ i = s / i++;
+ i = c / u++;
+
+ i = c++ / c;
+ i = i++ / c;
+ i = c++ / i;
+ i = i++ / i;
+
+ i = s++ / c;
+ i = i++ / u;
+
+ i = c / cfn();
+ i = c / ifn();
+ i = i / cfn();
+ i = i / ifn();
+
+ i = s / cfn();
+ i = c / ufn();
+
+ i = cfn() / c;
+ i = ifn() / c;
+ i = cfn() / i;
+ i = ifn() / i;
+
+ i = sfn() / c;
+ i = ifn() / u;
+
+ i = *pc / c++;
+ i = *pc / i++;
+ i = *pi / c++;
+ i = *pi / i++;
+
+ i = *ps / c++;
+ i = *pi / u++;
+
+ i = c++ / *pc;
+ i = i++ / *pc;
+ i = c++ / *pi;
+ i = i++ / *pi;
+
+ i = s++ / *pc;
+ i = i++ / *pu;
+
+ i = **ppc / c++;
+ i = **ppc / i++;
+ i = **ppi / c++;
+ i = **ppi / i++;
+
+ i = **pps / c++;
+ i = **ppi / u++;
+
+ i = c++ / **ppc;
+ i = i++ / **ppc;
+ i = c++ / **ppi;
+ i = i++ / **ppi;
+
+ i = s++ / **ppc;
+ i = i++ / **ppu;
+
+ i = c * 0;
+ i = 0 * c;
+ i = i * 0;
+ i = 0 * i;
+
+ i = s * 0;
+ i = 0 * u;
+
+ i = c * 1;
+ i = 1 * c;
+ i = i * 1;
+ i = 1 * i;
+
+ i = s * 1;
+ i = 1 * u;
+
+ i = c * 2;
+ i = 2 * c;
+ i = i * 2;
+ i = 2 * i;
+
+ i = s * 2;
+ i = 2 * u;
+
+ i = c * 500;
+ i = 500 * c;
+ i = i * 500;
+ i = 500 * i;
+
+ i = s * 500;
+ i = 500 * u;
+
+ i = c * c;
+ i = c * c++;
+ i = c++ * c;
+ i = c * cfn();
+ i = cfn() * c;
+ i = *pc * c++;
+ i = c++ * *pc;
+ i = **ppc * c++;
+ i = c++ * **ppc;
+
+ i = c % 0;
+ i = 0 % c;
+ i = i % 0;
+ i = 0 % i;
+
+ i = s % 0;
+ i = 0 % u;
+
+ i = c % 1;
+ i = 1 % c;
+ i = i % 1;
+ i = 1 % i;
+
+ i = s % 1;
+ i = 1 % u;
+
+ i = c % 2;
+ i = 2 % c;
+ i = i % 2;
+ i = 2 % i;
+
+ i = s % 2;
+ i = 2 % u;
+
+ i = c % 500;
+ i = 500 % c;
+ i = i % 500;
+ i = 500 % i;
+
+ i = s % 500;
+ i = 500 % u;
+
+ i = c << 0;
+ i = 0 << c;
+ i = i << 0;
+ i = 0 << i;
+
+ i = s << 0;
+ i = 0 << u;
+
+ i = c << 1;
+ i = 1 << c;
+ i = i << 1;
+ i = 1 << i;
+
+ i = s << 1;
+ i = 1 << u;
+
+ i = c << 8;
+ i = 8 << c;
+ i = i << 8;
+ i = 8 << i;
+
+ i = s << 8;
+ i = 8 << u;
+
+ i = c << 9;
+ i = 9 << c;
+ i = i << 9;
+ i = 9 << i;
+
+ i = s << 9;
+ i = 9 << u;
+
+ i = c >> 0;
+ i = 0 >> c;
+ i = i >> 0;
+ i = 0 >> i;
+
+ i = s >> 0;
+ i = 0 >> u;
+
+ i = c >> 1;
+ i = 1 >> c;
+ i = i >> 1;
+ i = 1 >> i;
+
+ i = s >> 1;
+ i = 1 >> u;
+
+ i = c >> 8;
+ i = 8 >> c;
+ i = i >> 8;
+ i = 8 >> i;
+
+ i = s >> 8;
+ i = 8 >> u;
+
+ i = c >> 9;
+ i = 9 >> c;
+ i = i >> 9;
+ i = 9 >> i;
+
+ i = s >> 9;
+ i = 9 >> u;
+}
diff --git a/bcc-bruce/misc/test/puzzle.t b/bcc-bruce/misc/test/puzzle.t
new file mode 100644
index 0000000..9d2c4ab
--- /dev/null
+++ b/bcc-bruce/misc/test/puzzle.t
@@ -0,0 +1,178 @@
+/* puzzle.t - from C puzzle book */
+
+#define puzzle(which) ( puts( "-----which-----\n" ), which() )
+
+main()
+{
+ puzzle( op1 );
+ puzzle( op2 );
+ puzzle( op3 );
+ puzzle( op4 );
+ puzzle( op5 );
+ puzzle( op6 );
+ puzzle( prep1 );
+ puzzle( prep2 );
+}
+
+op1()
+{
+ int x;
+
+ x = - 3 + 4 * 5 - 6; printf("%d\n",x);
+ x = 3 + 4 % 5 - 6; printf("%d\n",x);
+ x = - 3 * 4 % - 6 / 5; printf("%d\n",x);
+ x = ( 7 + 6 ) % 5 /2; printf("%d\n",x);
+}
+
+#define PRINTX printf( "%d\n", x )
+
+op2()
+{
+ int x, y, z;
+
+ x = 2;
+ x *= 3 + 2; PRINTX;
+ x *= y = z = 4; PRINTX;
+ x = y == z; PRINTX;
+ x == (y == z); PRINTX;
+}
+
+#define PRINT(int) printf( "int = %d\n", int )
+
+op3()
+{
+ int x, y, z;
+
+ x = 2; y = 1; z = 0;
+ x = x && y || z; PRINT(x);
+ PRINT( x || ! y && z );
+
+ x = y = 1;
+ z = x ++ - 1; PRINT(x); PRINT(z);
+ z += - x ++ + ++ y;PRINT(x);PRINT(z);
+ z = x / ++ x; PRINT(z);
+}
+
+op4()
+{
+ int x, y, z;
+
+ x = 03; y = 02; z = 01;
+ PRINT( x | y & z );
+ PRINT( x | y & ~ z );
+ PRINT( x ^ y & ~ z );
+ PRINT( x & y && z );
+
+ x = 1; y = -1;
+ PRINT( ! x | x );
+ PRINT( ~ x | x );
+ PRINT( x ^ x );
+ x <<= 3; PRINT(x);
+ y <<= 3; PRINT(y);
+ y >>= 3; PRINT(y);
+}
+
+op5()
+{
+ int x, y, z;
+
+ x = 1; y = 1; z = 1;
+
+ x += y += z;
+ PRINT( x < y ? y : x );
+
+ PRINT( x < y ? x ++ : y ++ );
+ PRINT(x); PRINT(y);
+
+ PRINT( z += x < y ? x ++ : y ++ );
+ PRINT(y); PRINT(z);
+
+ x = 3; y=z=4;
+ PRINT( (z >= y >= x) ? 1 : 0 );
+ PRINT( z >= y && y >= x );
+}
+
+#define PRINT3(x,y,z) printf("x=%d\ty=%d\tz=%d\n",x,y,z)
+
+op6()
+{
+ int x, y, z;
+
+ x = y = z = 1;
+ ++x || ++y && ++z; PRINT3(x,y,z);
+
+ x = y = z = 1;
+ ++x && ++y || ++z; PRINT3(x,y,z);
+
+ x = y = z = 1;
+ ++x && ++y && ++z; PRINT3(x,y,z);
+
+ x = y = z = -1;
+ ++x && ++y || ++z; PRINT3(x,y,z);
+
+ x = y = z = -1;
+ ++x || ++y && ++z; PRINT3(x,y,z);
+
+ x = y = z = -1;
+ ++x && ++y && ++z; PRINT3(x,y,z);
+}
+
+#define FUDGE(k) k+3
+#define PR(a) printf("a= %d\t",(int)(a))
+#define PRINTNEW(a) PR(a); putchar( '\n' );
+#define PRINT2(a,b) PR(a); PRINT(b)
+#define PRINT3NEW(a,b,c) PR(a); PRINT2(b,c)
+#define MAX(a,b) (a<b ? b : a )
+
+prep1()
+{
+ {
+ int x;
+ x = 2;
+ PRINTNEW( x*FUDGE(2) );
+ }
+ {
+ int cel;
+ for( cel=0; cel<=100; cel+=50 )
+ PRINT2( cel, 9/5*cel+32 );
+ }
+ {
+ int x, y;
+ x=1; y=2;
+ PRINT3NEW( MAX(x++,y),x,y );
+ PRINT3NEW( MAX(x++,y),x,y );
+ }
+}
+
+#define NEG(a)-a
+#define weeks(mins) (days(mins)/7)
+#define days(mins) (hours(mins)/24)
+#define hours(mins) (mins/60)
+#define mins(secs) (secs/60)
+#define TAB(c,i,oi,tx) if(c=='\t')\
+ for(tx=8-(i-oi-1)%8,oi=i; tx; tx--)\
+ putchar(' ')
+
+static char *input = "\twhich\tif?";
+
+prep2()
+{
+ {
+ int x;
+ x=1;
+ PRINT( -NEG(x) );
+ }
+ {
+ PRINT( weeks(10080) );
+ PRINT( days(mins(86400)) );
+ }
+ {
+ char c;
+ int i, oldi, temp;
+
+ for( oldi= -1,i=0; (c=input[i])!='\0'; i++ )
+ if( c<' ' ) TAB(c,i,oldi,temp);
+ else putchar(c);
+ putchar('\n');
+ }
+}
diff --git a/bcc-bruce/misc/test/sierpin.t b/bcc-bruce/misc/test/sierpin.t
new file mode 100644
index 0000000..79016f7
--- /dev/null
+++ b/bcc-bruce/misc/test/sierpin.t
@@ -0,0 +1,123 @@
+/* sierpin.t */
+
+#define PPIFBUF 0xf010 /* address of ptr to IFBUF */
+#define PSET 2 /* use this plot option */
+
+struct IFBUF
+{
+ char ERR;
+ char COMMAND;
+ char COLOR;
+ char PLOTOPTION;
+ int LINESTYLE;
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char BFFLAG;
+};
+
+#define H0 512 /* square size */
+#define XOFFS 80 /* offset to centre square */
+#define XNUM 15 /* scale 512 * 15/16 = 480 */
+#define XDENOM 16
+#define YNUM 25 /* scale 512 * 25/64 = 200 */
+#define YDENOM 64 /* to give max height, dot ratio 480/200 = 2.4 */
+
+struct IFBUF *pifbuf;
+int h, x, y;
+
+main()
+{
+ struct IFBUF **ppifbuf; /* required since no casts */
+ int i, x0, y0;
+ char color;
+
+ pifbuf = *(ppifbuf = PPIFBUF); /* pifbuf = *(struct IFBUF **)PPIFBUF; */
+ pifbuf->PLOTOPTION = PSET;
+ pifbuf->LINESTYLE = /* normal */
+ pifbuf->COMMAND = /* ?? */
+ pifbuf->BFFLAG = 0; /* not a box */
+ color = i = 0;
+ x0 = 2 * (h = H0/4);
+ y0 = 3 * (H0/4);
+ while ( h > 1 )
+ {
+ ++i;
+ if ( ++color > 7 )
+ color = 1;
+ pifbuf->COLOR = color;
+ x = x0 -= h;
+ y = y0 += h /= 2;
+ glocate();
+ a( i ); x += h; y -= h; plot();
+ b( i ); x -= h; y -= h; plot();
+ c( i ); x -= h; y += h; plot();
+ d( i ); x += h; y += h; plot();
+ }
+}
+
+a( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ a( i ); x += h; y -=h; plot();
+ b( i ); x += 2*h; plot();
+ d( i ); x += h; y += h; plot();
+ a( i );
+ }
+}
+
+b( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ b( i ); x -= h; y -=h; plot();
+ c( i ); y -= 2*h; plot();
+ a( i ); x += h; y -= h; plot();
+ b( i );
+ }
+}
+
+c( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ c( i ); x -= h; y +=h; plot();
+ d( i ); x -= 2*h; plot();
+ b( i ); x -= h; y -= h; plot();
+ c( i );
+ }
+}
+
+d( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ d( i ); x += h; y +=h; plot();
+ a( i ); y += 2*h; plot();
+ c( i ); x -= h; y += h; plot();
+ d( i );
+ }
+}
+
+glocate()
+{
+ pifbuf->X2 = x - x * (XDENOM - XNUM) / XDENOM + XOFFS;
+ pifbuf->Y2 = (y * YNUM) / YDENOM;
+}
+
+plot()
+{
+ pifbuf->X1 = pifbuf->X2;
+ pifbuf->Y1 = pifbuf->Y2;
+ glocate();
+#asm
+ SWI2
+ FDB $4201 call LINEMA
+#endasm
+}
diff --git a/bcc-bruce/misc/test/sievec.t b/bcc-bruce/misc/test/sievec.t
new file mode 100644
index 0000000..1b51fdb
--- /dev/null
+++ b/bcc-bruce/misc/test/sievec.t
@@ -0,0 +1,28 @@
+#define TRUE 1
+#define FALSE 0
+#define SIZE 8190
+
+char flags[SIZE+1];
+
+main()
+{
+ int i,prime,k,count,iter;
+
+ for (iter=0;iter<10;iter++)
+ {
+ count=0;
+ for (i=0;i<=SIZE;i++)
+ flags[i]=TRUE;
+ for (i=0;i<=SIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ for (k=i+prime;k<=SIZE;k=k+prime)
+ flags[k]=FALSE;
+ count++;
+ }
+ }
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc-bruce/misc/test/sievecp.t b/bcc-bruce/misc/test/sievecp.t
new file mode 100644
index 0000000..185b031
--- /dev/null
+++ b/bcc-bruce/misc/test/sievecp.t
@@ -0,0 +1,45 @@
+/* sieve using pointers */
+
+#define TRUE 1
+#define FALSE 0
+#define NITER 100
+#define SIZE 8191 /* last prime <= 2*this+3 */
+#define SQRSIZE 63 /* last divisor tested = 2*this+3 */
+
+char flags[SIZE+2*SQRSIZE+3]; /* avoid ptr+=prime overflowing */
+
+main()
+{
+ int i,count,iter;
+ register char *ptr;
+ char *endptr;
+ int prime;
+
+ for (iter=0;iter<NITER;iter++)
+ {
+ count=0;
+ ptr=flags;
+ endptr=flags+SIZE;
+ while (ptr<endptr)
+ *ptr++=TRUE;
+ for (i=0;i<SQRSIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ ptr=flags+i+prime; /* ptr<endptr since i<SQRSIZE */
+ while (ptr<endptr)
+ {
+ *ptr=FALSE;
+ ptr+=prime; /* does not overflow since in flags */
+ }
+ count++;
+ }
+ }
+ ptr=flags+SQRSIZE;
+ while (ptr<endptr)
+ if (*ptr++)
+ count++;
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc-bruce/misc/test/sievei.t b/bcc-bruce/misc/test/sievei.t
new file mode 100644
index 0000000..d4910dc
--- /dev/null
+++ b/bcc-bruce/misc/test/sievei.t
@@ -0,0 +1,28 @@
+#define TRUE 1
+#define FALSE 0
+#define SIZE 8190
+
+int flags[SIZE+1];
+
+main()
+{
+ int i,prime,k,count,iter;
+
+ for (iter=0;iter<10;iter++)
+ {
+ count=0;
+ for (i=0;i<=SIZE;i++)
+ flags[i]=TRUE;
+ for (i=0;i<=SIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ for (k=i+prime;k<=SIZE;k=k+prime)
+ flags[k]=FALSE;
+ count++;
+ }
+ }
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc-bruce/misc/test/sort.t b/bcc-bruce/misc/test/sort.t
new file mode 100644
index 0000000..34bcb9e
--- /dev/null
+++ b/bcc-bruce/misc/test/sort.t
@@ -0,0 +1,104 @@
+unsigned t[10000];
+unsigned s[10000];
+unsigned size,repet;
+unsigned comp=0,swap=0; /* s.b. long */
+
+main(argc)
+{
+ int i,zz;
+
+/*
+ printf("size?");
+ scanf("%d",&size);
+ printf("repet?");
+ scanf("%d",&repet);
+*/
+ if ( argc > 20 )
+ {
+ printf( "usage: sort [args], where 500*argc is the array size\n" );
+ exit( 1 );
+ }
+ size = 500 * argc;
+ repet = 1;
+ for (i = 0; i < size; i++)
+ s[i] = size-i;
+ printf("\npress key to begin shell sorting\n");
+ getchar();
+ for (zz=0;zz<repet;zz++)
+ {
+ comp=swap=0;
+ for (i=0;i<size;i++)
+ t[i]=s[i];
+ sort();
+ }
+ printf("\nsorted\n");
+ printf("\ncompares = %d, swaps = %d\n",comp,swap);
+ printf("\npress key to begin quick sorting\n");
+ getchar();
+ for (zz=0;zz<repet;zz++)
+ {
+ comp=swap=0;
+ for (i=0;i<size;i++)
+ t[i]=s[i];
+ qqsort();
+ }
+ printf("\nsorted\n");
+ printf("\ncompares = %d, swaps = %d\n",comp,swap);
+}
+
+sort()
+{
+ int i,j,h,temp;
+
+ h=1;
+ while (9*h+4<size)
+ h=3*h+1;
+ while (h>0)
+ {
+ for (j=h; j<size; j++)
+ for (i=j-h; i>=0; i-=h)
+ {
+ ++comp;
+ if (t[i]<=t[i+h])
+ break;
+ ++swap;
+ temp=t[i];
+ t[i]=t[i+h];
+ t[i+h]=temp;
+ }
+ h=(h-1)/3;
+ }
+}
+
+qqsort()
+{
+ qsort(0,size-1);
+}
+
+qsort(l,r)
+int l,r;
+{
+ int i,j;
+ unsigned x,w;
+
+ i=l;j=r;
+ x=t[(l+r)>>1];
+ do
+ {
+ while (t[i] < x)
+ {
+ ++comp;
+ i++;
+ }
+ while (x < t[j]) {--j;}
+ if (i<=j)
+ {
+ ++swap;
+ w=t[i];t[i]=t[j];t[j]=w;
+ i++;j--;
+ }
+ }
+ while (i<=j);
+ if (l<j) qsort(l,j);
+ if (i<r) qsort(i,r);
+}
diff --git a/bcc-bruce/misc/test/stdio.t b/bcc-bruce/misc/test/stdio.t
new file mode 100644
index 0000000..e7e174d
--- /dev/null
+++ b/bcc-bruce/misc/test/stdio.t
@@ -0,0 +1,87 @@
+/* stdio.h */
+
+#asm
+
+#define BUFSIZ 512
+#define _NFILE 20
+
+#define _IOREAD 1
+#define _IOWRITE 2
+#define _IODIRTY 4
+#define _IOEOF 8
+#define _IOERR 16
+#define _IOMYBUF 32 /* says if stream routines allocated buffer */
+#define _IOUNBUF 64
+
+#define EOF (-1)
+#define NULL 0
+
+#endasm
+
+#define stdin (&_iob[0])
+#define stdout (&_iob[1])
+#define stderr (&_iob[2])
+
+#define FILE struct _iobuf
+
+struct _iobuf
+{
+ char *_ptr;
+ char *_base;
+ char *_rtop;
+ char *_wtop;
+ char _flags;
+ char _fd;
+}
+ _iob[_NFILE];
+
+#define clearerr(fp) ((fp)->flags&=~_IOERR)
+#define getchar() getc(stdin)
+#define feof(fp) ((fp)->_flags&_IOEOF)
+#define ferror(fp) ((fp)->_flags&_IOERR)
+#define fileno(fp) ((fp)->_fd)
+#define putchar(c) putc((c),stdout)
+
+#define void int
+
+FILE *fdopen();
+char *fgets();
+FILE *fopen();
+FILE *freopen();
+long ftell();
+
+long lseek();
+unsigned read();
+unsigned write();
+
+char *malloc();
+char *realloc();
+char *sbrk();
+
+char *index();
+char *rindex();
+char *strcat();
+char *strcpy();
+char *strncat();
+char *strncpy();
+
+#asm
+
+BLANK EQU 32
+COEOL EQU 10
+EOL EQU 13
+MAXCONTROL EQU 31
+
+* struct _iobuf translated into offsets
+
+ BLOCK 0
+PTR RMB 2
+BASE RMB 2
+RTOP RMB 2
+WTOP RMB 2
+FLAGS RMB 1
+FD RMB 1
+IOB.SIZE
+ ENDB
+
+#endasm
diff --git a/bcc-bruce/os.h b/bcc-bruce/os.h
new file mode 100644
index 0000000..672ddd8
--- /dev/null
+++ b/bcc-bruce/os.h
@@ -0,0 +1,79 @@
+/* os.h - source/target operating system dependencies for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ must have unix-near-compatible creat, open, read, write and close
+
+ source O/S's supported:
+ default:
+ *IX
+ special:
+ EDOS (#define SOS_EDOS if required)
+ MSDOS (#define SOS_MSDOS)
+ target O/S's supported:
+ default:
+ *IX
+ MSDOS
+ special:
+ EDOS (#define TOS_EDOS)
+*/
+
+/* defaults */
+
+#define CREATPERMS 0666 /* permissions for creat */
+#define EOL 10 /* source newline */
+#define EOLTO 10 /* target newline */
+#define DIRCHAR '/'
+#define DIRSTRING "/"
+#define DEFAULT_INCLUDE_DIR "/usr/include"
+#define isabspath(fnameptr, tempcptr) \
+ ((*(tempcptr) = *(fnameptr)) == DIRCHAR)
+
+/* special */
+
+#ifdef SOS_EDOS
+# undef DEFAULT_INCLUDE_DIR
+# define DEFAULT_INCLUDE_DIR "3"
+# undef DIRCHAR
+# define DIRCHAR ':'
+# undef DIRSTRING
+# define DIRSTRING ":"
+# define AS09
+# undef EOL
+# define EOL 13
+# undef isabspath
+# define isabspath(fnameptr, tempcptr) \
+ ((*(tempcptr) = *(fnameptr)) >= '0' && *(tempcptr) <= '9' && \
+ (fnameptr)[1] == DIRCHAR)
+#endif
+
+#ifdef SOS_MSDOS
+# define COEOL 10
+# undef DEFAULT_INCLUDE_DIR
+# define DEFAULT_INCLUDE_DIR "\\usr\\include"
+# undef DIRCHAR
+# define DIRCHAR '\\'
+# undef DIRSTRING
+# define DIRSTRING "\\"
+# undef EOL
+# define EOL 13
+/*
+ Problems with newline on MSDOS (as usual).
+ Defining EOL as 10 (LF) handles LF-terminated lines as well as
+ CRLF-terminated lines, but escaped CRLF's do not work. The compiler
+ should handle the escapes better. (Perhaps it does now.)
+ Defining EOL as 13 (CR) handles CRLF-terminated lines but fails on
+ LF-terminated lines.
+*/
+#endif
+
+#ifdef TOS_EDOS
+# undef EOLTO
+# define EOLTO 13
+#endif
+
+/* don't let names dealt with here affect anything outside this file */
+
+#undef SOS_EDOS
+#undef SOS_MSDOS
diff --git a/bcc-bruce/output.c b/bcc-bruce/output.c
new file mode 100644
index 0000000..09e45a2
--- /dev/null
+++ b/bcc-bruce/output.c
@@ -0,0 +1,813 @@
+/* output.c - output and error handling for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "input.h"
+#include "os.h"
+#include "sizes.h"
+#include "table.h"
+
+#undef EXTERN
+#define EXTERN
+#include "output.h"
+
+#ifdef XENIX_AS
+# define HEXSTARTCHAR '/'
+#else
+# define HEXSTARTCHAR '$'
+#endif
+#define OUTBUFSIZE 2048
+#define opcodeleadin() /* outtab() for fussy assemblers */
+
+PRIVATE unsigned errcount; /* # errors in compilation */
+ /* depends on zero init */
+PRIVATE char hexdigits[] = "0123456789ABCDEF";
+PRIVATE char *outbuf;
+EXTERN char *outbufend; /* end of pair of output buffers */
+PRIVATE char *outbufmid;
+PRIVATE fd_t output;
+PRIVATE fastin_t outstage; /* depends on zero init */
+
+FORWARD void errorsummary P((void));
+FORWARD void errsum1 P((void));
+#ifdef MC6809
+#ifdef DEBUG
+FORWARD void outvaldigs P((uvalue_t num));
+#endif
+#endif
+
+PUBLIC void bugerror(message)
+char *message;
+{
+ error2error("compiler bug - ", message);
+}
+
+PUBLIC void closeout()
+{
+ char *saveoutptr;
+
+ if (outstage == 3)
+ {
+ saveoutptr = outbufptr;
+ flushout(); /* buffer from last stage */
+ outbufptr = saveoutptr;
+ }
+ outstage = 0; /* flush from top to current ptr */
+ flushout();
+ close(output);
+}
+
+/* error handler */
+
+PUBLIC void error(message)
+char *message;
+{
+ error2error(message, "");
+}
+
+/* error handler - concatenate 2 messages */
+
+PUBLIC void error2error(message1, message2)
+char *message1;
+char *message2;
+{
+ char *warning;
+
+ if (message1[0] == '%' && message1[1] == 'w')
+ {
+ message1 += 2;
+ warning = "warning: ";
+ }
+ else
+ {
+ ++errcount;
+ warning = "error: ";
+ }
+ if (output != 1)
+ {
+ char *old_outbuf;
+ char *old_outbufptr;
+ char *old_outbuftop;
+ fd_t old_output;
+ fastin_t old_outstage;
+ char smallbuf[81]; /* don't use heap - might be full or busy */
+
+ old_outbuf = outbuf;
+ old_outbufptr = outbufptr;
+ old_outbuftop = outbuftop;
+ old_output = output;
+ old_outstage = outstage;
+
+ outbufptr = outbuf = &smallbuf[0];
+ outbuftop = &smallbuf[sizeof smallbuf];
+ output = 1;
+ outstage = 0;
+ errorloc();
+ outstr(warning);
+ outstr(message1);
+ outstr(message2);
+ outnl();
+ flushout();
+
+ outbuf = old_outbuf;
+ outbufptr = old_outbufptr;
+ outbuftop = old_outbuftop;
+ output = old_output;
+ outstage = old_outstage;
+ }
+ comment();
+ errorloc();
+ outstr(warning);
+ outstr(message1);
+ outstr(message2);
+ outnl();
+}
+
+/* summarise errors */
+
+PRIVATE void errorsummary()
+{
+ if (errcount != 0)
+ {
+ outfail();
+ errsum1();
+ }
+ outnl();
+ comment();
+ errsum1();
+}
+
+PRIVATE void errsum1()
+{
+ outudec(errcount);
+ outnstr(" errors detected");
+}
+
+/* fatal error, exit early */
+
+PUBLIC void fatalerror(message)
+char *message;
+{
+ error(message);
+ finishup();
+}
+
+/* finish up compile */
+
+PUBLIC void finishup()
+{
+ if (!cppmode)
+ {
+ if (watchlc)
+ {
+ cseg();
+ outop0str("if *-.program.start-");
+ outnhex(getlc());
+ outfail();
+ outnstr("phase error");
+ outop0str("endif\n");
+ }
+#ifdef HOLDSTRINGS
+ dumpstrings();
+#endif
+ dumpglbs();
+ errorsummary();
+ }
+ closein();
+ closeout();
+ exit(errcount == 0 ? 0 : 1);
+}
+
+/* flush output file */
+
+PUBLIC void flushout()
+{
+ unsigned nbytes;
+
+ switch (outstage)
+ {
+ case 0:
+ nbytes = (unsigned) (outbufptr - outbuf);
+ outbufptr = outbuf;
+ break;
+ case 2:
+ nbytes = OUTBUFSIZE;
+ outbufptr = outbuf;
+ outbuftop = outbufmid;
+ outstage = 3;
+ break;
+ default:
+ nbytes = OUTBUFSIZE;
+ if (outstage == 1)
+ nbytes = 0;
+ outbufptr = outbufmid;
+ outbuftop = outbufend;
+ outstage = 2;
+ break;
+ }
+ if (nbytes != 0)
+ {
+ if (!orig_cppmode)
+ clearlabels(outbufptr, outbufptr + nbytes);
+ if (write(output, outbufptr, nbytes) != nbytes)
+ {
+ write(2, "output file error\n", 18);
+ closein();
+ close(output);
+ exit(1);
+ }
+ }
+}
+
+PUBLIC void initout()
+{
+ static char smallbuf[1];
+
+ outbufend = outbuftop = (outbuf = outbufptr = smallbuf) + sizeof smallbuf;
+ output = 1; /* standard output */
+}
+
+PUBLIC void limiterror(message)
+char *message;
+{
+ error2error("compiler limit exceeded - ", message);
+ finishup();
+}
+
+PUBLIC void openout(oname)
+char *oname;
+{
+ if (output != 1)
+ fatalerror("more than one output file");
+ if ((output = creat(oname, CREATPERMS)) < 0)
+ {
+ output = 1;
+ fatalerror("cannot open output");
+ }
+}
+
+/* print character */
+
+PUBLIC void outbyte(c)
+int c;
+{
+#if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1
+ register char *outp;
+
+ outp = outbufptr;
+ *outp++ = c;
+ outbufptr = outp;
+ if (outp >= outbuftop)
+ flushout();
+#else /* !C_CODE etc */
+
+#if __AS09__
+# asm
+ TFR X,D
+ LDX _outbufptr,PC
+ STB ,X+
+ STX _outbufptr,PC
+ CMPX _outbuftop,PC
+ LBHS CALL.FLUSHOUT
+# endasm
+#endif /* __AS09__ */
+
+#if __AS386_16__
+# asm
+# if !__FIRST_ARG_IN_AX__
+ pop dx
+ pop ax
+ dec sp
+ dec sp
+# else
+# if ARGREG != DREG
+ xchg ax,bx
+# endif
+# endif
+ mov bx,[_outbufptr]
+ mov [bx],al
+ inc bx
+ mov [_outbufptr],bx
+ cmp bx,[_outbuftop]
+ jae OUTBYTE.FLUSH
+# if !__FIRST_ARG_IN_AX__
+ jmp dx
+# else
+ ret
+# endif
+
+OUTBYTE.FLUSH:
+# if !__FIRST_ARG_IN_AX__
+ push dx
+# endif
+ br _flushout
+# endasm
+#endif /* __AS386_16__ */
+
+#if __AS386_32__
+# asm
+# if !__FIRST_ARG_IN_AX__
+ mov eax,_outbyte.c[esp]
+# else
+# if ARGREG != DREG
+ xchg eax,ebx
+# endif
+# endif
+ mov ecx,[_outbufptr]
+ mov [ecx],al
+ inc ecx
+ mov [_outbufptr],ecx
+ cmp ecx,[_outbuftop]
+ jae OUTBYTE.FLUSH
+ ret
+
+OUTBYTE.FLUSH:
+ br _flushout
+# endasm
+#endif /* __AS386_32__ */
+#endif /* C_CODE etc */
+}
+
+/* print comma */
+
+PUBLIC void outcomma()
+{
+ outbyte(',');
+}
+
+/* print line number in format ("# %u \"%s\"%s", nr, fname, str) */
+
+PUBLIC void outcpplinenumber(nr, fname, str)
+unsigned nr;
+char *fname;
+char *str;
+{
+ outstr("# ");
+ outudec(nr);
+ outstr(" \"");
+ outstr(fname);
+ outstr("\"");
+ outnstr(str);
+}
+
+/* print unsigned offset, hex format */
+
+PUBLIC void outhex(num)
+uoffset_t num;
+{
+#ifdef HEXSTARTCHAR
+ if (num >= 10)
+ outbyte(HEXSTARTCHAR);
+#endif
+ outhexdigs(num);
+#ifdef HEXENDCHAR
+ if (num >= 10)
+ outbyte(HEXENDCHAR);
+#endif
+}
+
+/* print unsigned offset, hex format with digits only (no hex designator) */
+
+PUBLIC void outhexdigs(num)
+register uoffset_t num;
+{
+ if (num >= 0x10)
+ {
+ outhexdigs(num / 0x10);
+ num %= 0x10;
+ }
+ outbyte(hexdigits[(fastin_t) num]);
+}
+
+/* print string terminated by EOL */
+
+PUBLIC void outline(s)
+char *s;
+{
+ register char *outp;
+ register char *rs;
+
+ outp = outbufptr;
+ rs = s;
+#ifdef COEOL
+ if (*rs == COEOL)
+ ++rs;
+#endif
+ do
+ {
+ *outp++ = *rs;
+ if (outp >= outbuftop)
+ {
+ outbufptr = outp;
+ flushout();
+ outp = outbufptr;
+ }
+ }
+ while (*rs++ != EOL);
+ outbufptr = outp;
+#ifdef COEOL
+ if (*rs == COEOL)
+ outbyte(COEOL);
+#endif
+}
+
+/* print minus sign */
+
+PUBLIC void outminus()
+{
+ outbyte('-');
+}
+
+/* print character, then newline */
+
+PUBLIC void outnbyte(byte)
+int byte;
+{
+ outbyte(byte);
+ outnl();
+}
+
+/* print unsigned offset, hex format, then newline */
+
+PUBLIC void outnhex(num)
+uoffset_t num;
+{
+ outhex(num);
+ outnl();
+}
+
+/* print newline */
+
+PUBLIC void outnl()
+{
+ if (watchlc)
+ {
+ outtab();
+ comment();
+ outhex(getlc());
+ }
+ outbyte('\n');
+}
+
+/* print opcode and newline, bump lc by 1 */
+
+PUBLIC void outnop1str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc();
+ outnl();
+}
+
+/* print opcode and newline, bump lc by 2 */
+
+PUBLIC void outnop2str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc2();
+ outnl();
+}
+
+/* print string, then newline */
+
+PUBLIC void outnstr(s)
+char *s;
+{
+ outstr(s);
+ outnl();
+}
+
+/* print opcode */
+
+PUBLIC void outop0str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+}
+
+/* print opcode, bump lc by 1 */
+
+PUBLIC void outop1str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc();
+}
+
+/* print opcode, bump lc by 2 */
+
+PUBLIC void outop2str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc2();
+}
+
+/* print opcode, bump lc by 3 */
+
+PUBLIC void outop3str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc3();
+}
+
+/* print plus sign */
+
+PUBLIC void outplus()
+{
+ outbyte('+');
+}
+
+/* print signed offset, hex format */
+
+PUBLIC void outshex(num)
+offset_t num;
+{
+ if (num >= -(maxoffsetto + 1))
+ {
+ outminus();
+ num = -num;
+ }
+ outhex((uoffset_t) num);
+}
+
+/* print string */
+
+PUBLIC void outstr(s)
+char *s;
+{
+#if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1
+ register char *outp;
+ register char *rs;
+
+ outp = outbufptr;
+ rs = s;
+ while (*rs)
+ {
+ *outp++ = *rs++;
+ if (outp >= outbuftop)
+ {
+ outbufptr = outp;
+ flushout();
+ outp = outbufptr;
+ }
+ }
+ outbufptr = outp;
+#else /* !C_CODE etc */
+
+#if __AS09__
+# asm
+ LEAU ,X
+ LDX _outbuftop,PC
+ PSHS X
+ LDX _outbufptr,PC
+ BRA OUTSTR.NEXT
+
+CALL.FLUSHOUT
+ PSHS U,B
+ STX _outbufptr,PC
+ LBSR _flushout
+ LDX _outbufptr,PC
+ LDY _outbuftop,PC
+ PULS B,U,PC
+
+OUTSTR.LOOP
+ STB ,X+
+ CMPX ,S
+ BLO OUTSTR.NEXT
+ BSR CALL.FLUSHOUT
+ STY ,S
+OUTSTR.NEXT
+ LDB ,U+
+ BNE OUTSTR.LOOP
+ STX _outbufptr,PC
+ LEAS 2,S
+# endasm
+#endif /* __AS09__ */
+
+#if __AS386_16__
+# asm
+# if !__CALLER_SAVES__
+ mov dx,di
+ mov cx,si
+# endif
+# if !__FIRST_ARG_IN_AX__
+ pop ax
+ pop si
+ dec sp
+ dec sp
+ push ax
+# else
+# if ARGREG == DREG
+ xchg si,ax
+# else
+ mov si,bx
+# endif
+# endif
+ mov di,[_outbufptr]
+ mov bx,[_outbuftop]
+ br OUTSTR.NEXT
+
+CALL.FLUSHOUT:
+ push si
+# if !__CALLER_SAVES__
+ push dx
+ push cx
+# endif
+ push ax
+ mov [_outbufptr],di
+ call _flushout
+ mov di,[_outbufptr]
+ mov bx,[_outbuftop]
+ pop ax
+# if !__CALLER_SAVES__
+ pop cx
+ pop dx
+#endif
+ pop si
+ ret
+
+OUTSTR.LOOP:
+ stosb
+ cmp di,bx
+ jb OUTSTR.NEXT
+ call CALL.FLUSHOUT
+OUTSTR.NEXT:
+ lodsb
+ test al,al
+ jne OUTSTR.LOOP
+ mov [_outbufptr],di
+# if !__CALLER_SAVES__
+ mov si,cx
+ mov di,dx
+# endif
+# endasm
+#endif /* __AS386_16__ */
+
+#if __AS386_32__
+# asm
+# if !__CALLER_SAVES__
+ mov edx,edi
+ push esi
+# define TEMPS 4
+# else
+# define TEMPS 0
+# endif
+# if !__FIRST_ARG_IN_AX__
+ mov esi,TEMPS+_outstr.s[esp]
+# else
+# if ARGREG == DREG
+ xchg esi,eax
+# else
+ mov esi,ebx
+# endif
+# endif
+ mov edi,[_outbufptr]
+ mov ecx,[_outbuftop]
+ br OUTSTR.NEXT
+
+CALL.FLUSHOUT:
+ push esi
+# if !__CALLER_SAVES__
+ push edx
+# endif
+ push eax
+ mov [_outbufptr],edi
+ call _flushout
+ mov edi,[_outbufptr]
+ mov ecx,[_outbuftop]
+ pop eax
+# if !__CALLER_SAVES__
+ pop edx
+# endif
+ pop esi
+ ret
+
+OUTSTR.LOOP:
+ stosb
+ cmp edi,ecx
+ jb OUTSTR.NEXT
+ call CALL.FLUSHOUT
+OUTSTR.NEXT:
+ lodsb
+ test al,al
+ jne OUTSTR.LOOP
+ mov [_outbufptr],edi
+# if !__CALLER_SAVES__
+ pop esi
+ mov edi,edx
+# endif
+# endasm
+#endif /* __AS386_32__ */
+#endif /* C_CODE etc */
+}
+
+/* print tab */
+
+PUBLIC void outtab()
+{
+ outbyte('\t');
+}
+
+/* print unsigned, decimal format */
+
+PUBLIC void outudec(num)
+unsigned num;
+{
+ char str[10 + 1];
+
+ str[sizeof str - 1] = 0;
+ outstr(pushudec(str + sizeof str - 1, num));
+}
+
+#ifdef MC6809
+#ifdef DEBUG
+
+/* print unsigned value, hex format (like outhex except value_t is larger) */
+
+PUBLIC void outuvalue(num)
+uvalue_t num;
+{
+#ifdef HEXSTARTCHAR
+ if (num >= 10)
+ outbyte(HEXSTARTCHAR);
+#endif
+ outvaldigs(num);
+#ifdef HEXENDCHAR
+ if (num >= 10)
+ outbyte(HEXENDCHAR);
+#endif
+}
+
+/* print unsigned value, hex format with digits only (no hex designator) */
+
+PRIVATE void outvaldigs(num)
+register uvalue_t num;
+{
+ if (num >= 0x10)
+ {
+ outvaldigs(num / 0x10);
+ num %= 0x10;
+ }
+ outbyte(hexdigits[(fastin_t) num]);
+}
+
+/* print signed value, hex format (like outshex except value_t is larger) */
+
+PUBLIC void outvalue(num)
+register value_t num;
+{
+ if (num < 0)
+ {
+ outminus();
+ num = -num;
+ }
+ outuvalue((uoffset_t) num);
+}
+
+#endif /* DEBUG */
+#endif /* MC6809 */
+
+/* push decimal digits of an unsigned onto a stack of chars */
+
+PUBLIC char *pushudec(s, num)
+register char *s;
+register unsigned num;
+{
+ register unsigned reduction;
+
+ while (num >= 10)
+ {
+ reduction = num / 10;
+ *--s = num - 10 * reduction + '0';
+ num = reduction;
+ }
+ *--s = num + '0';
+ return s;
+}
+
+PUBLIC void setoutbufs()
+{
+ if (!isatty(output))
+ {
+ outbufptr = outbuf = ourmalloc(2 * OUTBUFSIZE);
+#ifdef TS
+ts_s_outputbuf += 2 * OUTBUFSIZE;
+#endif
+ outbufmid = outbuftop = outbufptr + OUTBUFSIZE;
+ outbufend = outbufmid + OUTBUFSIZE;
+ outstage = 1;
+ }
+ if (watchlc)
+ outnstr(".program.start:\n"); /* kludge temp label */
+}
diff --git a/bcc-bruce/output.h b/bcc-bruce/output.h
new file mode 100644
index 0000000..6dc9cf1
--- /dev/null
+++ b/bcc-bruce/output.h
@@ -0,0 +1,14 @@
+/* output.h - output for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define OUTBYTE(ch) \
+ do {register char *outp = outbufptr; *outp++ = (ch); \
+ outbufptr = outp; if (outp >= outbuftop) flushout(); } while (0)
+
+EXTERN bool_t ctext; /* nonzero to intermix C source */
+ /* depends on zero init */
+EXTERN char *outbufptr; /* current spot in output buffer */
+EXTERN char *outbuftop; /* top of current output buffer */
+EXTERN bool_t watchlc; /* nonzero to print lc after every line */
+ /* depends on zero init */
diff --git a/bcc-bruce/parse.h b/bcc-bruce/parse.h
new file mode 100644
index 0000000..ab67f6c
--- /dev/null
+++ b/bcc-bruce/parse.h
@@ -0,0 +1,19 @@
+/* parse.h - parser for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* possible scope levels */
+
+#define ARGLEVEL 1
+#define GLBLEVEL 0
+#define MAXLEVEL 125
+#define MINLOCLEVEL 1
+
+/* possible node flags */
+
+#define LVALUE (1 << 0)
+
+EXTERN struct nodestruct *etptr; /* ptr to next entry in expression tree */
+EXTERN struct symstruct *gvarsymptr; /* gsymptr for last identifier declared */
+EXTERN scopelev_t level; /* scope level */
+ /* depends on zero init */
diff --git a/bcc-bruce/preproc.c b/bcc-bruce/preproc.c
new file mode 100644
index 0000000..59ed9dc
--- /dev/null
+++ b/bcc-bruce/preproc.c
@@ -0,0 +1,944 @@
+/* preprocessor routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "input.h"
+#include "os.h"
+#include "output.h"
+#include "parse.h"
+#include "sc.h"
+#include "scan.h"
+#include "table.h"
+#include "type.h"
+
+#define MAX_IF 32
+#define MAX__LINE__ 10 /* enough for 32-bit source unsigneds */
+#define MAX_MACRO 32
+#define MAX_PARAM 127 /* max char with no sign on all machines */
+
+/* Definition types. These are kept in the 'storage' member of struct
+ * symstruct and must be distinct from 'LOCAL' because dumplocs() doesn't
+ * check.
+ */
+enum
+{
+ DEF_LINE, /* __LINE__ keyword */
+ DEF_NONE /* nothing special */
+};
+
+struct ifstruct
+{
+ bool_t elseflag;
+ bool_t ifflag;
+};
+
+struct macroposition
+{
+ char *maclineptr;
+ char **paramlist;
+ char *paramspot;
+ bool_t inparam;
+ indn_t nparam;
+};
+
+PRIVATE char dummyparam[] = { EOL, 0 };
+PRIVATE fastin_t iflevel; /* depends on zero init */
+PRIVATE struct ifstruct ifstate;
+ /* elseflag depends on zero init */
+PRIVATE struct ifstruct ifstack[MAX_IF];
+
+PRIVATE struct macroposition macrostack[MAX_MACRO];
+
+FORWARD void asmcontrol P((void));
+FORWARD void control P((void));
+FORWARD void defineorundefinestring P((char *str, bool_pt defineflag));
+FORWARD void elsecontrol P((void));
+FORWARD void endif P((void));
+FORWARD fastin_pt getparnames P((void));
+FORWARD void ifcontrol P((sym_pt ifcase));
+FORWARD void undef P((void));
+
+/* asmcontrol() - process #asm */
+
+PRIVATE void asmcontrol()
+{
+ char treasure; /* to save at least one leading blank */
+
+ asmmode = TRUE;
+ if (orig_cppmode)
+ outstr("#asm\n");
+ else
+ dumplocs();
+ while (TRUE)
+ {
+ skipline();
+ skipeol();
+ if (eof)
+ {
+ eofin("#asm");
+ break;
+ }
+ if (SYMOFCHAR(ch) == SPECIALCHAR)
+ specialchar();
+ treasure = 0;
+ if (SYMOFCHAR(ch) == WHITESPACE)
+ treasure = ch;
+ blanks();
+ if (ch == '#')
+ {
+ if (ctext)
+ {
+ register char *lptr;
+
+ comment();
+ if (treasure != 0)
+ outbyte(treasure);
+ lptr = lineptr;
+ while (*lptr++ != EOL) /* XXX - handle COEOL too */
+ outbyte(ch);
+ outnl();
+ }
+ gch1();
+ docontrol();
+ if (!asmmode)
+ break;
+ }
+ else
+ {
+ if (treasure != 0)
+ outbyte(treasure);
+ while (ch != EOL) /* XXX - handle COEOL too */
+ {
+ outbyte(ch);
+ gch1();
+ }
+ outnl();
+ }
+ }
+ if (orig_cppmode)
+ outstr("#endasm"); /* nl is done by skipeol */
+}
+
+/* blanksident() - return nonzero if at blanks followed by an identifier */
+
+PUBLIC bool_pt blanksident()
+{
+ blanks();
+ return isident();
+}
+
+PUBLIC void checknotinif()
+{
+ while (iflevel != 0)
+ {
+ if (ifstate.ifflag)
+ eofin("true #conditional");
+ else
+ eofin("false #conditional");
+ endif();
+ }
+}
+
+/* control() - select and switch to control statement */
+
+PRIVATE void control()
+{
+ char sname[NAMESIZE + 1];
+ sym_t ctlcase;
+ struct symstruct *symptr;
+
+ sname[0] = '#'; /* prepare for bad control */
+ sname[1] = 0;
+ while (blanksident())
+ {
+ if ((gsymptr = findlorg(gsname)) == NULL ||
+ gsymptr->flags != DEFINITION)
+ {
+ strcat(sname, gsname);
+ break;
+ }
+ entermac();
+ }
+ if (sname[1] == 0 && ch == EOL)
+ return;
+ if (SYMOFCHAR(ch) == INTCONST)
+ return; /* XXX - # linenumber not implemented */
+ if ((symptr = findlorg(sname)) == NULL)
+ {
+ if (ifstate.ifflag)
+ error(" bad control");
+ return;
+ }
+ ctlcase = symptr->offset.offsym;
+ if (ifstate.ifflag == FALSE &&
+ (ctlcase < ELSECNTL || ctlcase > IFNDEFCNTL))
+ return;
+ switch (ctlcase)
+ {
+ case ASMCNTL:
+ asmcontrol();
+ break;
+ case DEFINECNTL:
+ define();
+ break;
+ case ELSECNTL:
+ elsecontrol();
+ break;
+ case ENDASMCNTL:
+ asmmode = FALSE;
+ break;
+ case ENDIFCNTL:
+ endif();
+ break;
+ case IFCNTL:
+ case IFDEFCNTL:
+ case IFNDEFCNTL:
+ ifcontrol(symptr->offset.offsym);
+ break;
+ case INCLUDECNTL:
+ include();
+ break;
+ case LINECNTL:
+ break; /* XXX - #line not implemented */
+ case UNDEFCNTL:
+ undef();
+ break;
+ }
+}
+
+/* define() - process #define */
+
+/*
+ MACRO storage.
+ A symbol recording the macro name is added to the symbol table.
+ This overrides all current scopes of the name (put at head of hash chain).
+ The flags are set to DEFINITION.
+ The indcount is 0 if no parameters, else 1 + number of parameters.
+ The offset field points to the macro string.
+ The macro string is null-terminated but EOL-sentineled.
+ It consists of EOL-terminated substrings followed by parameter numbers,
+ e.g., junk(x,y)=-x+y is stored as '-', EOL, 1, '+', EOL, 2, EOL, 0.
+ Here 1 is for the 1st parameter (start at 1 so 0 can terminate).
+ EOL acts as a sentinel for the scanner.
+ This choice works well because EOL cannot occur in a macro string.
+*/
+
+PUBLIC void define()
+{
+ char sname[NAMESIZE];
+ char quote;
+ struct symstruct **hashptr;
+ struct symstruct *locmark;
+ char *macstring;
+ fastin_t nparnames;
+ char *oldstring;
+ struct symstruct *symptr;
+
+ if (!blanksident())
+ {
+ error("illegal macro name");
+ return;
+ }
+ strcpy(sname, gsname); /* will overwrite gsname if parameters */
+ if (ch == '(')
+ {
+ locmark = locptr;
+ newlevel(); /* temp storage for parameter names */
+ nparnames = getparnames() + 1;
+ }
+ else
+ nparnames = 0;
+ blanks();
+ macstring = charptr;
+ quote = 0;
+ while (ch != EOL)
+ {
+ if (charptr >= char1top) /* check room for char and end of string */
+ macstring = growobject(macstring, 2);
+ if (nparnames && isident())
+ {
+ if ((symptr = findlorg(gsname)) != NULL &&
+ symptr->level == level)
+ {
+#ifdef TS
+++ts_n_macstring_param;
+ts_s_macstring += 2;
+#endif
+ *charptr++ = EOL; /* end current string */
+ *charptr++ = symptr->indcount; /* param to insert */
+ }
+ else
+ {
+ if (charptr + strlen(gsname) >= chartop) /* null too */
+ macstring = growobject(macstring, strlen(gsname) + 1);
+#ifdef TS
+++ts_n_macstring_ident;
+ts_s_macstring += strlen(gsname);;
+#endif
+ strcpy(charptr, gsname);
+ charptr += strlen(gsname); /* discard null */
+ }
+ continue;
+ }
+ if (ch == '\\')
+ {
+ gch1();
+ *charptr = '\\';
+ *(charptr + 1) = ch;
+#ifdef TS
+++ts_n_macstring_quoted;
+ts_s_macstring += 2;
+#endif
+ charptr += 2;
+ gch1();
+ continue;
+ }
+ if (quote)
+ {
+ if (ch == quote)
+ quote = 0;
+ }
+ else if (ch == '"' || ch == '\'')
+ quote = ch;
+ else if (ch == '/')
+ {
+ if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR)
+ {
+ gch1();
+ ch = *--lineptr = '/'; /* pushback */
+ }
+ if (*(lineptr + 1) == '*')
+ {
+ gch1();
+ skipcomment();
+ ch = *--lineptr = ' '; /* comment is space in modern cpp's */
+ }
+ }
+#ifdef TS
+++ts_n_macstring_ordinary;
+++ts_s_macstring;
+#endif
+ *charptr++ = ch;
+ gch1();
+ }
+ {
+ register char *rcp;
+
+ /* strip trailing blanks, but watch out for parameters */
+ for (rcp = charptr;
+ rcp > macstring && SYMOFCHAR(*(rcp - 1)) == WHITESPACE
+ && (--rcp == macstring || *(rcp - 1) != EOL); )
+ charptr = rcp;
+ }
+ if (charptr >= char1top)
+ macstring = growobject(macstring, 2);
+#ifdef TS
+++ts_n_macstring_term;
+ts_s_macstring += 2;
+#endif
+ *charptr++ = EOL;
+ *charptr++ = 0;
+ if (nparnames)
+ {
+ oldlevel();
+ locptr = locmark;
+ }
+ if (asmmode)
+ equ(sname, macstring);
+
+ if ((symptr = findlorg(sname)) != NULL && symptr->flags == DEFINITION)
+ {
+ if (strcmp(macstring, oldstring = symptr->offset.offp) != 0)
+ error("%wredefined macro");
+ if (strlen(macstring) > strlen(oldstring = symptr->offset.offp))
+ symptr->offset.offp = macstring;
+ else
+ {
+ strcpy(oldstring, macstring); /* copy if == to avoid test */
+ charptr = macstring;
+ }
+ return;
+ }
+ symptr = qmalloc(sizeof (struct symstruct) + strlen(sname));
+#ifdef TS
+++ts_n_defines;
+ts_s_defines += sizeof (struct symstruct) + strlen(sname);
+#endif
+ addsym(sname, vtype, symptr);
+ symptr->storage = DEF_NONE;
+ symptr->indcount = nparnames;
+ symptr->flags = DEFINITION;
+ symptr->level = GLBLEVEL;
+ symptr->offset.offp = macstring;
+ if (*(hashptr = gethashptr(sname)) != NULL)
+ {
+ symptr->next = *hashptr;
+ symptr->next->prev = &symptr->next;
+ }
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+}
+
+PRIVATE void defineorundefinestring(str, defineflag)
+char *str; /* "name[=def]" or "name def" */
+bool_pt defineflag;
+{
+ char *fakeline;
+ unsigned len;
+ bool_t old_eof;
+
+ len = strlen(str);
+ strcpy(fakeline = (char *) ourmalloc(3 + len + 2 + 2) + 3, str);
+ /* 3 pushback, 2 + 2 guards */
+#ifdef TS
+ts_s_fakeline += 3 + len + 2 + 2;
+ts_s_fakeline_tot += 3 + len + 2 + 2;
+#endif
+ {
+ register char *endfakeline;
+
+ endfakeline = fakeline + len;
+ endfakeline[0] = EOL; /* guards any trailing backslash */
+ endfakeline[1] = EOL; /* line ends here or before */
+ }
+ old_eof = eof;
+ eof = TRUE; /* valid after first EOL */
+ ch = *(lineptr = fakeline);
+ if (defineflag)
+ {
+ if (blanksident()) /* if not, let define() produce error */
+ {
+ blanks();
+ if (ch == '=')
+ *lineptr = ' ';
+ else if (ch == EOL)
+ {
+ register char *lptr;
+
+ lptr = lineptr;
+ lptr[0] = ' ';
+ lptr[1] = '1'; /* 2 extra were allocated for this & EOL */
+ lptr[2] = EOL;
+ }
+ }
+ ch = *(lineptr = fakeline);
+ define();
+ }
+ else
+ undef();
+ eof = old_eof;
+#ifdef TS
+ts_s_fakeline_tot -= len + 2 + 2;
+#endif
+ ourfree(fakeline - 3);
+}
+
+PUBLIC void definestring(str)
+char *str; /* "name[=def]" or "name def" */
+{
+ defineorundefinestring(str, TRUE);
+}
+
+/* docontrol() - process control statement, loop till "#if" is true */
+
+PUBLIC void docontrol()
+{
+ while (TRUE)
+ {
+ control();
+ skipline();
+ if (ifstate.ifflag)
+ return;
+ while (TRUE)
+ {
+ skipeol();
+ if (eof)
+ return;
+ blanks();
+ if (ch == '#')
+ {
+ gch1();
+ break;
+ }
+ skipline();
+ }
+ }
+}
+
+/* elsecontrol() - process #else */
+
+PRIVATE void elsecontrol()
+{
+ if (iflevel == 0)
+ {
+ error("else without if");
+ return;
+ }
+ ifstate.ifflag = ifstate.elseflag;
+ ifstate.elseflag = FALSE;
+}
+
+/* endif() - process #endif */
+
+PRIVATE void endif()
+{
+ if (iflevel == 0)
+ {
+ error("endif without if");
+ return;
+ }
+ {
+ register struct ifstruct *ifptr;
+
+ ifptr = &ifstack[--iflevel];
+ ifstate.elseflag = ifptr->elseflag;
+ ifstate.ifflag = ifptr->ifflag;
+ }
+}
+
+/* entermac() - switch line ptr to macro string */
+
+PUBLIC void entermac()
+{
+ char quote;
+ struct symstruct *symptr;
+ char **paramhead;
+ char **paramlist;
+ int ngoodparams;
+ int nparleft;
+ int lpcount;
+
+ if (maclevel >= MAX_MACRO)
+ {
+ limiterror("macros nested too deeply (33 levels)");
+ return;
+ }
+ symptr = gsymptr;
+ ngoodparams = 0;
+ paramhead = NULL;
+ if (symptr->indcount != 0)
+ {
+ nparleft = symptr->indcount - 1;
+ if (nparleft == 0)
+ paramhead = NULL;
+ else
+ paramhead = ourmalloc(sizeof *paramlist * nparleft);
+ paramlist = paramhead;
+#ifdef TS
+++ts_n_macparam;
+ts_s_macparam += sizeof *paramlist * nparleft;
+ts_s_macparam_tot += sizeof *paramlist * nparleft;
+#endif
+ blanks();
+ while (ch == EOL && !eof)
+ {
+ skipeol();
+ blanks();
+ }
+ if (ch != '(')
+ error("missing '('");
+ else
+ {
+ gch1();
+ while (nparleft)
+ {
+ --nparleft;
+ ++ngoodparams;
+ *(paramlist++) = charptr;
+ quote = 0;
+ lpcount = 1;
+ while (TRUE)
+ {
+ if (ch == '\\')
+ {
+ gch1();
+ if (charptr >= char1top)
+ *(paramlist - 1) = growobject(*(paramlist - 1), 2);
+#ifdef TS
+++ts_n_macparam_string_quoted;
+++ts_s_macparam_string;
+++ts_s_macparam_string_tot;
+#endif
+ *charptr++ = '\\';
+ }
+ else if (quote)
+ {
+ if (ch == quote)
+ quote = 0;
+ }
+ else if (ch == '"' || ch == '\'')
+ quote = ch;
+ else if (ch == '/')
+ {
+ if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR)
+ {
+ gch1();
+ ch = *--lineptr = '/'; /* pushback */
+ }
+ if (*(lineptr + 1) == '*')
+ {
+ gch1();
+ skipcomment();
+ ch = *--lineptr = ' '; /* pushback */
+ }
+ }
+ else if (ch == '(')
+ ++lpcount;
+ else if (ch == ')' && --lpcount == 0 ||
+ ch == ',' && lpcount == 1)
+ break;
+ if (ch == EOL)
+ ch = ' ';
+ if (charptr >= char1top)
+ *(paramlist - 1) = growobject(*(paramlist - 1), 2);
+#ifdef TS
+++ts_n_macparam_string_ordinary;
+++ts_s_macparam_string;
+++ts_s_macparam_string_tot;
+#endif
+ *charptr++ = ch;
+ if (*lineptr == EOL)
+ {
+ skipeol(); /* macro case disposed of already */
+ if (SYMOFCHAR(ch) == SPECIALCHAR)
+ specialchar();
+ if (eof)
+ break;
+ }
+ else
+ gch1();
+ }
+#ifdef TS
+++ts_n_macparam_string_term;
+++ts_s_macparam_string;
+++ts_s_macparam_string_tot;
+#endif
+ *charptr++ = EOL;
+ {
+ register char *newparam;
+ register char *oldparam;
+ unsigned size;
+
+ oldparam = *(paramlist - 1);
+ size = (/* size_t */ unsigned) (charptr - oldparam);
+ newparam = ourmalloc(size);
+#ifdef TS
+ts_s_macparam_string_alloced += size;
+ts_s_macparam_string_alloced_tot += size;
+#endif
+ memcpy(newparam, oldparam, size);
+ *(paramlist - 1) = newparam;
+#ifdef TS
+ts_s_macparam_string_tot -= charptr - oldparam;
+#endif
+ charptr = oldparam;
+ }
+ if (ch == ',')
+ gch1();
+ else
+ break;
+ }
+ }
+ blanks();
+ while (ch == EOL && !eof)
+ {
+ skipeol();
+ blanks();
+ }
+ if (eof)
+ eofin("macro parameter expansion");
+ if (nparleft)
+ {
+ error("too few macro parameters");
+ do
+ *(paramlist++) = dummyparam;
+ while (--nparleft);
+ }
+ if (ch == ')')
+ gch1();
+ else if (ch == ',')
+ {
+ error("too many macro parameters");
+
+ /* XXX - should read and discard extra parameters. Also check
+ * for eof at end.
+ */
+ while (ch != ')')
+ {
+ if (ch == EOL)
+ {
+ skipeol();
+ if (eof)
+ break;
+ continue;
+ }
+ gch1();
+ }
+ }
+ else
+ error("missing ')'");
+ }
+
+ if (symptr->storage == DEF_LINE)
+ {
+ char *str;
+
+ str = pushudec(symptr->offset.offp + MAX__LINE__, input.linenumber);
+ memcpy(symptr->offset.offp, str, /* size_t */
+ (unsigned) (symptr->offset.offp + MAX__LINE__ + 1 + 1 - str));
+ }
+
+ {
+ register struct macroposition *mpptr;
+
+ mpptr = &macrostack[maclevel];
+ mpptr->paramlist = paramhead;
+ mpptr->maclineptr = lineptr;
+ ch = *(lineptr = symptr->offset.offp);
+ mpptr->inparam = FALSE;
+ mpptr->nparam = ngoodparams;
+ ++maclevel;
+ }
+/*
+ comment();
+ outstr("MACRO (level ");
+ outudec((unsigned) maclevel);
+ outstr(") ");
+ outline(lineptr);
+*/
+}
+
+/* getparnames() - get parameter names during macro definition, return count */
+
+PRIVATE fastin_pt getparnames()
+{
+ fastin_t nparnames;
+ struct symstruct *symptr;
+
+ nparnames = 0;
+ gch1();
+ while (blanksident())
+ {
+ if ((symptr = findlorg(gsname)) != NULL &&
+ symptr->level == level)
+ error("repeated parameter");
+ symptr = addloc(gsname, itype);
+ if (nparnames >= MAX_PARAM)
+ limiterror("too many macro parameters (128)");
+ else
+ ++nparnames; /* number params from 1 */
+ symptr->indcount = nparnames; /* param number */
+ blanks();
+ if (ch == ',')
+ gch1();
+ }
+ if (ch != ')')
+ error("missing ')'");
+ else
+ gch1();
+ return nparnames;
+}
+
+/* ifcontrol - process #if, #ifdef, #ifndef */
+
+PRIVATE void ifcontrol(ifcase)
+sym_pt ifcase;
+{
+ bool_t iftrue;
+ struct symstruct *symptr;
+
+ if (iflevel >= MAX_IF)
+ {
+ limiterror("#if's nested too deeply (33 levels)");
+ return;
+ }
+ {
+ register struct ifstruct *ifptr;
+
+ ifptr = &ifstack[iflevel++];
+ ifptr->elseflag = ifstate.elseflag;
+ ifptr->ifflag = ifstate.ifflag;
+ ifstate.elseflag = FALSE; /* prepare for !(if now)||(if future)*/
+ }
+ if (ifstate.ifflag)
+ {
+ if ((sym_t) ifcase != IFCNTL)
+ {
+ iftrue = FALSE;
+ if (blanksident() && (symptr = findlorg(gsname)) != NULL &&
+ symptr->flags == DEFINITION)
+ iftrue = TRUE;
+ }
+ else
+ {
+ incppexpr = TRUE;
+ nextsym();
+ iftrue = constexpression() != 0;
+ incppexpr = FALSE;
+ }
+ if (!iftrue && (sym_t) ifcase != IFNDEFCNTL ||
+ iftrue && (sym_t) ifcase == IFNDEFCNTL)
+ {
+ ifstate.elseflag = TRUE;
+ ifstate.ifflag = FALSE;
+ }
+ }
+}
+
+/* ifinit() - initialise if state */
+
+PUBLIC void ifinit()
+{
+ ifstate.ifflag = TRUE;
+}
+
+/* leavemac() - leave current and further macro substrings till not at end */
+
+PUBLIC void leavemac()
+{
+ register struct macroposition *mpptr;
+
+ do
+ {
+ mpptr = &macrostack[maclevel - 1];
+ if (mpptr->inparam)
+ {
+ lineptr = ++mpptr->paramspot;
+ mpptr->inparam = FALSE;
+ }
+ else
+ {
+ ch = *++lineptr; /* gch1() would mess up next param == EOL-1 */
+ if (ch != 0)
+ {
+ mpptr->paramspot = lineptr;
+ lineptr = mpptr->paramlist[ch - 1];
+ mpptr->inparam = TRUE;
+ }
+ else
+ {
+ lineptr = mpptr->maclineptr;
+ if (mpptr->nparam != 0)
+ {
+ register char **paramlist;
+
+#ifdef TS
+ts_s_macparam_tot -= sizeof *paramlist * mpptr->nparam;
+#endif
+ paramlist = mpptr->paramlist;
+ do
+{
+#ifdef TS
+ts_s_macparam_string_alloced_tot -= strchr(*paramlist, EOL) - *paramlist + 1;
+#endif
+ ourfree(*paramlist++);
+}
+ while (--mpptr->nparam != 0);
+ ourfree(mpptr->paramlist);
+ }
+ --maclevel;
+ }
+ }
+ }
+ while ((ch = *lineptr) == EOL && maclevel != 0);
+}
+
+PUBLIC void predefine()
+{
+ definestring("__BCC__ 1");
+ definestring("__LINE__ 0123456789"); /* MAX__LINE__ digits */
+ findlorg("__LINE__")->storage = DEF_LINE;
+}
+
+PUBLIC char *savedlineptr()
+{
+ return macrostack[0].maclineptr;
+}
+
+PUBLIC void skipcomment()
+{
+/* Skip current char, then everything up to '*' '/' or eof. */
+
+ gch1();
+ do
+ {
+ while (TRUE)
+ {
+ {
+ register char *reglineptr;
+
+ reglineptr = lineptr;
+ symofchar['*'] = SPECIALCHAR;
+ while (SYMOFCHAR(*reglineptr) != SPECIALCHAR)
+ ++reglineptr;
+ symofchar['*'] = STAR;
+ lineptr = reglineptr;
+ if (*reglineptr == '*')
+ break;
+ ch = *reglineptr;
+ }
+ specialchar();
+ if (ch == EOL)
+ {
+ skipeol();
+ if (eof)
+ break;
+ }
+ else if (ch != '*')
+ gch1();
+ }
+ gch1();
+ if (eof)
+ {
+ eofin("comment");
+ return;
+ }
+ }
+ while (ch != '/');
+ gch1();
+}
+
+/* skipline() - skip rest of line */
+
+PUBLIC void skipline()
+{
+ while (TRUE)
+ {
+ blanks();
+ if (ch == EOL)
+ return;
+ if (ch == '\\')
+ {
+ gch1();
+ if (ch == EOL) /* XXX - I think blanks() eats \EOL */
+ return;
+ gch1(); /* XXX - escape() better? */
+ }
+ else if (ch == '"' || ch == '\'')
+ {
+ stringorcharconst();
+ charptr = constant.value.s;
+ }
+ else
+ gch1();
+ }
+}
+
+/* undef() - process #undef */
+
+PRIVATE void undef()
+{
+ struct symstruct *symptr;
+
+ if (blanksident() && (symptr = findlorg(gsname)) != NULL &&
+ symptr->flags == DEFINITION)
+ delsym(symptr);
+}
+
+PUBLIC void undefinestring(str)
+char *str;
+{
+ defineorundefinestring(str, FALSE);
+}
diff --git a/bcc-bruce/preserve.c b/bcc-bruce/preserve.c
new file mode 100644
index 0000000..0103a43
--- /dev/null
+++ b/bcc-bruce/preserve.c
@@ -0,0 +1,215 @@
+/* preserve.c - preserve opererands or registers in use for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "type.h"
+
+/* change stack ptr without changing condition codes */
+
+PUBLIC void changesp(newsp, absflag)
+offset_t newsp;
+bool_pt absflag;
+{
+ if (newsp != sp || (bool_t) absflag && switchnow != NULL)
+ {
+#ifdef FRAMEPOINTER
+ if (newsp != framep || !(bool_t) absflag && switchnow != NULL)
+ {
+ outleasp();
+ if (!(bool_t) absflag && switchnow != NULL)
+ outswoffset(newsp);
+ else
+ outoffset(newsp - framep);
+ outindframereg();
+ outnl();
+ }
+ else
+ regtransfer(FRAMEREG, STACKREG);
+ sp = newsp;
+ if (framep == 0)
+ bugerror("no frame pointer");
+#else
+# ifdef I8088
+ outleasp();
+ outoffset(newsp - sp);
+ outindstackreg();
+ outnl();
+# else
+ modstk(newsp); /* this should preserve CC */
+# endif
+#endif /* FRAMEPOINTER */
+ }
+}
+
+/* load source to any while preserving target */
+
+PUBLIC void loadpres(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regmark;
+
+ if (target->storage & ALLDATREGS)
+ {
+ if (source->type->scalar & CHAR)
+ {
+ push(target);
+ load(source, DREG);
+ }
+ else
+ load(source, getindexreg());
+ }
+ else
+ {
+ regmark = reguse;
+ reguse |= target->storage;
+ loadany(source);
+ reguse = regmark;
+ }
+}
+
+/* change stack ptr */
+
+PUBLIC void modstk(newsp)
+offset_t newsp;
+{
+ if (newsp != sp)
+ {
+#ifdef FRAMEPOINTER
+ if (newsp != framep || framep == 0 || switchnow != NULL)
+ addconst(newsp - sp, STACKREG);
+ else
+ regtransfer(FRAMEREG, STACKREG);
+#else
+# ifdef I8088
+ addconst(newsp - sp, STACKREG);
+# else
+ outleasp();
+ outoffset(newsp - sp);
+ outncspregname();
+# endif
+#endif
+ sp = newsp;
+ }
+}
+
+/* preserve target without changing source */
+
+PUBLIC void pres2(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ if (target->storage & allregs)
+ {
+ if (target->storage & (allregs - allindregs) /* XXX */ ||
+ target->indcount == 0 && target->type->scalar & (DLONG | RSCALAR))
+ push(target); /* XXX - perhaps not float */
+ else if (((target->storage | reguse) & allindregs) == allindregs)
+ {
+ loadpres(target, source);
+ push(target);
+ }
+ else
+ reguse |= target->storage;
+ }
+}
+
+/* preserve source */
+
+PUBLIC void preserve(source)
+struct symstruct *source;
+{
+ if (source->storage & allregs)
+ {
+ if (source->storage & (allregs - allindregs) /* XXX */ ||
+ ((source->storage | reguse) & allindregs) == allindregs)
+ push(source);
+ else
+ reguse |= source->storage;
+ }
+}
+
+/* preserve lvalue target without changing source or target */
+
+PUBLIC store_pt preslval(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt regpushed;
+
+ if (target->indcount == 0)
+ reguse &= ~target->storage;
+ else
+ reguse = (target->storage | reguse) & allindregs;
+ if (!((source->type->scalar | target->type->scalar) & (DLONG | RSCALAR))
+ || reguse != allindregs)
+ return 0; /* XXX - perhaps not float */
+ reguse = source->storage | target->storage; /* free one other than s/t */
+ pushreg(regpushed = getindexreg());
+ reguse = ~(store_t) regpushed & allindregs;
+ return regpushed;
+}
+
+PUBLIC void recovlist(reglist)
+store_pt reglist;
+{
+ poplist(reglist);
+ reguse |= (store_t) reglist;
+}
+
+#ifdef I8088
+PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5};
+ /* CONSTANT, BREG, ax = DREG, bx = INDREG0, si = INDREG1, di = INDREG2 */
+ /* LOCAL, GLOBAL, STACKREG, cx = DATREG1, dx = DATREG2 */
+#endif
+#ifdef MC6809
+PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 3, 2};
+ /* CONSTANT, BREG, DREG, XREG = INDREG0, UREG = INDREG1, YREG = INDREG2 */
+#endif
+
+PUBLIC void savereturn(savelist, saveoffset)
+store_pt savelist;
+offset_t saveoffset;
+{
+ store_t reg;
+ smalin_t *regoffptr;
+ offset_t spoffset;
+
+ if (savelist == 0)
+ return;
+#ifdef MC6809 /* must check this */
+ if (savelist == XREG || savelist == INDREG1)
+ saveoffset -= accregsize; /* patch for DREG/YREG not saved */
+#endif
+ for (reg = 1, regoffptr = regoffset; reg != 0; ++regoffptr, reg <<= 1)
+ if (reg & savelist)
+ {
+ outstore();
+ spoffset = saveoffset + *regoffptr * maxregsize;
+#ifdef I8088
+# ifdef FRAMEPOINTER
+ if (switchnow != NULL)
+ outswoffset(spoffset);
+ else
+ outoffset(spoffset - framep);
+ outindframereg();
+# else
+ outoffset(spoffset - sp);
+ outindstackreg();
+# endif
+ outncregname(reg);
+#endif
+#ifdef MC6809
+ if (reg == YREG)
+ bumplc();
+ outregname(reg);
+ outtab();
+ outoffset(spoffset - sp);
+ outncspregname();
+#endif
+ }
+}
diff --git a/bcc-bruce/proto.h b/bcc-bruce/proto.h
new file mode 100644
index 0000000..00dc116
--- /dev/null
+++ b/bcc-bruce/proto.h
@@ -0,0 +1,399 @@
+/* proto.h - extern functions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#if __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+/* assign.c */
+void assign P((struct symstruct *source, struct symstruct *target));
+void cast P((struct typestruct *type, struct symstruct *target));
+void extend P((struct symstruct *target));
+
+/* codefrag.c */
+void adjsp P((label_t label));
+void clrBreg P((void));
+void comment P((void));
+void ctoi P((void));
+void defbyte P((void));
+void deflong P((uoffset_t value));
+void defword P((void));
+void defdword P((void));
+void even P((void));
+void negDreg P((void));
+void comDreg P((void));
+void outadd P((void));
+void outaddsp P((void));
+void outcalladr P((void));
+void outcmp P((void));
+void outdec P((void));
+void outdword P((void));
+void outfail P((void));
+void outinc P((void));
+void outindleft P((void));
+void outindright P((void));
+void outindstackreg P((void));
+void outldaccum P((void));
+void outldmulreg P((void));
+void outlea P((void));
+void outleasp P((void));
+void outload P((void));
+void outmulmulreg P((void));
+void outopsep P((void));
+void outpshs P((void));
+void outpuls P((void));
+void outreturn P((void));
+void outstore P((void));
+void outsub P((void));
+void outtest P((void));
+void outword P((void));
+void sctoi P((void));
+void stoi P((void));
+void ustoi P((void));
+void outABX P((void));
+void outdirectpage P((void));
+void outextended P((void));
+void outncspregname P((void));
+void outindframereg P((void));
+void adc0 P((void));
+void addconst P((offset_t offset, store_pt reg));
+void adjlc P((offset_t offset, store_pt reg));
+void andconst P((offset_t offset));
+void bssseg P((void));
+label_t casejump P((void));
+void common P((char *name));
+void cseg P((void));
+void defnulls P((uoffset_t nullcount));
+label_t defstr P((char *sptr, char *stop, bool_pt dataflag));
+bool_pt diveasy P((value_t divisor, bool_pt uflag));
+void dpseg P((void));
+void dseg P((void));
+void equ P((char *name, char *string));
+void equlab P((label_t label, offset_t offset));
+void globl P((char *name));
+void import P((char *name));
+void itol P((store_pt reg));
+void lcommlab P((label_t label));
+void lcommon P((char *name));
+void lea P((offset_t offset, store_pt sourcereg, store_pt targreg));
+void loadconst P((offset_t offset, store_pt reg));
+int lslconst P((value_t shift, store_pt reg));
+int lsrconst P((value_t shift, store_pt reg, bool_pt uflag));
+bool_pt modeasy P((value_t divisor, bool_pt uflag));
+bool_pt muleasy P((uvalue_t factor, store_pt reg));
+void negreg P((store_pt reg));
+char *opstring P((op_pt op));
+void outccname P((char *name));
+void outhiaccum P((void));
+void outimmadr P((offset_t offset));
+void outimadj P((offset_t offset, store_pt targreg));
+void outimmed P((void));
+void outjumpstring P((void));
+void outnccname P((char *name));
+void outncimmadr P((offset_t offset));
+void outoffset P((offset_t offset));
+void public P((char *name));
+void private P((char *name));
+void regexchange P((store_pt sourcereg, store_pt targreg));
+void regtransfer P((store_pt sourcereg, store_pt targreg));
+void sbc0 P((void));
+void set P((char *name, offset_t value));
+void sl1 P((store_pt reg));
+void slconst P((value_t shift, store_pt reg));
+void srconst P((value_t shift, bool_pt uflag));
+void uitol P((store_pt reg));
+void restoreopreg P((void));
+void saveopreg P((void));
+
+/* debug.c */
+void dbitem P((struct symstruct *item));
+void dbtype P((struct typestruct *type));
+void debug P((struct nodestruct *exp));
+void debugswap P((void));
+
+/* declare.c */
+void colon P((void));
+void decllist P((void));
+void lparen P((void));
+void needvarname P((void));
+void program P((void));
+void rbrace P((void));
+void rbracket P((void));
+void rparen P((void));
+void semicolon P((void));
+struct typestruct *typename P((void));
+
+/* express.c */
+struct nodestruct *assignment_exp P((void));
+struct nodestruct *expression P((void));
+
+/* exptree.c */
+struct nodestruct *castnode P((struct typestruct *type,
+ struct nodestruct *nodeptr));
+void etreeinit P((void));
+struct nodestruct *leafnode P((struct symstruct *source));
+struct nodestruct *node P((op_pt t, struct nodestruct *p1,
+ struct nodestruct *p2));
+
+/* floatop.c */
+bool_pt f_indirect P((struct symstruct *target));
+void float1op P((op_pt op, struct symstruct *source));
+void floatop P((op_pt op, struct symstruct *source, struct symstruct *target));
+void fpush P((struct symstruct *source));
+void justpushed P((struct symstruct *target));
+
+/* function.c */
+void call P((char *name));
+void function P((struct symstruct *source));
+void ldregargs P((void));
+void loadretexpression P((void));
+void listo P((struct symstruct *target, offset_t lastargsp));
+void listroot P((struct symstruct *target));
+void popframe P((void));
+void reslocals P((void));
+void ret P((void));
+
+/* gencode.c */
+void bileaf P((struct nodestruct *exp));
+fastin_pt bitcount P((uvalue_t number));
+void codeinit P((void));
+fastin_pt highbit P((uvalue_t number));
+void makeleaf P((struct nodestruct *exp));
+
+/* genloads.c */
+void addoffset P((struct symstruct *source));
+void address P((struct symstruct *source));
+void exchange P((struct symstruct *source, struct symstruct *target));
+store_pt getindexreg P((void));
+void indexadr P((struct symstruct *source, struct symstruct *target));
+void indirec P((struct symstruct *source));
+void load P((struct symstruct *source, store_pt targreg));
+void loadany P((struct symstruct *source));
+void loadreg P((struct symstruct *source, store_pt targreg));
+void makelessindirect P((struct symstruct *source));
+void movereg P((struct symstruct *source, store_pt targreg));
+void onstack P((struct symstruct *target));
+void outadr P((struct symstruct *adr));
+void outcregname P((store_pt reg));
+void outncregname P((store_pt reg));
+void outnregname P((store_pt reg));
+void outregname P((store_pt reg));
+void outshortregname P((store_pt reg));
+void pointat P((struct symstruct *target));
+void poplist P((store_pt reglist));
+void push P((struct symstruct *source));
+void pushlist P((store_pt reglist));
+void pushreg P((store_pt reg));
+void storereg P((store_pt sourcereg, struct symstruct *target));
+void struc P((struct symstruct *source, struct symstruct *target));
+void transfer P((struct symstruct *source, store_pt targreg));
+
+/* glogcode.c */
+void cmp P((struct symstruct *source, struct symstruct *target,
+ ccode_t *pcondtrue));
+void condop P((struct nodestruct *exp));
+void jumpfalse P((struct nodestruct *exp, label_t label));
+void jumptrue P((struct nodestruct *exp, label_t label));
+void logop P((struct nodestruct *exp));
+
+/* hardop.c */
+void add P((struct symstruct *source, struct symstruct *target));
+void incdec P((op_pt op, struct symstruct *source));
+void neg P((struct symstruct *target));
+void not P((struct symstruct *target));
+void op1 P((op_pt op, struct symstruct *source, struct symstruct *target));
+void ptrsub P((struct symstruct *source, struct symstruct *target));
+void sub P((struct symstruct *source, struct symstruct *target));
+
+/* input.c */
+void closein P((void));
+void errorloc P((void));
+void gch1 P((void));
+void include P((void));
+void openio P((int argc, char **argv));
+void skipeol P((void));
+void specialchar P((void));
+
+/* label.c */
+void bumplc P((void));
+void bumplc2 P((void));
+void bumplc3 P((void));
+void clearfunclabels P((void));
+void clearlabels P((char *patchbuf, char *patchtop));
+void clearswitchlabels P((void));
+uoffset_t getlc P((void));
+void deflabel P((label_t label));
+label_t gethighlabel P((void));
+label_t getlabel P((void));
+void jump P((label_t label));
+void lbranch P((ccode_pt cond, label_t label));
+struct symstruct *namedlabel P((void));
+void outcond P((ccode_pt cond));
+void outlabel P((label_t label));
+void outnlabel P((label_t label));
+void sbranch P((ccode_pt cond, label_t label));
+void unbumplc P((void));
+
+/* loadexp.c */
+value_t constexpression P((void));
+void initexpression P((struct typestruct *type));
+struct typestruct *loadexpression P((store_pt targreg,
+ struct typestruct *targtype));
+
+/* longop.c */
+void longop P((op_pt op, struct symstruct *source, struct symstruct *target));
+void long1op P((op_pt op, struct symstruct *target));
+void outlongendian P((void));
+
+/* output.c */
+void bugerror P((char *message));
+void closeout P((void));
+void error P((char *message));
+void error2error P((char *message1, char *message2));
+void fatalerror P((char *message));
+void finishup P((void));
+void flushout P((void));
+void limiterror P((char *message));
+void initout P((void));
+void openout P((char *oname));
+void outbyte P((int ch));
+void outcomma P((void));
+void outcpplinenumber P((unsigned nr, char *fname, char *str));
+void outhex P((uoffset_t num));
+void outhexdigs P((uoffset_t num));
+void outline P((char *s));
+void outminus P((void));
+void outnl P((void));
+void outnbyte P((int byte));
+void outnhex P((uoffset_t num));
+void outnop1str P((char *s));
+void outnop2str P((char *s));
+void outnstr P((char *s));
+void outop0str P((char *s));
+void outop1str P((char *s));
+void outop2str P((char *s));
+void outop3str P((char *s));
+void outplus P((void));
+void outshex P((offset_t num));
+void outstr P((char *s));
+void outtab P((void));
+void outudec P((unsigned num));
+void outuvalue P((uvalue_t num));
+void outvalue P((value_t num));
+char *pushudec P((char *s, unsigned num));
+void setoutbufs P((void));
+
+/* preproc.c */
+void blanks P((void));
+bool_pt blanksident P((void));
+void checknotinif P((void));
+void define P((void));
+void definestring P((char *str));
+void docontrol P((void));
+void entermac P((void));
+void ifinit P((void));
+void leavemac P((void));
+void predefine P((void));
+char *savedlineptr P((void));
+void skipcomment P((void));
+void skipline P((void));
+void undefinestring P((char *str));
+
+/* preserve.c */
+void changesp P((offset_t newsp, bool_pt absflag));
+void loadpres P((struct symstruct *source, struct symstruct *target));
+void modstk P((offset_t newsp));
+void pres2 P((struct symstruct *source, struct symstruct *target));
+void preserve P((struct symstruct *source));
+store_pt preslval P((struct symstruct *source, struct symstruct *target));
+void recovlist P((store_pt reglist));
+void savereturn P((store_pt savelist, offset_t saveoffset));
+
+/* sc.c */
+int main P((int argc, char **argv));
+
+/* scan.c */
+void cppscan P((void));
+void eofin P((char *message));
+bool_pt isident P((void));
+void nextsym P((void));
+void stringorcharconst P((void));
+
+/* softop.c */
+void softop P((op_pt op, struct symstruct *source, struct symstruct *target));
+
+/* state.c */
+void compound P((void));
+void outswoffset P((offset_t offset));
+void outswstacklab P((void));
+
+/* table.c */
+struct symstruct *addglb P((char *name, struct typestruct *type));
+struct symstruct *addloc P((char *name, struct typestruct *type));
+struct symstruct *addlorg P((char *name, struct typestruct *type));
+void addsym P((char *name, struct typestruct *type,
+ struct symstruct *symptr));
+struct symstruct *constsym P((value_t intconst));
+void delsym P((struct symstruct *symptr));
+void dumpglbs P((void));
+void dumplocs P((void));
+void dumpstrings P((void));
+struct symstruct *exprsym P((struct symstruct *symptr));
+struct symstruct *findlorg P((char *name));
+struct symstruct *findstruct P((char *name));
+struct symstruct **gethashptr P((char *sname));
+void growheap P((unsigned size));
+void *growobject P((void *object, unsigned extra));
+label_t holdstr P((char *sptr, char *stop));
+void newlevel P((void));
+void oldlevel P((void));
+void ourfree P((void *ptr));
+void *ourmalloc P((unsigned nbytes));
+void outofmemoryerror P((char *message));
+void *qmalloc P((unsigned size));
+void swapsym P((struct symstruct *sym1, struct symstruct *sym2));
+void syminit P((void));
+
+/* type.c */
+struct typestruct *addstruct P((char *structname));
+struct typestruct *iscalartotype P((scalar_pt scalar));
+struct typestruct *newtype P((void));
+void outntypechar P((struct typestruct *type));
+struct typestruct *pointype P((struct typestruct *type));
+struct typestruct *prefix P((constr_pt constructor, uoffset_t size,
+ struct typestruct *type));
+struct typestruct *promote P((struct typestruct *type));
+struct typestruct *tounsigned P((struct typestruct *type));
+void typeinit P((void));
+
+/* library - fcntl.h */
+int creat P((const char *_path, int _mode));
+int open P((const char *_path, int _oflag, ...));
+
+/* library - stdlib.h */
+double atof P((const char *_str));
+void exit P((int _status));
+void free P((void *_ptr));
+void *malloc P((unsigned _nbytes));
+void *realloc P((void *_ptr, unsigned _nbytes));
+
+/* library - string.h */
+void *memcpy P((void *_t, const void *_s, unsigned _length));
+void *memset P((void *_s, int _c, unsigned _nbytes));
+char *strcat P((char *_target, const char *_source));
+char *strchr P((const char *_s, int _ch));
+int strcmp P((const char *_s1, const char *_s2));
+char *strcpy P((char *_target, const char *_source));
+unsigned strlen P((const char *_s));
+char *strncpy P((char *_target, const char *_source, unsigned _maxlength));
+char *strrchr P((const char *_s, int _ch));
+
+/* library - unistd.h */
+int close P((int _fd));
+int isatty P((int _fd));
+long lseek P((int _fd, long _offset, int _whence));
+int read P((int _fd, char *_buf, unsigned _nbytes));
+int write P((int _fd, char *_buf, unsigned _nbytes));
diff --git a/bcc-bruce/reg.h b/bcc-bruce/reg.h
new file mode 100644
index 0000000..822bda7
--- /dev/null
+++ b/bcc-bruce/reg.h
@@ -0,0 +1,139 @@
+/* reg.h - registers for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ The compiler generates "addresses" of the form
+ indirect(indcount) (rx + offset)
+ where
+ rx is a machine register (possibly null)
+ n is the indirection count (possibly 0)
+ offset is a constant.
+ It does not support more complicated formats like
+ indirect(indcount) (rx + index * scale + offset).
+
+ The register is coded as bit flag in the storage component of
+ the symbol structure. This allows groups of registers to be tested
+ using bitwise "&". Throughout the compiler, the group of these bit
+ flags has the type reg_t. If there are only a few registers, reg_t
+ can be an unsigned char. It must be unsigned if the high bit is
+ used, to avoid sign extension problems. For bootstrapping the compiler
+ from a compiler with no unsigned char, the unsigned type should be
+ used instead (with a signifigant waste of storage).
+
+ The bit flags should really be defined as ((reg_t) whatever) but
+ then they would not (necessarily) be constant expressions and couldn't
+ be used in switch selectors or (worse) preprocessor expressions.
+
+ The CONSTANT and GLOBAL (non-) register bits are almost
+ equivalent. A constant with nonzero indirection is marked as a
+ GLOBAL and not a CONSTANT. This makes it easier to test for a constant
+ CONSTANT. Globals which are formed in this way are converted to
+ constants if their indirection count is reset to 0 (by & operator).
+*/
+
+/* register bit flags */
+
+#define NOSTORAGE 0x000 /* structure/union member offsets */
+#define CONSTANT 0x001 /* offsets are values */
+#define BREG 0x002
+#define DREG 0x004
+#define INDREG0 0x008
+#define INDREG1 0x010
+#define INDREG2 0x020
+#define LOCAL 0x040
+#define GLOBAL 0x080 /* offsets from storage name or 0 */
+#define CCREG CONSTANT /* arg to PSHS/PULS functions only */
+#ifdef I8088
+# ifdef FRAMEPOINTER
+# define FRAMEREG LOCAL
+# endif
+# define STACKREG 0x100
+# define DATREG1 0x200
+# define DATREG2 0x400
+# define DATREG1B 0x800
+#endif
+#ifdef MC6809
+# define DPREG LOCAL /* arg to PSHS/PULS functions only */
+# define PCREG GLOBAL /* arg to PSHS/PULS functions only */
+#endif
+
+/* data for pushing and pulling registers */
+
+#define MINREGCHAR 'A'
+#ifdef I8088
+# define FLAGSREGCHAR 'f'
+# define pushchar() pushlist(AXREG)
+#endif
+#ifdef MC6809
+# define pushchar() pushlist(BREG)
+#endif
+
+/* special registers */
+
+#ifdef I8088
+# define ALREG BREG
+# define AXREG DREG
+# define DXREG DATREG2
+# define MULREG DATREG1B
+# define SHIFTREG DATREG1B
+#endif
+#ifdef MC6809
+# define XREG INDREG0 /* XREG is special for ABX in index & switch */
+# define YREG INDREG2 /* XREG and YREG allow LEA (Z test) in cmp() */
+#endif
+
+/* groups of registers */
+
+#define ALLDATREGS (BREG|DREG)
+#define CHARREGS BREG
+#define MAXREGS 1 /* number of data registers */
+#define WORKDATREGS (BREG|DREG)
+
+/* function call and return registers */
+
+#define ARGREG RETURNREG /* for (1st) argument */
+#define LONGARGREGS LONGRETURNREGS /* for long or float arg */
+#define LONGRETURNREGS (INDREG0|LONGREG2)
+#define LONGREG2 DREG
+#ifdef I8088
+# define LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
+# define RETURNREG DREG
+#endif
+#ifdef MC6809
+# define RETURNREG INDREG0
+#endif
+
+/* registers which can be pulled as a group with the program counter */
+/* to perform an efficient function return */
+
+#ifdef MC6809
+#define JUNK1REGS BREG /* 1 bytes locals to discard */
+#define JUNK2REGS INDREG2
+#define JUNK3REGS (BREG|INDREG2)
+#define JUNK4REGS (INDREG1|INDREG2)
+#endif
+
+/* registers which can be pushed as a group with the first argument */
+/* to perform an efficient function startup */
+
+#ifdef MC6809
+# define LOC1REGS CCREG /* 1 bytes local to allocate */
+# define LOC2REGS DREG
+# define LOC3REGS (CCREG|DREG)
+# define LOC4REGS (CCREG|DREG|DPREG)
+# endif
+
+/* registers to be used by software operations */
+
+#define OPREG INDREG0 /* 2nd reg for software ops (1st is DREG) */
+#define OPWORKREG INDREG2 /* 3rd register for software ops */
+
+/* maximum indirection count for 1 instruction */
+
+#ifdef I8088
+# define MAXINDIRECT 1
+#endif
+#ifdef MC6809
+# define MAXINDIRECT 2
+#endif
diff --git a/bcc-bruce/sc.h b/bcc-bruce/sc.h
new file mode 100644
index 0000000..c17536a
--- /dev/null
+++ b/bcc-bruce/sc.h
@@ -0,0 +1,27 @@
+/* sc.h - storage classes for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef MC6809
+#define DIRECTPAGE 0x01 /* modifier on global to show in dpseg */
+#endif
+#define EXTERNAL 0x02 /* external */
+#define STATIC 0x04
+
+/* symbols with flags above the 1st initialised value are not to be dumped */
+
+#define MAXDUMPFLAG 0x07
+#define INITIALIZED 0x08 /* modifier on global to show initialized */
+#define LABELLED 0x10 /* modifier on static to show labelled */
+ /* and on STRING to show labelled */
+
+/* remaining "flags" are numbers, not flags */
+/* they are disjoint from all combinations of flags above */
+/* except STRING => LABELLED (and no other flags) */
+
+#define DEFINITION 0x20 /* #defined name */
+#define KEYWORD 0x40 /* reserved word for C */
+#define STRUCTNAME 0x60 /* struct/union name or member name */
+#define REGVAR 0x80 /* register variable */
+#define TEMP 0xa0 /* temporary on stack expression eval */
+#define STRING 0xc0 /* string constant (=> LABELLED) */
diff --git a/bcc-bruce/scan.c b/bcc-bruce/scan.c
new file mode 100644
index 0000000..0baecf8
--- /dev/null
+++ b/bcc-bruce/scan.c
@@ -0,0 +1,806 @@
+/* scan.c - lexical analyser for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define GCH1() do { if (SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) specialchar(); } while (0)
+
+#include "const.h"
+#include "types.h"
+#include "input.h"
+#include "os.h"
+#include "output.h"
+#include "sc.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "scan.h"
+
+PUBLIC sym_t symofchar[256] =
+{
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, WHITESPACE, SPECIALCHAR, BADCHAR,
+ WHITESPACE, SPECIALCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ WHITESPACE, LOGNOTOP, STRINGCONST, CONTROL, /* !"# */
+ BADCHAR, MODOP, AMPERSAND, CHARCONST, /* $%&' */
+ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */
+ COMMA, HYPHEN, FLOATCONST, SLASH, /* ,-./ */
+
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */
+ INTCONST, INTCONST, COLON, SEMICOLON, /* 89:; */
+ LTOP, ASSIGNOP, GTOP, CONDOP, /* <=>? */
+
+ BADCHAR, IDENT, IDENT, IDENT, /* @ABC */
+ IDENT, IDENT, IDENT, IDENT, /* DEFG */
+ IDENT, IDENT, IDENT, IDENT, /* HIJK */
+ IDENT, IDENT, IDENT, IDENT, /* LMNO */
+ IDENT, IDENT, IDENT, IDENT, /* PQRS */
+ IDENT, IDENT, IDENT, IDENT, /* TUVW */
+ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */
+ SPECIALCHAR, RBRACKET, EOROP, IDENT, /* \]^_ */
+
+ BADCHAR, IDENT, IDENT, IDENT, /* `abc */
+ IDENT, IDENT, IDENT, IDENT, /* defg */
+ IDENT, IDENT, IDENT, IDENT, /* hijk */
+ IDENT, IDENT, IDENT, IDENT, /* lmno */
+ IDENT, IDENT, IDENT, IDENT, /* pqrs */
+ IDENT, IDENT, IDENT, IDENT, /* tuvw */
+ IDENT, IDENT, IDENT, LBRACE, /* xyz{ */
+ OROP, RBRACE, NOTOP, BADCHAR, /* |}~ */
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR
+};
+
+FORWARD void getident P((void));
+FORWARD void intconst P((void));
+FORWARD void ppnumber P((void));
+PRIVATE void newstringorcharconst P((void));
+
+/* skip white space up to end of line (skip EOL's if in comments) */
+
+PUBLIC void blanks()
+{
+ register char *reglineptr;
+
+ while (TRUE)
+ {
+ reglineptr = lineptr;
+ while (SYMOFCHAR(*reglineptr) == WHITESPACE)
+ ++reglineptr;
+ lineptr = reglineptr;
+ if (SYMOFCHAR(ch = *reglineptr) == SPECIALCHAR)
+ {
+ specialchar();
+ if (ch == EOL)
+ return;
+ if (SYMOFCHAR(ch) == WHITESPACE)
+ continue;
+ reglineptr = lineptr;
+ }
+ if (*reglineptr != '/')
+ return;
+ if (SYMOFCHAR(*(reglineptr + 1)) == SPECIALCHAR)
+ {
+ ch = *(lineptr = reglineptr + 1);
+ specialchar();
+ ch = *(reglineptr = --lineptr) = '/'; /* pushback */
+ }
+ if (*(reglineptr + 1) != '*')
+ return;
+ gch1();
+ skipcomment();
+ }
+}
+
+PUBLIC void cppscan()
+{
+ while (TRUE)
+ {
+ switch (SYMOFCHAR(ch))
+ {
+ case CHARCONST:
+ case STRINGCONST:
+ stringorcharconst();
+ *charptr = 0; /* room reserved */
+ outstr(constant.value.s); /* XXX - embedded null would kill it */
+ charptr = constant.value.s;
+ break;
+ case CONTROL:
+ gch1();
+ if (maclevel != 0)
+ {
+ error("# in a macro: not preprocessed"); /* XXX? */
+ break;
+ }
+ else
+ {
+ cppmode = FALSE;
+ docontrol();
+ cppmode = TRUE;
+ break;
+ }
+ case SLASH:
+ gch1();
+ if (ch == '*')
+ {
+ skipcomment();
+ break;
+ }
+ outbyte('/');
+ break;
+ case FLOATCONST:
+ gch1();
+ if (SYMOFCHAR(ch) == INTCONST)
+ {
+ --lineptr;
+ ch = '.'; /* pushback */
+ ppnumber();
+ outstr(constant.value.s);
+ charptr = constant.value.s;
+ }
+ else
+ outbyte('.');
+ break;
+ case IDENT:
+ getident();
+ if ((gsymptr = findlorg(gsname)) != NULL)
+ {
+ if (gsymptr->flags == DEFINITION)
+ {
+ entermac();
+ break;
+ }
+ }
+ outstr(gsname);
+ break;
+ case INTCONST:
+ ppnumber();
+ outstr(constant.value.s);
+ charptr = constant.value.s;
+ break;
+ case SPECIALCHAR:
+ specialchar(); /* XXX - this is necessary because entermac
+ * and skipeol can leave lineptr at a special
+ * char although GCH1 cannot. entermac would
+ * be easy to fix, but too many places already
+ * have to handle the extra work after skipeol
+ * for other reasons.
+ */
+ if (ch == EOL)
+ {
+ skipeol();
+ if (eof)
+ return;
+ break;
+ }
+#ifdef COEOL
+ if (ch == COEOL)
+ {
+ gch1();
+ break;
+ }
+#endif
+ if (SYMOFCHAR(ch) != SPECIALCHAR)
+ break; /* specialchar advanced the input */
+ /* must be '\\' */
+ default:
+ OUTBYTE(ch);
+ GCH1();
+ break;
+ }
+ }
+}
+
+PUBLIC void eofin(message)
+char *message;
+{
+ error2error("end of file in ", message);
+}
+
+/* get identifier in gsname == gs2name + 2 */
+
+PRIVATE void getident()
+{
+ register int c;
+ register char *idptr;
+ register int length;
+ register char *reglineptr;
+
+ idptr = gsname;
+ length = NAMESIZE;
+ reglineptr = lineptr;
+ c = ch;
+more:
+ do
+ {
+ *idptr++ = c;
+ c = (unsigned char) *++reglineptr;
+ }
+ while (symofchar[c] <= MAXIDSYM && --length != 0);
+ ch = c;
+ *idptr = 0;
+ lineptr = reglineptr;
+ if (symofchar[c] == SPECIALCHAR)
+ {
+ specialchar();
+ if (SYMOFCHAR(ch) <= MAXIDSYM && length != 0)
+ {
+ reglineptr = lineptr;
+ c = ch;
+ goto more;
+ }
+ }
+}
+
+/* return nonzero if at an identifier */
+
+PUBLIC bool_pt isident()
+{
+ if (SYMOFCHAR(ch) != IDENT)
+ return FALSE;
+ getident();
+ return TRUE;
+}
+
+PRIVATE void intconst()
+{
+ fastin_t base;
+ fastin_t digit;
+ register char *digptr;
+ fastin_t lcount;
+ fastin_t ucount;
+ bool_t dflag;
+
+ ppnumber();
+ digptr = charptr = constant.value.s;
+ if (*digptr == '0')
+ {
+ if (digptr[1] != 'x' && digptr[1] != 'X')
+ base = 8;
+ else
+ {
+ base = 16;
+ digptr += 2;
+ }
+ }
+ else
+ base = 10;
+ dflag = FALSE;
+ if (*digptr == 0)
+ error("constant has no digits");
+ if (base != 16)
+ {
+ while (SYMOFCHAR(*digptr) == INTCONST)
+ ++digptr;
+ if (*digptr == '.')
+ {
+ dflag = TRUE;
+ ++digptr;
+ while (SYMOFCHAR(*digptr) == INTCONST)
+ ++digptr;
+ }
+ if (*digptr == 'E' || *digptr == 'e')
+ {
+ dflag = TRUE;
+ ++digptr;
+ if (*digptr == '+' || *digptr == '-')
+ ++digptr;
+ if (SYMOFCHAR(*digptr) != INTCONST)
+ error("exponent has no digits");
+ while (SYMOFCHAR(*digptr) == INTCONST)
+ ++digptr;
+ }
+ }
+ if (dflag)
+ {
+ constant.type = dtype;
+ digit = *digptr;
+ *digptr = 0;
+ constant.value.d = atof(constant.value.s);
+ *digptr = digit;
+ if (digit == 'F' || digit == 'f')
+ {
+ ++digptr;
+ constant.type = fltype;
+ constant.value.d = (float) constant.value.d;
+ }
+ sym = FLOATCONST;
+ if (*digptr != 0)
+ error("junk at end of floating point constant");
+ return;
+ }
+ if (base != 16)
+ digptr = constant.value.s;
+ constant.value.v = 0;
+ while (*digptr >= '0')
+ {
+ digit = *digptr;
+ if (digit > '9')
+ {
+ if (base != 16)
+ break;
+ if (digit >= 'a' && digit <= 'f')
+ digit = digit + (-'a' + '0' + 10);
+ else if (digit >= 'A' && digit <= 'F')
+ digit = digit + (-'A' + '0' + 10);
+ else
+ break;
+ }
+ constant.value.v = base * constant.value.v + (digit - '0');
+ ++digptr;
+ }
+ ucount = lcount = 0;
+ while (TRUE)
+ {
+ if (*digptr == 'L' || *digptr == 'l')
+ ++lcount;
+ else if (*digptr == 'U' || *digptr == 'u')
+ ++ucount;
+ else
+ break;
+ ++digptr;
+ }
+ if (lcount > 1)
+ error("more than one 'L' in integer constant");
+ if (ucount > 1)
+ error("more than one 'U' in integer constant");
+ if (constant.value.v <= maxintto && lcount == 0 && ucount == 0)
+ constant.type = itype;
+ else if (constant.value.v <= maxuintto && lcount == 0
+ && (base != 10 || ucount != 0))
+ constant.type = uitype;
+ else if (constant.value.v <= maxlongto && ucount == 0)
+ constant.type = ltype;
+ else
+ constant.type = ultype;
+ if (*digptr != 0)
+ error("junk at end of integer constant");
+}
+
+PUBLIC void nextsym()
+{
+ static char lastch;
+ register char *reglineptr;
+
+ while (TRUE) /* exit with short, fast returns */
+ {
+ reglineptr = lineptr;
+ while ((sym = SYMOFCHAR(*reglineptr)) == WHITESPACE)
+ ++reglineptr;
+ lastch = *reglineptr;
+ if (SYMOFCHAR(ch = *(lineptr = reglineptr + 1)) == SPECIALCHAR
+ && sym != SPECIALCHAR)
+ specialchar();
+ switch (sym)
+ {
+ case CHARCONST:
+ --lineptr;
+ ch = lastch; /* pushback */
+ stringorcharconst();
+ newstringorcharconst();
+ if (charptr == constant.value.s)
+ {
+ charptr = constant.value.s;
+ error("empty character constant");
+ constant.value.v = 0;
+ }
+ else
+ {
+ if (charptr != constant.value.s + 1)
+ error("character constant too long");
+ charptr = constant.value.s;
+ constant.value.v = *constant.value.s & CHMASKTO;
+ }
+ constant.type = itype;
+ return;
+ case CONTROL:
+ if (maclevel != 0)
+ {
+ error("# in a macro: not preprocessed"); /* XXX? */
+ return;
+ }
+ else
+ {
+ docontrol();
+ break;
+ }
+ case FLOATCONST:
+ if (SYMOFCHAR(ch) == INTCONST)
+ {
+ --lineptr;
+ ch = lastch;
+ intconst();
+ }
+ else
+ sym = STRUCELTOP;
+ return;
+ case IDENT:
+ --lineptr;
+ ch = lastch;
+ getident();
+ if ((gsymptr = findlorg(gsname)) != NULL)
+ {
+ if (gsymptr->flags == DEFINITION)
+ {
+ entermac();
+ break;
+ }
+ if (gsymptr->flags == KEYWORD)
+ sym = gsymptr->offset.offsym;
+ }
+ return;
+ case INTCONST:
+ --lineptr;
+ ch = lastch;
+ intconst();
+ return;
+ case SPECIALCHAR:
+ ch = *(lineptr = reglineptr);
+ specialchar();
+ if (ch == EOL)
+ {
+ if (incppexpr)
+ {
+ sym = SEMICOLON;
+ return;
+ }
+ skipeol();
+ if (eof)
+ {
+ sym = EOFSYM;
+ return;
+ }
+ break;
+ }
+ if (SYMOFCHAR(ch) != SPECIALCHAR)
+ break;
+ gch1();
+ /* fall through to BADCHAR case */
+ case BADCHAR:
+ error("illegal character");
+ break;
+ case STRINGCONST:
+ --lineptr;
+ ch = lastch; /* pushback */
+ stringorcharconst();
+ newstringorcharconst();
+#ifdef TS
+ ts_n_string += charptr - constant.value.s;
+#endif
+ return;
+ case COLON: /* could be COLONOP or in label */
+ case COMMA: /* could be COMMAOP or in list */
+ case CONDOP:
+ case LBRACE:
+ case LBRACKET:
+ case LPAREN:
+ case NOTOP:
+ case RBRACE:
+ case RBRACKET:
+ case RPAREN:
+ case SEMICOLON:
+ return;
+ case ASSIGNOP:
+ if (ch == '=')
+ {
+ sym = EQOP;
+ gch1();
+ }
+ return;
+ case ADDOP:
+ if (ch == '+')
+ {
+ sym = INCSYM; /* PREINCOP or POSINCOP */
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = ADDABOP;
+ gch1();
+ }
+ return;
+ case HYPHEN: /* NEGOP or SUBOP or decoded below */
+ if (ch == '-')
+ {
+ sym = DECSYM; /* PREDECOP or POSTDECOP */
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = SUBABOP;
+ gch1();
+ }
+ else if (ch == '>')
+ {
+ sym = STRUCPTROP;
+ gch1();
+ }
+ return;
+ case STAR: /* INDIRECTOP or MULOP or as below */
+ if (ch == '=')
+ {
+ sym = MULABOP;
+ gch1();
+ }
+ return;
+ case SLASH:
+ if (ch == '*')
+ {
+ skipcomment();
+ break;
+ }
+ if (ch == '=')
+ {
+ sym = DIVABOP;
+ gch1();
+ }
+ else
+ sym = DIVOP;
+ return;
+ case MODOP:
+ if (ch == '=')
+ {
+ sym = MODABOP;
+ gch1();
+ }
+ return;
+ case LTOP:
+ if (ch == '=')
+ {
+ sym = LEOP;
+ gch1();
+ }
+ else if (ch == '<')
+ {
+ gch1();
+ if (ch == '=')
+ {
+ sym = SLABOP;
+ gch1();
+ }
+ else
+ {
+ sym = SLOP;
+ }
+ }
+ return;
+ case GTOP:
+ if (ch == '=')
+ {
+ sym = GEOP;
+ gch1();
+ }
+ else if (ch == '>')
+ {
+ gch1();
+ if (ch == '=')
+ {
+ sym = SRABOP;
+ gch1();
+ }
+ else
+ {
+ sym = SROP;
+ }
+ }
+ return;
+ case AMPERSAND: /* ADDRESSOP or ANDOP or as below */
+ if (ch == '&')
+ {
+ sym = LOGANDOP;
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = ANDABOP;
+ gch1();
+ }
+ return;
+ case EOROP:
+ if (ch == '=')
+ {
+ sym = EORABOP;
+ gch1();
+ }
+ return;
+ case OROP:
+ if (ch == '|')
+ {
+ sym = LOGOROP;
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = ORABOP;
+ gch1();
+ }
+ return;
+ case LOGNOTOP:
+ if (ch == '=')
+ {
+ sym = NEOP;
+ gch1();
+ }
+ return;
+ }
+ }
+}
+
+PRIVATE void ppnumber()
+{
+ constant.value.s = charptr;
+ while (TRUE)
+ {
+ if (charptr >= char1top)
+ constant.value.s = growobject(constant.value.s, 2);
+ *charptr++ = ch;
+ if (ch == 'E' || ch == 'e')
+ {
+ gch1();
+ if (ch == '+' || ch == '-')
+ continue;
+ }
+ else
+ GCH1();
+ if (SYMOFCHAR(ch) > MAXPPNUMSYM)
+ break;
+ }
+ *charptr = 0;
+}
+
+PUBLIC void stringorcharconst()
+{
+ char terminator;
+
+ constant.value.s = charptr;
+ terminator = ch;
+ while (TRUE)
+ {
+ if (charptr >= char3top)
+ constant.value.s = growobject(constant.value.s, 4);
+ *charptr++ = ch;
+ if (ch == '\\')
+ {
+ gch1();
+ if (ch == EOL)
+ {
+ if (!orig_cppmode)
+ eofin("escape sequence");
+ break;
+ }
+ *charptr++ = ch;
+ }
+ GCH1();
+ if (ch == EOL)
+ {
+ if (!orig_cppmode)
+ error(terminator == '"' ? "end of line in string constant"
+ : "end of line in character constant");
+ break;
+ }
+ if (ch == terminator)
+ {
+ *charptr++ = terminator;
+ gch1();
+ break;
+ }
+ }
+}
+
+PRIVATE void newstringorcharconst()
+{
+ char *endinptr;
+ int escvalue;
+ fastin_t maxdigits;
+ register char *inptr;
+ register char *outptr;
+
+ outptr = constant.value.s;
+ inptr = charptr - 1;
+ if (inptr == outptr || *inptr != *outptr)
+ endinptr = charptr; /* not properly terminated */
+ else
+ endinptr = inptr;
+ inptr = outptr + 1;
+ while (inptr != endinptr)
+ {
+ if (*inptr == '\\')
+ {
+ if (++inptr == endinptr)
+ break; /* error reported already */
+ if (*inptr >= '0' && *inptr < '8')
+ {
+ escvalue = 0;
+ maxdigits = 3;
+ do
+ {
+ escvalue = 8 * escvalue + *inptr - '0';
+ ++inptr;
+ }
+ while (--maxdigits != 0 && *inptr >= '0' && *inptr < '8');
+ --inptr;
+ *outptr++ = escvalue;
+ }
+ else switch (*inptr)
+ {
+ case '"':
+ case '\'':
+ case '\\':
+ *outptr++ = *inptr;
+ break;
+ case 'a':
+ *outptr++ = 7;
+ break;
+ case 'b':
+ *outptr++ = 8;
+ break;
+ case 'f':
+ *outptr++ = 12;
+ break;
+ case 'n':
+ *outptr++ = EOLTO;
+ break;
+ case 'r':
+ *outptr++ = 13;
+ break;
+ case 't':
+ *outptr++ = 9;
+ break;
+ case 'v':
+ *outptr++ = 11;
+ break;
+ default:
+ error("%wnonstandard escape sequence");
+ *outptr++ = *inptr;
+ break;
+ }
+ }
+ else
+ *outptr++ = *inptr;
+ ++inptr;
+ }
+ charptr = outptr;
+}
diff --git a/bcc-bruce/scan.h b/bcc-bruce/scan.h
new file mode 100644
index 0000000..5333e96
--- /dev/null
+++ b/bcc-bruce/scan.h
@@ -0,0 +1,201 @@
+/* scan.h - scanner for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define NAMESIZE 64 /* limit on identifier lengths */
+#define SYMOFCHAR(ch) (symofchar[(unsigned char) (ch)])
+
+/* scanner codes */
+
+enum
+{
+/* The first group of entries consists of all the values that occur in the
+ switch for cppscan().
+*/
+ IDENT,
+ INTCONST,
+#define MAXIDSYM INTCONST /* IDENT and INTCONST must be the only
+ * symofchar[] entries below this */
+ FLOATCONST,
+#define MAXPPNUMSYM FLOATCONST /* IDENT, INTCONST and FLOATCONST must be the
+ * only symofchar[] entries below this */
+ CHARCONST,
+ CONTROL,
+ SLASH,
+ SPECIALCHAR,
+ STRINGCONST,
+
+/* The next group of entries are all the rest of the values that occur in
+ symofchar[] and so in the switch for nextsym().
+*/
+ AMPERSAND, /* ADDRESSOP or ANDOP */
+ BADCHAR,
+ COLON, /* also COLONOP */
+ COMMA, /* also COMMAOP */
+ DECSYM, /* PREDECOP or POSTDECOP */
+ EOFSYM,
+ HYPHEN, /* NEGOP or SUBOP */
+ INCSYM, /* PREINCOP or POSTINCOP */
+ LBRACE,
+ LBRACKET,
+ LPAREN,
+ RBRACE,
+ RBRACKET,
+ RPAREN,
+ SEMICOLON,
+ STAR, /* INDIRECTOP or MULOP */
+ WHITESPACE,
+
+/* The next group of entries consists of all operator codes. These codes must
+ be contiguous so they can be used as (offsetted) array indexes. The group
+ is ordered by operator-precedence (this is not necessary). The first part
+ of it overlaps the previous group.
+*/
+
+/* Assign-abops (level 1) belong here but are at end to improve switch. */
+
+#define FIRSTOP CONDOP
+ CONDOP, /* level 2 */
+
+ OROP, /* level 5 */
+
+ EOROP, /* level 6 */
+
+ ANDOP, /* level 7 */
+
+ GTOP, /* level 9 */
+ LTOP,
+
+ ADDOP, /* level 11 */
+
+ DIVOP, /* level 12 */
+ MODOP,
+
+ LOGNOTOP, /* level 13 */
+ NOTOP,
+
+ STRUCELTOP, /* level 14 */
+ STRUCPTROP,
+
+/* End of symbols that appear in symofchar[]. */
+
+ ASSIGNOP, /* level 1 - assign ops must be contiguous */
+ ADDABOP,
+ ANDABOP,
+ DIVABOP,
+ EORABOP,
+ MODABOP,
+ MULABOP,
+ ORABOP,
+ SLABOP,
+ SRABOP,
+ SUBABOP,
+
+ COMMAOP, /* level 0 */
+
+ COLONOP, /* level 2 */
+
+ LOGOROP, /* level 3 */
+
+ LOGANDOP, /* level 4 */
+
+ EQOP, /* level 8 */
+ NEOP,
+
+ GEOP, /* level 9 */
+ LEOP,
+
+ SLOP, /* level 10 */
+ SROP,
+
+ SUBOP, /* level 11 */
+
+ MULOP, /* level 12 */
+
+ ADDRESSOP, /* level 13 */
+ CASTOP,
+ INDIRECTOP,
+ NEGOP,
+ PREDECOP,
+ PREINCOP,
+ POSTDECOP,
+ POSTINCOP,
+
+ FUNCOP, /* level 14 */
+ LISTOP,
+ ROOTLISTOP,
+
+ LEAF, /* special */
+ PTRADDABOP,
+ PTRADDOP,
+ PTRSUBOP,
+
+/* end of operator codes (they must stay contiguous) */
+
+#define LASTOP PTRSUBOP
+
+ ENUMDECL,
+ NULLDECL,
+ STRUCTDECL,
+ TYPEDECL,
+ TYPEDEFNAME,
+ UNIONDECL,
+ UNSIGNDECL,
+
+ AUTODECL,
+ EXTERNDECL,
+ REGDECL,
+ STATICDECL,
+ TYPEDEFDECL,
+
+ BREAKSYM,
+ CASESYM,
+ CONTSYM,
+ DEFAULTSYM,
+ DEFINEDSYM,
+ DOSYM,
+ ELSESYM,
+ FORSYM,
+ GOTOSYM,
+ IFSYM,
+ RETURNSYM,
+ SIZEOFSYM,
+ SWITCHSYM,
+ WHILESYM,
+
+ ASMCNTL,
+ DEFINECNTL,
+ ENDASMCNTL,
+ INCLUDECNTL,
+ LINECNTL,
+ UNDEFCNTL,
+
+ ELIFCNTL, /* "IF" controls must be contiguous */
+ ELSECNTL,
+ ENDIFCNTL,
+ IFCNTL,
+ IFDEFCNTL,
+ IFNDEFCNTL
+};
+
+EXTERN op_pt arg1op; /* LISTOP, or ROOTLISTOP if arg1inreg */
+EXTERN struct
+{
+ union
+ {
+ char *s;
+ value_t v;
+ double d;
+ }
+ value;
+ struct typestruct *type;
+}
+ constant; /* value of last constant scanned */
+ /* sym tells type */
+EXTERN char funcname[NAMESIZE]; /* name of current function for unique labels */
+EXTERN char gs2name[2 + NAMESIZE]; /* 2 reserved for namespace keys */
+#define gsname (gs2name + 2) /* before last identifier */
+EXTERN struct symstruct *gsymptr; /* symbol ptr for last identifier */
+EXTERN bool_t incppexpr; /* nonzero while scanning cpp expression */
+EXTERN sym_t sym; /* current symbol */
+extern sym_t symofchar[]; /* table to convert chars to their symbols */
diff --git a/bcc-bruce/sizes.h b/bcc-bruce/sizes.h
new file mode 100644
index 0000000..df0d141
--- /dev/null
+++ b/bcc-bruce/sizes.h
@@ -0,0 +1,50 @@
+/* sizes.h - target scalar type sizes for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ the compiler is not very portable in this area
+ it only directly supports I8088-I80386 and MC6809
+ it assumes
+ sizeof(source long) >= sizeof(target long)
+ usual register size = int
+ long = 2 int sizes
+*/
+
+#define CHBITSTO 8 /* bits in a character */
+#define CHMASKTO 0xFF /* mask to reduce SOURCE int to TARGET uchar */
+#define INT16BITSTO 16 /* not accessed in non-16 bit case */
+#define INT32BITSTO 32 /* not accessed in non-32 bit case */
+#define MAXINTBITSTO 32 /* max bits in an integer (var processors) */
+#define MAXSCHTO 127 /* maximum signed character */
+#define MAXUCHTO 255 /* maximum unsigned character */
+#define MINSCHTO (-128) /* minimum signed character */
+
+#ifdef MC6809
+# define is5bitoffset(n) ((uoffset_t) (n) + 0x10 < 0x20)
+#endif
+#define isbyteoffset(n) ((uoffset_t) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO)
+#define ischarconst(n) ((uvalue_t) (n) <= MAXUCHTO)
+#define isnegbyteoffset(n) ((uvalue_t) (n) + MAXSCHTO <= MAXSCHTO - MINSCHTO)
+#define isshortbranch(n) ((uoffset_t) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO)
+
+#ifdef MC6809
+/* Hack to reduce number of direct page variables. */
+#define intmaskto ((uvalue_t) 0xFFFFL)
+#define maxintto ((uvalue_t) 0x7FFFL)
+#define maxlongto ((uvalue_t) 0x7FFFFFFFL)
+#define maxoffsetto ((uvalue_t) 0x7FFFL)
+#define maxshortto ((uvalue_t) 0x7FFFL)
+#define maxuintto ((uvalue_t) 0xFFFFL)
+#define maxushortto ((uvalue_t) 0xFFFFL)
+#define shortmaskto ((uvalue_t) 0xFFFFL)
+#else
+extern uvalue_t intmaskto; /* mask for ints */
+extern uvalue_t maxintto; /* maximum int */
+extern uvalue_t maxlongto; /* maximum long */
+extern uvalue_t maxoffsetto; /* maximum offset */
+extern uvalue_t maxshortto; /* maximum short */
+extern uvalue_t maxuintto; /* maximum unsigned */
+extern uvalue_t maxushortto; /* maximum unsigned short */
+extern uvalue_t shortmaskto; /* mask for shorts */
+#endif
diff --git a/bcc-bruce/softop.c b/bcc-bruce/softop.c
new file mode 100644
index 0000000..d676e18
--- /dev/null
+++ b/bcc-bruce/softop.c
@@ -0,0 +1,222 @@
+/* softop.c - software operations for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ softop(operation code, source leaf, target leaf)
+ handles binary operations which are not done in hardware
+ if the result type is (unsigned) long, float or double, all the work
+ is immediately passed on to routines in other files. Otherwise:
+ source and target may be either char, int or unsigned int
+ they are not cast to ints or unsigneds before they get here
+ considerable effort goes into avoiding unnecessary pushes
+-----------------------------------------------------------------------------*/
+
+PUBLIC void softop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regpushed;
+ store_t regmark;
+ scalar_t resultscalar;
+ scalar_t sscalar;
+ scalar_t tscalar;
+ value_t sourceval;
+ bool_t uflag;
+ store_t workreg;
+
+ if ((tscalar = target->type->scalar) & DLONG)
+ {
+ longop(op, source, target);
+ return;
+ }
+ if (tscalar & RSCALAR)
+ {
+ floatop(op, source, target);
+ return;
+ }
+ sscalar = source->type->scalar;
+ resultscalar = tscalar;
+ uflag = tscalar & UNSIGNED;
+ if (op != SLOP && op != SROP)
+ {
+ resultscalar |= sscalar;
+ uflag |= sscalar & UNSIGNED;
+ }
+#ifdef MC6809
+ if ((op_t) op == MULOP && sscalar & CHAR && tscalar & CHAR &&
+ (source->storage != CONSTANT || (uvalue_t) source->offset.offv > 2))
+ {
+ if (source->storage & WORKDATREGS)
+ push(source);
+ load(target, DREG);
+ outldmulreg();
+ outadr(source);
+ outmulmulreg();
+ target->storage = DREG;
+ target->type = iscalartotype(resultscalar);
+ return;
+ }
+#endif
+ if (source->storage == CONSTANT)
+ {
+ extend(target);
+#ifdef I8088
+ if (op == MULOP || op == SLOP)
+ loadany(target);
+ else
+#endif
+ load(target, DREG);
+ target->type = iscalartotype(resultscalar);
+ sourceval = source->offset.offv;
+ switch ((op_t) op)
+ {
+ case DIVOP:
+ if (diveasy(sourceval, uflag))
+ return;
+ break;
+ case MODOP:
+ if (modeasy(sourceval, uflag))
+ {
+ if ((uvalue_t) sourceval <= MAXUCHTO + 1)
+ {
+ target->storage = BREG;
+ target->type = ctype;
+ if (uflag)
+ target->type = uctype;
+ }
+ return;
+ }
+ break;
+ case MULOP:
+ if (muleasy((uvalue_t) sourceval, target->storage))
+ return;
+ load(target, DREG);
+ break;
+ case SLOP:
+ slconst(sourceval, target->storage);
+ return;
+ case SROP:
+ srconst(sourceval, uflag);
+ return;
+ }
+ sscalar = (source->type = iscalartotype(resultscalar))->scalar;
+ }
+
+/* to load source first if it is CHAR: */
+/* need work register if target is in WORKDATREGS */
+/* use OPREG unless it will become overloaded later */
+
+/* to preserve source while target is loaded: */
+/* if source is in WORKDATREGS, put it in OPREG, */
+/* unless target is OPREG-indirect */
+/* otherwise, if source is in WORKDATREGS, put it in work reg not OPREG */
+/* also assign a work reg if source is already in OPREG and target needs one */
+
+ regpushed = (regmark = reguse) & OPREG;
+ workreg = OPREG;
+ if (sscalar & CHAR && target->storage & WORKDATREGS &&
+ source->storage == OPREG && source->indcount != 0 ||
+ (sscalar & CHAR || source->storage & WORKDATREGS) &&
+ target->storage == OPREG && target->indcount != 0 ||
+ source->storage == OPREG &&
+ target->storage == GLOBAL && target->indcount == 0
+#ifdef MC6809
+ && posindependent
+#endif
+ )
+ {
+ if ((regmark | OPREG) == allindregs)
+ regpushed |= (workreg = OPWORKREG);
+ else
+ {
+ reguse |= OPREG;
+ workreg = getindexreg();
+ }
+ }
+ pushlist(regpushed); /* no more pushes */
+ reguse = allindregs; /* error if another reg unexpectedly needed */
+
+ if (sscalar & CHAR)
+ {
+ if (target->storage & WORKDATREGS)
+ {
+ extend(target);
+ if (source->storage == workreg)
+ exchange(source, target);
+ else
+ transfer(target, workreg);
+ }
+ extend(source);
+ if (target->storage != OPREG &&
+ (target->storage != GLOBAL || target->indcount != 0
+#ifdef MC6809
+ || !posindependent
+#endif
+ ))
+ workreg = OPREG;
+ }
+ if (source->storage & WORKDATREGS)
+ {
+ if (target->storage == OPREG && target->indcount == 0)
+ exchange(source, target);
+ else
+ {
+ transfer(source, workreg);
+ workreg = OPREG;
+ }
+ }
+ if (target->storage == GLOBAL && target->indcount == 0
+#ifdef MC6809
+ && posindependent
+#endif
+ )
+ load(target, workreg);
+
+/* source and target now in position to be loaded without any more registers */
+
+ extend(target);
+ load(target, DREG);
+ load(source, OPREG);
+ switch ((op_t) op)
+ {
+ case DIVOP:
+#ifdef I8088
+ call("idiv_");
+#else
+ call("idiv");
+#endif
+ break;
+ case MODOP:
+ call("imod");
+ break;
+ case MULOP:
+#ifdef I8088
+ call("imul_");
+#else
+ call("imul");
+#endif
+ break;
+ case SLOP:
+ call("isl");
+ break;
+ case SROP:
+ call("isr");
+ break;
+ }
+ if (uflag)
+ outbyte('u');
+ outnl();
+ target->type = iscalartotype(resultscalar);
+ poplist(regpushed);
+ reguse = regmark;
+}
diff --git a/bcc-bruce/state.c b/bcc-bruce/state.c
new file mode 100644
index 0000000..526d1f9
--- /dev/null
+++ b/bcc-bruce/state.c
@@ -0,0 +1,793 @@
+/* state.c - statement routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "input.h" /* just for ch and eof for label check */
+#include "label.h"
+#include "os.h" /* just for EOL */
+#include "parse.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+#define COLONCHAR ':' /* for label */
+#define GROWCASES 64 /* extra cases for growth of switch struct */
+#define INITIALCASES 16 /* initial cases in switch structure */
+
+struct loopstruct
+{
+ label_t breaklab; /* destination for break */
+ label_t contlab; /* destination for continue */
+ struct nodestruct *etmark; /* expression tree built during loop */
+ struct symstruct *exprmark; /* expression symbols built during loop */
+ struct symstruct *locmark; /* local variables built during loop */
+ struct loopstruct *prevloop; /* previous active for, switch or while */
+ offset_t spmark; /* stack value for continue and break */
+};
+
+struct switchstruct
+{
+ struct casestruct *caseptr; /* current spot in caselist */
+ struct casestruct *casetop; /* last in caselist + 1 */
+ bool_t charselector; /* tells if case selector is char */
+ label_t dfaultlab; /* destination for default case (0 if none) */
+ struct switchstruct *prevswitch; /* previous active switch */
+ struct casestruct
+ {
+ value_t casevalue; /* value giving this case */
+ label_t caselabel; /* corresponding label */
+ }
+ caselist[INITIALCASES]; /* perhaps larger */
+};
+
+PRIVATE struct loopstruct *loopnow; /* currently active for/switch/while */
+ /* depends on NULL init */
+PRIVATE bool_t returnflag; /* set if last effective statement */
+ /* was a return */
+PRIVATE label_t swstacklab; /* label giving stack for switch statement */
+
+FORWARD void addloop P((struct loopstruct *newloop));
+FORWARD void badloop P((void));
+FORWARD void deleteloop P((void));
+FORWARD void evalexpression P((struct nodestruct *exp));
+FORWARD void exprstatement P((void));
+FORWARD bool_pt isforever P((struct nodestruct *exp));
+FORWARD void sort P((struct casestruct *caselist, int count));
+FORWARD void dobreak P((void));
+FORWARD void docase P((void));
+FORWARD void docont P((void));
+FORWARD void dodefault P((void));
+FORWARD void dodowhile P((void));
+FORWARD void dofor P((void));
+FORWARD void dogoto P((void));
+FORWARD void doif P((void));
+FORWARD void doreturn P((void));
+FORWARD void doswitch P((void));
+FORWARD void dowhile P((void));
+FORWARD void jumptocases P((void));
+FORWARD void statement P((void));
+
+/* --- utility routines --- */
+
+PRIVATE void addloop(newloop)
+struct loopstruct *newloop;
+{
+ newloop->breaklab = getlabel();
+ newloop->contlab = getlabel();
+ newloop->etmark = etptr;
+ newloop->exprmark = exprptr;
+ newloop->locmark = locptr;
+ newloop->prevloop = loopnow;
+ newloop->spmark = sp;
+ loopnow = newloop;
+}
+
+PRIVATE void badloop()
+{
+ error(" no active fors, switches or whiles");
+}
+
+PRIVATE void deleteloop()
+{
+ etptr = loopnow->etmark;
+ exprptr = loopnow->exprmark;
+ locptr = loopnow->locmark;
+ loopnow = loopnow->prevloop;
+}
+
+PRIVATE void evalexpression(exp)
+struct nodestruct *exp;
+{
+ offset_t spmark;
+
+ spmark = sp;
+ makeleaf(exp);
+ modstk(spmark);
+}
+
+PRIVATE void exprstatement()
+{
+ struct nodestruct *etmark;
+ struct symstruct *exprmark;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ evalexpression(expression());
+ etptr = etmark;
+ exprptr = exprmark;
+}
+
+PRIVATE bool_pt isforever(exp)
+register struct nodestruct *exp;
+{
+ return exp == NULL ||
+ exp->tag == LEAF && exp->left.symptr->storage == CONSTANT &&
+ exp->left.symptr->offset.offv != 0;
+}
+
+PRIVATE void sort(caselist, count) /* shell sort */
+struct casestruct *caselist;
+int count;
+{
+ register int gap;
+ register int i;
+ int j;
+ struct casestruct swaptemp;
+
+ gap = 1;
+ do
+ gap = 3 * gap + 1;
+ while (gap <= count);
+ while (gap != 1)
+ {
+ gap /= 3;
+ for (j = gap; j < count; ++j)
+ for (i = j - gap;
+ i >= 0 && caselist[i].casevalue > caselist[i + gap].casevalue;
+ i -= gap)
+ {
+ swaptemp = caselist[i];
+ caselist[i] = caselist[i + gap];
+ caselist[i + gap] = swaptemp;
+ }
+ }
+}
+
+/* --- syntax routines --- */
+
+/* ----------------------------------------------------------------------------
+ compound-statement:
+ "{" <declaration-list> <statement-list> "}"
+---------------------------------------------------------------------------- */
+
+PUBLIC void compound() /* have just seen "{" */
+{
+ struct symstruct *locmark;
+ store_t regmark;
+#ifdef FRAMEPOINTER
+ offset_t framepmark;
+ offset_t softspmark;
+#else
+ /* softsp == sp here unless level == ARGLEVEL so mark is unnec */
+ /* this is also true if funcsaveregsize != 0 but the tests are too messy */
+#endif
+ offset_t spmark;
+
+ locmark = locptr;
+ regmark = reguse;
+#ifdef FRAMEPOINTER
+ softspmark = softsp;
+ framepmark = framep;
+#endif
+ spmark = sp;
+ newlevel();
+ decllist();
+ softsp &= alignmask;
+ if (sym != RBRACE) /* no need for locals if empty compound */
+ reslocals();
+ returnflag = FALSE;
+ while (sym != RBRACE && sym != EOFSYM)
+ statement();
+ oldlevel();
+ if (!returnflag)
+ {
+ if (level != ARGLEVEL)
+ {
+ if (switchnow == NULL)
+ {
+#ifdef FRAMEPOINTER
+ if (framep != 0)
+ {
+ /* some args or locals, maybe at lower levels */
+ modstk(softspmark);
+ if (framep != framepmark)
+ /* frame was just set up */
+ popframe();
+ }
+#else
+ modstk(spmark);
+#endif
+ }
+ }
+ else
+ ret();
+ }
+#ifdef FRAMEPOINTER
+ framep = framepmark;
+ sp = spmark;
+ softsp = softspmark;
+#else
+ softsp = sp = spmark;
+#endif
+ reguse = regmark;
+ locptr = locmark;
+ rbrace();
+}
+
+PRIVATE void dobreak()
+{
+ offset_t spmark;
+
+ if (loopnow == NULL)
+ badloop();
+ else
+ {
+ if (switchnow == NULL)
+ {
+ spmark = sp;
+ modstk(loopnow->spmark);
+ sp = spmark;
+ }
+ jump(loopnow->breaklab);
+ }
+}
+
+PRIVATE void docase()
+{
+ value_t caseval;
+
+ caseval = constexpression() & intmaskto; /* FIXME: warn overflow */
+ if (caseval > maxintto)
+ caseval -= (maxuintto + 1);
+ colon();
+ if (switchnow == NULL)
+ error("case not in switch");
+ else
+ {
+ if (switchnow->charselector && (caseval < 0 || caseval > 255))
+ error("%wcase cannot be reached with char switch");
+ else
+ {
+ if (switchnow->caseptr >= switchnow->casetop)
+ {
+ int ncases;
+
+ ncases = (/* ptrdiff_t */ int)
+ (switchnow->caseptr - &switchnow->caselist[0]);
+ switchnow = realloc(switchnow,
+ (/* size_t */ unsigned)
+ ((char *) switchnow->caseptr
+ - (char *) switchnow)
+ + GROWCASES * sizeof (struct casestruct));
+#ifdef TS
+++ts_n_case_realloc;
+ts_s_case += GROWCASES * sizeof (struct casestruct);
+ts_s_case_tot += GROWCASES * sizeof (struct casestruct);
+#endif
+ if (switchnow == NULL)
+ outofmemoryerror("");
+ switchnow->caseptr = &switchnow->caselist[ncases];
+ switchnow->casetop = switchnow->caseptr + GROWCASES;
+ }
+ switchnow->caseptr->casevalue = caseval;
+ deflabel(switchnow->caseptr->caselabel = getlabel());
+ ++switchnow->caseptr;
+ }
+ }
+}
+
+PRIVATE void docont()
+{
+ struct loopstruct *contloop;
+ offset_t spmark;
+ struct switchstruct *switchthen;
+
+ for (contloop = loopnow, switchthen = switchnow; ;
+ contloop = contloop->prevloop, switchthen = switchthen->prevswitch)
+ {
+ if (contloop == NULL)
+ {
+ badloop();
+ return;
+ }
+ if (contloop->contlab != 0)
+ break;
+ }
+ if (switchnow == NULL)
+ {
+ spmark = sp;
+ modstk(contloop->spmark);
+ sp = spmark;
+ }
+ else if (switchthen == NULL)
+ {
+ outaddsp();
+ outshex(contloop->spmark);
+ outminus();
+ outswstacklab();
+#ifdef MC6809
+ outcregname(LOCAL);
+#endif
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ outnl();
+ }
+ jump(contloop->contlab);
+}
+
+PRIVATE void dodefault()
+{
+ colon();
+ if (switchnow == NULL)
+ error("default not in switch");
+ else if (switchnow->dfaultlab != 0)
+ error("multiple defaults");
+ else
+ deflabel(switchnow->dfaultlab = getlabel());
+}
+
+PRIVATE void dodowhile()
+{
+ struct loopstruct dwhileloop;
+ label_t dolab;
+
+ addloop(&dwhileloop);
+ deflabel(dolab = getlabel());
+ statement();
+ if (sym == WHILESYM)
+ nextsym();
+ else
+ error("missing while at end of do-while");
+ deflabel(dwhileloop.contlab);
+ lparen();
+ jumptrue(expression(), dolab);
+ rparen();
+ semicolon();
+ deflabel(dwhileloop.breaklab);
+ deleteloop();
+}
+
+PRIVATE void dofor()
+{
+ struct loopstruct forloop;
+ label_t forstatlab;
+ label_t fortestlab;
+ struct nodestruct *testexp;
+ struct nodestruct *loopexp;
+
+ lparen();
+ if (sym != SEMICOLON)
+ exprstatement();
+ semicolon();
+ addloop(&forloop);
+ if (sym == SEMICOLON)
+ testexp = NULL;
+ else
+ testexp = expression(); /* remember test expression */
+ semicolon();
+ if (sym == RPAREN)
+ loopexp = NULL;
+ else
+ loopexp = expression(); /* remember loop expression */
+ rparen();
+ if (!isforever(testexp))
+ jump(fortestlab = getlabel()); /* test at bottom */
+ deflabel(forstatlab = getlabel()); /* back here if test succeeds */
+ statement();
+ deflabel(forloop.contlab);
+ if (loopexp != NULL)
+ evalexpression(loopexp);
+ if (isforever(testexp))
+ jump(forstatlab);
+ else
+ {
+ deflabel(fortestlab); /* test label */
+ jumptrue(testexp, forstatlab);
+ }
+ deflabel(forloop.breaklab);
+ deleteloop();
+}
+
+PRIVATE void dogoto()
+{
+ struct symstruct *symptr;
+
+ if (sym == IDENT || sym == TYPEDEFNAME)
+ {
+ symptr = namedlabel();
+/*
+ if (symptr->indcount == 4)
+ modstk(
+ else
+*/
+ adjsp(symptr->offset.offlabel);
+ jump(symptr->offset.offlabel);
+ nextsym();
+ }
+ else
+ error("need identifier");
+}
+
+PRIVATE void doif()
+{
+ struct nodestruct *etmark;
+ label_t elselab;
+ label_t exitlab;
+ struct symstruct *exprmark;
+
+ lparen();
+ etmark = etptr;
+ exprmark = exprptr;
+ jumpfalse(expression(), elselab = getlabel());
+ etptr = etmark;
+ exprptr = exprmark;
+ rparen();
+ statement(); /* true, do a statement */
+ if (sym == ELSESYM) /* "if .. else" statement */
+ {
+ nextsym();
+ jump(exitlab = getlabel()); /* over "else" label and code */
+ deflabel(elselab);
+ statement();
+ deflabel(exitlab);
+ }
+ else
+ deflabel(elselab);
+}
+
+PRIVATE void doreturn()
+{
+ offset_t spmark;
+
+ spmark = sp;
+ if (sym != SEMICOLON) /* returning expression */
+ loadretexpression();
+ ret(); /* clean up stack and return */
+ sp = spmark; /* restore stack for rest of function */
+}
+
+PRIVATE void doswitch()
+{
+ struct switchstruct *sw;
+ struct loopstruct switchloop;
+ offset_t spmark;
+ label_t sdecidelab;
+
+ sw = (struct switchstruct *) ourmalloc(sizeof *sw);
+#ifdef TS
+++ts_n_case;
+ts_s_case += sizeof *sw;
+ts_s_case_tot += sizeof *sw;
+#endif
+ lparen();
+ sw->charselector = loadexpression(DREG, NULLTYPE)->scalar & CHAR;
+ rparen();
+ if (switchnow == NULL)
+ spmark = lowsp = sp;
+ addloop(&switchloop);
+ sw->dfaultlab = switchloop.contlab = 0; /* kill to show this is a switch */
+ sw->casetop = (sw->caseptr = sw->caselist) + INITIALCASES;
+ sw->prevswitch = switchnow;
+ jump(sdecidelab = getlabel()); /* to case decision label */
+ if (switchnow == NULL)
+ swstacklab = gethighlabel();
+ switchnow = sw;
+ statement(); /* cases */
+ sw = switchnow;
+ jump(switchloop.breaklab); /* over case decision to break label */
+ deflabel(sdecidelab);
+ if (sw->prevswitch == NULL)
+ modstk(lowsp);
+ jumptocases();
+ deflabel(switchloop.breaklab);
+ if ((switchnow = sw->prevswitch) == NULL)
+ {
+ equlab(swstacklab, lowsp);
+ clearswitchlabels();
+ modstk(spmark);
+ }
+ deleteloop();
+#ifdef TS
+ts_s_case_tot -= (char *) sw->casetop - (char *) sw;
+#endif
+ ourfree(sw);
+}
+
+PRIVATE void dowhile()
+{
+ struct loopstruct whileloop;
+ struct nodestruct *testexp;
+ label_t wstatlab;
+
+ lparen();
+ addloop(&whileloop);
+ testexp = expression();
+ rparen();
+ if (!isforever(testexp))
+ jump(whileloop.contlab); /* test at bottom */
+ deflabel(wstatlab = getlabel()); /* back here if test succeeds */
+ statement();
+ deflabel(whileloop.contlab);
+ jumptrue(testexp, wstatlab);
+ deflabel(whileloop.breaklab);
+ deleteloop();
+}
+
+PRIVATE void jumptocases()
+{
+ value_t basevalue;
+ struct casestruct *case1ptr;
+ struct casestruct *caseptr;
+ struct casestruct *casetop;
+ value_t caseval;
+ bool_t charselector;
+ bool_t dfaultflag;
+ label_t dfaultlab;
+ label_t jtablelab;
+ ccode_t lowcondition;
+ store_pt targreg;
+ label_t zjtablelab;
+
+ caseptr = switchnow->caselist;
+ casetop = switchnow->caseptr;
+ sort(caseptr, (/* ptrdiff_t */ int) (casetop - caseptr));
+ basevalue = 0;
+ if ((charselector = switchnow->charselector) != 0)
+ {
+ targreg = BREG;
+ lowcondition = LO;
+ }
+ else
+ {
+ targreg = DREG;
+ lowcondition = LT;
+ }
+ dfaultflag = TRUE;
+ if ((dfaultlab = switchnow->dfaultlab) == 0)
+ {
+ dfaultflag = FALSE;
+ dfaultlab = loopnow->breaklab;
+ }
+ --casetop;
+ for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr)
+ if (case1ptr->casevalue == (case1ptr + 1)->casevalue)
+ error("duplicate case in switch");
+ while (caseptr <= casetop)
+ {
+ outsub();
+ outimadj((offset_t) (caseptr->casevalue - basevalue), targreg);
+ basevalue = caseptr->casevalue;
+ for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr)
+ if (case1ptr->casevalue < (case1ptr + 1)->casevalue - 10)
+ break;
+ if (case1ptr < caseptr + 5)
+ {
+ lbranch(EQ, caseptr->caselabel);
+ ++caseptr;
+ }
+ else
+ {
+ lbranch(lowcondition, dfaultlab);
+ outcmp();
+ outimadj((offset_t) (case1ptr->casevalue - basevalue), targreg);
+ lbranch(HI, zjtablelab = getlabel());
+ if (charselector)
+ ctoi();
+#ifdef MC6809
+ else
+ bumplc(); /* extra for CMPD */
+#endif
+ slconst((value_t) (ptypesize / 2), DREG);
+ /* really log ptypesize */
+ deflabel(jtablelab = casejump());
+#ifdef I8088
+ jtablelab = jtablelab; /* not used, allocated for regress */
+#endif
+ for (caseval = caseptr->casevalue; caseval <= case1ptr->casevalue;
+ ++caseval)
+ {
+#ifdef I8088
+ if (ptypesize > 2)
+ defdword();
+ else
+#endif
+ defword();
+ if (caseval != caseptr->casevalue)
+ outlabel(dfaultlab);
+ else
+ {
+ outlabel(caseptr->caselabel);
+ ++caseptr;
+ }
+#ifdef MC6809
+ if (posindependent)
+ {
+ outminus();
+ outlabel(jtablelab);
+ }
+#endif
+ bumplc2();
+#ifdef I8088
+ if (ptypesize > 2)
+ bumplc2();
+#endif
+ outnl();
+ }
+ deflabel(zjtablelab);
+ }
+ lowcondition = LO; /* 1st subtraction makes rest unsigned */
+ }
+ if (dfaultflag)
+ jump(dfaultlab);
+}
+
+PUBLIC void outswoffset (offset)
+offset_t offset;
+{
+#ifdef FRAMEPOINTER
+ outoffset(offset - softsp - framep);
+#else
+ outoffset(offset - softsp - sp);
+#endif
+ outplus();
+ outswstacklab();
+#ifdef I8088
+ bumplc();
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+PUBLIC void outswstacklab()
+{
+ outbyte(LOCALSTARTCHAR);
+ outlabel(swstacklab);
+}
+
+/* ----------------------------------------------------------------------------
+ statement:
+ <compound-statement>
+ <if-statement>
+ <while-statement>
+ <do-statement>
+ <for-statement>
+ <switch-statement>
+ <case-statement>
+ <default-statement>
+ <break-statement>
+ <continue-statement>
+ <return-statement>
+ <goto-statement>
+ <labelled-statement>
+ <null-statement>
+ <expression> ;
+---------------------------------------------------------------------------- */
+
+PRIVATE void statement()
+{
+#if 1
+ struct symstruct *symptr;
+#endif
+
+more:
+ switch (sym)
+ {
+ case LBRACE:
+ nextsym();
+ compound();
+ return;
+ case IFSYM:
+ nextsym();
+ doif();
+ break;
+ case WHILESYM:
+ nextsym();
+ dowhile();
+ break;
+ case FORSYM:
+ nextsym();
+ dofor();
+ break;
+ case RETURNSYM:
+ nextsym();
+ doreturn();
+ semicolon();
+ returnflag = TRUE;
+ return;
+ case SWITCHSYM:
+ nextsym();
+ doswitch();
+ break;
+ case BREAKSYM:
+ nextsym();
+ dobreak();
+ semicolon();
+ break;
+ case CASESYM:
+ nextsym();
+ docase();
+ goto more;
+ case DEFAULTSYM:
+ nextsym();
+ dodefault();
+ goto more;
+ case DOSYM:
+ nextsym();
+ dodowhile();
+ break;
+ case CONTSYM:
+ nextsym();
+ docont();
+ semicolon();
+ break;
+ case GOTOSYM:
+ nextsym();
+ dogoto();
+ semicolon();
+ break;
+ case SEMICOLON:
+ nextsym();
+ return;
+ case IDENT:
+ case TYPEDEFNAME:
+ blanks(); /* cannot afford nextsym() */
+ while (ch == EOL && !eof)
+ {
+ /* this now fails only on #controls and macros giving ':' */
+ skipeol();
+ blanks();
+ }
+ if (ch == COLONCHAR)
+ {
+#if 0
+ struct symstruct *symptr;
+#endif
+ symptr = namedlabel();
+ if (symptr->indcount != 2)
+ error("redefined label");
+ else
+ {
+ deflabel(symptr->offset.offlabel);
+ if (switchnow != NULL)
+ symptr->indcount = 3;
+ else
+ {
+ symptr->indcount = 4;
+ outbyte(LOCALSTARTCHAR);
+ outlabel(symptr->offset.offlabel);
+ outop0str("\t=\t");
+ outshex(sp);
+ outnl();
+ }
+ }
+ nextsym();
+ nextsym();
+ goto more;
+ }
+ /* else fall into default */
+ default:
+ exprstatement();
+ semicolon();
+ break;
+ }
+ returnflag = FALSE;
+}
diff --git a/bcc-bruce/table.c b/bcc-bruce/table.c
new file mode 100644
index 0000000..028950f
--- /dev/null
+++ b/bcc-bruce/table.c
@@ -0,0 +1,668 @@
+/* table.c - table handler for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* Can I now get rid of EXPRLEVEL? Yes, except expression symbols must
+ * usually be set to some level different from OFFKLUDGELEVEL.
+ */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "gencode.h"
+#include "os.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "table.h"
+
+#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */
+#define HASHTABSIZE 256
+#define MARKER ((unsigned) 0x18C396A5L) /* lint everywhere it is used */
+#define MAXEXPR 500
+#define MAXLOCAL 100
+#define NKEYWORDS 34
+#define NSCALTYPES 12
+#define STACKSPACE 256 /* punt for normal recursions - switch extra */
+
+struct keywordstruct
+{
+ char *kwname;
+ sym_t kwcode;
+};
+
+#ifdef HOLDSTRINGS
+struct string
+{
+ struct string *snext;
+ char *sptr;
+ char *stop;
+ label_t slabel;
+};
+#endif
+
+struct typedatastruct
+{
+ char *tdname;
+ bool_t tdkeyscalar;
+ scalar_t tdscalar;
+ smalin_t tdsize;
+ struct typestruct **tdtypeptr;
+};
+
+PRIVATE struct symstruct exprsyms[MAXEXPR];
+PRIVATE struct symstruct *hashtab[HASHTABSIZE];
+ /* depends on zero init */
+#ifdef HOLDSTRINGS
+PRIVATE struct string *laststring; /* last in list of strings */
+ /* depends on NULL init */
+#endif
+PUBLIC struct symstruct locsyms[MAXLOCAL];
+
+PRIVATE struct symstruct constemplate =
+{
+ CONSTANT, /* storage */
+ 0, /* indcount */
+ 0, /* flags */
+ EXPRLEVEL, /* level */
+ NULL, /* next */
+ NULL, /* prev */
+ NULL, /* type, init later to itype */
+ /* offset is a union, set every time constemplate is used */
+ /* name is a union, namea member is constant "\0" */
+};
+
+PRIVATE struct keywordstruct keywords[NKEYWORDS] =
+{
+ { "enum", ENUMDECL, },
+ { "struct", STRUCTDECL, },
+ { "union", UNIONDECL, },
+ { "unsigned", UNSIGNDECL, },
+
+ { "auto", AUTODECL, },
+ { "extern", EXTERNDECL, },
+ { "register", REGDECL, },
+ { "static", STATICDECL, },
+
+ { "typedef", TYPEDEFDECL, },
+
+ { "break", BREAKSYM, },
+ { "case", CASESYM, },
+ { "continue", CONTSYM, },
+ { "default", DEFAULTSYM, },
+ { "do", DOSYM, },
+ { "else", ELSESYM, },
+ { "for", FORSYM, },
+ { "goto", GOTOSYM, },
+ { "if", IFSYM, },
+ { "return", RETURNSYM, },
+ { "sizeof", SIZEOFSYM, },
+ { "switch", SWITCHSYM, },
+ { "while", WHILESYM, },
+
+ { "#asm", ASMCNTL, },
+ { "#define", DEFINECNTL, },
+ { "#else", ELSECNTL, },
+ { "#endasm", ENDASMCNTL, },
+ { "#endif", ENDIFCNTL, },
+ { "#if", IFCNTL, },
+ { "#ifdef", IFDEFCNTL, },
+ { "#include", INCLUDECNTL, },
+ { "#ifndef", IFNDEFCNTL, },
+ { "#line", LINECNTL, },
+ { "#undef", UNDEFCNTL, },
+
+ { "defined", DEFINEDSYM, }, /* should be deactivated except in #if's */
+};
+
+PRIVATE struct typedatastruct scaltypes[NSCALTYPES] =
+{
+ { "void", TRUE, 0, 0, &vtype, }, /* first - addkeyword uses vtype */
+ { "char", TRUE, CHAR, 1, &ctype, },
+ { "char", FALSE, UNSIGNED | CHAR, 1, &uctype, },
+ { "char", FALSE, CHAR, 1, &sctype, },
+ { "short", TRUE, SHORT, 2, &stype, },
+ { "short", FALSE, UNSIGNED | SHORT, 2, &ustype, },
+ { "int", TRUE, INT, 2, &itype, },
+ { "int", FALSE, UNSIGNED | INT, 2, &uitype, },
+ { "long", TRUE, LONG | DLONG, 4, &ltype, },
+ { "long", FALSE, UNSIGNED | LONG | DLONG, 4, &ultype, },
+ { "float", TRUE, FLOAT, 4, &fltype, },
+ { "double", TRUE, DOUBLE, 8, &dtype, },
+};
+
+FORWARD struct symstruct *addkeyword P((char *name, sym_pt code));
+FORWARD void heapcorrupterror P((void));
+
+PUBLIC struct symstruct *addglb(name, type)
+char *name;
+struct typestruct *type;
+{
+ struct symstruct **hashptr;
+ struct symstruct *oldsymptr;
+ register struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ {
+ oldsymptr = symptr;
+ symptr = symptr->next;
+ }
+ symptr = qmalloc(sizeof (struct symstruct) + strlen(name));
+#ifdef TS
+++ts_n_global;
+ts_size_global += sizeof (struct symstruct) + strlen(name);
+#endif
+ addsym(name, type, symptr);
+ symptr->storage = GLOBAL;
+ symptr->level = GLBLEVEL;
+ if (*hashptr == NULL)
+ {
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+ }
+ else
+ {
+ oldsymptr->next = symptr;
+ symptr->prev = &oldsymptr->next;
+ }
+ return symptr;
+}
+
+PRIVATE struct symstruct *addkeyword(name, code)
+char *name;
+sym_pt code;
+{
+ struct symstruct *symptr;
+
+ (symptr = addglb(name, vtype))->flags = KEYWORD;
+ symptr->offset.offsym = code;
+ return symptr;
+}
+
+PUBLIC struct symstruct *addloc(name, type)
+char *name;
+struct typestruct *type;
+{
+ struct symstruct **hashptr;
+ register struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ symptr = symptr->next;
+ symptr = locptr;
+ locptr = (struct symstruct *) align(&symptr->name.namea[strlen(name) + 1]);
+ if (locptr >= &locsyms[MAXLOCAL])
+ limiterror("too many local symbols (101)");
+ addsym(name, type, symptr);
+ if (type->constructor == FUNCTION)
+ symptr->storage = GLOBAL;
+ else
+ symptr->storage = LOCAL;
+ symptr->level = level;
+ if (*hashptr != NULL)
+ {
+ symptr->next = *hashptr;
+ symptr->next->prev = &symptr->next;
+ }
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+ return symptr;
+}
+
+PUBLIC struct symstruct *addlorg(name, type)
+char *name;
+struct typestruct *type;
+{
+ if (level != GLBLEVEL)
+ return addloc(name, type);
+ return addglb(name, type);
+}
+
+PUBLIC void addsym(name, type, symptr)
+char *name;
+struct typestruct *type;
+register struct symstruct *symptr;
+{
+ if (type->constructor & (ARRAY | FUNCTION))
+ symptr->indcount = 0;
+ else
+ symptr->indcount = 1;
+ symptr->flags = 0;
+ symptr->next = NULL;
+ symptr->type = type;
+ symptr->offset.offi = 0;
+ strcpy(symptr->name.namea, name);
+}
+
+PUBLIC struct symstruct *constsym(longconst)
+value_t longconst;
+{
+ register struct symstruct *symptr;
+
+ symptr = exprsym(&constemplate);
+ symptr->offset.offv = longconst;
+ return symptr;
+}
+
+PUBLIC void delsym(symptr)
+register struct symstruct *symptr;
+{
+ if ((*(symptr->prev) = symptr->next) != NULL)
+ symptr->next->prev = symptr->prev;
+}
+
+/* dumpglbs() - define locations of globals and reserve space for them */
+
+PUBLIC void dumpglbs()
+{
+ int i;
+ register struct symstruct *symptr;
+ register struct typestruct *type;
+
+#ifdef TS
+extern char *brksize;
+struct ts
+{
+ char *what;
+ uvalue_t *where;
+};
+static struct ts ts[] =
+{
+ "ts_n_newtypelist ", &ts_n_newtypelist,
+ "ts_s_newtypelist ", &ts_s_newtypelist,
+ "ts_n_filename_term ", &ts_n_filename_term,
+ "ts_s_filename_term ", &ts_s_filename_term,
+ "ts_n_filename ", &ts_n_filename,
+ "ts_s_filename ", &ts_s_filename,
+ "ts_s_filename_tot ", &ts_s_filename_tot,
+ "ts_n_pathname ", &ts_n_pathname,
+ "ts_s_pathname ", &ts_s_pathname,
+ "ts_s_pathname_tot ", &ts_s_pathname_tot,
+ "ts_n_inputbuf ", &ts_n_inputbuf,
+ "ts_s_inputbuf ", &ts_s_inputbuf,
+ "ts_s_inputbuf_tot ", &ts_s_inputbuf_tot,
+ "ts_n_includelist ", &ts_n_includelist,
+ "ts_s_includelist ", &ts_s_includelist,
+ "ts_s_outputbuf ", &ts_s_outputbuf,
+ "ts_n_macstring_ident ", &ts_n_macstring_ident,
+ "ts_n_macstring_ordinary ", &ts_n_macstring_ordinary,
+ "ts_n_macstring_param ", &ts_n_macstring_param,
+ "ts_n_macstring_quoted ", &ts_n_macstring_quoted,
+ "ts_n_macstring_term ", &ts_n_macstring_term,
+ "ts_s_macstring ", &ts_s_macstring,
+ "ts_n_defines ", &ts_n_defines,
+ "ts_s_defines ", &ts_s_defines,
+ "ts_n_macparam ", &ts_n_macparam,
+ "ts_s_macparam ", &ts_s_macparam,
+ "ts_s_macparam_tot ", &ts_s_macparam_tot,
+ "ts_n_macparam_string_ordinary ", &ts_n_macparam_string_ordinary,
+ "ts_n_macparam_string_quoted ", &ts_n_macparam_string_quoted,
+ "ts_n_macparam_string_term ", &ts_n_macparam_string_term,
+ "ts_s_macparam_string ", &ts_s_macparam_string,
+ "ts_s_macparam_string_tot ", &ts_s_macparam_string_tot,
+ "ts_s_macparam_string_alloced ", &ts_s_macparam_string_alloced,
+ "ts_s_macparam_string_alloced_tot ", &ts_s_macparam_string_alloced_tot,
+ "ts_s_fakeline ", &ts_s_fakeline,
+ "ts_s_fakeline_tot ", &ts_s_fakeline_tot,
+ "ts_n_string ", &ts_n_string,
+ "ts_n_case ", &ts_n_case,
+ "ts_n_case_realloc ", &ts_n_case_realloc,
+ "ts_s_case ", &ts_s_case,
+ "ts_s_case_tot ", &ts_s_case_tot,
+ "ts_n_structname ", &ts_n_structname,
+ "ts_s_structname ", &ts_s_structname,
+ "ts_n_type ", &ts_n_type,
+ "ts_s_type ", &ts_s_type,
+ "ts_n_global ", &ts_n_global,
+ "ts_size_global ", &ts_size_global,
+ "ts_n_holdstr ", &ts_n_holdstr,
+ "ts_size_holdstr ", &ts_size_holdstr,
+ "ts_n_growobj ", &ts_n_growobj,
+ "ts_size_growobj_wasted ", &ts_size_growobj_wasted,
+ "ts_n_growheap ", &ts_n_growheap,
+ "ts_s_growheap ", &ts_s_growheap,
+};
+struct ts *tp;
+
+for (tp = &ts[0]; tp < &ts[sizeof ts / sizeof ts[0]]; ++tp)
+{
+ comment();
+ outstr(tp->what);
+ outstr("");
+ outuvalue(*tp->where);
+ outnl();
+}
+comment();
+outstr("brksize ");
+outhex((uvalue_t) brksize);
+outnl();
+#endif
+
+#ifndef DIRECTPAGE
+ bssseg();
+#endif
+ for (i = 0; i < HASHTABSIZE; ++i)
+ for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next)
+ if (symptr->storage == GLOBAL && !(symptr->flags & EXTERNAL)
+ && *symptr->name.namea >= 'A' && symptr->flags <= MAXDUMPFLAG
+ /* Don't access type unless flags <= MAXDUMPFLAG, because
+ * type is punned to a symbol pointer for the label chain
+ * and might be null.
+ */
+ && symptr->type->constructor != FUNCTION)
+ {
+#ifdef DIRECTPAGE
+ if (symptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ type = symptr->type;
+ if (symptr->flags & STATIC)
+ lcommon(symptr->name.namea);
+ else
+ common(symptr->name.namea);
+ outnhex(type->typesize);
+ }
+ if (printf_fp)
+ globl("__xfpcvt");
+ if (scanf_fp)
+ globl("__xfptvc");
+}
+
+/* dumplocs() - define offsets of current locals */
+
+PUBLIC void dumplocs()
+{
+ register struct symstruct *symptr;
+ int i;
+
+ for (i = 0; i < HASHTABSIZE; ++i)
+ for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next)
+ if (symptr->storage == LOCAL)
+ set(symptr->name.namea, symptr->offset.offi - sp);
+}
+
+#ifdef HOLDSTRINGS
+
+/* dumpstrings() - dump held-up strings */
+
+PUBLIC void dumpstrings()
+{
+ struct string *stringp;
+
+ dseg();
+ for (stringp = laststring; stringp != NULL; stringp = stringp->snext)
+ {
+ outnlabel(stringp->slabel);
+ defstr(stringp->sptr, stringp->stop, TRUE);
+ dataoffset += stringp->stop - stringp->sptr + 1;
+ }
+}
+
+#endif
+
+PUBLIC struct symstruct *exprsym(symptr)
+struct symstruct *symptr;
+{
+ register struct symstruct *newsymptr;
+
+ newsymptr = exprptr++;
+ if (exprptr >= &exprsyms[MAXEXPR])
+ limiterror("expression too complex (501 symbols)");
+ *newsymptr = *symptr;
+ newsymptr->level = EXPRLEVEL;
+ newsymptr->name.namep = symptr->name.namea;
+ return newsymptr;
+}
+
+PUBLIC struct symstruct *findlorg(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (strcmp(symptr->name.namea, name) != 0 ||
+ symptr->flags == STRUCTNAME))
+ symptr = symptr->next;
+ return symptr;
+}
+
+PUBLIC struct symstruct *findstruct(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (symptr->flags != STRUCTNAME ||
+ strcmp(symptr->name.namea, name) != 0))
+ symptr = symptr->next;
+ return symptr;
+}
+
+/* convert name to a hash table ptr */
+
+PUBLIC struct symstruct **gethashptr(sname)
+char *sname;
+{
+ register int hashval;
+ register char *rsname;
+
+ hashval = 0;
+ rsname = sname;
+#if 1
+ while (*rsname)
+ hashval = hashval * 2 + *rsname++;
+#else
+ hashval = rsname[0];
+ if (rsname[1] != 0)
+ hashval = (rsname[2] << 2) ^ rsname[1] ^ (rsname[0] << 1);
+ else
+ hashval = rsname[0];
+#endif
+ return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1));
+}
+
+PRIVATE void heapcorrupterror()
+{
+ outofmemoryerror(" (heap corrupt - stack overflow?)");
+}
+
+#ifdef HOLDSTRINGS
+
+/* hold string for dumping at end, to avoid mixing it with other data */
+
+PUBLIC label_t holdstr(sptr, stop)
+char *sptr;
+char *stop;
+{
+ register struct string *stringp;
+
+ stringp = qmalloc(sizeof *stringp);
+#ifdef TS
+++ts_n_holdstr;
+ts_size_holdstr += sizeof *stringp;
+#endif
+ stringp->snext = laststring;
+ stringp->sptr = sptr;
+ stringp->stop = stop;
+ laststring = stringp;
+ return stringp->slabel = getlabel();
+}
+
+#endif /* HOLDSTRINGS */
+
+PUBLIC void newlevel()
+{
+ if (*(unsigned *) chartop != MARKER)
+ heapcorrupterror();
+ if (level >= MAXLEVEL)
+ limiterror("compound statements nested too deeply (126 levels)");
+ else
+ ++level;
+}
+
+PUBLIC void oldlevel()
+{
+ register struct symstruct *symptr;
+
+ if (*(unsigned *) chartop != MARKER)
+ heapcorrupterror();
+ if (level == 0)
+ bugerror("not in a compound statement");
+ else
+ --level;
+ for (symptr = &locsyms[0]; symptr < locptr;
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ if (symptr->level > level)
+ delsym(symptr);
+}
+
+PUBLIC void ourfree(ptr)
+void *ptr;
+{
+ free(ptr);
+}
+
+PUBLIC void *ourmalloc(nbytes)
+unsigned nbytes;
+{
+ void *ptr;
+
+ if ((ptr = malloc(nbytes)) == NULL)
+ outofmemoryerror("");
+ return ptr;
+}
+
+PUBLIC void outofmemoryerror(message)
+char *message;
+{
+ error2error("compiler out of memory", message);
+
+#if defined(DEBUG) && 0
+ {
+ unsigned size;
+ char *ptr;
+
+ for (size = 0x1000; size != 0; --size)
+ if ((ptr = malloc(size)) != NULL)
+ {
+ outstr("found free memory at ");
+ outuvalue((uvalue_t) ptr);
+ outstr(" size ");
+ outuvalue((uvalue_t) size);
+ outnl();
+ }
+ }
+#endif
+
+ finishup();
+}
+
+PUBLIC void *growobject(object, extra)
+void *object;
+unsigned extra;
+{
+ /* size_t */ unsigned oblength;
+
+ /* It would be nice to realloc the previous memory if it can be left in
+ * the same place. Since a realloc that moves the memory can almost be
+ * relied on to mess up pointers before *obptr, and since malloc(extra)
+ * would be unlikely to produce memory adjoining chartop, it is not
+ * clear how to do this.
+ */
+#ifdef TS
+ts_size_growobj_wasted += chartop - (char *) object;
+#endif
+ oblength = (/* size_t */ unsigned) (charptr - (char *) object);
+ growheap(oblength + extra);
+#ifdef TS
+++ts_n_growobj;
+#endif
+ memcpy(charptr, object, oblength);
+ object = charptr;
+ charptr += oblength;
+ return object;
+}
+
+#define ALLOC_UNIT ((unsigned) 0x400)
+#ifdef S_ALIGNMENT
+#define ALLOC_OVERHEAD (S_ALIGNMENT - 1 + sizeof (unsigned))
+#else
+#define ALLOC_OVERHEAD (sizeof (unsigned))
+#endif
+
+PUBLIC void growheap(size)
+unsigned size;
+{
+ register char *newptr;
+
+ if ((newptr = malloc(size += ALLOC_UNIT + ALLOC_OVERHEAD)) == NULL
+ && (newptr = malloc(size -= ALLOC_UNIT)) == NULL)
+ outofmemoryerror("");
+#ifdef TS
+++ts_n_growheap;
+ts_s_growheap += size;
+#endif
+ charptr = newptr;
+ newptr = (char *) align(newptr + size - ALLOC_OVERHEAD);
+ chartop = newptr;
+ char1top = newptr - 1;
+ char3top = newptr - 3;
+ *(unsigned *) newptr = MARKER;
+}
+
+PUBLIC void *qmalloc(size)
+unsigned size;
+{
+ register char *ptr;
+
+ if ((charptr = (char *) align(charptr)) + size > chartop)
+ growheap(size);
+ ptr = charptr;
+ charptr += size;
+ return ptr;
+}
+
+PUBLIC void swapsym(sym1, sym2)
+struct symstruct *sym1;
+struct symstruct *sym2;
+{
+ struct symstruct swaptemp;
+
+ swaptemp = *sym1;
+ *sym1 = *sym2;
+ *sym2 = swaptemp;
+}
+
+PUBLIC void syminit()
+{
+ struct keywordstruct *kwptr;
+ struct typedatastruct *tdptr;
+ struct typestruct *type;
+
+ exprptr = exprsyms;
+ locptr = locsyms;
+ for (tdptr = scaltypes; tdptr < scaltypes + NSCALTYPES; ++tdptr)
+ {
+ (*tdptr->tdtypeptr = type = newtype())->scalar = tdptr->tdscalar;
+ type->alignmask = ~((type->typesize = tdptr->tdsize) - 1) |
+ alignmask;
+ type->tname = tdptr->tdname;
+ if (tdptr->tdkeyscalar)
+ addkeyword(tdptr->tdname, TYPEDECL)->type = type;
+ }
+ for (kwptr = keywords; kwptr < keywords + NKEYWORDS; ++kwptr)
+ addkeyword(kwptr->kwname, kwptr->kwcode);
+ constemplate.type = itype;
+}
diff --git a/bcc-bruce/table.h b/bcc-bruce/table.h
new file mode 100644
index 0000000..f9b2f38
--- /dev/null
+++ b/bcc-bruce/table.h
@@ -0,0 +1,71 @@
+/* table.h - table handler for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+EXTERN char *charptr; /* next free spot in catchall table */
+EXTERN char *chartop; /* spot after last in table */
+EXTERN char *char1top; /* last character spot in table */
+EXTERN char *char3top; /* third last character spot in table */
+EXTERN struct symstruct *exprptr;
+ /* next entry in expression symbol table */
+EXTERN struct symstruct *locptr;
+ /* next entry in local symbol table */
+extern struct symstruct locsyms[];
+ /* local symbol table */
+
+#define TS1
+#ifdef TS
+uvalue_t ts_n_newtypelist;
+uvalue_t ts_s_newtypelist;
+uvalue_t ts_n_filename_term;
+uvalue_t ts_s_filename_term;
+uvalue_t ts_n_filename;
+uvalue_t ts_s_filename;
+uvalue_t ts_s_filename_tot;
+uvalue_t ts_n_pathname;
+uvalue_t ts_s_pathname;
+uvalue_t ts_s_pathname_tot;
+uvalue_t ts_n_inputbuf;
+uvalue_t ts_s_inputbuf;
+uvalue_t ts_s_inputbuf_tot;
+uvalue_t ts_n_includelist;
+uvalue_t ts_s_includelist;
+uvalue_t ts_s_outputbuf;
+uvalue_t ts_n_macstring_ident;
+uvalue_t ts_n_macstring_ordinary;
+uvalue_t ts_n_macstring_param;
+uvalue_t ts_n_macstring_quoted;
+uvalue_t ts_n_macstring_term;
+uvalue_t ts_s_macstring;
+uvalue_t ts_n_defines;
+uvalue_t ts_s_defines;
+uvalue_t ts_n_macparam;
+uvalue_t ts_s_macparam;
+uvalue_t ts_s_macparam_tot;
+uvalue_t ts_n_macparam_string_ordinary;
+uvalue_t ts_n_macparam_string_quoted;
+uvalue_t ts_n_macparam_string_term;
+uvalue_t ts_s_macparam_string;
+uvalue_t ts_s_macparam_string_tot;
+uvalue_t ts_s_macparam_string_alloced;
+uvalue_t ts_s_macparam_string_alloced_tot;
+uvalue_t ts_s_fakeline;
+uvalue_t ts_s_fakeline_tot;
+uvalue_t ts_n_string;
+uvalue_t ts_n_case;
+uvalue_t ts_n_case_realloc;
+uvalue_t ts_s_case;
+uvalue_t ts_s_case_tot;
+uvalue_t ts_n_structname;
+uvalue_t ts_s_structname;
+uvalue_t ts_n_type;
+uvalue_t ts_s_type;
+uvalue_t ts_n_global;
+uvalue_t ts_size_global;
+uvalue_t ts_n_holdstr;
+uvalue_t ts_size_holdstr;
+uvalue_t ts_n_growobj;
+uvalue_t ts_size_growobj_wasted;
+uvalue_t ts_n_growheap;
+uvalue_t ts_s_growheap;
+#endif
diff --git a/bcc-bruce/type.c b/bcc-bruce/type.c
new file mode 100644
index 0000000..4852c9d
--- /dev/null
+++ b/bcc-bruce/type.c
@@ -0,0 +1,203 @@
+/* type.c - type and storage-class routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "gencode.h" /* s.b. switches.h */
+#include "sc.h"
+#include "scan.h"
+#include "table.h"
+
+#undef EXTERN
+#define EXTERN
+#include "type.h"
+
+PUBLIC uoffset_t ctypesize = 1;
+PUBLIC uoffset_t dtypesize = 8;
+PUBLIC uoffset_t ftypesize = 0;
+PUBLIC uoffset_t itypesize = 2;
+PUBLIC uoffset_t ptypesize = 2;
+PUBLIC uoffset_t stypesize = 2;
+
+PRIVATE char skey0;
+PRIVATE char skey1;
+
+PUBLIC struct typestruct *addstruct(structname)
+char *structname;
+{
+ unsigned namelength;
+ struct symstruct *symptr;
+ struct typestruct *structype;
+
+ (structype = newtype())->constructor = STRUCTU;
+ structype->alignmask = ctype->alignmask;
+ if (++skey1 == 0)
+ {
+ ++skey1; /* must be nonzero or key string would end */
+ ++skey0; /* will never reach 'A' to be an identifier */
+ }
+ structype->structkey[0] = skey0;
+ structype->structkey[1] = skey1;
+ if (*structname != 0)
+ {
+ symptr = addlorg(structname, structype);
+ symptr->storage = 0;
+ symptr->flags = STRUCTNAME;
+ if (charptr + (namelength = strlen(structname)) >= chartop)
+ growheap(namelength + 1);
+#ifdef TS
+++ts_n_structname;
+ts_s_structname += namelength + 1;
+#endif
+ structype->tname = strcpy(charptr, structname);
+ charptr += namelength + 1;
+ }
+ return structype;
+}
+
+PUBLIC struct typestruct *iscalartotype(scalar)
+scalar_pt scalar;
+{
+ if (scalar & LONG)
+ {
+ if (scalar & UNSIGNED)
+ return ultype;
+ return ltype;
+ }
+ if (scalar & UNSIGNED)
+ return uitype;
+ return itype;
+}
+
+PUBLIC struct typestruct *newtype()
+{
+ register struct typestruct *type;
+
+ type = qmalloc(sizeof *type);
+#ifdef TS
+++ts_n_type;
+ts_s_type += sizeof *type;
+#endif
+ type->typesize = /* (uoffset_t) */
+ type->scalar = /* (scalar_t) */
+ type->constructor = /* (constr_t) */
+ type->structkey[0] = 0;
+ type->nexttype =
+ type->prevtype =
+ type->sidetype = NULL;
+ type->listtype = NULL;
+ type->tname = "";
+ return type;
+}
+
+PUBLIC void outntypechar(type)
+struct typestruct *type;
+{
+ outnbyte(*type->tname);
+}
+
+PUBLIC struct typestruct *pointype(type)
+struct typestruct *type;
+{
+ return prefix(POINTER, ptypesize, type);
+}
+
+PUBLIC struct typestruct *prefix(constructor, size, type)
+constr_pt constructor;
+uoffset_t size;
+struct typestruct *type;
+{
+ register struct typestruct *searchtype;
+
+ for (searchtype = type->prevtype; searchtype != NULL;
+ searchtype = searchtype->sidetype)
+ if (searchtype->constructor == (constr_t) constructor &&
+ searchtype->typesize == size)
+ return searchtype;
+ switch ((searchtype = newtype())->constructor = constructor)
+ {
+ case ARRAY:
+ searchtype->alignmask = type->alignmask;
+ break;
+ case FUNCTION:
+ searchtype->alignmask = ~(uoffset_t) 0;
+ break;
+ case POINTER:
+ searchtype->alignmask = ~(ptypesize - 1) | alignmask;
+ break;
+ case STRUCTU:
+ bugerror("prefixing structure/union");
+ searchtype->alignmask = alignmask;
+ break;
+ }
+ searchtype->typesize = size;
+ searchtype->nexttype = type;
+ searchtype->sidetype = type->prevtype;
+ return type->prevtype = searchtype;
+}
+
+PUBLIC struct typestruct *promote(type)
+struct typestruct *type;
+{
+ scalar_t scalar;
+
+ if ((scalar = type->scalar) & (CHAR | SHORT))
+ {
+ if (scalar & UNSIGNED)
+ return uitype;
+ return itype;
+ }
+ if (scalar & FLOAT)
+ return dtype;
+ if (type->constructor & ARRAY)
+ return pointype(type->nexttype);
+ if (type->constructor & FUNCTION)
+ return pointype(type);
+ return type;
+}
+
+PUBLIC struct typestruct *tounsigned(type)
+struct typestruct *type;
+{
+ switch (type->scalar & ~(UNSIGNED | DLONG))
+ {
+ case CHAR:
+ return uctype;
+ case SHORT:
+ return ustype;
+ case INT:
+ return uitype;
+ case LONG:
+ return ultype;
+ default:
+ error("unsigned only applies to integral types");
+ return type;
+ }
+}
+
+PUBLIC void typeinit()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ uitype->typesize =
+ itype->typesize =
+ ptypesize =
+ itypesize = 4;
+ dtype->alignmask =
+ fltype->alignmask =
+ uitype->alignmask =
+ ltype->alignmask =
+ ultype->alignmask =
+ itype->alignmask = ~(uoffset_t) (4 - 1);
+ ltype->scalar = LONG; /* not DLONG */
+ ultype->scalar = UNSIGNED | LONG;
+ }
+#endif
+ fitype = prefix(FUNCTION, ftypesize, itype);
+ pctype = pointype(ctype);
+ skey0 = 1;
+ vtype->constructor = VOID;
+}
diff --git a/bcc-bruce/type.h b/bcc-bruce/type.h
new file mode 100644
index 0000000..c451283
--- /dev/null
+++ b/bcc-bruce/type.h
@@ -0,0 +1,98 @@
+/* type.h - types for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ A type is essentially a "constructor", a size, and a list of pointers
+ leading to a scalar type.
+ The type constructors are codes for the scalar types and (), [], *,
+ struct and union.
+ The scalar types are char, short, int, long, float and double.
+ The type lists are triply linked.
+
+ Part of the type structure might look like
+
+ int (int)
+ =
+ func <-------> int (int ())
+ | =
+ --> ptr <--> int (int *)
+
+ (the exact structure depends on the order of declarations).
+ This layout results from the pre-declared (int) and (int ()) followed by
+ a declaration using (int *).
+ The sideways link (from func to ptr here) allows all types leading to a
+ given type to be found.
+ This allows different declarations of (int *) to be recognised as the same.
+ Type equivalence is equality of type pointers.
+*/
+
+/*
+ flags for scalar types
+ up to 3 of the flags may be set (none for constructed types)
+ the 2nd and third flags can only be UNSIGNED or DLONG
+ UNSIGNED only applies to integral types
+ DLONG only applies to long and unsigned long types and says that these
+ are actually longer than an int
+*/
+
+#define CHAR 0x01
+#define SHORT 0x02
+#define INT 0x04
+#define LONG 0x08
+#define FLOAT 0x10
+#define DOUBLE 0x20
+#define UNSIGNED 0x40
+#define DLONG 0x80
+
+#define ISCALAR (CHAR | SHORT | INT | LONG)
+#define RSCALAR (FLOAT | DOUBLE)
+
+/*
+ flags for type constructor
+ at most 1 of the flags may be set (none for scalar types)
+ flags are used for fast testing for array/pointer
+*/
+
+#define ARRAY 1
+#define FUNCTION 2
+#define POINTER 4
+#define STRUCTU 8
+#define VOID 0x10
+
+/* type sizes */
+/* default sizes and long and float sizes are hard-coded into type data */
+
+extern uoffset_t ctypesize;
+extern uoffset_t dtypesize;
+extern uoffset_t ftypesize;
+extern uoffset_t itypesize;
+extern uoffset_t ptypesize;
+extern uoffset_t stypesize;
+
+/* basic scalar types */
+
+EXTERN struct typestruct *dtype;
+EXTERN struct typestruct *fltype;
+EXTERN struct typestruct *itype;
+EXTERN struct typestruct *ltype;
+EXTERN struct typestruct *sctype;
+EXTERN struct typestruct *stype;
+EXTERN struct typestruct *uctype;
+EXTERN struct typestruct *uitype;
+EXTERN struct typestruct *ultype;
+EXTERN struct typestruct *ustype;
+EXTERN struct typestruct *vtype;
+
+/* working type */
+
+EXTERN struct typestruct *ctype;
+
+/* constructed types */
+
+EXTERN struct typestruct *fitype;
+EXTERN struct typestruct *pctype;
+
+/* return type of current function */
+
+EXTERN struct typestruct *returntype;
diff --git a/bcc-bruce/types.h b/bcc-bruce/types.h
new file mode 100644
index 0000000..547637c
--- /dev/null
+++ b/bcc-bruce/types.h
@@ -0,0 +1,206 @@
+/* types.h - type definitions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ source types big enough to handle target quantities
+ these have to be match the source compiler and target machine
+ this is impossible if the source long type is too small
+*/
+
+typedef unsigned char char_t; /* target char */
+typedef long value_t; /* target ints, longs and offsets */
+typedef unsigned long uvalue_t; /* target unsigned ints, longs and offsets */
+
+#ifdef I8088
+typedef long offset_t; /* target machine offset */
+typedef unsigned long uoffset_t; /* target unsigned machine offset */
+#define outuvalue outhex
+#define outvalue outshex
+#endif
+#ifdef MC6809
+typedef int offset_t;
+typedef unsigned uoffset_t;
+#endif
+
+
+/*
+ storage class type must hold all the flags defined elsewhere
+ it must have a few more bits than the target has registers
+*/
+
+#ifdef I8088
+typedef unsigned store_pt; /* promoted store_t */
+typedef unsigned store_t; /* storage class flags */
+#endif
+#ifdef MC6809
+# if __STDC__
+typedef int store_pt;
+# else
+typedef unsigned store_pt;
+# endif
+typedef unsigned char store_t;
+#endif
+
+
+/*
+ types for library routines
+*/
+
+typedef int fd_t; /* file descriptor */
+
+
+/*
+ basic scalar types - may be tuned to suit machine
+*/
+
+typedef int fastin_pt; /* promoted fastin_t */
+ /* always an int - use to show that the */
+ /* value may be accessed as a fastin_t */
+typedef char fastin_t; /* fast int - a small integer value */
+ /* on some machines, chars can be accessed */
+ /* more efficiently than ints for arithmetic */
+ /* such as comparing and masking which */
+ /* does not requiring promotion */
+ /* change to int if chars are inefficient */
+ /* or if char has < 8 bits */
+typedef int smalin_pt; /* promoted smalin_t */
+typedef char smalin_t; /* small int - a small integer value */
+ /* on most machines, chars are stored in */
+ /* less space than any other type */
+ /* change to fastin_t if this is not true */
+ /* or if char has < 8 bits */
+ /* or if space is not a limiting factor */
+#if __STDC__
+typedef int smalu_pt;
+#else
+typedef unsigned smalu_pt;
+#endif
+typedef unsigned char smalu_t;
+
+
+/*
+ derived scalar types
+ the types containing bit flags fit in an 8 bit smalin_t
+*/
+
+typedef fastin_pt bool_pt; /* promoted bool_t */
+typedef fastin_t bool_t; /* boolean: TRUE if nonzero */
+typedef fastin_pt ccode_pt; /* promoted ccode_t */
+typedef fastin_t ccode_t; /* condition code code */
+typedef smalu_pt constr_pt; /* promoted constr_t */
+typedef smalu_t constr_t; /* type constructor flags */
+typedef smalu_pt indn_pt; /* promoted indn_t */
+typedef smalu_t indn_t; /* storage indirection count */
+typedef unsigned label_t; /* label number */
+typedef smalu_t maclev_t; /* macro expansion level */
+typedef smalin_pt op_pt; /* promoted op_t */
+typedef smalin_t op_t; /* operator code */
+typedef smalu_t sc_t; /* storage class flags */
+typedef smalu_pt scalar_pt; /* promoted scalar_t */
+typedef smalu_t scalar_t; /* type scalar flags */
+typedef smalu_t scopelev_t; /* scope level */
+typedef fastin_pt sym_pt; /* promoted sym_t */
+typedef fastin_t sym_t; /* symbol code from scanner */
+typedef smalu_t weight_t; /* expression tree node weight */
+
+
+/*
+ derived structure types
+ the fields are ordered in a way that is most space-efficient
+ when smalin_t is char and smalu_t is unsigned char
+ the first element of the structures is the one most frequently accessed
+*/
+
+/*
+ expression table entry format
+*/
+
+struct nodestruct
+{
+ op_t tag;
+ weight_t weight;
+ smalu_t flags;
+ struct typestruct *nodetype;
+ union nodeunion
+ {
+ struct nodestruct *nodeptr;
+ struct symstruct *symptr;
+ } left;
+ struct nodestruct *right;
+};
+
+/*
+ symbol table entry format
+*/
+
+struct symstruct
+{
+ store_t storage;
+ indn_t indcount;
+ sc_t flags;
+ scopelev_t level;
+ struct symstruct *next;
+ struct symstruct **prev;
+ struct typestruct *type;
+ union
+ {
+ double *offd; /* value for double constants */
+ offset_t offi; /* offset for register or global storage */
+ label_t offlabel; /* label number for strings */
+ char *offp; /* to string for macro definitions */
+ sym_pt offsym; /* symbol code for keywords */
+ value_t offv; /* value for integral constants */
+ }
+ offset;
+ union
+ {
+ label_t label; /* label number for strings */
+ char namea[1]; /* variable length array for declarations */
+ char *namep; /* to constant storage for exprs */
+ }
+ name;
+};
+
+/*
+ type table entry format
+*/
+
+struct typestruct
+{
+ scalar_t scalar; /* scalar type flags u d f l i s c */
+ constr_t constructor; /* constructed type flags a f p s/u */
+ char structkey[2]; /* unique prefix for member names */
+ /* ranges from "\001\001" to "@\377" */
+ /* avoiding nulls */
+ uoffset_t alignmask; /* alignment mask, typesize - 1 for scalars */
+ uoffset_t typesize; /* size of this type */
+ char *tname; /* name of scalar type or constructor */
+ struct typelist *listtype; /* list of member types */
+ struct typestruct *nexttype;
+ /* next in list */
+ struct typestruct *prevtype;
+ /* previous in list */
+ struct typestruct *sidetype;
+ /* next in sideways list */
+};
+
+/*
+ list of type structures
+*/
+
+struct typelist
+{
+ struct typelist *tlnext;
+ struct typestruct *tltype;
+};
+
+
+/*
+ definitions to avoid passing raw NULLs to functions
+*/
+
+#define NULLNODE ((struct nodestruct *) NULL)
+#define NULLTYPE ((struct typestruct *) NULL)
+
+#include "proto.h"
diff --git a/bcc-linux16.patch b/bcc-linux16.patch
new file mode 100644
index 0000000..6fe0ad2
--- /dev/null
+++ b/bcc-linux16.patch
@@ -0,0 +1,444 @@
+diff -Nurd bcc-bruce/COPYING bcc-linux16/COPYING
+--- bcc-bruce/COPYING Thu Jan 1 01:00:00 1970
++++ bcc-linux16/COPYING Sun Mar 26 10:39:11 1995
+@@ -0,0 +1,339 @@
++ GNU GENERAL PUBLIC LICENSE
++ Version 2, June 1991
++
++ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
++ 675 Mass Ave, Cambridge, MA 02139, USA
++ Everyone is permitted to copy and distribute verbatim copies
++ of this license document, but changing it is not allowed.
++
++ Preamble
++
++ The licenses for most software are designed to take away your
++freedom to share and change it. By contrast, the GNU General Public
++License is intended to guarantee your freedom to share and change free
++software--to make sure the software is free for all its users. This
++General Public License applies to most of the Free Software
++Foundation's software and to any other program whose authors commit to
++using it. (Some other Free Software Foundation software is covered by
++the GNU Library General Public License instead.) You can apply it to
++your programs, too.
++
++ When we speak of free software, we are referring to freedom, not
++price. Our General Public Licenses are designed to make sure that you
++have the freedom to distribute copies of free software (and charge for
++this service if you wish), that you receive source code or can get it
++if you want it, that you can change the software or use pieces of it
++in new free programs; and that you know you can do these things.
++
++ To protect your rights, we need to make restrictions that forbid
++anyone to deny you these rights or to ask you to surrender the rights.
++These restrictions translate to certain responsibilities for you if you
++distribute copies of the software, or if you modify it.
++
++ For example, if you distribute copies of such a program, whether
++gratis or for a fee, you must give the recipients all the rights that
++you have. You must make sure that they, too, receive or can get the
++source code. And you must show them these terms so they know their
++rights.
++
++ We protect your rights with two steps: (1) copyright the software, and
++(2) offer you this license which gives you legal permission to copy,
++distribute and/or modify the software.
++
++ Also, for each author's protection and ours, we want to make certain
++that everyone understands that there is no warranty for this free
++software. If the software is modified by someone else and passed on, we
++want its recipients to know that what they have is not the original, so
++that any problems introduced by others will not reflect on the original
++authors' reputations.
++
++ Finally, any free program is threatened constantly by software
++patents. We wish to avoid the danger that redistributors of a free
++program will individually obtain patent licenses, in effect making the
++program proprietary. To prevent this, we have made it clear that any
++patent must be licensed for everyone's free use or not licensed at all.
++
++ The precise terms and conditions for copying, distribution and
++modification follow.
++
++ GNU GENERAL PUBLIC LICENSE
++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
++
++ 0. This License applies to any program or other work which contains
++a notice placed by the copyright holder saying it may be distributed
++under the terms of this General Public License. The "Program", below,
++refers to any such program or work, and a "work based on the Program"
++means either the Program or any derivative work under copyright law:
++that is to say, a work containing the Program or a portion of it,
++either verbatim or with modifications and/or translated into another
++language. (Hereinafter, translation is included without limitation in
++the term "modification".) Each licensee is addressed as "you".
++
++Activities other than copying, distribution and modification are not
++covered by this License; they are outside its scope. The act of
++running the Program is not restricted, and the output from the Program
++is covered only if its contents constitute a work based on the
++Program (independent of having been made by running the Program).
++Whether that is true depends on what the Program does.
++
++ 1. You may copy and distribute verbatim copies of the Program's
++source code as you receive it, in any medium, provided that you
++conspicuously and appropriately publish on each copy an appropriate
++copyright notice and disclaimer of warranty; keep intact all the
++notices that refer to this License and to the absence of any warranty;
++and give any other recipients of the Program a copy of this License
++along with the Program.
++
++You may charge a fee for the physical act of transferring a copy, and
++you may at your option offer warranty protection in exchange for a fee.
++
++ 2. You may modify your copy or copies of the Program or any portion
++of it, thus forming a work based on the Program, and copy and
++distribute such modifications or work under the terms of Section 1
++above, provided that you also meet all of these conditions:
++
++ a) You must cause the modified files to carry prominent notices
++ stating that you changed the files and the date of any change.
++
++ b) You must cause any work that you distribute or publish, that in
++ whole or in part contains or is derived from the Program or any
++ part thereof, to be licensed as a whole at no charge to all third
++ parties under the terms of this License.
++
++ c) If the modified program normally reads commands interactively
++ when run, you must cause it, when started running for such
++ interactive use in the most ordinary way, to print or display an
++ announcement including an appropriate copyright notice and a
++ notice that there is no warranty (or else, saying that you provide
++ a warranty) and that users may redistribute the program under
++ these conditions, and telling the user how to view a copy of this
++ License. (Exception: if the Program itself is interactive but
++ does not normally print such an announcement, your work based on
++ the Program is not required to print an announcement.)
++
++These requirements apply to the modified work as a whole. If
++identifiable sections of that work are not derived from the Program,
++and can be reasonably considered independent and separate works in
++themselves, then this License, and its terms, do not apply to those
++sections when you distribute them as separate works. But when you
++distribute the same sections as part of a whole which is a work based
++on the Program, the distribution of the whole must be on the terms of
++this License, whose permissions for other licensees extend to the
++entire whole, and thus to each and every part regardless of who wrote it.
++
++Thus, it is not the intent of this section to claim rights or contest
++your rights to work written entirely by you; rather, the intent is to
++exercise the right to control the distribution of derivative or
++collective works based on the Program.
++
++In addition, mere aggregation of another work not based on the Program
++with the Program (or with a work based on the Program) on a volume of
++a storage or distribution medium does not bring the other work under
++the scope of this License.
++
++ 3. You may copy and distribute the Program (or a work based on it,
++under Section 2) in object code or executable form under the terms of
++Sections 1 and 2 above provided that you also do one of the following:
++
++ a) Accompany it with the complete corresponding machine-readable
++ source code, which must be distributed under the terms of Sections
++ 1 and 2 above on a medium customarily used for software interchange; or,
++
++ b) Accompany it with a written offer, valid for at least three
++ years, to give any third party, for a charge no more than your
++ cost of physically performing source distribution, a complete
++ machine-readable copy of the corresponding source code, to be
++ distributed under the terms of Sections 1 and 2 above on a medium
++ customarily used for software interchange; or,
++
++ c) Accompany it with the information you received as to the offer
++ to distribute corresponding source code. (This alternative is
++ allowed only for noncommercial distribution and only if you
++ received the program in object code or executable form with such
++ an offer, in accord with Subsection b above.)
++
++The source code for a work means the preferred form of the work for
++making modifications to it. For an executable work, complete source
++code means all the source code for all modules it contains, plus any
++associated interface definition files, plus the scripts used to
++control compilation and installation of the executable. However, as a
++special exception, the source code distributed need not include
++anything that is normally distributed (in either source or binary
++form) with the major components (compiler, kernel, and so on) of the
++operating system on which the executable runs, unless that component
++itself accompanies the executable.
++
++If distribution of executable or object code is made by offering
++access to copy from a designated place, then offering equivalent
++access to copy the source code from the same place counts as
++distribution of the source code, even though third parties are not
++compelled to copy the source along with the object code.
++
++ 4. You may not copy, modify, sublicense, or distribute the Program
++except as expressly provided under this License. Any attempt
++otherwise to copy, modify, sublicense or distribute the Program is
++void, and will automatically terminate your rights under this License.
++However, parties who have received copies, or rights, from you under
++this License will not have their licenses terminated so long as such
++parties remain in full compliance.
++
++ 5. You are not required to accept this License, since you have not
++signed it. However, nothing else grants you permission to modify or
++distribute the Program or its derivative works. These actions are
++prohibited by law if you do not accept this License. Therefore, by
++modifying or distributing the Program (or any work based on the
++Program), you indicate your acceptance of this License to do so, and
++all its terms and conditions for copying, distributing or modifying
++the Program or works based on it.
++
++ 6. Each time you redistribute the Program (or any work based on the
++Program), the recipient automatically receives a license from the
++original licensor to copy, distribute or modify the Program subject to
++these terms and conditions. You may not impose any further
++restrictions on the recipients' exercise of the rights granted herein.
++You are not responsible for enforcing compliance by third parties to
++this License.
++
++ 7. If, as a consequence of a court judgment or allegation of patent
++infringement or for any other reason (not limited to patent issues),
++conditions are imposed on you (whether by court order, agreement or
++otherwise) that contradict the conditions of this License, they do not
++excuse you from the conditions of this License. If you cannot
++distribute so as to satisfy simultaneously your obligations under this
++License and any other pertinent obligations, then as a consequence you
++may not distribute the Program at all. For example, if a patent
++license would not permit royalty-free redistribution of the Program by
++all those who receive copies directly or indirectly through you, then
++the only way you could satisfy both it and this License would be to
++refrain entirely from distribution of the Program.
++
++If any portion of this section is held invalid or unenforceable under
++any particular circumstance, the balance of the section is intended to
++apply and the section as a whole is intended to apply in other
++circumstances.
++
++It is not the purpose of this section to induce you to infringe any
++patents or other property right claims or to contest validity of any
++such claims; this section has the sole purpose of protecting the
++integrity of the free software distribution system, which is
++implemented by public license practices. Many people have made
++generous contributions to the wide range of software distributed
++through that system in reliance on consistent application of that
++system; it is up to the author/donor to decide if he or she is willing
++to distribute software through any other system and a licensee cannot
++impose that choice.
++
++This section is intended to make thoroughly clear what is believed to
++be a consequence of the rest of this License.
++
++ 8. If the distribution and/or use of the Program is restricted in
++certain countries either by patents or by copyrighted interfaces, the
++original copyright holder who places the Program under this License
++may add an explicit geographical distribution limitation excluding
++those countries, so that distribution is permitted only in or among
++countries not thus excluded. In such case, this License incorporates
++the limitation as if written in the body of this License.
++
++ 9. The Free Software Foundation may publish revised and/or new versions
++of the General Public License from time to time. Such new versions will
++be similar in spirit to the present version, but may differ in detail to
++address new problems or concerns.
++
++Each version is given a distinguishing version number. If the Program
++specifies a version number of this License which applies to it and "any
++later version", you have the option of following the terms and conditions
++either of that version or of any later version published by the Free
++Software Foundation. If the Program does not specify a version number of
++this License, you may choose any version ever published by the Free Software
++Foundation.
++
++ 10. If you wish to incorporate parts of the Program into other free
++programs whose distribution conditions are different, write to the author
++to ask for permission. For software which is copyrighted by the Free
++Software Foundation, write to the Free Software Foundation; we sometimes
++make exceptions for this. Our decision will be guided by the two goals
++of preserving the free status of all derivatives of our free software and
++of promoting the sharing and reuse of software generally.
++
++ NO WARRANTY
++
++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
++REPAIR OR CORRECTION.
++
++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
++POSSIBILITY OF SUCH DAMAGES.
++
++ END OF TERMS AND CONDITIONS
++
++ Appendix: How to Apply These Terms to Your New Programs
++
++ If you develop a new program, and you want it to be of the greatest
++possible use to the public, the best way to achieve this is to make it
++free software which everyone can redistribute and change under these terms.
++
++ To do so, attach the following notices to the program. It is safest
++to attach them to the start of each source file to most effectively
++convey the exclusion of warranty; and each file should have at least
++the "copyright" line and a pointer to where the full notice is found.
++
++ <one line to give the program's name and a brief idea of what it does.>
++ Copyright (C) 19yy <name of author>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++Also add information on how to contact you by electronic and paper mail.
++
++If the program is interactive, make it output a short notice like this
++when it starts in an interactive mode:
++
++ Gnomovision version 69, Copyright (C) 19yy name of author
++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
++ This is free software, and you are welcome to redistribute it
++ under certain conditions; type `show c' for details.
++
++The hypothetical commands `show w' and `show c' should show the appropriate
++parts of the General Public License. Of course, the commands you use may
++be called something other than `show w' and `show c'; they could even be
++mouse-clicks or menu items--whatever suits your program.
++
++You should also get your employer (if you work as a programmer) or your
++school, if any, to sign a "copyright disclaimer" for the program, if
++necessary. Here is a sample; alter the names:
++
++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
++ `Gnomovision' (which makes passes at compilers) written by James Hacker.
++
++ <signature of Ty Coon>, 1 April 1989
++ Ty Coon, President of Vice
++
++This General Public License does not permit incorporating your program into
++proprietary programs. If your program is a subroutine library, you may
++consider it more useful to permit linking proprietary applications with the
++library. If this is what you want to do, use the GNU Library General
++Public License instead of this License.
+diff -Nurd bcc-bruce/Makefile bcc-linux16/Makefile
+--- bcc-bruce/Makefile Tue Jul 25 19:27:02 1995
++++ bcc-linux16/Makefile Mon Nov 6 23:06:11 1995
+@@ -1,27 +1,23 @@
+-#
+-# Build bcc
+-#
+-
+-all: bcc bcc-cc1
+-
+-CFLAGS = -DLOCALPREFIX="\"/usr/local\"" -O2
++CFLAGS =-O2
++LDFLAGS =
++CC = gcc
+
+-SRCS =assign.c declare.c gencode.c label.c preserve.c type.c \
+- bcc-cc1.c express.c genloads.c loadexp.c scan.c \
+- exptree.c glogcode.c longop.c softop.c codefrag.c \
+- floatop.c hardop.c output.c state.c debug.c function.c \
+- input.c preproc.c table.c
++bcc: bcc.c
++ $(CC) $(CFLAGS) $(LDFLAGS) $@.c -o $@
+
+-OBJS =assign.o declare.o gencode.o label.o preserve.o type.o \
+- bcc-cc1.o express.o genloads.o loadexp.o scan.o \
+- exptree.o glogcode.o longop.o softop.o codefrag.o \
+- floatop.o hardop.o output.o state.o debug.o function.o \
+- input.o preproc.o table.o
++bcc09: bcc.c
++ $(CC) -DMC6809 $(CFLAGS) $(LDFLAGS) bcc.c -o $@
+
++ccc: bcc.c
++ $(CC) -DCCC $(CFLAGS) $(LDFLAGS) bcc.c -o $@
+
+-bcc: bcc.c
+- $(CC) $(CFLAGS) -o bcc bcc.c
++SOURCES = bcc-cc1.c codefrag.c debug.c declare.c express.c exptree.c floatop.c \
++ function.c gencode.c genloads.c glogcode.c hardop.c input.c label.c \
++ loadexp.c longop.c output.c preproc.c preserve.c scan.c softop.c \
++ state.c table.c type.c assign.c
+
+-bcc-cc1: $(OBJS)
+- $(CC) $(CFLAGS) -o bcc-cc1 $(OBJS)
++bcc-cc1: $(SOURCES)
++ $(CC) $(CFLAGS) $(LDFLAGS) $(SOURCES) -o bcc-cc1
+
++clean:
++ rm -f bcc bcc09 ccc
+diff -Nurd bcc-bruce/README bcc-linux16/README
+--- bcc-bruce/README Thu Jan 1 01:00:00 1970
++++ bcc-linux16/README Mon Nov 6 23:07:46 1995
+@@ -0,0 +1,8 @@
++ This is a source distribution of bcc designed for use with as86 and
++ld86 (part of the bin86 package). I have altered the Makefile so that bcc-cc1
++can be made from the Makefile (it does not check for dependancies, so it can
++be slow. bcc and bcc-cc1 are both needed to build Linux/16.
++
++ - Chad Page
++ page0588@sundance.sjsu.edu
++
+diff -Nurd bcc-bruce/VERSION bcc-linux16/VERSION
+--- bcc-bruce/VERSION Thu Jan 1 01:00:00 1970
++++ bcc-linux16/VERSION Sun Mar 26 10:48:18 1995
+@@ -0,0 +1 @@
++1995 Mar 12 10:29 UTC
+Binary files bcc-bruce/bcc and bcc-linux16/bcc differ
+Binary files bcc-bruce/bcc-cc1 and bcc-linux16/bcc-cc1 differ
+diff -Nurd bcc-bruce/bcc.c bcc-linux16/bcc.c
+--- bcc-bruce/bcc.c Tue Jul 25 19:18:16 1995
++++ bcc-linux16/bcc.c Mon Nov 6 23:05:59 1995
+@@ -32,15 +32,15 @@
+ #define BCC86
+ #define CC1 "bcc-cc1"
+ #define CC1_MINUS_O_BROKEN FALSE
+-#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */
++#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */
+ #define CPPFLAGS "-E"
+-#define CRT0 "crt0.o"
++#define CRT0 "ncrtso.o"
+ #define GCC "gcc"
+ #define LD "ld86"
+-#define STANDARD_CRT0_0_PREFIX LOCALPREFIX "/lib/bcc/i86/"
+-#define STANDARD_CRT0_3_PREFIX LOCALPREFIX "/lib/bcc/i386/"
+-#define STANDARD_EXEC_PREFIX LOCALPREFIX "/lib/bcc/"
+-#define STANDARD_EXEC_PREFIX_2 LOCALPREFIX "/bin/"
++#define STANDARD_CRT0_0_PREFIX "/usr/home/minix/lib/"
++#define STANDARD_CRT0_3_PREFIX "/usr/home/minix/lib/"
++#define STANDARD_EXEC_PREFIX "/usr/bin/"
++#define STANDARD_EXEC_PREFIX_2 "/usr/bin/"
+
+ #ifdef CCC
+ #undef BCC86
+@@ -207,7 +207,7 @@
+ addarg(&ldargs, "-i");
+ #endif
+ #ifdef BAS86
+- addarg(&ldrargs, "-r");
++ addarg(&ldrargs, "-r -0");
+ #endif
+
+ /* Pass 1 over argv to gather compile options. */
diff --git a/bin86-0.3/ChangeLog b/bin86-0.3/ChangeLog
new file mode 100644
index 0000000..1e6d936
--- /dev/null
+++ b/bin86-0.3/ChangeLog
@@ -0,0 +1,67 @@
+Tue May 16 22:01:05 1995 H.J. Lu (hjl@nynexst.com)
+
+ * version 0.3 is released.
+
+ * Makefile: fix a few typos.
+
+ * as/const.h: include "endian.h".
+ (LOW_BYTE): check the byte order.
+
+ * Makefile (endian.h): new target.
+ (const.h): depend on endian.h.
+
+ * as/det_endian.c: new from glibc.
+
+Sat Mar 18 16:39:19 1995 Francois-Rene Rideau (rideau@clipper.ens.fr)
+
+ * as/pops.c (doif): support nested conditionals.
+
+Mon Nov 21 22:48:26 1994 H.J. Lu (hlu@nighthawk)
+
+ * version 0.2 is released.
+
+ * Makefile (MFLAGS): new. add BINDIR and CC.
+
+Fri Nov 18 22:25:24 1994 Package Maintainer (opt@calum.csclub.uwaterloo.ca)
+
+ * ./as/Makefile:
+ * ./as/const.h:
+ * ./as/proto.h:
+ * ./as/readsrc.c:
+ * ./as/type.h:
+ * ./ld/Makefile:
+ * ./ld/align.h:
+ * ./ld/config.h:
+ * ./ld/type.h:
+ * ./ld/typeconv.c: remove endian dependency.
+
+Thu Mar 3 15:12:23 1994 H.J. Lu (hlu@nighthawk)
+
+ * version 0.1 is released.
+
+ * Makefile: new.
+
+ * a.out.h/bsd-a.out.h (struct exec): use short form if
+ __linux__ is defined.
+
+ * as/Makefile: minor changes.
+ (CLFAGS): add -I../a.out.h.
+
+ * ld/Makefile: minor changes.
+ (CLFAGS): add -I../a.out.h.
+
+ * ld/io.c (MY_STAT_H): don't define it if __linux__ is
+ defined.
+
+ * ld/ld.c (flag['z']): initialized to 0 if __linux__ is
+ defined.
+
+ * ld/obj.h (roundup):
+ * ld/writebin.c (roundup):
+ ld/readobj.c (roundup): change that to ld_roundup to avoid the
+ conflict with the system's roundup.
+
+ * ld/writebin.c: cleanup for the latest Linux C library.
+ (FILEHEADERLENGTH): change to sizeof (struct exec).
+ don't write a_trsize and its friends.
+
diff --git a/bin86-0.3/Makefile b/bin86-0.3/Makefile
new file mode 100644
index 0000000..62a0730
--- /dev/null
+++ b/bin86-0.3/Makefile
@@ -0,0 +1,36 @@
+CC=gcc
+CFLAGS=-O6 -fomit-frame-pointer
+LDFLAGS=
+# Where to get strtoul ()?
+#LIBS=-liberty
+DIRS=ld as
+
+BINDIR=/usr/gnu/i486-linux/bin
+AS86=i486-linux-ld86
+LD86=i486-linux-ld86
+
+BINDIR=/usr/bin
+AS86=as86
+LD86=ld86
+
+STRIP=strip
+
+MFLAGS= "LIBS=$(LIBS)" \
+ "CFLAGS=$(CFLAGS)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "CC=$(CC)"
+
+all:
+ for d in $(DIRS); do \
+ (cd $$d; $(MAKE) $(MFLAGS) $@;); \
+ done
+
+install: all
+ cp as/as86 $(BINDIR)/$(AS86)
+ cp ld/ld86 $(BINDIR)/$(LD86)
+ $(STRIP) $(BINDIR)/$(AS86) $(BINDIR)/$(LD86)
+
+depend clean clobber:
+ for d in $(DIRS); do \
+ (cd $$d; $(MAKE) $(MFLAGS) $@;); \
+ done
diff --git a/bin86-0.3/README b/bin86-0.3/README
new file mode 100644
index 0000000..f91a9dc
--- /dev/null
+++ b/bin86-0.3/README
@@ -0,0 +1,79 @@
+To build this real mode as/ld for x86, just edit Makefile and then
+do
+
+make install
+
+It is only tested under SunOS 4.1.3 and Linux.
+
+H.J. Lu
+hjl@nynexst.com
+11/21/94
+------
+We seem to have cross bin86 for Solaris working. The most important
+changes involve alignment (it needs to be on) and byte ordering.
+Some of the patches just eliminate compiler warnings (conversion of
+pointer to integer without a cast, etc.) and some (in the Makefiles)
+reflect the local setup, and can probably be ignored (the change to $BINDIR,
+for example).
+
+ - Ian (iagoldbe@csclub.uwaterloo.ca)
+
+----
+I modified it for the latest Linux C library 4.5.21 and released it as
+bin86 0.1. It is only tested for building the Linux kernel and is not
+intended for any other purposes. To build it under Linux, just type
+
+make all
+make install
+
+It is not tested for cross-compiling. If you have any patches for
+cross-compiling, please send them to me.
+
+Thanks.
+
+
+H.J. Lu
+hjl@nynexst.com
+03/03/94
+-------------
+This is the as86 and ld86 distribution written by Bruce Evans. It's
+copyright Bruce Evans, all rights reserved although you may use and copy
+it for your personal use. It's a complete 8086 assembler and loader
+which can make 32-bit code for the 386+ processors (under linux it's
+used only to create the 16-bit bootsector and setup binaries). The
+syntax is not compatible with the GNU assembler, but closer to intel
+syntax ("wrong" order of operands etc).
+
+Hints for compiling:
+
+ - you'll need the a.out.h-files from the a.out.h directory for the
+linker. These aren't really part of the distribution, but I included
+them for ease of setup (in case you need to crosscompile etc). Do a
+ cp a.out.h/* ld/
+or similar before compiling the linker.
+
+ - the assembler needs the typeconv.o file produced by the linker
+compilation. So compile the linker first, and then do a
+ cp ld/typeconv.o as/
+before making the assembler.
+
+This distribution also contains some test-files etc that aren't actually
+needed, but as they also give some idea of the assembler syntax, I left
+them in. The directories are as follows:
+
+ as - the assembler sources (minus typeconv.c)
+ ld - linker sources
+ bcc - bruce evans' cc frontend sources (the actual compiler isn't
+ included).
+ bccfp - assembly floating point routines written by bruce evans. Note
+ that these use integer register returns, and won't work with the
+ linux libraries. They can be used as examples of as86 code.
+ a.out.h - header files for crosscompilation.
+
+Note that I am NOT the author of this package, but I'll forward any
+comments to bruce evans and I'll try to answer any questions about the
+assembler/linker I can. I just made it available as bde doesn't have
+ftp capability right now. Bruce Evans does have mail as
+<bde@runx.oz.au>.
+
+ Linus Torvalds
diff --git a/bin86-0.3/a.out.h/a.out.gnu.h b/bin86-0.3/a.out.h/a.out.gnu.h
new file mode 100644
index 0000000..bf6d4d9
--- /dev/null
+++ b/bin86-0.3/a.out.h/a.out.gnu.h
@@ -0,0 +1,276 @@
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+
+#if defined(sequent) && defined(i386)
+#define a_magic a_info
+#include <a.out.h>
+#undef a_magic
+#define __STRUCT_EXEC_OVERRIDE__
+#define N_NLIST_DECLARED
+#define N_RELOCATION_INFO_DECLARED
+#endif
+
+#define __GNU_EXEC_MACROS__
+
+#ifndef __STRUCT_EXEC_OVERRIDE__
+
+struct exec
+{
+ unsigned long a_info; /* Use macros N_MAGIC, etc for access */
+ unsigned long a_text; /* length of text, in bytes */
+ unsigned long a_data; /* length of data, in bytes */
+ unsigned long a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned long a_syms; /* length of symbol table data in file, in bytes */
+ unsigned long a_entry; /* start address */
+ unsigned long a_trsize; /* length of relocation info for text, in bytes */
+ unsigned long a_drsize; /* length of relocation info for data, in bytes */
+};
+
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+
+/* these go in the N_MACHTYPE field */
+enum machine_type {
+#if defined (M_OLDSUN2)
+ M__OLDSUN2 = M_OLDSUN2,
+#else
+ M_OLDSUN2 = 0,
+#endif
+#if defined (M_68010)
+ M__68010 = M_68010,
+#else
+ M_68010 = 1,
+#endif
+#if defined (M_68020)
+ M__68020 = M_68020,
+#else
+ M_68020 = 2,
+#endif
+#if defined (M_SPARC)
+ M__SPARC = M_SPARC,
+#else
+ M_SPARC = 3,
+#endif
+ /* skip a bunch so we don't run into any of sun's numbers */
+ M_386 = 100,
+};
+
+#if !defined (N_MAGIC)
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#endif
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0xff) << 16) \
+ | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+
+#ifndef OMAGIC
+/* Code indicating object file or impure executable. */
+#define OMAGIC 0407
+/* Code indicating pure executable. */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable. */
+#define ZMAGIC 0413
+#endif /* not OMAGIC */
+
+#if !defined (N_BADMAG)
+#define N_BADMAG(x) \
+ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC)
+#endif
+
+#define _N_BADMAG(x) \
+ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC)
+
+#define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec))
+
+#if !defined (N_TXTOFF)
+#define N_TXTOFF(x) \
+ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
+#endif
+
+#if !defined (N_DATOFF)
+#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
+#endif
+
+#if !defined (N_TRELOFF)
+#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
+#endif
+
+#if !defined (N_DRELOFF)
+#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
+#endif
+
+#if !defined (N_SYMOFF)
+#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
+#endif
+
+#if !defined (N_STROFF)
+#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
+#endif
+
+/* Address of text segment in memory after it is loaded. */
+#if !defined (N_TXTADDR)
+#define N_TXTADDR(x) 0
+#endif
+
+/* Address of data segment in memory after it is loaded.
+ Note that it is up to you to define SEGMENT_SIZE
+ on machines not listed here. */
+#if defined(vax) || defined(hp300) || defined(pyr)
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+#ifdef hp300
+#define PAGE_SIZE 4096
+#endif
+#ifdef sony
+#define SEGMENT_SIZE 0x2000
+#endif /* Sony. */
+#ifdef is68k
+#define SEGMENT_SIZE 0x20000
+#endif
+#if defined(m68k) && defined(PORTAR)
+#define PAGE_SIZE 0x400
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+
+#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
+
+#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
+ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+#endif
+
+/* Address of bss segment in memory after it is loaded. */
+#if !defined (N_BSSADDR)
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+#endif
+
+#if !defined (N_NLIST_DECLARED)
+struct nlist {
+ union {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx;
+ } n_un;
+ unsigned char n_type;
+ char n_other;
+ short n_desc;
+ unsigned long n_value;
+};
+#endif /* no N_NLIST_DECLARED. */
+
+#if !defined (N_UNDF)
+#define N_UNDF 0
+#endif
+#if !defined (N_ABS)
+#define N_ABS 2
+#endif
+#if !defined (N_TEXT)
+#define N_TEXT 4
+#endif
+#if !defined (N_DATA)
+#define N_DATA 6
+#endif
+#if !defined (N_BSS)
+#define N_BSS 8
+#endif
+#if !defined (N_COMM)
+#define N_COMM 18
+#endif
+#if !defined (N_FN)
+#define N_FN 15
+#endif
+
+#if !defined (N_EXT)
+#define N_EXT 1
+#endif
+#if !defined (N_TYPE)
+#define N_TYPE 036
+#endif
+#if !defined (N_STAB)
+#define N_STAB 0340
+#endif
+
+/* The following type indicates the definition of a symbol as being
+ an indirect reference to another symbol. The other symbol
+ appears as an undefined reference, immediately following this symbol.
+
+ Indirection is asymmetrical. The other symbol's value will be used
+ to satisfy requests for the indirect symbol, but not vice versa.
+ If the other symbol does not have a definition, libraries will
+ be searched to find a definition. */
+#define N_INDR 0xa
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ element's value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+
+#if !defined (N_RELOCATION_INFO_DECLARED)
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+struct relocation_info
+{
+ /* Address (within segment) to be relocated. */
+ unsigned long r_address;
+#if 0
+ /* The meaning of r_symbolnum depends on r_extern. */
+ unsigned int r_symbolnum:24;
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in file's the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+ /* Four bits that aren't used, but when writing an object file
+ it is desirable to clear them. */
+ unsigned int r_pad:4;
+#else
+ unsigned long foo;
+#endif
+};
+#endif /* no N_RELOCATION_INFO_DECLARED. */
+
+
+#endif /* __A_OUT_GNU_H__ */
diff --git a/bin86-0.3/a.out.h/bsd-a.out.h b/bin86-0.3/a.out.h/bsd-a.out.h
new file mode 100644
index 0000000..b59435b
--- /dev/null
+++ b/bin86-0.3/a.out.h/bsd-a.out.h
@@ -0,0 +1,108 @@
+#ifndef _BSD_A_OUT_H
+#define _BSD_A_OUT_H
+
+struct exec { /* a.out header */
+ unsigned char a_magic[2]; /* magic number */
+ unsigned char a_flags; /* flags, see below */
+ unsigned char a_cpu; /* cpu id */
+ unsigned char a_hdrlen; /* length of header */
+ unsigned char a_unused; /* reserved for future use */
+ unsigned short a_version; /* version stamp (not used at present) */
+ long a_text; /* size of text segement in bytes */
+ long a_data; /* size of data segment in bytes */
+ long a_bss; /* size of bss segment in bytes */
+ long a_entry; /* entry point */
+ long a_total; /* total memory allocated */
+ long a_syms; /* size of symbol table */
+ /* SHORT FORM ENDS HERE */
+#ifndef __linux__
+ long a_trsize; /* text relocation size */
+ long a_drsize; /* data relocation size */
+ long a_tbase; /* text relocation base */
+ long a_dbase; /* data relocation base */
+#endif
+};
+
+#define A_MAGIC0 ((unsigned char) 0x01)
+#define A_MAGIC1 ((unsigned char) 0x03)
+#define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 || (X).a_magic[1] != A_MAGIC1)
+
+/* CPU Id of TARGET machine (byte order coded in low order two bits) */
+#define A_NONE 0x00 /* unknown */
+#define A_I8086 0x04 /* intel i8086/8088 */
+#define A_M68K 0x0B /* motorola m68000 */
+#define A_NS16K 0x0C /* national semiconductor 16032 */
+#define A_I80386 0x10 /* intel i80386 */
+#define A_SPARC 0x17 /* Sun SPARC */
+
+#define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */
+#define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */
+
+/* Flags. */
+#define A_UZP 0x01 /* unmapped zero page (pages) */
+#define A_EXEC 0x10 /* executable */
+#define A_SEP 0x20 /* separate I/D */
+#define A_PURE 0x40 /* pure text */ /* not used */
+#define A_TOVLY 0x80 /* text overlay */ /* not used */
+
+/* Tell a.out.gnu.h not to define `struct exec'. */
+#define __STRUCT_EXEC_OVERRIDE__
+
+/* Hide M_386 from enum declaration in a.out.h. */
+#define M_386 HIDE_M_386
+
+#include "a.out.gnu.h"
+
+#undef M_386
+#define M_386 A_I80386
+
+#undef N_MAGIC
+#define N_MAGIC3(magic0, magic1, type) \
+ ((magic0) | ((magic1) << 8) | ((type) << 16))
+#define N_MAGIC(exec) \
+ N_MAGIC3((exec).a_magic[0], (exec).a_magic[1], (exec).a_flags)
+
+#undef N_MACHTYPE
+#define N_MACHTYPE(exec) ((enum machine_type)((exec).a_cpu))
+
+#undef N_FLAGS
+#define N_FLAGS(exec) 0
+
+#undef N_SET_INFO
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_magic[0] = (magic) & 0xff, \
+ (exec).a_magic[1] = ((magic) >> 8) & 0xff, \
+ (exec).a_flags = ((magic) >> 16) & 0xff, \
+ (exec).a_cpu = (type) & 0xff)
+
+#undef N_SET_MAGIC
+#define N_SET_MAGIC(exec, magic) \
+ ((exec).a_magic[0] = (magic) & 0xff, \
+ (exec).a_magic[1] = ((magic) >> 8) & 0xff, \
+ (exec).a_flags = ((magic) >> 16) & 0xff)
+
+#undef N_SET_MACHTYPE
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_cpu = (machtype) & 0xff, \
+ (exec).a_hdrlen = sizeof (exec))
+
+#undef N_SET_FLAGS
+#define N_SET_FLAGS(exec, flags) /* nothing */
+
+#undef OMAGIC
+#define OMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, 0)
+
+#undef NMAGIC
+#define NMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, A_EXEC)
+
+#undef ZMAGIC
+#define ZMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, A_EXEC)
+
+#undef _N_HDROFF
+#define _N_HDROFF(x) 0
+
+#define PAGE_SIZE 16
+#define SEGMENT_SIZE PAGE_SIZE
+#define getpagesize() PAGE_SIZE
+
+#endif /* _BSD_A_OUT_H */
diff --git a/bin86-0.3/as/6809/const.h b/bin86-0.3/as/6809/const.h
new file mode 100644
index 0000000..512c348
--- /dev/null
+++ b/bin86-0.3/as/6809/const.h
@@ -0,0 +1,507 @@
+/*
+ * bin86/as/6809/const.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */
+#define LOW_BYTE 0 /* must be changed for big-endian */
+
+/* const.h - constants for assembler */
+
+/* major switches */
+
+#undef I80386 /* generate 80386 code */
+#define MC6809 /* generate 6809 code */
+#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */
+#undef SOS_EDOS /* source OS is EDOS */
+
+/* defaults */
+
+#define DIRCHAR '/' /* character separating filename from dir */
+#define INBUFSIZE 8192
+#define SOS_EOLSTR "\012"
+
+/* defaults modified by switches */
+
+#ifdef SOS_EDOS
+# undef INBUFSIZE
+# define INBUFSIZE 512
+# undef SOS_EOLSTR
+# define SOS_EOLSTR "\015\012"
+# define STAKSIZ 256 /* table grows up to stack less this */
+#endif
+
+/* booleans */
+
+#define FALSE 0
+#define TRUE 1
+
+/* ASCII constants */
+
+#define ETB 23
+
+/* C tricks */
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+#define NULL 0
+
+/* O/S constants */
+
+#define CREAT_PERMS 0666
+#define EOF (-1)
+#define STDIN 0
+#define STDOUT 1
+
+/* register codes (internal to assembler) */
+
+#ifdef I80386
+
+/* index regs must be first */
+
+#define BPREG 0
+#define BXREG 1
+#define DIREG 2
+#define SIREG 3
+#define MAX16BITINDREG 3
+
+#define EAXREG 4
+#define EBPREG 5
+#define EBXREG 6
+#define ECXREG 7
+#define EDIREG 8
+#define EDXREG 9
+#define ESIREG 10
+#define ESPREG 11
+#define MAXINDREG 11
+
+#define AXREG 12
+#define CXREG 13
+#define DXREG 14
+#define SPREG 15
+
+#define AHREG 16
+#define ALREG 17
+#define BHREG 18
+#define BLREG 19
+#define CHREG 20
+#define CLREG 21
+#define DHREG 22
+#define DLREG 23
+
+#define CSREG 24
+#define DSREG 25
+#define ESREG 26
+#define FSREG 27
+#define GSREG 28
+#define SSREG 29
+
+#define CR0REG 30
+#define CR2REG 31
+#define CR3REG 32
+#define DR0REG 33
+#define DR1REG 34
+#define DR2REG 35
+#define DR3REG 36
+#define DR6REG 37
+#define DR7REG 38
+#define TR6REG 39
+#define TR7REG 40
+
+#define NOREG 41
+
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* index regs must be first, then PC, then other regs */
+
+#define AREG 5
+#define BREG 6
+#define CCREG 7
+#define DPREG 8
+#define DREG 9
+#define MAXINDREG 3
+#define NOREG 10
+#define PCREG 4
+#define SREG 0
+#define UREG 1
+#define XREG 2
+#define YREG 3
+
+#endif
+
+#ifdef I80386
+
+/* type and size keywords */
+
+#define BYTEOP 0
+#define DWORDOP 1
+#define FWORDOP 2
+#define FAROP 3
+#define PTROP 4
+#define PWORDOP 5
+#define QWORDOP 6
+#define TBYTEOP 7
+#define WORDOP 8
+#endif
+
+/* special chars */
+
+#define EOL 0
+#define MACROCHAR '?'
+
+/* symbol codes */
+
+/* the first 2 must be from chars in identifiers */
+#define IDENT 0
+#define INTCONST 1
+
+/* the next few are best for other possibly-multi-char tokens */
+#define ADDOP 2 /* also ++ */
+#define BINCONST 3
+#define CHARCONST 4
+#define GREATERTHAN 5 /* also >> and context-sensitive */
+#define HEXCONST 6
+#define LESSTHAN 7 /* also << and context-sensitive */
+#define SUBOP 8 /* also -- */
+#define WHITESPACE 9
+
+#define ANDOP 10
+#define COMMA 11
+#define EOLSYM 12
+#define EQOP 13
+#define IMMEDIATE 14
+#define INDIRECT 15
+#define LBRACKET 16
+#define LPAREN 17
+#define MACROARG 18
+#define NOTOP 19
+#define OROP 20
+#define OTHERSYM 21
+#define POSTINCOP 22
+#define PREDECOP 23
+#define RBRACKET 24
+#define RPAREN 25
+#define SLASH 26 /* context-sensitive */
+#define SLOP 27
+#define SROP 28
+#define STAR 29 /* context-sensitive */
+#define STRINGCONST 30
+#define COLON 31
+
+/* these are from assembler errors module */
+
+/* syntax errors */
+
+#define COMEXP 0
+#define DELEXP 1
+#define FACEXP 2
+#define IREGEXP 3
+#define LABEXP 4
+#define LPEXP 5
+#define OPEXP 6
+#define RBEXP 7
+#define REGEXP 8
+#define RPEXP 9
+#define SPEXP 10
+
+/* expression errors */
+
+#define ABSREQ 11
+#define NONIMPREQ 12
+#define RELBAD 13
+
+/* label errors */
+
+#define ILLAB 14
+#define MACUID 15
+#define MISLAB 16
+#define MNUID 17
+#define REGUID 18
+#define RELAB 19
+#define UNBLAB 20
+#define UNLAB 21
+#define VARLAB 22
+
+/* addressing errors */
+
+#define ABOUNDS 23
+#define DBOUNDS 24
+#define ILLMOD 25
+#define ILLREG 26
+
+/* control structure errors */
+
+#define ELSEBAD 27
+#define ELSEIFBAD 27
+#define ENDBBAD 28
+#define ENDIFBAD 27
+#define EOFBLOCK 29
+#define EOFIF 30
+
+#define EOFLC 31
+#define EOFMAC 32
+#define FAILERR 33
+
+/* overflow errors */
+
+#define BLOCKOV 34
+#define BWRAP 35
+#define COUNTOV 36
+#define COUNTUN 37
+#define GETOV 38
+#define IFOV 39
+
+#define LINLONG 40
+#define MACOV 41
+#define OBJSYMOV 42
+#define OWRITE 43
+#define PAROV 44
+#define SYMOV 45
+#define SYMOUTOV 46
+
+/* i/o errors */
+
+#define OBJOUT 47
+
+/* miscellaneous errors */
+
+#define CTLINS 48
+#define FURTHER 49
+#define NOIMPORT 50
+#define NOTIMPLEMENTED 51
+#define REENTER 52
+#define SEGREL 53
+
+/* warnings */
+
+#define MINWARN 54
+#define ALREADY 54
+#define SHORTB 55
+
+/* symbol table entry */
+
+ /* type entry contains following flags */
+#define ENTBIT (1<<0) /* entry point (=OBJ_N_MASK) */
+#define COMMBIT (1<<1) /* common */
+#define LABIT (1<<2) /* label (a PC location or defined by EQU) */
+#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */
+#define MACBIT (1<<4) /* macro */
+#define REDBIT (1<<5) /* redefined */
+#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */
+#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */
+
+ /* data entry contains following flags, valid */
+ /* for expressions as well as syms */
+#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT \ PAGE1 */
+#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT \ PAGE2 */
+#define REGBIT (1<<2) /* register = MNREGBIT \ REGBIT */
+#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT \ SIZEBIT */
+#define SEGM 15 /* 1st 4 bits reused for segment if !MNREGBIT */
+#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */
+#define FORBIT (1<<5) /* forward referenced */
+#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */
+#define UNDBIT (1<<7) /* undefined */
+
+/* pseudo-op routine numbers */
+/* conditionals are first, this is used to test if op is a conditional */
+
+#define ELSEOP 0
+#define ELSEIFOP 1
+#define ELSEIFCOP 2
+#define ENDIFOP 3
+#define IFOP 4
+#define IFCOP 5
+#define MAXCOND 6 /* limit of conditionals */
+
+#define BLOCKOP 6
+#define COMMOP 7
+#define ENDOP 8
+#define ENDBOP 9
+#define ENTEROP 10
+#define ENTRYOP 11
+#define EQUOP 12
+#define EXPORTOP 13
+#define FAILOP 14
+#define FCBOP 15
+#define FCCOP 16
+#define FDBOP 17
+#define GETOP 18
+#define IDENTOP 19
+#define IMPORTOP 20
+#define _LISTOP 21
+#define LOCOP 22
+#define _MACLISTOP 23
+#define MACROOP 24
+#define _MAPOP 25
+#define ORGOP 26
+#define RMBOP 27
+#define SETOP 28
+#define SETDPOP 29
+#define _WARNOP 30
+
+#ifdef I80386
+
+/* further pseudo-ops */
+
+#define BSSOP 31
+#define COMMOP1 32
+#define DATAOP 33
+#define TEXTOP 34
+#define USE16OP 35
+#define USE32OP 36
+
+/* machine-op routine numbers */
+
+#define ARPL 37
+#define BCC 38
+#define BOUND 39
+#define CALL 40
+#define DIVMUL 41
+#define ENTER 42
+#define GROUP1 43
+#define GROUP2 44
+#define GROUP6 45
+#define GROUP7 46
+#define GROUP8 47
+#define GvEv 48
+#define IMUL 49
+#define IN 50
+#define INCDEC 51
+#define INHER 52
+#define INHER16 53
+#define INHER32 54
+#define INHER_A 55
+#define INT 56
+#define JCC 57
+#define JCXZ 58
+#define LEA 59
+#define LOAD_FULL_POINTER 60
+#define MOV 61
+#define MOVX 62
+#define NEGNOT 63
+#define OUT 64
+#define PUSHPOP 65
+#define RET 66
+#define RETF 67
+#define SEG 68
+#define SETCC 69
+#define SH_DOUBLE 70
+#define TEST 71
+#define XCHG 72
+
+/* further pseudo-ops */
+
+#define BLKWOP 73
+#define EVENOP 74
+#define FQBOP 75
+#define ALIGNOP 76
+
+/* further machine-ops */
+
+#define CALLI 77
+
+/* yet further pseudo-ops */
+
+#define LCOMMOP 78
+#define LCOMMOP1 79
+
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* machine-op routine numbers */
+
+#define ALL 31 /* all address modes allowed, like LDA */
+#define ALTER 32 /* all but immediate, like STA */
+#define IMMED 33 /* immediate only (ANDCC, ORCC) */
+#define INDEXD 34 /* indexed (LEA's) */
+#define INHER 35 /* inherent, like CLC or CLRA */
+#define LONG 36 /* long branches */
+#define SHORT 37 /* short branches */
+#define SSTAK 38 /* S-stack (PSHS, PULS) */
+#define SWAP 39 /* TFR, EXG */
+#define USTAK 40 /* U-stack (PSHU,PULU) */
+
+/* yet further pseudo-ops */
+
+#define LCOMMOP 41
+
+#endif
+
+/* object code format (Introl) */
+
+#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */
+
+#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */
+
+#define OBJ_ABS 0x40 /* absolute code command */
+#define OBJ_OFFSET_REL 0x80 /* offset relocation command */
+#define OBJ_SET_SEG 0x20 /* set segment command */
+#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */
+#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */
+#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */
+#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */
+
+#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */
+#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */
+oops - RELBIT misplaced
+#endif
+#define OBJ_E_MASK 0x80 /* exported bit (symbols) */
+#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */
+oops - EXPBIT misplaced
+#endif
+#define OBJ_I_MASK 0x40 /* imported bit (symbols) */
+#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */
+oops - IMPBIT misplaced
+#endif
+#define OBJ_N_MASK 0x01 /* entry bit (symbols) */
+#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */
+oops - ENTBIT misplaced
+#endif
+#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */
+#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */
+#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */
+#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */
+
+#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */
+#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */
+
+#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */
+#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */
+
+#define SYMLIS_NAMELEN 26
+#define SYMLIS_LEN (sizeof (struct sym_listing_s))
+
+#define FILNAMLEN 64 /* max length of a file name */
+#define LINLEN 256 /* max length of input line */
+#define LINUM_LEN 5 /* length of formatted line number */
+
+#define SPTSIZ 1024 /* number of symbol ptrs */
+ /* pseudo-op flags */
+#define POPHI 1 /* set to print hi byte of adr */
+#define POPLO 2 /* to print lo byte of ADR */
+#define POPLC 4 /* to print LC */
+#define POPLONG 8 /* to print high word of ADR */
+#define MAXBLOCK 8 /* max nesting level of BLOCK stack */
+#define MAXGET 8 /* max nesting level of GET stack */
+#define MAXIF 8 /* max nesting level of IF stack */
+#define MACPSIZ (128/sizeof (struct schain_s))
+ /* size of macro param buffer */
+#define MAXMAC 8 /* max nesting level of macro stack */
+#define NLOC 16 /* number of location counters */
+#ifdef I80386
+#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */
+#endif
+
+/* special segments */
+
+#define BSSLOC 3
+#define DATALOC 3
+#define DPLOC 2
+#define STRLOC 1
+#define TEXTLOC 0
diff --git a/bin86-0.3/as/Makefile b/bin86-0.3/as/Makefile
new file mode 100644
index 0000000..70104e8
--- /dev/null
+++ b/bin86-0.3/as/Makefile
@@ -0,0 +1,57 @@
+CC =gcc
+CFLAGS =-O1 -fomit-frame-pointer -Dwarn=as_warn
+INC_CFLAGS =-I../a.out.h
+LDFLAGS =-s
+
+OBJS =as.o assemble.o error.o express.o \
+ genbin.o genlist.o genobj.o gensym.o \
+ keywords.o macro.o mops.o pops.o \
+ readsrc.o scan.o table.o ../ld/typeconv.o
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+
+.c.o:
+ $(CC) $(CFLAGS) $(INC_CFLAGS) -c $<
+
+all: as86
+
+as86: $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $(OBJS)
+
+clean:
+ $(RM) *.o as86 core endian.h
+
+as.o: const.h type.h byteord.h macro.h file.h flag.h globvar.h
+assemble.o: const.h type.h address.h globvar.h opcode.h scan.h
+error.o: const.h type.h
+express.o: const.h type.h address.h globvar.h scan.h source.h
+genbin.o: const.h type.h address.h file.h globvar.h
+genlist.o: const.h type.h address.h flag.h file.h globvar.h macro.h scan.h \
+ source.h
+genobj.o: const.h type.h address.h file.h globvar.h
+gensym.o: const.h type.h flag.h file.h globvar.h
+keywords.o: const.h type.h opcode.h
+macro.o: const.h type.h globvar.h scan.h macro.h
+mops.o: const.h type.h globvar.h opcode.h scan.h address.h
+pops.o: const.h type.h address.h flag.h globvar.h opcode.h scan.h
+readsrc.o: const.h type.h flag.h file.h globvar.h macro.h scan.h source.h
+scan.o: const.h type.h scan.h
+table.o: const.h type.h globvar.h scan.h
+
+const.h: endian.h
+
+endian.h: det_endian.c
+ $(CC) -o det_endian det_endian.c
+ -@if [ $$? = 0 ]; then \
+ det_endian > $@; \
+ if [ $$? = 0 ]; then \
+ rm -f det_endian; \
+ else \
+ echo Failed to create $@; \
+ exit 1; \
+ fi; \
+ else \
+ echo Failed to compile det_endian.c; \
+ exit 1; \
+ fi
diff --git a/bin86-0.3/as/address.h b/bin86-0.3/as/address.h
new file mode 100644
index 0000000..e310535
--- /dev/null
+++ b/bin86-0.3/as/address.h
@@ -0,0 +1,36 @@
+/*
+ * bin86/as/address.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* address.h - global variables involving addresses for assembler */
+
+EXTERN struct address_s lastexp;/* last expression parsed */
+
+EXTERN union
+{
+ char fcbuf[LINLEN - 6]; /* buffer for fcb and fcc data */
+ /* data is absolute in 1 char pieces */
+ /* limited by FCC\t"" etc on line */
+ struct address_s fdbuf[(LINLEN - 4) / 2];
+ /* buffer for fdb data */
+ /* data can be of any 2-byte adr type */
+ /* limited by FDB\t and commas on line */
+#if SIZEOF_OFFSET_T > 2
+ struct address_s fqbuf[(LINLEN - 4) / 4];
+ /* buffer for fqb data */
+ /* data can be of any 4-byte adr type */
+ /* limited by FQB\t and commas on line */
+#endif
+}
+ databuf;
+
+EXTERN bool_t fcflag;
+EXTERN bool_t fdflag;
+#if SIZEOF_OFFSET_T > 2
+EXTERN bool_t fqflag;
+#endif
+
+EXTERN struct address_s immadr;
+EXTERN smallcount_t immcount;
diff --git a/bin86-0.3/as/as.c b/bin86-0.3/as/as.c
new file mode 100644
index 0000000..9f91639
--- /dev/null
+++ b/bin86-0.3/as/as.c
@@ -0,0 +1,280 @@
+/*
+ * bin86/as/as.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* as.c - assembler */
+
+/*
+ usage: as source [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] [-guw]
+ in any order (but no repeated file options)
+*/
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "const.h"
+#include "type.h"
+#include "byteord.h"
+#include "macro.h"
+#undef EXTERN
+#define EXTERN
+#include "file.h"
+#include "flag.h"
+#include "globvar.h"
+
+PRIVATE struct block_s hid_blockstak[MAXBLOCK]; /* block stack */
+PRIVATE struct lc_s hid_lctab[NLOC]; /* location counter table */
+PRIVATE struct if_s hid_ifstak[MAXBLOCK]; /* if stack */
+PRIVATE struct schain_s hid_mcpar[MACPSIZ]; /* MACRO params */
+PRIVATE struct macro_s hid_macstak[MAXBLOCK]; /* macro stack */
+PRIVATE struct sym_s *hid_spt[SPTSIZ]; /* hash table */
+
+FORWARD void initp1 P((void));
+FORWARD int my_creat P((char *name, char *message));
+FORWARD void process_args P((int argc, char **argv));
+FORWARD void summary P((fd_t fd));
+FORWARD void summ_number P((unsigned num));
+FORWARD void usage P((void));
+
+#define USERMEM (sizeof(int) <= 2 ? (unsigned) 0xAC00 : (unsigned) 0x20000L)
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ heapptr = malloc(USERMEM);
+ heapend = heapptr + USERMEM;
+ if (heapptr == 0)
+ as_abort("cannot allocate memory");
+#ifdef SOS_EDOS
+ heapend = stackreg() - STAKSIZ;
+#endif
+ initp1();
+ initp1p2();
+ inst_keywords();
+ initbin();
+ initobj();
+ initsource(); /* only nec to init for unsupported mem file */
+ typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN);
+ warn.global = TRUE; /* constant */
+ process_args(argc, argv);
+ initscan();
+
+ assemble(); /* doesn't return, maybe use setjmp */
+
+ /* NOTREACHED */
+ return 0;
+}
+
+PUBLIC void as_abort(message)
+char *message;
+{
+ write(STDOUT, "as: ", 4);
+ write(STDOUT, message, strlen(message));
+ write(STDOUT, "\n", 1);
+ exit(1);
+}
+
+PUBLIC void finishup()
+{
+ bintrailer();
+ objtrailer();
+ if (list.global ||symgen)
+ gensym(); /* output to lstfil and/or symfil */
+ if (list.global ||toterr != 0 || totwarn != 0)
+ summary(lstfil);
+ if (lstfil != STDOUT && (toterr != 0 || totwarn != 0))
+ summary(STDOUT);
+ statistics();
+ exit(toterr != 0 ? 1 : 0); /* should close output files and check */
+}
+
+/* initialise constant nonzero values */
+
+PRIVATE void initp1()
+{
+#ifdef I80386
+ idefsize = defsize = sizeof (char *) > 2 ? 4 : 2;
+#endif
+ lctabtop = lctab + NLOC;
+ lstfil = STDOUT;
+ mapnum = 15; /* default map number for symbol table */
+ spt_top = (spt = hid_spt) + SPTSIZ;
+}
+
+/* initialise nonzero values which start same each pass */
+
+PUBLIC void initp1p2()
+{
+ register struct lc_s *lcp;
+
+ ifflag = TRUE;
+ pedata = UNDBIT; /* program entry point not defined */
+ blockstak = hid_blockstak + MAXBLOCK;
+ ifstak = hid_ifstak + MAXIF;
+ macstak = hid_macstak + MAXMAC;
+ macptop = (macpar = hid_mcpar) + MACPSIZ;
+ lctabtop = (lcptr = lctab = hid_lctab) + NLOC;
+ for (lcp = lctab; lcp < lctabtop; ++lcp)
+ /* init of lcdata/lc (many times) in loop to save space */
+ {
+ lcp->data = lcdata = RELBIT; /* lc relocatable until 1st ORG */
+ lcp->lc = lc = 0;
+ }
+}
+
+PRIVATE int my_creat(name, message)
+char *name;
+char *message;
+{
+ int fd;
+
+ if ((fd = creat(name, CREAT_PERMS)) < 0 || fd > 255)
+ as_abort(message);
+ return fd;
+}
+
+PRIVATE void process_args(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+ bool_t isnextarg;
+ char *nextarg;
+
+ if (argc <= 1)
+ usage();
+ do
+ {
+ arg = *++argv;
+ if (arg[0] == '-')
+ {
+ if (arg[2] != 0)
+ usage(); /* no multiple options */
+ isnextarg = FALSE;
+ if (argc > 2)
+ {
+ nextarg = argv[1];
+ if (nextarg[0] != 0 && nextarg[0] != '-')
+ isnextarg = TRUE;
+ }
+ switch (arg[1])
+ {
+#ifdef I80386
+ case '0':
+ idefsize = defsize = 0x2;
+ break;
+ case '3':
+ idefsize = defsize = 0x4;
+ break;
+ case 'a':
+ asld_compatible = TRUE;
+ break;
+#endif
+ case 'b':
+ if (!isnextarg || binfil != 0)
+ usage();
+ binfil = my_creat(nextarg, "error creating binary file");
+ binaryg = TRUE;
+ --argc;
+ ++argv;
+ break;
+ case 'g':
+ globals_only_in_obj = TRUE;
+ break;
+#ifdef I80386
+ case 'j':
+ jumps_long = TRUE;
+ break;
+#endif
+ case 'l':
+ list.global = TRUE;
+ goto get_any_list_file;
+ case 'm':
+ maclist.global = TRUE;
+ get_any_list_file:
+ if (isnextarg)
+ {
+ if (lstfil != STDOUT)
+ usage();
+ lstfil = my_creat(nextarg, "error creating list file");
+ --argc;
+ ++argv;
+ }
+ break;
+ case 'n':
+ if (!isnextarg)
+ usage();
+ truefilename = nextarg;
+ --argc;
+ ++argv;
+ break;
+ case 'o':
+ if (!isnextarg || objfil != 0)
+ usage();
+ objectg = TRUE;
+ objfil = my_creat(nextarg, "error creating object file");
+ --argc;
+ ++argv;
+ break;
+ case 's':
+ if (!isnextarg || symfil != 0)
+ usage();
+ symgen = TRUE;
+ symfil = my_creat(nextarg, "error creating symbol file");
+ --argc;
+ ++argv;
+ break;
+ case 'u':
+ inidata = IMPBIT | SEGM;
+ break;
+ case 'w':
+ warn.semaphore = -1;
+ break;
+ default:
+ usage(); /* bad option */
+ }
+ }
+ else if (infil != 0)
+ usage(); /* no multiple sources */
+ else
+ {
+ if (strlen(arg) > FILNAMLEN)
+ as_abort("source file name too long");
+ infil = open_input(strcpy(filnamptr, arg));
+ infiln = infil0 = 1;
+ }
+ }
+ while (--argc != 1);
+ inidata = (~binaryg & inidata) | (RELBIT | UNDBIT);
+} /* IMPBIT from inidata unless binaryg */
+
+PRIVATE void summary(fd)
+int fd;
+{
+ innum = fd;
+ writenl();
+ summ_number(toterr);
+ writesn(" errors");
+ summ_number(totwarn);
+ writesn(" warnings");
+}
+
+PRIVATE void summ_number(num)
+unsigned num;
+{
+ /* format number like line numbers, build it at free spot heapptr */
+ *build_number(num, LINUM_LEN, heapptr) = 0;
+ writes(heapptr);
+}
+
+PRIVATE void usage()
+{
+ as_abort(
+#ifdef I80386
+"usage: as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src");
+#else
+ "usage: as [-guw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src");
+#endif
+}
diff --git a/bin86-0.3/as/asm/calljmp.asm b/bin86-0.3/as/asm/calljmp.asm
new file mode 100644
index 0000000..36a6ea4
--- /dev/null
+++ b/bin86-0.3/as/asm/calljmp.asm
@@ -0,0 +1,70 @@
+ CALL 0x10:0x20 ; not implemented
+ CALL AL; ; illeg
+ CALL DS ; illeg
+
+ CALL REL16
+
+ CALL AX
+ CALL BX
+ CALL CX
+ CALL DX
+ CALL SP
+ CALL BP
+ CALL SI
+ CALL DI
+
+ CALL BYTE [BX] ; illeg
+ CALL [BX]
+ CALL WORD [BX]
+
+ USE32
+ CALL REL32
+
+ USE16
+ CALL EAX
+ CALL EBX
+ CALL ECX
+ CALL EDX
+ CALL ESP
+ CALL EBP
+ CALL ESI
+ CALL EDI
+
+ CALL DWORD [BX]
+
+ JMP 0x10:0x20 ; not implemented
+ JMP AL; ; illeg
+ JMP DS ; illeg
+
+ JMP REL16
+
+ JMP AX
+ JMP BX
+ JMP CX
+ JMP DX
+ JMP SP
+ JMP BP
+ JMP SI
+ JMP DI
+
+ JMP BYTE [BX] ; illeg
+ JMP [BX]
+ JMP WORD [BX]
+
+ USE32
+ JMP REL32
+
+ USE16
+ JMP EAX
+ JMP EBX
+ JMP ECX
+ JMP EDX
+ JMP ESP
+ JMP EBP
+ JMP ESI
+ JMP EDI
+
+ JMP DWORD [BX]
+
+REL16:
+REL32:
diff --git a/bin86-0.3/as/asm/ea.asm b/bin86-0.3/as/asm/ea.asm
new file mode 100644
index 0000000..8717a73
--- /dev/null
+++ b/bin86-0.3/as/asm/ea.asm
@@ -0,0 +1,109 @@
+ MOV AX,[BX+SI]
+ MOV AX,[BX+DI]
+ MOV AX,[BP+SI]
+ MOV AX,[BP+DI]
+ MOV AX,[SI]
+ MOV AX,[DI]
+ MOV AX,[0x1234]
+ MOV AX,[BX]
+
+ MOV AX,[BX+SI+0x12]
+ MOV AX,[BX+DI+0x12]
+ MOV AX,[BP+SI+0x12]
+ MOV AX,[BP+DI+0x12]
+ MOV AX,[SI+0x12]
+ MOV AX,[DI+0x12]
+ MOV AX,[BP+0x12]
+ MOV AX,[BX+0x12]
+
+ MOV AX,[BX+SI+0x1234]
+ MOV AX,[BX+DI+0x1234]
+ MOV AX,[BP+SI+0x1234]
+ MOV AX,[BP+DI+0x1234]
+ MOV AX,[SI+0x1234]
+ MOV AX,[DI+0x1234]
+ MOV AX,[BP+0x1234]
+ MOV AX,[BX+0x1234]
+
+ MOV AL,AL
+ MOV AL,AH
+ MOV AL,BL
+ MOV AL,BH
+ MOV AL,CL
+ MOV AL,CH
+ MOV AL,DL
+ MOV AL,DH
+
+ MOV AX,AX
+ MOV AX,CX
+ MOV AX,DX
+ MOV AX,BX
+ MOV AX,SP
+ MOV AX,BP
+ MOV AX,SI
+ MOV AX,DI
+
+ MOV AX,[EAX]
+ MOV AX,[ECX]
+ MOV AX,[EDX]
+ MOV AX,[EBX]
+
+ MOV AX,[0x12345678]
+ MOV AX,[ESI]
+ MOV AX,[EDI]
+
+ MOV AX,[EAX+0x12]
+ MOV AX,[ECX+0x12]
+ MOV AX,[EDX+0x12]
+ MOV AX,[EBX+0x12]
+
+ MOV AX,[EBP+0x12]
+ MOV AX,[ESI+0x12]
+ MOV AX,[EDI+0x12]
+
+ MOV AX,[EAX+0x12345678]
+ MOV AX,[ECX+0x12345678]
+ MOV AX,[EDX+0x12345678]
+ MOV AX,[EBX+0x12345678]
+
+ MOV AX,[EBP+0x12345678]
+ MOV AX,[ESI+0x12345678]
+ MOV AX,[EDI+0x12345678]
+
+ MOV EAX,EAX
+ MOV EAX,ECX
+ MOV EAX,EDX
+ MOV EAX,EBX
+ MOV EAX,ESP
+ MOV EAX,EBP
+ MOV EAX,ESI
+ MOV EAX,EDI
+
+ MOV AX,[EAX+ESI*2]
+ MOV AX,[ECX+ESI*2]
+ MOV AX,[EDX+ESI*2]
+ MOV AX,[EBX+ESI*2]
+ MOV AX,[ESP+ESI*2]
+ MOV AX,[ESI*2+0x12345678]
+ MOV AX,[ESI+ESI*2]
+ MOV AX,[EDI+ESI*2]
+
+ MOV AX,[EAX+ESI*2+0x12]
+ MOV AX,[ECX+ESI*2+0x12]
+ MOV AX,[EDX+ESI*2+0x12]
+ MOV AX,[EBX+ESI*2+0x12]
+ MOV AX,[ESP+ESI*2+0x12]
+ MOV AX,[ESP+0x12]
+ MOV AX,[EBP+ESI*2+0x12]
+ MOV AX,[ESI+ESI*2+0x12]
+ MOV AX,[EDI+ESI*2+0x12]
+
+ MOV AX,[EAX+ESI*2+0x12345678]
+ MOV AX,[ECX+ESI*2+0x12345678]
+ MOV AX,[EDX+ESI*2+0x12345678]
+ MOV AX,[EBX+ESI*2+0x12345678]
+ MOV AX,[ESP+ESI*2+0x12345678]
+ MOV AX,[ESP+0x12345678]
+ MOV AX,[EBP+ESI*2+0x12345678]
+ MOV AX,[ESI+ESI*2+0x12345678]
+ MOV AX,[EDI+ESI*2+0x12345678]
diff --git a/bin86-0.3/as/asm/each.asm b/bin86-0.3/as/asm/each.asm
new file mode 100644
index 0000000..2145489
--- /dev/null
+++ b/bin86-0.3/as/asm/each.asm
@@ -0,0 +1,145 @@
+aaa
+aad
+aam
+aas
+adc bx,[esi*4]
+add bx,[esi*4]
+and bx,[esi*4]
+arpl [esi*4],bx
+bound bx,[esi*4]
+bsf bx,[esi*4]
+bsr bx,[esi*4]
+bswap ebx
+bt [esi*4],bx
+btc [esi*4],bx
+btr [esi*4],bx
+bts [esi*4],bx
+call [esi*4]
+cbw
+cwde
+clc
+cld
+cli
+clts
+cmc
+cmp bx,[esi*4]
+cmpsb
+cmpsw
+cmpsd
+cmpxchg [esi*4],bx
+cwd
+cdq
+daa
+das
+dec [esi*4]
+div [esi*4]
+enter 0x200,3
+hlt
+idiv [esi*4]
+imul [esi*4]
+in al,0x20
+inc [esi*4]
+insb
+insw
+insd
+int 0x20
+into
+invd
+invlpg [esi*4]
+iret
+iretd
+jnz many
+many:
+jmp [esi*4]
+lahf
+lar bx,[esi*4]
+lea bx,[esi*4]
+leave
+lgdt [esi*4]
+lidt [esi*4]
+lds bx,[esi*4]
+les bx,[esi*4]
+lfs bx,[esi*4]
+lgs bx,[esi*4]
+lss bx,[esi*4]
+lldt [esi*4]
+lmsw [esi*4]
+lock
+lodsb
+lodsw
+lodsd
+loop alot
+alot:
+lsl bx,[esi*4]
+ltr [esi*4]
+mov ax,[esi*4]
+mov bx,[esi*4]
+mov cr0,eax
+movsb
+movsw
+movsd
+movsx bx,byte [esi*4]
+movzx bx,byte [esi*4]
+mul [esi*4]
+neg [esi*4]
+nop
+not [esi*4]
+or bx,[esi*4]
+out 0x20,al
+outsb
+outsw
+outsd
+pop [esi*4]
+popa
+popad
+popf
+popfd
+push [esi*4]
+pusha
+pushad
+pushf
+pushfd
+rcl [esi*4],1
+rcr [esi*4],1
+rol [esi*4],1
+ror [esi*4],1
+rep
+repe
+repz
+repne
+repnz
+ret
+retf
+sahf
+sal [esi*4],1
+sar [esi*4],1
+shl [esi*4],1
+shr [esi*4],1
+sbb bx,[esi*4]
+scasb
+scasw
+scasd
+setnz byte [esi*4]
+sgdt [esi*4]
+sidt [esi*4]
+shld [esi*4],bx,1
+shrd [esi*4],bx,1
+sldt [esi*4]
+smsw [esi*4]
+stc
+std
+sti
+stosb
+stosw
+stosd
+str [esi*4]
+sub bx,[esi*4]
+test bx,[esi*4]
+verr [esi*4]
+verw [esi*4]
+wait
+wbinvd
+xadd [esi*4],bx
+xchg bx,[esi*4]
+xlat
+xor bx,[esi*4]
diff --git a/bin86-0.3/as/asm/easlow.as b/bin86-0.3/as/asm/easlow.as
new file mode 100644
index 0000000..75d71e2
--- /dev/null
+++ b/bin86-0.3/as/asm/easlow.as
@@ -0,0 +1,1219 @@
+ MOV AL,[0]
+ MOV AH,[1]
+ MOV BL,[-1] ; illeg
+ MOV BH,[127]
+ MOV CL,[-128] ; illeg
+ MOV CH,[128]
+ MOV DL,[-129] ; illeg
+ MOV DH,[32767]
+ MOV AL,[-32768] ; illeg
+ MOV AH,[32768]
+ MOV BL,[-32769] ; illeg
+ MOV BH,[$7FFFFFFF] ; illeg
+ MOV CL,[$80000000] ; illeg
+
+ MOV AL,AL
+ MOV AL,AH
+ MOV AL,BL
+ MOV AL,BH
+ MOV AL,CL
+ MOV AL,CH
+ MOV AL,DL
+ MOV AL,DH
+
+ MOV AL,AX ; illeg
+ MOV AL,BX ; illeg
+ MOV AL,CX ; illeg
+ MOV AL,DX ; illeg
+ MOV AL,BP ; illeg
+ MOV AL,DI ; illeg
+ MOV AL,SI ; illeg
+ MOV AL,SP ; illeg
+
+ MOV AH,AL
+ MOV AH,AH
+ MOV AH,BL
+ MOV AH,BH
+ MOV AH,CL
+ MOV AH,CH
+ MOV AH,DL
+ MOV AH,DH
+
+ MOV AH,AX ; illeg
+ MOV AH,BX ; illeg
+ MOV AH,CX ; illeg
+ MOV AH,DX ; illeg
+ MOV AH,BP ; illeg
+ MOV AH,DI ; illeg
+ MOV AH,SI ; illeg
+ MOV AH,SP ; illeg
+
+ MOV BL,AL
+ MOV BL,AH
+ MOV BL,BL
+ MOV BL,BH
+ MOV BL,CL
+ MOV BL,CH
+ MOV BL,DL
+ MOV BL,DH
+
+ MOV BL,AX ; illeg
+ MOV BL,BX ; illeg
+ MOV BL,CX ; illeg
+ MOV BL,DX ; illeg
+ MOV BL,BP ; illeg
+ MOV BL,DI ; illeg
+ MOV BL,SI ; illeg
+ MOV BL,SP ; illeg
+
+ MOV BH,AL
+ MOV BH,AH
+ MOV BH,BL
+ MOV BH,BH
+ MOV BH,CL
+ MOV BH,CH
+ MOV BH,DL
+ MOV BH,DH
+
+ MOV BH,AX ; illeg
+ MOV BH,BX ; illeg
+ MOV BH,CX ; illeg
+ MOV BH,DX ; illeg
+ MOV BH,BP ; illeg
+ MOV BH,DI ; illeg
+ MOV BH,SI ; illeg
+ MOV BH,SP ; illeg
+
+ MOV CL,AL
+ MOV CL,AH
+ MOV CL,BL
+ MOV CL,BH
+ MOV CL,CL
+ MOV CL,CH
+ MOV CL,DL
+ MOV CL,DH
+
+ MOV CL,AX ; illeg
+ MOV CL,BX ; illeg
+ MOV CL,CX ; illeg
+ MOV CL,DX ; illeg
+ MOV CL,BP ; illeg
+ MOV CL,DI ; illeg
+ MOV CL,SI ; illeg
+ MOV CL,SP ; illeg
+
+ MOV CH,AL
+ MOV CH,AH
+ MOV CH,BL
+ MOV CH,BH
+ MOV CH,CL
+ MOV CH,CH
+ MOV CH,DL
+ MOV CH,DH
+
+ MOV CH,AX ; illeg
+ MOV CH,BX ; illeg
+ MOV CH,CX ; illeg
+ MOV CH,DX ; illeg
+ MOV CH,BP ; illeg
+ MOV CH,DI ; illeg
+ MOV CH,SI ; illeg
+ MOV CH,SP ; illeg
+
+ MOV DL,AL
+ MOV DL,AH
+ MOV DL,BL
+ MOV DL,BH
+ MOV DL,CL
+ MOV DL,CH
+ MOV DL,DL
+ MOV DL,DH
+
+ MOV DL,AX ; illeg
+ MOV DL,BX ; illeg
+ MOV DL,CX ; illeg
+ MOV DL,DX ; illeg
+ MOV DL,BP ; illeg
+ MOV DL,DI ; illeg
+ MOV DL,SI ; illeg
+ MOV DL,SP ; illeg
+
+ MOV DH,AL
+ MOV DH,AH
+ MOV DH,BL
+ MOV DH,BH
+ MOV DH,CL
+ MOV DH,CH
+ MOV DH,DL
+ MOV DH,DH
+
+ MOV DH,AX ; illeg
+ MOV DH,BX ; illeg
+ MOV DH,CX ; illeg
+ MOV DH,DX ; illeg
+ MOV DH,BP ; illeg
+ MOV DH,DI ; illeg
+ MOV DH,SI ; illeg
+ MOV DH,SP ; illeg
+
+ MOV AL,[AL] ; illeg
+ MOV AH,[AH] ; illeg
+ MOV BL,[BL] ; illeg
+ MOV BH,[BH] ; illeg
+ MOV CL,[CL] ; illeg
+ MOV CH,[CH] ; illeg
+ MOV DL,[DL] ; illeg
+ MOV DH,[DH] ; illeg
+
+ MOV AL,[AX] ; illeg
+ MOV AH,[BX]
+ MOV BL,[CX] ; illeg
+ MOV BH,[DX] ; illeg
+ MOV CL,[BP]
+ MOV CH,[DI]
+ MOV DL,[SI]
+ MOV DH,[SP] ; illeg
+
+ MOV AL,[AX+1] ; illeg
+ MOV AH,[BX+1]
+ MOV BL,[CX+1] ; illeg
+ MOV BH,[DX+1] ; illeg
+ MOV CL,[BP+1]
+ MOV CH,[DI+1]
+ MOV DL,[SI+1]
+ MOV DH,[SP+1] ; illeg
+
+ MOV AL,[AX-1] ; illeg
+ MOV AH,[BX-1]
+ MOV BL,[CX-1] ; illeg
+ MOV BH,[DX-1] ; illeg
+ MOV CL,[BP-1]
+ MOV CH,[DI-1]
+ MOV DL,[SI-1]
+ MOV DH,[SP-1] ; illeg
+
+ MOV AL,[AX+127] ; illeg
+ MOV AH,[BX+127]
+ MOV BL,[CX+127] ; illeg
+ MOV BH,[DX+127] ; illeg
+ MOV CL,[BP+127]
+ MOV CH,[DI+127]
+ MOV DL,[SI+127]
+ MOV DH,[SP+127] ; illeg
+
+ MOV AL,[AX-128] ; illeg
+ MOV AH,[BX-128]
+ MOV BL,[CX-128] ; illeg
+ MOV BH,[DX-128] ; illeg
+ MOV CL,[BP-128]
+ MOV CH,[DI-128]
+ MOV DL,[SI-128]
+ MOV DH,[SP-128] ; illeg
+
+ MOV AL,[AX+128] ; illeg
+ MOV AH,[BX+128]
+ MOV BL,[CX+128] ; illeg
+ MOV BH,[DX+128] ; illeg
+ MOV CL,[BP+128]
+ MOV CH,[DI+128]
+ MOV DL,[SI+128]
+ MOV DH,[SP+128] ; illeg
+
+ MOV AL,[AX-129] ; illeg
+ MOV AH,[BX-129]
+ MOV BL,[CX-129] ; illeg
+ MOV BH,[DX-129] ; illeg
+ MOV CL,[BP-129]
+ MOV CH,[DI-129]
+ MOV DL,[SI-129]
+ MOV DH,[SP-129] ; illeg
+
+ MOV AL,[AX+32767] ; illeg
+ MOV AH,[BX+32767]
+ MOV BL,[CX+32767] ; illeg
+ MOV BH,[DX+32767] ; illeg
+ MOV CL,[BP+32767]
+ MOV CH,[DI+32767]
+ MOV DL,[SI+32767]
+ MOV DH,[SP+32767] ; illeg
+
+ MOV AL,[AX-32768] ; illeg
+ MOV AH,[BX-32768]
+ MOV BL,[CX-32768] ; illeg
+ MOV BH,[DX-32768] ; illeg
+ MOV CL,[BP-32768]
+ MOV CH,[DI-32768]
+ MOV DL,[SI-32768]
+ MOV DH,[SP-32768] ; illeg
+
+ MOV AL,[AX+32768] ; illeg
+ MOV AH,[BX+32768]
+ MOV BL,[CX+32768] ; illeg
+ MOV BH,[DX+32768] ; illeg
+ MOV CL,[BP+32768]
+ MOV CH,[DI+32768]
+ MOV DL,[SI+32768]
+ MOV DH,[SP+32768] ; illeg
+
+ MOV AL,[AX-32769] ; illeg
+ MOV AH,[BX-32769]
+ MOV BL,[CX-32769] ; illeg
+ MOV BH,[DX-32769] ; illeg
+ MOV CL,[BP-32769]
+ MOV CH,[DI-32769]
+ MOV DL,[SI-32769]
+ MOV DH,[SP-32769] ; illeg
+
+ MOV AL,[AX+$7FFFFFFF] ; illeg
+ MOV AH,[BX+$7FFFFFFF] ; illeg (bounds)
+ MOV BL,[CX+$7FFFFFFF] ; illeg
+ MOV BH,[DX+$7FFFFFFF] ; illeg
+ MOV CL,[BP+$7FFFFFFF] ; illeg (bounds)
+ MOV CH,[DI+$7FFFFFFF] ; illeg (bounds)
+ MOV DL,[SI+$7FFFFFFF] ; illeg (bounds)
+ MOV DH,[SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[AX-$80000000] ; illeg
+ MOV AH,[BX-$80000000] ; illeg (bounds)
+ MOV BL,[CX-$80000000] ; illeg
+ MOV BH,[DX-$80000000] ; illeg
+ MOV CL,[BP-$80000000] ; illeg (bounds)
+ MOV CH,[DI-$80000000] ; illeg (bounds)
+ MOV DL,[SI-$80000000] ; illeg (bounds)
+ MOV DH,[SP-$80000000] ; illeg
+
+ MOV AL,[AX+AX] ; illeg
+ MOV AH,[AX+BX] ; illeg
+ MOV BL,[AX+CX] ; illeg
+ MOV BH,[AX+DX] ; illeg
+ MOV CL,[AX+BP] ; illeg
+ MOV CH,[AX+DI] ; illeg
+ MOV DL,[AX+SI] ; illeg
+ MOV DH,[AX+SP] ; illeg
+
+ MOV AL,[BX+AX] ; illeg
+ MOV AH,[BX+BX] ; illeg
+ MOV BL,[BX+CX] ; illeg
+ MOV BH,[BX+DX] ; illeg
+ MOV CL,[BX+BP] ; illeg
+ MOV CH,[BX+DI]
+ MOV DL,[BX+SI]
+ MOV DH,[BX+SP] ; illeg
+
+ MOV AL,[CX+AX] ; illeg
+ MOV AH,[CX+BX] ; illeg
+ MOV BL,[CX+CX] ; illeg
+ MOV BH,[CX+DX] ; illeg
+ MOV CL,[CX+BP] ; illeg
+ MOV CH,[CX+DI] ; illeg
+ MOV DL,[CX+SI] ; illeg
+ MOV DH,[CX+SP] ; illeg
+
+ MOV AL,[DX+AX] ; illeg
+ MOV AH,[DX+BX] ; illeg
+ MOV BL,[DX+CX] ; illeg
+ MOV BH,[DX+DX] ; illeg
+ MOV CL,[DX+BP] ; illeg
+ MOV CH,[DX+DI] ; illeg
+ MOV DL,[DX+SI] ; illeg
+ MOV DH,[DX+SP] ; illeg
+
+ MOV AL,[BP+AX] ; illeg
+ MOV AH,[BP+BX] ; illeg
+ MOV BL,[BP+CX] ; illeg
+ MOV BH,[BP+DX] ; illeg
+ MOV CL,[BP+BP] ; illeg
+ MOV CH,[BP+DI]
+ MOV DL,[BP+SI]
+ MOV DH,[BP+SP] ; illeg
+
+ MOV AL,[DI+AX] ; illeg
+ MOV AH,[DI+BX]
+ MOV BL,[DI+CX] ; illeg
+ MOV BH,[DI+DX] ; illeg
+ MOV CL,[DI+BP]
+ MOV CH,[DI+DI] ; illeg
+ MOV DL,[DI+SI] ; illeg
+ MOV DH,[DI+SP] ; illeg
+
+ MOV AL,[SI+AX] ; illeg
+ MOV AH,[SI+BX]
+ MOV BL,[SI+CX] ; illeg
+ MOV BH,[SI+DX] ; illeg
+ MOV CL,[SI+BP]
+ MOV CH,[SI+DI] ; illeg
+ MOV DL,[SI+SI] ; illeg
+ MOV DH,[SI+SP] ; illeg
+
+ MOV AL,[SP+AX] ; illeg
+ MOV AH,[SP+BX] ; illeg
+ MOV BL,[SP+CX] ; illeg
+ MOV BH,[SP+DX] ; illeg
+ MOV CL,[SP+BP] ; illeg
+ MOV CH,[SP+DI] ; illeg
+ MOV DL,[SP+SI] ; illeg
+ MOV DH,[SP+SP] ; illeg
+
+ MOV AL,[AX+AX+1] ; illeg
+ MOV AH,[AX+BX+1] ; illeg
+ MOV BL,[AX+CX+1] ; illeg
+ MOV BH,[AX+DX+1] ; illeg
+ MOV CL,[AX+BP+1] ; illeg
+ MOV CH,[AX+DI+1] ; illeg
+ MOV DL,[AX+SI+1] ; illeg
+ MOV DH,[AX+SP+1] ; illeg
+
+ MOV AL,[BX+AX+1] ; illeg
+ MOV AH,[BX+BX+1] ; illeg
+ MOV BL,[BX+CX+1] ; illeg
+ MOV BH,[BX+DX+1] ; illeg
+ MOV CL,[BX+BP+1] ; illeg
+ MOV CH,[BX+DI+1]
+ MOV DL,[BX+SI+1]
+ MOV DH,[BX+SP+1] ; illeg
+
+ MOV AL,[CX+AX+1] ; illeg
+ MOV AH,[CX+BX+1] ; illeg
+ MOV BL,[CX+CX+1] ; illeg
+ MOV BH,[CX+DX+1] ; illeg
+ MOV CL,[CX+BP+1] ; illeg
+ MOV CH,[CX+DI+1] ; illeg
+ MOV DL,[CX+SI+1] ; illeg
+ MOV DH,[CX+SP+1] ; illeg
+
+ MOV AL,[DX+AX+1] ; illeg
+ MOV AH,[DX+BX+1] ; illeg
+ MOV BL,[DX+CX+1] ; illeg
+ MOV BH,[DX+DX+1] ; illeg
+ MOV CL,[DX+BP+1] ; illeg
+ MOV CH,[DX+DI+1] ; illeg
+ MOV DL,[DX+SI+1] ; illeg
+ MOV DH,[DX+SP+1] ; illeg
+
+ MOV AL,[BP+AX+1] ; illeg
+ MOV AH,[BP+BX+1] ; illeg
+ MOV BL,[BP+CX+1] ; illeg
+ MOV BH,[BP+DX+1] ; illeg
+ MOV CL,[BP+BP+1] ; illeg
+ MOV CH,[BP+DI+1]
+ MOV DL,[BP+SI+1]
+ MOV DH,[BP+SP+1] ; illeg
+
+ MOV AL,[DI+AX+1] ; illeg
+ MOV AH,[DI+BX+1]
+ MOV BL,[DI+CX+1] ; illeg
+ MOV BH,[DI+DX+1] ; illeg
+ MOV CL,[DI+BP+1]
+ MOV CH,[DI+DI+1] ; illeg
+ MOV DL,[DI+SI+1] ; illeg
+ MOV DH,[DI+SP+1] ; illeg
+
+ MOV AL,[SI+AX+1] ; illeg
+ MOV AH,[SI+BX+1]
+ MOV BL,[SI+CX+1] ; illeg
+ MOV BH,[SI+DX+1] ; illeg
+ MOV CL,[SI+BP+1]
+ MOV CH,[SI+DI+1] ; illeg
+ MOV DL,[SI+SI+1] ; illeg
+ MOV DH,[SI+SP+1] ; illeg
+
+ MOV AL,[SP+AX+1] ; illeg
+ MOV AH,[SP+BX+1] ; illeg
+ MOV BL,[SP+CX+1] ; illeg
+ MOV BH,[SP+DX+1] ; illeg
+ MOV CL,[SP+BP+1] ; illeg
+ MOV CH,[SP+DI+1] ; illeg
+ MOV DL,[SP+SI+1] ; illeg
+ MOV DH,[SP+SP+1] ; illeg
+
+ MOV AL,[AX+AX-1] ; illeg
+ MOV AH,[AX+BX-1] ; illeg
+ MOV BL,[AX+CX-1] ; illeg
+ MOV BH,[AX+DX-1] ; illeg
+ MOV CL,[AX+BP-1] ; illeg
+ MOV CH,[AX+DI-1] ; illeg
+ MOV DL,[AX+SI-1] ; illeg
+ MOV DH,[AX+SP-1] ; illeg
+
+ MOV AL,[BX+AX-1] ; illeg
+ MOV AH,[BX+BX-1] ; illeg
+ MOV BL,[BX+CX-1] ; illeg
+ MOV BH,[BX+DX-1] ; illeg
+ MOV CL,[BX+BP-1] ; illeg
+ MOV CH,[BX+DI-1]
+ MOV DL,[BX+SI-1]
+ MOV DH,[BX+SP-1] ; illeg
+
+ MOV AL,[CX+AX-1] ; illeg
+ MOV AH,[CX+BX-1] ; illeg
+ MOV BL,[CX+CX-1] ; illeg
+ MOV BH,[CX+DX-1] ; illeg
+ MOV CL,[CX+BP-1] ; illeg
+ MOV CH,[CX+DI-1] ; illeg
+ MOV DL,[CX+SI-1] ; illeg
+ MOV DH,[CX+SP-1] ; illeg
+
+ MOV AL,[DX+AX-1] ; illeg
+ MOV AH,[DX+BX-1] ; illeg
+ MOV BL,[DX+CX-1] ; illeg
+ MOV BH,[DX+DX-1] ; illeg
+ MOV CL,[DX+BP-1] ; illeg
+ MOV CH,[DX+DI-1] ; illeg
+ MOV DL,[DX+SI-1] ; illeg
+ MOV DH,[DX+SP-1] ; illeg
+
+ MOV AL,[BP+AX-1] ; illeg
+ MOV AH,[BP+BX-1] ; illeg
+ MOV BL,[BP+CX-1] ; illeg
+ MOV BH,[BP+DX-1] ; illeg
+ MOV CL,[BP+BP-1] ; illeg
+ MOV CH,[BP+DI-1]
+ MOV DL,[BP+SI-1]
+ MOV DH,[BP+SP-1] ; illeg
+
+ MOV AL,[DI+AX-1] ; illeg
+ MOV AH,[DI+BX-1]
+ MOV BL,[DI+CX-1] ; illeg
+ MOV BH,[DI+DX-1] ; illeg
+ MOV CL,[DI+BP-1]
+ MOV CH,[DI+DI-1] ; illeg
+ MOV DL,[DI+SI-1] ; illeg
+ MOV DH,[DI+SP-1] ; illeg
+
+ MOV AL,[SI+AX-1] ; illeg
+ MOV AH,[SI+BX-1]
+ MOV BL,[SI+CX-1] ; illeg
+ MOV BH,[SI+DX-1] ; illeg
+ MOV CL,[SI+BP-1]
+ MOV CH,[SI+DI-1] ; illeg
+ MOV DL,[SI+SI-1] ; illeg
+ MOV DH,[SI+SP-1] ; illeg
+
+ MOV AL,[SP+AX-1] ; illeg
+ MOV AH,[SP+BX-1] ; illeg
+ MOV BL,[SP+CX-1] ; illeg
+ MOV BH,[SP+DX-1] ; illeg
+ MOV CL,[SP+BP-1] ; illeg
+ MOV CH,[SP+DI-1] ; illeg
+ MOV DL,[SP+SI-1] ; illeg
+ MOV DH,[SP+SP-1] ; illeg
+
+ MOV AL,[AX+AX+127] ; illeg
+ MOV AH,[AX+BX+127] ; illeg
+ MOV BL,[AX+CX+127] ; illeg
+ MOV BH,[AX+DX+127] ; illeg
+ MOV CL,[AX+BP+127] ; illeg
+ MOV CH,[AX+DI+127] ; illeg
+ MOV DL,[AX+SI+127] ; illeg
+ MOV DH,[AX+SP+127] ; illeg
+
+ MOV AL,[BX+AX+127] ; illeg
+ MOV AH,[BX+BX+127] ; illeg
+ MOV BL,[BX+CX+127] ; illeg
+ MOV BH,[BX+DX+127] ; illeg
+ MOV CL,[BX+BP+127] ; illeg
+ MOV CH,[BX+DI+127]
+ MOV DL,[BX+SI+127]
+ MOV DH,[BX+SP+127] ; illeg
+
+ MOV AL,[CX+AX+127] ; illeg
+ MOV AH,[CX+BX+127] ; illeg
+ MOV BL,[CX+CX+127] ; illeg
+ MOV BH,[CX+DX+127] ; illeg
+ MOV CL,[CX+BP+127] ; illeg
+ MOV CH,[CX+DI+127] ; illeg
+ MOV DL,[CX+SI+127] ; illeg
+ MOV DH,[CX+SP+127] ; illeg
+
+ MOV AL,[DX+AX+127] ; illeg
+ MOV AH,[DX+BX+127] ; illeg
+ MOV BL,[DX+CX+127] ; illeg
+ MOV BH,[DX+DX+127] ; illeg
+ MOV CL,[DX+BP+127] ; illeg
+ MOV CH,[DX+DI+127] ; illeg
+ MOV DL,[DX+SI+127] ; illeg
+ MOV DH,[DX+SP+127] ; illeg
+
+ MOV AL,[BP+AX+127] ; illeg
+ MOV AH,[BP+BX+127] ; illeg
+ MOV BL,[BP+CX+127] ; illeg
+ MOV BH,[BP+DX+127] ; illeg
+ MOV CL,[BP+BP+127] ; illeg
+ MOV CH,[BP+DI+127]
+ MOV DL,[BP+SI+127]
+ MOV DH,[BP+SP+127] ; illeg
+
+ MOV AL,[DI+AX+127] ; illeg
+ MOV AH,[DI+BX+127]
+ MOV BL,[DI+CX+127] ; illeg
+ MOV BH,[DI+DX+127] ; illeg
+ MOV CL,[DI+BP+127]
+ MOV CH,[DI+DI+127] ; illeg
+ MOV DL,[DI+SI+127] ; illeg
+ MOV DH,[DI+SP+127] ; illeg
+
+ MOV AL,[SI+AX+127] ; illeg
+ MOV AH,[SI+BX+127]
+ MOV BL,[SI+CX+127] ; illeg
+ MOV BH,[SI+DX+127] ; illeg
+ MOV CL,[SI+BP+127]
+ MOV CH,[SI+DI+127] ; illeg
+ MOV DL,[SI+SI+127] ; illeg
+ MOV DH,[SI+SP+127] ; illeg
+
+ MOV AL,[SP+AX+127] ; illeg
+ MOV AH,[SP+BX+127] ; illeg
+ MOV BL,[SP+CX+127] ; illeg
+ MOV BH,[SP+DX+127] ; illeg
+ MOV CL,[SP+BP+127] ; illeg
+ MOV CH,[SP+DI+127] ; illeg
+ MOV DL,[SP+SI+127] ; illeg
+ MOV DH,[SP+SP+127] ; illeg
+
+ MOV AL,[AX+AX-128] ; illeg
+ MOV AH,[AX+BX-128] ; illeg
+ MOV BL,[AX+CX-128] ; illeg
+ MOV BH,[AX+DX-128] ; illeg
+ MOV CL,[AX+BP-128] ; illeg
+ MOV CH,[AX+DI-128] ; illeg
+ MOV DL,[AX+SI-128] ; illeg
+ MOV DH,[AX+SP-128] ; illeg
+
+ MOV AL,[BX+AX-128] ; illeg
+ MOV AH,[BX+BX-128] ; illeg
+ MOV BL,[BX+CX-128] ; illeg
+ MOV BH,[BX+DX-128] ; illeg
+ MOV CL,[BX+BP-128] ; illeg
+ MOV CH,[BX+DI-128]
+ MOV DL,[BX+SI-128]
+ MOV DH,[BX+SP-128] ; illeg
+
+ MOV AL,[CX+AX-128] ; illeg
+ MOV AH,[CX+BX-128] ; illeg
+ MOV BL,[CX+CX-128] ; illeg
+ MOV BH,[CX+DX-128] ; illeg
+ MOV CL,[CX+BP-128] ; illeg
+ MOV CH,[CX+DI-128] ; illeg
+ MOV DL,[CX+SI-128] ; illeg
+ MOV DH,[CX+SP-128] ; illeg
+
+ MOV AL,[DX+AX-128] ; illeg
+ MOV AH,[DX+BX-128] ; illeg
+ MOV BL,[DX+CX-128] ; illeg
+ MOV BH,[DX+DX-128] ; illeg
+ MOV CL,[DX+BP-128] ; illeg
+ MOV CH,[DX+DI-128] ; illeg
+ MOV DL,[DX+SI-128] ; illeg
+ MOV DH,[DX+SP-128] ; illeg
+
+ MOV AL,[BP+AX-128] ; illeg
+ MOV AH,[BP+BX-128] ; illeg
+ MOV BL,[BP+CX-128] ; illeg
+ MOV BH,[BP+DX-128] ; illeg
+ MOV CL,[BP+BP-128] ; illeg
+ MOV CH,[BP+DI-128]
+ MOV DL,[BP+SI-128]
+ MOV DH,[BP+SP-128] ; illeg
+
+ MOV AL,[DI+AX-128] ; illeg
+ MOV AH,[DI+BX-128]
+ MOV BL,[DI+CX-128] ; illeg
+ MOV BH,[DI+DX-128] ; illeg
+ MOV CL,[DI+BP-128]
+ MOV CH,[DI+DI-128] ; illeg
+ MOV DL,[DI+SI-128] ; illeg
+ MOV DH,[DI+SP-128] ; illeg
+
+ MOV AL,[SI+AX-128] ; illeg
+ MOV AH,[SI+BX-128]
+ MOV BL,[SI+CX-128] ; illeg
+ MOV BH,[SI+DX-128] ; illeg
+ MOV CL,[SI+BP-128]
+ MOV CH,[SI+DI-128] ; illeg
+ MOV DL,[SI+SI-128] ; illeg
+ MOV DH,[SI+SP-128] ; illeg
+
+ MOV AL,[SP+AX-128] ; illeg
+ MOV AH,[SP+BX-128] ; illeg
+ MOV BL,[SP+CX-128] ; illeg
+ MOV BH,[SP+DX-128] ; illeg
+ MOV CL,[SP+BP-128] ; illeg
+ MOV CH,[SP+DI-128] ; illeg
+ MOV DL,[SP+SI-128] ; illeg
+ MOV DH,[SP+SP-128] ; illeg
+
+ MOV AL,[AX+AX+128] ; illeg
+ MOV AH,[AX+BX+128] ; illeg
+ MOV BL,[AX+CX+128] ; illeg
+ MOV BH,[AX+DX+128] ; illeg
+ MOV CL,[AX+BP+128] ; illeg
+ MOV CH,[AX+DI+128] ; illeg
+ MOV DL,[AX+SI+128] ; illeg
+ MOV DH,[AX+SP+128] ; illeg
+
+ MOV AL,[BX+AX+128] ; illeg
+ MOV AH,[BX+BX+128] ; illeg
+ MOV BL,[BX+CX+128] ; illeg
+ MOV BH,[BX+DX+128] ; illeg
+ MOV CL,[BX+BP+128] ; illeg
+ MOV CH,[BX+DI+128]
+ MOV DL,[BX+SI+128]
+ MOV DH,[BX+SP+128] ; illeg
+
+ MOV AL,[CX+AX+128] ; illeg
+ MOV AH,[CX+BX+128] ; illeg
+ MOV BL,[CX+CX+128] ; illeg
+ MOV BH,[CX+DX+128] ; illeg
+ MOV CL,[CX+BP+128] ; illeg
+ MOV CH,[CX+DI+128] ; illeg
+ MOV DL,[CX+SI+128] ; illeg
+ MOV DH,[CX+SP+128] ; illeg
+
+ MOV AL,[DX+AX+128] ; illeg
+ MOV AH,[DX+BX+128] ; illeg
+ MOV BL,[DX+CX+128] ; illeg
+ MOV BH,[DX+DX+128] ; illeg
+ MOV CL,[DX+BP+128] ; illeg
+ MOV CH,[DX+DI+128] ; illeg
+ MOV DL,[DX+SI+128] ; illeg
+ MOV DH,[DX+SP+128] ; illeg
+
+ MOV AL,[BP+AX+128] ; illeg
+ MOV AH,[BP+BX+128] ; illeg
+ MOV BL,[BP+CX+128] ; illeg
+ MOV BH,[BP+DX+128] ; illeg
+ MOV CL,[BP+BP+128] ; illeg
+ MOV CH,[BP+DI+128]
+ MOV DL,[BP+SI+128]
+ MOV DH,[BP+SP+128] ; illeg
+
+ MOV AL,[DI+AX+128] ; illeg
+ MOV AH,[DI+BX+128]
+ MOV BL,[DI+CX+128] ; illeg
+ MOV BH,[DI+DX+128] ; illeg
+ MOV CL,[DI+BP+128]
+ MOV CH,[DI+DI+128] ; illeg
+ MOV DL,[DI+SI+128] ; illeg
+ MOV DH,[DI+SP+128] ; illeg
+
+ MOV AL,[SI+AX+128] ; illeg
+ MOV AH,[SI+BX+128]
+ MOV BL,[SI+CX+128] ; illeg
+ MOV BH,[SI+DX+128] ; illeg
+ MOV CL,[SI+BP+128]
+ MOV CH,[SI+DI+128] ; illeg
+ MOV DL,[SI+SI+128] ; illeg
+ MOV DH,[SI+SP+128] ; illeg
+
+ MOV AL,[SP+AX+128] ; illeg
+ MOV AH,[SP+BX+128] ; illeg
+ MOV BL,[SP+CX+128] ; illeg
+ MOV BH,[SP+DX+128] ; illeg
+ MOV CL,[SP+BP+128] ; illeg
+ MOV CH,[SP+DI+128] ; illeg
+ MOV DL,[SP+SI+128] ; illeg
+ MOV DH,[SP+SP+128] ; illeg
+
+ MOV AL,[AX+AX-129] ; illeg
+ MOV AH,[AX+BX-129] ; illeg
+ MOV BL,[AX+CX-129] ; illeg
+ MOV BH,[AX+DX-129] ; illeg
+ MOV CL,[AX+BP-129] ; illeg
+ MOV CH,[AX+DI-129] ; illeg
+ MOV DL,[AX+SI-129] ; illeg
+ MOV DH,[AX+SP-129] ; illeg
+
+ MOV AL,[BX+AX-129] ; illeg
+ MOV AH,[BX+BX-129] ; illeg
+ MOV BL,[BX+CX-129] ; illeg
+ MOV BH,[BX+DX-129] ; illeg
+ MOV CL,[BX+BP-129] ; illeg
+ MOV CH,[BX+DI-129]
+ MOV DL,[BX+SI-129]
+ MOV DH,[BX+SP-129] ; illeg
+
+ MOV AL,[CX+AX-129] ; illeg
+ MOV AH,[CX+BX-129] ; illeg
+ MOV BL,[CX+CX-129] ; illeg
+ MOV BH,[CX+DX-129] ; illeg
+ MOV CL,[CX+BP-129] ; illeg
+ MOV CH,[CX+DI-129] ; illeg
+ MOV DL,[CX+SI-129] ; illeg
+ MOV DH,[CX+SP-129] ; illeg
+
+ MOV AL,[DX+AX-129] ; illeg
+ MOV AH,[DX+BX-129] ; illeg
+ MOV BL,[DX+CX-129] ; illeg
+ MOV BH,[DX+DX-129] ; illeg
+ MOV CL,[DX+BP-129] ; illeg
+ MOV CH,[DX+DI-129] ; illeg
+ MOV DL,[DX+SI-129] ; illeg
+ MOV DH,[DX+SP-129] ; illeg
+
+ MOV AL,[BP+AX-129] ; illeg
+ MOV AH,[BP+BX-129] ; illeg
+ MOV BL,[BP+CX-129] ; illeg
+ MOV BH,[BP+DX-129] ; illeg
+ MOV CL,[BP+BP-129] ; illeg
+ MOV CH,[BP+DI-129]
+ MOV DL,[BP+SI-129]
+ MOV DH,[BP+SP-129] ; illeg
+
+ MOV AL,[DI+AX-129] ; illeg
+ MOV AH,[DI+BX-129]
+ MOV BL,[DI+CX-129] ; illeg
+ MOV BH,[DI+DX-129] ; illeg
+ MOV CL,[DI+BP-129]
+ MOV CH,[DI+DI-129] ; illeg
+ MOV DL,[DI+SI-129] ; illeg
+ MOV DH,[DI+SP-129] ; illeg
+
+ MOV AL,[SI+AX-129] ; illeg
+ MOV AH,[SI+BX-129]
+ MOV BL,[SI+CX-129] ; illeg
+ MOV BH,[SI+DX-129] ; illeg
+ MOV CL,[SI+BP-129]
+ MOV CH,[SI+DI-129] ; illeg
+ MOV DL,[SI+SI-129] ; illeg
+ MOV DH,[SI+SP-129] ; illeg
+
+ MOV AL,[SP+AX-129] ; illeg
+ MOV AH,[SP+BX-129] ; illeg
+ MOV BL,[SP+CX-129] ; illeg
+ MOV BH,[SP+DX-129] ; illeg
+ MOV CL,[SP+BP-129] ; illeg
+ MOV CH,[SP+DI-129] ; illeg
+ MOV DL,[SP+SI-129] ; illeg
+ MOV DH,[SP+SP-129] ; illeg
+
+ MOV AL,[AX+AX+32767] ; illeg
+ MOV AH,[AX+BX+32767] ; illeg
+ MOV BL,[AX+CX+32767] ; illeg
+ MOV BH,[AX+DX+32767] ; illeg
+ MOV CL,[AX+BP+32767] ; illeg
+ MOV CH,[AX+DI+32767] ; illeg
+ MOV DL,[AX+SI+32767] ; illeg
+ MOV DH,[AX+SP+32767] ; illeg
+
+ MOV AL,[BX+AX+32767] ; illeg
+ MOV AH,[BX+BX+32767] ; illeg
+ MOV BL,[BX+CX+32767] ; illeg
+ MOV BH,[BX+DX+32767] ; illeg
+ MOV CL,[BX+BP+32767] ; illeg
+ MOV CH,[BX+DI+32767]
+ MOV DL,[BX+SI+32767]
+ MOV DH,[BX+SP+32767] ; illeg
+
+ MOV AL,[CX+AX+32767] ; illeg
+ MOV AH,[CX+BX+32767] ; illeg
+ MOV BL,[CX+CX+32767] ; illeg
+ MOV BH,[CX+DX+32767] ; illeg
+ MOV CL,[CX+BP+32767] ; illeg
+ MOV CH,[CX+DI+32767] ; illeg
+ MOV DL,[CX+SI+32767] ; illeg
+ MOV DH,[CX+SP+32767] ; illeg
+
+ MOV AL,[DX+AX+32767] ; illeg
+ MOV AH,[DX+BX+32767] ; illeg
+ MOV BL,[DX+CX+32767] ; illeg
+ MOV BH,[DX+DX+32767] ; illeg
+ MOV CL,[DX+BP+32767] ; illeg
+ MOV CH,[DX+DI+32767] ; illeg
+ MOV DL,[DX+SI+32767] ; illeg
+ MOV DH,[DX+SP+32767] ; illeg
+
+ MOV AL,[BP+AX+32767] ; illeg
+ MOV AH,[BP+BX+32767] ; illeg
+ MOV BL,[BP+CX+32767] ; illeg
+ MOV BH,[BP+DX+32767] ; illeg
+ MOV CL,[BP+BP+32767] ; illeg
+ MOV CH,[BP+DI+32767]
+ MOV DL,[BP+SI+32767]
+ MOV DH,[BP+SP+32767] ; illeg
+
+ MOV AL,[DI+AX+32767] ; illeg
+ MOV AH,[DI+BX+32767]
+ MOV BL,[DI+CX+32767] ; illeg
+ MOV BH,[DI+DX+32767] ; illeg
+ MOV CL,[DI+BP+32767]
+ MOV CH,[DI+DI+32767] ; illeg
+ MOV DL,[DI+SI+32767] ; illeg
+ MOV DH,[DI+SP+32767] ; illeg
+
+ MOV AL,[SI+AX+32767] ; illeg
+ MOV AH,[SI+BX+32767]
+ MOV BL,[SI+CX+32767] ; illeg
+ MOV BH,[SI+DX+32767] ; illeg
+ MOV CL,[SI+BP+32767]
+ MOV CH,[SI+DI+32767] ; illeg
+ MOV DL,[SI+SI+32767] ; illeg
+ MOV DH,[SI+SP+32767] ; illeg
+
+ MOV AL,[SP+AX+32767] ; illeg
+ MOV AH,[SP+BX+32767] ; illeg
+ MOV BL,[SP+CX+32767] ; illeg
+ MOV BH,[SP+DX+32767] ; illeg
+ MOV CL,[SP+BP+32767] ; illeg
+ MOV CH,[SP+DI+32767] ; illeg
+ MOV DL,[SP+SI+32767] ; illeg
+ MOV DH,[SP+SP+32767] ; illeg
+
+ MOV AL,[AX+AX-32768] ; illeg
+ MOV AH,[AX+BX-32768] ; illeg
+ MOV BL,[AX+CX-32768] ; illeg
+ MOV BH,[AX+DX-32768] ; illeg
+ MOV CL,[AX+BP-32768] ; illeg
+ MOV CH,[AX+DI-32768] ; illeg
+ MOV DL,[AX+SI-32768] ; illeg
+ MOV DH,[AX+SP-32768] ; illeg
+
+ MOV AL,[BX+AX-32768] ; illeg
+ MOV AH,[BX+BX-32768] ; illeg
+ MOV BL,[BX+CX-32768] ; illeg
+ MOV BH,[BX+DX-32768] ; illeg
+ MOV CL,[BX+BP-32768] ; illeg
+ MOV CH,[BX+DI-32768]
+ MOV DL,[BX+SI-32768]
+ MOV DH,[BX+SP-32768] ; illeg
+
+ MOV AL,[CX+AX-32768] ; illeg
+ MOV AH,[CX+BX-32768] ; illeg
+ MOV BL,[CX+CX-32768] ; illeg
+ MOV BH,[CX+DX-32768] ; illeg
+ MOV CL,[CX+BP-32768] ; illeg
+ MOV CH,[CX+DI-32768] ; illeg
+ MOV DL,[CX+SI-32768] ; illeg
+ MOV DH,[CX+SP-32768] ; illeg
+
+ MOV AL,[DX+AX-32768] ; illeg
+ MOV AH,[DX+BX-32768] ; illeg
+ MOV BL,[DX+CX-32768] ; illeg
+ MOV BH,[DX+DX-32768] ; illeg
+ MOV CL,[DX+BP-32768] ; illeg
+ MOV CH,[DX+DI-32768] ; illeg
+ MOV DL,[DX+SI-32768] ; illeg
+ MOV DH,[DX+SP-32768] ; illeg
+
+ MOV AL,[BP+AX-32768] ; illeg
+ MOV AH,[BP+BX-32768] ; illeg
+ MOV BL,[BP+CX-32768] ; illeg
+ MOV BH,[BP+DX-32768] ; illeg
+ MOV CL,[BP+BP-32768] ; illeg
+ MOV CH,[BP+DI-32768]
+ MOV DL,[BP+SI-32768]
+ MOV DH,[BP+SP-32768] ; illeg
+
+ MOV AL,[DI+AX-32768] ; illeg
+ MOV AH,[DI+BX-32768]
+ MOV BL,[DI+CX-32768] ; illeg
+ MOV BH,[DI+DX-32768] ; illeg
+ MOV CL,[DI+BP-32768]
+ MOV CH,[DI+DI-32768] ; illeg
+ MOV DL,[DI+SI-32768] ; illeg
+ MOV DH,[DI+SP-32768] ; illeg
+
+ MOV AL,[SI+AX-32768] ; illeg
+ MOV AH,[SI+BX-32768]
+ MOV BL,[SI+CX-32768] ; illeg
+ MOV BH,[SI+DX-32768] ; illeg
+ MOV CL,[SI+BP-32768]
+ MOV CH,[SI+DI-32768] ; illeg
+ MOV DL,[SI+SI-32768] ; illeg
+ MOV DH,[SI+SP-32768] ; illeg
+
+ MOV AL,[SP+AX-32768] ; illeg
+ MOV AH,[SP+BX-32768] ; illeg
+ MOV BL,[SP+CX-32768] ; illeg
+ MOV BH,[SP+DX-32768] ; illeg
+ MOV CL,[SP+BP-32768] ; illeg
+ MOV CH,[SP+DI-32768] ; illeg
+ MOV DL,[SP+SI-32768] ; illeg
+ MOV DH,[SP+SP-32768] ; illeg
+
+ MOV AL,[AX+AX+32768] ; illeg
+ MOV AH,[AX+BX+32768] ; illeg
+ MOV BL,[AX+CX+32768] ; illeg
+ MOV BH,[AX+DX+32768] ; illeg
+ MOV CL,[AX+BP+32768] ; illeg
+ MOV CH,[AX+DI+32768] ; illeg
+ MOV DL,[AX+SI+32768] ; illeg
+ MOV DH,[AX+SP+32768] ; illeg
+
+ MOV AL,[BX+AX+32768] ; illeg
+ MOV AH,[BX+BX+32768] ; illeg
+ MOV BL,[BX+CX+32768] ; illeg
+ MOV BH,[BX+DX+32768] ; illeg
+ MOV CL,[BX+BP+32768] ; illeg
+ MOV CH,[BX+DI+32768]
+ MOV DL,[BX+SI+32768]
+ MOV DH,[BX+SP+32768] ; illeg
+
+ MOV AL,[CX+AX+32768] ; illeg
+ MOV AH,[CX+BX+32768] ; illeg
+ MOV BL,[CX+CX+32768] ; illeg
+ MOV BH,[CX+DX+32768] ; illeg
+ MOV CL,[CX+BP+32768] ; illeg
+ MOV CH,[CX+DI+32768] ; illeg
+ MOV DL,[CX+SI+32768] ; illeg
+ MOV DH,[CX+SP+32768] ; illeg
+
+ MOV AL,[DX+AX+32768] ; illeg
+ MOV AH,[DX+BX+32768] ; illeg
+ MOV BL,[DX+CX+32768] ; illeg
+ MOV BH,[DX+DX+32768] ; illeg
+ MOV CL,[DX+BP+32768] ; illeg
+ MOV CH,[DX+DI+32768] ; illeg
+ MOV DL,[DX+SI+32768] ; illeg
+ MOV DH,[DX+SP+32768] ; illeg
+
+ MOV AL,[BP+AX+32768] ; illeg
+ MOV AH,[BP+BX+32768] ; illeg
+ MOV BL,[BP+CX+32768] ; illeg
+ MOV BH,[BP+DX+32768] ; illeg
+ MOV CL,[BP+BP+32768] ; illeg
+ MOV CH,[BP+DI+32768]
+ MOV DL,[BP+SI+32768]
+ MOV DH,[BP+SP+32768] ; illeg
+
+ MOV AL,[DI+AX+32768] ; illeg
+ MOV AH,[DI+BX+32768]
+ MOV BL,[DI+CX+32768] ; illeg
+ MOV BH,[DI+DX+32768] ; illeg
+ MOV CL,[DI+BP+32768]
+ MOV CH,[DI+DI+32768] ; illeg
+ MOV DL,[DI+SI+32768] ; illeg
+ MOV DH,[DI+SP+32768] ; illeg
+
+ MOV AL,[SI+AX+32768] ; illeg
+ MOV AH,[SI+BX+32768]
+ MOV BL,[SI+CX+32768] ; illeg
+ MOV BH,[SI+DX+32768] ; illeg
+ MOV CL,[SI+BP+32768]
+ MOV CH,[SI+DI+32768] ; illeg
+ MOV DL,[SI+SI+32768] ; illeg
+ MOV DH,[SI+SP+32768] ; illeg
+
+ MOV AL,[SP+AX+32768] ; illeg
+ MOV AH,[SP+BX+32768] ; illeg
+ MOV BL,[SP+CX+32768] ; illeg
+ MOV BH,[SP+DX+32768] ; illeg
+ MOV CL,[SP+BP+32768] ; illeg
+ MOV CH,[SP+DI+32768] ; illeg
+ MOV DL,[SP+SI+32768] ; illeg
+ MOV DH,[SP+SP+32768] ; illeg
+
+ MOV AL,[AX+AX-32769] ; illeg
+ MOV AH,[AX+BX-32769] ; illeg
+ MOV BL,[AX+CX-32769] ; illeg
+ MOV BH,[AX+DX-32769] ; illeg
+ MOV CL,[AX+BP-32769] ; illeg
+ MOV CH,[AX+DI-32769] ; illeg
+ MOV DL,[AX+SI-32769] ; illeg
+ MOV DH,[AX+SP-32769] ; illeg
+
+ MOV AL,[BX+AX-32769] ; illeg
+ MOV AH,[BX+BX-32769] ; illeg
+ MOV BL,[BX+CX-32769] ; illeg
+ MOV BH,[BX+DX-32769] ; illeg
+ MOV CL,[BX+BP-32769] ; illeg
+ MOV CH,[BX+DI-32769]
+ MOV DL,[BX+SI-32769]
+ MOV DH,[BX+SP-32769] ; illeg
+
+ MOV AL,[CX+AX-32769] ; illeg
+ MOV AH,[CX+BX-32769] ; illeg
+ MOV BL,[CX+CX-32769] ; illeg
+ MOV BH,[CX+DX-32769] ; illeg
+ MOV CL,[CX+BP-32769] ; illeg
+ MOV CH,[CX+DI-32769] ; illeg
+ MOV DL,[CX+SI-32769] ; illeg
+ MOV DH,[CX+SP-32769] ; illeg
+
+ MOV AL,[DX+AX-32769] ; illeg
+ MOV AH,[DX+BX-32769] ; illeg
+ MOV BL,[DX+CX-32769] ; illeg
+ MOV BH,[DX+DX-32769] ; illeg
+ MOV CL,[DX+BP-32769] ; illeg
+ MOV CH,[DX+DI-32769] ; illeg
+ MOV DL,[DX+SI-32769] ; illeg
+ MOV DH,[DX+SP-32769] ; illeg
+
+ MOV AL,[BP+AX-32769] ; illeg
+ MOV AH,[BP+BX-32769] ; illeg
+ MOV BL,[BP+CX-32769] ; illeg
+ MOV BH,[BP+DX-32769] ; illeg
+ MOV CL,[BP+BP-32769] ; illeg
+ MOV CH,[BP+DI-32769]
+ MOV DL,[BP+SI-32769]
+ MOV DH,[BP+SP-32769] ; illeg
+
+ MOV AL,[DI+AX-32769] ; illeg
+ MOV AH,[DI+BX-32769]
+ MOV BL,[DI+CX-32769] ; illeg
+ MOV BH,[DI+DX-32769] ; illeg
+ MOV CL,[DI+BP-32769]
+ MOV CH,[DI+DI-32769] ; illeg
+ MOV DL,[DI+SI-32769] ; illeg
+ MOV DH,[DI+SP-32769] ; illeg
+
+ MOV AL,[SI+AX-32769] ; illeg
+ MOV AH,[SI+BX-32769]
+ MOV BL,[SI+CX-32769] ; illeg
+ MOV BH,[SI+DX-32769] ; illeg
+ MOV CL,[SI+BP-32769]
+ MOV CH,[SI+DI-32769] ; illeg
+ MOV DL,[SI+SI-32769] ; illeg
+ MOV DH,[SI+SP-32769] ; illeg
+
+ MOV AL,[SP+AX-32769] ; illeg
+ MOV AH,[SP+BX-32769] ; illeg
+ MOV BL,[SP+CX-32769] ; illeg
+ MOV BH,[SP+DX-32769] ; illeg
+ MOV CL,[SP+BP-32769] ; illeg
+ MOV CH,[SP+DI-32769] ; illeg
+ MOV DL,[SP+SI-32769] ; illeg
+ MOV DH,[SP+SP-32769] ; illeg
+
+ MOV AL,[AX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[AX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[AX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[AX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[AX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[AX+DI+$7FFFFFFF] ; illeg
+ MOV DL,[AX+SI+$7FFFFFFF] ; illeg
+ MOV DH,[AX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[BX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[BX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[BX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[BX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[BX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[BX+DI+$7FFFFFFF] ; illeg (bounds)
+ MOV DL,[BX+SI+$7FFFFFFF] ; illeg (bounds)
+ MOV DH,[BX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[CX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[CX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[CX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[CX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[CX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[CX+DI+$7FFFFFFF] ; illeg
+ MOV DL,[CX+SI+$7FFFFFFF] ; illeg
+ MOV DH,[CX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[DX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[DX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[DX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[DX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[DX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[DX+DI+$7FFFFFFF] ; illeg
+ MOV DL,[DX+SI+$7FFFFFFF] ; illeg
+ MOV DH,[DX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[BP+AX+$7FFFFFFF] ; illeg
+ MOV AH,[BP+BX+$7FFFFFFF] ; illeg
+ MOV BL,[BP+CX+$7FFFFFFF] ; illeg
+ MOV BH,[BP+DX+$7FFFFFFF] ; illeg
+ MOV CL,[BP+BP+$7FFFFFFF] ; illeg
+ MOV CH,[BP+DI+$7FFFFFFF] ; illeg (bounds)
+ MOV DL,[BP+SI+$7FFFFFFF] ; illeg (bounds)
+ MOV DH,[BP+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[DI+AX+$7FFFFFFF] ; illeg
+ MOV AH,[DI+BX+$7FFFFFFF] ; illeg (bounds)
+ MOV BL,[DI+CX+$7FFFFFFF] ; illeg
+ MOV BH,[DI+DX+$7FFFFFFF] ; illeg
+ MOV CL,[DI+BP+$7FFFFFFF] ; illeg (bounds)
+ MOV CH,[DI+DI+$7FFFFFFF] ; illeg
+ MOV DL,[DI+SI+$7FFFFFFF] ; illeg
+ MOV DH,[DI+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[SI+AX+$7FFFFFFF] ; illeg
+ MOV AH,[SI+BX+$7FFFFFFF] ; illeg (bounds)
+ MOV BL,[SI+CX+$7FFFFFFF] ; illeg
+ MOV BH,[SI+DX+$7FFFFFFF] ; illeg
+ MOV CL,[SI+BP+$7FFFFFFF] ; illeg (bounds)
+ MOV CH,[SI+DI+$7FFFFFFF] ; illeg
+ MOV DL,[SI+SI+$7FFFFFFF] ; illeg
+ MOV DH,[SI+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[SP+AX+$7FFFFFFF] ; illeg
+ MOV AH,[SP+BX+$7FFFFFFF] ; illeg
+ MOV BL,[SP+CX+$7FFFFFFF] ; illeg
+ MOV BH,[SP+DX+$7FFFFFFF] ; illeg
+ MOV CL,[SP+BP+$7FFFFFFF] ; illeg
+ MOV CH,[SP+DI+$7FFFFFFF] ; illeg
+ MOV DL,[SP+SI+$7FFFFFFF] ; illeg
+ MOV DH,[SP+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[AX+AX-$80000000] ; illeg
+ MOV AH,[AX+BX-$80000000] ; illeg
+ MOV BL,[AX+CX-$80000000] ; illeg
+ MOV BH,[AX+DX-$80000000] ; illeg
+ MOV CL,[AX+BP-$80000000] ; illeg
+ MOV CH,[AX+DI-$80000000] ; illeg
+ MOV DL,[AX+SI-$80000000] ; illeg
+ MOV DH,[AX+SP-$80000000] ; illeg
+
+ MOV AL,[BX+AX-$80000000] ; illeg
+ MOV AH,[BX+BX-$80000000] ; illeg
+ MOV BL,[BX+CX-$80000000] ; illeg
+ MOV BH,[BX+DX-$80000000] ; illeg
+ MOV CL,[BX+BP-$80000000] ; illeg
+ MOV CH,[BX+DI-$80000000] ; illeg (bounds)
+ MOV DL,[BX+SI-$80000000] ; illeg (bounds)
+ MOV DH,[BX+SP-$80000000] ; illeg
+
+ MOV AL,[CX+AX-$80000000] ; illeg
+ MOV AH,[CX+BX-$80000000] ; illeg
+ MOV BL,[CX+CX-$80000000] ; illeg
+ MOV BH,[CX+DX-$80000000] ; illeg
+ MOV CL,[CX+BP-$80000000] ; illeg
+ MOV CH,[CX+DI-$80000000] ; illeg
+ MOV DL,[CX+SI-$80000000] ; illeg
+ MOV DH,[CX+SP-$80000000] ; illeg
+
+ MOV AL,[DX+AX-$80000000] ; illeg
+ MOV AH,[DX+BX-$80000000] ; illeg
+ MOV BL,[DX+CX-$80000000] ; illeg
+ MOV BH,[DX+DX-$80000000] ; illeg
+ MOV CL,[DX+BP-$80000000] ; illeg
+ MOV CH,[DX+DI-$80000000] ; illeg
+ MOV DL,[DX+SI-$80000000] ; illeg
+ MOV DH,[DX+SP-$80000000] ; illeg
+
+ MOV AL,[BP+AX-$80000000] ; illeg
+ MOV AH,[BP+BX-$80000000] ; illeg
+ MOV BL,[BP+CX-$80000000] ; illeg
+ MOV BH,[BP+DX-$80000000] ; illeg
+ MOV CL,[BP+BP-$80000000] ; illeg
+ MOV CH,[BP+DI-$80000000] ; illeg (bounds)
+ MOV DL,[BP+SI-$80000000] ; illeg (bounds)
+ MOV DH,[BP+SP-$80000000] ; illeg
+
+ MOV AL,[DI+AX-$80000000] ; illeg
+ MOV AH,[DI+BX-$80000000] ; illeg (bounds)
+ MOV BL,[DI+CX-$80000000] ; illeg
+ MOV BH,[DI+DX-$80000000] ; illeg
+ MOV CL,[DI+BP-$80000000] ; illeg (bounds)
+ MOV CH,[DI+DI-$80000000] ; illeg
+ MOV DL,[DI+SI-$80000000] ; illeg
+ MOV DH,[DI+SP-$80000000] ; illeg
+
+ MOV AL,[SI+AX-$80000000] ; illeg
+ MOV AH,[SI+BX-$80000000] ; illeg (bounds)
+ MOV BL,[SI+CX-$80000000] ; illeg
+ MOV BH,[SI+DX-$80000000] ; illeg
+ MOV CL,[SI+BP-$80000000] ; illeg (bounds)
+ MOV CH,[SI+DI-$80000000] ; illeg
+ MOV DL,[SI+SI-$80000000] ; illeg
+ MOV DH,[SI+SP-$80000000] ; illeg
+
+ MOV AL,[SP+AX-$80000000] ; illeg
+ MOV AH,[SP+BX-$80000000] ; illeg
+ MOV BL,[SP+CX-$80000000] ; illeg
+ MOV BH,[SP+DX-$80000000] ; illeg
+ MOV CL,[SP+BP-$80000000] ; illeg
+ MOV CH,[SP+DI-$80000000] ; illeg
+ MOV DL,[SP+SI-$80000000] ; illeg
+ MOV DH,[SP+SP-$80000000] ; illeg
diff --git a/bin86-0.3/as/asm/f.asm b/bin86-0.3/as/asm/f.asm
new file mode 100644
index 0000000..c067bf9
--- /dev/null
+++ b/bin86-0.3/as/asm/f.asm
@@ -0,0 +1,114 @@
+; [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st]
+ fadd qword [ebx]
+ fadd dword [ebx]
+ fadd st,st(1)
+ fadd st(1),st
+ fdiv qword [ebx]
+ fdiv dword [ebx]
+ fdiv st,st(1) ; special swapping for this
+
+; [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st
+ faddp st(1),st
+
+; [fbld fbstp] mem10r
+ fbld tbyte [ebx]
+ fbstp tbyte [ebx]
+
+; [fcom fcomp] [mem4r mem8r optional-st(i)]
+ fcom dword [ebx]
+ fcom qword [ebx]
+ fcom
+ fcom st(1)
+
+; ffree st(i)
+ ffree st(1)
+
+; [fucom fucomp fxch] optional-st(i)
+ fucom
+ fucom st(1)
+
+; [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i]
+ fiadd word [ebx]
+ fiadd dword [ebx]
+
+; [fild fistp] [mem2i mem4i mem8i]
+ fild word [ebx]
+ fild dword [ebx]
+ fild qword [ebx]
+
+; [fld fstp] [mem4r mem8r mem10r st(i)]
+ fld dword [ebx]
+ fld qword [ebx]
+ fld tbyte [ebx]
+ fld st(1)
+
+; [fldcw fnstcw] mem2i
+ fldcw word [ebx]
+ fnstcw word [ebx]
+
+; [fldenv fnsave fnstenv frstor] mem
+ fldenv [ebx]
+ fnsave [ebx]
+ fnstenv [ebx]
+ frstor [ebx]
+
+; fnstsw [mem2i ax]
+ fnstsw word [ebx]
+ fnstsw ax
+
+; fst [mem4r mem8r st(i)]
+ fst dword [ebx]
+ fst qword [ebx]
+ fst st(1)
+
+; fstcw mem2i (wait)
+ fstcw word [ebx]
+
+; fstsw [mem2i ax] (wait)
+ fstsw word [ebx]
+ fstsw ax
+
+; [fsave fstenv] mem (wait)
+ fsave [ebx]
+ fstenv [ebx]
+
+; [fxxx] (no operands)
+ fnop ; D9D0
+ fchs ; D9E0
+ fabs ; D9E1
+ ftst ; D9E4
+ fxam ; D9E5
+ fld1 ; D9E8
+ fldl2t ; D9E9
+ fldl2e ; D9EA
+ fldpi ; D9EB
+ fldlg2 ; D9EC
+ fldln2 ; D9ED
+ fldz ; D9EE
+ f2xm1 ; D9F0
+ fyl2x ; D9F1
+ fptan ; D9F2
+ fpatan ; D9F3
+ fxtract ; D9F4
+ fprem1 ; D9F5
+ fdecstp ; D9F6
+ fincstp ; D9F7
+ fprem ; D9F8
+ fyl2xp1 ; D9F9
+ fsqrt ; D9FA
+ fsincos ; D9FB
+ frndint ; D9FC
+ fscale ; D9FD
+ fsin ; D9FE
+ fcos ; D9FF
+ fucompp ; DAE9
+ feni ; 9BDBE0
+ fneni ; DBE0
+ fdisi ; 9BDBE1
+ fndisi ; DBE1
+ fclex ; 9BDBE2
+ fnclex ; DBE2
+ finit ; 9BDBE3
+ fninit ; DBE3
+ fsetpm ; DBE4
+ fcompp ; DED9
diff --git a/bin86-0.3/as/asm/fadd.asm b/bin86-0.3/as/asm/fadd.asm
new file mode 100644
index 0000000..d18f002
--- /dev/null
+++ b/bin86-0.3/as/asm/fadd.asm
@@ -0,0 +1,271 @@
+_fadd:
+ PUSH BP
+ MOV BP,SP
+ MOV EAX,DWORD PTR [BP+4]
+ MOV EDX,DWORD PTR [BP+8]
+ MOV EBX,DWORD PTR [BP+12]
+ MOV ECX,DWORD PTR [BP+16]
+ CALL faddfxfy
+ MOV DWORD PTR _facc,EAX
+ MOV DWORD PTR _facc+4,EDX
+ POP BP
+ RET
+
+fsubfxfy:
+ XOR ECX,#$80000000 ; complement sign bit, fall into add routine
+faddfxfy:
+ PUSH EBP
+ PUSH EDI
+ PUSH ESI
+ MOV EDI,ECX ; free CL for shifts
+ MOV ESI,EDX ; this mainly for consistent naming
+ AND ESI,#$7FFFFFFF ; discard sign so comparison is simple
+ AND EDI,#$7FFFFFFF
+
+ CMP ESI,EDI
+ JA XBIG
+ JB SWAP
+ CMP EAX,EBX
+ JAE XBIG
+SWAP:
+ XCHG EDX,ECX
+ XCHG ESI,EDI
+ XCHG EAX,EBX
+XBIG:
+ AND ESI,#$000FFFFF ; discard exponent
+ AND EDI,#$000FFFFF
+ OR ESI,#$00100000 ; normalize
+ OR EDI,#$00100000
+
+ SHR ECX,32-(1+11)
+ SHR EDX,32-(1+11)
+ MOV EBP,ECX ; prepare to compare signs (want high bits 0)
+ SUB CX,DX ; get difference of signs in CX
+ NEG CX ; D holds sign and exponent of both throughout
+ CMP CX,#(64-11)+2
+ JAE TO_DONE1 ; x dominates y
+ XOR BP,DX
+ AND BP,#$0800 ; see if signs are same
+ JNZ TO_SUBTRACT ; else roundoff reg EBP is 0
+
+ CMP CL,#32
+ JAE TO_ADD_BIGSHIFT
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ ADD EAX,EBX
+ ADC ESI,EDI
+ SUB EBX,EBX
+
+; result DX(1+11):SI:AX:BP:BX but needs normalization
+
+NORMALIZE:
+ MOV CX,DX
+ AND CX,#$07FF
+ TEST ESI,#$00200000
+ JZ NORMALIZE2
+ BR LOVERFLOW
+
+TO_DONE1:
+ JMP DONE1
+
+TO_SUBTRACT:
+ BR SUBTRACT
+
+TO_ADD_BIGSHIFT:
+ BR ADD_BIGSHIFT
+
+TO_NORMLITTLE:
+ BR NORMLITTLE
+
+; result DX(1):CX(11):SI:AX:BP:BX
+
+NORMALIZE2:
+ SHRD EDI,ESI,32-11
+ ; top 11 bits of ESI known 0 and BSR is slooow
+ BSR EDI,EDI ; index of leading 1 bit in EDI is 11..31 in DI
+ JZ TO_NORMLITTLE ; ESI is zero (flag wrong in Intel Manual)
+ SUB DI,#31
+ NEG DI
+ PUSH CX ; gr
+ MOV CX,DI ; rr
+ SHLD ESI,EAX,CL
+ SHLD EAX,EBP,CL
+ SHLD EBP,EBX,CL
+ SHL EBX,CL
+ POP CX ; rr
+ SUB CX,DI
+ JC UNDERFLOW
+
+ROUND:
+ CMP EBP,#$80000000 ; test roundoff register
+ JA ROUNDUP
+ JB DONE ; no rounding
+ TEST EBX,EBX
+ JNZ ROUNDUP
+ TEST AL,#1 ; ambiguous case, round to even
+ JZ DONE ; even, no rounding
+ROUNDUP:
+ ADD EAX,#1
+ ADC ESI,#0
+ SUB EBP,EBP
+ SUB EBX,EBX
+ TEST ESI,#$00200000
+ JNZ LOVERFLOW ; rounding may cause overflow!
+
+DONE:
+ AND DX,#$0800 ; extract sign of largest and result
+ OR DX,CX ; include exponent with sign
+DONE1:
+ SHL EDX,32-(1+11)
+ AND ESI,#$000FFFFF ; discard normalization bit
+ OR EDX,ESI
+ POP ESI
+ POP EDI
+ POP EBP
+ RET
+
+UNDERFLOW: ; should have error message here
+ANSWER0:
+ SUB EDX,EDX
+ MOV EAX,EDX
+ POP ESI
+ POP EDI
+ POP EBP
+ RET
+
+LOVERFLOW: ; carry bit must be right-shifted back in
+ SHR ESI,1
+ RCR EAX,1
+ RCR EBP,1
+ RCR EBX,1
+ INC CX
+ CMP CX,#$0800
+ JNZ ROUND
+
+OVERFLOW: ; should have error message here
+ MOV EDX,#$FFE00000 ; + infinity
+ SUB EAX,EAX
+ POP ESI
+ POP EDI
+ POP EBP
+ RET
+
+ADD_BIGSHIFT:
+ SUB CL,#32
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ ADD EAX,EDI
+ ADC ESI,#0
+ XCHG EBP,EBX
+ BR NORMALIZE
+
+NORMLITTLE:
+ SHLD ESI,EAX,32-(1+11)
+ SHLD EAX,EBP,32-(1+11)
+ SHLD EBP,EBX,32-(1+11)
+ SHL EBX,20
+ SUB CL,#32-(1+11)
+ JC UNDERFLOW
+ BR NORMALIZE2
+
+SUBTRACT:
+ SUB EBP,EBP ; set up roundoff register
+ CMP CL,#32
+ JAE SUBTRACT_BIGSHIFT
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ NEG EBP
+ SBB EAX,EBX
+ SBB ESI,EDI
+ SUB EBX,EBX
+ MOV CX,DX
+ AND CX,#$07FF
+ BR NORMALIZE2
+
+SUBTRACT_BIGSHIFT:
+ SUB CL,#32
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ NEG EBX
+ NEG EBP
+ SBB EBX,#0
+ SBB EAX,EDI
+ SBB ESI,#0
+ XCHG EBP,EBX
+ MOV CX,DX
+ AND CX,#$07FF
+ BR NORMALIZE2
+
+TO_ANSWER0:
+ BR ANSWER0
+
+TO_OVERFLOW:
+ JMP TO_OVERFLOW
+
+TO_UNDERFLOW:
+ BR UNDERFLOW
+
+fmulfxfy:
+ PUSH EBP
+ PUSH EDI
+ PUSH ESI
+ MOV ESI,EDX ; free DX for multiplications
+ MOV EDI,ECX ; this mainly for consistent naming
+ SHR EDX,32-(1+11)
+ SHR ECX,32-(1+11)
+ MOV BP,DX
+ XOR BP,CX
+ AND BP,#$0800 ; extract sign
+ AND DX,#$07FF ; exp(x)
+ JZ TO_ANSWER0
+ AND CX,#$07FF ; exp(y)
+ JZ TO_ANSWER0
+ ADD CX,DX
+ SUB CX,#$0400
+ JB TO_UNDERFLOW
+ CMP CX,#$07FF
+ JA TO_OVERFLOW ; probably not quite right
+
+ AND ESI,#$000FFFFF ; discard sign and exponent
+ AND EDI,#$000FFFFF
+ OR ESI,#$00100000 ; normalize
+ OR EDI,#$00100000
+
+; exponent is in CX, sign in BP, operands in ESI:EAX and EDI:EBX, DX is free
+; product to go in ESI:EAX:EBP:EBX
+; terminology: x * y = (x32:x0) * (y32:y0) = x32y32 + x32y0 + x0y32 +x0y0
+
+ PUSH CX
+ PUSH BP
+ MOV ECX,EAX
+ MUL EBX ; x0y0
+ MOV EBP,EDX ; x0y0.high in EBP
+ XCHG EBX,EAX ; x0y0.low in EBX (final), y0 in EAX
+ MUL ESI ; x32y0
+ PUSH EAX ; x32y0.low on stack
+ PUSH EDX ; x32y0.high on stack
+ MOV EAX,ESI
+ MUL EDI ; x32y32
+ MOV ESI,EDX ; x32y32.high in ESI (final except carries)
+ XCHG ECX,EAX ; x32y32.low in ECX, x0 in EAX
+ MUL EDI ; x0y32
+
+ ADD EBP,EAX ; x0y0.high + x0y32.low
+ POP EAX ; x32y0.high
+ ADC EAX,EDX ; x32y0.high + x0y32.high
+ ADC ESI,#0
+ POP EDX ; x32y0.low
+ ADD EBP,EDX ; (x0y0.high + x0y32.low) + x32y0.low
+ ADC EAX,ECX ; (x32y0.high + x0y32.high) + x32y32.low
+ ADC ESI,#0
+ POP DX ; sign
+ POP CX ; exponent
+ ADD CX,#13 ; temp fixup
+ BR NORMALIZE2
+
+_facc:
+ .word 0,0
diff --git a/bin86-0.3/as/asm/farcall.asm b/bin86-0.3/as/asm/farcall.asm
new file mode 100644
index 0000000..6a779d9
--- /dev/null
+++ b/bin86-0.3/as/asm/farcall.asm
@@ -0,0 +1,10 @@
+call 1:2
+call far [1]
+use32
+call far [1]
+
+use16
+jmp 1:2
+jmp far [1]
+use32
+jmp far [1]
diff --git a/bin86-0.3/as/asm/group1.asm b/bin86-0.3/as/asm/group1.asm
new file mode 100644
index 0000000..fe2fb45
--- /dev/null
+++ b/bin86-0.3/as/asm/group1.asm
@@ -0,0 +1,31 @@
+ ADD AL,#3
+ ADD AX,#$1234
+ ADD EAX,#$12345678
+ ADD BL,#3
+ ADD BX,#$1234
+ ADD EBX,#$12345678
+ ADD BYTE [BX],#3
+ ADD BYTE 3[BX],#4
+ ADD BYTE [BX+SI],#4
+ ADD WORD [BX],#$1234
+ ADD DWORD [BX],#$12345678
+ ADD BYTE [BX],#3
+ ADD WORD [BX],#-3
+ ADD DWORD [BX],#-3
+ ADD CL,BL
+ ADD CX,BX
+ ADD ECX,EBX
+ ADD [BX],CL
+ ADD [BX],CX
+ ADD [BX],ECX
+ ADD CL,[BX]
+ ADD CX,[BX]
+ ADD ECX,[BX]
+
+ ADC CL,BL
+ AND CL,BL
+ CMP CL,BL
+ OR CL,BL
+ SUB CL,BL
+ SBB CL,BL
+ XOR CL,BL
diff --git a/bin86-0.3/as/asm/group6.asm b/bin86-0.3/as/asm/group6.asm
new file mode 100644
index 0000000..f742672
--- /dev/null
+++ b/bin86-0.3/as/asm/group6.asm
@@ -0,0 +1,24 @@
+; group6.asm
+; 0F 00 /nnn
+
+; LLDT r/m16 nnn = 010
+; LTR r/m16 nnn = 011
+; SLDT r/m16 nnn = 000
+; STR r/m16 nnn = 001
+; VERR r/m16 nnn = 100
+; VERW r/m16 nnn = 101
+
+ LLDT AL ; illeg size
+ LLDT EAX ; illeg size
+ LLDT WORD $1234 ; immed not allowed
+ LLDT DS ; segreg not allowed
+
+ LLDT AX
+ LLDT [BX]
+ LLDT [EAX]
+
+ LTR BX
+ SLDT [BP]
+ STR [EBX]
+ VERR CX
+ VERW [SI]
diff --git a/bin86-0.3/as/asm/group7.asm b/bin86-0.3/as/asm/group7.asm
new file mode 100644
index 0000000..0df497c
--- /dev/null
+++ b/bin86-0.3/as/asm/group7.asm
@@ -0,0 +1,34 @@
+; group7.asm
+; 0F 01 /nnn
+
+; INVLPG m nnn = 111
+; LGDT m16&32 nnn = 010
+; LIDT m16&32 nnn = 011
+; LMSW r/m16 nnn = 110
+; SGDT m nnn = 000
+; SIDT m nnn = 001
+; SMSW r/m16 nnn = 100
+
+ LGDT EAX ; register not allowed
+ LGDT #$1234 ; immed not allowed
+ LGDT WORD PTR [BX] ; illegal size
+
+ LGDT [BX]
+ LGDT PWORD PTR [BX]
+ LGDT FWORD PTR [BX]
+ LGDT [EAX]
+
+ INVLPG [EDI]
+ SGDT [BP]
+ SIDT [EBX]
+
+ LMSW AL ; illeg size
+ LMSW EAX ; illeg size
+ LMSW #$1234 ; immed not allowed
+ LMSW DS ; segreg not allowed
+
+ LMSW AX
+ LMSW [BX]
+ LMSW [EAX]
+
+ SMSW BX
diff --git a/bin86-0.3/as/asm/imul.asm b/bin86-0.3/as/asm/imul.asm
new file mode 100644
index 0000000..e2772c2
--- /dev/null
+++ b/bin86-0.3/as/asm/imul.asm
@@ -0,0 +1,33 @@
+ use32
+
+ imul bl
+ imul byte ptr [esi]
+ imul bx
+ imul word ptr [esi]
+ imul ebx
+ imul dword ptr [esi]
+
+ imul ax,bx
+ imul ax,[esi]
+ imul eax,ebx
+ imul eax,[esi]
+
+ imul ax,bx,22
+ imul ax,[esi],22
+ imul eax,ebx,22
+ imul eax,[esi],22
+
+ imul ax,[22]
+ imul eax,[22]
+ imul ax,#22
+ imul eax,#22
+
+ imul ax,bx,300
+ imul ax,[esi],300
+ imul eax,ebx,300000
+ imul eax,[esi],300000
+
+ imul ax,[300]
+ imul eax,[300000]
+ imul ax,#300
+ imul eax,#300000
diff --git a/bin86-0.3/as/asm/incdec.asm b/bin86-0.3/as/asm/incdec.asm
new file mode 100644
index 0000000..573861c
--- /dev/null
+++ b/bin86-0.3/as/asm/incdec.asm
@@ -0,0 +1,83 @@
+ INC AL
+ INC AH
+ INC BL
+ INC BH
+ INC CL
+ INC CH
+ INC DL
+ INC DH
+ INC #1 ; illeg
+ INC BYTE #1 ; illeg
+ INC [BX] ; illeg
+ INC BYTE [BX]
+
+ INC AX
+ INC BX
+ INC CX
+ INC DX
+ INC SP
+ INC BP
+ INC SI
+ INC DI
+ INC CS ; illeg
+ INC DS ; illeg
+ INC ES ; illeg
+ INC FS ; illeg
+ INC GS ; illeg
+ INC #$1234 ; illeg
+ INC WORD #$1234 ; illeg
+ INC WORD [BX]
+
+ INC EAX
+ INC EBX
+ INC ECX
+ INC EDX
+ INC ESP
+ INC EBP
+ INC ESI
+ INC EDI
+ INC #$12345678 ; illeg
+ INC DWORD #$12345678 ; illeg
+ INC DWORD [BX]
+
+ DEC AL
+ DEC AH
+ DEC BL
+ DEC BH
+ DEC CL
+ DEC CH
+ DEC DL
+ DEC DH
+ DEC #1 ; illeg
+ DEC BYTE #1 ; illeg
+ DEC [BX] ; illeg
+ DEC BYTE [BX]
+
+ DEC AX
+ DEC BX
+ DEC CX
+ DEC DX
+ DEC SP
+ DEC BP
+ DEC SI
+ DEC DI
+ DEC CS ; illeg
+ DEC DS ; illeg
+ DEC ES ; illeg
+ DEC FS ; illeg
+ DEC GS ; illeg
+ DEC #$1234 ; illeg
+ DEC WORD #$1234 ; illeg
+ DEC WORD [BX]
+
+ DEC EAX
+ DEC EBX
+ DEC ECX
+ DEC EDX
+ DEC ESP
+ DEC EBP
+ DEC ESI
+ DEC EDI
+ DEC #$12345678 ; illeg
+ DEC DWORD #$12345678 ; illeg
+ DEC DWORD [BX]
diff --git a/bin86-0.3/as/asm/inher.asm b/bin86-0.3/as/asm/inher.asm
new file mode 100644
index 0000000..f1343fa
--- /dev/null
+++ b/bin86-0.3/as/asm/inher.asm
@@ -0,0 +1,127 @@
+; INHER.ASM
+
+; INHER opcodes
+
+ AAA
+ AAS
+
+ CLC
+ CLD
+ CLI
+ CLTS
+ CMC
+ CMPSB
+
+ DAA
+ DAS
+
+ HLT
+
+ INTO
+ INSB
+
+ LAHF
+ LEAVE
+ LOCK
+ LODSB
+
+ MOVSB
+
+ NOP
+
+ OUTSB
+
+ REP
+ REPE
+ REPNE
+
+ SAHF
+ SCASB
+ STC
+ STD
+ STI
+ STOSB
+
+ WAIT
+
+; INHER16 and INHER32 opcodes
+
+ USE16
+
+ CBW
+ CWD
+ CWDE
+ CDQ
+ CMPSW
+ CMPSD
+
+ INSW
+ INSD
+ IRET
+ IRETD
+
+ LODSW
+ LODSD
+
+ MOVSW
+ MOVSD
+
+ OUTSW
+ OUTSD
+
+ POPA
+ POPAD
+ POPF
+ POPFD
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+
+ SCASW
+ SCASD
+ STOSW
+ STOSW
+
+ XLAT
+ XLATB
+
+ USE32
+
+ CBW
+ CWD
+ CWDE
+ CDQ
+ CMPSW
+ CMPSD
+
+ INSW
+ INSD
+ IRET
+ IRETD
+
+ LODSW
+ LODSD
+
+ MOVSW
+ MOVSD
+
+ OUTSW
+ OUTSD
+
+ POPA
+ POPAD
+ POPF
+ POPFD
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+
+ SCASW
+ SCASD
+ STOSW
+ STOSW
+
+ XLAT
+ XLATB
diff --git a/bin86-0.3/as/asm/inout.asm b/bin86-0.3/as/asm/inout.asm
new file mode 100644
index 0000000..3f0a3f2
--- /dev/null
+++ b/bin86-0.3/as/asm/inout.asm
@@ -0,0 +1,25 @@
+ IN EAX,DX ; plain IN is no longer allowed
+ INB
+ IN AL,DX
+ INW
+ IN AX,DX
+ IN EAX,DX
+ IN AL,$20
+ IN AL,$101
+ IN AX,$20
+ IN AX,$101
+ IN EAX,$20
+ IN EAX,$101
+
+ OUTB DX,EAX ; plain OUT is no longer allowed
+ OUTB
+ OUT DX,AL
+ OUTW
+ OUT DX,AX
+ OUT DX,EAX
+ OUT $20,AL
+ OUT $101,AL
+ OUT $20,AX
+ OUT #101,AX
+ OUT $20,EAX
+ OUT $101,EAX
diff --git a/bin86-0.3/as/asm/movspec.asm b/bin86-0.3/as/asm/movspec.asm
new file mode 100644
index 0000000..a4f9c15
--- /dev/null
+++ b/bin86-0.3/as/asm/movspec.asm
@@ -0,0 +1,246 @@
+mov eax,cr0
+mov eax,cr2
+mov eax,cr3
+mov eax,dr0
+mov eax,dr1
+mov eax,dr2
+mov eax,dr3
+mov eax,dr6
+mov eax,dr7
+mov eax,tr3
+mov eax,tr4
+mov eax,tr5
+mov eax,tr6
+mov eax,tr7
+
+mov cr0,eax
+mov cr2,eax
+mov cr3,eax
+mov dr0,eax
+mov dr1,eax
+mov dr2,eax
+mov dr3,eax
+mov dr6,eax
+mov dr7,eax
+mov tr3,eax
+mov tr4,eax
+mov tr5,eax
+mov tr6,eax
+mov tr7,eax
+
+
+mov ebx,cr0
+mov ebx,cr2
+mov ebx,cr3
+mov ebx,dr0
+mov ebx,dr1
+mov ebx,dr2
+mov ebx,dr3
+mov ebx,dr6
+mov ebx,dr7
+mov ebx,tr3
+mov ebx,tr4
+mov ebx,tr5
+mov ebx,tr6
+mov ebx,tr7
+
+mov cr0,ebx
+mov cr2,ebx
+mov cr3,ebx
+mov dr0,ebx
+mov dr1,ebx
+mov dr2,ebx
+mov dr3,ebx
+mov dr6,ebx
+mov dr7,ebx
+mov tr3,ebx
+mov tr4,ebx
+mov tr5,ebx
+mov tr6,ebx
+mov tr7,ebx
+
+
+mov ecx,cr0
+mov ecx,cr2
+mov ecx,cr3
+mov ecx,dr0
+mov ecx,dr1
+mov ecx,dr2
+mov ecx,dr3
+mov ecx,dr6
+mov ecx,dr7
+mov ecx,tr3
+mov ecx,tr4
+mov ecx,tr5
+mov ecx,tr6
+mov ecx,tr7
+
+mov cr0,ecx
+mov cr2,ecx
+mov cr3,ecx
+mov dr0,ecx
+mov dr1,ecx
+mov dr2,ecx
+mov dr3,ecx
+mov dr6,ecx
+mov dr7,ecx
+mov tr3,ecx
+mov tr4,ecx
+mov tr5,ecx
+mov tr6,ecx
+mov tr7,ecx
+
+
+mov edx,cr0
+mov edx,cr2
+mov edx,cr3
+mov edx,dr0
+mov edx,dr1
+mov edx,dr2
+mov edx,dr3
+mov edx,dr6
+mov edx,dr7
+mov edx,tr3
+mov edx,tr4
+mov edx,tr5
+mov edx,tr6
+mov edx,tr7
+
+mov cr0,edx
+mov cr2,edx
+mov cr3,edx
+mov dr0,edx
+mov dr1,edx
+mov dr2,edx
+mov dr3,edx
+mov dr6,edx
+mov dr7,edx
+mov tr3,edx
+mov tr4,edx
+mov tr5,edx
+mov tr6,edx
+mov tr7,edx
+
+
+mov esi,cr0
+mov esi,cr2
+mov esi,cr3
+mov esi,dr0
+mov esi,dr1
+mov esi,dr2
+mov esi,dr3
+mov esi,dr6
+mov esi,dr7
+mov esi,tr3
+mov esi,tr4
+mov esi,tr5
+mov esi,tr6
+mov esi,tr7
+
+mov cr0,esi
+mov cr2,esi
+mov cr3,esi
+mov dr0,esi
+mov dr1,esi
+mov dr2,esi
+mov dr3,esi
+mov dr6,esi
+mov dr7,esi
+mov tr3,esi
+mov tr4,esi
+mov tr5,esi
+mov tr6,esi
+mov tr7,esi
+
+
+mov edi,cr0
+mov edi,cr2
+mov edi,cr3
+mov edi,dr0
+mov edi,dr1
+mov edi,dr2
+mov edi,dr3
+mov edi,dr6
+mov edi,dr7
+mov edi,tr3
+mov edi,tr4
+mov edi,tr5
+mov edi,tr6
+mov edi,tr7
+
+mov cr0,edi
+mov cr2,edi
+mov cr3,edi
+mov dr0,edi
+mov dr1,edi
+mov dr2,edi
+mov dr3,edi
+mov dr6,edi
+mov dr7,edi
+mov tr3,edi
+mov tr4,edi
+mov tr5,edi
+mov tr6,edi
+mov tr7,edi
+
+
+mov esp,cr0
+mov esp,cr2
+mov esp,cr3
+mov esp,dr0
+mov esp,dr1
+mov esp,dr2
+mov esp,dr3
+mov esp,dr6
+mov esp,dr7
+mov esp,tr3
+mov esp,tr4
+mov esp,tr5
+mov esp,tr6
+mov esp,tr7
+
+mov cr0,esp
+mov cr2,esp
+mov cr3,esp
+mov dr0,esp
+mov dr1,esp
+mov dr2,esp
+mov dr3,esp
+mov dr6,esp
+mov dr7,esp
+mov tr3,esp
+mov tr4,esp
+mov tr5,esp
+mov tr6,esp
+mov tr7,esp
+
+
+mov ebp,cr0
+mov ebp,cr2
+mov ebp,cr3
+mov ebp,dr0
+mov ebp,dr1
+mov ebp,dr2
+mov ebp,dr3
+mov ebp,dr6
+mov ebp,dr7
+mov ebp,tr3
+mov ebp,tr4
+mov ebp,tr5
+mov ebp,tr6
+mov ebp,tr7
+
+mov cr0,ebp
+mov cr2,ebp
+mov cr3,ebp
+mov dr0,ebp
+mov dr1,ebp
+mov dr2,ebp
+mov dr3,ebp
+mov dr6,ebp
+mov dr7,ebp
+mov tr3,ebp
+mov tr4,ebp
+mov tr5,ebp
+mov tr6,ebp
+mov tr7,ebp
diff --git a/bin86-0.3/as/asm/pushpop.asm b/bin86-0.3/as/asm/pushpop.asm
new file mode 100644
index 0000000..b45117a
--- /dev/null
+++ b/bin86-0.3/as/asm/pushpop.asm
@@ -0,0 +1,86 @@
+ PUSH AL ; illeg
+ PUSH AH ; illeg
+ PUSH BL ; illeg
+ PUSH BH ; illeg
+ PUSH CL ; illeg
+ PUSH CH ; illeg
+ PUSH DL ; illeg
+ PUSH DH ; illeg
+ PUSH #1 ; illeg
+ PUSH BYTE #1 ; illeg
+ PUSH [BX] ; illeg
+ PUSH BYTE [BX] ; illeg
+ PUSH WORD #-1 ; right way to push a signed byte value
+
+ PUSH AX
+ PUSH BX
+ PUSH CX
+ PUSH DX
+ PUSH SP
+ PUSH BP
+ PUSH SI
+ PUSH DI
+ PUSH CS
+ PUSH DS
+ PUSH ES
+ PUSH FS
+ PUSH GS
+ PUSH SS
+ PUSH #$1234 ; illeg
+ PUSH WORD #$1234
+ PUSH WORD [BX]
+
+ PUSH EAX
+ PUSH EBX
+ PUSH ECX
+ PUSH EDX
+ PUSH ESP
+ PUSH EBP
+ PUSH ESI
+ PUSH EDI
+ PUSH #$12345678 ; illeg
+ PUSH DWORD #$12345678
+ PUSH DWORD [BX]
+
+ POP AL ; illeg
+ POP AH ; illeg
+ POP BL ; illeg
+ POP BH ; illeg
+ POP CL ; illeg
+ POP CH ; illeg
+ POP DL ; illeg
+ POP DH ; illeg
+ POP #1 ; illeg
+ POP BYTE #1 ; illeg
+ POP [BX] ; illeg
+ POP BYTE [BX] ; illeg
+
+ POP AX
+ POP BX
+ POP CX
+ POP DX
+ POP SP
+ POP BP
+ POP SI
+ POP DI
+ POP CS ; illeg
+ POP DS
+ POP ES
+ POP FS
+ POP GS
+ POP SS
+ POP #$1234 ; illeg
+ POP WORD #$1234 ; illeg
+ POP WORD [BX]
+
+ POP EAX
+ POP EBX
+ POP ECX
+ POP EDX
+ POP ESP
+ POP EBP
+ POP ESI
+ POP EDI
+ POP #$12345678 ; illeg
+ POP DWORD #$12345678 ; illeg
+ POP DWORD [BX]
diff --git a/bin86-0.3/as/asm/seg.asm b/bin86-0.3/as/asm/seg.asm
new file mode 100644
index 0000000..0394615
--- /dev/null
+++ b/bin86-0.3/as/asm/seg.asm
@@ -0,0 +1,6 @@
+ SEG CS
+ SEG DS
+ SEG ES
+ SEG FS
+ SEG GS
+ SEG SS
diff --git a/bin86-0.3/as/asm/shdouble.asm b/bin86-0.3/as/asm/shdouble.asm
new file mode 100644
index 0000000..1080ece
--- /dev/null
+++ b/bin86-0.3/as/asm/shdouble.asm
@@ -0,0 +1,34 @@
+; SHDOUBLE.ASM
+
+ILLEGALS EQU 1
+
+; 0F A4 SHLD r/m16,r16,imm8 3/7
+; 0F A4 SHLD r/m32,r32,imm8 3/7
+; 0F A5 SHLD r/m16,r16,CL 3/7
+; 0F A5 SHLD r/m32,r32,CL 3/7
+
+; 0F AC SHRD r/m16,r16,imm8 3/7
+; 0F AC SHRD r/m32,r32,imm8 3/7
+; 0F AD SHRD r/m16,r16,CL 3/7
+; 0F AD SHRD r/m32,r32,CL 3/7
+
+IF ILLEGALS
+ SHLD AL,BL,8 ; byte size
+ SHLD AX,8,8 ; immediate source
+ SHLD AX,DS,8 ; segment register
+ SHLD AX,[BX],8 ; non-register source
+ SHLD AX,BX,256 ; shift count too big
+ SHLD AL,BL,8 ; byte size
+ENDIF
+
+ SHLD BX,CX,3
+ SHLD EDX,ESI,1
+ SHLD CX,BX,CL
+ SHLD ESI,EDX,1
+ SHLD [BX],CX,3
+ SHLD [BX],ECX,1
+ SHLD [SI],BX,CL
+ SHLD [SI],EBX,CL
+
+ SHRD BX,CX,3
+ SHRD CX,BX,CL
diff --git a/bin86-0.3/as/asm/shift.asm b/bin86-0.3/as/asm/shift.asm
new file mode 100644
index 0000000..35cc23f
--- /dev/null
+++ b/bin86-0.3/as/asm/shift.asm
@@ -0,0 +1,119 @@
+ RCL AL,CL
+ RCL AH,CL
+ RCL BL,CL
+ RCL BH,CL
+ RCL CL,CL
+ RCL CH,CL
+ RCL DL,CL
+ RCL DH,CL
+ RCL #1,CL ; illeg
+ RCL [BX],CL ; illeg
+ RCL BYTE [BX],CL
+
+ RCL AX,CL
+ RCL BX,CL
+ RCL CX,CL
+ RCL DX,CL
+ RCL SP,CL
+ RCL BP,CL
+ RCL SI,CL
+ RCL DI,CL
+ RCL CS,CL ; illeg
+ RCL DS,CL ; illeg
+ RCL ES,CL ; illeg
+ RCL FS,CL ; illeg
+ RCL GS,CL ; illeg
+ RCL WORD [BX],CL
+
+ RCL EAX,CL
+ RCL EBX,CL
+ RCL ECX,CL
+ RCL EDX,CL
+ RCL ESP,CL
+ RCL EBP,CL
+ RCL ESI,CL
+ RCL EDI,CL
+ RCL DWORD [BX],CL
+
+ RCL AL,1
+ RCL AH,1
+ RCL BL,1
+ RCL BH,1
+ RCL CL,1
+ RCL CH,1
+ RCL DL,1
+ RCL DH,1
+ RCL #1,1 ; illeg
+ RCL [BX],1 ; illeg
+ RCL BYTE [BX],1
+
+ RCL AX,1
+ RCL BX,1
+ RCL CX,1
+ RCL DX,1
+ RCL SP,1
+ RCL BP,1
+ RCL SI,1
+ RCL DI,1
+ RCL CS,1 ; illeg
+ RCL DS,1 ; illeg
+ RCL ES,1 ; illeg
+ RCL FS,1 ; illeg
+ RCL GS,1 ; illeg
+ RCL WORD [BX],1
+
+ RCL EAX,1
+ RCL EBX,1
+ RCL ECX,1
+ RCL EDX,1
+ RCL ESP,1
+ RCL EBP,1
+ RCL ESI,1
+ RCL EDI,1
+ RCL DWORD [BX],1
+
+ RCL AL,15
+ RCL AH,15
+ RCL BL,15
+ RCL BH,15
+ RCL CL,15
+ RCL CH,15
+ RCL DL,15
+ RCL DH,15
+ RCL #1,15 ; illeg
+ RCL [BX],15 ; illeg
+ RCL BYTE [BX],15
+ RCL AL,$1000
+
+ RCL AX,15
+ RCL BX,15
+ RCL CX,15
+ RCL DX,15
+ RCL SP,15
+ RCL BP,15
+ RCL SI,15
+ RCL DI,15
+ RCL CS,15 ; illeg
+ RCL DS,15 ; illeg
+ RCL ES,15 ; illeg
+ RCL FS,15 ; illeg
+ RCL GS,15 ; illeg
+ RCL WORD [BX],15
+
+ RCL EAX,15
+ RCL EBX,15
+ RCL ECX,15
+ RCL EDX,15
+ RCL ESP,15
+ RCL EBP,15
+ RCL ESI,15
+ RCL EDI,15
+ RCL DWORD [BX],15
+
+ RCR AX,7
+ ROL AX,7
+ ROR AX,7
+ SAL AX,7
+ SAR AX,7
+ SHL AX,7
+ SHR AX,7
diff --git a/bin86-0.3/as/asm/summary.as b/bin86-0.3/as/asm/summary.as
new file mode 100644
index 0000000..cd62e37
--- /dev/null
+++ b/bin86-0.3/as/asm/summary.as
@@ -0,0 +1,385 @@
+general:
+ ; AL,imm8
+ ; AX,imm16
+ ; EAX,imm32
+ ; r/m8,imm8
+ ; r/m16,imm16
+ ; r/m32.imm32
+ ; r/m16,signed imm8
+ ; r/m32,signed imm8
+ ; r/m8,r8
+ ; r/m16,r16
+ ; r/m32,r32
+ ; r8,r/m8
+ ; r16,r/m16
+ ; r32,r/m32
+
+shiftcount:
+ ; 1
+ ; CL
+ ; imm8
+unary alterable:
+ ; r/m8
+ ; r/m16
+ ; r/m32
+
+ AAA
+ AAD ; [unsupported base]
+ AAM ; [unsupported base]
+ AAS
+ ADC ; general
+ ADD ; general
+ AND ; general
+ ARPL ; r/m16,r16
+ BOUND ; r16,m16&16
+ BOUND ; r32,m32&32
+ BSF ; r16,r/m16
+ BSF ; r32,r/m32
+ BSR ; r16,r/m16
+ BSR ; r32,r/m32
+ BSWAP ; r32
+ BT ; r/m16,r16
+ BT ; r/m32,r32
+ BT ; r/m16,imm8
+ BT ; r/m32,imm8
+ BTC ; r/m16,r16
+ BTC ; r/m32,r32
+ BTC ; r/m16,imm8
+ BTC ; r/m32,imm8
+ BTR ; r/m16,r16
+ BTR ; r/m32,r32
+ BTR ; r/m16,imm8
+ BTR ; r/m32,imm8
+ BTS ; r/m16,r16
+ BTS ; r/m32,r32
+ BTS ; r/m16,imm8
+ BTS ; r/m32,imm8
+ CALL ; rel16
+ CALL ; r/m16
+ CALL ; ptr16:16
+ CALL ; m16:16
+ CALL ; rel32
+ CALL ; r/m32
+ CALL ; ptr16:32
+ CALL ; m16:32
+ CBW
+ CDQ
+ CLC
+ CLD
+ CLI
+ CLTS
+ CMC
+ CMP ; general
+ CMPS ; [segreg:]m8,m8
+ CMPS ; [segreg:]m16,m16
+ CMPS ; [segreg:]m32,m32
+ CMPSB
+ CMPSW
+ CMPSD
+ CMPXCHG ; r/m8,r8
+ CMPXCHG ; r/m16,r16
+ CMPXCHG ; r/m32,r32
+ CWD
+ CWDE
+ DAA
+ DAS
+ DEC ; unary alterable
+ DEC ; r16
+ DEC ; r32
+ DIV ; AL,r/m8
+ DIV ; AX,r/m16
+ DIV ; EAX,r/m32
+ ENTER ; imm16,imm8
+ HLT
+ IDIV ; AL,r/m8
+ IDIV ; AX,r/m16
+ IDIV ; EAX,r/m32
+ IMUL ; r/m8
+ IMUL ; r/m16
+ IMUL ; r/m32
+ IMUL ; r16,r/m16
+ IMUL ; r32,r/m32
+ IMUL ; r16,r/m16,imm8
+ IMUL ; r32,r/m32,imm8
+ IMUL ; r16,imm8
+ IMUL ; r32,imm8
+ IMUL ; r16,r/m16,imm16
+ IMUL ; r32,r/m32,imm32
+ IMUL ; r16,imm16
+ IMUL ; r32,imm32
+ IN ; AL,imm8
+ IN ; AX,imm8
+ IN ; EAX,imm8
+ IN ; AL,DX
+ IN ; AX,DX
+ IN ; EAX,DX
+ INC ; unary alterable
+ INC ; r16
+ INC ; r32
+ INSB
+ INSW
+ INSD
+ INT ; imm8
+ INTO
+ INVD
+ INVLPG ; m
+ IRET
+ IRETD
+ JCC ; rel8
+ JCC ; rel16/32
+ JA
+ JAE
+ JB
+ JBE
+ JC
+ JCXZ
+ JECXZ
+ JE
+ JG
+ JGE
+ JL
+ JLE
+ JNA
+ JNAE
+ JNB
+ JNBE
+ JNC
+ JNE
+ JNG
+ JNGE
+ JNL
+ JNLE
+ JNO
+ JNP
+ JNS
+ JNZ
+ JO
+ JP
+ JPE
+ JPO
+ JS
+ JZ
+ JMP ; rel8
+ JMP ; rel16
+ JMP ; r/m16
+ JMP ; ptr16:16
+ JMP ; m16:16
+ JMP ; rel32
+ JMP ; r/m32
+ JMP ; ptr16:32
+ JMP ; m16:32
+ LAHF
+ LAR ; r16,r/m16
+ LAR ; r32,r/m32
+ LEA ; r16,m
+ LEA ; r32,m
+ LEAVE
+ LGDT ; m16&32
+ LIDT ; m16&32
+ LDS ; r16,m16:16
+ LDS ; r32,m16:32
+ LES ; r16,m16:16
+ LES ; r32,m16:32
+ LFS ; r16,m16:16
+ LFS ; r32,m16:32
+ LGS ; r16,m16:16
+ LGS ; r32,m16:32
+ LSS ; r16,m16:16
+ LSS ; r32,m16:32
+ LLDT ; r/m16
+ LMSW ; r/m16
+ LOCK
+ LODS ; [segreg:]m8
+ LODS ; [segreg:]m16
+ LODS ; [segreg:]m32
+ LODSB
+ LODSW
+ LODSD
+ LOOP ; rel8
+ LOOPE ; rel8
+ LOOPZ ; rel8
+ LOOPNE ; rel8
+ LOOPNZ ; rel8
+ LSL ; r16,r/m16
+ LSL ; r32,r/m32
+ LTR ; r/m16
+ MOV ; r/m8,r8
+ MOV ; r/m16,r16
+ MOV ; r/m32,r32
+ MOV ; r8,r/m8
+ MOV ; r16,r/m16
+ MOV ; r32,r/m32
+ MOV ; r/m16,Sreg
+ MOV ; Sreg,r/m16
+ MOV ; AL,moffs8
+ MOV ; AX,moffs16
+ MOV ; EAX,moffs32
+ MOV ; moffs8,AL
+ MOV ; moffs16,AX
+ MOV ; moffs32,EAX
+ MOV ; r8,imm8
+ MOV ; r16,imm16
+ MOV ; r32,imm32
+ MOV ; r32,CR0/CR2/CR3
+ MOV ; r/m8,imm8
+ MOV ; r/m16,imm16
+ MOV ; r/m32,imm32
+ MOV ; r32,CR0/CR2/CR3
+ MOV ; CR0/CR2/CR3,r32
+ MOV ; r32,DR0/DR1/DR2/DR3/DR6/DR7
+ MOV ; DR0/DR1/DR2/DR3/DR6/DR7,r32
+ MOV ; r32,TR6/TR7
+ MOV ; TR6/TR7,r32
+ MOVS ; [segreg:]m8,m8
+ MOVS ; [segreg:]m16,m16
+ MOVS ; [segreg:]m32,m32
+ MOVSB
+ MOVSW
+ MOVSD
+ MOVSX ; r16,r/m8
+ MOVSX ; r32,r/m8
+ MOVSX ; r32,r/m16
+ MOVZX ; r16,r/m8
+ MOVZX ; r32,r/m8
+ MOVZX ; r32,r/m16
+ MUL ; AL,r/m8
+ MUL ; AX,r/m16
+ MUL ; EAX,r/m32
+ NEG ; unary alterable
+ NOP
+ NOT ; unary alterable
+ OR ; general
+ OUT ; imm8,AL
+ OUT ; imm8,AX
+ OUT ; imm8,EAX
+ OUT ; DX,AL
+ OUT ; DX,AX
+ OUT ; DX,EAX
+ OUTS ; [segreg:]m8
+ OUTS ; [segreg:]m16
+ OUTS ; [segreg:]m32
+ OUTSB
+ OUTSW
+ OUTSD
+ POP ; m16
+ POP ; m32
+ POP ; r16
+ POP ; r32
+ POP ; DS
+ POP ; ES
+ POP ; FS
+ POP ; GS
+ POP ; SS
+ POPA
+ POPAD
+ POPF
+ POPFD
+ PUSH ; m16
+ PUSH ; m32
+ PUSH ; r16
+ PUSH ; r32
+ PUSH ; imm8
+ PUSH ; imm16
+ PUSH ; imm32
+ PUSH ; CS
+ PUSH ; DS
+ PUSH ; ES
+ PUSH ; FS
+ PUSH ; GS
+ PUSH ; SS
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+ RCL ; shiftcount
+ RCR ; shiftcount
+ ROL ; shiftcount
+ ROR ; shiftcount
+ REP ; INS/MOVS/OUTS/STOS
+ REPE ; CMPS/SCAS
+ REPNE ; CMPS/SCAS
+ RET
+ RET ; imm16
+ SAHF
+ SAL ; shiftcount
+ SAR ; shiftcount
+ SHL ; shiftcount
+ SHR ; shiftcount
+ SBB ; general
+ SCASB
+ SCASW
+ SCASD
+ SETA ; r/m8
+ SETAE ; r/m8
+ SETB ; r/m8
+ SETBE ; r/m8
+ SETC ; r/m8
+ SETE ; r/m8
+ SETG ; r/m8
+ SETGE ; r/m8
+ SETL ; r/m8
+ SETLE ; r/m8
+ SETNA ; r/m8
+ SETNAE ; r/m8
+ SETNB ; r/m8
+ SETNBE ; r/m8
+ SETNC ; r/m8
+ SETNE ; r/m8
+ SETNG ; r/m8
+ SETNGE ; r/m8
+ SETNL ; r/m8
+ SETNLE ; r/m8
+ SETNO ; r/m8
+ SETNP ; r/m8
+ SETNS ; r/m8
+ SETNZ ; r/m8
+ SETO ; r/m8
+ SETP ; r/m8
+ SETPE ; r/m8
+ SETPO ; r/m8
+ SETS ; r/m8
+ SETZ ; r/m8
+ SGDT ; m
+ SHLD ; r/m16,r16,imm8
+ SHLD ; r/m32,r32,imm8
+ SHLD ; r/m16,r16,CL
+ SHLD ; r/m32,r32,CL
+ SHRD ; r/m16,r16,imm8
+ SHRD ; r/m32,r32,imm8
+ SHRD ; r/m16,r16,CL
+ SHRD ; r/m32,r32,CL
+ SIDT ; m
+ SLDT ; r/m16
+ SMSW ; r/m16
+ STC
+ STD
+ STI
+ STOSB
+ STOSW
+ STOSD
+ STR ; r/m16
+ SUB ; general
+ TEST ; AL,imm8
+ TEST ; AX,imm16
+ TEST ; EAX,imm32
+ TEST ; r/m8,imm8
+ TEST ; r/m16,imm16
+ TEST ; r/m32,imm32
+ TEST ; r/m8,r8
+ TEST ; r/m16,r16
+ TEST ; r/m32/r32
+ VERR ; r/m16
+ VERW ; r/m16
+ WAIT
+ WBINVD
+ XADD ; r/m8,r8
+ XADD ; r/m16,r16
+ XADD ; r/m32,r32
+ XCHG ; AX,r16
+ XCHG ; EAX,r32
+ XCHG ; r/m8,r8
+ XCHG ; r/m16,r16
+ XCHG ; r/m32,r32
+ XLAT ; [segreg:]m8
+ XLATB
+ XOR ; general
diff --git a/bin86-0.3/as/asm/xchg.asm b/bin86-0.3/as/asm/xchg.asm
new file mode 100644
index 0000000..f05157f
--- /dev/null
+++ b/bin86-0.3/as/asm/xchg.asm
@@ -0,0 +1,103 @@
+ XCHG AX,BL ; illeg
+ XCHG AX,BYTE [BX] ; illeg
+ XCHG AX,DS ; illeg
+ XCHG AX,#1 ; illeg
+
+ XCHG AX,AX
+ XCHG AX,BX
+ XCHG AX,CX
+ XCHG AX,DX
+ XCHG AX,SP
+ XCHG AX,BP
+ XCHG AX,SI
+ XCHG AX,DI
+
+ XCHG AX,AX
+ XCHG BX,AX
+ XCHG CX,AX
+ XCHG DX,AX
+ XCHG SP,AX
+ XCHG BP,AX
+ XCHG SI,AX
+ XCHG DI,AX
+
+ XCHG EAX,EAX
+ XCHG EAX,EBX
+ XCHG EAX,ECX
+ XCHG EAX,EDX
+ XCHG EAX,ESP
+ XCHG EAX,EBP
+ XCHG EAX,ESI
+ XCHG EAX,EDI
+
+ XCHG EAX,EAX
+ XCHG EBX,EAX
+ XCHG ECX,EAX
+ XCHG EDX,EAX
+ XCHG ESP,EAX
+ XCHG EBP,EAX
+ XCHG ESI,EAX
+ XCHG EDI,EAX
+
+ XCHG AL,AL
+ XCHG AL,AH
+ XCHG AL,BL
+ XCHG AL,BH
+ XCHG BL,CL
+ XCHG BL,CH
+ XCHG BL,DL
+ XCHG BL,DH
+
+ XCHG [BX],AL
+ XCHG [BX],AH
+ XCHG [BX],BL
+ XCHG [BX],BH
+ XCHG [BX],CL
+ XCHG [BX],CH
+ XCHG [BX],DL
+ XCHG [BX],DH
+
+ XCHG AL,[BX]
+ XCHG AH,[BX]
+ XCHG BL,[BX]
+ XCHG BH,[BX]
+ XCHG CL,[BX]
+ XCHG CH,[BX]
+ XCHG DL,[BX]
+ XCHG DH,[BX]
+
+ XCHG [BX],AX
+ XCHG [BX],BX
+ XCHG [BX],CX
+ XCHG [BX],DX
+ XCHG [BX],SP
+ XCHG [BX],BP
+ XCHG [BX],SI
+ XCHG [BX],DI
+
+ XCHG AX,[BX]
+ XCHG BX,[BX]
+ XCHG CX,[BX]
+ XCHG DX,[BX]
+ XCHG SP,[BX]
+ XCHG BP,[BX]
+ XCHG SI,[BX]
+ XCHG DI,[BX]
+
+ XCHG [BX],EAX
+ XCHG [BX],EBX
+ XCHG [BX],ECX
+ XCHG [BX],EDX
+ XCHG [BX],ESP
+ XCHG [BX],EBP
+ XCHG [BX],ESI
+ XCHG [BX],EDI
+
+ XCHG AX,[EBX]
+ XCHG BX,[EBX]
+ XCHG CX,[EBX]
+ XCHG DX,[EBX]
+ XCHG SP,[EBX]
+ XCHG BP,[EBX]
+ XCHG SI,[EBX]
+ XCHG DI,[EBX]
diff --git a/bin86-0.3/as/assemble.c b/bin86-0.3/as/assemble.c
new file mode 100644
index 0000000..4e96178
--- /dev/null
+++ b/bin86-0.3/as/assemble.c
@@ -0,0 +1,314 @@
+/*
+ * bin86/as/assemble.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* assemble.c - main loop for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+
+PRIVATE bool_t nocolonlabel; /* set for labels not followed by ':' */
+PRIVATE void (*routine) P((void));
+PRIVATE pfv rout_table[] =
+{
+ pelse,
+ pelseif,
+ pelsifc,
+ pendif,
+ pif,
+ pifc,
+
+ /* start of non-conditionals */
+ palign,
+ pblkw,
+ pblock,
+ pbss,
+ pcomm,
+ pcomm1,
+ pdata,
+ pendb,
+ penter,
+ pentry,
+ pequ,
+ peven,
+ pexport,
+ pfail,
+ pfcb,
+ pfcc,
+ pfdb,
+ pfqb,
+ pget,
+ pglobl,
+ pident,
+ pimport,
+ plcomm,
+ plcomm1,
+ plist,
+ ploc,
+ pmaclist,
+ pmacro,
+ pmap,
+ porg,
+ pproceof,
+ prmb,
+ psect,
+ pset,
+ psetdp,
+ ptext,
+#ifdef I80386
+ puse16,
+ puse32,
+#endif
+ pwarn,
+ /* end of pseudo-ops */
+
+#ifdef I80386
+ mbcc,
+ mbswap,
+ mcall,
+ mcalli,
+ mdivmul,
+ menter,
+ mEwGw,
+ mExGx,
+ mf_inher,
+ mf_m,
+ mf_m2,
+ mf_m2_ax,
+ mf_m2_m4,
+ mf_m2_m4_m8,
+ mf_m4_m8_optst,
+ mf_m4_m8_st,
+ mf_m4_m8_stst,
+ mf_m4_m8_m10_st,
+ mf_m10,
+ mf_optst,
+ mf_st,
+ mf_stst,
+ mf_w_inher,
+ mf_w_m,
+ mf_w_m2,
+ mf_w_m2_ax,
+ mgroup1,
+ mgroup2,
+ mgroup6,
+ mgroup7,
+ mgroup8,
+ mGvEv,
+ mGvMa,
+ mGvMp,
+ mimul,
+ min,
+ mincdec,
+ minher,
+ minher16,
+ minher32,
+ minhera,
+ mint,
+ mjcc,
+ mjcxz,
+ mlea,
+ mmov,
+ mmovx,
+ mnegnot,
+ mout,
+ mpushpop,
+ mret,
+ mseg,
+ msetcc,
+ mshdouble,
+ mtest,
+ mxchg,
+#endif /* I80386 */
+
+#ifdef MC6809
+ mall, /* all address modes allowed, like LDA */
+ malter, /* all but immediate, like STA */
+ mimmed, /* immediate only (ANDCC, ORCC) */
+ mindex, /* indexed (LEA's) */
+ minher, /* inherent, like CLC or CLRA */
+ mlong, /* long branches */
+ mshort, /* short branches */
+ msstak, /* S-stack (PSHS, PULS) */
+ mswap, /* TFR, EXG */
+ mustak, /* U-stack (PSHU,PULU) */
+#endif /* MC6809 */
+};
+
+FORWARD void asline P((void));
+
+/*
+ This uses registers as follows: A is for work and is not preserved by
+ the subroutines.B holds the last symbol code, X usually points to data
+ about the last symbol, U usually holds the value of last expression
+ or symbol, and Y points to the current char. The value in Y is needed
+ by READCH and GETSYM. EXPRES needs B and Y, and returns a value in U.
+ If the expression starts with an identifier, X must point to its string.
+ LOOKUP needs a string pointer in X and length in A. It returns a table
+ pointer in X (unless not assembling and not found), symbol type in A
+ and overflow in CC.
+*/
+
+PUBLIC void assemble()
+{
+ while (TRUE)
+ {
+ asline();
+ if (label != NULL) /* must be confirmed if still set */
+ { /* it is nulled by EQU, COMM and SET */
+#ifndef MC6809
+#define NEEDENDLABEL ILLAB
+ if (nocolonlabel)
+ error(NEEDENDLABEL);
+#endif
+ label->type |= LABIT; /* confirm, perhaps redundant */
+ if (label->type & REDBIT)
+ {
+ /* REDBIT meant 'GLOBLBIT' while LABIT was not set. */
+ label->type |= EXPBIT;
+ label->type &= ~REDBIT;
+ }
+ if ((mcount | popflags) == 0)
+ /* unaccompanied label, display adr like EQU and SET */
+ showlabel();
+ label = NULL; /* reset for next line */
+ }
+ skipline();
+ listline();
+ genbin();
+ genobj();
+ binmbuf = lc += lcjump
+#ifdef I80386
+ + immcount
+#endif
+ ;
+ }
+}
+
+PRIVATE void asline()
+{
+ register struct sym_s *symptr;
+
+ postb = popflags = pcrflag =
+#ifdef I80386
+ sprefix = oprefix = aprefix =
+#endif
+ immcount = lastexp.data = lcjump = 0;
+#ifdef I80386
+ sib = NO_SIB;
+#endif
+#if SIZEOF_OFFSET_T > 2
+ fqflag =
+#endif
+ fdflag = fcflag = FALSE;
+ readline();
+ getsym();
+ if (sym != IDENT) /* expect label, mnemonic or macro */
+ return; /* anything else is a comment */
+ symptr = gsymptr;
+ if (!ifflag)
+ /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */
+ {
+ if (symptr == NULL || !(symptr->type & MNREGBIT) ||
+ symptr->data & REGBIT ||
+ symptr->value_reg_or_op.op.routine >= MIN_NONCOND)
+ return;
+ }
+ else if (!(symptr->type & (MACBIT | MNREGBIT)))
+ /* not macro, op, pseudo-op or register, expect label */
+ {
+ if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */
+ {
+ sym = COLON;
+ ++lineptr;
+ }
+ if (symptr->type & (LABIT | VARBIT))
+ {
+ if (symptr->type & REDBIT)
+ labelerror(RELAB);
+ label = symptr;
+ }
+ else if (checksegrel(symptr))
+ {
+ symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */
+#ifdef MC6809
+#if 0
+ if (sym == COLON)
+ symptr->type |= EXPBIT;
+#endif
+#endif
+ symptr->data = (symptr->data & FORBIT) | lcdata;
+ /* remember if forward referenced */
+ symptr->value_reg_or_op.value = lc;
+ /* unless changed by EQU,COMM or SET */
+ label = symptr;
+ }
+ getsym();
+ if (sym != IDENT)
+ {
+ if (sym == EQOP)
+ {
+ getsym();
+ pequ();
+ }
+ return; /* anything but ident is comment */
+ }
+ symptr = gsymptr;
+ }
+ if (symptr->type & MACBIT)
+ {
+ entermac(symptr);
+ return;
+ }
+ if (!(symptr->type & MNREGBIT))
+ {
+ error(OPEXP);
+ return;
+ }
+ if (symptr->data & REGBIT)
+ {
+ error(REGUID);
+ return;
+ }
+ mnsize = 0;
+ if ((page = (symptr->data & (PAGE1 | PAGE2))) != 0)
+ {
+#ifdef MNSIZE
+ if (page == (PAGE1 | PAGE2))
+ {
+ mnsize = 1;
+ page = 0;
+ }
+ else
+#endif
+ {
+#ifdef PAGE2_OPCODE
+ if (page == PAGE2)
+ page = PAGE2_OPCODE;
+ else
+#endif
+ page = PAGE1_OPCODE;
+ mcount = 1;
+ }
+ }
+ opcode = symptr->value_reg_or_op.op.opcode;
+ routine = rout_table[symptr->value_reg_or_op.op.routine];
+ getsym();
+ (*routine)();
+ if (sym != EOLSYM)
+ error(JUNK_AFTER_OPERANDS);
+#ifdef I80386
+ if (aprefix != 0)
+ ++mcount;
+ if (oprefix != 0)
+ ++mcount;
+ if (sprefix != 0)
+ ++mcount;
+#endif
+}
diff --git a/bin86-0.3/as/byteord.h b/bin86-0.3/as/byteord.h
new file mode 100644
index 0000000..01d2d85
--- /dev/null
+++ b/bin86-0.3/as/byteord.h
@@ -0,0 +1,24 @@
+/*
+ * bin86/as/byteord.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* byteord.h - byte order dependencies for C compiler, assembler, linker */
+
+/* These are for the targets of everything and for linker source too. */
+
+#ifdef I8086
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */
+#endif
+
+#ifdef I80386
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0
+#endif
+
+#ifdef MC6809
+# define BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
diff --git a/bin86-0.3/as/chk b/bin86-0.3/as/chk
new file mode 100755
index 0000000..ce55954
--- /dev/null
+++ b/bin86-0.3/as/chk
@@ -0,0 +1,9 @@
+for i in `ls asm/*.asm`
+do
+ j=`basename $i .asm`
+ ./as asm/$j.asm -b $j.bin -o $j.obj > /dev/null
+ cmp $j.bin bin/$j.bin
+ cmp $j.obj obj/$j.obj
+ rm $j.bin $j.obj
+done
+
diff --git a/bin86-0.3/as/const.h b/bin86-0.3/as/const.h
new file mode 100644
index 0000000..7961cf5
--- /dev/null
+++ b/bin86-0.3/as/const.h
@@ -0,0 +1,430 @@
+/*
+ * bin86/as/const.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+#undef __BYTE_ORDER
+#undef __LITTLE_ENDIAN
+#undef __BIG_ENDIAN
+#include "endian.h"
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define LOW_BYTE 3
+#else
+#define LOW_BYTE 0
+#endif
+
+#define align(x) ((x) = (void *)(((int) (x) + (4-1)) & ~(4-1)))
+/* const.h - constants for assembler */
+
+/* major switches */
+
+#define I80386 /* generate 80386 code */
+#undef MC6809 /* generate 6809 code */
+#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */
+#undef SOS_EDOS /* source OS is EDOS */
+
+/* defaults */
+
+#define DIRCHAR '/' /* character separating filename from dir */
+#define INBUFSIZE 8192
+#define SOS_EOLSTR "\012"
+
+/* defaults modified by switches */
+
+#ifdef SOS_EDOS
+# undef INBUFSIZE
+# define INBUFSIZE 512
+# undef SOS_EOLSTR
+# define SOS_EOLSTR "\015\012"
+# define STAKSIZ 256 /* table grows up to stack less this */
+#endif
+
+/* booleans */
+
+#define FALSE 0
+#define TRUE 1
+
+/* ASCII constants */
+
+#define ETB 23
+
+/* C tricks */
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+/* O/S constants */
+
+#define CREAT_PERMS 0666
+#define EOF (-1)
+#define STDIN 0
+#define STDOUT 1
+
+enum
+{
+/* Register codes (internal to assembler). */
+#ifdef I80386
+
+/* Index regs must be first. */
+ BPREG,
+ BXREG,
+ DIREG,
+ SIREG,
+#define MAX16BITINDREG SIREG
+
+ EAXREG,
+ EBPREG,
+ EBXREG,
+ ECXREG,
+ EDIREG,
+ EDXREG,
+ ESIREG,
+ ESPREG,
+#define MAXINDREG ESPREG
+
+ AXREG,
+ CXREG,
+ DXREG,
+ SPREG,
+
+ AHREG,
+ ALREG,
+ BHREG,
+ BLREG,
+ CHREG,
+ CLREG,
+ DHREG,
+ DLREG,
+
+ CSREG,
+ DSREG,
+ ESREG,
+ FSREG,
+ GSREG,
+ SSREG,
+
+ CR0REG,
+ CR2REG,
+ CR3REG,
+ DR0REG,
+ DR1REG,
+ DR2REG,
+ DR3REG,
+ DR6REG,
+ DR7REG,
+ TR3REG,
+ TR4REG,
+ TR5REG,
+ TR6REG,
+ TR7REG,
+
+ ST0REG,
+ ST1REG,
+ ST2REG,
+ ST3REG,
+ ST4REG,
+ ST5REG,
+ ST6REG,
+ ST7REG,
+
+ NOREG,
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* Index regs must be first, then PC. */
+ SREG,
+ UREG,
+ XREG,
+ YREG,
+#define MAXINDREG YREG
+
+ PCREG,
+ AREG,
+ BREG,
+ CCREG,
+ DPREG,
+ DREG,
+
+ NOREG,
+#endif /* MC6809 */
+};
+
+#ifdef I80386
+enum
+{
+/* Type and size keywords. */
+ BYTEOP,
+ DWORDOP,
+ FWORDOP,
+ FAROP,
+ PTROP,
+ PWORDOP,
+ QWORDOP,
+ TBYTEOP,
+ WORDOP,
+};
+#endif /* I80386 */
+
+/* special chars */
+
+#define EOL 0
+#define MACROCHAR '?'
+
+enum
+{
+/* Symbol codes. */
+
+/* The first 2 must be from chars in identifiers. */
+ IDENT,
+ INTCONST,
+
+/* The next few are best for other possibly-multi-char tokens. */
+ ADDOP, /* also ++ */
+ BINCONST,
+ CHARCONST,
+ GREATERTHAN, /* also >> and context-sensitive */
+ HEXCONST,
+ LESSTHAN, /* also << and context-sensitive */
+ SUBOP, /* also -- */
+ WHITESPACE,
+
+ ANDOP,
+ COMMA,
+ EOLSYM,
+ EQOP,
+ IMMEDIATE,
+ INDIRECT,
+ LBRACKET,
+ LPAREN,
+ MACROARG,
+ NOTOP,
+ OROP,
+ OTHERSYM,
+ POSTINCOP,
+ PREDECOP,
+ RBRACKET,
+ RPAREN,
+ SLASH, /* context-sensitive */
+ SLOP,
+ SROP,
+ STAR, /* context-sensitive */
+ STRINGCONST,
+ COLON,
+};
+
+enum
+{
+/* Error codes. */
+
+/* Syntax errors. */
+ COMEXP,
+ DELEXP,
+ FACEXP,
+ IREGEXP,
+ LABEXP,
+ LPEXP,
+ OPEXP,
+ RBEXP,
+ REGEXP,
+ RPEXP,
+ SPEXP,
+
+/* Expression errors. */
+ ABSREQ,
+ NONIMPREQ,
+ RELBAD,
+
+/* Label errors. */
+ ILLAB,
+ MACUID,
+ MISLAB,
+ MNUID,
+ REGUID,
+ RELAB,
+ UNBLAB,
+ UNLAB,
+ VARLAB,
+
+/* Addressing errors. */
+ ABOUNDS,
+ DBOUNDS,
+ ILLMOD,
+ ILLREG,
+
+/* Control structure errors. */
+ ELSEBAD,
+#define ELSEIFBAD ELSEBAD
+ ENDBBAD,
+#define ENDIFBAD ELSEBAD
+ EOFBLOCK,
+ EOFIF,
+ EOFLC,
+ EOFMAC,
+ FAILERR,
+
+/* Overflow errors. */
+ BLOCKOV,
+ BWRAP,
+ COUNTOV,
+ COUNTUN,
+ GETOV,
+ IFOV,
+
+ LINLONG,
+ MACOV,
+ OBJSYMOV,
+ OWRITE,
+ PAROV,
+ SYMOV,
+ SYMOUTOV,
+
+/* I/O errors. */
+ OBJOUT,
+
+/* Miscellaneous errors. */
+ AL_AX_EAX_EXP,
+ CTLINS,
+ FURTHER,
+ ILL_IMM_MODE,
+ ILL_IND_TO_IND,
+ ILL_IND,
+ ILL_IND_PTR,
+ ILL_SCALE,
+ ILL_SECTION,
+ ILL_SEG_REG,
+ ILL_SOURCE_EA,
+ ILL_SIZE,
+ IMM_REQ,
+ INDEX_REG_EXP,
+ IND_REQ,
+ MISMATCHED_SIZE,
+ NOIMPORT,
+ REENTER,
+ REL_REQ,
+ REPEATED_DISPL,
+ SEGREL,
+ SEG_REG_REQ,
+ SIZE_UNK,
+
+ FP_REG_REQ,
+ FP_REG_NOT_ALLOWED,
+ ILL_FP_REG,
+ ILL_FP_REG_PAIR,
+ JUNK_AFTER_OPERANDS,
+
+ ALREADY,
+
+/* Warnings. */
+#define MINWARN SHORTB
+ SHORTB,
+};
+
+/* symbol table entry */
+
+ /* type entry contains following flags */
+#define ENTBIT (1<<0) /* entry point (= OBJ_N_MASK) */
+#define COMMBIT (1<<1) /* common */
+#define LABIT (1<<2) /* label (a PC location or defined by EQU) */
+#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */
+#define MACBIT (1<<4) /* macro */
+#define REDBIT (1<<5) /* redefined (if with LABIT or VARBIT), to do
+ * with SA_MASK (if with COMMBIT), otherwise
+ * means globl */
+#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */
+#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */
+
+ /* data entry contains following flags, valid */
+ /* for expressions as well as syms */
+#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT | PAGE1 */
+#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT | PAGE2 */
+#define REGBIT (1<<2) /* register = MNREGBIT | REGBIT */
+#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT | SIZEBIT */
+#define SEGM 0x0F /* 1st 4 bits reused for segment if !MNREGBIT */
+#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */
+#define FORBIT (1<<5) /* forward referenced */
+#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */
+#define UNDBIT (1<<7) /* undefined */
+
+/* object code format (Introl) */
+
+#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */
+
+#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */
+
+#define OBJ_ABS 0x40 /* absolute code command */
+#define OBJ_OFFSET_REL 0x80 /* offset relocation command */
+#define OBJ_SET_SEG 0x20 /* set segment command */
+#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */
+#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */
+#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */
+#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */
+
+#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */
+#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */
+oops - RELBIT misplaced
+#endif
+#define OBJ_E_MASK 0x80 /* exported bit (symbols) */
+#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */
+oops - EXPBIT misplaced
+#endif
+#define OBJ_I_MASK 0x40 /* imported bit (symbols) */
+#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */
+oops - IMPBIT misplaced
+#endif
+#define OBJ_N_MASK 0x01 /* entry bit (symbols) */
+#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */
+oops - ENTBIT misplaced
+#endif
+#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */
+#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */
+#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */
+#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */
+
+#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */
+#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */
+
+#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */
+#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */
+
+#define SYMLIS_NAMELEN 26
+#define SYMLIS_LEN (sizeof (struct sym_listing_s))
+
+#define FILNAMLEN 64 /* max length of a file name */
+#define LINLEN 256 /* max length of input line */
+#define LINUM_LEN 5 /* length of formatted line number */
+
+#define SPTSIZ 1024 /* number of symbol ptrs */
+ /* pseudo-op flags */
+#define POPHI 1 /* set to print hi byte of adr */
+#define POPLO 2 /* to print lo byte of ADR */
+#define POPLC 4 /* to print LC */
+#define POPLONG 8 /* to print high word of ADR */
+#define MAXBLOCK 8 /* max nesting level of BLOCK stack */
+#define MAXGET 8 /* max nesting level of GET stack */
+#define MAXIF 8 /* max nesting level of IF stack */
+#define MACPSIZ (128 / sizeof (struct schain_s))
+ /* size of macro param buffer */
+#define MAXMAC 8 /* max nesting level of macro stack */
+#define NLOC 16 /* number of location counters */
+#ifdef I80386
+#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */
+#endif
+
+/* special segments */
+
+#define BSSLOC 3
+#define DATALOC 3
+#define DPLOC 2
+#define STRLOC 1
+#define TEXTLOC 0
diff --git a/bin86-0.3/as/det_endian.c b/bin86-0.3/as/det_endian.c
new file mode 100644
index 0000000..50b5bdc
--- /dev/null
+++ b/bin86-0.3/as/det_endian.c
@@ -0,0 +1,34 @@
+/* Determine the "endianness" of the CPU.
+ Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+ Contributed by Torbjorn Granlund (tege@sics.se).
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+main ()
+{
+ unsigned long int i;
+
+ if (sizeof (i) != 4)
+ puts ("#error \"Not a 32-bit machine!\"");
+
+ i = (((((('4' << 8) + '3') << 8) + '2') << 8) + '1');
+
+ printf ("#define __BYTE_ORDER %.4s\n", (char *) &i);
+
+ exit (0);
+}
diff --git a/bin86-0.3/as/error.c b/bin86-0.3/as/error.c
new file mode 100644
index 0000000..343ec8c
--- /dev/null
+++ b/bin86-0.3/as/error.c
@@ -0,0 +1,105 @@
+/*
+ * bin86/as/error.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* error.c - error routines for assembler */
+
+#include <string.h>
+#include "const.h"
+#include "type.h"
+
+PRIVATE char *errormessage[] =
+{
+ "comma expected",
+ "delimiter expected",
+ "factor expected",
+ "index register expected",
+ "label expected",
+ "left parentheses expected",
+ "opcode expected",
+ "right bracket expected",
+ "register expected",
+ "right parentheses expected",
+ "space expected",
+ "absolute expression required",
+ "non-imported expression required",
+ "relocation impossible",
+ "illegal label",
+ "MACRO used as identifier",
+ "missing label",
+ "opcode used as identifier",
+ "register used as identifier",
+ "redefined label",
+ "unbound label",
+ "undefined label",
+ "variable used as label",
+ "address out of bounds",
+ "data out of bounds",
+ "illegal address mode",
+ "illegal register",
+ "no matching IF",
+ "no matching BLOCK",
+ "end of file in BLOCK",
+ "end of file in IF",
+ "location counter was undefined at end",
+ "end of file in MACRO",
+ "user-generated error",
+ "BLOCK stack overflow",
+ "binary file wrap-around",
+ "counter overflow",
+ "counter underflow",
+ "GET stack overflow",
+ "IF stack overflow",
+ "line too long",
+ "MACRO stack overflow",
+ "object symbol table overflow",
+ "program overwrite",
+ "parameter table overflow",
+ "symbol table overflow",
+ "output symbol table overflow",
+ "error writing object file",
+ "al, ax or eax expected",
+ "control character in string",
+ "futher errors suppressed",
+ "illegal immediate mode",
+ "illegal indirect to indirect",
+ "illegal indirection",
+ "illegal indirection from previous 'ptr'",
+ "illegal scale",
+ "illegal section",
+ "illegal segment register",
+ "illegal source effective address",
+ "illegal size",
+ "immediate expression expected",
+ "index register expected",
+ "indirect expression required",
+ "mismatched size",
+ "no imports with binary file output",
+ "multiple ENTER pseudo-ops",
+ "relative expression required",
+ "repeated displacement",
+ "segment or relocatability redefined",
+ "segment register required",
+ "size unknown",
+ "FP register required",
+ "FP register not allowed",
+ "illegal FP register",
+ "illegal FP register pair",
+ "junk after operands",
+ "already defined",
+ "short branch would do",
+ "unknown error",
+};
+
+/* build null-terminated error message for given error at given spot */
+
+PUBLIC char *build_error_message(errnum, buf)
+unsigned errnum;
+char *buf;
+{
+ if (errnum >= sizeof errormessage / sizeof errormessage[0])
+ errnum = sizeof errormessage / sizeof errormessage[0] - 1;
+ return strcpy(buf, errormessage[errnum]);
+}
diff --git a/bin86-0.3/as/express.c b/bin86-0.3/as/express.c
new file mode 100644
index 0000000..7cd0b55
--- /dev/null
+++ b/bin86-0.3/as/express.c
@@ -0,0 +1,388 @@
+/*
+ * bin86/as/express.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* express.c - expression handler for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "globvar.h"
+#include "scan.h"
+#include "source.h"
+
+FORWARD void experror P((error_pt errnum));
+FORWARD void expundefined P((void));
+FORWARD void simple2 P((void));
+FORWARD void simple P((void));
+FORWARD void term P((void));
+FORWARD void factor2 P((void));
+
+PUBLIC void absexpres()
+{
+ expres();
+ chkabs();
+}
+
+/* check lastexp.data is abs */
+
+PUBLIC void chkabs()
+{
+ if (lastexp.data & RELBIT)
+ {
+ if (pass != 0)
+ error(ABSREQ);
+ expundefined();
+ }
+}
+
+PRIVATE void experror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ expundefined();
+}
+
+PRIVATE void expundefined()
+{
+ lastexp.data = FORBIT | UNDBIT;
+}
+
+PUBLIC void nonimpexpres()
+{
+ expres();
+ if (lastexp.data & IMPBIT)
+ experror(NONIMPREQ);
+}
+
+/* generate relocation error if pass 2, make lastexp.data forward&undefined */
+
+PUBLIC void showrelbad()
+{
+ if (pass != 0)
+ error(RELBAD);
+ expundefined();
+}
+
+PUBLIC void symabsexpres()
+{
+ getsym();
+ absexpres();
+}
+
+PUBLIC void symexpres()
+{
+ getsym();
+ expres();
+}
+
+/*
+ expres() parses expression = simple expression [op simple expression],
+ where op is =, < or >.
+ Parameters: sym, number in number, identifier from symname to lineptr - 1.
+ Returns value in lastexp.
+*/
+
+PUBLIC void expres()
+{
+ offset_t leftoffset;
+
+ simple();
+ leftoffset = lastexp.offset;
+ if (sym == EQOP)
+ {
+ simple2();
+ if (leftoffset == lastexp.offset)
+ lastexp.offset = -1;
+ else
+ lastexp.offset = 0;
+ }
+ else if (sym == LESSTHAN)
+ {
+ /* context-sensitive, LESSTHAN really means less than here */
+ simple2();
+ if (leftoffset < lastexp.offset)
+ lastexp.offset = -1;
+ else
+ lastexp.offset = 0;
+ }
+ else if (sym == GREATERTHAN)
+ {
+ /* context-sensitive, GREATERTHAN really means greater than here */
+ simple2();
+ if (leftoffset > lastexp.offset)
+ lastexp.offset = -1;
+ else
+ lastexp.offset = 0;
+ }
+}
+
+/* get symbol and 2nd simple expression, check both rel or both abs */
+
+PRIVATE void simple2()
+{
+ unsigned char leftdata;
+
+ leftdata = lastexp.data;
+ getsym();
+ simple();
+ if ((leftdata | lastexp.data) & IMPBIT ||
+ (leftdata ^ lastexp.data) & (RELBIT | SEGM))
+ showrelbad();
+ else
+ lastexp.data = (leftdata & lastexp.data) & ~(RELBIT | SEGM);
+}
+
+/*
+ simple() parses simple expression = [+-] term {op term},
+ where op is +, -, or \ (OR).
+*/
+
+PRIVATE void simple()
+{
+ offset_t leftoffset;
+ unsigned char leftdata;
+
+ if (sym == ADDOP || sym == SUBOP)
+ lastexp.data = lastexp.offset = 0;
+ else
+ term();
+ while (TRUE)
+ {
+ leftoffset = lastexp.offset;
+ leftdata = lastexp.data;
+ if (sym == ADDOP)
+ {
+ getsym();
+ term();
+ if (leftdata & lastexp.data & RELBIT)
+ showrelbad(); /* rel + rel no good */
+ else
+ lastexp.data |= leftdata;
+ lastexp.offset += leftoffset;
+ }
+ else if (sym == SUBOP)
+ {
+ getsym();
+ term();
+ /* check not abs - rel or rel - rel with mismatch */
+ if (lastexp.data & RELBIT &&
+ (!(leftdata & RELBIT) ||
+ (leftdata | lastexp.data) & IMPBIT ||
+ (leftdata ^ lastexp.data) & (RELBIT | SEGM)))
+ showrelbad();
+ else
+ lastexp.data = ((leftdata | lastexp.data) & ~(RELBIT | SEGM))
+ | ((leftdata ^ lastexp.data) & (RELBIT | SEGM));
+ lastexp.offset = leftoffset - lastexp.offset;
+ }
+ else if (sym == OROP)
+ {
+ getsym();
+ term();
+ lastexp.data |= leftdata;
+ chkabs(); /* both must be absolute */
+ lastexp.offset |= leftoffset;
+ }
+ else
+ return;
+ }
+}
+
+/* term() parses term = factor {op factor}, where op is *, /, &, <<, or >>. */
+
+PRIVATE void term()
+{
+ offset_t leftoffset;
+
+ factor();
+ while (TRUE)
+ {
+ leftoffset = lastexp.offset;
+ if (sym == STAR)
+ {
+ /* context-sensitive, STAR means multiplication here */
+ factor2();
+ lastexp.offset *= leftoffset;
+ }
+ else if (sym == SLASH)
+ {
+ /* context-sensitive, SLASH means division here */
+ factor2();
+ lastexp.offset = leftoffset / lastexp.offset;
+ }
+ else if (sym == ANDOP)
+ {
+ factor2();
+ lastexp.offset &= leftoffset;
+ }
+ else if (sym == SLOP)
+ {
+ factor2();
+ lastexp.offset = leftoffset << lastexp.offset;
+ }
+ else if (sym == SROP)
+ {
+ factor2();
+ lastexp.offset = leftoffset >> lastexp.offset;
+ }
+ else
+ return;
+ }
+}
+
+/* get symbol and 2nd or later factor, check both abs */
+
+PRIVATE void factor2()
+{
+ unsigned char leftdata;
+
+ leftdata = lastexp.data;
+ getsym();
+ factor();
+ lastexp.data |= leftdata;
+ chkabs();
+}
+
+/*
+ factor() parses factor = number | identifier | * | (expression) | ! factor,
+ ! is complementation. Returns value in lastexp.offset, possible flags
+ IMPBIT, FORBIT, RELBIT and UNDBIT in lastexp.data, and segment in SEGM
+ part of lastexp.data, and lastexp.sym at imported symbol if IMPBIT.
+ If the factor is an identifier, LOOKUP is used to get its value
+ (so the ident is installed in the symbol table if necessary, with
+ default flags inidata). If the identifier is not a label,
+ (could be imported, or later in the program), its FORBIT is set.
+ The expression FORBIT, IMPBIT, RELBIT, UNDBIT and SEGM are then
+ taken from the identifier.
+*/
+
+PUBLIC void factor()
+{
+ switch (sym)
+ {
+ case SLASH:
+ /* context-sensitive, SLASH means a hex number here */
+ context_hexconst();
+ case INTCONST:
+ lastexp.data = 0; /* absolute & not forward or undefined */
+ lastexp.offset = number;
+ getsym();
+ return;
+ case IDENT:
+ {
+ register struct sym_s *symptr;
+
+ symptr = gsymptr;
+ if (symptr->type & (MNREGBIT | MACBIT))
+ experror(symptr->type & MACBIT ? MACUID :
+ symptr->data & REGBIT ? REGUID : MNUID);
+ else
+ {
+ if (!(symptr->type & (LABIT | VARBIT)))
+ {
+ symptr->data |= FORBIT;
+ lastexp.sym = symptr;
+ }
+ if (pass == 0)
+ {
+ lastexp.data = symptr->data &
+ (FORBIT | RELBIT | UNDBIT | SEGM);
+ /* possible flags for pass 1 */
+ lastexp.offset = symptr->value_reg_or_op.value;
+ }
+ else
+ {
+ if ((lastexp.data = symptr->data) & IMPBIT)
+ lastexp.offset = 0; /* value != 0 for commons */
+ /* OK even if UNDBIT */
+ else
+ {
+ lastexp.offset = symptr->value_reg_or_op.value;
+ if (lastexp.data & UNDBIT)
+ experror(UNBLAB);
+ }
+ }
+ }
+ getsym();
+ return;
+ }
+ case LBRACKET:
+ if (!asld_compatible)
+ break; /* error, LPAREN is the grouping symbol */
+ getsym();
+ expres();
+ if (sym != RBRACKET)
+ error(RBEXP);
+ else
+ getsym();
+ return;
+ case LPAREN:
+ if (asld_compatible)
+ break; /* error, LBRACKET is the grouping symbol */
+ getsym();
+ expres();
+ if (sym != RPAREN)
+ error(RPEXP);
+ else
+ getsym();
+ return;
+ case NOTOP:
+ getsym();
+ factor();
+ chkabs();
+ lastexp.offset = ~lastexp.offset;
+ return;
+ case STAR:
+ /* context-sensitive, STAR means location counter here */
+ lastexp.offset = lc;
+ if ((lastexp.data = lcdata) & UNDBIT && pass != 0)
+ experror(UNBLAB);
+ getsym();
+ return;
+ }
+ experror(FACEXP);
+}
+
+/*
+ string compare for IFC/ELSEIFC
+ expects (<string1>,<string2>)
+ returns logical value in lastexp
+*/
+
+PUBLIC void scompare()
+{
+ /* prepare flags for OK, lastexp.offset for error */
+ lastexp.data = lastexp.offset = 0;
+ if (sym != LPAREN)
+ experror(LPEXP);
+ else
+ {
+ register char *string1;
+ register char *string2;
+
+ for (string2 = string1 = lineptr; *string2 != ')'; ++string2)
+ if (*string2 == 0 || *string2 == ')')
+ {
+ symname = string2;
+ experror(COMEXP);
+ return;
+ }
+ while (*string1++ == *string2++)
+ ;
+ if (string2[-1] == ')')
+ {
+ if (string1[-1] == ',')
+ lastexp.offset = TRUE; /* else leave FALSE */
+ }
+ else /* FALSE, keep reading to verify syntax */
+ for (; *string2 != ')'; ++string2)
+ if (*string2 == 0 || *string2 == ',')
+ {
+ symname = string2;
+ experror(RPEXP);
+ }
+ }
+}
diff --git a/bin86-0.3/as/file.h b/bin86-0.3/as/file.h
new file mode 100644
index 0000000..180b19b
--- /dev/null
+++ b/bin86-0.3/as/file.h
@@ -0,0 +1,18 @@
+/*
+ * bin86/as/file.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* file.h - global variables involving files for assembler */
+
+EXTERN fd_t binfil; /* binary output file (0 = memory) */
+EXTERN char *filnamptr; /* file name pointer */
+EXTERN fd_t infil0; /* initial input file */
+EXTERN fd_t infil; /* current input file (stacked, 0 = memory) */
+EXTERN unsigned char infiln; /* innum when file was opened */
+EXTERN unsigned char innum; /* counter for calls to opem */
+EXTERN fd_t lstfil; /* list output file (0 = standard) */
+EXTERN fd_t objfil; /* object output file */
+EXTERN fd_t symfil; /* symbol table output file */
+EXTERN char *truefilename; /* in case actual source name is a tmpname */
diff --git a/bin86-0.3/as/flag.h b/bin86-0.3/as/flag.h
new file mode 100644
index 0000000..21859cf
--- /dev/null
+++ b/bin86-0.3/as/flag.h
@@ -0,0 +1,11 @@
+/*
+ * bin86/as/flag.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* flag.h - global structured-flag variables for assembler */
+
+EXTERN struct flags_s list; /* listing on/off */
+EXTERN struct flags_s maclist; /* list macros on/off */
+EXTERN struct flags_s warn; /* warnings on/off */
diff --git a/bin86-0.3/as/genbin.c b/bin86-0.3/as/genbin.c
new file mode 100644
index 0000000..c215249
--- /dev/null
+++ b/bin86-0.3/as/genbin.c
@@ -0,0 +1,226 @@
+/*
+ * bin86/as/genbin.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* genbin.c - binary code generation routines for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "file.h"
+#include "globvar.h"
+
+PRIVATE char *asmbeg; /* beginning of assembler code */
+ /* for overwrite check */
+ /* bss-init to zero = NULL and not changed */
+PRIVATE offset_t binfbuf; /* binary code buffer for file (counter) */
+PRIVATE offset_t binmax; /* maximum value of binmbuf for pass 1 */
+PRIVATE offset_t binmin; /* minimum value of binmbuf for pass 1 */
+
+FORWARD void putbinoffset P((offset_t offset, count_t size));
+
+/* write header to binary file */
+
+PUBLIC void binheader()
+{
+ if ((innum = binfil) != 0x0)
+ {
+ writec(0x0); /* binary header byte */
+#ifdef LONG_BINHEADER
+ writeoff(binmax - binmin); /* program length */
+ writeoff(binfbuf = binmin); /* program start */
+#else
+ writew((unsigned) (binmax - binmin)); /* program length */
+ writew((unsigned) (binfbuf = binmin)); /* program start */
+#endif
+ }
+}
+
+/* write trailer to binary file */
+
+PUBLIC void bintrailer()
+{
+ if ((innum = binfil) != 0x0)
+ {
+ writec(0xFF); /* binary trailer byte */
+ writew(0x0); /* further trailer bytes */
+#ifdef LONG_BINHEADER
+ writeoff(pedata & UNDBIT ? binmin : progent); /* entry point */
+#else
+ writew(pedata & UNDBIT ? (unsigned) binmin : (unsigned) progent);
+#endif
+ }
+}
+
+/* generate binary code for current line */
+
+PUBLIC void genbin()
+{
+ struct address_s *adrptr;
+ char *bufptr;
+ unsigned char remaining;
+
+ if (binaryg && mcount != 0x0)
+ {
+ if (popflags)
+ {
+ if (fcflag)
+ {
+ bufptr = databuf.fcbuf;
+ remaining = mcount;
+ do
+ putbin(*bufptr++);
+ while (--remaining != 0x0);
+ }
+ if (fdflag)
+ {
+ adrptr = databuf.fdbuf;
+ remaining = mcount;
+ do
+ {
+ putbinoffset(adrptr->offset, 0x2);
+ ++adrptr;
+ }
+ while ((remaining -= 0x2) != 0x0);
+ }
+#if SIZEOF_OFFSET_T > 0x2
+ if (fqflag)
+ {
+ adrptr = databuf.fqbuf;
+ remaining = mcount;
+ do
+ {
+ putbinoffset(adrptr->offset, 0x4);
+ ++adrptr;
+ }
+ while ((remaining -= 0x4) != 0x0);
+ }
+#endif
+ }
+ else
+ {
+ remaining = mcount - 0x1; /* count opcode immediately */
+#ifdef I80386
+ if (aprefix != 0x0)
+ {
+ putbin(aprefix);
+ --remaining;
+ }
+ if (oprefix != 0x0)
+ {
+ putbin(oprefix);
+ --remaining;
+ }
+ if (sprefix != 0x0)
+ {
+ putbin(sprefix);
+ --remaining;
+ }
+#endif
+ if (page != 0x0)
+ {
+ putbin(page);
+ --remaining;
+ }
+ putbin(opcode);
+ if (remaining != 0x0)
+ {
+ if (postb != 0x0)
+ {
+ putbin(postb);
+ --remaining;
+ }
+#ifdef I80386
+ if (sib != NO_SIB)
+ {
+ putbin(sib);
+ --remaining;
+ }
+#endif
+ if (remaining != 0x0)
+ putbinoffset(lastexp.offset, remaining);
+ }
+#ifdef I80386
+ if (immcount != 0x0)
+ putbinoffset(immadr.offset, immcount);
+#endif
+ }
+ /* else no code for this instruction, or already generated */
+ }
+}
+
+/* initialise private variables */
+
+PUBLIC void initbin()
+{
+ binmin = -1; /* greater than anything */
+}
+
+/* write char to binary file or directly to memory */
+
+PUBLIC void putbin(c)
+opcode_pt c;
+{
+ if (binfil != 0x0)
+ {
+ if (!binaryc) /* pass 1, just record limits */
+ {
+ if (binmbuf < binmin)
+ binmin = binmbuf;
+ if (++binmbuf > binmax)
+ binmax = binmbuf;
+ }
+ else
+ {
+ if (binfbuf > binmbuf)
+ error(BWRAP); /* file buffer ahead of memory buffer */
+ else
+ {
+ innum = binfil;
+ while (binfbuf < binmbuf)
+ {
+ writec(0x0);/* pad with nulls if file buffer behind */
+ ++binfbuf;
+ }
+ writec(c);
+ binmbuf = ++binfbuf;
+ }
+ }
+ }
+ else if (binaryc && !(lcdata & UNDBIT))
+ /* memory output, and enabled */
+ {
+ register char *bufptr;
+
+ if ((bufptr = (char *) binmbuf) >= asmbeg && bufptr < heapptr)
+ error(OWRITE);
+ else
+ *bufptr = c;
+ ++binmbuf;
+ }
+}
+
+/* write sized offset to binary file or directly to memory */
+
+PRIVATE void putbinoffset(offset, size)
+offset_t offset;
+count_t size;
+{
+ char buf[sizeof offset];
+
+#if SIZEOF_OFFSET_T > 0x2
+ u4cn(buf, offset, size);
+#else
+ u2cn(buf, offset, size);
+#endif
+ putbin(buf[0]);
+ if (size > 0x1)
+ putbin(buf[1]);
+ if (size > 0x2)
+ {
+ putbin(buf[2]);
+ putbin(buf[3]);
+ }
+}
diff --git a/bin86-0.3/as/genlist.c b/bin86-0.3/as/genlist.c
new file mode 100644
index 0000000..6286d4b
--- /dev/null
+++ b/bin86-0.3/as/genlist.c
@@ -0,0 +1,454 @@
+/*
+ * bin86/as/genlist.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* genlist.c - generate listing and error reports for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+#include "macro.h"
+#include "scan.h"
+#include "source.h"
+
+#define CODE_LIST_LENGTH (sizeof (struct code_listing_s) - 1)
+ /* length of formatted code listing */
+#define MAXERR 6 /* maximum errors listed per line */
+
+struct error_s /* to record error info */
+{
+ unsigned char errnum;
+ unsigned char position;
+};
+
+/* code listing format */
+
+struct code_listing_s
+{
+ union linum_macro_u
+ {
+ char linum[LINUM_LEN];
+ struct
+ {
+ char pad[1];
+ char mark[1];
+ char level[1];
+ }
+ macro;
+ }
+ linum_or_macro;
+ char padlinum[1];
+ char lc[4];
+ char padlc[1];
+#ifdef I80386
+ char lprefix[2];
+ char aprefix[2];
+ char oprefix[2];
+ char sprefix[2];
+#endif
+ char page[2];
+ char opcode[2];
+ char postb[2];
+#ifdef I80386
+ char sib[2];
+#endif
+ char padopcode[1];
+#if SIZEOF_OFFSET_T > 2
+ char displ4[2];
+ char displ3[2];
+#endif
+ char displ2[2];
+ char displ1[2];
+ char reldispl[1];
+ char paddispl[1];
+#ifdef I80386
+ char imm4[2];
+ char imm3[2];
+ char imm2[2];
+ char imm1[2];
+ char relimm[1];
+ char padimm[1];
+#endif
+ char nullterm;
+};
+
+PRIVATE struct error_s errbuf[MAXERR]; /* error buffer */
+PRIVATE unsigned char errcount; /* # errors in line */
+PRIVATE bool_t erroverflow; /* set if too many errors on line */
+
+FORWARD char *build_1hex_number P((unsigned num, char *where));
+FORWARD void list1 P((fd_t fd));
+FORWARD void listcode P((void));
+FORWARD void listerrors P((void));
+FORWARD void paderrorline P((unsigned nspaces));
+
+/* format 1 byte number as 2 hex digits, return ptr to end */
+
+PRIVATE char *build_1hex_number(num, where)
+unsigned num;
+register char *where;
+{
+ static char hexdigits[] = "0123456789ABCDEF";
+
+ where[0] = hexdigits[(num % 256) / 16];
+ where[1] = hexdigits[num % 16];
+ return where + 2;
+}
+
+/* format 2 byte number as 4 hex digits, return ptr to end */
+
+PUBLIC char *build_2hex_number(num, where)
+unsigned num;
+char *where;
+{
+ return build_1hex_number(num, build_1hex_number(num / 256, where));
+}
+
+/* format 2 byte number as decimal with given width (pad with leading '0's) */
+/* return ptr to end */
+
+PUBLIC char *build_number(num, width, where)
+unsigned num;
+unsigned width;
+register char *where;
+{
+ static unsigned powers_of_10[] = {1, 10, 100, 1000, 10000,};
+ unsigned char digit;
+ unsigned char power;
+ register unsigned power_of_10;
+
+ power = 5; /* actually 1 more than power */
+ do
+ {
+ for (digit = '0', power_of_10 = (powers_of_10 - 1)[power];
+ num >= power_of_10; num -= power_of_10)
+ ++digit;
+ if (power <= width)
+ *where++ = digit;
+ }
+ while (--power != 0);
+ return where;
+}
+
+/* record number and position of error (or error buffer overflow) */
+
+PUBLIC void error(errnum)
+error_pt errnum;
+{
+ register struct error_s *errptr;
+ register struct error_s *errptrlow;
+ unsigned char position;
+
+ if (errnum < MINWARN || warn.current)
+ {
+ if (errcount >= MAXERR)
+ erroverflow = TRUE;
+ else
+ {
+ position = symname - linebuf;
+ for (errptr = errbuf + errcount;
+ errptr > errbuf && errptr->position > position;
+ errptr = errptrlow)
+ {
+ errptrlow = errptr - 1;
+ errptr->errnum = errptrlow->errnum;
+ errptr->position = errptrlow->position;
+ }
+ errptr->errnum = errnum;
+ errptr->position = position;
+ ++errcount;
+ if (errnum >= MINWARN)
+ ++totwarn;
+ else
+ ++toterr;
+ }
+ }
+}
+
+/* list 1 line to list file if any errors or flags permit */
+/* list line to console as well if any errors and list file is not console */
+
+PUBLIC void listline()
+{
+ if (!listpre)
+ {
+ if (errcount || list.current && (!macflag || mcount != 0) ||
+ macflag && maclist.current)
+ list1(lstfil);
+ if (errcount)
+ {
+ if (lstfil != STDOUT)
+ list1(STDOUT);
+ errcount = 0;
+ erroverflow = FALSE;
+ }
+ }
+}
+
+/* list 1 line unconditionally */
+
+PRIVATE void list1(fd)
+fd_t fd;
+{
+ innum = fd;
+ listcode();
+ write(innum, linebuf, lineptr - linebuf);
+ writenl();
+ if (errcount != 0)
+ listerrors();
+ listpre = TRUE;
+}
+
+/* list object code for 1 line */
+
+PRIVATE void listcode()
+{
+ unsigned char count;
+ struct code_listing_s *listptr;
+ int numlength;
+ char *numptr;
+
+ listptr = (struct code_listing_s *) heapptr;
+ memset((char *) listptr, ' ', sizeof *listptr);
+ listptr->nullterm = 0;
+ if (macflag)
+ {
+ listptr->linum_or_macro.macro.mark[0] = '+';
+ listptr->linum_or_macro.macro.level[0] = maclevel + ('a' - 1);
+ }
+ else
+ {
+ numlength = LINUM_LEN;
+ numptr = listptr->linum_or_macro.linum;
+ if (infiln != infil0)
+ {
+ *numptr++ = infiln - infil0 + ('a' - 1);
+ numlength = LINUM_LEN - 1;
+ }
+ build_number(linum, numlength, numptr);
+ }
+ if ((count = mcount) != 0 || popflags & POPLC)
+ build_2hex_number((u16_t) lc, listptr->lc);
+ if (popflags & POPLO)
+ {
+#if SIZEOF_OFFSET_T > 2
+ if (popflags & POPLONG)
+ build_2hex_number((u16_t) (lastexp.offset / (offset_t) 0x10000L),
+ listptr->displ4);
+#endif
+ if (popflags & POPHI)
+ build_2hex_number((u16_t) lastexp.offset, listptr->displ2);
+ else
+ build_1hex_number((u16_t) lastexp.offset, listptr->displ1);
+ if (lastexp.data & RELBIT)
+ listptr->reldispl[0] = '>';
+ }
+ else if (count != 0)
+ {
+#ifdef I80386
+ if (aprefix != 0)
+ {
+ --count;
+ build_1hex_number(aprefix, listptr->aprefix);
+ }
+ if (oprefix != 0)
+ {
+ --count;
+ build_1hex_number(oprefix, listptr->oprefix);
+ }
+ if (sprefix != 0)
+ {
+ --count;
+ build_1hex_number(sprefix, listptr->sprefix);
+ }
+#endif
+ if (page != 0)
+ {
+ build_1hex_number(page, listptr->page);
+ --count;
+ }
+ build_1hex_number(opcode, listptr->opcode);
+ --count;
+ if (postb != 0)
+ {
+ --count;
+ build_1hex_number(postb,
+#ifdef MC6809
+ count == 0 ? listptr->displ1 :
+#endif
+ listptr->postb);
+ }
+#ifdef I80386
+ if (sib != NO_SIB)
+ {
+ --count;
+ build_1hex_number(sib, listptr->sib);
+ }
+#endif
+ if (count > 0)
+ {
+ build_1hex_number((opcode_pt) lastexp.offset, listptr->displ1);
+ if (lastexp.data & RELBIT)
+ listptr->reldispl[0] = '>';
+ }
+ if (count > 1)
+ build_1hex_number((opcode_pt) lastexp.offset >> 0x8,
+ listptr->displ2);
+#if SIZEOF_OFFSET_T > 2
+ if (count > 2)
+ {
+ build_1hex_number((opcode_pt) (lastexp.offset >> 0x10),
+ listptr->displ3);
+ build_1hex_number((opcode_pt) (lastexp.offset >> 0x18),
+ listptr->displ4);
+ }
+#endif
+#ifdef I80386
+ if (immcount > 0)
+ {
+ build_1hex_number((opcode_pt) immadr.offset, listptr->imm1);
+ if (immadr.data & RELBIT)
+ listptr->relimm[0] = '>';
+ }
+ if (immcount > 1)
+ build_1hex_number((opcode_pt) immadr.offset >> 0x8,
+ listptr->imm2);
+ if (immcount > 2)
+ {
+ build_1hex_number((opcode_pt) (immadr.offset >> 0x10),
+ listptr->imm3);
+ build_1hex_number((opcode_pt) (immadr.offset >> 0x18),
+ listptr->imm4);
+ }
+#endif
+ }
+ writes((char *) listptr);
+}
+
+/* list errors, assuming some */
+
+PRIVATE void listerrors()
+{
+ unsigned char column;
+ unsigned char errcol; /* column # in error line */
+ unsigned char errcolw; /* working column in error line */
+ char *errmsg;
+ struct error_s *errptr;
+ char *linep;
+ unsigned char remaining;
+
+ paderrorline(CODE_LIST_LENGTH - LINUM_LEN);
+ remaining = errcount;
+ column = 0; /* column to match with error column */
+ errcolw = errcol = CODE_LIST_LENGTH; /* working & col number on err line */
+ errptr = errbuf;
+ linep = linebuf;
+ do
+ {
+ while (column < errptr->position)
+ {
+ ++column;
+ if (*linep++ == '\t') /* next tab (standard tabs only) */
+ errcolw = (errcolw + 8) & 0xf8;
+ else
+ ++errcolw;
+ while (errcolw > errcol)
+ {
+ writec(' ');
+ ++errcol;
+ }
+ }
+ if (errcolw < errcol) /* position under error on new line */
+ {
+ writenl();
+ paderrorline(errcolw - LINUM_LEN);
+ }
+ writec('^');
+ writes(errmsg = build_error_message(errptr->errnum, heapptr));
+ errcol += strlen(errmsg);
+ ++errptr;
+ }
+ while (--remaining != 0);
+ writenl();
+ if (erroverflow)
+ {
+ paderrorline(CODE_LIST_LENGTH - LINUM_LEN);
+ writesn(build_error_message(FURTHER, heapptr));
+ }
+}
+
+/* pad out error line to begin under 1st char of source listing */
+
+PRIVATE void paderrorline(nspaces)
+unsigned nspaces;
+{
+ int nstars = LINUM_LEN;
+
+ while (nstars-- != 0)
+ writec('*'); /* stars under line number */
+ while (nspaces-- != 0)
+ writec(' '); /* spaces out to error position */
+}
+
+/* write 1 character */
+
+PUBLIC void writec(c)
+char c;
+{
+ write(innum, &c, 1);
+}
+
+/* write newline */
+
+PUBLIC void writenl()
+{
+ writes(SOS_EOLSTR);
+}
+
+/* write 1 offset_t, order to suit target */
+
+PUBLIC void writeoff(offset)
+offset_t offset;
+{
+ char buf[sizeof offset];
+
+#if SIZEOF_OFFSET_T > 2
+ u4c4(buf, offset);
+#else
+ u2c2(buf, offset);
+#endif
+ write(innum, buf, sizeof buf);
+}
+
+/* write string */
+
+PUBLIC void writes(s)
+char *s;
+{
+ write(innum, s, strlen(s));
+}
+
+/* write string followed by newline */
+
+PUBLIC void writesn(s)
+char *s;
+{
+ writes(s);
+ writenl();
+}
+
+/* write 1 word, order to suit target */
+
+PUBLIC void writew(word)
+unsigned word;
+{
+ char buf[2];
+
+ u2c2(buf, (u16_t) word);
+ write(innum, buf, sizeof buf);
+}
diff --git a/bin86-0.3/as/genobj.c b/bin86-0.3/as/genobj.c
new file mode 100644
index 0000000..fc42394
--- /dev/null
+++ b/bin86-0.3/as/genobj.c
@@ -0,0 +1,669 @@
+/*
+ * bin86/as/genobj.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* genobj.c - object code generation routines for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "file.h"
+#include "globvar.h"
+
+#define OBJBUFSIZE 512 /* size of object code output buffer */
+#define isge2byteoffset(offset) ((offset) >= 0x100)
+#define isge4byteoffset(offset) ((offset) >= 0x10000L)
+
+PRIVATE char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */
+PRIVATE char *absbuf; /* start */
+PRIVATE char *absbufend; /* last location + 1 */
+PRIVATE char *absbufptr; /* current location */
+PRIVATE struct sym_s **arrext; /* array of external symbol ptrs */
+PRIVATE char hid_objbuf[OBJBUFSIZE]; /* object code buffer */
+PRIVATE unsigned numext; /* number of external symbols */
+PRIVATE char *objbuf; /* start */
+PRIVATE char *objbufend; /* last location + 1 */
+PRIVATE char *objbufptr; /* current location */
+PRIVATE unsigned char relsize; /* current relocation size, 0 init */
+ /* local to genobjadr, but here */
+ /* because of static re-init bug */
+PRIVATE offset_t rmbcount; /* accumulator for repeated RMB's */
+
+FORWARD void flushabs P((void));
+FORWARD void flushrmb P((void));
+FORWARD void genobjadr P((struct address_s *adrptr, int size));
+FORWARD void putobj1 P((opcode_pt c));
+FORWARD void putobj4 P((u32_t offset));
+FORWARD void putobjoffset P((offset_t offset, count_t size));
+FORWARD void putobjword P((unsigned word));
+FORWARD void writeobj P((char *buf, unsigned count));
+
+/* accumulate RMB requests into 1 (so + and - requests cancel) */
+
+PUBLIC void accumulate_rmb(offset)
+offset_t offset;
+{
+ if (objectc)
+ {
+ flushabs();
+ rmbcount += offset;
+ }
+}
+
+/* flush absolute object code buffer to object code buffer if necessary */
+
+PRIVATE void flushabs()
+{
+ if (absbufptr > absbuf)
+ {
+ putobj1((absbufptr - absbuf) | OBJ_ABS);
+ {
+ register char *bufptr;
+
+ bufptr = absbuf;
+ do
+ putobj1(*bufptr);
+ while (++bufptr < absbufptr);
+ absbufptr = absbuf;
+ }
+ }
+}
+
+/* flush object code buffer if necessary */
+
+PUBLIC void flushobj()
+{
+ int ntowrite;
+
+ if ((ntowrite = objbufptr - objbuf) > 0)
+ {
+ if (write(objfil, objbuf, ntowrite) != ntowrite)
+ {
+ error(OBJOUT);
+ listline();
+ finishup();
+ }
+ objbufptr = objbuf;
+ }
+}
+
+/* flush RMB count if necessary */
+
+PRIVATE void flushrmb()
+{
+ count_t size;
+
+ if (rmbcount != 0)
+ {
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(rmbcount))
+ {
+ putobj1(OBJ_SKIP_4);
+ size = 4;
+ }
+ else
+#endif
+ if (isge2byteoffset(rmbcount))
+ {
+ putobj1(OBJ_SKIP_2);
+ size = 2;
+ }
+ else
+ {
+ putobj1(OBJ_SKIP_1);
+ size = 1;
+ }
+ putobjoffset(rmbcount, size);
+ rmbcount = 0;
+ }
+}
+
+/* generate object code for current line */
+
+/*
+ any address parameter is (regrettably) in lastexp
+ any immediate parameter is (corectly) in immadr
+*/
+
+PUBLIC void genobj()
+{
+ struct address_s *adrptr;
+ char *bufptr;
+ unsigned char remaining;
+
+ if (objectc && mcount != 0)
+ {
+ if (popflags)
+ {
+ if (fcflag)
+ {
+ bufptr = databuf.fcbuf;
+ remaining = mcount;
+ do
+ putabs(*bufptr++);
+ while (--remaining != 0);
+ }
+ if (fdflag)
+ {
+ adrptr = databuf.fdbuf;
+ remaining = mcount;
+ do
+ genobjadr(adrptr++, 2);
+ while ((remaining -= 2) != 0);
+ }
+#if SIZEOF_OFFSET_T > 2
+ if (fqflag)
+ {
+ adrptr = databuf.fqbuf;
+ remaining = mcount;
+ do
+ genobjadr(adrptr++, 4);
+ while ((remaining -= 4) != 0);
+ }
+#endif
+ }
+ else
+ {
+ remaining = mcount - 1; /* count opcode immediately */
+#ifdef I80386
+ if (aprefix != 0)
+ {
+ putabs(aprefix);
+ --remaining;
+ }
+ if (oprefix != 0)
+ {
+ putabs(oprefix);
+ --remaining;
+ }
+ if (sprefix != 0)
+ {
+ putabs(sprefix);
+ --remaining;
+ }
+#endif
+ if (page != 0)
+ {
+ putabs(page);
+ --remaining;
+ }
+ putabs(opcode);
+ if (remaining != 0)
+ {
+ if (postb != 0)
+ {
+ putabs(postb);
+ --remaining;
+ }
+#ifdef I80386
+ if (sib != NO_SIB)
+ {
+ putabs(sib);
+ --remaining;
+ }
+#endif
+ if (remaining != 0)
+ genobjadr(&lastexp, remaining);
+ }
+ }
+#ifdef I80386
+ if (immcount != 0)
+ genobjadr(&immadr, immcount);
+#endif
+ }
+}
+
+/* generate object code for current address */
+
+PRIVATE void genobjadr(adrptr, size)
+struct address_s *adrptr;
+smallcount_t size;
+{
+ unsigned char byte;
+ unsigned symnum;
+
+ if (!(adrptr->data & RELBIT))
+ {
+ /* absolute address */
+
+ char buf[sizeof(offset_t)];
+
+#if SIZEOF_OFFSET_T > 2
+ u4cn(buf, adrptr->offset, size);
+#else
+ u2cn(buf, adrptr->offset, size);
+#endif
+ putabs(buf[0]);
+ if (size > 1)
+ putabs(buf[1]);
+ if (size > 2)
+ {
+ putabs(buf[2]);
+ putabs(buf[3]);
+ }
+ }
+ else
+ {
+ /* relocatable address */
+ if (size != relsize)
+ /* set reloc size index |00|0000xx| */
+ putobj((relsize = size) == 4 ? 0x03 : relsize);
+ if (!(adrptr->data & IMPBIT))
+ {
+ /* offset relocation (known offset) */
+ putobj((adrptr->data & SEGM) | OBJ_OFFSET_REL | pcrflag);
+ putobjoffset(adrptr->offset, size);
+ }
+ else
+ {
+ /* symbol relocation (imported symbol + offset) */
+ {
+ register struct sym_s **copyptr;
+
+ for (copyptr = arrext, symnum = 0;
+ symnum < numext && *copyptr++ != adrptr->sym; ++symnum)
+ ;
+ }
+ byte = OBJ_SYMBOL_REL;
+ if (isge2byteoffset(symnum))
+ byte = OBJ_SYMBOL_REL | OBJ_S_MASK;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(adrptr->offset))
+ {
+ byte |= 0x03; /* 4 byte offset */
+ size = 4;
+ }
+ else
+#endif
+ if (isge2byteoffset(adrptr->offset))
+ {
+ byte |= 0x02; /* 2 byte offset */
+ size = 2;
+ }
+ else if (adrptr->offset != 0)
+ {
+ byte |= 0x01; /* 1 byte offset */
+ size = 1;
+ }
+ else
+ size = 0;
+ putobj(byte | pcrflag);
+ if (isge2byteoffset(symnum))
+ putobjword(symnum);
+ else
+ putobj1(symnum);
+ if (adrptr->offset != 0)
+ putobjoffset(adrptr->offset, size);
+ }
+ }
+}
+
+/* initialise private variables */
+
+PUBLIC void initobj()
+{
+ absbufend = (absbufptr = absbuf = hid_absbuf) + sizeof hid_absbuf;
+ objbufend = (objbufptr = objbuf = hid_objbuf) + sizeof hid_objbuf;
+}
+
+/*
+ write header to object file
+ also build array of imported/exported symbols
+*/
+
+PUBLIC void objheader()
+{
+ static char module_header[] =
+ {
+#ifdef I80386
+ 0xA3, 0x86,
+ 1, 0,
+ (char) (0xA3 + 0x86 + 1 + 0),
+#endif
+#ifdef MC6809
+ 'S', '1', /* 2 byte magic number */
+ 0, 1, /* 2 byte number of modules in file */
+ 'S' + '1' + 0 + 1, /* 1 byte checksum */
+#endif
+ };
+ static char seg_max_sizes[] =
+ {
+ 0x55, /* all segments have maximum size 2^16 */
+ 0x55, /* this is encoded by 0b01 4 times per byte */
+ 0x55, /* other codes are 0b00 = max size 2^8 */
+ 0x55, /* 0b10 = max size 2^24, 0b11 = max 2^32 */
+ };
+ unsigned char byte;
+ register struct sym_s **copyptr;
+ struct sym_s **copytop;
+ struct sym_s **hashptr;
+ struct lc_s *lcp;
+ char module_name[FILNAMLEN + 1];
+ char *nameptr;
+ unsigned offset;
+ unsigned segsizebytes;
+ unsigned size;
+ unsigned char sizebits;
+ unsigned strsiz; /* size of object string table */
+ unsigned symosiz; /* size of object symbol table */
+ register struct sym_s *symptr;
+ u32_t textlength;
+
+ if ((objectc = objectg) == 0)
+ return;
+ writeobj(module_header, sizeof module_header);
+
+ /* calculate number of imported/exported symbols */
+ /* and lengths of symbol and string tables */
+ /* build array of imported/exported symbols */
+
+ symosiz = 0;
+ if (truefilename == NULL)
+ truefilename = filnamptr;
+ nameptr = strrchr(truefilename, DIRCHAR);
+ strcpy(module_name, nameptr != NULL ? nameptr + 1 : truefilename);
+ if ((nameptr = strrchr(module_name, '.')) != NULL)
+ *nameptr = 0;
+ strsiz = strlen(module_name) + 1;
+ align(heapptr);
+ for (hashptr = spt, arrext = copyptr = (struct sym_s **) heapptr;
+ hashptr < spt_top;)
+ if ((symptr = *hashptr++) != NULL)
+ do
+ {
+ if ((symptr->type & EXPBIT || symptr->data & IMPBIT) ||
+ !globals_only_in_obj && symptr->name[0] != '.' &&
+ !(symptr->type & (MNREGBIT | MACBIT | VARBIT)))
+ {
+ if (copyptr >= (struct sym_s **) heapend)
+ {
+ heapptr = (char *) copyptr;
+ fatalerror(OBJSYMOV);
+ }
+ *copyptr++ = symptr;
+ strsiz += symptr->length + 1;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(symptr->value_reg_or_op.value))
+ size = 4 + 4;
+ /* 4 is size of offset into string table and flags */
+ /* 2nd 4 is for 4 byte offset */
+ else
+#endif
+ if (isge2byteoffset(symptr->value_reg_or_op.value))
+ size = 4 + 2;
+ else if (symptr->value_reg_or_op.value != 0)
+ size = 4 + 1;
+ else
+ size = 4;
+ symosiz += size;
+ ++numext;
+ }
+ }
+ while ((symptr = symptr->next) != NULL);
+ heapptr = (char *) (copytop = copyptr);
+
+ /* calculate length of text, and number of seg size bytes in header */
+
+ textlength = segsizebytes = 0;
+ lcp = lctab;
+ do
+ if (lcp->lc != 0)
+ {
+ textlength += lcp->lc; /* assuming text starts at 0 */
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(lcp->lc))
+ segsizebytes += 4;
+ else
+#endif
+ segsizebytes += 2; /* use 2 byte size if possible */
+ }
+ while (++lcp < lctabtop);
+
+/*
+ offset to text = length of header since only 1 module
+ header consists of:
+ module header sizeof module_header
+ offset to start of text 4
+ length of text 4
+ length of string area 2
+ class 1
+ revision 1
+ seg max sizes sizeof seg_max_sizes
+ seg size descriptors 4
+ seg sizes segsizebytes
+ symbol count 2
+ symbol offsets and types symosiz
+ strings strsiz
+*/
+
+ /* offset to start of text */
+
+ putobj4((u32_t) (sizeof module_header + 4 + 4 + 2 + 1 + 1 +
+ sizeof seg_max_sizes + 4 + segsizebytes + 2 +
+ symosiz) + strsiz);
+
+ /* length of text */
+
+ putobj4((u32_t) textlength);
+
+ /* length of string area */
+
+ putobjword(strsiz);
+
+ /* class and revision */
+
+ putobj1(0);
+ putobj1(0);
+
+ /* segment max sizes (constant) */
+
+ writeobj(seg_max_sizes, sizeof seg_max_sizes);
+
+ /* segment size descriptors */
+ /* produce only 0 and 2 byte sizes */
+
+ lcp = lctabtop;
+ byte = 0;
+ sizebits = OBJ_SEGSZ_TWO << 6;
+ do
+ {
+ --lcp;
+ if (lcp->lc != 0)
+ {
+ byte |= sizebits;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(lcp->lc))
+ byte |= sizebits >> 1; /* XXX - convert size 2 to size 4 */
+#endif
+ }
+ if ((sizebits >>= 2) == 0)
+ {
+ putobj1(byte);
+ sizebits = OBJ_SEGSZ_TWO << 6;
+ }
+ }
+ while (lcp > lctab);
+
+ /* segment sizes */
+
+ do /* lcp starts at lctab */
+ if (lcp->lc != 0)
+ {
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(lcp->lc))
+ putobj4(lcp->lc);
+ else
+#endif
+ putobjword((unsigned) lcp->lc);
+ }
+ while (++lcp < lctabtop);
+
+ /* symbol count */
+
+ putobjword(numext);
+
+ /* symbol offsets and types */
+
+ offset = strlen(module_name) + 1; /* 1st symbol begins after name */
+ for (copyptr = arrext; copyptr < copytop;)
+ {
+ putobjword(offset);
+ symptr = *copyptr++;
+ byte = symptr->type & OBJ_N_MASK;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(symptr->value_reg_or_op.value))
+ {
+ byte |= OBJ_SZ_FOUR;
+ size = 4;
+ }
+ else
+#endif
+ if (isge2byteoffset(symptr->value_reg_or_op.value))
+ {
+ byte |= OBJ_SZ_TWO;
+ size = 2;
+ }
+ else if (symptr->value_reg_or_op.value != 0)
+ {
+ byte |= OBJ_SZ_ONE;
+ size = 1;
+ }
+ else
+ size = 0;
+ if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
+ {
+ byte |= OBJ_SA_MASK;
+ symptr->data &= ~OBJ_I_MASK;
+ }
+ putobjword((byte << 0x8) |
+ (symptr->type & OBJ_E_MASK) | /* |E|0000000| */
+ ((symptr->data & (OBJ_I_MASK | OBJ_A_MASK | OBJ_SEGM_MASK)) ^
+ /* |0|I|0|A|SEGM| */
+ RELBIT)); /* RELBIT by negative logic */
+ if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
+ symptr->data |= OBJ_I_MASK;
+ if (size != 0)
+ putobjoffset(symptr->value_reg_or_op.value, size);
+ offset += symptr->length + 1;
+ }
+
+ /* strings */
+
+ writeobj(module_name, strlen(module_name));
+ putobj1(0);
+ for (copyptr = arrext; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writeobj(symptr->name, symptr->length);
+ putobj1(0);
+ }
+ putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */
+}
+
+/* write trailer to object file */
+
+PUBLIC void objtrailer()
+{
+ if (objectc)
+ {
+ putobj(0); /* end of object file */
+ flushobj();
+ }
+}
+
+/* write char to absolute object code buffer, flush if necessary */
+
+PUBLIC void putabs(c)
+opcode_pt c;
+{
+ if (objectc)
+ {
+ if (rmbcount != 0)
+ flushrmb();
+ if (absbufptr >= absbufend)
+ flushabs();
+ *absbufptr++ = c;
+ }
+}
+
+/* write char to object code buffer, flush if necessary */
+
+PUBLIC void putobj(c)
+opcode_pt c;
+{
+ if (objectc)
+ {
+ flushabs();
+ flushrmb();
+ putobj1(c);
+ }
+}
+
+/* write char to object code buffer assuming nothing in absolute & rmb bufs */
+
+PRIVATE void putobj1(c)
+opcode_pt c;
+{
+ if (objbufptr >= objbufend)
+ flushobj();
+ *objbufptr++ = c;
+}
+
+/* write 32 bit offset to object code buffer assuming ... */
+
+PRIVATE void putobj4(offset)
+u32_t offset;
+{
+ char buf[sizeof offset];
+
+ u4c4(buf, offset);
+ writeobj(buf, sizeof buf);
+}
+
+/* write sized offset to object code buffer assuming ... */
+
+PRIVATE void putobjoffset(offset, size)
+offset_t offset;
+count_t size;
+{
+ char buf[sizeof offset];
+
+#if SIZEOF_OFFSET_T > 2
+ u4cn(buf, offset, size);
+#else
+ u2cn(buf, offset, size);
+#endif
+ putobj1(buf[0]);
+ if (size > 1)
+ putobj1(buf[1]);
+ if (size > 2)
+ {
+ putobj1(buf[2]);
+ putobj1(buf[3]);
+ }
+}
+
+/* write word to object code buffer assuming ... */
+
+PRIVATE void putobjword(word)
+unsigned word;
+{
+ char buf[sizeof word];
+
+ u2c2(buf, word);
+ putobj1(buf[0]);
+ putobj1(buf[1]);
+}
+
+/* write several bytes to object code buffer assuming ... */
+
+PRIVATE void writeobj(buf, count)
+char *buf;
+unsigned count;
+{
+ do
+ putobj1(*buf++);
+ while (--count);
+}
diff --git a/bin86-0.3/as/gensym.c b/bin86-0.3/as/gensym.c
new file mode 100644
index 0000000..e06d3ce
--- /dev/null
+++ b/bin86-0.3/as/gensym.c
@@ -0,0 +1,202 @@
+/*
+ * bin86/as/gensym.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* gensym.c - generate symbol table for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+
+FORWARD int printsym P((register struct sym_s *symptr, unsigned column));
+FORWARD void sort P((struct sym_s **array, struct sym_s **top,
+ bool_pt nameflag));
+
+/* sort labels in symbol table on name and value */
+/* if listing, write human-readable table to list file */
+/* if symbol file, write machine-readable tables to it */
+/* pointers become relative to start of file */
+
+PUBLIC void gensym()
+{
+ unsigned column;
+ struct sym_s **copyptr;
+ struct sym_s **copytop;
+ register struct sym_s **hashptr;
+ unsigned label_count; /* number of labels */
+ unsigned labels_length; /* length of all label strings */
+ unsigned label_stringptr; /* offset of label str from start of file */
+ register struct sym_s *symptr;
+ struct sym_s **symlptr; /* start of symbol output list */
+
+ labels_length = label_count = 0;
+
+ /* make copy of all relavant symbol ptrs on heap */
+ /* original ptrs can now be modified, but need to be an array for sort */
+
+ align(heapptr);
+ for (hashptr = spt, symlptr = copyptr = (struct sym_s **) heapptr;
+ hashptr < spt_top;)
+ if ((symptr = *hashptr++) != NULL)
+ do
+ if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT)))
+ {
+ if (copyptr >= (struct sym_s **) heapend)
+ {
+ heapptr = (char *) copyptr;
+ error(SYMOUTOV); /* avoid recursive fatalerror */
+ listline(); /* the main job is OK if here */
+ goto sort_symbols;
+ }
+ *copyptr++ = symptr;
+ ++label_count;
+ labels_length += symptr->length + 3; /* 3 for type, value */
+ }
+ while ((symptr = symptr->next) != NULL);
+
+sort_symbols:
+ sort(symlptr, copyptr, TRUE); /* sort on name */
+ heapptr = (char *) (copytop = copyptr);
+ if (list.global)
+ {
+ innum = lstfil;
+ writenl();
+ writesn("Symbols:");
+ for (copyptr = symlptr, column = 0; copyptr < copytop;)
+ column = printsym(*copyptr++, column);
+ if (column != 0)
+ writenl();
+ }
+ if ((innum = symfil) != 0)
+ {
+ writew(mapnum);
+ label_count *= 2; /* now length of ptr table (2 bytes per ptr) */
+ label_stringptr = label_count + 6;
+ /* offset to current string in symbol file */
+ /* 6 is length of header */
+ labels_length += label_stringptr;
+ /* offset to ptr table sorted on value */
+ writew(labels_length + label_count);
+ /* total length of symbol file */
+ writew(label_count);
+ for (copyptr = symlptr; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writew((unsigned)
+ (symptr->next = (struct sym_s *) label_stringptr));
+ /* reuse "next" to record string position */
+ label_stringptr += symptr->length + 3;
+ }
+ for (copyptr = symlptr; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writew((unsigned) symptr->value_reg_or_op.value);
+ writec(symptr->type);
+ write(innum, symptr->name, symptr->length - 1);
+ writec(symptr->name[symptr->length - 1] | 0x80);
+ }
+ sort(symlptr, copyptr, FALSE);
+ /* sort on value */
+ for (copyptr = symlptr; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writew((unsigned) symptr->next); /* now has string position */
+ }
+ }
+}
+
+/* print symbol nicely formatted for given column */
+
+PRIVATE int printsym(symptr, column)
+register struct sym_s *symptr;
+unsigned column;
+{
+ unsigned char length;
+ register struct sym_listing_s *listptr;
+ char *outname;
+ char *symname;
+
+ listptr = (struct sym_listing_s *) heapptr;
+ memset((char *) listptr, ' ', SYMLIS_LEN);
+ listptr->nullterm = 0;
+ if ((length = symptr->length) > SYMLIS_NAMELEN)
+ {
+ outname = listptr->name;
+ outname[length = SYMLIS_NAMELEN] = '+';
+ }
+ else
+ outname = (listptr->name + SYMLIS_NAMELEN) - length;
+ symname = symptr->name;
+ do
+ *outname++ = *symname++;
+ while (--length != 0);
+ listptr->ar[0] = symptr->data & RELBIT ? 'R' : 'A';
+ listptr->segm[0] = (symptr->data & SEGM) + '0';
+ if (symptr->type & COMMBIT)
+ listptr->cein[0] = 'C';
+ else if (symptr->type & ENTBIT)
+ listptr->cein[0] = 'N';
+ else if (symptr->type & EXPBIT)
+ listptr->cein[0] = 'E';
+ else if (symptr->data & IMPBIT)
+ listptr->cein[0] = 'I';
+#if SIZEOF_OFFSET_T > 2
+ build_2hex_number((unsigned) (symptr->value_reg_or_op.value >> 16),
+ listptr->value);
+#endif
+ build_2hex_number((unsigned) symptr->value_reg_or_op.value,
+ listptr->value);
+ writes((char *) listptr);
+ if ((column += SYMLIS_LEN) > (80 - SYMLIS_LEN))
+ {
+ writenl();
+ column = 0;
+ }
+ return column;
+}
+
+/* shell sort symbols */
+
+PRIVATE void sort(array, top, nameflag)
+struct sym_s **array;
+struct sym_s **top;
+bool_pt nameflag;
+{
+ int gap;
+ int i;
+ int j;
+ register struct sym_s **left;
+ register struct sym_s **right;
+ int size;
+ struct sym_s *swap;
+
+ size = top - array;
+ /* choose gaps according to Knuth V3 p95 */
+ for (gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j)
+ ;
+ do
+ {
+ for (j = gap; j < size; ++j)
+ for (i = j - gap; i >= 0; i -= gap)
+ {
+ left = &array[i];
+ right = &array[i + gap];
+ if ((bool_t) nameflag)
+ {
+ if (strcmp((*left)->name, (*right)->name) <= 0)
+ break;
+ }
+ else if ((unsigned) (*left)->value_reg_or_op.value <=
+ (*right)->value_reg_or_op.value)
+ break;
+ swap = *left;
+ *left = *right;
+ *right = swap;
+ }
+ }
+ while ((gap /= 3) != 0);
+}
diff --git a/bin86-0.3/as/globvar.h b/bin86-0.3/as/globvar.h
new file mode 100644
index 0000000..e560abc
--- /dev/null
+++ b/bin86-0.3/as/globvar.h
@@ -0,0 +1,95 @@
+/*
+ * bin86/as/globvar.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* globvar.h - global variables for assembler */
+
+/* global control and bookkeeping */
+
+EXTERN bool_t binaryc; /* current binary code flag */
+EXTERN bool_t binaryg; /* global binary code flag */
+EXTERN offset_t binmbuf; /* offset in binary code buffer for memory */
+
+EXTERN unsigned char dirpag; /* direct page */
+
+EXTERN bool_t globals_only_in_obj; /* global symbols only in object file */
+
+EXTERN bool_t jumps_long; /* make all jumps long */
+
+EXTERN unsigned char mapnum; /* global map number */
+
+EXTERN bool_t objectc; /* current object code flag */
+EXTERN bool_t objectg; /* global object code flag */
+
+EXTERN bool_t pass; /* pass, FALSE means 0, TRUE means 1 */
+
+EXTERN offset_t progent; /* program entry point */
+
+EXTERN bool_t symgen; /* generate symbol table flag */
+
+EXTERN unsigned toterr; /* total errors */
+EXTERN unsigned totwarn; /* total warnings */
+
+/* bookeeping for current line */
+
+EXTERN char *linebuf; /* buffer */
+
+/* for symbol table routines */
+
+EXTERN char *heapend; /* end of free space for symbol list */
+EXTERN char *heapptr; /* next free space in symbol list */
+EXTERN unsigned char inidata; /* init sym entry data governed by "u" flag */
+EXTERN struct sym_s **spt; /* symbol pointer table */
+EXTERN struct sym_s **spt_top; /* top of symbol ptr table */
+
+/* for translator */
+
+EXTERN struct sym_s *label; /* non-null if valid label starts line */
+EXTERN unsigned char pedata; /* shows how PROGENT bound, flags like LCDATA*/
+EXTERN unsigned char popflags; /* pseudo-op flags */
+
+/* for BLOCK stack */
+
+EXTERN struct block_s *blockstak; /* stack ptr */
+EXTERN unsigned char blocklevel; /* nesting level */
+
+/* for IF stack */
+
+EXTERN struct if_s *ifstak; /* stack ptr */
+EXTERN unsigned char iflevel; /* nesting level */
+EXTERN bool_t ifflag; /* set if assembling */
+
+/* location counters for various segments */
+
+EXTERN offset_t lc; /* location counter */
+EXTERN unsigned char lcdata; /* shows how lc is bound */
+ /* FORBIT is set if lc is forward referenced */
+ /* RELBIT is is if lc is relocat. (not ASEG) */
+EXTERN offset_t lcjump; /* lc jump between lines */
+#define mcount (((unsigned char *) &lcjump)[LOW_BYTE])
+ /* low byte of lcjump */
+EXTERN struct lc_s *lcptr; /* top of current spot in lctab */
+EXTERN struct lc_s *lctab; /* start of lctab */
+EXTERN struct lc_s *lctabtop; /* top of lctab */
+
+/* for code generator */
+
+EXTERN opsize_t mnsize; /* 1 if forced byte operand size, else 0 */
+EXTERN opcode_t page;
+EXTERN opcode_t opcode;
+EXTERN opcode_t postb; /* postbyte, 0 if none */
+EXTERN unsigned char pcrflag; /* OBJ_RMASK set if addressing is PC-relative */
+
+#ifdef I80386
+
+EXTERN opcode_t aprefix; /* address size prefix or 0 */
+EXTERN bool_t asld_compatible; /* asld compatibility flag */
+EXTERN opsize_t defsize; /* current default size */
+EXTERN opsize_t idefsize; /* initial default size */
+EXTERN opcode_t oprefix; /* operand size prefix or 0 */
+EXTERN opcode_t sprefix; /* segment prefix or 0 */
+EXTERN opcode_t sib; /* scale-index-base byte */
+
+#endif
diff --git a/bin86-0.3/as/keywords.c b/bin86-0.3/as/keywords.c
new file mode 100644
index 0000000..5d0bf84
--- /dev/null
+++ b/bin86-0.3/as/keywords.c
@@ -0,0 +1,733 @@
+/*
+ * bin86/as/keywords.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* keywords.c - keywords for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "opcode.h"
+
+/* registers */
+/* the register code (internal to assembler) is given in 1 byte */
+/* the "opcode" field is not used */
+
+PUBLIC char regs[] =
+{
+#ifdef I80386
+ 2, 'B', 'P', BPREG, 0,
+ 2, 'B', 'X', BXREG, 0,
+ 2, 'D', 'I', DIREG, 0,
+ 2, 'S', 'I', SIREG, 0,
+
+ 3, 'E', 'A', 'X', EAXREG, 0,
+ 3, 'E', 'B', 'P', EBPREG, 0,
+ 3, 'E', 'B', 'X', EBXREG, 0,
+ 3, 'E', 'C', 'X', ECXREG, 0,
+ 3, 'E', 'D', 'I', EDIREG, 0,
+ 3, 'E', 'D', 'X', EDXREG, 0,
+ 3, 'E', 'S', 'I', ESIREG, 0,
+ 3, 'E', 'S', 'P', ESPREG, 0,
+
+ 2, 'A', 'X', AXREG, 0,
+ 2, 'C', 'X', CXREG, 0,
+ 2, 'D', 'X', DXREG, 0,
+ 2, 'S', 'P', SPREG, 0,
+
+ 2, 'A', 'H', AHREG, 0,
+ 2, 'A', 'L', ALREG, 0,
+ 2, 'B', 'H', BHREG, 0,
+ 2, 'B', 'L', BLREG, 0,
+ 2, 'C', 'H', CHREG, 0,
+ 2, 'C', 'L', CLREG, 0,
+ 2, 'D', 'H', DHREG, 0,
+ 2, 'D', 'L', DLREG, 0,
+
+ 2, 'C', 'S', CSREG, 0,
+ 2, 'D', 'S', DSREG, 0,
+ 2, 'E', 'S', ESREG, 0,
+ 2, 'F', 'S', FSREG, 0,
+ 2, 'G', 'S', GSREG, 0,
+ 2, 'S', 'S', SSREG, 0,
+
+ 3, 'C', 'R', '0', CR0REG, 0,
+ 3, 'C', 'R', '2', CR2REG, 0,
+ 3, 'C', 'R', '3', CR3REG, 0,
+ 3, 'D', 'R', '0', DR0REG, 0,
+ 3, 'D', 'R', '1', DR1REG, 0,
+ 3, 'D', 'R', '2', DR2REG, 0,
+ 3, 'D', 'R', '3', DR3REG, 0,
+ 3, 'D', 'R', '6', DR6REG, 0,
+ 3, 'D', 'R', '7', DR7REG, 0,
+ 3, 'T', 'R', '3', TR3REG, 0,
+ 3, 'T', 'R', '4', TR4REG, 0,
+ 3, 'T', 'R', '5', TR5REG, 0,
+ 3, 'T', 'R', '6', TR6REG, 0,
+ 3, 'T', 'R', '7', TR7REG, 0,
+
+ 2, 'S', 'T', ST0REG, 0,
+#endif /* I80386 */
+
+#ifdef MC6809
+ 1, 'A', AREG, 0,
+ 1, 'B', BREG, 0,
+ 2, 'C', 'C', CCREG, 0,
+ 1, 'D', DREG, 0,
+ 2, 'D', 'P', DPREG, 0,
+ 2, 'P', 'C', PCREG, 0,
+ 3, 'P', 'C', 'R', PCREG, 0,
+ 1, 'S', SREG, 0,
+ 1, 'U', UREG, 0,
+ 1, 'X', XREG, 0,
+ 1, 'Y', YREG, 0,
+#endif
+ 0 /* end of register list */
+};
+
+#ifdef I80386
+
+/* type sizes */
+/* the "opcode" field gives the type size */
+
+PUBLIC char typesizes[] =
+{
+ 4, 'B', 'Y', 'T', 'E', BYTEOP, 1,
+ 5, 'D', 'W', 'O', 'R', 'D', DWORDOP, 4,
+ 5, 'F', 'W', 'O', 'R', 'D', FWORDOP, 6,
+ 3, 'F', 'A', 'R', FAROP, 0,
+ 3, 'P', 'T', 'R', PTROP, 0,
+ 5, 'P', 'W', 'O', 'R', 'D', PWORDOP, 6,
+ 5, 'Q', 'W', 'O', 'R', 'D', QWORDOP, 8,
+ 5, 'T', 'B', 'Y', 'T', 'E', TBYTEOP, 10,
+ 4, 'W', 'O', 'R', 'D', WORDOP, 2,
+ 0 /* end of typesize list */
+};
+
+#endif
+
+/* ops */
+/* the routine number is given in 1 byte */
+/* the opcode is given in 1 byte (it is not used for pseudo-ops) */
+
+PUBLIC char ops[] =
+{
+ /* pseudo-ops. The "opcode" field is unused and padded with a null byte */
+ /* conditionals - must be first */
+ 4, 'E', 'L', 'S', 'E', ELSEOP, 0,
+ 6, 'E', 'L', 'S', 'E', 'I', 'F', ELSEIFOP, 0,
+ 7, 'E', 'L', 'S', 'E', 'I', 'F', 'C', ELSEIFCOP, 0,
+ 5, 'E', 'N', 'D', 'I', 'F', ENDIFOP, 0,
+ 2, 'I', 'F', IFOP, 0,
+ 3, 'I', 'F', 'C', IFCOP, 0,
+
+ /* unconditionals */
+ 6, '.', 'A', 'L', 'I', 'G', 'N', ALIGNOP, 0,
+ 6, '.', 'A', 'S', 'C', 'I', 'I', FCCOP, 0,
+ 5, '.', 'B', 'L', 'K', 'B', RMBOP, 0,
+ 5, '.', 'B', 'L', 'K', 'W', BLKWOP, 0,
+ 5, 'B', 'L', 'O', 'C', 'K', BLOCKOP, 0,
+ 4, '.', 'B', 'S', 'S', BSSOP, 0,
+ 5, '.', 'B', 'Y', 'T', 'E', FCBOP, 0,
+ 4, 'C', 'O', 'M', 'M', COMMOP, 0,
+ 5, '.', 'C', 'O', 'M', 'M', COMMOP1, 0,
+ 5, '.', 'D', 'A', 'T', 'A', DATAOP, 0,
+ 6, '.', 'D', 'A', 'T', 'A', '1', FCBOP, 0,
+ 6, '.', 'D', 'A', 'T', 'A', '2', FDBOP, 0,
+ 6, '.', 'D', 'A', 'T', 'A', '4', FQBOP, 0,
+ 2, 'D', 'B', FCBOP, 0,
+ 2, 'D', 'D', FQBOP, 0,
+ 7, '.', 'D', 'E', 'F', 'I', 'N', 'E', EXPORTOP, 0,
+ 2, 'D', 'W', FDBOP, 0,
+ 3, 'E', 'N', 'D', PROCEOFOP, 0,
+ 4, 'E', 'N', 'D', 'B', ENDBOP, 0,
+ 5, 'E', 'N', 'T', 'E', 'R', ENTEROP, 0,
+ 5, 'E', 'N', 'T', 'R', 'Y', ENTRYOP, 0,
+ 3, 'E', 'Q', 'U', EQUOP, 0,
+ 5, '.', 'E', 'V', 'E', 'N', EVENOP, 0,
+ 6, 'E', 'X', 'P', 'O', 'R', 'T', EXPORTOP, 0,
+ 6, 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0,
+ 7, '.', 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0,
+ 5, 'E', 'X', 'T', 'R', 'N', IMPORTOP, 0,
+ 4, 'F', 'A', 'I', 'L', FAILOP, 0,
+ 5, '.', 'F', 'A', 'I', 'L', FAILOP, 0,
+ 3, 'F', 'C', 'B', FCBOP, 0,
+ 3, 'F', 'C', 'C', FCCOP, 0,
+ 3, 'F', 'D', 'B', FDBOP, 0,
+ 3, 'G', 'E', 'T', GETOP, 0,
+ 6, '.', 'G', 'L', 'O', 'B', 'L', GLOBLOP, 0,
+ 5, 'I', 'D', 'E', 'N', 'T', IDENTOP, 0,
+ 6, 'I', 'M', 'P', 'O', 'R', 'T', IMPORTOP, 0,
+ 7, 'I', 'N', 'C', 'L', 'U', 'D', 'E', GETOP, 0,
+ 5, 'L', 'C', 'O', 'M', 'M', LCOMMOP, 0,
+ 6, '.', 'L', 'C', 'O', 'M', 'M', LCOMMOP1, 0,
+ 5, '.', 'L', 'I', 'S', 'T', LISTOP, 0,
+ 3, 'L', 'O', 'C', LOCOP, 0,
+ 5, '.', 'L', 'O', 'N', 'G', FQBOP, 0,
+ 8, '.', 'M', 'A', 'C', 'L', 'I', 'S', 'T', MACLISTOP, 0,
+ 5, 'M', 'A', 'C', 'R', 'O', MACROOP, 0,
+ 4, '.', 'M', 'A', 'P', MAPOP, 0,
+ 3, 'O', 'R', 'G', ORGOP, 0,
+ 4, '.', 'O', 'R', 'G', ORGOP, 0,
+ 6, 'P', 'U', 'B', 'L', 'I', 'C', EXPORTOP, 0,
+ 3, 'R', 'M', 'B', RMBOP, 0,
+ 4, '.', 'R', 'O', 'M', DATAOP, 0,
+ 5, '.', 'S', 'E', 'C', 'T', SECTOP, 0,
+ 3, 'S', 'E', 'T', SETOP, 0,
+ 5, 'S', 'E', 'T', 'D', 'P', SETDPOP, 0,
+ 6, '.', 'S', 'H', 'O', 'R', 'T', FDBOP, 0,
+ 6, '.', 'S', 'P', 'A', 'C', 'E', RMBOP, 0,
+ 5, '.', 'T', 'E', 'X', 'T', TEXTOP, 0,
+ 5, 'U', 'S', 'E', '1', '6', USE16OP, 0,
+ 5, 'U', 'S', 'E', '3', '2', USE32OP, 0,
+ 5, '.', 'W', 'A', 'R', 'N', WARNOP, 0,
+ 5, '.', 'W', 'O', 'R', 'D', FDBOP, 0,
+ 6, '.', 'Z', 'E', 'R', 'O', 'W', BLKWOP, 0,
+
+ /* hardware ops. The opcode field is now used */
+#ifdef I80386
+ 3, 'A', 'A', 'A', INHER, 0x37,
+ 3, 'A', 'A', 'D', INHER_A, 0xD5,
+ 3, 'A', 'A', 'M', INHER_A, 0xD4,
+ 3, 'A', 'A', 'S', INHER, 0x3F,
+ 3, 'A', 'D', 'C', GROUP1, 0x10,
+ 3, 'A', 'D', 'D', GROUP1, 0x00,
+ 3, 'A', 'N', 'D', GROUP1, 0x20,
+ 4, 'A', 'R', 'P', 'L', EwGw, 0x63,
+ 3, 'B', 'C', 'C', BCC, 0x73,
+ 3, 'B', 'C', 'S', BCC, 0x72,
+ 3, 'B', 'E', 'Q', BCC, 0x74,
+ 3, 'B', 'G', 'E', BCC, 0x7D,
+ 3, 'B', 'G', 'T', BCC, 0x7F,
+ 3, 'B', 'H', 'I', BCC, 0x77,
+ 4, 'B', 'H', 'I', 'S', BCC, 0x73,
+ 3, 'B', 'L', 'E', BCC, 0x7E,
+ 3, 'B', 'L', 'O', BCC, 0x72,
+ 4, 'B', 'L', 'O', 'S', BCC, 0x76,
+ 3, 'B', 'L', 'T', BCC, 0x7C,
+ 3, 'B', 'M', 'I', BCC, 0x78,
+ 3, 'B', 'N', 'E', BCC, 0x75,
+ 5, 'B', 'O', 'U', 'N', 'D', GvMa, 0x62,
+ 3, 'B', 'P', 'C', BCC, 0x7B,
+ 3, 'B', 'P', 'L', BCC, 0x79,
+ 3, 'B', 'P', 'S', BCC, 0x7A,
+ 2, 'B', 'R', CALL, JMP_OPCODE,
+ 3, 'B', 'V', 'C', BCC, 0x71,
+ 3, 'B', 'V', 'S', BCC, 0x70,
+ 4, 'C', 'A', 'L', 'L', CALL, JSR_OPCODE,
+ 5, 'C', 'A', 'L', 'L', 'F', CALLI, 0x9A,
+ 5, 'C', 'A', 'L', 'L', 'I', CALLI, 0x9A,
+ 3, 'C', 'B', 'W', INHER16, 0x98,
+ 3, 'C', 'L', 'C', INHER, 0xF8,
+ 3, 'C', 'L', 'D', INHER, 0xFC,
+ 3, 'C', 'L', 'I', INHER, 0xFA,
+ 3, 'C', 'M', 'C', INHER, 0xF5,
+ 3, 'C', 'M', 'P', GROUP1, CMP_OPCODE_BASE,
+ 4, 'C', 'M', 'P', 'S', INHER, CMPSW_OPCODE,
+ 5, 'C', 'M', 'P', 'S', 'B', INHER, CMPSB_OPCODE,
+ 5, 'C', 'M', 'P', 'S', 'D', INHER32, CMPSW_OPCODE,
+ 5, 'C', 'M', 'P', 'S', 'W', INHER16, CMPSW_OPCODE,
+ 4, 'C', 'M', 'P', 'W', INHER16, CMPSW_OPCODE,
+ 4, 'C', 'S', 'E', 'G', INHER, 0x2E,
+ 3, 'C', 'W', 'D', INHER16, 0x99,
+ 4, 'C', 'W', 'D', 'E', INHER32, 0x98,
+ 3, 'C', 'D', 'Q', INHER32, 0x99,
+ 3, 'D', 'A', 'A', INHER, 0x27,
+ 3, 'D', 'A', 'S', INHER, 0x2F,
+ 4, 'D', 'S', 'E', 'G', INHER, 0x3E,
+ 3, 'D', 'E', 'C', INCDEC, 0x08,
+ 3, 'D', 'I', 'V', DIVMUL, 0x30,
+ 5, 'E', 'N', 'T', 'E', 'R', ENTER, 0xC8,
+ 4, 'E', 'S', 'E', 'G', INHER, 0x26,
+ 4, 'F', 'S', 'E', 'G', INHER, 0x64,
+ 4, 'G', 'S', 'E', 'G', INHER, 0x65,
+ 3, 'H', 'L', 'T', INHER, 0xF4,
+ 4, 'I', 'D', 'I', 'V', DIVMUL, 0x38,
+ 4, 'I', 'M', 'U', 'L', IMUL, 0x28,
+ 2, 'I', 'N', IN, 0xEC,
+ 3, 'I', 'N', 'C', INCDEC, 0x00,
+ 3, 'I', 'N', 'S', INHER, 0x6D,
+ 4, 'I', 'N', 'S', 'B', INHER, 0x6C,
+ 4, 'I', 'N', 'S', 'D', INHER32, 0x6D,
+ 4, 'I', 'N', 'S', 'W', INHER16, 0x6D,
+ 3, 'I', 'N', 'T', INT, 0xCD,
+ 4, 'I', 'N', 'T', 'O', INHER, 0xCE,
+ 3, 'I', 'N', 'W', IN, 0xED,
+ 4, 'I', 'R', 'E', 'T', INHER16, 0xCF,
+ 5, 'I', 'R', 'E', 'T', 'D', INHER32, 0xCF,
+ 1, 'J', CALL, JMP_SHORT_OPCODE,
+ 2, 'J', 'A', JCC, 0x77,
+ 3, 'J', 'A', 'E', JCC, 0x73,
+ 2, 'J', 'B', JCC, 0x72,
+ 3, 'J', 'B', 'E', JCC, 0x76,
+ 2, 'J', 'C', JCC, 0x72,
+ 4, 'J', 'C', 'X', 'E', JCXZ, 0x2,
+ 4, 'J', 'C', 'X', 'Z', JCXZ, 0x2,
+ 5, 'J', 'E', 'C', 'X', 'E', JCXZ, 0x4,
+ 5, 'J', 'E', 'C', 'X', 'Z', JCXZ, 0x4,
+ 2, 'J', 'E', JCC, 0x74,
+ 2, 'J', 'G', JCC, 0x7F,
+ 3, 'J', 'G', 'E', JCC, 0x7D,
+ 2, 'J', 'L', JCC, 0x7C,
+ 3, 'J', 'L', 'E', JCC, 0x7E,
+ 3, 'J', 'M', 'P', CALL, JMP_SHORT_OPCODE,
+ 4, 'J', 'M', 'P', 'F', CALLI, 0xEA,
+ 4, 'J', 'M', 'P', 'I', CALLI, 0xEA,
+ 3, 'J', 'N', 'A', JCC, 0x76,
+ 4, 'J', 'N', 'A', 'E', JCC, 0x72,
+ 3, 'J', 'N', 'B', JCC, 0x73,
+ 4, 'J', 'N', 'B', 'E', JCC, 0x77,
+ 3, 'J', 'N', 'C', JCC, 0x73,
+ 3, 'J', 'N', 'E', JCC, 0x75,
+ 3, 'J', 'N', 'G', JCC, 0x7E,
+ 4, 'J', 'N', 'G', 'E', JCC, 0x7C,
+ 3, 'J', 'N', 'L', JCC, 0x7D,
+ 4, 'J', 'N', 'L', 'E', JCC, 0x7F,
+ 3, 'J', 'N', 'O', JCC, 0x71,
+ 3, 'J', 'N', 'P', JCC, 0x7B,
+ 3, 'J', 'N', 'S', JCC, 0x79,
+ 3, 'J', 'N', 'Z', JCC, 0x75,
+ 2, 'J', 'O', JCC, 0x70,
+ 2, 'J', 'P', JCC, 0x7A,
+ 3, 'J', 'P', 'E', JCC, 0x7A,
+ 3, 'J', 'P', 'O', JCC, 0x7B,
+ 2, 'J', 'S', JCC, 0x78,
+ 2, 'J', 'Z', JCC, 0x74,
+ 4, 'L', 'A', 'H', 'F', INHER, 0x9F,
+ 3, 'L', 'D', 'S', GvMp, 0xC5,
+ 3, 'L', 'E', 'A', LEA, 0x8D,
+ 5, 'L', 'E', 'A', 'V', 'E', INHER, 0xC9,
+ 3, 'L', 'E', 'S', GvMp, 0xC4,
+ 4, 'L', 'O', 'C', 'K', INHER, 0xF0,
+ 4, 'L', 'O', 'D', 'B', INHER, 0xAC,
+ 4, 'L', 'O', 'D', 'S', INHER, 0xAD,
+ 5, 'L', 'O', 'D', 'S', 'B', INHER, 0xAC,
+ 5, 'L', 'O', 'D', 'S', 'D', INHER32, 0xAD,
+ 5, 'L', 'O', 'D', 'S', 'W', INHER16, 0xAD,
+ 4, 'L', 'O', 'D', 'W', INHER16, 0xAD,
+ 4, 'L', 'O', 'O', 'P', JCC, 0xE2,
+ 5, 'L', 'O', 'O', 'P', 'E', JCC, 0xE1,
+ 6, 'L', 'O', 'O', 'P', 'N', 'E', JCC, 0xE0,
+ 6, 'L', 'O', 'O', 'P', 'N', 'Z', JCC, 0xE0,
+ 5, 'L', 'O', 'O', 'P', 'Z', JCC, 0xE1,
+ 3, 'M', 'O', 'V', MOV, 0x88,
+ 4, 'M', 'O', 'V', 'S', INHER, MOVSW_OPCODE,
+ 5, 'M', 'O', 'V', 'S', 'B', INHER, MOVSB_OPCODE,
+ 5, 'M', 'O', 'V', 'S', 'D', INHER32, MOVSW_OPCODE,
+ 5, 'M', 'O', 'V', 'S', 'W', INHER16, MOVSW_OPCODE,
+ 4, 'M', 'O', 'V', 'W', INHER16, MOVSW_OPCODE,
+ 3, 'M', 'U', 'L', DIVMUL, 0x20,
+ 3, 'N', 'E', 'G', NEGNOT, 0x18,
+ 3, 'N', 'O', 'P', INHER, 0x90,
+ 3, 'N', 'O', 'T', NEGNOT, 0x10,
+ 2, 'O', 'R', GROUP1, 0x08,
+ 3, 'O', 'U', 'T', OUT, 0xEE,
+ 4, 'O', 'U', 'T', 'S', INHER, 0x6F,
+ 5, 'O', 'U', 'T', 'S', 'B', INHER, 0x6E,
+ 5, 'O', 'U', 'T', 'S', 'D', INHER32, 0x6F,
+ 5, 'O', 'U', 'T', 'S', 'W', INHER16, 0x6F,
+ 4, 'O', 'U', 'T', 'W', OUT, 0xEF,
+ 3, 'P', 'O', 'P', PUSHPOP, POP_OPCODE,
+ 4, 'P', 'O', 'P', 'A', INHER16, 0x61,
+ 5, 'P', 'O', 'P', 'A', 'D', INHER32, 0x61,
+ 4, 'P', 'O', 'P', 'F', INHER16, 0x9D,
+ 5, 'P', 'O', 'P', 'F', 'D', INHER32, 0x9D,
+ 4, 'P', 'U', 'S', 'H', PUSHPOP, PUSH_OPCODE,
+ 5, 'P', 'U', 'S', 'H', 'A', INHER16, 0x60,
+ 6, 'P', 'U', 'S', 'H', 'A', 'D', INHER32, 0x60,
+ 5, 'P', 'U', 'S', 'H', 'F', INHER16, 0x9C,
+ 6, 'P', 'U', 'S', 'H', 'F', 'D', INHER32, 0x9C,
+ 3, 'R', 'C', 'L', GROUP2, 0x10,
+ 3, 'R', 'C', 'R', GROUP2, 0x18,
+ 3, 'R', 'O', 'L', GROUP2, 0x00,
+ 3, 'R', 'O', 'R', GROUP2, 0x08,
+ 3, 'R', 'E', 'P', INHER, 0xF3,
+ 4, 'R', 'E', 'P', 'E', INHER, 0xF3,
+ 5, 'R', 'E', 'P', 'N', 'E', INHER, 0xF2,
+ 5, 'R', 'E', 'P', 'N', 'Z', INHER, 0xF2,
+ 4, 'R', 'E', 'P', 'Z', INHER, 0xF3,
+ 3, 'R', 'E', 'T', RET, 0xC3,
+ 4, 'R', 'E', 'T', 'F', RET, 0xCB,
+ 4, 'R', 'E', 'T', 'I', RET, 0xCB,
+ 4, 'S', 'A', 'H', 'F', INHER, 0x9E,
+ 3, 'S', 'A', 'L', GROUP2, 0x20,
+ 3, 'S', 'A', 'R', GROUP2, 0x38,
+ 3, 'S', 'B', 'B', GROUP1, 0x18,
+ 4, 'S', 'C', 'A', 'B', INHER, 0xAE,
+ 4, 'S', 'C', 'A', 'S', INHER, 0xAF,
+ 5, 'S', 'C', 'A', 'S', 'B', INHER, 0xAE,
+ 5, 'S', 'C', 'A', 'S', 'D', INHER32, 0xAF,
+ 5, 'S', 'C', 'A', 'S', 'W', INHER16, 0xAF,
+ 4, 'S', 'C', 'A', 'W', INHER16, 0xAF,
+ 3, 'S', 'E', 'G', SEG, 0x06,
+ 3, 'S', 'H', 'L', GROUP2, 0x20,
+ 3, 'S', 'H', 'R', GROUP2, 0x28,
+ 4, 'S', 'S', 'E', 'G', INHER, 0x36,
+ 3, 'S', 'T', 'C', INHER, 0xF9,
+ 3, 'S', 'T', 'D', INHER, 0xFD,
+ 3, 'S', 'T', 'I', INHER, 0xFB,
+ 4, 'S', 'T', 'O', 'B', INHER, 0xAA,
+ 4, 'S', 'T', 'O', 'S', INHER, 0xAB,
+ 5, 'S', 'T', 'O', 'S', 'B', INHER, 0xAA,
+ 5, 'S', 'T', 'O', 'S', 'D', INHER32, 0xAB,
+ 5, 'S', 'T', 'O', 'S', 'W', INHER16, 0xAB,
+ 4, 'S', 'T', 'O', 'W', INHER16, 0xAB,
+ 3, 'S', 'U', 'B', GROUP1, 0x28,
+ 4, 'T', 'E', 'S', 'T', TEST, 0x84,
+ 4, 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE,
+ 4, 'X', 'C', 'H', 'G', XCHG, 0x86,
+ 4, 'X', 'L', 'A', 'T', INHER, 0xD7,
+ 5, 'X', 'L', 'A', 'T', 'B', INHER, 0xD7,
+ 3, 'X', 'O', 'R', GROUP1, 0x30,
+
+ /* floating point */
+ 5, 'F', '2', 'X', 'M', '1', F_INHER, 0x70,
+ 4, 'F', 'A', 'B', 'S', F_INHER, 0x61,
+ 4, 'F', 'A', 'D', 'D', F_M4_M8_STST, 0x00,
+ 5, 'F', 'A', 'D', 'D', 'P', F_STST, 0x60,
+ 4, 'F', 'B', 'L', 'D', F_M10, 0x74,
+ 5, 'F', 'B', 'S', 'T', 'P', F_M10, 0x76,
+ 4, 'F', 'C', 'H', 'S', F_INHER, 0x60,
+ 5, 'F', 'C', 'L', 'E', 'X', F_W_INHER, 0xE2,
+ 4, 'F', 'C', 'O', 'M', F_M4_M8_OPTST, 0x02,
+ 5, 'F', 'C', 'O', 'M', 'P', F_M4_M8_OPTST, 0x03,
+ 6, 'F', 'C', 'O', 'M', 'P', 'P', F_INHER, 0x19,
+ 4, 'F', 'C', 'O', 'S', F_INHER, 0x7F,
+ 7, 'F', 'D', 'E', 'C', 'S', 'T', 'P', F_INHER, 0x76,
+ 5, 'F', 'D', 'I', 'S', 'I', F_W_INHER, 0xE1,
+ 4, 'F', 'D', 'I', 'V', F_M4_M8_STST, 0x06,
+ 5, 'F', 'D', 'I', 'V', 'P', F_STST, 0x67,
+ 5, 'F', 'D', 'I', 'V', 'R', F_M4_M8_STST, 0x07,
+ 6, 'F', 'D', 'I', 'V', 'R', 'P', F_STST, 0x66,
+ 4, 'F', 'E', 'N', 'I', F_W_INHER, 0xE0,
+ 5, 'F', 'F', 'R', 'E', 'E', F_ST, 0x50,
+ 5, 'F', 'I', 'A', 'D', 'D', F_M2_M4, 0x20,
+ 5, 'F', 'I', 'C', 'O', 'M', F_M2_M4, 0x22,
+ 6, 'F', 'I', 'C', 'O', 'M', 'P', F_M2_M4, 0x23,
+ 5, 'F', 'I', 'D', 'I', 'V', F_M2_M4, 0x26,
+ 6, 'F', 'I', 'D', 'I', 'V', 'R', F_M2_M4, 0x27,
+ 4, 'F', 'I', 'L', 'D', F_M2_M4_M8, 0x30,
+ 5, 'F', 'I', 'M', 'U', 'L', F_M2_M4, 0x21,
+ 7, 'F', 'I', 'N', 'C', 'S', 'T', 'P', F_INHER, 0x77,
+ 5, 'F', 'I', 'N', 'I', 'T', F_W_INHER, 0xE3,
+ 4, 'F', 'I', 'S', 'T', F_M2_M4, 0x32,
+ 5, 'F', 'I', 'S', 'T', 'P', F_M2_M4_M8, 0x33,
+ 5, 'F', 'I', 'S', 'U', 'B', F_M2_M4, 0x24,
+ 6, 'F', 'I', 'S', 'U', 'B', 'R', F_M2_M4, 0x25,
+ 3, 'F', 'L', 'D', F_M4_M8_M10_ST, 0x10,
+ 4, 'F', 'L', 'D', '1', F_INHER, 0x68,
+ 6, 'F', 'L', 'D', 'L', '2', 'E', F_INHER, 0x6A,
+ 6, 'F', 'L', 'D', 'L', '2', 'T', F_INHER, 0x69,
+ 5, 'F', 'L', 'D', 'C', 'W', F_M2, 0x15,
+ 6, 'F', 'L', 'D', 'E', 'N', 'V', F_M, 0x14,
+ 6, 'F', 'L', 'D', 'L', 'G', '2', F_INHER, 0x6C,
+ 6, 'F', 'L', 'D', 'L', 'N', '2', F_INHER, 0x6D,
+ 5, 'F', 'L', 'D', 'P', 'I', F_INHER, 0x6B,
+ 4, 'F', 'L', 'D', 'Z', F_INHER, 0x6E,
+ 4, 'F', 'M', 'U', 'L', F_M4_M8_STST, 0x01,
+ 5, 'F', 'M', 'U', 'L', 'P', F_STST, 0x61,
+ 6, 'F', 'N', 'C', 'L', 'E', 'X', F_INHER, 0xE2,
+ 6, 'F', 'N', 'D', 'I', 'S', 'I', F_INHER, 0xE1,
+ 5, 'F', 'N', 'E', 'N', 'I', F_INHER, 0xE0,
+ 6, 'F', 'N', 'I', 'N', 'I', 'T', F_INHER, 0xE3,
+ 4, 'F', 'N', 'O', 'P', F_INHER, 0x50,
+ 6, 'F', 'N', 'S', 'A', 'V', 'E', F_M, 0x56,
+ 6, 'F', 'N', 'S', 'T', 'C', 'W', F_M2, 0x17,
+ 7, 'F', 'N', 'S', 'T', 'E', 'N', 'V', F_M, 0x16,
+ 6, 'F', 'N', 'S', 'T', 'S', 'W', F_M2_AX, 0x57,
+ 6, 'F', 'P', 'A', 'T', 'A', 'N', F_INHER, 0x73,
+ 5, 'F', 'P', 'R', 'E', 'M', F_INHER, 0x78,
+ 6, 'F', 'P', 'R', 'E', 'M', '1', F_INHER, 0x75,
+ 5, 'F', 'P', 'T', 'A', 'N', F_INHER, 0x72,
+ 7, 'F', 'R', 'N', 'D', 'I', 'N', 'T', F_INHER, 0x7C,
+ 6, 'F', 'R', 'S', 'T', 'O', 'R', F_M, 0x54,
+ 5, 'F', 'S', 'A', 'V', 'E', F_W_M, 0x56,
+ 6, 'F', 'S', 'C', 'A', 'L', 'E', F_INHER, 0x7D,
+ 6, 'F', 'S', 'E', 'T', 'P', 'M', F_INHER, 0xE4,
+ 4, 'F', 'S', 'I', 'N', F_INHER, 0x7E,
+ 7, 'F', 'S', 'I', 'N', 'C', 'O', 'S', F_INHER, 0x7B,
+ 5, 'F', 'S', 'Q', 'R', 'T', F_INHER, 0x7A,
+ 3, 'F', 'S', 'T', F_M4_M8_ST, FST_ENCODED,
+ 5, 'F', 'S', 'T', 'C', 'W', F_W_M2, 0x17,
+ 6, 'F', 'S', 'T', 'E', 'N', 'V', F_W_M, 0x16,
+ 4, 'F', 'S', 'T', 'P', F_M4_M8_M10_ST, FSTP_ENCODED,
+ 5, 'F', 'S', 'T', 'S', 'W', F_W_M2_AX, 0x57,
+ 4, 'F', 'S', 'U', 'B', F_M4_M8_STST, 0x04,
+ 5, 'F', 'S', 'U', 'B', 'P', F_STST, 0x65,
+ 5, 'F', 'S', 'U', 'B', 'R', F_M4_M8_STST, 0x05,
+ 6, 'F', 'S', 'U', 'B', 'R', 'P', F_STST, 0x64,
+ 4, 'F', 'T', 'S', 'T', F_INHER, 0x64,
+ 5, 'F', 'U', 'C', 'O', 'M', F_OPTST, 0x54,
+ 6, 'F', 'U', 'C', 'O', 'M', 'P', F_OPTST, 0x55,
+ 7, 'F', 'U', 'C', 'O', 'M', 'P', 'P', F_INHER, 0xA9,
+ 5, 'F', 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE,
+ 4, 'F', 'X', 'A', 'M', F_INHER, 0x65,
+ 4, 'F', 'X', 'C', 'H', F_OPTST, 0x11,
+ 7, 'F', 'X', 'T', 'R', 'A', 'C', 'T', F_INHER, 0x74,
+ 5, 'F', 'Y', 'L', '2', 'X', F_INHER, 0x71,
+ 7, 'F', 'Y', 'L', '2', 'X', 'P', '1', F_INHER, 0x79,
+#endif /* I80386 */
+
+#ifdef MC6809
+ 3, 'A', 'B', 'X', INHER, 0x3A,
+ 4, 'A', 'D', 'C', 'A', ALL, 0x89,
+ 4, 'A', 'D', 'C', 'B', ALL, 0xC9,
+ 4, 'A', 'D', 'D', 'A', ALL, 0x8B,
+ 4, 'A', 'D', 'D', 'B', ALL, 0xCB,
+ 4, 'A', 'D', 'D', 'D', ALL, 0xC3,
+ 4, 'A', 'N', 'D', 'A', ALL, 0x84,
+ 4, 'A', 'N', 'D', 'B', ALL, 0xC4,
+ 5, 'A', 'N', 'D', 'C', 'C', IMMED, 0x1C,
+ 3, 'A', 'S', 'L', ALTER, 0x08,
+ 4, 'A', 'S', 'L', 'A', INHER, 0x48,
+ 4, 'A', 'S', 'L', 'B', INHER, 0x58,
+ 3, 'A', 'S', 'R', ALTER, 0x07,
+ 4, 'A', 'S', 'R', 'A', INHER, 0x47,
+ 4, 'A', 'S', 'R', 'B', INHER, 0x57,
+ 3, 'B', 'C', 'C', SHORT, 0x24,
+ 3, 'B', 'C', 'S', SHORT, 0x25,
+ 3, 'B', 'E', 'Q', SHORT, 0x27,
+ 3, 'B', 'G', 'E', SHORT, 0x2C,
+ 3, 'B', 'G', 'T', SHORT, 0x2E,
+ 3, 'B', 'H', 'I', SHORT, 0x22,
+ 3, 'B', 'H', 'S', SHORT, 0x24,
+ 4, 'B', 'I', 'T', 'A', ALL, 0X85,
+ 4, 'B', 'I', 'T', 'B', ALL, 0XC5,
+ 3, 'B', 'L', 'E', SHORT, 0x2F,
+ 3, 'B', 'L', 'O', SHORT, 0x25,
+ 3, 'B', 'L', 'S', SHORT, 0x23,
+ 3, 'B', 'L', 'T', SHORT, 0x2D,
+ 3, 'B', 'M', 'I', SHORT, 0x2B,
+ 3, 'B', 'N', 'E', SHORT, 0x26,
+ 3, 'B', 'P', 'L', SHORT, 0x2A,
+ 3, 'B', 'R', 'A', SHORT, 0x20,
+ 4, 'L', 'B', 'R', 'A', LONG, 0x16,
+ 3, 'B', 'R', 'N', SHORT, 0x21,
+ 3, 'B', 'S', 'R', SHORT, 0x8D,
+ 4, 'L', 'B', 'S', 'R', LONG, 0x17,
+ 3, 'B', 'V', 'C', SHORT, 0x28,
+ 3, 'B', 'V', 'S', SHORT, 0x29,
+ 3, 'C', 'L', 'R', ALTER, 0x0F,
+ 4, 'C', 'L', 'R', 'A', INHER, 0x4F,
+ 4, 'C', 'L', 'R', 'B', INHER, 0x5F,
+ 4, 'C', 'M', 'P', 'A', ALL, 0x81,
+ 4, 'C', 'M', 'P', 'B', ALL, 0xC1,
+ 4, 'C', 'M', 'P', 'X', ALL, 0x8C,
+ 3, 'C', 'O', 'M', ALTER, 0x03,
+ 4, 'C', 'O', 'M', 'A', INHER, 0x43,
+ 4, 'C', 'O', 'M', 'B', INHER, 0x53,
+ 4, 'C', 'W', 'A', 'I', IMMED, 0x3C,
+ 3, 'D', 'A', 'A', INHER, 0x19,
+ 3, 'D', 'E', 'C', ALTER, 0x0A,
+ 4, 'D', 'E', 'C', 'A', INHER, 0x4A,
+ 4, 'D', 'E', 'C', 'B', INHER, 0x5A,
+ 4, 'E', 'O', 'R', 'A', ALL, 0x88,
+ 4, 'E', 'O', 'R', 'B', ALL, 0xC8,
+ 3, 'E', 'X', 'G', SWAP, 0x1E,
+ 3, 'I', 'N', 'C', ALTER, 0x0C,
+ 4, 'I', 'N', 'C', 'A', INHER, 0x4C,
+ 4, 'I', 'N', 'C', 'B', INHER, 0x5C,
+ 3, 'J', 'M', 'P', ALTER, 0x0E,
+ 3, 'J', 'S', 'R', ALTER, 0x8D,
+ 3, 'L', 'D', 'A', ALL, 0x86,
+ 3, 'L', 'D', 'B', ALL, 0xC6,
+ 3, 'L', 'D', 'D', ALL, 0xCC,
+ 3, 'L', 'D', 'U', ALL, 0xCE,
+ 3, 'L', 'D', 'X', ALL, 0x8E,
+ 4, 'L', 'E', 'A', 'S', INDEXD, 0x32,
+ 4, 'L', 'E', 'A', 'U', INDEXD, 0x33,
+ 4, 'L', 'E', 'A', 'X', INDEXD, 0x30,
+ 4, 'L', 'E', 'A', 'Y', INDEXD, 0x31,
+ 3, 'L', 'S', 'L', ALTER, 0x08,
+ 4, 'L', 'S', 'L', 'A', INHER, 0x48,
+ 4, 'L', 'S', 'L', 'B', INHER, 0x58,
+ 3, 'L', 'S', 'R', ALTER, 0x04,
+ 4, 'L', 'S', 'R', 'A', INHER, 0x44,
+ 4, 'L', 'S', 'R', 'B', INHER, 0x54,
+ 3, 'M', 'U', 'L', INHER, 0x3D,
+ 3, 'N', 'E', 'G', ALTER, 0x00,
+ 4, 'N', 'E', 'G', 'A', INHER, 0x40,
+ 4, 'N', 'E', 'G', 'B', INHER, 0x50,
+ 3, 'N', 'O', 'P', INHER, 0x12,
+ 3, 'O', 'R', 'A', ALL, 0x8A,
+ 3, 'O', 'R', 'B', ALL, 0xCA,
+ 4, 'O', 'R', 'C', 'C', IMMED, 0x1A,
+ 4, 'P', 'S', 'H', 'S', SSTAK, 0x34,
+ 4, 'P', 'S', 'H', 'U', USTAK, 0x36,
+ 4, 'P', 'U', 'L', 'S', SSTAK, 0x35,
+ 4, 'P', 'U', 'L', 'U', USTAK, 0x37,
+ 3, 'R', 'O', 'L', ALTER, 0x09,
+ 4, 'R', 'O', 'L', 'A', INHER, 0x49,
+ 4, 'R', 'O', 'L', 'B', INHER, 0x59,
+ 3, 'R', 'O', 'R', ALTER, 0x06,
+ 4, 'R', 'O', 'R', 'A', INHER, 0x46,
+ 4, 'R', 'O', 'R', 'B', INHER, 0x56,
+ 3, 'R', 'T', 'I', INHER, 0x3B,
+ 3, 'R', 'T', 'S', INHER, 0x39,
+ 4, 'S', 'B', 'C', 'A', ALL, 0x82,
+ 4, 'S', 'B', 'C', 'B', ALL, 0xC2,
+ 3, 'S', 'E', 'X', INHER, 0x1D,
+ 3, 'S', 'T', 'A', ALTER, 0x87,
+ 3, 'S', 'T', 'B', ALTER, 0xC7,
+ 3, 'S', 'T', 'D', ALTER, 0xCD,
+ 3, 'S', 'T', 'U', ALTER, 0xCF,
+ 3, 'S', 'T', 'X', ALTER, 0x8F,
+ 4, 'S', 'U', 'B', 'A', ALL, 0x80,
+ 4, 'S', 'U', 'B', 'B', ALL, 0xC0,
+ 4, 'S', 'U', 'B', 'D', ALL, 0x83,
+ 3, 'S', 'W', 'I', INHER, 0x3F,
+ 4, 'S', 'Y', 'N', 'C', INHER, 0x13,
+ 3, 'T', 'F', 'R', SWAP, 0x1F,
+ 3, 'T', 'S', 'T', ALTER, 0x0D,
+ 4, 'T', 'S', 'T', 'A', INHER, 0x4D,
+ 4, 'T', 'S', 'T', 'B', INHER, 0x5D,
+#endif /* MC6809 */
+ 0 /* end of ops */
+};
+
+PUBLIC char page1ops[] =
+{
+#ifdef I80386
+ 3, 'B', 'S', 'F', GvEv, 0xBC,
+ 3, 'B', 'S', 'R', GvEv, 0xBD,
+ 5, 'B', 'S', 'W', 'A', 'P', BSWAP, 0xC8,
+ 2, 'B', 'T', GROUP8, 0x20,
+ 3, 'B', 'T', 'C', GROUP8, 0x38,
+ 3, 'B', 'T', 'R', GROUP8, 0x30,
+ 3, 'B', 'T', 'S', GROUP8, 0x28,
+ 4, 'C', 'L', 'T', 'S', INHER, 0x06,
+ 7, 'C', 'M', 'P', 'X', 'C', 'H', 'G', ExGx, 0xA6,
+ 4, 'I', 'N', 'V', 'D', INHER, 0x08,
+ 6, 'I', 'N', 'V', 'L', 'P', 'G', GROUP7, 0x38,
+ 3, 'L', 'A', 'R', GvEv, 0x02,
+ 3, 'L', 'F', 'S', GvMp, 0xB4,
+ 4, 'L', 'G', 'D', 'T', GROUP7, 0x10,
+ 3, 'L', 'G', 'S', GvMp, 0xB5,
+ 4, 'L', 'I', 'D', 'T', GROUP7, 0x18,
+ 4, 'L', 'L', 'D', 'T', GROUP6, 0x10,
+ 4, 'L', 'M', 'S', 'W', GROUP7, 0x30,
+ 3, 'L', 'S', 'L', GvEv, 0x03,
+ 3, 'L', 'S', 'S', GvMp, 0xB2,
+ 3, 'L', 'T', 'R', GROUP6, 0x18,
+ 5, 'M', 'O', 'V', 'S', 'X', MOVX, 0xBE,
+ 5, 'M', 'O', 'V', 'Z', 'X', MOVX, 0xB6,
+ 4, 'S', 'E', 'T', 'A', SETCC, 0x97,
+ 5, 'S', 'E', 'T', 'A', 'E', SETCC, 0x93,
+ 4, 'S', 'E', 'T', 'B', SETCC, 0x92,
+ 5, 'S', 'E', 'T', 'B', 'E', SETCC, 0x96,
+ 4, 'S', 'E', 'T', 'C', SETCC, 0x92,
+ 4, 'S', 'E', 'T', 'E', SETCC, 0x94,
+ 4, 'S', 'E', 'T', 'G', SETCC, 0x9F,
+ 5, 'S', 'E', 'T', 'G', 'E', SETCC, 0x9D,
+ 4, 'S', 'E', 'T', 'L', SETCC, 0x9C,
+ 5, 'S', 'E', 'T', 'L', 'E', SETCC, 0x9E,
+ 5, 'S', 'E', 'T', 'N', 'A', SETCC, 0x96,
+ 6, 'S', 'E', 'T', 'N', 'A', 'E', SETCC, 0x92,
+ 5, 'S', 'E', 'T', 'N', 'B', SETCC, 0x93,
+ 6, 'S', 'E', 'T', 'N', 'B', 'E', SETCC, 0x97,
+ 5, 'S', 'E', 'T', 'N', 'C', SETCC, 0x93,
+ 5, 'S', 'E', 'T', 'N', 'E', SETCC, 0x95,
+ 5, 'S', 'E', 'T', 'N', 'G', SETCC, 0x9E,
+ 6, 'S', 'E', 'T', 'N', 'G', 'E', SETCC, 0x9C,
+ 5, 'S', 'E', 'T', 'N', 'L', SETCC, 0x9D,
+ 6, 'S', 'E', 'T', 'N', 'L', 'E', SETCC, 0x9F,
+ 5, 'S', 'E', 'T', 'N', 'O', SETCC, 0x91,
+ 5, 'S', 'E', 'T', 'N', 'P', SETCC, 0x9B,
+ 5, 'S', 'E', 'T', 'N', 'S', SETCC, 0x99,
+ 5, 'S', 'E', 'T', 'N', 'Z', SETCC, 0x95,
+ 4, 'S', 'E', 'T', 'O', SETCC, 0x90,
+ 4, 'S', 'E', 'T', 'P', SETCC, 0x9A,
+ 5, 'S', 'E', 'T', 'P', 'E', SETCC, 0x9A,
+ 5, 'S', 'E', 'T', 'P', 'O', SETCC, 0x9B,
+ 4, 'S', 'E', 'T', 'S', SETCC, 0x98,
+ 4, 'S', 'E', 'T', 'Z', SETCC, 0x94,
+ 4, 'S', 'G', 'D', 'T', GROUP7, 0x00,
+ 4, 'S', 'I', 'D', 'T', GROUP7, 0x08,
+ 4, 'S', 'H', 'L', 'D', SH_DOUBLE, 0xA4,
+ 4, 'S', 'H', 'R', 'D', SH_DOUBLE, 0xAC,
+ 4, 'S', 'L', 'D', 'T', GROUP6, 0x00,
+ 4, 'S', 'M', 'S', 'W', GROUP7, 0x20,
+ 3, 'S', 'T', 'R', GROUP6, 0x08,
+ 4, 'V', 'E', 'R', 'R', GROUP6, 0x20,
+ 4, 'V', 'E', 'R', 'W', GROUP6, 0x28,
+ 6, 'W', 'B', 'I', 'N', 'V', 'D', INHER, 0x09,
+ 4, 'X', 'A', 'D', 'D', ExGx, 0xC0,
+#endif /* I80386 */
+
+#ifdef MC6809
+ 4, 'L', 'B', 'C', 'C', LONG, 0x24,
+ 4, 'L', 'B', 'C', 'S', LONG, 0x25,
+ 4, 'L', 'B', 'E', 'Q', LONG, 0x27,
+ 4, 'L', 'B', 'G', 'E', LONG, 0x2C,
+ 4, 'L', 'B', 'G', 'T', LONG, 0x2E,
+ 4, 'L', 'B', 'H', 'I', LONG, 0x22,
+ 4, 'L', 'B', 'H', 'S', LONG, 0x24,
+ 4, 'L', 'B', 'L', 'E', LONG, 0x2F,
+ 4, 'L', 'B', 'L', 'O', LONG, 0x25,
+ 4, 'L', 'B', 'L', 'S', LONG, 0x23,
+ 4, 'L', 'B', 'L', 'T', LONG, 0x2D,
+ 4, 'L', 'B', 'M', 'I', LONG, 0x2B,
+ 4, 'L', 'B', 'N', 'E', LONG, 0x26,
+ 4, 'L', 'B', 'P', 'L', LONG, 0x2A,
+ 4, 'L', 'B', 'R', 'N', LONG, 0x21,
+ 4, 'L', 'B', 'V', 'C', LONG, 0x28,
+ 4, 'L', 'B', 'V', 'S', LONG, 0x29,
+ 4, 'C', 'M', 'P', 'D', ALL, 0x83,
+ 4, 'C', 'M', 'P', 'Y', ALL, 0x8C,
+ 3, 'L', 'D', 'S', ALL, 0xCE,
+ 3, 'L', 'D', 'Y', ALL, 0x8E,
+ 3, 'S', 'T', 'S', ALTER, 0xCF,
+ 3, 'S', 'T', 'Y', ALTER, 0x8F,
+ 4, 'S', 'W', 'I', '2', INHER, 0x3F,
+#endif /* MC6809 */
+ 0 /* end of page 1 ops */
+};
+
+PUBLIC char page2ops[] =
+{
+#ifdef MC6809
+ 4, 'C', 'M', 'P', 'S', ALL, 0x8C,
+ 4, 'C', 'M', 'P', 'U', ALL, 0x83,
+ 4, 'S', 'W', 'I', '3', INHER, 0x3F,
+#endif
+ 0 /* end of page 2 ops */
+};
+
+#ifdef I80386
+# ifdef MNSIZE
+PUBLIC char bytesizeops[] =
+{
+ 4, 'A', 'D', 'C', 'B', GROUP1, 0x10,
+ 4, 'A', 'D', 'D', 'B', GROUP1, 0x00,
+ 4, 'A', 'N', 'D', 'B', GROUP1, 0x20,
+ 4, 'C', 'M', 'P', 'B', GROUP1, CMP_OPCODE_BASE,
+ 4, 'D', 'E', 'C', 'b', INCDEC, 0x08,
+ 4, 'D', 'I', 'V', 'B', DIVMUL, 0x30,
+ 5, 'I', 'D', 'I', 'V', 'B', DIVMUL, 0x38,
+ 5, 'I', 'M', 'U', 'L', 'B', IMUL, 0x28,
+ 3, 'I', 'N', 'B', IN, 0xEC,
+ 4, 'I', 'N', 'C', 'B', INCDEC, 0x00,
+ 4, 'M', 'O', 'V', 'B', MOV, 0x88,
+ 4, 'M', 'U', 'L', 'B', DIVMUL, 0x20,
+ 4, 'N', 'E', 'G', 'B', NEGNOT, 0x18,
+ 4, 'N', 'O', 'T', 'B', NEGNOT, 0x10,
+ 3, 'O', 'R', 'B', GROUP1, 0x08,
+ 4, 'O', 'U', 'T', 'B', OUT, 0xEE,
+ 4, 'R', 'C', 'L', 'B', GROUP2, 0x10,
+ 4, 'R', 'C', 'R', 'B', GROUP2, 0x18,
+ 4, 'R', 'O', 'L', 'B', GROUP2, 0x00,
+ 4, 'R', 'O', 'R', 'B', GROUP2, 0x08,
+ 4, 'S', 'A', 'L', 'B', GROUP2, 0x20,
+ 4, 'S', 'A', 'R', 'B', GROUP2, 0x38,
+ 4, 'S', 'H', 'L', 'B', GROUP2, 0x20,
+ 4, 'S', 'H', 'R', 'B', GROUP2, 0x28,
+ 4, 'S', 'B', 'B', 'B', GROUP1, 0x18,
+ 4, 'S', 'U', 'B', 'B', GROUP1, 0x28,
+ 5, 'T', 'E', 'S', 'T', 'B', TEST, 0x84,
+ 5, 'X', 'C', 'H', 'G', 'B', XCHG, 0x86,
+ 4, 'X', 'O', 'R', 'B', GROUP1, 0x30,
+ 0 /* end of byte size ops */
+};
+# endif /* MNSIZE */
+#endif /* I80386 */
diff --git a/bin86-0.3/as/macro.c b/bin86-0.3/as/macro.c
new file mode 100644
index 0000000..103ed08
--- /dev/null
+++ b/bin86-0.3/as/macro.c
@@ -0,0 +1,174 @@
+/*
+ * bin86/as/macro.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* macro.c - expand macros for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "macro.h"
+
+/*
+ Enter macro: stack macro and get its parameters.
+ Parameters form a linked list of null-terminated strings of form
+ next:string. The first string is the macro number in 4 bytes.
+*/
+
+PUBLIC void entermac(symptr)
+struct sym_s *symptr;
+{
+ if (maclevel >= MAXMAC)
+ error(MACOV);
+ else if (macpar + 2 > macptop)
+ error(PAROV); /* no room for 0th param */
+ /* (2 structs to fit it!) */
+ else
+ {
+ char ch;
+ struct schain_s *param1;
+ register char *reglineptr;
+ register char *stringptr;
+
+ ++maclevel;
+ (--macstak)->text = (char *) symptr->value_reg_or_op.value;
+ macstak->parameters = param1 = macpar;
+ param1->next = NULL;
+ *(stringptr = build_number(++macnum, 3, param1->string)) = 0;
+ macpar = (struct schain_s *) (stringptr + 1);
+ /* TODO: alignment */
+ getsym();
+ if (sym != LPAREN)
+ return; /* no other params */
+ reglineptr = lineptr;
+ stringptr = macpar->string;
+ while (TRUE)
+ {
+ if (stringptr >= (char *) macptop)
+ {
+ symname = reglineptr;
+ error(PAROV);
+ return;
+ }
+ ch = *reglineptr++;
+ if (ch == '/')
+ /* escaped means no special meaning for slash, comma, paren */
+ ch = *reglineptr++;
+ else if (ch == ',' || ch == ')')
+ {
+ if (stringptr >= (char *) macptop)
+ {
+ symname = reglineptr;
+ error(PAROV); /* no room for null */
+ return;
+ }
+ *stringptr = 0;
+ param1->next = macpar; /* ptr from previous */
+ (param1 = macpar)->next = NULL;
+ /* this goes nowhere */
+ macpar = (struct schain_s *) (stringptr + 1);
+ /* but is finished OK - TODO align */
+ stringptr = macpar->string;
+ if (ch == ')')
+ return;
+ continue;
+ }
+ if ((*stringptr++ = ch) == 0)
+ {
+ symname = reglineptr;
+ error(RPEXP);
+ return;
+ }
+ }
+ }
+}
+
+/* MACRO pseudo-op */
+
+PUBLIC void pmacro()
+{
+ bool_t saving;
+ bool_t savingc;
+ struct sym_s *symptr;
+
+ saving = /* prepare for bad macro */
+ savingc = FALSE; /* normally don't save comments */
+ macload = TRUE; /* show loading */
+ if (label != NULL)
+ error(ILLAB);
+ else if (sym != IDENT)
+ error(LABEXP);
+ else
+ {
+ symptr = gsymptr;
+ if (symptr->type & MNREGBIT)
+ error(LABEXP);
+ else if (symptr->type & LABIT || symptr->data & FORBIT)
+ error(RELAB);
+ else if (pass == 0 || symptr->type & REDBIT)
+ /* copy on pass 0, also pass 1 if redefined */
+ {
+ saving = TRUE;
+ if (symptr->type & MACBIT)
+ symptr->type |= REDBIT;
+ else
+ symptr->type |= MACBIT;
+ symptr->data = UNDBIT; /* undefined till end */
+ symptr->value_reg_or_op.value = (unsigned) heapptr;
+ /* beginning of store for macro */
+ /* value s.b. (char *) */
+ getsym_nolookup(); /* test for "C" */
+ if (sym == IDENT && lineptr == symname + 1 && *symname == 'C')
+ savingc = TRUE;
+ }
+ }
+ while (TRUE)
+ {
+ skipline();
+ listline();
+ readline();
+ if (!macload)
+ break; /* macload cleared to show eof */
+ getsym_nolookup();
+ if (sym == IDENT)
+ {
+ if (lineptr == symname + 4 && strncmp(symname, "MEND", 4) == 0)
+ break;
+ }
+ else if (sym != MACROARG)
+ {
+ if (!savingc)
+ continue; /* don't save comment */
+ }
+ if (!saving)
+ continue;
+ {
+ register char *reglineptr;
+ register char *regheapptr;
+
+ reglineptr = linebuf;
+ regheapptr = heapptr;
+ do
+ {
+ if (regheapptr >= heapend)
+ {
+ heapptr = regheapptr;
+ fatalerror(SYMOV); /* won't fit */
+ }
+ }
+ while ((*regheapptr++ = *reglineptr++) != EOLCHAR);
+ heapptr = regheapptr;
+ }
+ }
+ macload = FALSE;
+ if (saving)
+ {
+ *heapptr++ = ETB;
+ symptr->data = 0;
+ }
+}
diff --git a/bin86-0.3/as/macro.h b/bin86-0.3/as/macro.h
new file mode 100644
index 0000000..9fdee58
--- /dev/null
+++ b/bin86-0.3/as/macro.h
@@ -0,0 +1,16 @@
+/*
+ * bin86/as/macro.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* macro.h - global variables for macro expansion for assembler */
+
+EXTERN bool_t macflag; /* inside macro flag */
+EXTERN bool_t macload; /* loading macro flag */
+EXTERN unsigned macnum; /* macro call counter */
+
+EXTERN unsigned char maclevel; /* nesting level */
+EXTERN struct schain_s *macpar; /* parameter save buffer */
+EXTERN struct schain_s *macptop; /* top of param buffer (+1) */
+EXTERN struct macro_s *macstak; /* stack ptr */
diff --git a/bin86-0.3/as/mops.c b/bin86-0.3/as/mops.c
new file mode 100644
index 0000000..be4e0f6
--- /dev/null
+++ b/bin86-0.3/as/mops.c
@@ -0,0 +1,2840 @@
+/*
+ * bin86/as/mops.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* mops.c - handle pseudo-ops */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "address.h"
+
+#define is8bitadr(offset) ((offset_t) offset < 0x100)
+#define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100)
+#define pass2 pass
+
+FORWARD void mshort2 P((void));
+FORWARD reg_pt regchk P((void));
+FORWARD void reldata P((void));
+
+#ifdef I80386
+
+#define iswordadr(offset) ((offset_t) (offset) < 0x10000L)
+#define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L)
+#define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL)
+
+#define BYTE_SEGWORD 0x00
+#define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG)
+
+#define BASE_MASK 0x07
+#define BASE_SHIFT 0
+#define INDEX_MASK 0x38
+#define INDEX_SHIFT 3
+#define MOD_MASK 0xC0
+# define REG_MOD 0xC0
+# define MEM0_MOD 0x00
+# define MEM1_MOD 0x40
+# define MEM2_MOD 0x80
+#define REG_MASK 0x38
+#define REG_SHIFT 3
+#define RM_MASK 0x07
+#define RM_SHIFT 0
+# define D16_RM 0x06
+# define D32_RM 0x05
+# define SIB_NOBASE 0x05
+# define SIB_RM 0x04
+#define SREG_MASK 0x38
+#define SREG_SHIFT 3
+#define SS_MASK 0xC0
+#define SS_SHIFT 6
+
+#define SEGMOV 0x04
+#define SIGNBIT 0x02
+#define TOREGBIT 0x02
+#define WORDBIT 0x01
+
+PRIVATE opcode_t baseind16[] =
+{
+ 0x00, /* BP + BP, illegal */
+ 0x00, /* BX + BP, illegal */
+ 0x03, /* DI + BP */
+ 0x02, /* SI + BP */
+ 0x00, /* BP + BX, illegal */
+ 0x00, /* BX + BX, illegal */
+ 0x01, /* DI + BX */
+ 0x00, /* SI + BX */
+ 0x03, /* BP + DI */
+ 0x01, /* BX + DI */
+ 0x00, /* DI + DI, illegal */
+ 0x00, /* SI + DI, illegal */
+ 0x02, /* BP + SI */
+ 0x00, /* BX + SI */
+ 0x00, /* DI + SI, illegal */
+ 0x00, /* SI + SI, illegal */
+};
+
+PRIVATE opcode_t regbits[] =
+{
+ 0x05 << REG_SHIFT, /* BP */
+ 0x03 << REG_SHIFT, /* BX */
+ 0x07 << REG_SHIFT, /* DI */
+ 0x06 << REG_SHIFT, /* SI */
+
+ 0x00 << REG_SHIFT, /* EAX */
+ 0x05 << REG_SHIFT, /* EBP */
+ 0x03 << REG_SHIFT, /* EBX */
+ 0x01 << REG_SHIFT, /* ECX */
+ 0x07 << REG_SHIFT, /* EDI */
+ 0x02 << REG_SHIFT, /* EDX */
+ 0x06 << REG_SHIFT, /* ESI */
+ 0x04 << REG_SHIFT, /* ESP */
+
+ 0x00 << REG_SHIFT, /* AX */
+ 0x01 << REG_SHIFT, /* CX */
+ 0x02 << REG_SHIFT, /* DX */
+ 0x04 << REG_SHIFT, /* SP */
+
+ 0x04 << REG_SHIFT, /* AH */
+ 0x00 << REG_SHIFT, /* AL */
+ 0x07 << REG_SHIFT, /* BH */
+ 0x03 << REG_SHIFT, /* BL */
+ 0x05 << REG_SHIFT, /* CH */
+ 0x01 << REG_SHIFT, /* CL */
+ 0x06 << REG_SHIFT, /* DH */
+ 0x02 << REG_SHIFT, /* DL */
+
+ 0x01 << REG_SHIFT, /* CS */
+ 0x03 << REG_SHIFT, /* DS */
+ 0x00 << REG_SHIFT, /* ES */
+ 0x04 << REG_SHIFT, /* FS */
+ 0x05 << REG_SHIFT, /* GS */
+ 0x02 << REG_SHIFT, /* SS */
+
+ 0x00 << REG_SHIFT, /* CR0 */
+ 0x02 << REG_SHIFT, /* CR2 */
+ 0x03 << REG_SHIFT, /* CR3 */
+
+ 0x00 << REG_SHIFT, /* DR0 */
+ 0x01 << REG_SHIFT, /* DR1 */
+ 0x02 << REG_SHIFT, /* DR2 */
+ 0x03 << REG_SHIFT, /* DR3 */
+ 0x06 << REG_SHIFT, /* DR6 */
+ 0x07 << REG_SHIFT, /* DR7 */
+
+ 0x03 << REG_SHIFT, /* TR3 */
+ 0x04 << REG_SHIFT, /* TR4 */
+ 0x05 << REG_SHIFT, /* TR5 */
+ 0x06 << REG_SHIFT, /* TR6 */
+ 0x07 << REG_SHIFT, /* TR7 */
+
+ 0x00 << REG_SHIFT, /* ST(0) */
+ 0x01 << REG_SHIFT, /* ST(1) */
+ 0x02 << REG_SHIFT, /* ST(2) */
+ 0x03 << REG_SHIFT, /* ST(3) */
+ 0x04 << REG_SHIFT, /* ST(4) */
+ 0x05 << REG_SHIFT, /* ST(5) */
+ 0x06 << REG_SHIFT, /* ST(6) */
+ 0x07 << REG_SHIFT, /* ST(7) */
+};
+
+PRIVATE opsize_t regsize[] =
+{
+ 2, /* BP */
+ 2, /* BX */
+ 2, /* DI */
+ 2, /* SI */
+
+ 4, /* EAX */
+ 4, /* EBP */
+ 4, /* EBX */
+ 4, /* ECX */
+ 4, /* EDI */
+ 4, /* EDX */
+ 4, /* ESI */
+ 4, /* ESP */
+
+ 2, /* AX */
+ 2, /* CX */
+ 2, /* DX */
+ 2, /* SP */
+
+ 1, /* AH */
+ 1, /* AL */
+ 1, /* BH */
+ 1, /* BL */
+ 1, /* CH */
+ 1, /* CL */
+ 1, /* DH */
+ 1, /* DL */
+
+ 2, /* CS */
+ 2, /* DS */
+ 2, /* ES */
+ 2, /* FS */
+ 2, /* GS */
+ 2, /* SS */
+
+ 4, /* CR0 */
+ 4, /* CR2 */
+ 4, /* CR3 */
+
+ 4, /* DR0 */
+ 4, /* DR1 */
+ 4, /* DR2 */
+ 4, /* DR3 */
+ 4, /* DR6 */
+ 4, /* DR7 */
+
+ 4, /* TR3 */
+ 4, /* TR4 */
+ 4, /* TR5 */
+ 4, /* TR6 */
+ 4, /* TR7 */
+
+ 10, /* ST(0) */
+ 10, /* ST(1) */
+ 10, /* ST(2) */
+ 10, /* ST(3) */
+ 10, /* ST(4) */
+ 10, /* ST(5) */
+ 10, /* ST(6) */
+ 10, /* ST(7) */
+
+ 0, /* NOREG */
+};
+
+PRIVATE opcode_t regsegword[] =
+{
+ WORDBIT, /* BP */
+ WORDBIT, /* BX */
+ WORDBIT, /* DI */
+ WORDBIT, /* SI */
+
+ WORDBIT, /* EAX */
+ WORDBIT, /* EBP */
+ WORDBIT, /* EBX */
+ WORDBIT, /* ECX */
+ WORDBIT, /* EDI */
+ WORDBIT, /* EDX */
+ WORDBIT, /* ESI */
+ WORDBIT, /* ESP */
+
+ WORDBIT, /* AX */
+ WORDBIT, /* CX */
+ WORDBIT, /* DX */
+ WORDBIT, /* SP */
+
+ BYTE_SEGWORD, /* AH */
+ BYTE_SEGWORD, /* AL */
+ BYTE_SEGWORD, /* BH */
+ BYTE_SEGWORD, /* BL */
+ BYTE_SEGWORD, /* CH */
+ BYTE_SEGWORD, /* CL */
+ BYTE_SEGWORD, /* DH */
+ BYTE_SEGWORD, /* DL */
+
+ SEGMOV, /* CS */
+ SEGMOV, /* DS */
+ SEGMOV, /* ES */
+ SEGMOV, /* FS */
+ SEGMOV, /* GS */
+ SEGMOV, /* SS */
+
+ 0x20, /* CR0 */
+ 0x20, /* CR2 */
+ 0x20, /* CR3 */
+
+ 0x21, /* DR0 */
+ 0x21, /* DR1 */
+ 0x21, /* DR2 */
+ 0x21, /* DR3 */
+ 0x21, /* DR6 */
+ 0x21, /* DR7 */
+
+ 0x24, /* TR3 */
+ 0x24, /* TR4 */
+ 0x24, /* TR5 */
+ 0x24, /* TR6 */
+ 0x24, /* TR7 */
+
+ 0x00, /* ST(0) */
+ 0x00, /* ST(1) */
+ 0x00, /* ST(2) */
+ 0x00, /* ST(3) */
+ 0x00, /* ST(4) */
+ 0x00, /* ST(5) */
+ 0x00, /* ST(6) */
+ 0x00, /* ST(7) */
+
+ 0x00, /* NOREG */
+};
+
+PRIVATE opcode_t rm[] =
+{
+ 0x05, /* BP */
+ 0x03, /* BX */
+ 0x07, /* DI */
+ 0x06, /* SI */
+
+ 0x00, /* EAX */
+ 0x05, /* EBP */
+ 0x03, /* EBX */
+ 0x01, /* ECX */
+ 0x07, /* EDI */
+ 0x02, /* EDX */
+ 0x06, /* ESI */
+ 0x04, /* ESP */
+
+ 0x00, /* AX */
+ 0x01, /* CX */
+ 0x02, /* DX */
+ 0x04, /* SP */
+
+ 0x04, /* AH */
+ 0x00, /* AL */
+ 0x07, /* BH */
+ 0x03, /* BL */
+ 0x05, /* CH */
+ 0x01, /* CL */
+ 0x06, /* DH */
+ 0x02, /* DL */
+
+ 0x01, /* CS */
+ 0x03, /* DS */
+ 0x00, /* ES */
+ 0x04, /* FS */
+ 0x05, /* GS */
+ 0x02, /* SS */
+
+ 0x00, /* CR0 */
+ 0x00, /* CR2 */
+ 0x00, /* CR3 */
+
+ 0x00, /* DR0 */
+ 0x00, /* DR1 */
+ 0x00, /* DR2 */
+ 0x00, /* DR3 */
+ 0x00, /* DR6 */
+ 0x00, /* DR7 */
+
+ 0x00, /* TR3 */
+ 0x00, /* TR4 */
+ 0x00, /* TR5 */
+ 0x00, /* TR6 */
+ 0x00, /* TR7 */
+
+ 0x00, /* ST(0) */
+ 0x00, /* ST(1) */
+ 0x00, /* ST(2) */
+ 0x00, /* ST(3) */
+ 0x00, /* ST(4) */
+ 0x00, /* ST(5) */
+ 0x00, /* ST(6) */
+ 0x00, /* ST(7) */
+
+ 0x04, /* null index reg for sib only */
+};
+
+PRIVATE opcode_t rmfunny[] =
+{
+ 0x06, /* BP */
+ 0x07, /* BX */
+ 0x05, /* DI */
+ 0x04, /* SI */
+};
+
+PRIVATE opcode_t segoverride[] =
+{
+ 0x2E, /* CS */
+ 0x3E, /* DS */
+ 0x26, /* ES */
+ 0x64, /* FS */
+ 0x65, /* GS */
+ 0x36, /* SS */
+};
+
+PRIVATE opcode_t ss[] = /* scale to ss bits */
+{
+ 0x00, /* x0, illegal */
+ 0x00 << SS_SHIFT, /* x1 */
+ 0x01 << SS_SHIFT, /* x2 */
+ 0x00, /* x3, illegal */
+ 0x02 << SS_SHIFT, /* x4 */
+ 0x00, /* x5, illegal */
+ 0x00, /* x6, illegal */
+ 0x00, /* x7, illegal */
+ 0x03 << SS_SHIFT, /* x8 */
+};
+
+PRIVATE unsigned char calljmp_kludge;
+PRIVATE opcode_t direction;
+PRIVATE bool_t fpreg_allowed;
+PRIVATE opcode_t segword;
+/*
+ Values of segword:
+ BYTE_SEGWORD for byte ea's.
+ SEGMOV for segment registers
+ opcode for special registers
+ WORDBIT for other word and dword ea's
+*/
+
+PRIVATE struct ea_s source;
+PRIVATE struct ea_s source2;
+PRIVATE struct ea_s target;
+
+FORWARD void Eb P((struct ea_s *eap));
+FORWARD void Ew P((struct ea_s *eap));
+FORWARD void Ev P((struct ea_s *eap));
+FORWARD void Ex P((struct ea_s *eap));
+FORWARD void Gw P((struct ea_s *eap));
+FORWARD void Gv P((struct ea_s *eap));
+FORWARD void Gx P((struct ea_s *eap));
+FORWARD void buildea P((struct ea_s *eap));
+FORWARD void buildfloat P((void));
+FORWARD void buildfreg P((void));
+FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag));
+FORWARD void buildregular P((void));
+FORWARD void buildsegword P((struct ea_s *eap));
+FORWARD void buildunary P((opcode_pt opc));
+FORWARD opsize_pt displsize P((struct ea_s *eap));
+FORWARD reg_pt fpregchk P((void));
+FORWARD bool_pt getaccumreg P((struct ea_s *eap));
+FORWARD void getbinary P((void));
+FORWARD bool_pt getdxreg P((struct ea_s *eap));
+FORWARD void getea P((struct ea_s *eap));
+FORWARD void getimmed P((struct ea_s *eap, count_t immcount));
+FORWARD void getindirect P((struct ea_s *eap));
+FORWARD void getshift P((struct ea_s *eap));
+FORWARD reg_pt indregchk P((reg_pt matchreg));
+FORWARD void kgerror P((error_pt errnum));
+FORWARD void lbranch P((unsigned backamount));
+FORWARD void notbytesize P((struct ea_s *eap));
+FORWARD void notimmed P((struct ea_s *eap));
+FORWARD void notindirect P((struct ea_s *eap));
+FORWARD void notsegorspecreg P((struct ea_s *eap));
+FORWARD void yesimmed P((struct ea_s *eap));
+FORWARD void yes_samesize P((void));
+
+PRIVATE void Eb(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ if (eap->size != 0x1)
+ {
+#ifndef NODEFAULTSIZE
+ if (eap->size == 0x0)
+ eap->size = 0x1;
+ else
+#endif
+ kgerror(ILL_SIZE);
+ }
+}
+
+PRIVATE void Ew(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ if (eap->size != 0x2)
+ {
+#ifndef NODEFAULTSIZE
+ if (eap->size == 0x0)
+ eap->size = 0x2;
+ else
+#endif
+ kgerror(ILL_SIZE);
+ }
+}
+
+PRIVATE void Ev(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ notbytesize(eap);
+}
+
+PRIVATE void Ex(eap)
+register struct ea_s *eap;
+{
+ getea(eap);
+ notimmed(eap);
+ notsegorspecreg(eap);
+}
+
+PRIVATE void Gd(eap)
+register struct ea_s *eap;
+{
+ Gx(eap);
+ if (eap->size != 0x4)
+ kgerror(ILL_SIZE);
+}
+
+PRIVATE void Gw(eap)
+register struct ea_s *eap;
+{
+ Gx(eap);
+ if (eap->size != 0x2)
+ kgerror(ILL_SIZE);
+}
+
+PRIVATE void Gv(eap)
+register struct ea_s *eap;
+{
+ Gx(eap);
+ notbytesize(eap);
+}
+
+PRIVATE void Gx(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ notindirect(eap);
+}
+
+PRIVATE void buildea(eap)
+register struct ea_s *eap;
+{
+ opsize_t asize;
+
+ ++mcount;
+ lastexp = eap->displ;
+ if (eap->indcount == 0x0)
+ postb = REG_MOD | rm[eap->base];
+ else
+ {
+ if (eap->base == NOREG)
+ {
+ if (eap->index == NOREG)
+ {
+ if ((asize = displsize(eap)) > 0x2)
+ postb = D32_RM;
+ else
+ postb = D16_RM;
+ }
+ else
+ {
+ asize = 0x4;
+ postb = SIB_NOBASE; /* for sib later */
+ }
+ }
+ else
+ {
+ if (eap->base > MAX16BITINDREG)
+ {
+ asize = 0x4;
+ postb = rm[eap->base];
+ }
+ else
+ {
+ asize = 0x2;
+ if (!(lastexp.data & UNDBIT) &&
+ !iswordorswordoffset(lastexp.offset))
+ error(ABOUNDS);
+ if (eap->index == NOREG)
+ postb = rmfunny[eap->base];
+ else if (eap->base <= MAX16BITINDREG)
+ postb = baseind16[eap->base + 0x4 * eap->index];
+ }
+ }
+ if (asize != defsize)
+ aprefix = 0x67;
+ if (eap->base == NOREG)
+ mcount += asize;
+ else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
+ !is8bitsignedoffset(lastexp.offset))
+ {
+ postb |= MEM2_MOD;
+ mcount += asize;
+ }
+ else if (lastexp.offset != 0x0 ||
+ eap->base == BPREG && eap->index == NOREG ||
+ eap->base == EBPREG)
+ {
+ postb |= MEM1_MOD;
+ ++mcount;
+ }
+ if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG))
+ {
+ sib = ss[eap->scale] |
+ (rm[eap->index] << INDEX_SHIFT) |
+ (postb & RM_MASK);
+ postb = (postb & MOD_MASK) | SIB_RM;
+ ++mcount;
+ }
+ }
+}
+
+PRIVATE void buildfloat()
+{
+ if (mcount != 0x0)
+ {
+ buildea(&source);
+ oprefix = 0x0;
+ postb |= (opcode & 0x07) << REG_SHIFT;
+ opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
+ }
+}
+
+PRIVATE void buildfreg()
+{
+ mcount += 0x2;
+ oprefix = 0x0;
+ postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG);
+ opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
+}
+
+PRIVATE void buildimm(eap, signflag)
+register struct ea_s *eap;
+bool_pt signflag;
+{
+ immadr = eap->displ;
+ immcount = eap->size;
+ if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)))
+ {
+ if (immcount == 0x1)
+ {
+ if ((offset_t) (immadr.offset + 0x80) >= 0x180)
+ datatoobig();
+ }
+ else if (signflag && is8bitsignedoffset(immadr.offset))
+ {
+ opcode |= SIGNBIT;
+ immcount = 0x1;
+ }
+ else if (immcount == 0x2)
+ {
+ if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L)
+ datatoobig();
+ }
+ }
+}
+
+PRIVATE void buildregular()
+{
+ if (mcount != 0x0)
+ {
+ buildea(&target);
+ postb |= regbits[source.base];
+ }
+}
+
+/* Check size and build segword. */
+
+PRIVATE void buildsegword(eap)
+register struct ea_s *eap;
+{
+ if (eap->size == 0x0)
+#ifdef NODEFAULTSIZE
+ kgerror(SIZE_UNK);
+#else
+ eap->size = defsize;
+#endif
+ if (eap->indcount != 0x0 || eap->base == NOREG)
+ {
+ segword = WORDBIT;
+ if (eap->size == 0x1)
+ segword = BYTE_SEGWORD;
+ }
+ else
+ segword = regsegword[eap->base];
+}
+
+PRIVATE void buildunary(opc)
+opcode_pt opc;
+{
+ if (mcount != 0x0)
+ {
+ buildea(&target);
+ postb |= opcode;
+ opcode = opc;
+ }
+}
+
+PRIVATE opsize_pt displsize(eap)
+register struct ea_s *eap;
+{
+ opsize_t asize;
+
+ asize = defsize;
+ if (!(eap->displ.data & UNDBIT))
+ {
+ if (asize > 0x2)
+ {
+ if (!(eap->displ.data & (FORBIT | RELBIT)) &&
+ iswordadr(eap->displ.offset))
+ asize = 0x2;
+ }
+ else if (!iswordorswordoffset(eap->displ.offset))
+ /* should really use iswordadr() */
+ /* but compiler generates signed offsets */
+ {
+ if (!(eap->displ.data & (FORBIT | RELBIT)))
+ asize = 0x4;
+ else if (pass2)
+ error(ABOUNDS);
+ }
+ }
+ return asize;
+}
+
+PRIVATE reg_pt fpregchk()
+{
+ reg_pt fpreg;
+
+ fpreg_allowed = TRUE;
+ fpreg = regchk();
+ fpreg_allowed = FALSE;
+ if (fpreg != ST0REG)
+ return NOREG;
+ getsym();
+ if (sym == LPAREN)
+ {
+ getsym();
+ if (sym != INTCONST || (unsigned) number >= 0x8)
+ error(ILL_FP_REG);
+ else
+ {
+ fpreg += number;
+ getsym();
+ if (sym != RPAREN)
+ error(RPEXP);
+ else
+ getsym();
+ }
+ }
+ return fpreg;
+}
+
+PRIVATE bool_pt getaccumreg(eap)
+register struct ea_s *eap;
+{
+ if ((eap->base = regchk()) != AXREG && eap->base != ALREG
+ && eap->base != EAXREG)
+ return FALSE;
+ getsym();
+ if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
+ oprefix = 0x66;
+ return TRUE;
+}
+
+/*
+ Get binary ea's in target & source (flipped if direction is set).
+ Put size in source if not already.
+ Initialise direction, segword, bump mcount.
+*/
+
+PRIVATE void getbinary()
+{
+ ++mcount;
+ getea(&target);
+ if (target.indcount == 0x0 && target.base == NOREG)
+ {
+ error(ILL_IMM_MODE);
+ target.base = AXREG;
+ target.size = defsize;
+ }
+ getcomma();
+ getea(&source);
+ if (source.size == 0x0)
+ source.size = target.size;
+ else if (target.size != 0x0 && target.size != source.size)
+ {
+ kgerror(MISMATCHED_SIZE);
+ return;
+ }
+ if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV)
+ direction = 0x0;
+ else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV)
+ {
+ struct ea_s swap;
+
+ direction = TOREGBIT;
+ swap = source;
+ source = target;
+ target = swap;
+ }
+ else if (target.indcount != 0x0)
+ {
+ kgerror(ILL_IND_TO_IND);
+ return;
+ }
+ else
+ {
+ kgerror(ILL_SEG_REG);
+ return;
+ }
+ buildsegword(&source);
+}
+
+PRIVATE bool_pt getdxreg(eap)
+register struct ea_s *eap;
+{
+ if ((eap->base = regchk()) != DXREG)
+ return FALSE;
+ getsym();
+ return TRUE;
+}
+
+/* parse effective address */
+
+/*
+ Syntax is restrictive in that displacements must be in the right spots
+ and will not be added up.
+
+ optional size-type prefix, which is
+ BYTE
+ BYTE PTR
+ WORD
+ WORD PTR
+ DWORD
+ DWORD PTR
+ PTR
+ reg
+ segreg
+ [scaled index]
+ where scaled index =
+ indreg
+ indreg*scale
+ indreg+indreg
+ indreg+indreg*scale
+ [scaled index+displ]
+ [scaled index-displ]
+ optional-immediate-prefix displ[scaled index]
+ [displ]
+ optional-imediate-prefix displ
+ (scaled index) -- anachronism
+ optional-imediate-prefix displ(scaled index) -- anachronism
+*/
+
+PRIVATE void getea(eap)
+register struct ea_s *eap;
+{
+ bool_t leading_displ;
+ bool_t leading_immed;
+ register struct sym_s *symptr;
+
+ leading_immed = leading_displ = lastexp.data = eap->indcount
+ = lastexp.offset = 0x0;
+ eap->index = eap->base = NOREG;
+ eap->scale = 0x1;
+ eap->size = mnsize; /* 0x1 for byte ops, else 0x0 */
+
+ if (sym == IDENT)
+ {
+ if ((symptr = gsymptr)->type & MNREGBIT)
+ {
+ if (symptr->data & SIZEBIT)
+ {
+ getsym();
+ if (symptr->value_reg_or_op.op.opcode == 0x0)
+ eap->indcount = 0x2 - calljmp_kludge;
+ else
+ {
+ if (eap->size != 0x0)
+ {
+ if (eap->size != symptr->value_reg_or_op.op.opcode)
+ error(MISMATCHED_SIZE);
+ }
+ else
+ eap->size = symptr->value_reg_or_op.op.opcode;
+ if (eap->size > 0x1 && eap->size != defsize)
+ oprefix = 0x66;
+ if (sym == IDENT &&
+ (symptr = gsymptr)->type & MNREGBIT &&
+ symptr->data & SIZEBIT &&
+ symptr->value_reg_or_op.op.routine == PTROP)
+ {
+ getsym();
+ eap->indcount = 0x2 - calljmp_kludge;
+ }
+ }
+ }
+ }
+ if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT)))
+ symptr->data |= FORBIT; /* show seen in advance */
+ }
+ if ((eap->base = regchk()) != NOREG)
+ {
+ getsym();
+ if (eap->indcount != 0x0)
+ {
+ error(ILL_IND_PTR);
+ eap->indcount = 0x0;
+ }
+ if (eap->size != 0x0 && eap->size != regsize[eap->base])
+ error(MISMATCHED_SIZE);
+ if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
+ oprefix = 0x66;
+ eap->displ = lastexp;
+ return;
+ }
+ if (sym != lindirect)
+ {
+ if (sym == IMMEDIATE || sym == STAR)
+ {
+ /* context-sensitive, STAR means signed immediate here */
+ leading_immed = TRUE;
+ getsym();
+ }
+ leading_displ = TRUE;
+ expres();
+ eap->displ = lastexp;
+ }
+ if (sym == lindirect)
+ {
+ getsym();
+ eap->indcount = 0x2 - calljmp_kludge;
+ if ((eap->base = indregchk(NOREG)) != NOREG)
+ {
+ if (eap->indcount == 0x0 && leading_displ)
+ error(IND_REQ);
+ getsym();
+ if (sym == ADDOP)
+ {
+ getsym();
+ if ((eap->index = indregchk(eap->base)) != NOREG)
+ getsym();
+ else
+ {
+ if (eap->indcount == 0x0)
+ error(IND_REQ);
+ if (leading_displ)
+ error(REPEATED_DISPL);
+ expres(); /* this eats ADDOP, SUBOP, MULOP */
+ }
+ }
+ if (sym == STAR)
+ {
+ /* context-sensitive, STAR means scaled here*/
+ if (eap->index == NOREG && eap->base == ESPREG)
+ {
+ error(INDEX_REG_EXP);
+ eap->base = EAXREG;
+ }
+ getsym();
+ factor();
+ chkabs();
+ if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1)
+ {
+ if (eap->base <= MAX16BITINDREG ||
+ lastexp.offset != 0x2 && lastexp.offset != 0x4 &&
+ lastexp.offset != 0x8)
+ error(ILL_SCALE);
+ else
+ {
+ eap->scale = lastexp.offset;
+ if (eap->index == NOREG)
+ {
+ eap->index = eap->base;
+ eap->base = NOREG;
+ }
+ }
+ }
+ lastexp.data = lastexp.offset = 0x0;
+ }
+ if ((sym == ADDOP || sym == SUBOP))
+ {
+ if (eap->indcount == 0x0)
+ error(IND_REQ);
+ if (leading_displ)
+ error(REPEATED_DISPL);
+ expres();
+ }
+ }
+ else
+ {
+ if (leading_displ)
+ error(REPEATED_DISPL);
+ expres();
+ }
+ if (sym != rindirect)
+ error(rindexp);
+ else
+ getsym();
+ }
+ else if (!leading_immed && idefsize <= 0x2)
+ eap->indcount = 0x1; /* compatibility kludge */
+ if (!leading_displ)
+ eap->displ = lastexp;
+}
+
+PRIVATE void getimmed(eap, immcount)
+struct ea_s *eap;
+count_t immcount;
+{
+ getea(eap);
+ yesimmed(eap);
+ if (mcount != 0x0)
+ {
+ eap->size = immcount;
+ buildimm(eap, FALSE);
+ }
+}
+
+PRIVATE void getindirect(eap)
+register struct ea_s *eap;
+{
+ getea(eap);
+ if (eap->indcount == 0x0)
+ kgerror(IND_REQ);
+}
+
+PRIVATE void getshift(eap)
+register struct ea_s *eap;
+{
+ getcomma();
+ getea(eap);
+ if (eap->base != CLREG)
+ yesimmed(eap);
+}
+
+/*
+ Check if current symbol is a compatible index register.
+ Generate error if it is a reg but not a compatible index.
+ Return register number (adjusted if necessary to a legal index) or NOREG.
+*/
+
+PRIVATE reg_pt indregchk(matchreg)
+reg_pt matchreg;
+{
+ reg_pt reg;
+
+ if ((reg = regchk()) != NOREG)
+ {
+ switch (matchreg)
+ {
+ case BPREG:
+ case BXREG:
+ if (reg != DIREG && reg != SIREG)
+ {
+ reg = SIREG;
+ error(INDEX_REG_EXP);
+ }
+ break;
+ case DIREG:
+ case SIREG:
+ if (reg != BPREG && reg != BXREG)
+ {
+ reg = BXREG;
+ error(INDEX_REG_EXP);
+ }
+ break;
+ case NOREG:
+ break;
+ default:
+ if (reg <= MAX16BITINDREG || reg == ESPREG)
+ {
+ reg = EAXREG;
+ error(INDEX_REG_EXP);
+ }
+ break;
+ }
+ if (reg > MAXINDREG && calljmp_kludge == 0x0)
+ {
+ if (matchreg != NOREG)
+ reg = EAXREG;
+ else
+ reg = BXREG;
+ error(INDEX_REG_EXP);
+ }
+ }
+ return reg;
+}
+
+PRIVATE void kgerror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ sprefix = oprefix = aprefix = mcount = 0x0;
+}
+
+PRIVATE void lbranch(backamount)
+unsigned backamount;
+{
+ mcount += defsize + 0x1;
+ if (pass2)
+ {
+ reldata();
+ if (!(lastexp.data & (RELBIT | UNDBIT)))
+ {
+ lastexp.offset = lastexp.offset - lc - lcjump;
+ if (backamount != 0x0 && !(lastexp.data & IMPBIT) &&
+ lastexp.offset + backamount < 0x80 + backamount)
+ error(SHORTB); /* -0x8? to 0x7F, warning */
+ }
+ }
+}
+
+/* BCC (long branches emulated by short branch over & long jump) */
+
+PUBLIC void mbcc()
+{
+ getea(&target);
+ if (target.indcount >= 0x2 || target.base != NOREG)
+ kgerror(REL_REQ);
+ else
+ {
+ if (defsize != 0x2)
+ {
+ page = PAGE1_OPCODE;
+ ++mcount;
+ opcode += 0x10;
+ lbranch(0x84);
+ }
+ else
+ {
+ aprefix = opcode ^ 0x1; /* kludged storage for short branch
+ over */
+ oprefix = defsize + 0x1;
+ mcount += 0x2;
+ opcode = JMP_OPCODE;
+ lbranch(0x83);
+ mcount -= 0x2;
+ }
+ }
+}
+
+/* bswap r32 */
+
+PUBLIC void mbswap()
+{
+ ++mcount;
+ Gd(&target);
+ opcode |= rm[target.base];
+}
+
+/* BR, CALL, J, JMP */
+
+PUBLIC void mcall()
+{
+ opcode_pt far;
+ bool_t indirect;
+ register struct sym_s *symptr;
+
+ far = 0x0;
+ if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT &&
+ symptr->data & SIZEBIT &&
+ symptr->value_reg_or_op.op.routine == FAROP)
+ {
+ far = 0x8;
+ getsym();
+ }
+ indirect = FALSE;
+ if (asld_compatible && idefsize <= 0x2)
+ {
+ calljmp_kludge = 0x2;
+ if (sym == INDIRECT)
+ {
+ calljmp_kludge = 0x0;
+ indirect = TRUE;
+ getsym();
+ }
+ }
+ getea(&target);
+ if (indirect && target.indcount == 0x1)
+ target.indcount = 0x2;
+ calljmp_kludge = 0x0;
+ if (sym == COLON)
+ {
+ if (opcode == JMP_SHORT_OPCODE)
+ opcode = JMP_OPCODE;
+ ++mcount;
+ yesimmed(&target);
+ getsym();
+ getea(&source);
+ yesimmed(&source);
+ if (mcount != 0x0)
+ {
+ if (opcode == JMP_OPCODE)
+ opcode = 0xEA;
+ else
+ opcode = 0x9A;
+ lastexp = source.displ;
+ if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
+ defsize == 0x2 &&
+ (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
+ datatoobig();
+ mcount += defsize;
+ target.size = 0x2;
+ buildimm(&target, FALSE);
+ }
+ }
+ else if (target.indcount >= 0x2 || target.base != NOREG)
+ {
+ ++mcount;
+ notsegorspecreg(&target);
+ if (target.indcount == 0)
+ notbytesize(&target);
+ if (mcount != 0x0)
+ {
+ if (opcode == JMP_SHORT_OPCODE)
+ opcode = JMP_OPCODE;
+ buildea(&target);
+ if (opcode == JMP_OPCODE)
+ opcode = 0x20;
+ else
+ opcode = 0x10;
+ postb |= opcode + far;
+ opcode = 0xFF;
+ }
+ }
+ else if (opcode == JMP_SHORT_OPCODE)
+ {
+ if (jumps_long)
+ {
+ opcode = JMP_OPCODE;
+ lbranch(0x83);
+ }
+ else
+ {
+ lastexp = target.displ;
+ if (lastexp.data & IMPBIT)
+ {
+ error(NONIMPREQ);
+ lastexp.data = FORBIT | UNDBIT;
+ }
+ mshort2();
+ }
+ }
+ else
+ lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0);
+}
+
+/* CALLI, JMPI */
+
+PUBLIC void mcalli()
+{
+ bool_t indirect;
+
+ ++mcount;
+ indirect = FALSE;
+ if (sym == INDIRECT)
+ {
+ getsym();
+ indirect = TRUE;
+ }
+ getea(&target);
+ if (target.indcount >= 0x2 || target.base != NOREG)
+ indirect = TRUE;
+ if (indirect)
+ {
+ buildea(&target);
+ if (opcode == 0xEA)
+ opcode = 0x28;
+ else
+ opcode = 0x18;
+ postb |= opcode;
+ opcode = 0xFF;
+ }
+ else
+ {
+ getcomma();
+ getea(&source);
+ yesimmed(&source);
+ if (mcount != 0x0)
+ {
+ lastexp = target.displ;
+ if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
+ defsize == 0x2 &&
+ (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
+ datatoobig();
+ mcount += defsize;
+ source.size = 0x2;
+ buildimm(&source, FALSE);
+ }
+ }
+}
+
+/* DIV, IDIV, MUL */
+
+PUBLIC void mdivmul()
+{
+ if (getaccumreg(&source))
+ {
+ ++mcount;
+ getcomma();
+ Ex(&target);
+ yes_samesize();
+ buildunary(0xF6 | regsegword[source.base]);
+ }
+ else
+ mnegnot();
+}
+
+/* ENTER */
+
+PUBLIC void menter()
+{
+ ++mcount;
+ getimmed(&target, 0x2);
+ getcomma();
+ getimmed(&source, 0x1);
+ if (mcount != 0x0)
+ {
+ mcount += 2;
+ lastexp = target.displ; /* getimmed(&source) wiped it out */
+ }
+}
+
+/* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */
+
+PUBLIC void mEwGw()
+{
+ ++mcount;
+ Ew(&target);
+ getcomma();
+ Gw(&source);
+ oprefix = 0x0;
+ buildregular();
+}
+
+/* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */
+
+PUBLIC void mExGx()
+{
+ ++mcount;
+ Ex(&target);
+ getcomma();
+ Gx(&source);
+ yes_samesize();
+ opcode |= segword;
+ buildregular();
+}
+
+PUBLIC void mf_inher()
+{
+ mcount += 0x2;
+ postb = REG_MOD | (opcode & ~REG_MOD);
+ opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6);
+ if (opcode == ESCAPE_OPCODE_BASE)
+ opcode = ESCAPE_OPCODE_BASE | 0x6; /* fix up encoding of fcompp */
+}
+
+/* [fldenv fnsave fnstenv frstor] mem */
+
+PUBLIC void mf_m()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size != 0x0)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* [fldcw fnstcw] mem2i */
+
+PUBLIC void mf_m2()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size != 0x0 && source.size != 0x2)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* fnstsw [mem2i ax] */
+
+PUBLIC void mf_m2_ax()
+{
+ if (getaccumreg(&target))
+ {
+ if (target.base != AXREG)
+ kgerror(ILLREG);
+ else
+ {
+ opcode = 0x74;
+ target.base = ST0REG; /* fake, really ax */
+ buildfreg();
+ }
+ }
+ else
+ mf_m2();
+}
+
+/* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */
+
+PUBLIC void mf_m2_m4()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x2)
+ opcode |= 0x40;
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* [fild fistp] [mem2i mem4i mem8i] */
+
+PUBLIC void mf_m2_m4_m8()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x2)
+ opcode |= 0x40;
+ else if (source.size == 0x8)
+ opcode |= 0x45; /* low bits 0 -> 5 and 3 -> 7 */
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* [fcom fcomp] [mem4r mem8r optional-st(i)] */
+
+PUBLIC void mf_m4_m8_optst()
+{
+ if (sym == EOLSYM)
+ {
+ target.base = ST1REG;
+ buildfreg();
+ }
+ else
+ mf_m4_m8_st();
+}
+
+/* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */
+
+PUBLIC void mf_m4_m8_stst()
+{
+ target.base = fpregchk();
+ if (target.base != NOREG)
+ {
+ getcomma();
+ source.base = fpregchk();
+ if (source.base == NOREG)
+ {
+ error(FP_REG_REQ);
+ source.base = ST0REG;
+ }
+ if (target.base == ST0REG)
+ target.base = source.base;
+ else
+ {
+ if (source.base != ST0REG)
+ error(ILL_FP_REG_PAIR);
+ opcode |= 0x40;
+ if ((opcode & 0x07) >= 0x4)
+ opcode ^= 0x01; /* weird swap of fdiv/fdivr, fsub/fsubr */
+ }
+ buildfreg();
+ }
+ else
+ {
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x8)
+ opcode |= 0x40;
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+ }
+}
+
+/* fst [mem4r mem8r st(i)] */
+
+PUBLIC void mf_m4_m8_st()
+{
+ target.base = fpregchk();
+ if (target.base != NOREG)
+ {
+ if (opcode == FST_ENCODED)
+ opcode |= 0x40;
+ buildfreg();
+ }
+ else
+ {
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x8)
+ opcode |= 0x40;
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+ }
+}
+
+/* [fld fstp] [mem4r mem8r mem10r st(i)] */
+
+PUBLIC void mf_m4_m8_m10_st()
+{
+ target.base = fpregchk();
+ if (target.base != NOREG)
+ {
+ if (opcode == FSTP_ENCODED)
+ opcode |= 0x40;
+ buildfreg();
+ }
+ else
+ {
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x8)
+ opcode |= 0x40;
+ else if (source.size == 0xA)
+ opcode |= 0x25; /* low bits 0 -> 5 and 3 -> 7 */
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+ }
+}
+
+/* [fbld fbstp] mem10r */
+
+PUBLIC void mf_m10()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size != 0xA)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* ffree st(i) */
+
+PUBLIC void mf_st()
+{
+ target.base = fpregchk();
+ if (target.base == NOREG)
+ kgerror(FP_REG_REQ);
+ buildfreg();
+}
+
+/* [fucom fucomp fxch] optional-st(i) */
+
+PUBLIC void mf_optst()
+{
+ if (sym == EOLSYM)
+ {
+ target.base = ST1REG;
+ buildfreg();
+ }
+ else
+ mf_st();
+}
+
+/* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */
+
+PUBLIC void mf_stst()
+{
+ target.base = fpregchk();
+ if (target.base == NOREG)
+ {
+ kgerror(FP_REG_REQ);
+ return;
+ }
+ getcomma();
+ source.base = fpregchk();
+ if (source.base == NOREG)
+ {
+ kgerror(FP_REG_REQ);
+ return;
+ }
+ if (source.base != ST0REG)
+ {
+ kgerror(ILL_FP_REG);
+ return;
+ }
+ buildfreg();
+}
+
+PUBLIC void mf_w_inher()
+{
+ sprefix = WAIT_OPCODE;
+ mf_inher();
+}
+
+/* [fsave fstenv] mem */
+
+PUBLIC void mf_w_m()
+{
+ sprefix = WAIT_OPCODE;
+ mf_m();
+}
+
+/* fstcw mem2i */
+
+PUBLIC void mf_w_m2()
+{
+ sprefix = WAIT_OPCODE;
+ mf_m2();
+}
+
+/* fstsw [mem2i ax] */
+
+PUBLIC void mf_w_m2_ax()
+{
+ sprefix = WAIT_OPCODE;
+ mf_m2_ax();
+}
+
+/* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */
+
+PUBLIC void mgroup1()
+{
+ getbinary();
+ notsegorspecreg(&source);
+ if (mcount != 0x0)
+ {
+ if (source.base == NOREG)
+ {
+ if (target.indcount == 0x0 && (target.base == ALREG ||
+ target.base == AXREG ||
+ target.base == EAXREG &&
+ (source.displ.data & (FORBIT | RELBIT | UNDBIT) ||
+ !is8bitsignedoffset(source.displ.offset))))
+ {
+ opcode |= 0x04 | segword;
+ buildimm(&source, FALSE);
+ }
+ else
+ {
+ buildunary(0x80 | segword);
+ buildimm(&source, TRUE);
+ }
+ }
+ else
+ {
+ opcode |= direction | segword;
+ buildregular();
+ }
+ }
+}
+
+/* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */
+
+PUBLIC void mgroup2()
+{
+ ++mcount;
+ Ex(&target);
+ buildsegword(&target);
+ getshift(&source);
+ if (mcount != 0x0)
+ {
+ buildunary(0xD0 | segword);
+ if (source.base == CLREG)
+ opcode |= 0x2;
+ else if (source.displ.offset != 0x1)
+ {
+ opcode -= 0x10;
+ source.size = 0x1;
+ buildimm(&source, FALSE);
+ }
+ }
+}
+
+/* LLDT, LTR, SLDT, STR, VERR, VERW */
+
+PUBLIC void mgroup6()
+{
+ ++mcount;
+ Ew(&target);
+ oprefix = 0x0;
+ buildunary(0x0);
+}
+
+/* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */
+
+PUBLIC void mgroup7()
+{
+ ++mcount;
+ if (opcode == 0x20 || opcode == 0x30)
+ {
+ Ew(&target);
+ oprefix = 0x0;
+ }
+ else
+ {
+ getindirect(&target);
+ oprefix = 0x0;
+ if (target.size != 0x0 && target.size != 0x6)
+ error(MISMATCHED_SIZE); /* XXX - size 6 wrong for INVLPG? */
+ }
+ buildunary(0x1);
+}
+
+/* BT, BTR, BTS, BTC */
+
+PUBLIC void mgroup8()
+{
+ ++mcount;
+ Ev(&target);
+ getcomma();
+ /* Gv or Ib */
+ getea(&source);
+ notindirect(&source);
+ notsegorspecreg(&source);
+ if (mcount != 0x0)
+ {
+ if (source.base == NOREG)
+ {
+ buildunary(0xBA);
+ source.size = 0x1;
+ buildimm(&source, TRUE);
+ }
+ else
+ {
+ yes_samesize();
+ opcode += 0x83;
+ buildregular();
+ }
+ }
+}
+
+/* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */
+
+PUBLIC void mGvEv()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ Ev(&target);
+ yes_samesize();
+ buildregular();
+}
+
+/* bound [r16,m16&16 r32,m32&32] */
+
+PUBLIC void mGvMa()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ getindirect(&target);
+ yes_samesize();
+ buildregular();
+}
+
+/* LDS, LES, LFS, LGS, LSS */
+
+PUBLIC void mGvMp()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ getindirect(&target);
+ if (target.size != 0x0 && target.size != 0x2 + source.size)
+ error(MISMATCHED_SIZE);
+ buildregular();
+}
+
+/* IMUL */
+
+PUBLIC void mimul()
+{
+ ++mcount;
+ Ex(&target);
+ if (sym != COMMA)
+ {
+ buildsegword(&target);
+ buildunary(0xF6 | segword);
+ return;
+ }
+ getcomma();
+ notindirect(&target);
+ source = target; /* direction is swapped */
+ getea(&target);
+ notsegorspecreg(&target);
+ yes_samesize();
+ if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG))
+ {
+ page = PAGE1_OPCODE;
+ ++mcount;
+ opcode = 0xAF;
+ buildregular();
+ }
+ else
+ {
+ if (sym == COMMA)
+ {
+ getsym();
+ getea(&source2);
+ yesimmed(&source2);
+ }
+ else
+ {
+ source2 = target;
+ target = source;
+ }
+ source2.size = target.size;
+ if (is8bitsignedoffset(source2.displ.offset))
+ {
+ source2.size = 0x1;
+ opcode = 0x6B;
+ }
+ else
+ {
+ source2.size = target.size;
+ opcode = 0x69;
+ }
+ buildregular();
+ if (mcount != 0x0)
+ buildimm(&source2, FALSE);
+ }
+}
+
+/* IN */
+
+PUBLIC void min()
+{
+ ++mcount;
+ if (opcode & WORDBIT) /* inw; ind not supported */
+ mnsize = 0x2;
+ if (sym == EOLSYM && mnsize != 0x0)
+ target.size = mnsize;
+ else
+ {
+ if (getaccumreg(&target))
+ {
+ if (mnsize != 0x0 && regsize[target.base] != mnsize)
+ error(MISMATCHED_SIZE);
+ getcomma();
+ }
+ else
+ target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG];
+ opcode |= regsegword[target.base];
+ if (!getdxreg(&source))
+ {
+ getimmed(&source, 0x1);
+ opcode -= 0x8;
+ }
+ }
+ if (target.size > 0x1 && target.size != defsize)
+ oprefix = 0x66;
+}
+
+/* DEC, INC */
+
+PUBLIC void mincdec()
+{
+ ++mcount;
+ Ex(&target);
+ buildsegword(&target);
+ if (target.indcount == 0x0 && segword == WORDBIT)
+ opcode |= 0x40 | rm[target.base];
+ else
+ buildunary(0xFE | segword);
+}
+
+/* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */
+/* MOVSW, OUTSW, SCASW, STOSW */
+
+PUBLIC void minher16()
+{
+ minher();
+ if (defsize != 0x2)
+ oprefix = 0x66;
+}
+
+/* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */
+/* MOVSD, OUTSD, SCASD, STOSD */
+
+PUBLIC void minher32()
+{
+ minher();
+ if (defsize != 0x4)
+ oprefix = 0x66;
+}
+
+/* AAD, AAM */
+
+PUBLIC void minhera()
+{
+ ++mcount;
+ if (sym == EOLSYM)
+ {
+ target.displ.offset = 0xA;
+ target.size = 0x1;
+ buildimm(&target, FALSE);
+ }
+ else
+ getimmed(&target, 0x1);
+}
+
+/* INT */
+
+PUBLIC void mint()
+{
+ ++mcount;
+ getimmed(&target, 0x1);
+ if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) &&
+ (opcode_t) immadr.offset == 0x3)
+ {
+ immcount = 0x0;
+ opcode = 0xCC;
+ }
+}
+
+/* JCC */
+
+PUBLIC void mjcc()
+{
+ if (jumps_long && opcode < 0x80) /* above 0x80 means loop - not long */
+ mbcc();
+ else
+ mshort();
+}
+
+/* JCXZ, JECXZ */
+
+PUBLIC void mjcxz()
+{
+ if (opcode != defsize)
+ {
+ aprefix = 0x67;
+ ++mcount; /* quick fix - mshort() needs to know */
+ }
+ opcode = 0xE3;
+ mshort();
+ if (aprefix != 0x0)
+ --mcount; /* quick fix - main routine bumps it again */
+}
+
+/* LEA */
+
+PUBLIC void mlea()
+{
+ Gv(&source); /* back to front */
+ getcomma();
+ ++mcount;
+ getindirect(&target);
+ yes_samesize();
+ buildregular();
+}
+
+/* MOV */
+
+PUBLIC void mmov()
+{
+ getbinary();
+ if (segword >= SEGMOV)
+ {
+ oprefix = 0x0;
+ notimmed(&source);
+ if (segword > SEGMOV) /* special reg */
+ notindirect(&target);
+ }
+ if (mcount != 0x0)
+ {
+ if (target.base == NOREG && target.index == NOREG &&
+ (source.base == ALREG || source.base == AXREG ||
+ source.base == EAXREG))
+ {
+ opcode = 0xA0 | (direction ^ TOREGBIT) | segword;
+ lastexp = target.displ;
+ if ((source.size = displsize(&target)) != defsize)
+ aprefix = 0x67;
+ mcount += source.size;
+ }
+ else if (source.base == NOREG)
+ {
+ if (target.indcount == 0x0)
+ opcode = 0xB0 | (segword << 0x3) | rm[target.base];
+ else
+ {
+ buildea(&target);
+ opcode = 0xC6 | segword;
+ }
+ buildimm(&source, FALSE);
+ }
+ else
+ {
+ if (isspecreg(source.base))
+ {
+ page = PAGE1_OPCODE;
+ ++mcount;
+ opcode = 0x0;
+ }
+ opcode |= direction | segword;
+ buildregular();
+ }
+ }
+}
+
+/* MOVSX, MOVZX */
+
+PUBLIC void mmovx()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ Ex(&target);
+ if (target.size == 0x0)
+ kgerror(SIZE_UNK);
+ if (target.size > 0x2)
+ kgerror(ILL_SIZE);
+ oprefix = 0x0;
+ if (source.size != defsize)
+ oprefix = 0x66;
+ buildsegword(&target);
+ opcode |= segword;
+ buildregular();
+}
+
+/* NEG, NOT */
+
+PUBLIC void mnegnot()
+{
+ ++mcount;
+ Ex(&target);
+ buildsegword(&target);
+ buildunary(0xF6 | segword);
+}
+
+/* OUT */
+
+PUBLIC void mout()
+{
+ ++mcount;
+ if (opcode & WORDBIT) /* outw; outd not supported */
+ mnsize = 0x2;
+ if (sym == EOLSYM && mnsize != 0x0)
+ source.size = mnsize;
+ else
+ {
+ if (!getdxreg(&target))
+ {
+ getimmed(&target, 0x1);
+ opcode -= 0x8;
+ }
+ if (sym == COMMA)
+ {
+ getsym();
+ if (!getaccumreg(&source))
+ kgerror(AL_AX_EAX_EXP);
+ else if (mnsize != 0x0 && regsize[source.base] != mnsize)
+ error(MISMATCHED_SIZE);
+ }
+ else
+ source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG];
+ opcode |= regsegword[source.base];
+ }
+ if (source.size > 0x1 && source.size != defsize)
+ oprefix = 0x66;
+}
+
+/* POP, PUSH */
+
+PUBLIC void mpushpop()
+{
+ opcode_t oldopcode;
+
+ ++mcount;
+ getea(&target);
+ buildsegword(&target);
+ notbytesize(&target);
+ if ((oldopcode = opcode) == POP_OPCODE)
+ {
+ notimmed(&target);
+ if (target.base == CSREG)
+ kgerror(ILL_SEG_REG);
+ }
+ if (mcount != 0x0)
+ {
+ if (target.indcount == 0x0)
+ {
+ if (segword == SEGMOV)
+ {
+ switch (target.base)
+ {
+ case CSREG:
+ opcode = 0x0E;
+ break;
+ case DSREG:
+ opcode = 0x1E;
+ break;
+ case ESREG:
+ opcode = 0x06;
+ break;
+ case SSREG:
+ opcode = 0x16;
+ break;
+ case FSREG:
+ opcode = 0xA0;
+ page = PAGE1_OPCODE;
+ ++mcount;
+ break;
+ case GSREG:
+ opcode = 0xA8;
+ page = PAGE1_OPCODE;
+ ++mcount;
+ break;
+ }
+ if (oldopcode == POP_OPCODE)
+ ++opcode;
+ }
+ else if (target.base != NOREG)
+ {
+ opcode = 0x50 | rm[target.base];
+ if (oldopcode == POP_OPCODE)
+ opcode |= 0x8;
+ }
+ else
+ {
+ opcode = 0x68;
+ if (oldopcode == POP_OPCODE)
+ ++opcode;
+ buildimm(&target, TRUE);
+ }
+ }
+ else
+ {
+ buildea(&target);
+ if (oldopcode == PUSH_OPCODE)
+ postb |= 0x6 << REG_SHIFT;
+ }
+ }
+}
+
+/* RET, RETF */
+
+PUBLIC void mret()
+{
+ ++mcount;
+ if (sym != EOLSYM)
+ {
+ --opcode;
+ getimmed(&target, 0x2);
+ }
+}
+
+/* SEG CS/DS/ES/FS/GS/SS */
+
+PUBLIC void mseg()
+{
+ reg_pt reg;
+
+ if (regsegword[reg = regchk()] != SEGMOV)
+ error(SEG_REG_REQ);
+ else
+ {
+ getsym();
+ ++mcount;
+ opcode = (segoverride - CSREG)[reg];
+ }
+}
+
+/* SETCC */
+
+PUBLIC void msetcc()
+{
+ ++mcount;
+ Eb(&target);
+ if (mcount != 0x0)
+ buildea(&target);
+}
+
+/* SHLD, SHRD */
+
+PUBLIC void mshdouble()
+{
+ ++mcount;
+ Ev(&target);
+ getcomma();
+ Gv(&source);
+ yes_samesize();
+ buildregular();
+ getshift(&source2);
+ lastexp = target.displ; /* getshift() wiped it out */
+ if (mcount != 0x0)
+ {
+ if (source2.base == CLREG)
+ opcode |= 0x1;
+ else
+ {
+ source2.size = 0x1;
+ buildimm(&source2, FALSE);
+ }
+ }
+}
+
+/*
+ TEST
+ Similar to the regular group1 operators.
+ It does not allow the sign extended immediate byte forms
+ and does not use the relevant direction bit.
+*/
+
+PUBLIC void mtest()
+{
+ getbinary();
+ notsegorspecreg(&source);
+ if (source.base == NOREG)
+ {
+ if (mcount != 0x0)
+ {
+ if (target.indcount == 0x0
+ && (target.base == ALREG || target.base == AXREG
+ || target.base == EAXREG))
+ opcode = 0xA8 | segword;
+ else
+ {
+ buildea(&target);
+ opcode = 0xF6 | segword;
+ }
+ }
+ buildimm(&source, FALSE);
+ }
+ else
+ {
+ opcode |= segword;
+ buildregular();
+ }
+}
+
+/*
+ XCHG
+ Similar to the regular group1 operators.
+ It does not allow any of the immediate forms
+ and does not use the irrelevant direction bit.
+*/
+
+PUBLIC void mxchg()
+{
+ getbinary();
+ notimmed(&source);
+ notsegorspecreg(&source);
+ if (target.indcount == 0x0)
+ {
+ if (target.base == AXREG || target.base == EAXREG)
+ {
+ opcode = 0x90 + rm[source.base];
+ return;
+ }
+ if (source.base == AXREG || source.base == EAXREG)
+ {
+ opcode = 0x90 + rm[target.base];
+ return;
+ }
+ }
+ opcode |= segword;
+ buildregular();
+}
+
+PRIVATE void notbytesize(eap)
+register struct ea_s *eap;
+{
+ if (eap->size == 0x1)
+ kgerror(ILL_SIZE);
+}
+
+PRIVATE void notimmed(eap)
+register struct ea_s *eap;
+{
+ if (eap->indcount == 0x0 && eap->base == NOREG)
+ kgerror(ILL_IMM_MODE);
+}
+
+PRIVATE void notindirect(eap)
+register struct ea_s *eap;
+{
+ if (eap->indcount != 0x0)
+ kgerror(ILL_IND);
+}
+
+PRIVATE void notsegorspecreg(eap)
+register struct ea_s *eap;
+{
+ if (regsegword[eap->base] >= SEGMOV)
+ kgerror(ILLREG);
+}
+
+PRIVATE void yesimmed(eap)
+register struct ea_s *eap;
+{
+ if (eap->indcount == 0x1)
+ eap->indcount = 0x0;
+ if (eap->indcount != 0x0 || eap->base != NOREG)
+ kgerror(IMM_REQ);
+}
+
+PRIVATE void yes_samesize()
+{
+ if (target.size == 0x0)
+ target.size = source.size;
+ else if (source.size != 0x0 && target.size != source.size)
+ kgerror(MISMATCHED_SIZE);
+}
+
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* 6809 opcode constants */
+
+/* bits for indexed addressing */
+
+#define INDIRECTBIT 0x10
+#define INDEXBIT 0x80 /* except 5 bit offset */
+#define PCRELBIT 0x04 /* PC relative (in certain cases) */
+#define RRBITS 0x60 /* register select bits */
+
+PRIVATE opcode_t rrindex[] = /* register and index bits for indexed adr */
+{
+ 0x60 | INDEXBIT, /* S */
+ 0x40 | INDEXBIT, /* U */
+ 0x00 | INDEXBIT, /* X */
+ 0x20 | INDEXBIT, /* Y */
+ PCRELBIT | INDEXBIT, /* PC */
+};
+
+PRIVATE opcode_t pushpull[] = /* push/pull codes */
+{
+ 0x40, /* S */
+ 0x40, /* U */
+ 0x10, /* X */
+ 0x20, /* Y */
+ 0x80, /* PC */
+ 0x02, /* A */
+ 0x04, /* B */
+ 0x01, /* CC */
+ 0x08, /* DP */
+ 0x06, /* D */
+};
+
+PRIVATE opcode_t tfrexg1[] = /* transfer/exchange codes for source reg */
+{
+ 0x40, /* S */
+ 0x30, /* U */
+ 0x10, /* X */
+ 0x20, /* Y */
+ 0x50, /* PC */
+ 0x80, /* A */
+ 0x90, /* B */
+ 0xA0, /* CC */
+ 0xB0, /* DP */
+ 0x00, /* D */
+};
+
+PRIVATE opcode_t tfrexg2[] = /* transfer/exchange codes for target reg */
+{
+ 0x04, /* S */
+ 0x03, /* U */
+ 0x01, /* X */
+ 0x02, /* Y */
+ 0x05, /* PC */
+ 0x08, /* A */
+ 0x09, /* B */
+ 0x0A, /* CC */
+ 0x0B, /* DP */
+ 0x00, /* D */
+};
+
+FORWARD void checkpostinc P((void));
+FORWARD void doaltind P((void));
+FORWARD void do1altind P((void));
+FORWARD void fixupind P((void));
+FORWARD void getindexnopost P((void));
+FORWARD void inderror P((error_pt errnum));
+FORWARD reg_pt indreg P((reg_pt maxindex));
+FORWARD void predec1 P((void));
+FORWARD void sustack P((reg_pt stackreg));
+
+PRIVATE void checkpostinc()
+{
+ if (sym == ADDOP)
+ {
+ if (postb & INDIRECTBIT)
+ inderror(ILLMOD); /* single-inc indirect illegal */
+ else
+ {
+ lastexp.offset &= 0xFF00; /* for printing if postbyte is 0: ,X+ */
+ getsym();
+ }
+ }
+ else if (sym == POSTINCOP)
+ {
+ postb |= 0x1;
+ getsym();
+ }
+ else
+ postb |= 0x4;
+ fixupind();
+}
+
+/* common code for all-mode ops, alterable-mode ops, indexed ops */
+
+PRIVATE void doaltind()
+{
+ mcount += 0x2;
+ if (sym == LBRACKET)
+ {
+ postb = INDIRECTBIT;
+ getsym();
+ do1altind();
+ if (sym != RBRACKET)
+ error(RBEXP);
+ }
+ else
+ do1altind();
+}
+
+PRIVATE void do1altind()
+{
+ bool_t byteflag; /* set if direct or short indexed adr forced */
+ char *oldlineptr;
+ char *oldsymname;
+ reg_pt reg;
+ bool_t wordflag; /* set if extended or long indexed adr forced*/
+
+ if ((reg = regchk()) != NOREG)
+ {
+ switch (reg)
+ {
+ case AREG:
+ postb |= 0x86;
+ break;
+ case BREG:
+ postb |= 0x85;
+ break;
+ case DREG:
+ postb |= 0x8B;
+ break;
+ default:
+ if (indreg(MAXINDREG) != NOREG)
+ checkpostinc();
+ return;
+ }
+ getsym();
+ if (sym != COMMA)
+ inderror(COMEXP);
+ else
+ getindexnopost();
+ return;
+ }
+ else if (sym == SUBOP) /* could be -R or - in expression */
+ {
+ oldlineptr = lineptr; /* save state */
+ oldsymname = symname;
+ getsym();
+ reg = regchk();
+ lineptr = oldlineptr;
+ symname = oldsymname;
+ if (reg != NOREG)
+ {
+ predec1(); /* it's -R */
+ return;
+ }
+ sym = SUBOP;
+ }
+ else if (sym == COMMA)
+ {
+ postb |= INDEXBIT;
+ getsym();
+ if (sym == SUBOP)
+ {
+ predec1();
+ return;
+ }
+ else if (sym != PREDECOP)
+ {
+ if (indreg(MAXINDREG) != NOREG)
+ checkpostinc();
+ return;
+ }
+ }
+ if (sym == PREDECOP)
+ {
+ postb |= 0x83;
+ getindexnopost();
+ return;
+ }
+
+ /* should have expression */
+
+ wordflag = byteflag = FALSE;
+ if (sym == LESSTHAN)
+ {
+ /* context-sensitive, LESSTHAN means byte-sized here */
+ byteflag = TRUE;
+ getsym();
+ }
+ else if (sym == GREATERTHAN)
+ {
+ /* context-sensitive, GREATERTHAN means word-sized here */
+ wordflag = TRUE;
+ getsym();
+ }
+ expres();
+ if (sym == COMMA)
+ { /* offset from register */
+ getsym();
+ if ((reg = indreg(PCREG)) == NOREG)
+ return;
+ postb |= 0x8; /* default 8 bit offset */
+ if (reg == PCREG)
+ {
+ reldata();
+ if (!(lastexp.data & (RELBIT | UNDBIT)))
+ {
+ lastexp.offset = lastexp.offset - lc;
+ if (page != 0x0)
+ lastexp.offset -= 0x4; /* extra for instruction */
+ else
+ lastexp.offset -= 0x3; /* 3 byte instruction
+ assuming 8 bit offset */
+ }
+ }
+ if (byteflag)
+ {
+ if (!(lastexp.data & (RELBIT | UNDBIT)) &&
+ !is8bitsignedoffset(lastexp.offset))
+ error(ABOUNDS); /* forced short form is impossible */
+ ++mcount;
+ }
+ else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
+ !is8bitsignedoffset(lastexp.offset))
+ { /* 16 bit offset */
+ if (postb & PCRELBIT && !(lastexp.data & RELBIT))
+ --lastexp.offset; /* instruction 1 longer than already
+ allowed */
+ postb |= 0x1;
+ mcount += 0x2;
+ }
+ else if (!(postb & PCRELBIT) &&
+ (offset_t) (lastexp.offset + 0x10) < 0x20 &&
+ !(postb & INDIRECTBIT && lastexp.offset != 0x0))
+ { /* 5 bit offset */
+ postb &= RRBITS | INDIRECTBIT;
+ if (lastexp.offset == 0x0)
+ postb |= 0x84; /* index with zero offset */
+ else
+ postb |= (lastexp.offset & 0x1F);
+ }
+ else /* 8 bit offset */
+ ++mcount;
+ fixupind();
+ }
+ else if (postb & INDIRECTBIT)
+ { /* extended indirect */
+ postb = 0x9F;
+ mcount += 0x2;
+ fixupind();
+ }
+ else if (postb & INDEXBIT)
+ inderror(ILLMOD); /* e.g. LEAX $10 */
+ else
+ {
+ if (byteflag || !wordflag && !(lastexp.data & (FORBIT | RELBIT)) &&
+ (lastexp.offset >> 0x8) == dirpag)
+ { /* direct addressing */
+ if (opcode >= 0x80)
+ opcode |= 0x10;
+ }
+ else /* extended addressing */
+ {
+ if (opcode < 0x80)
+ opcode |= 0x70;
+ else
+ opcode |= 0x30;
+ ++mcount;
+ if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) &&
+ !(lastexp.data & IMPBIT) &&
+ lastexp.offset + (0x81 - 0x3) < 0x101)
+ /* JSR or JMP could be done with BSR or BRA */
+ error(SHORTB);
+ }
+ }
+}
+
+PRIVATE void fixupind()
+{
+ if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */
+ {
+ if (opcode < 0x80)
+ opcode |= 0x60;
+ else
+ opcode |= 0x20;
+ }
+}
+
+PRIVATE void getindexnopost()
+{
+ getsym();
+ if (indreg(MAXINDREG) != NOREG)
+ fixupind();
+}
+
+PRIVATE void inderror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ if (postb & INDIRECTBIT)
+ sym = RBRACKET; /* fake right bracket to kill further errors */
+ fixupind();
+}
+
+/* check current symbol is an index register (possibly excepting PC) */
+/* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */
+/* otherwise generate error, return FALSE */
+
+PRIVATE reg_pt indreg(maxindex)
+reg_pt maxindex;
+{
+ reg_pt reg;
+
+ if ((reg = regchk()) == NOREG)
+ inderror(IREGEXP);
+ else if (reg > maxindex)
+ {
+ inderror(ILLREG);
+ reg = NOREG;
+ }
+ else
+ {
+ postb |= rrindex[reg];
+ getsym();
+ }
+ return reg;
+}
+
+/* all-mode ops */
+
+PUBLIC void mall()
+{
+ if (sym == IMMEDIATE)
+ mimmed();
+ else
+ malter();
+}
+
+/* alterable mode ops */
+
+PUBLIC void malter()
+{
+ postb = 0x0; /* not yet indexed or indirect */
+ doaltind();
+}
+
+/* indexed mode ops */
+
+PUBLIC void mindex()
+{
+ postb = INDEXBIT; /* indexed but not yet indirect */
+ doaltind();
+}
+
+/* immediate ops */
+
+PUBLIC void mimmed()
+{
+ opcode_t nybble;
+
+ mcount += 0x2;
+ if (sym != IMMEDIATE)
+ error(ILLMOD);
+ else
+ {
+ if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 ||
+ nybble == 0xC || nybble >= 0xE))
+ ++mcount; /* magic for long immediate */
+ symexpres();
+ if (pass2 && mcount <= 0x2)
+ {
+ chkabs();
+ checkdatabounds();
+ }
+ }
+}
+
+/* long branches */
+
+PUBLIC void mlong()
+{
+ mcount += 0x3; /* may be 0x0 or 0x1 here */
+ expres();
+ if (pass2)
+ {
+ reldata();
+ if (!(lastexp.data & (RELBIT | UNDBIT)))
+ {
+ lastexp.offset = lastexp.offset - lc - lcjump;
+ if (!(lastexp.data & IMPBIT) &&
+ lastexp.offset + 0x81 < 0x101)
+ error(SHORTB); /* -0x81 to 0x7F, warning */
+ }
+ }
+}
+
+/* PSHS and PULS */
+
+PUBLIC void msstak()
+{
+ sustack(SREG);
+}
+
+/* TFR and EXG */
+
+PUBLIC void mswap()
+{
+ reg_pt reg;
+
+ mcount = 0x2;
+ if ((reg = regchk()) == NOREG)
+ error(REGEXP);
+ else
+ {
+ postb = tfrexg1[reg];
+ getsym();
+ if (sym != COMMA)
+ error(COMEXP);
+ else
+ {
+ getsym();
+ if ((reg = regchk()) == NOREG)
+ error(REGEXP);
+ else if ((postb |= tfrexg2[reg])
+ & 0x88 && (postb & 0x88) != 0x88)
+ error(ILLREG); /* registers not of same size */
+ }
+ }
+}
+
+/* PSHU and PULU */
+
+PUBLIC void mustak()
+{
+ sustack(UREG);
+}
+
+PRIVATE void predec1()
+{
+ if (postb & INDIRECTBIT)
+ inderror(ILLMOD); /* single-dec indirect illegal */
+ else
+ {
+ postb |= 0x82;
+ getindexnopost();
+ }
+}
+
+/* common routine for PSHS/PULS/PSHU/PULU */
+
+PRIVATE void sustack(stackreg)
+reg_pt stackreg;
+{
+ reg_pt reg;
+
+ mcount = 0x2;
+ while ((reg = regchk()) != NOREG)
+ {
+ if (reg == stackreg)
+ {
+ error(ILLREG); /* cannot stack self */
+ break;
+ }
+ postb |= pushpull[reg];
+ getsym();
+ if (sym != COMMA)
+ break;
+ getsym();
+ }
+}
+
+#endif /* MC6809 */
+
+/* routines common to all processors */
+
+PUBLIC void getcomma()
+{
+ if (sym != COMMA)
+ error(COMEXP);
+ else
+ getsym();
+}
+
+/* inherent ops */
+
+/* for I80386 */
+/* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */
+/* INVD, */
+/* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */
+/* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */
+
+PUBLIC void minher()
+{
+ ++mcount;
+}
+
+/* short branches */
+
+PUBLIC void mshort()
+{
+ nonimpexpres();
+ mshort2();
+}
+
+PRIVATE void mshort2()
+{
+ mcount += 0x2;
+ if (pass2)
+ {
+ reldata();
+ if (lastexp.data & RELBIT)
+ showrelbad();
+ else if (!(lastexp.data & UNDBIT))
+ {
+ lastexp.offset = lastexp.offset - lc - mcount;
+ if (!is8bitsignedoffset(lastexp.offset))
+ error(ABOUNDS);
+ }
+ }
+}
+
+/* check if current symbol is a register, return register number or NOREG */
+
+PRIVATE reg_pt regchk()
+{
+ register struct sym_s *symptr;
+
+ if (sym == IDENT)
+ {
+ if ((symptr = gsymptr)->type & MNREGBIT)
+ {
+ if (symptr->data & REGBIT)
+ {
+#ifdef I80386
+ if (symptr->value_reg_or_op.reg == ST0REG && !fpreg_allowed)
+ error(FP_REG_NOT_ALLOWED);
+#endif
+ return symptr->value_reg_or_op.reg;
+ }
+ }
+ else if (!(symptr->type & (LABIT | MACBIT | VARBIT)))
+ symptr->data |= FORBIT; /* show seen in advance */
+ }
+ return NOREG;
+}
+
+/* convert lastexp.data for PC relative */
+
+PRIVATE void reldata()
+{
+ if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM))
+ {
+ if ((lastexp.data ^ lcdata) & RELBIT)
+ showrelbad(); /* rel - abs is weird, abs - rel is bad */
+ else
+ {
+ pcrflag = OBJ_R_MASK;
+ lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT;
+ /* segment is that of lastexp.data */
+ }
+ }
+ else /* same file, segment and relocation */
+ lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM);
+}
diff --git a/bin86-0.3/as/opcode.h b/bin86-0.3/as/opcode.h
new file mode 100644
index 0000000..1e96079
--- /dev/null
+++ b/bin86-0.3/as/opcode.h
@@ -0,0 +1,162 @@
+/*
+ * bin86/as/opcode.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* opcode.h - routine numbers and special opcodes for assembler */
+
+enum
+{
+/* Pseudo-op routine numbers.
+ * Conditionals are first - this is used to test if op is a conditional.
+ */
+ ELSEOP,
+ ELSEIFOP,
+ ELSEIFCOP,
+ ENDIFOP,
+ IFOP,
+ IFCOP,
+
+#define MIN_NONCOND ALIGNOP
+ ALIGNOP,
+ BLKWOP,
+ BLOCKOP,
+ BSSOP,
+ COMMOP,
+ COMMOP1,
+ DATAOP,
+ ENDBOP,
+ ENTEROP,
+ ENTRYOP,
+ EQUOP,
+ EVENOP,
+ EXPORTOP,
+ FAILOP,
+ FCBOP,
+ FCCOP,
+ FDBOP,
+ FQBOP,
+ GETOP,
+ GLOBLOP,
+ IDENTOP,
+ IMPORTOP,
+ LCOMMOP,
+ LCOMMOP1,
+ LISTOP,
+ LOCOP,
+ MACLISTOP,
+ MACROOP,
+ MAPOP,
+ ORGOP,
+ PROCEOFOP,
+ RMBOP,
+ SECTOP,
+ SETOP,
+ SETDPOP,
+ TEXTOP,
+#ifdef I80386
+ USE16OP,
+ USE32OP,
+#endif
+ WARNOP,
+
+/* Machine-op routine numbers. */
+#ifdef I80386
+ BCC,
+ BSWAP,
+ CALL,
+ CALLI,
+ DIVMUL,
+ ENTER,
+ EwGw,
+ ExGx,
+ F_INHER,
+ F_M,
+ F_M2,
+ F_M2_AX,
+ F_M2_M4,
+ F_M2_M4_M8,
+ F_M4_M8_OPTST,
+ F_M4_M8_ST,
+ F_M4_M8_STST,
+ F_M4_M8_M10_ST,
+ F_M10,
+ F_OPTST,
+ F_ST,
+ F_STST,
+ F_W_INHER,
+ F_W_M,
+ F_W_M2,
+ F_W_M2_AX,
+ GROUP1,
+ GROUP2,
+ GROUP6,
+ GROUP7,
+ GROUP8,
+ GvEv,
+ GvMa,
+ GvMp,
+ IMUL,
+ IN,
+ INCDEC,
+ INHER,
+ INHER16,
+ INHER32,
+ INHER_A,
+ INT,
+ JCC,
+ JCXZ,
+ LEA,
+ MOV,
+ MOVX,
+ NEGNOT,
+ OUT,
+ PUSHPOP,
+ RET,
+ SEG,
+ SETCC,
+ SH_DOUBLE,
+ TEST,
+ XCHG,
+#endif /* I80386 */
+
+#ifdef MC6809
+ ALL, /* all address modes allowed, like LDA */
+ ALTER, /* all but immediate, like STA */
+ IMMED, /* immediate only (ANDCC, ORCC) */
+ INDEXD, /* indexed (LEA's) */
+ INHER, /* inherent, like CLC or CLRA */
+ LONG, /* long branches */
+ SHORT, /* short branches */
+ SSTAK, /* S-stack (PSHS, PULS) */
+ SWAP, /* TFR, EXG */
+ USTAK, /* U-stack (PSHU,PULU) */
+#endif /* MC6809 */
+};
+
+/* Special opcodes. */
+#ifdef I80386
+# define CMP_OPCODE_BASE 0x38
+# define CMPSB_OPCODE 0xA6
+# define CMPSW_OPCODE 0xA7
+# define ESCAPE_OPCODE_BASE 0xD8
+# define FST_ENCODED 0x12
+# define FSTP_ENCODED 0x13
+# define JMP_OPCODE 0xE9
+# define JMP_SHORT_OPCODE 0xEB
+# define JSR_OPCODE 0xE8
+# define MOVSB_OPCODE 0xA4
+# define MOVSW_OPCODE 0xA5
+# define PAGE1_OPCODE 0x0F
+# define POP_OPCODE 0x8F
+# define PUSH_OPCODE 0xFF
+# define WAIT_OPCODE 0x9B
+#endif
+
+#ifdef MC6809
+# define JMP_OPCODE 0x7E
+# define JSR_OPCODE 0xBD
+# define PAGE1_OPCODE 0x10
+# define PAGE2_OPCODE 0x11
+#endif
diff --git a/bin86-0.3/as/pops.c b/bin86-0.3/as/pops.c
new file mode 100644
index 0000000..a475df6
--- /dev/null
+++ b/bin86-0.3/as/pops.c
@@ -0,0 +1,977 @@
+/*
+ * bin86/as/pops.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* pops.c - handle pseudo-ops for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "flag.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+
+PRIVATE bool_t elseflag; /* set if ELSE/ELSEIF are enabled */
+ /* depends on zero = FALSE init */
+PRIVATE bool_t lcommflag;
+
+FORWARD void bumpsem P((struct flags_s *flagptr));
+FORWARD void constdata P((unsigned size));
+FORWARD void docomm P((void));
+FORWARD void doelseif P((pfv func));
+FORWARD void doequset P((int labits));
+FORWARD void doentexp P((int entbits, int impbits));
+FORWARD void doif P((pfv func));
+FORWARD struct sym_s *needlabel P((void));
+FORWARD void showredefinedlabel P((void));
+FORWARD void setloc P((unsigned seg));
+
+PRIVATE void bumpsem(flagptr)
+register struct flags_s *flagptr;
+{
+ int newcount;
+
+ if (flagptr->global &&pass != 0)
+ {
+ /* bump semaphore count by an expression (default 1), */
+ /* then set currentflag iff semaphore count is plus */
+ if (sym == EOLSYM)
+ lastexp.offset = 1;
+ else
+ {
+ absexpres();
+ if (lastexp.data & UNDBIT)
+ return;
+ }
+ newcount = (int) lastexp.offset;
+#ifdef I80386 /* really sizeof (offset_t) != sizeof (int) */
+ if (newcount != lastexp.offset)
+ datatoobig();
+#endif
+ newcount += flagptr->semaphore;
+ if ((int) lastexp.offset >= 0)
+ {
+ if (newcount < flagptr->semaphore)
+ {
+ error(COUNTOV);
+ newcount = 0x7fff;
+ }
+ }
+ else if (newcount >= flagptr->semaphore)
+ {
+ error(COUNTUN);
+ newcount = -0x8000;
+ }
+ flagptr->semaphore = newcount;
+ flagptr->current = newcount >= 0;
+ }
+}
+
+/* check symbol is either undefined */
+/* or has the same segment & relocatability as lc */
+
+PUBLIC bool_pt checksegrel(symptr)
+register struct sym_s *symptr;
+{
+ if ((symptr->type & LABIT ||
+ symptr->data & IMPBIT && !(symptr->data & UNDBIT)) &&
+ ((symptr->data ^ lcdata) & (RELBIT | SEGM)))
+ {
+ error(SEGREL);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* check address fits in 1 byte (possibly with sign truncated) */
+
+PUBLIC void checkdatabounds()
+{
+ if (!(lastexp.data & UNDBIT) &&
+ (offset_t) (lastexp.offset + 0x80) >= 0x180)
+ datatoobig();
+}
+
+/* allocate constant data (zero except for size 1), default zero for size 1 */
+
+PRIVATE void constdata(size)
+unsigned size;
+{
+ offset_t remaining;
+
+ absexpres();
+ if (!((lcdata |= lastexp.data) & UNDBIT))
+ {
+ lcjump = lastexp.offset * size;
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ if (size == 1 && sym == COMMA)
+ {
+ symabsexpres();
+ checkdatabounds();
+ for (remaining = lcjump; remaining != 0; --remaining)
+ {
+ putbin((opcode_pt) lastexp.offset); /* fill byte */
+ putabs((opcode_pt) lastexp.offset);
+ }
+ lastexp.offset = lcjump;
+ }
+ else
+ accumulate_rmb(lastexp.offset * size);
+ }
+}
+
+PUBLIC void datatoobig()
+{
+ error(DBOUNDS);
+}
+
+/* common routine for COMM/.COMM */
+
+PRIVATE void docomm()
+{
+ register struct sym_s *labptr;
+
+ absexpres(); /* if undefined, value 0 and size unchanged */
+ labptr = label;
+ if (checksegrel(labptr))
+ {
+ if (labptr->type & (EXPBIT | LABIT))
+ labelerror(ALREADY);
+ else
+ {
+ if (!(labptr->type & COMMBIT) ||
+ lastexp.offset > labptr->value_reg_or_op.value)
+ labptr->value_reg_or_op.value = lastexp.offset;
+ labptr->type |= COMMBIT;
+ if (lcommflag)
+ labptr->type |= REDBIT; /* kludge - COMMBIT | REDBIT => SA */
+ labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT);
+ showlabel();
+ }
+ }
+ lcommflag = FALSE;
+}
+
+/* common routine for ELSEIF/ELSEIFC */
+
+PRIVATE void doelseif(func)
+pfv func;
+{
+ if (iflevel == 0)
+ error(ELSEIFBAD);
+ else
+ {
+ ifflag = FALSE;
+ if (elseflag)
+ {
+ (*func) ();
+ if (!(lastexp.data & UNDBIT) && lastexp.offset != 0)
+ /* expression valid and TRUE, enable assembling */
+ {
+ ifflag = TRUE;
+ elseflag = FALSE;
+ }
+ }
+ }
+}
+
+/* common routine for EQU/SET */
+
+PRIVATE void doequset(labits)
+unsigned char labits;
+{
+ register struct sym_s *labptr;
+ unsigned char olddata;
+ unsigned char oldtype;
+
+ labptr = label;
+ /* set up new label flags in case labe isl used in expression */
+ labptr->type = (oldtype = labptr->type) | labits;
+ labptr->data = (olddata = labptr->data) & ~IMPBIT;
+ /* non-imported now */
+ nonimpexpres();
+ lastexp.data |= olddata & FORBIT; /* take all but FORBIT from
+ expression */
+ if (oldtype & LABIT && !(olddata & UNDBIT))
+ /* this is a previously defined label */
+
+ /*
+ redefinition only allowed if same relocatability, segment and
+ value
+ */
+ {
+ if ((olddata ^ lastexp.data) & (RELBIT | UNDBIT) ||
+ labptr->value_reg_or_op.value != lastexp.offset)
+ {
+ showredefinedlabel();
+ return;
+ }
+ }
+ labptr->data = lastexp.data;
+ labptr->value_reg_or_op.value = lastexp.offset;
+ showlabel();
+}
+
+/* common routine for ENTRY/EXPORT */
+
+PRIVATE void doentexp(entbits, impbits)
+unsigned char entbits;
+unsigned char impbits;
+{
+ struct sym_s *symptr;
+
+ while (TRUE)
+ {
+ if ((symptr = needlabel()) != NULL)
+ {
+ if (symptr->type & COMMBIT)
+ error(ALREADY);
+ else if (impbits != 0)
+ {
+ if (pass != 0)
+ ;
+ else if (symptr->type & (EXPBIT | LABIT))
+ symptr->type |= EXPBIT;
+ else
+ {
+ symptr->type |= REDBIT;
+ if (!(symptr->data & IMPBIT))
+ symptr->data |= IMPBIT | SEGM;
+ }
+ }
+ else
+ {
+ if (pass != 0)
+ {
+ if (!(symptr->type & LABIT))
+ error(UNLAB);
+ }
+ else
+ {
+ symptr->type |= entbits | EXPBIT;
+ symptr->data &= ~IMPBIT;
+ }
+ }
+ }
+ getsym();
+ if (sym != COMMA)
+ break;
+ getsym();
+ }
+}
+
+/* common routine for IF/IFC */
+
+PRIVATE void doif(func)
+pfv func;
+{
+ if (iflevel >= MAXIF)
+ error(IFOV);
+ else
+ {
+ ++iflevel;
+ --ifstak;
+ ifstak->elseflag = elseflag;
+ elseflag = FALSE; /* prepare */
+
+
+ /* parse the argument.
+ * [Fare] moved it here to allow nested if's, as
+ * the argument must be parsed even if we are not assembling !
+ */
+ (*func) ();
+
+ if ((ifstak->ifflag = ifflag) != FALSE)
+ /* else not assembling before, so not now & no ELSE's */
+ {
+ /* [Fari]: was here! (*func) (); */
+ if (!(lastexp.data & UNDBIT) && lastexp.offset == 0)
+ /* else expression invalid or FALSE, don't change flags */
+ {
+ ifflag = FALSE; /* not assembling */
+ elseflag = TRUE;/* but ELSE will change that */
+ }
+ }
+ }
+}
+
+PUBLIC void fatalerror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ skipline();
+ listline();
+ finishup();
+}
+
+/* swap position with label position, do error, put back posn */
+/* also clear label ptr */
+
+PUBLIC void labelerror(errnum)
+error_pt errnum;
+{
+ struct sym_s *oldgsymptr;
+ char *oldlineptr;
+ unsigned char oldsym;
+ char *oldsymname;
+
+ oldgsymptr = gsymptr;
+ oldlineptr = lineptr;
+ oldsym = sym;
+ oldsymname = symname;
+ lineptr = linebuf;
+ getsym(); /* 1st symbol is label or symbol after
+ * missing one */
+ error(errnum);
+ gsymptr = oldgsymptr;
+ lineptr = oldlineptr;
+ sym = oldsym;
+ symname = oldsymname;
+ label = NULL;
+}
+
+PRIVATE struct sym_s *needlabel()
+{
+ register struct sym_s *symptr;
+
+ if (sym != IDENT ||
+ (symptr = gsymptr)->type & (MACBIT | MNREGBIT | VARBIT))
+ {
+ error(LABEXP);
+ return NULL;
+ }
+ return symptr;
+}
+
+/* .ALIGN pseudo-op */
+
+PUBLIC void palign()
+{
+ absexpres();
+ if (!((lcdata |= lastexp.data) & UNDBIT))
+ {
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ if (lastexp.offset != 0 &&
+ (lcjump = lc % lastexp.offset) != 0)
+ accumulate_rmb(lcjump = lastexp.offset - lcjump);
+ }
+}
+
+/* .BLKW pseudo-op */
+
+PUBLIC void pblkw()
+{
+ constdata(2);
+}
+
+/* BLOCK pseudo-op */
+
+PUBLIC void pblock()
+{
+ if (blocklevel >= MAXBLOCK)
+ error(BLOCKOV);
+ else
+ {
+ register struct block_s *blockp;
+
+ ++blocklevel;
+ blockp = blockstak;
+ blockstak = --blockp;
+ blockp->data = lcdata;
+ blockp->dp = dirpag;
+ blockp->lc = lc;
+ porg(); /* same as ORG apart from stacking */
+ }
+}
+
+/* .BSS pseudo-op */
+
+PUBLIC void pbss()
+{
+ setloc(BSSLOC);
+}
+
+/* COMM pseudo-op */
+
+PUBLIC void pcomm()
+{
+ if (label == NULL)
+ labelerror(MISLAB);
+ else if (label->type & VARBIT)
+ labelerror(VARLAB); /* variable cannot be COMM'd */
+ else
+ docomm();
+}
+
+/* .COMM pseudo-op */
+
+PUBLIC void pcomm1()
+{
+ unsigned oldseg;
+
+ if (label != NULL)
+ labelerror(ILLAB);
+ oldseg = lcdata & SEGM;
+ setloc(BSSLOC);
+ if ((label = needlabel()) != NULL && checksegrel(label))
+ {
+ /* Like import. */
+ if (label->type & (EXPBIT | LABIT))
+ error(ALREADY);
+ else
+ label->data = lcdata | (FORBIT | IMPBIT | RELBIT);
+ getsym();
+ getcomma();
+ if (label->type & (EXPBIT | LABIT))
+ absexpres(); /* just to check it */
+ else
+ docomm();
+ }
+ setloc(oldseg);
+}
+
+/* .DATA pseudo-op */
+
+PUBLIC void pdata()
+{
+ setloc(DATALOC);
+}
+
+/* ELSE pseudo-op */
+
+PUBLIC void pelse()
+{
+ if (iflevel == 0)
+ error(ELSEBAD);
+ else
+ {
+ ifflag = FALSE; /* assume ELSE disabled */
+ if (elseflag)
+ {
+ ifflag = TRUE; /* ELSE enabled */
+ elseflag = FALSE;
+ }
+ }
+}
+
+/* ELSEIF pseudo-op */
+
+PUBLIC void pelseif()
+{
+ doelseif(absexpres);
+}
+
+/* ELSEIFC pseudo-op */
+
+PUBLIC void pelsifc()
+{
+ doelseif(scompare);
+}
+
+/* ENDB pseudo-op */
+
+PUBLIC void pendb()
+{
+ if (label != NULL)
+ labelerror(ILLAB);
+ if (blocklevel == 0)
+ error(ENDBBAD);
+ else
+ {
+ register struct block_s *blockp;
+
+ blockp = blockstak;
+ lcdata = blockp->data;
+ dirpag = blockp->dp;
+ accumulate_rmb(blockp->lc - lc);
+ lc = blockp->lc;
+ --blocklevel;
+ blockstak = blockp + 1;
+ }
+}
+
+/* ENDIF pseudo-op */
+
+PUBLIC void pendif()
+{
+ if (iflevel == 0)
+ error(ENDIFBAD);
+ else
+ {
+ ifflag = ifstak->ifflag;
+ elseflag = ifstak->elseflag;
+ ++ifstak;
+ --iflevel;
+ }
+}
+
+/* ENTER pseudo-op */
+
+PUBLIC void penter()
+{
+ if (!(pedata & UNDBIT))
+ error(REENTER);
+ else
+ {
+ if (!((pedata = (pedata & ~UNDBIT) | lcdata) & UNDBIT))
+ {
+ progent = lc;
+ popflags = POPLC;
+ }
+ }
+}
+
+/* ENTRY pseudo-op */
+
+PUBLIC void pentry()
+{
+ doentexp(ENTBIT, 0);
+}
+
+/* EQU pseudo-op */
+
+PUBLIC void pequ()
+{
+ register struct sym_s *labptr;
+
+ if ((labptr = label) == NULL)
+ labelerror(MISLAB);
+ else if (labptr->type & COMMBIT)
+ showredefinedlabel(); /* common cannot be EQU'd */
+ else if (labptr->type & VARBIT)
+ labelerror(VARLAB); /* variable cannot be EQU'd */
+ else
+ doequset(LABIT);
+}
+
+/* .EVEN pseudo-op */
+
+PUBLIC void peven()
+{
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ accumulate_rmb(lcjump = lastexp.data = lc & 1);
+}
+
+/* EXPORT pseudo-op */
+
+PUBLIC void pexport()
+{
+ doentexp(0, 0);
+}
+
+/* FAIL pseudo-op */
+
+PUBLIC void pfail()
+{
+ error(FAILERR);
+}
+
+/* FCB pseudo-op */
+
+PUBLIC void pfcb()
+{
+ char *bufptr;
+ offset_t firstbyte;
+
+ bufptr = databuf.fcbuf;
+ absexpres();
+ firstbyte = lastexp.offset;
+ while (TRUE)
+ {
+ checkdatabounds();
+ *bufptr++ = lastexp.offset;
+ ++mcount; /* won't overflow, line length limits it */
+ if (sym != COMMA)
+ break;
+ symabsexpres();
+ }
+ lastexp.offset = firstbyte;
+ popflags = POPLO | POPLC;
+ fcflag = TRUE;
+}
+
+/* FCC pseudo-op */
+
+PUBLIC void pfcc()
+{
+ register char *bufptr;
+ unsigned char byte;
+ char delimiter;
+ register char *reglineptr;
+
+ bufptr = databuf.fcbuf;
+ reglineptr = symname;
+ if ((delimiter = *reglineptr) != EOLCHAR)
+ ++reglineptr;
+ while (TRUE)
+ {
+ if (*reglineptr == EOLCHAR)
+ {
+ symname = reglineptr;
+ error(DELEXP);
+ break;
+ }
+ if (*reglineptr == delimiter)
+ {
+ if (*++reglineptr != delimiter)
+ break;
+ }
+ else if (*reglineptr == '\\' && reglineptr[1] != EOLCHAR)
+ ++reglineptr;
+ if ((byte = *reglineptr) < ' ')
+ {
+ symname = reglineptr;
+ error(CTLINS);
+ byte = ' ';
+ }
+ *bufptr++ = byte;
+ ++reglineptr;
+ }
+ lineptr = reglineptr;
+ getsym();
+ if (bufptr > databuf.fcbuf)
+ {
+ lastexp.offset = databuf.fcbuf[0]; /* show 1st char only */
+ mcount = bufptr - databuf.fcbuf;
+ /* won't overflow, line length limits it */
+ fcflag = TRUE;
+ popflags = POPLO | POPLC;
+ }
+}
+
+/* FDB pseudo-op */
+
+PUBLIC void pfdb()
+{
+ struct address_s *adrptr;
+ unsigned firstdata;
+ offset_t firstword;
+
+ adrptr = databuf.fdbuf;
+ expres();
+ firstword = lastexp.offset;
+ firstdata = lastexp.data;
+ while (TRUE)
+ {
+ *adrptr++ = lastexp;
+ mcount += 2; /* won't overflow, line length limits it */
+ if (sym != COMMA)
+ break;
+ symexpres();
+ }
+ lastexp.offset = firstword;
+ lastexp.data = firstdata;
+ popflags = POPHI | POPLO | POPLC;
+ fdflag = TRUE;
+}
+
+#if SIZEOF_OFFSET_T > 2
+
+/* FQB pseudo-op */
+
+PUBLIC void pfqb()
+{
+ struct address_s *adrptr;
+ offset_t firstdata;
+ offset_t firstword;
+
+ adrptr = databuf.fqbuf;
+ expres();
+ firstword = lastexp.offset;
+ firstdata = lastexp.data;
+ while (TRUE)
+ {
+ *adrptr++ = lastexp;
+ mcount += 4; /* won't overflow, line length limits it */
+ if (sym != COMMA)
+ break;
+ symexpres();
+ }
+ lastexp.offset = firstword;
+ lastexp.data = firstdata;
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ fqflag = TRUE;
+}
+
+#endif /* SIZEOF_OFFSET_T > 2 */
+
+/* .GLOBL pseudo-op */
+
+PUBLIC void pglobl()
+{
+ if (binaryg)
+ error(NOIMPORT);
+ doentexp(0, IMPBIT);
+}
+
+/* IDENT pseudo-op (not complete) */
+
+PUBLIC void pident()
+{
+ if (sym != IDENT)
+ error(LABEXP);
+ else
+ getsym_nolookup(); /* should save ident string */
+}
+
+/* IF pseudo-op */
+
+PUBLIC void pif()
+{
+ doif(absexpres);
+}
+
+/* IFC pseudo-op */
+
+PUBLIC void pifc()
+{
+ doif(scompare);
+}
+
+/* IMPORT pseudo-op */
+
+PUBLIC void pimport()
+{
+ struct sym_s *symptr;
+
+ if (binaryg)
+ error(NOIMPORT);
+ while (TRUE)
+ {
+ if ((symptr = needlabel()) != NULL && checksegrel(symptr))
+ {
+ if (symptr->type & (COMMBIT | EXPBIT | LABIT))
+ /* IMPORT is null if label (to be) declared */
+ error(ALREADY);
+ else
+ /* get current segment from lcdata, no need to mask rest */
+ symptr->data = lcdata | (FORBIT | IMPBIT | RELBIT);
+ }
+ getsym();
+ if (sym != COMMA)
+ break;
+ getsym();
+ }
+}
+
+/* LCOMM pseudo-op */
+
+PUBLIC void plcomm()
+{
+ lcommflag = TRUE;
+ pcomm();
+}
+
+/* .LCOMM pseudo-op */
+
+PUBLIC void plcomm1()
+{
+ lcommflag = TRUE;
+ pcomm1();
+}
+
+/* .LIST pseudo-op */
+
+PUBLIC void plist()
+{
+ bumpsem(&list);
+}
+
+/* LOC pseudo-op */
+
+PUBLIC void ploc()
+{
+ if (label != NULL)
+ labelerror(ILLAB);
+ absexpres();
+ if (!(lastexp.data & UNDBIT))
+ {
+ if (lastexp.offset >= NLOC)
+ datatoobig();
+ else
+ setloc((unsigned) lastexp.offset);
+ }
+}
+
+/* .MACLIST pseudo-op */
+
+PUBLIC void pmaclist()
+{
+ bumpsem(&maclist);
+}
+
+/* .MAP pseudo-op */
+
+PUBLIC void pmap()
+{
+ absexpres();
+ if (!(lastexp.data & UNDBIT))
+ {
+ mapnum = lastexp.offset;
+ popflags = POPLO;
+ if (lastexp.offset >= 0x100)
+ datatoobig();
+ }
+}
+
+/* ORG pseudo-op */
+
+PUBLIC void porg()
+{
+ if (label != NULL)
+ labelerror(ILLAB);
+ absexpres();
+ if (!((lcdata = lastexp.data) & UNDBIT))
+ {
+ accumulate_rmb(lastexp.offset - lc);
+ binmbuf = lc = lastexp.offset;
+ popflags = POPLC;
+ }
+}
+
+/* RMB pseudo-op */
+
+PUBLIC void prmb()
+{
+ constdata(1);
+}
+
+/* .SECT pseudo-op */
+
+PUBLIC void psect()
+{
+ if (label != NULL)
+ labelerror(ILLAB);
+ while (sym == IDENT)
+ {
+ if (!(gsymptr->type & MNREGBIT))
+ error(ILL_SECTION);
+ else switch (gsymptr->value_reg_or_op.op.routine)
+ {
+ case BSSOP:
+ pbss();
+ break;
+ case DATAOP:
+ pdata();
+ break;
+ case TEXTOP:
+ ptext();
+ break;
+ default:
+ error(ILL_SECTION);
+ break;
+ }
+ getsym();
+ if (sym == COMMA)
+ getsym();
+ }
+}
+
+/* SET pseudo-op */
+
+PUBLIC void pset()
+{
+ register struct sym_s *labptr;
+
+ if ((labptr = label) == NULL)
+ labelerror(MISLAB);
+ else if (labptr->type & COMMBIT)
+ labelerror(RELAB); /* common cannot be SET'd */
+ else
+ doequset(labptr->type & LABIT ? 0 : VARBIT);
+}
+
+/* SETDP pseudo-op */
+
+PUBLIC void psetdp()
+{
+ absexpres();
+ if (!(lastexp.data & UNDBIT))
+ {
+ dirpag = lastexp.offset;
+ popflags = POPLO;
+ if (lastexp.offset >= 0x100)
+ datatoobig();
+ }
+}
+
+/* .TEXT pseudo-op */
+
+PUBLIC void ptext()
+{
+ setloc(TEXTLOC);
+}
+
+/* .WARN pseudo-op */
+
+PUBLIC void pwarn()
+{
+ bumpsem(&warn);
+}
+
+#ifdef I80386
+
+/* USE16 pseudo-op */
+
+PUBLIC void puse16()
+{
+ defsize = 2;
+}
+
+/* USE16 pseudo-op */
+
+PUBLIC void puse32()
+{
+ defsize = 4;
+}
+
+#endif
+
+/* show redefined label and error, and set REDBIT */
+
+PRIVATE void showredefinedlabel()
+{
+ register struct sym_s *labptr;
+
+ labptr = label; /* showlabel() will kill label prematurely */
+ showlabel();
+ if (!(labptr->type & REDBIT))
+ {
+ labptr->type |= REDBIT;
+ labelerror(RELAB);
+ }
+}
+
+PUBLIC void showlabel()
+{
+ register struct sym_s *labptr;
+
+ labptr = label;
+ lastexp.data = labptr->data;
+ lastexp.offset = labptr->value_reg_or_op.value;
+ popflags = POPLONG | POPHI | POPLO;
+ label = NULL; /* show handled by COMM, EQU or SET */
+}
+
+/* set location segment */
+
+PRIVATE void setloc(seg)
+unsigned seg;
+{
+ if (pass != 0 && seg != (lcdata & SEGM))
+ putobj(seg | OBJ_SET_SEG);
+ {
+ register struct lc_s *lcp;
+
+ lcp = lcptr;
+ lcp->data = lcdata;
+ lcp->lc = lc;
+ lcptr = lcp = lctab + (unsigned char) seg;
+ lcdata = (lcp->data & ~SEGM) | (unsigned char) seg;
+ binmbuf = lc = lcp->lc;
+ popflags = POPLC;
+ }
+}
diff --git a/bin86-0.3/as/proto.h b/bin86-0.3/as/proto.h
new file mode 100644
index 0000000..0b70a4b
--- /dev/null
+++ b/bin86-0.3/as/proto.h
@@ -0,0 +1,256 @@
+/*
+ * bin86/as/proto.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* extern functions */
+
+#if __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+/* as.c */
+int main P((int argc, char **argv));
+void as_abort P((char *message));
+void finishup P((void));
+void initp1p2 P((void));
+
+/* assemble.c */
+void assemble P((void));
+
+/* error.c */
+char *build_error_message P((error_pt errnum, char *buf));
+
+/* express.c */
+void absexpres P((void));
+void chkabs P((void));
+void nonimpexpres P((void));
+void showrelbad P((void));
+void symabsexpres P((void));
+void symexpres P((void));
+void expres P((void));
+void factor P((void));
+void scompare P((void));
+
+/* genbin.c */
+void binheader P((void));
+void bintrailer P((void));
+void genbin P((void));
+void initbin P((void));
+void putbin P((opcode_pt c));
+
+/* genlist.c */
+char *build_2hex_number P((unsigned num, char *where));
+char *build_number P((unsigned num, unsigned width, char *where));
+void error P((error_pt errnum));
+void listline P((void));
+void writec P((int c));
+void writenl P((void));
+void writeoff P((offset_t offset));
+void writes P((char *s));
+void writesn P((char *s));
+void writew P((unsigned word));
+
+/* genobj.c */
+void accumulate_rmb P((offset_t offset));
+void flushobj P((void));
+void genobj P((void));
+void initobj P((void));
+void objheader P((void));
+void objtrailer P((void));
+void putabs P((opcode_pt c));
+void putobj P((opcode_pt c));
+
+/* gensym.c */
+void gensym P((void));
+
+/* macro.c */
+void entermac P((struct sym_s *symptr));
+void pmacro P((void));
+
+/* mops.c */
+#ifdef I80386
+void mbcc P((void));
+void mbswap P((void));
+void mcall P((void));
+void mcalli P((void));
+void mdivmul P((void));
+void menter P((void));
+void mEwGw P((void));
+void mExGx P((void));
+void mf_inher P((void));
+void mf_m P((void));
+void mf_m2 P((void));
+void mf_m2_ax P((void));
+void mf_m2_m4 P((void));
+void mf_m2_m4_m8 P((void));
+void mf_m4_m8_optst P((void));
+void mf_m4_m8_st P((void));
+void mf_m4_m8_stst P((void));
+void mf_m4_m8_m10_st P((void));
+void mf_m10 P((void));
+void mf_optst P((void));
+void mf_st P((void));
+void mf_stst P((void));
+void mf_w_inher P((void));
+void mf_w_m P((void));
+void mf_w_m2 P((void));
+void mf_w_m2_ax P((void));
+void mgroup1 P((void));
+void mgroup2 P((void));
+void mgroup6 P((void));
+void mgroup7 P((void));
+void mgroup8 P((void));
+void mGvEv P((void));
+void mGvMa P((void));
+void mGvMp P((void));
+void mimul P((void));
+void min P((void));
+void mincdec P((void));
+void minher P((void));
+void minher16 P((void));
+void minher32 P((void));
+void minhera P((void));
+void mint P((void));
+void mjcc P((void));
+void mjcxz P((void));
+void mlea P((void));
+void mmov P((void));
+void mmovx P((void));
+void mnegnot P((void));
+void mout P((void));
+void mpushpop P((void));
+void mret P((void));
+void mseg P((void));
+void msetcc P((void));
+void mshdouble P((void));
+void mtest P((void));
+void mxchg P((void));
+#endif /* I80386 */
+
+#ifdef MC6809
+void mall P((void));
+void malter P((void));
+void mimmed P((void));
+void mindex P((void));
+void minher P((void));
+void mlong P((void));
+void msstak P((void));
+void mswap P((void));
+void mustak P((void));
+#endif /* MC6809 */
+
+void getcomma P((void));
+void mshort P((void));
+
+/* pops.c */
+bool_pt checksegrel P((struct sym_s *symptr));
+void checkdatabounds P((void));
+void datatoobig P((void));
+void fatalerror P((error_pt errnum));
+void labelerror P((error_pt errnum));
+void palign P((void));
+void pblkw P((void));
+void pblock P((void));
+void pbss P((void));
+void pcomm P((void));
+void pcomm1 P((void));
+void pdata P((void));
+void pelse P((void));
+void pelseif P((void));
+void pelsifc P((void));
+void pendb P((void));
+void pendif P((void));
+void penter P((void));
+void pentry P((void));
+void pequ P((void));
+void peven P((void));
+void pexport P((void));
+void pfail P((void));
+void pfcb P((void));
+void pfcc P((void));
+void pfdb P((void));
+void pfqb P((void));
+void pglobl P((void));
+void pident P((void));
+void pif P((void));
+void pifc P((void));
+void pimport P((void));
+void plcomm P((void));
+void plcomm1 P((void));
+void plist P((void));
+void ploc P((void));
+void pmaclist P((void));
+void pmap P((void));
+void porg P((void));
+void prmb P((void));
+void psect P((void));
+void pset P((void));
+void psetdp P((void));
+void ptext P((void));
+void puse16 P((void));
+void puse32 P((void));
+void pwarn P((void));
+void showlabel P((void));
+
+/* readsrc.c */
+void initsource P((void));
+fd_t open_input P((char *name));
+void pget P((void));
+void pproceof P((void));
+void readline P((void));
+void skipline P((void));
+
+/* scan.c */
+void context_hexconst P((void));
+void getsym P((void));
+void getsym_nolookup P((void));
+void initscan P((void));
+
+/* table.c */
+void inst_keywords P((void));
+struct sym_s *lookup P((void));
+void statistics P((void));
+
+/* type.c */
+void u2c2 P((char *buf, u16_pt offset));
+void u4c4 P((char *buf, u32_t offset));
+void u2cn P((char *buf, u16_pt offset, unsigned count));
+void u4cn P((char *buf, u32_t offset, unsigned count));
+bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian));
+
+char *strrchr(const char *s, int c);
+void *malloc(int c);
+
+#if 0
+/* library - fcntl.h */
+int creat P((const char *__path, int __mode));
+int open P((const char *__path, int __oflag, ...));
+
+/* library - stdlib.h */
+void abort P((void));
+void exit P((int __status));
+void *malloc P((unsigned __size));
+
+/* library - string.h */
+int memcmp P((const void *__s1, const void *__s2, unsigned __max));
+void *memset P((void *__s, int __ch, unsigned __nbytes));
+char *strchr P((const char *__s, int __ch));
+int strcmp P((const char *__s1, const char *__s2));
+char *strcpy P((char *__target, const char *__source));
+unsigned strlen P((const char *__s));
+int strncmp P((const char *__s1, const char *__s2, int __max));
+char *strrchr P((const char *__s, int __ch));
+
+/* library - unistd.h */
+char *brk P((char *__adr));
+int close P((int __fd));
+long lseek P((int __fd, long __offset, int __whence));
+int read P((int __fd, char *__buf, unsigned __nbytes));
+char *sbrk P((int __incr));
+int write P((int __fd, char *__buf, unsigned __nbytes));
+
+#endif
diff --git a/bin86-0.3/as/readsrc.c b/bin86-0.3/as/readsrc.c
new file mode 100644
index 0000000..350fc4d
--- /dev/null
+++ b/bin86-0.3/as/readsrc.c
@@ -0,0 +1,335 @@
+/*
+ * bin86/as/readsrc.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+#define MAXLINE 256 /* when this is made bigger, fix pfcc not
+ * to store the string length in a byte-
+ * sized variable */
+
+/* readsrc.c - read source files for assembler */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "const.h"
+#include "type.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+#include "macro.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "source.h"
+
+struct fcbstruct /* file control block structure */
+{
+ fd_t fd; /* file descriptor */
+ char *lineptr; /* current spot in line */
+ char *buf; /* start of buffer (after partial line) */
+ char *first; /* start of partial line before buf */
+ char *limit; /* end of used part of input buffer */
+ unsigned blocksize; /* chars from last read and partial line flag */
+ struct fbufstruct *includer;/* buffer of file which included current one */
+};
+
+struct fbufstruct /* file buffer structure */
+{
+ struct fcbstruct fcb; /* status after opening an include sub-file */
+ char fpartline[MAXLINE + 1];/* buffer for partial line */
+ char fbuf[INBUFSIZE + 1]; /* buffer to read into */
+ char fname[1]; /* file name (variable length), 1 for null */
+};
+
+struct get_s /* to record included files */
+{
+ fd_t fd;
+ unsigned line;
+ long position;
+};
+
+PRIVATE char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */
+
+PRIVATE struct get_s hid_getstak[MAXGET]; /* GET stack */
+PRIVATE struct get_s *getstak; /* ptr */
+
+PRIVATE struct fcbstruct input; /* current input file control block */
+ /* input.lineptr is not kept up to date */
+ /* input.fd depends on zero init */
+PRIVATE struct fbufstruct xyz;
+PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */
+ /* its fcb only to date in includes */
+
+PRIVATE char hid_linebuf[LINLEN]; /* line buffer */
+PRIVATE char *maclinebuf;
+PRIVATE char *maclineptr;
+
+FORWARD void clearsource P((void));
+FORWARD void line_too_long P((void));
+
+PRIVATE void clearsource()
+{
+ input.includer = inputbuf;
+ inputbuf = &xyz;
+ input.first = input.limit = input.buf = inputbuf->fbuf;
+ *(lineptr = linebuf = input.first - 1) = EOLCHAR;
+ input.blocksize = 0;
+}
+
+PRIVATE void line_too_long()
+{
+ symname = linebuf + (LINLEN - 1); /* spot for the error */
+ error(LINLONG); /* so error is shown in column LINLEN - 1 */
+}
+
+/* initialise private variables */
+
+PUBLIC void initsource()
+{
+ filnamptr = hid_filnambuf;
+ getstak = hid_getstak + MAXGET;
+ clearsource(); /* sentinel to invoke blank skipping */
+}
+
+PUBLIC fd_t open_input(name)
+char *name;
+{
+ fd_t fd;
+
+ if ((unsigned) (fd = open(name, O_RDONLY)) > 255)
+ as_abort("error opening input file");
+ clearsource();
+ return fd;
+}
+
+/*
+ handle GET pseudo_op
+ stack state of current file, open new file and reset global state vars
+ file must be seekable for the buffer discard/restore method to work
+*/
+
+PUBLIC void pget()
+{
+#if OLD
+ if (infiln >= MAXGET)
+ error(GETOV);
+ else
+ {
+ skipline();
+ listline();
+ if (infiln != 0)
+ {
+ --getstak;
+ getstak->fd = infil;
+ getstak->line = linum;
+ getstak->position = lseek(infil, 0L, 1) - (inbufend - inbufptr);
+ ++infiln;
+ linum = 0;
+ infil = open_input(lineptr - 1);
+ }
+ }
+#else
+ abort();
+#endif
+}
+
+/* process end of file */
+/* close file, unstack old file if current one is included */
+/* otherwise switch pass 0 to pass 1 or exit on pass 2 */
+/* end of file may be from phyical end of file or an END statement */
+
+PUBLIC void pproceof()
+{
+ if (infiln != 0)
+ close(infil);
+ if (lineptr == linebuf)
+ list.current = FALSE; /* don't list line after last unless error */
+ if (infiln == infil0)
+ /* all conditionals must be closed before end of main file (not GETs) */
+ {
+ if (blocklevel != 0)
+ error(EOFBLOCK);
+ if (iflevel != 0)
+ error(EOFIF);
+ if (lcdata & UNDBIT)
+ error(EOFLC);
+ lcptr->data = lcdata;
+ lcptr->lc = lc;
+ }
+ /* macros must be closed before end of all files */
+ if (macload)
+ error(EOFMAC);
+ listline(); /* last line or line after last if error */
+ if (infiln != infil0)
+ {
+ infil = getstak->fd;
+ linum = getstak->line;
+ if (--infiln != 0)
+ lseek(infil, getstak->position, 0);
+ ++getstak;
+ }
+ else if (!pass)
+ {
+ pass = TRUE;
+ objheader(); /* while pass 1 data all valid */
+ binmbuf = 0; /* reset zero variables */
+ maclevel = iflevel = blocklevel =
+ totwarn = toterr = linum = macnum = 0;
+ initp1p2(); /* reset other varaiables */
+ binaryc = binaryg;
+#ifdef I80386
+ defsize = idefsize;
+#endif
+ list.current = list.global;
+ maclist.current = maclist.global;
+
+ warn.current = TRUE;
+ if (warn.semaphore < 0)
+ warn.current = FALSE;
+ if (infiln != 0)
+ infil = open_input(filnamptr);
+ binheader();
+ }
+ else
+ finishup();
+}
+
+/*
+ read 1 line of source.
+ Source line ends with '\n', line returned is null terminated without '\n'.
+ Control characters other than blank, tab and newline are discarded.
+ Long lines (length > LINLEN) are truncated, and an error is generated.
+ On EOF, calls pproceof(), and gets next line unless loading a macro.
+ This is where macro lines are recursively expanded.
+*/
+
+PUBLIC void readline()
+{
+ listpre = FALSE; /* not listed yet */
+ if (maclevel != 0)
+ {
+ register char *bufptr; /* hold *bufptr in a reg char variable */
+ register char *reglineptr; /* if possible (not done here) */
+ char *oldbufptr;
+ struct schain_s *parameters;
+ char paramnum;
+ unsigned char remaining; /* space remaining in line + 2 */
+ /* value 0 not used except for temp predec */
+ /* value 1 means error already gen */
+ /* values 1 and 2 mean no space */
+
+ for (; maclevel != 0;
+ macpar = macstak->parameters, ++macstak, --maclevel)
+ if (*(bufptr = macstak->text) != ETB)
+ /* nonempty macro, process it and return without continuing the for loop */
+ {
+ if (!macflag)
+ {
+ maclinebuf = linebuf;
+ maclineptr = lineptr;
+ macflag = TRUE;
+ }
+ remaining = (unsigned char)LINLEN + 2;
+ lineptr = linebuf = reglineptr = hid_linebuf;
+ while (*bufptr++ != EOLCHAR)
+ {
+ if (bufptr[-1] == MACROCHAR && *bufptr >= '0' && *bufptr <= '9')
+ {
+ parameters = macstak->parameters;
+ for (paramnum = *bufptr++; paramnum-- != '0';)
+ if ((parameters = parameters->next) == NULL)
+ break;
+ if (parameters != NULL)
+ {
+ for (oldbufptr = bufptr, bufptr = parameters->string;
+ *bufptr++ != 0;)
+ {
+ if (--remaining <= 1)
+ {
+ if (remaining != 0)
+ line_too_long();
+ remaining = 1;
+ break; /* forget rest, param on 1 line */
+ }
+ *reglineptr++ = bufptr[-1];
+ }
+ bufptr = oldbufptr;
+ }
+ }
+ else
+ {
+ if (--remaining <= 1)
+ {
+ if (remaining != 0)
+ line_too_long();
+ remaining = 1;
+ }
+ else
+ *reglineptr++ = bufptr[-1];
+ }
+ }
+ macstak->text = bufptr;
+ *reglineptr = EOLCHAR;
+ return;
+ }
+ }
+ if (macflag)
+ {
+ linebuf = maclinebuf;
+ lineptr = maclineptr;
+ macflag = FALSE;
+ }
+again:
+ ++linum;
+ ++lineptr; /* if eof, this is input.limit + 1 */
+ if (input.blocksize != 0) /* and this routine just resets eof */
+ {
+ if (lineptr < input.limit) /* move back partial line */
+ {
+ register char *col;
+
+ col = input.buf;
+ while ((*--col = *--input.limit) != EOLCHAR)
+ ;
+ input.first = col + 1;
+ ++input.limit;
+ input.blocksize = 0;
+ }
+ else /* may be non-terminated line, don't stop */
+ lineptr = input.limit;
+ }
+ if (lineptr == input.limit)
+ {
+ lineptr = input.first;
+ input.blocksize = read(infil, input.buf, INBUFSIZE);
+ if (input.blocksize < 0)
+ abort();
+ if (input.blocksize == 0)
+ {
+ clearsource();
+ pproceof();
+ if (macload)
+ {
+ symname = lineptr;
+ return; /* macro not allowed across eof */
+ }
+ goto again;
+ }
+ input.first = input.buf;
+ *(input.limit = input.buf + input.blocksize) = EOLCHAR;
+ }
+ linebuf = lineptr;
+ if (lineptr >= input.limit)
+ *(lineptr = input.limit = input.buf) = EOLCHAR;
+}
+
+PUBLIC void skipline()
+{
+ register char *reglineptr;
+
+ reglineptr = lineptr - 1;
+ while (*reglineptr != EOLCHAR)
+ ++reglineptr;
+ lineptr = reglineptr;
+}
diff --git a/bin86-0.3/as/scan.c b/bin86-0.3/as/scan.c
new file mode 100644
index 0000000..d8c3cd2
--- /dev/null
+++ b/bin86-0.3/as/scan.c
@@ -0,0 +1,253 @@
+/*
+ * bin86/as/scan.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* scan.c - lexical analyser for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#undef EXTERN
+#define EXTERN
+#include "scan.h"
+
+PRIVATE int numbase; /* base for number */
+
+PRIVATE char symofchar[256] = /* table to convert chars to their symbols */
+{
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, EOLSYM, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, EOLSYM, STRINGCONST, IMMEDIATE, /* !"# */
+ HEXCONST, BINCONST, ANDOP, CHARCONST, /* $%&' */
+ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */
+ COMMA, SUBOP, IDENT, SLASH, /* ,-./ */
+
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */
+ INTCONST, INTCONST, COLON, EOLSYM, /* 89:; */
+ LESSTHAN, EQOP, GREATERTHAN, MACROARG, /* <=>? */
+
+ INDIRECT, IDENT, IDENT, IDENT, /* @ABC */
+ IDENT, IDENT, IDENT, IDENT, /* DEFG */
+ IDENT, IDENT, IDENT, IDENT, /* HIJK */
+ IDENT, IDENT, IDENT, IDENT, /* LMNO */
+ IDENT, IDENT, IDENT, IDENT, /* PQRS */
+ IDENT, IDENT, IDENT, IDENT, /* TUVW */
+ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */
+ OTHERSYM, RBRACKET, OTHERSYM, IDENT, /* \]^_ */
+
+ OTHERSYM, IDENT, IDENT, IDENT, /* `abc */
+ IDENT, IDENT, IDENT, IDENT, /* defg */
+ IDENT, IDENT, IDENT, IDENT, /* hijk */
+ IDENT, IDENT, IDENT, IDENT, /* lmno */
+ IDENT, IDENT, IDENT, IDENT, /* pqrs */
+ IDENT, IDENT, IDENT, IDENT, /* tuvw */
+ IDENT, IDENT, IDENT, OTHERSYM, /* xyz{ */
+ OROP, OTHERSYM, NOTOP, OTHERSYM, /* |}~ */
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE
+};
+
+FORWARD void intconst P((void));
+
+PUBLIC void context_hexconst()
+{
+ numbase = 16;
+ intconst();
+}
+
+PUBLIC void getsym()
+{
+ register char *reglineptr;
+
+ reglineptr = lineptr;
+advance:
+ symname = reglineptr;
+ switch (sym = symofchar[*reglineptr++])
+ {
+ case WHITESPACE:
+ goto advance;
+ case ADDOP:
+ if (*reglineptr == '+')
+ {
+ sym = POSTINCOP;
+ ++reglineptr;
+ }
+ break;
+ case BINCONST:
+ numbase = 2;
+ lineptr = reglineptr;
+ intconst();
+ return;
+ case CHARCONST:
+ if ((number = *reglineptr) < ' ')
+ number = ' ';
+ if (*reglineptr != EOL)
+ ++reglineptr;
+ sym = INTCONST;
+ break;
+ case GREATERTHAN: /* context-sensitive */
+ if (*reglineptr == '>')
+ {
+ sym = SROP;
+ ++reglineptr;
+ }
+ break;
+ case HEXCONST:
+ numbase = 16;
+ lineptr = reglineptr;
+ intconst();
+ return;
+ case IDENT:
+ /* walk to end of identifier - magic INTCONST is max of INT, IDENT */
+ while (symofchar[*reglineptr] <= INTCONST)
+ ++reglineptr;
+ lineptr = reglineptr;
+ gsymptr = lookup();
+ return;
+ case INTCONST:
+ if (*(reglineptr - 1) == '0')
+ {
+ if (*reglineptr != 'x' && *reglineptr != 'X')
+ numbase = 8;
+ else
+ {
+ numbase = 16;
+ ++reglineptr;
+ }
+ }
+ else
+ {
+ --reglineptr;
+ numbase = 10;
+ }
+ lineptr = reglineptr;
+ intconst();
+ return;
+ case LESSTHAN: /* context-sensitive */
+ if (*reglineptr == '<')
+ {
+ sym = SLOP;
+ ++reglineptr;
+ }
+ break;
+ case SUBOP:
+ if (*reglineptr == '-')
+ {
+ sym = PREDECOP;
+ ++reglineptr;
+ }
+ break;
+ }
+ lineptr = reglineptr;
+ return;
+}
+
+PUBLIC void getsym_nolookup()
+{
+ bool_t old_ifflag;
+
+ old_ifflag = ifflag;
+ ifflag = FALSE;
+ getsym();
+ ifflag = old_ifflag;
+}
+
+PRIVATE void intconst()
+{
+ register char *reglineptr;
+
+ number = 0;
+ reglineptr = lineptr;
+ for (; *reglineptr >= '0'; ++reglineptr)
+ {
+ if (*reglineptr > '9')
+ {
+ if (numbase != 16)
+ break;
+ if (*reglineptr >= 'a' && *reglineptr <= 'f')
+ {
+ if (number != 0)
+ number = numbase * number + (*reglineptr - 'a' + 10);
+ else
+ number = *reglineptr - 'a' + 10;
+ }
+ else if (*reglineptr >= 'A' && *reglineptr <= 'F')
+ {
+ if (number != 0)
+ number = numbase * number + (*reglineptr - 'A' + 10);
+ else
+ number = *reglineptr - 'A' + 10;
+ }
+ else
+ break;
+ }
+ else if (number != 0)
+ number = numbase * number + (*reglineptr - '0');
+ else
+ number = *reglineptr - '0';
+ }
+ if (*reglineptr == 'L' || *reglineptr == 'l')
+ ++reglineptr;
+ sym = INTCONST;
+ lineptr = reglineptr;
+}
+
+PUBLIC void initscan()
+{
+ if (asld_compatible)
+ {
+ lindirect = LPAREN;
+ rindexp = RPEXP;
+ rindirect = RPAREN;
+ }
+ else
+ {
+ lindirect = LBRACKET;
+ rindexp = RBEXP;
+ rindirect = RBRACKET;
+ }
+}
diff --git a/bin86-0.3/as/scan.h b/bin86-0.3/as/scan.h
new file mode 100644
index 0000000..f4421b7
--- /dev/null
+++ b/bin86-0.3/as/scan.h
@@ -0,0 +1,18 @@
+/*
+ * bin86/as/scan.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* scan.h - global variables for scanner for assembler */
+
+#define EOLCHAR '\n'
+
+EXTERN struct sym_s *gsymptr; /* global symbol ptr */
+EXTERN char lindirect; /* left symbol for indirect addressing */
+EXTERN char *lineptr; /* current line position */
+EXTERN offset_t number; /* constant number */
+EXTERN int rindexp; /* error code for missing rindirect */
+EXTERN char rindirect; /* right symbol for indirect addressing */
+EXTERN char sym; /* current symbol */
+EXTERN char *symname; /* current symbol name */
diff --git a/bin86-0.3/as/source.h b/bin86-0.3/as/source.h
new file mode 100644
index 0000000..5b4f847
--- /dev/null
+++ b/bin86-0.3/as/source.h
@@ -0,0 +1,10 @@
+/*
+ * bin86/as/source.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* source.h - global variables for source handlers for assembler */
+
+EXTERN unsigned linum; /* line # */
+EXTERN bool_t listpre; /* flag to show line has already been listed */
diff --git a/bin86-0.3/as/table.c b/bin86-0.3/as/table.c
new file mode 100644
index 0000000..eab6e4b
--- /dev/null
+++ b/bin86-0.3/as/table.c
@@ -0,0 +1,229 @@
+/*
+ * bin86/as/table.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* table.c - symbol table handler for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "scan.h"
+
+#define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */
+
+#ifdef I80386
+# ifdef MNSIZE
+EXTERN char bytesizeops[];
+# endif
+#endif
+EXTERN char ops[];
+EXTERN char page1ops[];
+EXTERN char page2ops[];
+EXTERN char regs[];
+#ifdef I80386
+EXTERN char typesizes[];
+#endif
+
+#ifdef DEBUG
+unsigned nhash;
+unsigned nlookup;
+unsigned nsym;
+unsigned nx[30];
+FORWARD void printchain P((void));
+#endif
+
+FORWARD void install P((register char *keyptr, unsigned data));
+
+PUBLIC void inst_keywords()
+{
+ install(regs, REGBIT);
+#ifdef I80386
+ install(typesizes, SIZEBIT);
+#endif
+ install(ops, 0);
+ install(page1ops, PAGE1);
+ install(page2ops, PAGE2);
+#ifdef I80386
+# ifdef MNSIZE
+ install(bytesizeops, PAGE1 | PAGE2);
+# endif
+#endif
+}
+
+PRIVATE void install(keyptr, data)
+register char *keyptr;
+unsigned data;
+{
+ char lowcasebuf[20];
+ unsigned namelength;
+ char *nameptr;
+ char *namend;
+ register struct sym_s *symptr;
+
+ while (*keyptr != 0)
+ {
+ namelength = *keyptr++;
+ lineptr = (symname = keyptr) + namelength;
+ for (nameptr = lowcasebuf, namend = lowcasebuf + namelength;
+ nameptr < namend;)
+ {
+ if (*keyptr < 'A' || *keyptr > 'Z')
+ *nameptr++ = *keyptr++;
+ else
+ *nameptr++ = *keyptr++ + ('a' - 'A');
+ }
+ symptr = lookup();
+ symptr->type = MNREGBIT;
+ symptr->data = data;
+ symptr->value_reg_or_op.op.routine = *keyptr;
+ symptr->value_reg_or_op.op.opcode = keyptr[1];
+ lineptr = (symname = lowcasebuf) + namelength;
+ symptr = lookup();
+ symptr->type = MNREGBIT;
+ symptr->data = data;
+ symptr->value_reg_or_op.op.routine = *keyptr;
+ symptr->value_reg_or_op.op.opcode = keyptr[1];
+ keyptr += 2;
+ }
+}
+
+/* Lookup() searches symbol table for the string from symname to lineptr - 1.
+ * If string is not found and ifflag is TRUE, string is added to table, with
+ * type = 0
+ * data = inidata (RELBIT | UNDBIT, possibly with IMPBIT | SEGM)
+ * Returns pointer to symbol entry (NULL if not found and not installed)
+ * unless symbol table overflows, when routine aborts.
+ */
+
+PUBLIC struct sym_s *lookup()
+{
+ struct sym_s **hashptr;
+ register char *nameptr;
+ register struct sym_s *symptr;
+ register unsigned hashval;
+ register unsigned length;
+#ifdef DEBUG
+ int tries;
+
+ ++nlookup;
+ tries = 0;
+#endif
+
+ /* Hash function is a weighted xor of 1 to 4 chars in the string.
+ * This works seems to work better than looking at all the chars.
+ * It is important that the function be fast.
+ * The string comparision function should also be fast and it helps
+ * if it is optimized for mostly identical comparisions.
+ * The multiplication by MULTIPLIER should compile as a shift.
+ */
+
+#define MULTIPLIER (SPTSIZ / (1 << USEFUL_BITS_IN_ASCII))
+#define USEFUL_BITS_IN_ASCII 6
+
+ nameptr = lineptr;
+ length = nameptr - symname;
+ if (length <= 3)
+ {
+ if (length <= 2)
+ hashval = hconv(nameptr[-1]) * MULTIPLIER;
+ else
+ hashval = hconv(nameptr[-2]) * MULTIPLIER,
+ hashval ^= hconv(nameptr[-1]);
+ }
+ else
+ hashval = hconv(nameptr[-(length / 2)]) * MULTIPLIER,
+ hashval ^= hconv(nameptr[-2]) << 2,
+ hashval ^= hconv(nameptr[-1]);
+ nameptr = symname;
+ if ((symptr = *(hashptr = spt +
+ (hashval ^ (hconv(nameptr[0]) << 1)) % SPTSIZ))
+ != NULL)
+ {
+ do
+ {
+#ifdef DEBUG
+ if (tries != 0)
+ --nx[tries];
+ ++tries;
+ if (tries < sizeof nx / sizeof nx[0])
+ ++nx[tries];
+ if (tries >= 5)
+ printchain(hashptr - spt)
+#endif
+ if ((unsigned char) length != symptr->length)
+ continue;
+ if (memcmp(symptr->name, nameptr, length) == 0)
+ return symptr;
+ }
+ while ((symptr = symptr->next) != NULL);
+
+ /* Calculate last non-NULL hash ptr.
+ * This is faster than keeping hashptr up to date in previous loop
+ * since most lookups are successful and hash ptr is not needed.
+ */
+ do
+ {
+ symptr = *hashptr;
+ hashptr = &symptr->next;
+ }
+ while (symptr->next != NULL);
+ }
+ if (!ifflag)
+ return NULL;
+ align(heapptr);
+ if (heapptr >= heapend)
+ fatalerror(SYMOV);
+#ifdef DEBUG
+ ++nsym;
+ if (hashptr >= spt && hashptr < spt + SPTSIZ)
+ ++nhash;
+#endif
+ *hashptr = symptr = (struct sym_s *) heapptr;
+ symptr->type = 0;
+ symptr->data = inidata;
+ symptr->length = length;
+ symptr->value_reg_or_op.value = (unsigned) (symptr->next = NULL);
+ heapptr = symptr->name;
+ do
+ *heapptr++ = *nameptr++;
+ while (--length != 0);
+ *heapptr++ = 0;
+ return symptr;
+}
+
+#ifdef DEBUG
+
+static void printchain(hashval)
+unsigned hashval;
+{
+ register struct sym_s *symptr;
+
+ printf("%04x ", hashval);
+ for (symptr = spt[hashval]; symptr != NULL; symptr = symptr->next)
+ printf("%s ", symptr->name);
+ printf("\n");
+}
+
+#endif
+
+PUBLIC void statistics()
+{
+#ifdef DEBUG
+ int i;
+ int weight;
+
+ for (i = 0; i < SPTSIZ; ++i)
+ printchain(i);
+ printf("nhash = %d, nsym = %d, nlookup = %d nx =\n", nhash, nsym, nlookup);
+ weight = 0;
+ for (i = 0; i < 30; ++i)
+ {
+ printf("%5d", nx[i]);
+ weight += nx[i] * i;
+ }
+ printf("\n");
+ printf("weight = %d%d\n", w;
+#endif
+}
diff --git a/bin86-0.3/as/todo b/bin86-0.3/as/todo
new file mode 100644
index 0000000..56c5424
--- /dev/null
+++ b/bin86-0.3/as/todo
@@ -0,0 +1,10 @@
+Improve string escaping.
+
+Produce bsd symbol tables.
+
+Accept gas format.
+
+Decide how to choose between 8-bit and 32-bit branches. 16-bit branches in
+32-bit mode are unusable because top 16 bits of PC are messed up.
+
+Limit insns to specified processor (warn for 386 insns on 8086).
diff --git a/bin86-0.3/as/type.h b/bin86-0.3/as/type.h
new file mode 100644
index 0000000..cb2aed5
--- /dev/null
+++ b/bin86-0.3/as/type.h
@@ -0,0 +1,177 @@
+/*
+ * bin86/as/type.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* type.h - types for assembler */
+
+/* redefine foo_t's because their use has become non-portable */
+
+#define bool_t bool_T
+#define count_t count_T
+#define fd_t fd_T
+#define indcount_t indcount_T
+#define offset_t offset_T
+#define opcode_t opcode_T
+#define opsize_t opsize_T
+#define scale_t scale_T
+#define sem_t sem_T
+#define smallcount_t smallcount_T
+#define soffset_t soffset_T
+#define u8_t u8_T
+#define u16_t u16_T
+#define u32_t u32_T
+
+typedef unsigned char bool_t;
+typedef int bool_pt; /* change to int for ANSI C */
+typedef unsigned count_t;
+typedef unsigned error_pt;
+typedef int fd_t;
+typedef unsigned char indcount_t;
+#ifdef I80386
+typedef unsigned long offset_t;
+typedef long soffset_t;
+# define SIZEOF_OFFSET_T 4 /* non-portable */
+#endif
+#ifdef MC6809
+typedef unsigned offset_t;
+typedef int soffset_t;
+# define SIZEOF_OFFSET_T 2 /* but sizeof (offset_t) often breaks cpp */
+#endif
+typedef unsigned opcode_pt;
+typedef unsigned char opcode_t;
+typedef unsigned opsize_pt;
+typedef unsigned char opsize_t;
+typedef unsigned reg_pt;
+typedef unsigned char scale_t;
+typedef unsigned char smallcount_t;
+typedef /* signed */ char sem_t;
+typedef unsigned u16_pt;
+typedef unsigned short u16_t;
+typedef unsigned long u32_pt;
+typedef unsigned long u32_t;
+
+/* symbol table entry */
+
+struct sym_s
+{
+ struct sym_s *next; /* next symbol in hash chain (NULL if none) */
+ /* zero offset because it is accessed most */
+ unsigned char type;
+ unsigned char data; /* flags valid for expressions as well as syms*/
+ union
+ {
+ offset_t value; /* value, if sym is a label */
+ unsigned char reg; /* register code, if sym is a register */
+ struct
+ {
+ unsigned char routine; /* routine number */
+ opcode_t opcode; /* opcode, if sym is a hardware op */
+ }
+ op; /* if sym is pseudo-op or hardware op */
+ }
+ value_reg_or_op;
+ unsigned char length; /* length of symbol string */
+ char name[1]; /* string of variable length */
+};
+
+/* address */
+
+struct address_s
+{
+ offset_t offset;
+ unsigned char data;
+ struct sym_s *sym;
+};
+
+#ifdef I80386
+
+/* effective address */
+
+struct ea_s
+{
+ indcount_t indcount;
+ opsize_t size;
+ reg_pt base;
+ reg_pt index;
+ scale_t scale;
+ struct address_s displ;
+};
+
+#endif
+
+/* flags */
+
+struct flags_s
+{
+ bool_t global;
+ bool_t current;
+ int semaphore;
+};
+
+/* location counter */
+
+struct lc_s
+{
+ unsigned char data;
+ offset_t lc;
+};
+
+/* string chain */
+
+struct schain_s
+{
+ struct schain_s *next;
+ char string[2]; /* variable length */
+};
+
+/* block stack */
+
+struct block_s
+{
+ unsigned char data;
+ unsigned char dp;
+ offset_t lc;
+};
+
+/* if stack */
+
+struct if_s
+{
+ bool_t ifflag;
+ bool_t elseflag;
+};
+
+/* macro stack */
+
+struct macro_s
+{
+ char *text;
+ struct schain_s *parameters;
+};
+
+/* symbol listing format */
+
+struct sym_listing_s
+{
+ char name[SYMLIS_NAMELEN];
+ char zname[2];
+ char segm[1];
+ char pad1[1];
+ char value[4];
+ char pad2[1];
+ char ar[1];
+ char pad3[1];
+ char cein[1];
+ char pad4[1];
+ char nullterm;
+};
+
+#if __STDC__
+typedef void (*pfv)(void);
+#else
+typedef void (*pfv)();
+#endif
+
+#include "proto.h"
diff --git a/bin86-0.3/as/work/q b/bin86-0.3/as/work/q
new file mode 100644
index 0000000..0f6fefe
--- /dev/null
+++ b/bin86-0.3/as/work/q
@@ -0,0 +1,4 @@
+for i in $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s
+do
+ $a/as $i -3 -w -u
+done
diff --git a/bin86-0.3/as/work/r b/bin86-0.3/as/work/r
new file mode 100644
index 0000000..aca1637
--- /dev/null
+++ b/bin86-0.3/as/work/r
@@ -0,0 +1,4 @@
+for i in $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s
+do
+ $lb/as $i -3 -w -u
+done
diff --git a/bin86-0.3/as/work/r-good b/bin86-0.3/as/work/r-good
new file mode 100644
index 0000000..1fa22e6
--- /dev/null
+++ b/bin86-0.3/as/work/r-good
@@ -0,0 +1,1183 @@
+sgdt sidt sldt _aprefix _oprefix
+sgdt sidt sldt _aprefix _oprefix
+.byte CBW JB JNBE .C9
+sgdt sidt sldt _aprefix _oprefix
+edx sal _notimmed _getimmed _yesimmed
+sgdt sidt sldt _aprefix _oprefix _getshift
+sgdt sidt sldt _aprefix _oprefix _getshift
+sgdt sidt sldt _aprefix _oprefix _getshift
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+LCOMM REPE STOW .4 .4A
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+edx sal _notimmed _getimmed _yesimmed
+edx sal _notimmed _getimmed _yesimmed
+INC JNA REPNE SETNC .131
+edx sal _notimmed _getimmed _yesimmed
+edx sal _notimmed _getimmed _yesimmed
+qword outsd rcrb rorb _mdivmul
+JNL ROL CMPB .2D .140
+BNE INW JMPI LOOPNE .141
+dr0 SALB SHLB .7D .154
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+EXPORT RCLB ROLB .7F .156
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+edx sal _notimmed _getimmed _yesimmed
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+scasw stosw setc smsw .19A
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+XLAT ADDB ANDB .B8 .1B4
+LGDT LIDT LLDT INCB .B4
+LGDT LIDT LLDT INCB .B4 .1B8
+LGDT LIDT LLDT INCB .B4 .1B8
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+.byte CBW JB JNBE .C9
+BH JG PUSHA .F9 .1E9
+cmpsd iretd verr .FF .1EF
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+ELSEIF PUSHAD REP .E8 .1F4
+word insd xorb .EB ..FFFF
+byte cmpsw .E .EA ..FFFE
+byte cmpsw .E .EA ..FFFE .1FE
+byte cmpsw .E .EA ..FFFE .1FE
+byte cmpsw .E .EA ..FFFE .1FE
+byte cmpsw .E .EA ..FFFE .1FE
+CWD MOVSX NOTB .102 .202
+LCOMM REPE STOW .4 .4A .111
+LCOMM REPE STOW .4 .4A .111
+edx sal _notimmed _getimmed _yesimmed
+INC JNA REPNE SETNC .131
+INB LOOP SETNB .134 .234
+BMI .2 .2A .139 .239
+JNL ROL CMPB .2D .140
+JNL ROL CMPB .2D .140 .240
+JNL ROL CMPB .2D .140 .240
+LCOMM REPE STOW .4 .4A .111 .211
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+LGDT LIDT LLDT INCB .B4 .1B8
+.byte CBW JB JNBE .C9 .1C1
+.byte CBW JB JNBE .C9 .1C1
+edx sal _notimmed _getimmed _yesimmed
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+edx sal _notimmed _getimmed _yesimmed
+word insd xorb .EB ..FFFF .1FF
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+LCOMM REPE STOW .4 .4A .111 .211
+LCOMM REPE STOW .4 .4A .111 .211
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+edx sal _notimmed _getimmed _yesimmed
+edx sal _notimmed _getimmed _yesimmed
+INC JNA REPNE SETNC .131 .231
+INC JNA REPNE SETNC .131 .231
+edx sal _notimmed _getimmed _yesimmed
+edx sal _notimmed _getimmed _yesimmed
+qword outsd rcrb rorb _mdivmul
+qword outsd rcrb rorb _mdivmul
+JNL ROL CMPB .2D .140 .240
+JNL ROL CMPB .2D .140 .240
+BNE INW JMPI LOOPNE .141
+BNE INW JMPI LOOPNE .141
+dr0 SALB SHLB .7D .154
+dr0 SALB SHLB .7D .154
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+EXPORT RCLB ROLB .7F .156
+EXPORT RCLB ROLB .7F .156
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+edx sal _notimmed _getimmed _yesimmed
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+scasw stosw setc smsw .19A
+retf testb _segword _marpl .19B
+scasw stosw setc smsw .19A
+ENDB SAR SBB .A0 .1A0
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+jcxe jecxe .A .AA .1AA
+XLAT ADDB ANDB .B8 .1B4
+XLAT ADDB ANDB .B8 .1B4
+LGDT LIDT LLDT INCB .B4 .1B8
+LGDT LIDT LLDT INCB .B4 .1B8
+LGDT LIDT LLDT INCB .B4 .1B8
+LGDT LIDT LLDT INCB .B4 .1B8
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+.byte CBW JB JNBE .C9 .1C1
+.byte CBW JB JNBE .C9 .1C1
+byte cmpsw .E .EA ..FFFE .1FE
+BH JG PUSHA .F9 .1E9
+BH JG PUSHA .F9 .1E9
+lodsw lmsw verw .FC .1EC
+cmpsd iretd verr .FF .1EF
+cmpsd iretd verr .FF .1EF
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+ELSEIF PUSHAD REP .E8 .1F4
+ELSEIF PUSHAD REP .E8 .1F4
+word insd xorb .EB ..FFFF .1FF
+word insd xorb .EB ..FFFF .1FF
+byte cmpsw .E .EA ..FFFE .1FE
+byte cmpsw .E .EA ..FFFE .1FE
+byte cmpsw .E .EA ..FFFE .1FE
+byte cmpsw .E .EA ..FFFE .1FE
+byte cmpsw .E .EA ..FFFE .1FE
+byte cmpsw .E .EA ..FFFE .1FE
+CWD MOVSX NOTB .102 .202
+CWD MOVSX NOTB .102 .202
+LCOMM REPE STOW .4 .4A .111 .211
+LCOMM REPE STOW .4 .4A .111 .211
+LCOMM REPE STOW .4 .4A .111 .211
+edx sal _notimmed _getimmed _yesimmed
+INC JNA REPNE SETNC .131 .231
+INC JNA REPNE SETNC .131 .231
+IN JNC SETNA .133 .233
+INB LOOP SETNB .134 .234
+CMC JNE SETNG .135 .235
+INB LOOP SETNB .134 .234
+BMI .2 .2A .139 .239
+BMI .2 .2A .139 .239
+JNL ROL CMPB .2D .140 .240
+JNL ROL CMPB .2D .140 .240
+JNL ROL CMPB .2D .140 .240
+JNL ROL CMPB .2D .140 .240
+0000 .bss AAA .1C3
+0001 .list EXTERN .1C4
+0002 .byte CBW JB JNBE .C9 .1C1
+0003 AAD .1C2
+0004 .1C7
+0005 .D0 .1C8
+0006 .data DAA JBE .1C5
+0007 LAR .1C6
+0008 .C3
+0009 RCL .C4 .1D0
+000a .C1 .1C9
+000b SGDT SIDT SLDT .C2
+000c AAM .C7
+000d .C8
+000e .C5
+000f EBX DECb .C6
+0010 .1D7
+0011 .1D8
+0012 AAS JA .D9 .1D5
+0013 RCR .1D6
+0014 DAS .1D3
+0015 .C0 .1D4
+0016 DB JAE JNAE .1D1
+0017 EBP SETDP
+0018 .D3
+0019 .D4
+001a .D1
+001b FAR .D2
+001c .D7
+001d POPAD .D8 .1C0
+001e .D5 .1D9
+001f EAX .D6
+0020 BLOCK BCC SETAE
+0021 .1B0
+0022 .A9 .1A9
+0023 .warn
+0024 CDQ
+0025 SCAB .B0
+0026
+0027
+0028 FCC .org .A3 .1A3
+0029 ADCB .A4 .1A4
+002a .A1 .1A1
+002b FCB LODB .A2 .1A2
+002c .A7 .1A7
+002d .word .A8 .1A8
+002e .A5 .1A5
+002f EDX SAL .A6 .1A6
+0030 EDI BCS
+0031 SBBB SUBB
+0032 ADC JC SCAW .B9
+0033 ADD
+0034 LDS LOCK SETBE
+0035 ENDB SAR SBB .A0 .1A0
+0036 DD SCAS .1B9
+0037
+0038 LODS .B3 .1B7
+0039 LGDT LIDT LLDT INCB .B4 .1B8
+003a .B1 .1B5
+003b FDB .B2 .1B6
+003c CWDE LODW .B7 .1B3
+003d XLAT ADDB ANDB .B8 .1B4
+003e .B5 .1B1
+003f ECX .B6 .1B2
+0040 IF
+0041
+0042 IFC .199
+0043
+0044 .zerow DEC LES XCHG
+0045 .text SHR
+0046
+0047
+0048 .193
+0049 ENTER _Ev .194
+004a _Ew .191
+004b _Ex .192
+004c .197
+004d SAHF _source2 .198
+004e .195
+004f .196
+0050
+0051
+0052 BEQ JE
+0053 IRET
+0054 LFS
+0055 .190
+0056 LEA
+0057 XCHGB
+0058 SETGE .9C
+0059 POPFD .9D
+005a .9 .9A
+005b .9B
+005c NEG
+005d
+005e .9E
+005f GET SHL .9F
+0060
+0061
+0062 SEG .E9
+0063 NEGB
+0064 LGS
+0065 .F0 .1E0
+0066 BGE .1F9
+0067
+0068 .E3 .1F7
+0069 _Gv .E4 .1F8
+006a _Gw .E1 .1F5
+006b _Gx .E2 .1F6
+006c .E7 .1F3
+006d ELSEIF PUSHAD REP .E8 .1F4
+006e JNGE .E5 .1F1
+006f .E6 .1F2
+0070 AH
+0071 BGT RET .1F0
+0072 BH JG PUSHA .F9 .1E9
+0073
+0074 CH
+0075 .E0
+0076 DH JGE
+0077 SET PUSHF
+0078 .F3 .1E3
+0079 PUSHFD .F4 .1E4
+007a BHI .F1 .1E1
+007b .F2 .1E2
+007c .F7 .1E7
+007d .F8 .1E8
+007e .F5 .1E5
+007f LAHF .F6 .1E6
+0080 tr7 .187
+0081 .188
+0082 J .185
+0083 tr6 .186
+0084 .183
+0085 MULB .184
+0086 DI .181
+0087 .182
+0088 .6C
+0089 .6D
+008a JNLE .6 .6A
+008b .6B
+008c PUBLIC
+008d IMULB .170
+008e .6E .189
+008f .6F
+0090 CALLI .173
+0091 .174
+0092 .171
+0093 CALL DIV .172
+0094 .177
+0095 .178
+0096 .175
+0097 .176
+0098 .5C
+0099 .5D .180
+009a .5 .5A .179
+009b .5B
+009c
+009d
+009e ELSEIFC .5E
+009f WAIT .5F
+00a0 dr7
+00a1 FAIL BLT
+00a2 JL
+00a3 dr6
+00a4 SI dr3
+00a5 cr2 IDIV .150
+00a6 cr3 dr1 JLE .169
+00a7 dr2 IMPORT
+00a8 .8C .167
+00a9 .8D .168
+00aa .8 .8A .165
+00ab .8B .166
+00ac .163
+00ad ENDIF HLT .164
+00ae .8E .161
+00af .8F .162
+00b0 AL BHIS
+00b1 .160
+00b2 BL .159
+00b3
+00b4 CL
+00b5
+00b6 DL BLE CLC
+00b7 CLD
+00b8 .7C .153
+00b9 dr0 SALB SHLB .7D .154
+00ba .7 .7A .151
+00bb cr0 SHLD .7B .152
+00bc BLO CLI SETLE .157
+00bd .158
+00be .7E .155
+00bf EXPORT RCLB ROLB .7F .156
+00c0 IN JNC SETNA .133 .233
+00c1 INB LOOP SETNB .134 .234
+00c2 INC JNA REPNE SETNC .131 .231
+00c3 JNB LOOPZ .132 .232
+00c4 JNG SETNE .137 .237
+00c5 .138 .238
+00c6 CMC JNE SETNG .135 .235
+00c7 ARPL .136 .236
+00c8 BLOS .2C
+00c9 JNL ROL CMPB .2D .140 .240
+00ca BMI .2 .2A .139 .239
+00cb CMP LOOPNZ SETNL .2B
+00cc JNO
+00cd JNP
+00ce SETNO .2E
+00cf SETNP .2F
+00d0 JNS .147
+00d1 .148
+00d2 INS POPA SETNS .145
+00d3 AND INT ROR .146
+00d4 SP .143
+00d5 .144
+00d6 BNE INW JMPI LOOPNE .141
+00d7 POPF .142
+00d8 .1C
+00d9 SETNZ .1D
+00da CMPS .1 .1A
+00db END JNZ .1B
+00dc SETNLE
+00dd JMP .130 .230
+00de CMPW LOOPE .1E .149
+00df REPNZ XOR .1F
+00e0 BPS
+00e1 .120 .220
+00e2 JP .119 .219
+00e3 RMB
+00e4
+00e5 BOUND
+00e6 JPE SETPO
+00e7 IDENT
+00e8 SETNGE .4C .113 .213
+00e9 NOT .4D .114 .214
+00ea LCOMM REPE STOW .4 .4A .111 .211
+00eb .4B .112 .212
+00ec JPO SETPE .117 .217
+00ed MOV .118 .218
+00ee STOS .4E .115 .215
+00ef .4F .116 .216
+00f0 BPC SETNAE
+00f1 POP
+00f2 BP JO
+00f3
+00f4 LOC SETNBE
+00f5 NOP .110 .210
+00f6 .129 .229
+00f7 REPZ
+00f8 COMM .3C .127 .227
+00f9 BPL .3D .128 .228
+00fa .3 .3A .125 .225
+00fb .3B .126 .226
+00fc .123 .223
+00fd STOB .124 .224
+00fe .3E .121 .221
+00ff .3F .122 .222
+0100
+0101
+0102
+0103 DIVB
+0104 SS
+0105 STR
+0106
+0107
+0108
+0109
+010a ORG MOVW
+010b IMUL
+010c OR
+010d ORB
+010e MOVS
+010f
+0110
+0111
+0112 BR
+0113
+0114
+0115 IDIVB
+0116 LEAVE STC
+0117 STD
+0118
+0119
+011a
+011b
+011c EQU STI
+011d MOVB
+011e
+011f
+0120 ESI BTS
+0121
+0122
+0123 BTR
+0124 CS LSS
+0125
+0126 DS
+0127 ESP .even JCXZ JECXZ BSF
+0128 ES
+0129
+012a FS
+012b
+012c GS
+012d
+012e
+012f
+0130 BTC
+0131
+0132 JS BT
+0133 BSR
+0134
+0135
+0136
+0137 LTR
+0138
+0139
+013a JCXE JECXE
+013b
+013c
+013d LSL
+013e
+013f PTR
+0140 BVS
+0141 SETZ
+0142 MACRO
+0143
+0144 ENTRY
+0145
+0146
+0147
+0148
+0149 PWORD
+014a SETS
+014b
+014c
+014d SCASB STOSB
+014e _jumps_long
+014f OUT SCASD STOSD
+0150 BVC
+0151 DWORD EXTRN
+0152
+0153 MUL XLATB SETL
+0154
+0155
+0156 RETI SETO
+0157 SETP
+0158 INCLUDE SETA
+0159 SETB
+015a SCASW STOSW SETC SMSW
+015b RETF TESTB
+015c SETE
+015d FWORD TEST
+015e TBYTE SETG
+015f
+0160 _calljmp_kludge .107 .207
+0161 OUTB .108 .208
+0162 INTO OUTSW .105 .205
+0163 .106 .206
+0164 ELSE .103 .203
+0165 SUB .104 .204
+0166 DW MOVSW .101 .201
+0167 CWD MOVSX NOTB .102 .202
+0168 LODSW LMSW VERW
+0169
+016a CLTS
+016b
+016c
+016d CMPSB
+016e INSW .109 .209
+016f CMPSD IRETD VERR
+0170 AX
+0171 MOVSB PUSH SARB SHRB
+0172 BX .ascii OUTS
+0173 .extern MOVSD SHRD
+0174 CX
+0175 .map OUTSB
+0176 DX .space OUTW
+0177 QWORD OUTSD RCRB RORB
+0178
+0179 INSB .100 .200
+017a BYTE CMPSW
+017b WORD INSD XORB
+017c
+017d LODSD
+017e
+017f LODSB
+0180
+0181
+0182 JZ
+0183
+0184
+0185
+0186 .comm
+0187
+0188
+0189
+018a
+018b
+018c
+018d
+018e
+018f
+0190 _mgroup1
+0191 .maclist _mgroup2
+0192 _mgroup3
+0193
+0194
+0195 .globl _mgroup6
+0196 _mgroup7
+0197 _mgroup8
+0198 .long
+0199
+019a
+019b
+019c
+019d
+019e
+019f
+01a0
+01a1
+01a2
+01a3
+01a4
+01a5
+01a6 .lcomm
+01a7
+01a8
+01a9
+01aa
+01ab
+01ac
+01ad
+01ae
+01af
+01b0
+01b1
+01b2
+01b3
+01b4
+01b5
+01b6
+01b7
+01b8
+01b9
+01ba
+01bb
+01bc
+01bd
+01be
+01bf
+01c0
+01c1
+01c2
+01c3
+01c4
+01c5
+01c6
+01c7
+01c8
+01c9
+01ca .define
+01cb
+01cc
+01cd .short
+01ce
+01cf
+01d0
+01d1 .fail
+01d2
+01d3
+01d4
+01d5
+01d6
+01d7
+01d8
+01d9
+01da
+01db
+01dc
+01dd
+01de
+01df
+01e0
+01e1
+01e2
+01e3
+01e4 .blkw
+01e5
+01e6
+01e7
+01e8
+01e9
+01ea
+01eb
+01ec
+01ed
+01ee
+01ef .align
+01f0
+01f1
+01f2
+01f3 .blkb
+01f4
+01f5
+01f6
+01f7
+01f8
+01f9
+01fa
+01fb MOVZX
+01fc
+01fd
+01fe
+01ff
+0200 if
+0201 _gsymptr
+0202 seg
+0203
+0204 lgs
+0205 bound
+0206 bge setpo
+0207 ident _mimul
+0208 setnge _mcalli
+0209
+020a lcomm repe stow
+020b
+020c setpe
+020d rep
+020e stos
+020f
+0210 setnae _getunary
+0211 bgt ret
+0212 je
+0213
+0214 setnbe
+0215
+0216 jge
+0217 set repz
+0218 comm
+0219
+021a bhi
+021b
+021c
+021d stob
+021e
+021f
+0220 setna
+0221 loop setnb
+0222 ifc repne setnc
+0223 loopz
+0224 dec les setne
+0225 shr
+0226 setng
+0227 arpl
+0228 blos
+0229 cmpb
+022a _fqflag _fdflag _fcflag
+022b loopnz setnl _mshort
+022c
+022d _mloadfullpointer
+022e setno
+022f setnp
+0230 ah
+0231 _min
+0232 bh beq jg popa setns
+0233
+0234 ch lfs
+0235
+0236 dh jmpi lea loopne
+0237 popf
+0238
+0239 setnz
+023a cmps
+023b
+023c neg setnle _buildea _yes_samesize
+023d _sib
+023e cmpw loope
+023f get repnz shl _mmovx
+0240 bcc _getbinary
+0241 fail
+0242 jb
+0243
+0244 cdq
+0245 idiv _minher32
+0246
+0247 import
+0248 fcc
+0249 _minher16
+024a
+024b fcb
+024c _displsize _getcomma
+024d endif
+024e
+024f edx sal _notimmed _getimmed _yesimmed
+0250 edi bcs bhis
+0251 _mmov
+0252 adc ja
+0253 add
+0254 lds _mshdouble
+0255 sar sbb
+0256 db
+0257
+0258
+0259 salb shlb
+025a _datatoobig
+025b fdb shld _immcount
+025c setle
+025d
+025e
+025f ecx export rclb rolb
+0260 aaa
+0261
+0262 cbw
+0263 aad
+0264
+0265 mulb
+0266 daa jbe
+0267 lar
+0268
+0269 rcl
+026a jnle
+026b _mint
+026c public aam
+026d imulb
+026e
+026f ebx
+0270 calli
+0271
+0272 aas jc
+0273 call rcr
+0274 das _opcode _asld_compatible
+0275
+0276 dd jae
+0277 ebp
+0278
+0279
+027a
+027b far
+027c _mnsize
+027d
+027e elseifc
+027f eax wait
+0280 bps in
+0281 _immadr
+0282
+0283 rmb .WARN negb
+0284
+0285
+0286 jpe
+0287 _mtest
+0288 .ORG
+0289 not _baseind16 _direction
+028a _chkabs
+028b
+028c jpo
+028d elseif .WORD mov pushad
+028e jnge
+028f
+0290 bpc _buildimm
+0291 pop
+0292 pusha .10E .20E
+0293 _lbranch .10F .20F
+0294 sp loc .10C .20C
+0295 nop .10D _mretf .20D
+0296 .10A .20A
+0297 pushf .10B .20B
+0298
+0299 bpl pushfd
+029a
+029b _buildsegword
+029c
+029d
+029e
+029f lahf
+02a0 .BSS jnc
+02a1 .LIST inb
+02a2 .BYTE inc jna jp
+02a3 jnb
+02a4 jng xchg
+02a5
+02a6 .DATA cmc jne _mxchg
+02a7
+02a8 _minhera
+02a9 enter jnl rol
+02aa bmi _getaccumreg _regchk
+02ab cmp
+02ac jno
+02ad jnp sahf
+02ae _lc _mincdec
+02af
+02b0 jns
+02b1
+02b2 bp ins jo
+02b3 and int iret ror
+02b4
+02b5
+02b6 bne inw _mbcc _mjcc
+02b7 xchgb _notindirect _getindirect
+02b8 setge
+02b9 popfd
+02ba
+02bb end jnz _regsegword _mcall
+02bc
+02bd jmp
+02be
+02bf xor
+02c0 TR7 block setae
+02c1 blt
+02c2 j
+02c3 TR6
+02c4
+02c5 scab
+02c6 di jle
+02c7
+02c8
+02c9 adcb _databuf
+02ca _notsegreg _indregchk _mseg _pcrflag
+02cb lodb
+02cc _mlea
+02cd hlt _buildregular
+02ce
+02cf decb
+02d0 _lcdata
+02d1 sbbb subb
+02d2 scaw _regbits
+02d3
+02d4 lock setbe _segoverride
+02d5 endb
+02d6 ble clc scas
+02d7 cld _mnegnot
+02d8 lods
+02d9 lgdt lidt lldt incb
+02da
+02db _mpushpop
+02dc blo cli cwde lodw
+02dd xlat addb andb
+02de _nonimpexpres
+02df _mret _showrelbad
+02e0 DR7 _reldata _page
+02e1 extern
+02e2 jl jnbe
+02e3 DR6
+02e4 si DR3 .ZEROW
+02e5 CR2 .TEXT
+02e6 CR3 DR1
+02e7 DR2
+02e8
+02e9
+02ea
+02eb sgdt sidt sldt _aprefix _oprefix _getshift _sprefix
+02ec
+02ed _minher
+02ee
+02ef
+02f0 al
+02f1
+02f2 bl
+02f3 div
+02f4 cl
+02f5
+02f6 dl jnae
+02f7 setdp
+02f8
+02f9 DR0 _mjcxz
+02fa
+02fb CR0
+02fc
+02fd popad
+02fe
+02ff _target
+0300 _rm
+0301
+0302 .39
+0303
+0304
+0305 sub .40
+0306 .LCOMM
+0307 cwd
+0308 .33
+0309 .34
+030a .31 .12E .22E
+030b .32 .12F .22F
+030c .37 .12C .22C
+030d .38 .12D .22D
+030e .35 .12A .22A
+030f .36 .12B .22B
+0310
+0311
+0312 .49
+0313
+0314
+0315 .30
+0316
+0317
+0318 .43 .11C .21C
+0319 .44 .11D .21D
+031a .41 .11A .21A
+031b movzx .42 .11B .21B
+031c .47
+031d USE16 .48
+031e .45 .11E .21E
+031f .46 .11F .21F
+0320 bvs
+0321
+0322 .19 .14E
+0323 .14F
+0324 .14C
+0325 .20 .14D
+0326 .COMM dw .14A
+0327 .14B
+0328 .13
+0329 .14
+032a .11
+032b .12
+032c .17
+032d .18
+032e _ss .15
+032f out .16
+0330 ax bvc .13C .23C
+0331 .MACLIST USE32 .13D .23D
+0332 bx .29 .13A .23A
+0333 mul .13B .23B
+0334 cx
+0335 .GLOBL .10
+0336 dx .13E .23E
+0337 .13F .23F
+0338 .LONG .23
+0339 .24
+033a .21
+033b .22
+033c .27
+033d .28
+033e .25
+033f .26
+0340 esi bts
+0341 _mEvGv
+0342 .79
+0343 btr
+0344 ss .BLKW lss
+0345 .80
+0346
+0347 esp bsf
+0348 .73 .15C
+0349 .74 .15D _mGvEv
+034a .71 .15A
+034b .72 .15B
+034c or .77
+034d .78
+034e .75 .15E
+034f .ALIGN .76 .15F
+0350 btc
+0351
+0352 br .89
+0353 .BLKB bsr
+0354
+0355 .70
+0356
+0357 ltr
+0358 .83
+0359 .84
+035a .81 .16E
+035b .82 .16F
+035c .87 .16C
+035d use16 lsl .88 .16D
+035e .85 .16A
+035f ptr .86 .16B
+0360 .17C
+0361 .17D
+0362 .59 .17A
+0363 .17B
+0364 cs
+0365 str .60
+0366 ds .17E
+0367 .17F
+0368 es .53
+0369 .54
+036a fs org .DEFINE .51
+036b .52
+036c gs .57
+036d .SHORT orb .58
+036e .55
+036f .56
+0370 _sym
+0371 .FAIL use32
+0372 js bt .69 .18E
+0373 .18F
+0374 .18C
+0375 .50 .18D
+0376 stc .18A
+0377 std .18B
+0378 .63
+0379 .64
+037a .61
+037b .62
+037c equ sti .67
+037d .68
+037e .65
+037f .66
+0380 _source _buildunary
+0381 outb
+0382 into outsw
+0383
+0384 else
+0385 _factor
+0386 movsw
+0387 .EVEN movsx notb
+0388 lodsw lmsw verw .FC .1EC
+0389 .FD .1ED
+038a clts .F .FA .1EA
+038b .FB .1EB
+038c
+038d cmpsb
+038e insw _expres .FE .1EE
+038f cmpsd iretd verr .FF .1EF
+0390
+0391 movsb push sarb shrb
+0392 outs
+0393 movsd shrd
+0394
+0395 outsb
+0396 outw
+0397 qword outsd rcrb rorb _mdivmul
+0398 .EC
+0399 insb
+039a byte cmpsw .E .EA ..FFFE .1FE
+039b word insd xorb .EB ..FFFF .1FF
+039c .1FC
+039d lodsd .1FD
+039e .EE .1FA
+039f lodsb .EF _mout .1FB
+03a0
+03a1 setz
+03a2 macro .99
+03a3
+03a4 entry
+03a5 _error _kgerror
+03a6 _msetcc
+03a7
+03a8 .93
+03a9 pword .94
+03aa sets .91 _notcsreg
+03ab .92
+03ac .97
+03ad scasb stosb .98 _menter
+03ae .95
+03af scasd stosd .96
+03b0
+03b1 dword extrn
+03b2
+03b3 xlatb setl
+03b4
+03b5 .90
+03b6 reti seto
+03b7 setp
+03b8 include seta .19C
+03b9 setb .19D
+03ba scasw stosw setc smsw .19A
+03bb retf testb _segword _marpl .19B
+03bc sete _getea
+03bd fword test
+03be tbyte setg .19E
+03bf .19F
+03c0
+03c1
+03c2 jz
+03c3
+03c4
+03c5
+03c6
+03c7 jcxz jecxz
+03c8 .BC
+03c9 .BD
+03ca .B .BA .1BE
+03cb .BB .1BF
+03cc _notbytesize .1BC
+03cd .1BD
+03ce .BE .1BA
+03cf .BF .1BB
+03d0 _getsym
+03d1
+03d2 .ASCII
+03d3 .EXTERN
+03d4
+03d5 .MAP
+03d6 .SPACE
+03d7
+03d8 .AC .1AC
+03d9 .AD .1AD
+03da jcxe jecxe .A .AA .1AA
+03db .AB .1AB
+03dc _regsize _defsize
+03dd
+03de .AE .1AE
+03df .AF .1AF
+03e0
+03e1
+03e2 .1DE
+03e3 divb _lcjump .1DF
+03e4 .1DC
+03e5 .1DD
+03e6 _pass .1DA
+03e7 .1DB
+03e8 .DC
+03e9 .DD
+03ea movw .D .DA
+03eb imul .DB _mbound
+03ec _yeswordsize
+03ed
+03ee movs .DE
+03ef .DF
+03f0 _rmfunny .1CC
+03f1 _postb .1CD
+03f2 .1CA
+03f3 .1CB
+03f4
+03f5 idivb
+03f6 leave .1CE
+03f7 .1CF
+03f8 .CC
+03f9 .CD
+03fa .C _getdxreg .CA
+03fb .CB
+03fc
+03fd movb
+03fe .CE
+03ff _lastexp .CF
+nhash = 731, nsym = 1463, nlookup = 18376 nx =
+ 011029 2760 2820 185 97 20 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 731 406 200 87 29 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+weight = 26368, compares = 27603
diff --git a/bin86-0.3/as/work/t b/bin86-0.3/as/work/t
new file mode 100644
index 0000000..29ebfd6
--- /dev/null
+++ b/bin86-0.3/as/work/t
@@ -0,0 +1,3 @@
+cp work/$1 as
+sync
+time sh t1
diff --git a/bin86-0.3/as/work/t1 b/bin86-0.3/as/work/t1
new file mode 100644
index 0000000..c2a47d5
--- /dev/null
+++ b/bin86-0.3/as/work/t1
@@ -0,0 +1,10 @@
+./as q -w -u
+./as q -w -u
+./as q -w -u
+./as q -w -u
+./as q -w -u
+./as q -w -u
+./as q -w -u
+./as q -w -u
+./as q -w -u
+./as q -w -u
diff --git a/bin86-0.3/as/work/z b/bin86-0.3/as/work/z
new file mode 100644
index 0000000..108c07e
--- /dev/null
+++ b/bin86-0.3/as/work/z
@@ -0,0 +1,5 @@
+r q -w -u
+_exit b
+c
+_nhash/x
+_hid_spt+0x40/32x
diff --git a/bin86-0.3/bcc/bcc.c b/bin86-0.3/bcc/bcc.c
new file mode 100644
index 0000000..58035c8
--- /dev/null
+++ b/bin86-0.3/bcc/bcc.c
@@ -0,0 +1,831 @@
+/*
+ * bin86/bcc/bcc.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* bcc.c - driver for Bruce's C compiler and for CvW's C compiler */
+
+#define _POSIX_SOURCE 1
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FALSE 0
+#define FORWARD static
+#ifndef NULL
+#define NULL 0
+#endif
+#define PRIVATE static
+#define PUBLIC
+#define TRUE 1
+
+#if __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+#define AS "as"
+#define BAS86
+#define BCC86
+#define CC1 "cc1"
+#define CC1_MINUS_O_BROKEN FALSE
+#define CPP "cc1"
+#define CPPFLAGS "-E"
+#define CRTSO "crtso.o"
+#define GCC "/usr/bin/gcc"
+#define LD "ld"
+#define STANDARD_CRTSO0_PREFIX "/usr/local/lib/i86/"
+#define STANDARD_CRTSO3_PREFIX "/usr/local/lib/i386/"
+#define STANDARD_EXEC_PREFIX "/usr/local/libexec/i386/bcc/"
+
+#ifdef CCC
+#undef BCC86
+#undef CC1
+#define CC1 "c386"
+#undef CC1_MINUS_O_BROKEN
+#define CC1_MINUS_O_BROKEN TRUE
+#undef CPP
+#define CPP "cpp" /* could also use bcc-cc1 -E */
+#undef CPPFLAGS
+#define CPPFLAGS "-traditional"
+#undef GCC
+#undef STANDARD_CRTSO0_PREFIX
+#undef STANDARD_CRTSO3_PREFIX
+#define STANDARD_CRTSO_PREFIX "/usr/local/lib/i386/"
+#define STANDARD_EXEC_PREFIX_2 "/usr/local/bin/"
+#endif /* CCC */
+
+#ifdef MC6809
+#undef BAS86
+#undef BCC86
+#undef CRTSO
+#undef GCC
+#undef STANDARD_CRTSO0_PREFIX
+#undef STANDARD_CRTSO3_PREFIX
+#undef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX "/usr/local/libexec/m09/bcc/"
+#endif /* MC6809 */
+
+#define ALLOC_UNIT 16 /* allocation unit for arg arrays */
+#define DIRCHAR '/'
+#define START_ARGS 4 /* number of reserved args */
+
+typedef unsigned char bool_T; /* boolean: TRUE if nonzero */
+
+struct arg_s
+{
+ char *prog;
+ bool_T minus_O_broken;
+ int argc;
+ char **argv;
+ unsigned nr_allocated;
+};
+
+struct prefix_s
+{
+ char *name;
+ struct prefix_s *next;
+};
+
+PRIVATE struct arg_s asargs = { AS, };
+PRIVATE struct arg_s ccargs = { CC1, CC1_MINUS_O_BROKEN, };
+PRIVATE struct arg_s cppargs = { CPP, };
+#ifdef STANDARD_CRTSO_PREFIX
+PRIVATE struct prefix_s crtso_prefix = { STANDARD_CRTSO_PREFIX, };
+#endif
+#ifdef STANDARD_CRTSO0_PREFIX
+PRIVATE struct prefix_s crtso0_prefix = { STANDARD_CRTSO0_PREFIX, };
+#endif
+#ifdef STANDARD_CRTSO3_PREFIX
+PRIVATE struct prefix_s crtso3_prefix = { STANDARD_CRTSO3_PREFIX, };
+#endif
+PRIVATE struct prefix_s exec_prefix;
+PRIVATE struct arg_s ldargs = { LD, };
+#ifdef BAS86
+PRIVATE struct arg_s ldrargs = { LD, };
+#endif
+PRIVATE char *progname;
+PRIVATE bool_T runerror; /* = FALSE */
+PRIVATE struct arg_s tmpargs; /* = empty */
+PRIVATE char *tmpdir;
+PRIVATE bool_T verbose; /* = FALSE */
+
+/* Who can say if the standard headers declared these? */
+int chmod P((const char *name, int mode));
+int execv P((char *name, char **argv));
+void exit P((int status));
+pid_t fork P((void));
+char *getenv P((const char *_name));
+pid_t getpid P((void));
+void *malloc P((unsigned size));
+void *realloc P((void *ptr, unsigned size));
+void (*signal P((int sig, void (*func) P((int sig))))) P((int sig));
+char *strcpy P((char *target, const char *source));
+size_t strlen P((const char *s));
+char *strrchr P((const char *s, int c));
+int unlink P((const char *name));
+pid_t wait P((int *status));
+int write P((int fd, char *buf, unsigned nbytes));
+
+FORWARD void addarg P((struct arg_s *argp, char *arg));
+FORWARD void addprefix P((struct prefix_s *prefix, char *name));
+FORWARD void fatal P((char *message));
+FORWARD char *fixpath P((char *path, struct prefix_s *prefix, int mode));
+FORWARD void killtemps P((void));
+FORWARD void *my_malloc P((unsigned size, char *where));
+FORWARD char *my_mktemp P((void));
+FORWARD void my_unlink P((char *name));
+FORWARD void outofmemory P((char *where));
+FORWARD int run P((char *in_name, char *out_name, struct arg_s *argp));
+FORWARD void set_trap P((void));
+FORWARD void show_who P((char *message));
+FORWARD void startarg P((struct arg_s *argp));
+FORWARD char *stralloc P((char *s));
+FORWARD char *stralloc2 P((char *s1, char *s2));
+FORWARD void trap P((int signum));
+FORWARD void unsupported P((char *option, char *message));
+FORWARD void writen P((void));
+FORWARD void writes P((char *s));
+FORWARD void writesn P((char *s));
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+ int argcount = argc;
+ bool_T *argdone = my_malloc((unsigned) argc * sizeof *argdone, "argdone");
+ bool_T as_only = FALSE;
+ char *basename;
+#ifdef BCC86
+ bool_T bits32 = sizeof (char *) >= 4;
+ char *bits_arg;
+#endif
+ bool_T cc_only = FALSE;
+#ifdef CCC
+ bool_T cpp_pass = TRUE;
+#else
+ bool_T cpp_pass = FALSE;
+#endif
+#ifdef BCC86
+ char *crtso;
+#endif
+ bool_T debug = FALSE;
+ bool_T echo = FALSE;
+ unsigned errcount = 0;
+ char ext;
+ char *f_out = NULL;
+ bool_T float_emulation = FALSE;
+#ifdef BAS86
+ bool_T gnu_objects = FALSE;
+#endif
+ char *in_name;
+ int length;
+ unsigned ncisfiles = 0;
+ unsigned nifiles = 0;
+ unsigned npass_specs;
+ bool_T optimize = FALSE;
+ char *out_name;
+ bool_T profile = FALSE;
+ bool_T prep_only = FALSE;
+ bool_T prep_line_numbers = FALSE;
+ int status;
+ char *temp;
+
+ progname = argv[0];
+ addarg(&cppargs, CPPFLAGS);
+#ifdef CCC
+ addarg(&asargs, "-j");
+#endif
+ addarg(&asargs, "-u");
+ addarg(&asargs, "-w");
+#ifdef BCC86
+ addarg(&ldargs, "-i");
+#endif
+#ifdef BAS86
+ addarg(&ldrargs, "-r");
+#endif
+
+ /* pass 1 over argv to gather compile options */
+ for (; --argc != 0;)
+ {
+ arg = *++argv;
+ *++argdone = TRUE;
+ if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0)
+ switch (arg[1])
+ {
+#ifdef BCC86
+ case '0':
+ bits32 = FALSE;
+ break;
+ case '3':
+ bits32 = TRUE;
+ break;
+#endif
+ case 'E':
+ prep_only = prep_line_numbers = cpp_pass = TRUE;
+ break;
+#ifdef BAS86
+ case 'G':
+ gnu_objects = TRUE;
+ break;
+#endif
+ case 'P':
+ prep_only = cpp_pass = TRUE;
+ prep_line_numbers = FALSE;
+ break;
+ case 'O':
+ optimize = TRUE; /* unsupported( arg, "optimize" ); */
+ break;
+ case 'S':
+ cc_only = TRUE;
+ break;
+ case 'V':
+ echo = TRUE;
+ break;
+ case 'c':
+ as_only = TRUE;
+ break;
+ case 'e':
+ cpp_pass = TRUE;
+ break;
+ case 'f':
+ float_emulation = TRUE;
+ ++errcount;
+ unsupported(arg, "float emulation");
+ break;
+ case 'g':
+ debug = TRUE; /* unsupported( arg, "debug" ); */
+ break;
+ case 'o':
+ if (--argc < 1)
+ {
+ ++errcount;
+ show_who("output file missing after -o\n");
+ }
+ else
+ {
+ if (f_out != NULL)
+ show_who("more than one output file\n");
+ f_out = *++argv;
+ *++argdone = TRUE;
+ }
+ break;
+ case 'p':
+ profile = TRUE;
+ ++errcount;
+ unsupported(arg, "profile");
+ break;
+ case 'v':
+ verbose = TRUE;
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else if (arg[0] == '-')
+ switch (arg[1])
+ {
+ case 'A':
+ addarg(&asargs, arg + 2);
+ break;
+ case 'B':
+ addprefix(&exec_prefix, arg + 2);
+ break;
+ case 'C':
+ addarg(&ccargs, arg + 2);
+ break;
+ case 'D':
+ case 'I':
+ case 'U':
+#ifndef CCC
+ addarg(&ccargs, arg);
+#endif
+ addarg(&cppargs, arg);
+ break;
+ case 'L':
+ addarg(&ldargs, arg + 2);
+ break;
+ case 'P':
+ addarg(&cppargs, arg + 2);
+ break;
+#ifdef CCC
+ case 'Q':
+ addarg(&ccargs, arg);
+ break;
+#endif
+ case 'T':
+ tmpdir = arg + 2;
+ break;
+ case 't':
+ ++errcount;
+ unsupported(arg, "pass number");
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else
+ {
+ ++nifiles;
+ *argdone = FALSE;
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.' &&
+ ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 's'))
+ ++ncisfiles;
+ }
+ }
+ npass_specs = prep_only + cc_only + as_only;
+ if (npass_specs != 0)
+ {
+ if (npass_specs > 1)
+ {
+ ++errcount;
+ show_who("more than 1 option from -E -P -S -c\n");
+ }
+ if (f_out != NULL && ncisfiles > 1)
+ {
+ ++errcount;
+ show_who("cannot have more than 1 input with non-linked output\n");
+ }
+ }
+ if (nifiles == 0)
+ {
+ ++errcount;
+ show_who("no input files\n");
+ }
+ if (errcount != 0)
+ exit(1);
+
+ if ((temp = getenv("BCC_EXEC_PREFIX")) != NULL)
+ addprefix(&exec_prefix, temp);
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX);
+#ifdef STANDARD_EXEC_PREFIX_2
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX_2);
+#endif
+ cppargs.prog = fixpath(cppargs.prog, &exec_prefix, X_OK);
+ ccargs.prog = fixpath(ccargs.prog, &exec_prefix, X_OK);
+ asargs.prog = fixpath(asargs.prog, &exec_prefix, X_OK);
+ ldargs.prog = fixpath(ldargs.prog, &exec_prefix, X_OK);
+ ldrargs.prog = fixpath(ldrargs.prog, &exec_prefix, X_OK);
+ if (tmpdir == NULL && (tmpdir = getenv("TMPDIR")) == NULL)
+ tmpdir = "/tmp";
+
+ if (prep_only && !prep_line_numbers)
+ addarg(&cppargs, "-P");
+#ifdef BCC86
+ if (bits32)
+ {
+ bits_arg = "-3";
+ crtso = fixpath(CRTSO, &crtso3_prefix, R_OK);
+ }
+ else
+ {
+ bits_arg = "-0";
+ crtso = fixpath(CRTSO, &crtso0_prefix, R_OK);
+ }
+ addarg(&ccargs, bits_arg);
+ addarg(&cppargs, bits_arg);
+ addarg(&asargs, bits_arg);
+#ifdef BAS86
+ if (!gnu_objects)
+ {
+ addarg(&ldargs, bits_arg);
+ addarg(&ldrargs, bits_arg);
+ addarg(&ldargs, crtso);
+ }
+#endif /* BAS86 */
+#endif /* BCC86 */
+#if defined(BAS86) && !defined(BCC86)
+ if (!gnu_objects)
+ addarg(&ldargs, fixpath(CRTSO, &crtso_prefix, R_OK));
+#endif
+ if (ncisfiles < 2)
+ echo = FALSE;
+ set_trap();
+
+ /* pass 2 over argv to compile and assemble .c and .s files */
+ /* and gather arguments for loader */
+ for (argv -= (argc = argcount) - 1, argdone -= argcount - 1; --argc != 0;)
+ {
+ arg = *++argv;
+ if (!*++argdone)
+ {
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.' &&
+ ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 's'))
+ {
+ if (echo || verbose)
+ {
+ writes(arg);
+ writesn(":");
+ }
+ if ((basename = strrchr(arg, DIRCHAR)) == NULL)
+ basename = arg;
+ else
+ ++basename;
+ in_name = arg;
+ if (ext == 'c')
+ {
+ if (cpp_pass)
+ {
+ if (prep_only)
+ out_name = f_out;
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+ }
+ ext = 'i';
+ }
+ if (ext == 'i')
+ {
+ if (prep_only)
+ continue;
+ if (cc_only)
+ {
+ if (f_out != NULL)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &ccargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 's')
+ {
+ if (prep_only || cc_only)
+ continue;
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ if (as_only)
+ {
+ if (f_out != NULL)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ addarg(&asargs, "-n");
+ arg[length - 1] = 's';
+ addarg(&asargs, arg);
+#ifdef BCC86
+ if (gnu_objects)
+ {
+ char *tmp_out_name;
+
+ tmp_out_name = my_mktemp();
+ status = run(in_name, tmp_out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ if (run(tmp_out_name, out_name, &ldrargs) != 0)
+ continue;
+ }
+ else
+#endif
+ {
+ status = run(in_name, out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ }
+ ext = 'o';
+ in_name = out_name;
+ }
+ if (ext == 'o')
+ {
+ if (prep_only || cc_only || as_only)
+ continue;
+ addarg(&ldargs, in_name);
+ }
+ }
+ else
+ addarg(&ldargs, arg);
+ }
+ }
+
+ if (!prep_only && !cc_only && !as_only && !runerror)
+ {
+ if (f_out == NULL)
+ f_out = "a.out";
+#ifdef BCC86
+ if (gnu_objects)
+ {
+ ldargs.prog = GCC;
+ run((char *) NULL, f_out, &ldargs);
+ }
+ else
+#endif
+ {
+ addarg(&ldargs, "-lc");
+ run((char *) NULL, f_out, &ldargs);
+ }
+ }
+ killtemps();
+ return runerror ? 1 : 0;
+}
+
+PRIVATE void addarg(argp, arg)
+register struct arg_s *argp;
+char *arg;
+{
+ int new_argc;
+ char **new_argv;
+
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ new_argc = argp->argc + 1;
+ if (new_argc >= argp->nr_allocated)
+ {
+ argp->nr_allocated += ALLOC_UNIT;
+ new_argv = realloc(argp->argv, argp->nr_allocated * sizeof *argp->argv);
+ if (new_argv == NULL)
+ outofmemory("addarg");
+ argp->argv = new_argv;
+ }
+ argp->argv[argp->argc] = arg;
+ argp->argv[argp->argc = new_argc] = NULL;
+}
+
+PRIVATE void addprefix(prefix, name)
+struct prefix_s *prefix;
+char *name;
+{
+ struct prefix_s *new_prefix;
+
+ if (prefix->name == NULL)
+ prefix->name = name;
+ else
+ {
+ new_prefix = my_malloc(sizeof *new_prefix, "addprefix");
+ new_prefix->name = name;
+ new_prefix->next = NULL;
+ prefix->next = new_prefix;
+ }
+}
+
+PRIVATE void fatal(message)
+char *message;
+{
+ writesn(message);
+ killtemps();
+ exit(1);
+}
+
+PRIVATE char *fixpath(path, prefix, mode)
+char *path;
+struct prefix_s *prefix;
+int mode;
+{
+ char *ppath;
+
+ for (; prefix != NULL; prefix = prefix->next)
+ {
+ ppath = stralloc2(prefix->name, path);
+ if (access(ppath, mode) == 0)
+ return ppath;
+ free(ppath);
+ }
+ return path;
+}
+
+PRIVATE void killtemps()
+{
+ while (tmpargs.argc > START_ARGS)
+ my_unlink(tmpargs.argv[--tmpargs.argc]);
+}
+
+PRIVATE void *my_malloc(size, where)
+unsigned size;
+char *where;
+{
+ void *block;
+
+ if ((block = malloc(size)) == NULL)
+ outofmemory(where);
+ return block;
+}
+
+PRIVATE char *my_mktemp()
+{
+ char *p;
+ unsigned digit;
+ unsigned digits;
+ char *template;
+ static unsigned tmpnum;
+
+ p = template = stralloc2(tmpdir, "/bccYYYYXXXX");
+ p += strlen(p);
+ digits = getpid();
+ while (*--p == 'X')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p = digit + '0';
+ digits /= 16;
+ }
+ digits = tmpnum;
+ while (*p == 'Y')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p-- = digit + '0';
+ digits /= 16;
+ }
+ ++tmpnum;
+ addarg(&tmpargs, template);
+ return template;
+}
+
+PRIVATE void my_unlink(name)
+char *name;
+{
+ if (verbose)
+ {
+ show_who("unlinking ");
+ writesn(name);
+ }
+ if (unlink(name) < 0 && verbose)
+ {
+ show_who("error unlinking ");
+ writesn(name);
+ }
+}
+
+PRIVATE void outofmemory(where)
+char *where;
+{
+ show_who("out of memory in ");
+ fatal(where);
+}
+
+PRIVATE int run(in_name, out_name, argp)
+char *in_name;
+char *out_name;
+struct arg_s *argp;
+{
+ int arg0;
+ int i;
+ int status;
+
+ arg0 = 0;
+ if (in_name == NULL)
+ ++arg0;
+ if (out_name == NULL)
+ arg0 += 2;
+ else if (argp->minus_O_broken)
+ ++arg0;
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ argp->argv[arg0] = argp->prog;
+ i = arg0 + 1;
+ if (in_name != NULL)
+ argp->argv[i++] = in_name;
+ if (out_name != NULL)
+ {
+ if (!argp->minus_O_broken)
+ argp->argv[i++] = "-o";
+ argp->argv[i++] = out_name;
+ }
+ if (verbose)
+ {
+ for (i = arg0; i < argp->argc; ++i)
+ {
+ writes(argp->argv[i]);
+ writes(" ");
+ }
+ writen();
+ }
+ switch (fork())
+ {
+ case -1:
+ show_who("fork failed");
+ fatal("");
+ case 0:
+ execv(argp->prog, argp->argv + arg0);
+ show_who("exec of ");
+ writes(argp->prog);
+ fatal(" failed");
+ default:
+ wait(&status);
+ for (i = tmpargs.argc - 1; i >= START_ARGS; --i)
+ if (in_name == tmpargs.argv[i])
+ {
+ my_unlink(in_name);
+ --tmpargs.argc;
+ memmove(tmpargs.argv + i, tmpargs.argv + i + 1,
+ (tmpargs.argc - i) * sizeof tmpargs.argv[0]);
+ break;
+ }
+ if (status != 0)
+ {
+ killtemps();
+ runerror = TRUE;
+ }
+ return status;
+ }
+}
+
+PRIVATE void set_trap()
+{
+ int signum;
+
+#ifndef _NSIG
+#define NSIG _NSIG
+#endif
+ for (signum = 0; signum <= _NSIG; ++signum)
+#ifdef SIGCHLD
+ if (signum != SIGCHLD)
+#endif
+ if (signal(signum, SIG_IGN) != SIG_IGN)
+ signal(signum, trap);
+}
+
+PRIVATE void show_who(message)
+char *message;
+{
+ writes(progname);
+ writes(": ");
+ writes(message);
+}
+
+PRIVATE void startarg(argp)
+struct arg_s *argp;
+{
+ argp->argv = my_malloc((argp->nr_allocated = ALLOC_UNIT)
+ * sizeof *argp->argv, "startarg");
+ argp->argc = START_ARGS;
+ argp->argv[START_ARGS] = NULL;
+}
+
+PRIVATE char *stralloc(s)
+char *s;
+{
+ return strcpy(my_malloc(strlen(s) + 1, "stralloc"), s);
+}
+
+PRIVATE char *stralloc2(s1, s2)
+char *s1;
+char *s2;
+{
+ return strcat(strcpy(my_malloc(
+ strlen(s1) + strlen(s2) + 1, "stralloc2"), s1), s2);
+}
+
+PRIVATE void trap(signum)
+int signum;
+{
+ signal(signum, SIG_IGN);
+ if (verbose)
+ show_who("caught signal");
+ fatal("");
+}
+
+PRIVATE void unsupported(option, message)
+char *option;
+char *message;
+{
+ show_who("compiler option ");
+ writes(option);
+ writes(" (");
+ writes(message);
+ writesn(") not supported yet");
+}
+
+PRIVATE void writen()
+{
+ writes("\n");
+}
+
+PRIVATE void writes(s)
+char *s;
+{
+ write(2, s, strlen(s));
+}
+
+PRIVATE void writesn(s)
+char *s;
+{
+ writes(s);
+ writen();
+}
diff --git a/bin86-0.3/bcc/bcc.doc b/bin86-0.3/bcc/bcc.doc
new file mode 100644
index 0000000..7f2a8ed
--- /dev/null
+++ b/bin86-0.3/bcc/bcc.doc
@@ -0,0 +1,165 @@
+Bcc options
+-----------
+
+bcc [-03EGOPSVcegv] [-Aas_option] [-Bexecutable_prefix] [-Ccc1_option]
+ [-Ddefine] [-Iinclude_dir] [-Lld_option] [-Qc386_option] [-Ttmpdir]
+ [-Uundef] [-o outfile] [-fpt error] [ld_options] [infiles]
+
+The 6809 version does not support -0, -3 or -G.
+Only the c386 version supports -Q.
+
+defaults (off or none except for these):
+-03 native
+outfile stdout for preprocessor output
+ somewhere/file.[ci] -> file.s for compiler output
+ somewhere/file.[cis] -> file.o for assembler output
+ a.out for ld output
+
+-0 8086 target (works even on 80386 host)
+-3 80386 target (works even on 8086 host)
+-A pass remainder of option to assembler (e.g. -A-l -Alistfile for a listing)
+-B prefix for executable search path (as usual; after the -B prefixes comes
+ the environment variable BCC_EXEC_PREFIX if that is set, followed by the
+ compiled-in default (something like /usr/libexec/i386/bcc/))
+-C pass remainder of option to cc1 (e.g. -C-c for caller-saves)
+-D define (as usual)
+-E produce preprocessor output (as usual)
+-G produce gnu-Minix objects (link with gnu ld)
+-I include search path (as usual)
+-L pass remainder of option to linker
+-O optimize (does nothing)
+-P produce preprocessor output with no line numbers (as usual)
+-Q pass full option to c386
+-S produce assembler file (as usual)
+-T temporary directory (overrides previous value and default; default is
+ from the environment variable TMPDIR if that is set, otherwise /tmp)
+-U undefine (as usual)
+-V print names of files being compiled
+-c produce object file (as usual)
+-e run the preprocess pass separately. This takes less memory, and may help
+ or harm by giving more traditional semantics like token pasting with /**/.
+-f error (float emulation not supported)
+-g produce debugging info (does nothing)
+-o output file name follows (assembler, object or executable) (as usual)
+-p error (profiling not supported)
+-t error (substitution of some cc passes not supported)
+-v print names and args of subprocesses being run
+
+Other options are passed to the linker, in particular -i-, -lx, -M, -m, -s.
+The -i option is always passed to the linker but can be cancelled using -i-.
+
+This is supposed to match the V7 manual except for -0, -3, -A, -C, -G, -L,
+-T, -V, -e, -v and where not supported.
+
+cc1 options
+----------
+
+cc1 [-03EPcdfltw[-]] [-Ddefine] [-Iinclude_dir] [-Uundef] [-o outfile] [infile]
+
+The 6809 version does not support -0 or -3 but it supports -p.
+
+defaults (off or none except for these):
+-03 native
+-c on for 6809
+-f on for 6809
+outfile stdout
+infile stdin
+
+-0 8086 target (works even on 80386 host)
+-3 80386 target (works even on 8086 host)
+-D define (as usual)
+-E produce preprocessor output (as usual)
+-I include search path (as usual)
+-P produce preprocessor output with no line numbers (as usual)
+-c produce code with caller saving regs before function calls
+-d print debugging information in assembly output
+-f produce code with 1st argument passed in a register
+-l produce code for 2 3 1 0 long byte order (only works in 16-bit versions)
+-o assembler output file name follows
+-p produce (almost) position-independent code
+-t print source code in assemby output
+-w print what cc1 thinks is the location counter in assembly output
+
+All the options except -D, -I and -o may be turned off by following the
+option letter by a '-'. Options are processed left to right so the last
+setting has precedence.
+
+The following is defined before option processing:
+
+__BCC__ 1
+
+The following may be defined after option processing:
+
+__AS09__ 1 if 6809 version
+__AS386_16__ 1 if -0 option on 80*86
+__AS386_32__ 1 if -3 option on 80*86
+__CALLER_SAVES__ 1 if -c option
+__FIRST_ARG_IN_AX__ 1 if -f option on 80*86
+__FIRST_ARG_IN_X__ 1 if -f option on 6809
+__LONG_BIG_ENDIAN__ 1 if -l option
+__POS_INDEPENDENT__ 1 if -p option on 6809
+
+The following are standard builtins:
+
+__FILE__ stringized name of current input file
+__LINE__ current line number
+
+As options
+----------
+
+as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src
+
+The 6809 version does not support -0, -3, -a or -j.
+
+defaults (off or none except for these; no output is produced without a flag):
+-03 native
+list stdout (beware of clobbering next arg)
+name basename of the source name
+
+-0 start with 16-bit code segment
+-3 start with 32-bit code segment
+-a enable partial compatibility with asld
+-b produce binary file, filename may follow (obsolete)
+-g only put global symbols in object file
+-j force all jumps to be long
+-l produce list file, filename may follow
+-m print macro expansions in listing
+-n name of module follows (goes in object instead of source name)
+-o produce object file, filename follows
+-s produce symbol file, filename follows (obsolete)
+-u take undefined symbols as imported-with-unspecified segment
+-w don't print warnings
+
+The -u and -w options are perhaps back to front because they are needed for
+cc1 output and Minix's make does the wrong thing with .s files left around.
+However, all assembler code not written by compilers should assemble with
+them turned off.
+
+Ld options
+----------
+
+For the version that produces Minix a.out format:
+ld [-03Mims[-]] [-T textaddr] [-llib_extension] [-o outfile] infile...
+
+For the version that produces gnu-Minix a.out format:
+ld [-03Mimrs[-]] [-T textaddr] [-llib_extension] [-o outfile] infile...
+
+The 6809 version does not support -i or -r.
+
+defaults (off or none except for these):
+-03 native
+outfile a.out
+
+-0 produce header with 16-bit magic and use subdir i86 for -lx
+-3 produce header with 32-bit magic and use subdir i386 for -lx
+-M print symbols linked on stdout
+-T text base address follows (in format suitable for strtoul)
+-i separate I&D output
+-lx add library /local/lib/subdir/libx.a to list of files linked
+-m print modules linked on stdout
+-o output file name follows
+-r produce output suitable for further relocation
+-s strip symbols
+
+All the options except -T, -l and -o may be turned off by following the option
+letter by a '-', as for cc1.
diff --git a/bin86-0.3/bccfp/Makefile b/bin86-0.3/bccfp/Makefile
new file mode 100644
index 0000000..6caa362
--- /dev/null
+++ b/bin86-0.3/bccfp/Makefile
@@ -0,0 +1,44 @@
+# Makefile for bcc 386 software floating point library
+
+.SUFFIXES: .x # .x files are .s files that need C-preprocessing
+.x.o:
+ $(CPP) $(CPPFLAGS) $< >tmp
+ $(AS) tmp -n $* -o $@
+
+AS =as -3
+CFLAGS =-O
+CPP =/lib/cpp
+CPPFLAGS =-P
+FPDIST =Makefile $(FPSRC) test.c bccfp.tex
+FPSRC =fadd.x fcomp.x fdiv.x fmul.x fbsr.x \
+ fperr.c fperror.x fptoi.x fpushd.x fpulld.x \
+ fpushi.x fpushf.x fpullf.x frexp.x ftst.x \
+ gcclib.x \
+ fabs.x ldexp.x modf.c \
+ fperr.h fplib.h
+FPOBJ =fadd.o fcomp.o fdiv.o fmul.o fpbsr.o \
+ fperr.o fperror.o fptoi.o fpushd.o fpulld.o \
+ fpushi.o fpushf.o fpullf.o frexp.o ftst.o \
+ fabs.o ldexp.o modf.o
+JUNK =tmp
+LIB =.
+
+test: test.c $(LIB)/libfp.a
+ $(CC) -o $@ test.c $(LIB)/libfp.a -lm
+
+$(FPOBJ): fplib.h
+fperr.c fperror.x: fperr.h
+
+$(LIB)/libfp.a: $(FPOBJ)
+ ar rc $(LIB)/libfp.a $(FPOBJ)
+ rm -f $(JUNK)
+
+dist: $(FPDIST)
+ /bin/tar cvf - $(FPDIST) | /bin/compress -b 13 >bccfp.tar.Z
+ uue bccfp.tar.Z
+
+clean:
+ rm -f $(FPOBJ) $(JUNK) test
+
+realclean: clean
+ rm -f $(LIB)/libfp.a bccfp.tar.Z bccfp.uue
diff --git a/bin86-0.3/bccfp/bccfp.tex b/bin86-0.3/bccfp/bccfp.tex
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin86-0.3/bccfp/bccfp.tex
diff --git a/bin86-0.3/bccfp/changes b/bin86-0.3/bccfp/changes
new file mode 100644
index 0000000..2cc632a
--- /dev/null
+++ b/bin86-0.3/bccfp/changes
@@ -0,0 +1,30 @@
+fcomp:
+Fixes for negative 0 (perhaps this shouldn't be generated, like denormals
+and infinities (these would cause even more trouble) but Fsub routine or
+something generated one).
+
+frexp.x:
+Deleted 3rd arg (used to return value when bcc wasn't doing it right).
+
+Fixed frexp(value = 0) and ldexp(value = 0) returning nonzero.
+
+Most files:
+Changed comment symbol to '!' for new assembler (not the native ';' in
+case this is ported to ACK someday).
+
+Avoided using ebp and unnecessary register saves.
+
+Changed assembler style to make it a bit more portable or like I do it
+(no '$' for hex, 8[esp] instead of [esp+8], use only .define and not export
+or .globl, use '#' (could use nothing) instead of '*' for immediate).
+The partly-supported 8(ebp) and .globl would be still more portable.
+
+Changed terminology 'mantissa' to 'fraction'.
+
+Round to even. Required for 'paranioa' not to find any defects.
+
+Used preprocessor.
+
+Parametrized most of the magic numbers. Phew!
+
+Supported denormals. Now 'paranioa' doesn't find any flaws.
diff --git a/bin86-0.3/bccfp/fabs.x b/bin86-0.3/bccfp/fabs.x
new file mode 100644
index 0000000..fe81676
--- /dev/null
+++ b/bin86-0.3/bccfp/fabs.x
@@ -0,0 +1,17 @@
+! bcc 386 floating point routines (version 2) -- _fabs
+! author: Bruce Evans
+
+#include "fplib.h"
+
+! double fabs(double value);
+! returns the absolute value of a number
+! this works for all NaNs, like the 80*87 fabs, but perhaps we should check
+! for exceptions that can happen when an 80*87 register is loaded
+
+ .globl _fabs
+ .align ALIGNMENT
+_fabs:
+ mov eax,PC_SIZE+D_LOW[esp]
+ mov edx,PC_SIZE+D_HIGH[esp]
+ and edx,~D_SIGN_MASK
+ ret
diff --git a/bin86-0.3/bccfp/fadd.x b/bin86-0.3/bccfp/fadd.x
new file mode 100644
index 0000000..d1e60b1
--- /dev/null
+++ b/bin86-0.3/bccfp/fadd.x
@@ -0,0 +1,485 @@
+! bcc 386 floating point routines (version 2)
+! -- Fadd, Faddd, Faddf, Fsub, Fsubd, Fsubf, normalize2
+! author: Bruce Evans
+
+#include "fplib.h"
+
+#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE)
+
+ .extern Fpushf
+ .extern fpdenormal
+ .extern fpoverflow
+ .extern fpunderflow
+
+ .globl Fadd
+ .align ALIGNMENT
+Fadd:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp]
+ mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp]
+ call addition
+ mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret #D_SIZE
+
+ .globl Faddd
+ .align ALIGNMENT
+Faddd:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ecx,D_HIGH[ebx]
+ mov ebx,D_LOW[ebx]
+ call addition
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .globl Faddf
+ .align ALIGNMENT
+Faddf:
+ push ebp
+ push edi
+ push esi
+ call Fpushf
+ pop ebx ! yl
+ pop ecx ! yu
+ mov eax,FRAME_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
+ call addition
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .globl Fsub
+ .align ALIGNMENT
+Fsub:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp]
+ mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp]
+ xor ecx,#D_SIGN_MASK ! complement sign
+ call addition
+ mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret #D_SIZE
+
+ .globl Fsubd
+ .align ALIGNMENT
+Fsubd:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ecx,D_HIGH[ebx]
+ mov ebx,D_LOW[ebx]
+ xor ecx,#D_SIGN_MASK ! complement sign
+ call addition
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .globl Fsubf
+ .align ALIGNMENT
+Fsubf:
+ push ebp
+ push edi
+ push esi
+ call Fpushf
+ pop ebx ! yl
+ pop ecx ! yu
+ mov eax,FRAME_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
+ xor ecx,#D_SIGN_MASK ! complement sign
+ call addition
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .align ALIGNMENT
+exp_y_0:
+
+! Check for x denormal, to split off special case where both are denormal,
+! so the norm bit (or 1 higher) is known to be set for addition, so addition
+! can be done faster
+
+ test esi,#D_EXP_MASK
+ jnz x_normal_exp_y_0
+ test esi,esi ! test top bits of x fraction
+ jnz both_denorm ! denormal iff nonzero fraction with zero exp
+ test eax,eax ! test rest of fraction
+ jz return_edx_eax ! everything 0 (XXX - do signs matter?)
+both_denorm:
+ call fpdenormal
+ test ebp,#D_SIGN_MASK
+ jnz denorm_subtract
+
+! Add denormal x to denormal or zero y
+
+#if D_NORM_BIT != D_EXP_SHIFT
+#include "error, carry into norm bit does not go into exponent"
+#endif
+
+ add eax,ebx
+ adc esi,edi
+ or edx,esi
+ ret
+
+denorm_subtract:
+ sub eax,ebx
+ sbb esi,edi
+ or edx,esi
+ ret
+
+ .align ALIGNMENT
+x_normal_exp_y_0:
+ test edi,edi ! this is like the check for x denormal
+ jnz y_denorm
+ test ebx,ebx
+ jz return_edx_eax ! y = 0
+y_denorm:
+ call fpdenormal
+ or ecx,#1 << D_EXP_SHIFT ! normalize y by setting exponent to 1
+ jmp got_y
+
+ .align ALIGNMENT
+return_edx_eax:
+ ret
+
+ .align ALIGNMENT
+add_bigshift:
+ cmp ecx,#D_FRAC_BIT+2
+ jae return_edx_eax ! x dominates y
+ sub ecx,#REG_BIT
+ shrd ebp,ebx,cl
+ shrd ebx,edi,cl
+ shr edi,cl
+ add eax,edi
+ adc esi,#0
+ xchg ebp,ebx
+ br normalize
+
+ .align ALIGNMENT
+addition:
+ mov esi,edx ! this mainly for consistent naming
+ and esi,#D_EXP_MASK | D_FRAC_MASK ! discard sign so comparison is simple
+ mov edi,ecx ! free cl for shifts
+ and edi,#D_EXP_MASK | D_FRAC_MASK
+ cmp esi,edi
+ ja xbigger
+ jb swap
+ cmp eax,ebx
+ jae xbigger
+swap:
+ xchg edx,ecx
+ xchg eax,ebx
+ xchg esi,edi
+xbigger:
+
+! edx holds sign of result from here on
+! and exponent of result before the normalization step
+
+ mov ebp,edx ! prepare difference of signs
+ xor ebp,ecx
+
+ and ecx,#D_EXP_MASK ! extract exp_y and check for y 0 or denormal
+ beq exp_y_0 ! otherwise x is not 0 or denormal either
+ and edi,#D_FRAC_MASK ! extract fraction
+ or edi,#D_NORM_MASK ! normalize
+got_y:
+ and esi,#D_FRAC_MASK ! extract fraction
+ or esi,#D_NORM_MASK ! normalize
+
+ sub ecx,edx ! carries from non-exp bits in edx killed later
+ neg ecx
+ and ecx,#D_EXP_MASK
+ shr ecx,#D_EXP_SHIFT ! difference of exponents
+
+got_x_and_y:
+ and ebp,#D_SIGN_MASK ! see if signs are same
+ bne subtract ! else roundoff reg ebp has been cleared
+
+ cmp cl,#REG_BIT
+ bhis add_bigshift
+ shrd ebp,ebx,cl
+ shrd ebx,edi,cl
+ shr edi,cl
+ add eax,ebx
+ adc esi,edi
+
+! result edx(D_SIGN_MASK | D_EXP_MASK bits):esi:eax:ebp but needs normalization
+
+ mov edi,edx
+ and edi,#D_EXP_MASK
+ test esi,#D_NORM_MASK << 1
+ jnz add_loverflow
+
+add_round:
+ cmp ebp,#1 << (REG_BIT-1) ! test roundoff register
+ jb add_done ! no rounding
+ jz tie
+add_roundup:
+ add eax,#1
+ adc esi,#0
+ test esi,#D_NORM_MASK << 1
+ jnz pre_add_loverflow ! rounding may cause overflow!
+add_done:
+ mov ecx,edx ! duplicated code from 'done'
+ and edx,#D_SIGN_MASK
+ or edx,edi
+ and esi,#D_FRAC_MASK
+ or edx,esi
+ ret
+
+ .align ALIGNMENT
+tie:
+ test al,#1 ! tie case, round to even
+ jz add_done ! even, no rounding
+ jmp add_roundup
+
+ .align ALIGNMENT
+pre_add_loverflow:
+ sub ebp,ebp ! clear rounding register
+ ! probably avoiding tests for more rounding
+add_loverflow:
+ shrd ebp,eax,#1
+ jnc over_set_sticky_bit
+ or ebp,#1
+over_set_sticky_bit:
+ shrd eax,esi,#1
+ shr esi,#1
+ add edi,1 << D_EXP_SHIFT
+ cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT
+ jl add_round
+overflow:
+ call fpoverflow
+ mov eax,ecx ! XXX - wrong reg
+ ret
+
+! result edx(D_SIGN_MASK | D_EXP_MASK bits):
+! esi((D_NORM_MASK << 1) | D_NORM_MASK | D_FRAC_MASK bits):eax:ebp:ebx
+! but needs normalization
+
+ .align ALIGNMENT
+normalize:
+ mov edi,edx
+ and edi,#D_EXP_MASK
+ test esi,#D_NORM_MASK << 1
+ bne loverflow
+
+! result edx(D_SIGN_MASK bit):edi(D_EXP_MASK bits):
+! esi(D_NORM_MASK | D_FRAC_MASK bits):eax:ebp:ebx
+! but needs normalization
+
+ .globl normalize2
+normalize2:
+ test esi,#D_NORM_MASK ! already-normalized is very common
+ jz normalize3
+round:
+ cmp ebp,#1 << (REG_BIT-1) ! test roundoff register
+ jb done ! no rounding
+ jz near_tie
+roundup:
+ add eax,#1
+ adc esi,#0
+ test esi,#D_NORM_MASK << 1
+ bne pre_loverflow ! rounding may cause overflow!
+done:
+cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT
+jae overflow
+ and edx,#D_SIGN_MASK ! extract sign of largest and result
+ or edx,edi ! include exponent with sign
+ and esi,#D_FRAC_MASK ! discard norm bit
+ or edx,esi ! include fraction with sign and exponent
+ ret
+
+ .align ALIGNMENT
+near_tie:
+ test ebx,ebx
+ jnz roundup
+ test al,#1 ! tie case, round to even
+ jz done ! even, no rounding
+ jmp roundup
+
+ .align ALIGNMENT
+not_in_8_below:
+ shld ecx,esi,#REG_BIT-D_NORM_BIT+16 ! in 9 to 16 below?
+ jz not_in_16_below ! must be way below (17-20 for usual D_NORM_BIT)
+ mov cl,bsr_table[ecx] ! bsr(esi) - (D_NORM_BIT-16)
+ neg ecx ! (D_NORM_BIT-16) - bsr(esi)
+ add ecx,#16
+ jmp got_shift
+
+ .align ALIGNMENT
+not_in_16_below:
+ mov cl,bsr_table[esi] ! bsr(esi) directly
+ neg ecx ! -bsr(esi)
+ add ecx,#D_NORM_BIT ! D_NORM_BIT - bsr(esi)
+ jmp got_shift
+
+ .align ALIGNMENT
+normalize3:
+ test esi,esi
+ jz shift32
+
+! Find first nonzero bit in esi
+! Don't use bsr, it is very slow (const + 3 * bit_found)
+! We know that there is some nonzero bit, and the norm bit and above are clear
+
+ sub ecx,ecx ! prepare unsigned extension of cl
+ shld ecx,esi,#REG_BIT-D_NORM_BIT+8 ! any bits in 8 below norm bit?
+ jz not_in_8_below
+ mov cl,bsr_table[ecx] ! bsr(esi) - (D_NORM_BIT-8)
+ neg ecx ! (D_NORM_BIT-8) - bsr(esi)
+ add ecx,#8 ! D_NORM_BIT - bsr(esi)
+got_shift:
+ shld esi,eax,cl
+ shld eax,ebp,cl
+ shld ebp,ebx,cl
+ shl ebx,cl
+ shl ecx,D_EXP_SHIFT
+ sub edi,ecx
+ bhi round ! XXX - can rounding change the exponent to > 0?
+ ! not bgt since edi may be 0x80000000
+ neg edi
+ shr edi,#D_EXP_SHIFT
+ inc edi
+ br fpunderflow
+
+ .align ALIGNMENT
+pre_loverflow:
+ sub ebp,ebp ! clear rounding registers
+ sub ebx,ebx ! probably avoiding tests for more rounding
+
+loverflow:
+ shr esi,#1 ! carry bit stayed in the reg
+ rcr eax,#1
+ rcr ebp,#1
+ rcr ebx,#1
+ add edi,1 << D_EXP_SHIFT
+ cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT
+ blt round
+ call fpoverflow
+ mov eax,ecx ! XXX - wrong reg
+ ret
+
+ .align ALIGNMENT
+shift32:
+ test eax,eax
+ jz shift64
+ mov esi,eax
+ mov eax,ebp
+ mov ebp,ebx
+ sub ebx,ebx
+ sub edi,#REG_BIT << D_EXP_SHIFT
+shiftxx:
+ test esi,#~(D_NORM_MASK | D_FRAC_MASK)
+ jz over_adjust ! else too big already
+ shrd ebx,ebp,#D_BIT-D_FRAC_BIT
+ shrd ebp,eax,#D_BIT-D_FRAC_BIT
+ shrd eax,esi,#D_BIT-D_FRAC_BIT
+ shr esi,#D_BIT-D_FRAC_BIT
+ add edi,#(D_BIT-D_FRAC_BIT) << D_EXP_SHIFT
+over_adjust:
+ test edi,edi
+ bgt normalize2
+ neg edi
+ shr edi,#D_EXP_SHIFT
+ inc edi
+ br fpunderflow
+
+ .align ALIGNMENT
+shift64:
+ test ebp,ebp
+ jz shift96
+ mov esi,ebp
+ mov eax,ebx
+ sub ebp,ebp
+ mov ebx,ebp
+ sub edi,#(2*REG_BIT) << D_EXP_SHIFT
+ jmp shiftxx
+
+ .align ALIGNMENT
+shift96:
+ test ebx,ebx ! XXX - this test is probably unnecessary
+ ! since the shift must be small unless we
+ ! are subtracting 2 almost-equal numbers,
+ ! and then the bits beyond 64 will mostly
+ ! be 0
+ jz return_esi_eax ! all zero
+ mov esi,ebx
+ sub ebx,ebx
+ sub edi,#(3*REG_BIT) << D_EXP_SHIFT
+ jmp shiftxx
+
+ .align ALIGNMENT
+return_esi_eax:
+ mov edx,esi
+ ret
+
+ .align ALIGNMENT
+subtract:
+ sub ebp,ebp ! set up roundoff register
+ cmp ecx,#REG_BIT
+ jae subtract_bigshift
+ shrd ebp,ebx,cl
+ shrd ebx,edi,cl
+ shr edi,cl
+ neg ebp ! begin subtraction esi:eax:0 - edi:ebx:ebp
+ sbb eax,ebx
+ sbb esi,edi
+ sub ebx,ebx
+ mov edi,edx
+ and edi,#D_EXP_MASK
+ br normalize2
+
+ .align ALIGNMENT
+subtract_bigshift:
+ cmp ecx,#D_FRAC_BIT+2
+ bhis return_edx_eax ! x dominates y
+ sub ecx,#REG_BIT
+ shrd ebp,ebx,cl
+ shrd ebx,edi,cl
+ shr edi,cl
+ not ebp ! begin subtraction esi:eax:0:0 - 0:edi:ebx:ebp
+ not ebx
+ add ebp,#1
+ adc ebx,#0
+ cmc
+ sbb eax,edi
+ sbb esi,#0
+ xchg ebp,ebx
+ mov edi,edx
+ and edi,#D_EXP_MASK
+ br normalize2
+
+ .data
+ .extern bsr_table
diff --git a/bin86-0.3/bccfp/fcomp.x b/bin86-0.3/bccfp/fcomp.x
new file mode 100644
index 0000000..71148ab
--- /dev/null
+++ b/bin86-0.3/bccfp/fcomp.x
@@ -0,0 +1,89 @@
+! bcc 386 floating point routines (version 2) -- Fcomp, Fcompd, Fcompf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern Fpushf
+
+! Pop 2 doubles from stack and compare them, return result in flags so
+! normal signed branches work (unlike 80x87 which returns the result in
+! the zero and carry flags).
+
+ .globl Fcomp
+ .align ALIGNMENT
+Fcomp:
+ pop ecx ! get return address
+ pop eax ! xl
+ pop edx ! xu
+ push ecx ! put back ret address - pop 2nd double later
+
+! All this popping is bad on 486's since plain mov takes 1+ cycle and pop
+! takes 4 cycles. But this code is designed for 386's where popping is
+! nominally the same speed and saves code space and so maybe instruction
+! fetch time as well as the instruction to adjust the stack (ret #n takes
+! no longer than plain ret but inhibits gotos).
+
+ mov ebx,PC_SIZE+D_LOW[esp] ! yl
+ mov ecx,PC_SIZE+D_HIGH[esp] ! yu
+ jmp compare
+
+! Pop double from stack and compare with double at [ebx]
+
+ .globl Fcompd
+ .align ALIGNMENT
+Fcompd:
+ mov eax,PC_SIZE+D_LOW[esp] ! xl
+ mov edx,PC_SIZE+D_HIGH[esp] ! xu
+ mov ecx,D_HIGH[ebx] ! yu
+ mov ebx,D_LOW[ebx] ! yl
+
+compare:
+ test edx,#D_SIGN_MASK ! is x >= 0?
+ jz cmp0 ! yes; just compare x and y
+ test ecx,#D_SIGN_MASK ! no; but is y >= 0?
+ jz cmp0 ! yes; just compare x and y
+
+ xchg edx,ecx ! x, y < 0, so ...
+ xchg eax,ebx ! ... swap x and y ...
+ xor edx,#D_SIGN_MASK ! ... and toggle signs
+ xor ecx,#D_SIGN_MASK
+
+cmp0:
+ cmp edx,ecx ! compare upper dwords
+ jnz checkneg0 ! if upper dwords differ, job is almost done
+ mov edx,eax ! upper dwords equal, so ...
+ mov ecx,ebx ! ... must make unsigned comparison of lower dwords
+ shr edx,#1 ! shift past sign
+ shr ecx,#1
+ cmp edx,ecx ! compare top 31 bits of lower dwords
+ jnz return ! if these differ, job is done
+ and eax,#1 ! compare lowest bits
+ and ebx,#1
+ cmp eax,ebx
+
+return:
+ ret #D_SIZE ! return, popping 1 double from stack
+
+checkneg0:
+ test edx,#D_EXP_MASK | D_FRAC_MASK ! check to catch unusual case ...
+ jnz recheck
+ test eax,eax
+ jnz recheck
+ test ecx,#D_EXP_MASK | D_FRAC_MASK
+ jnz recheck
+ test ebx,ebx
+ jz return ! ... both are (+-) zero, return 'z'
+
+recheck:
+ cmp edx,ecx ! the upper words were really different
+ ret #D_SIZE
+
+ .globl Fcompf
+ .align ALIGNMENT
+Fcompf:
+ call Fpushf
+ pop ebx ! yl
+ pop ecx ! yu
+ mov eax,PC_SIZE+D_LOW[esp] ! xl
+ mov edx,PC_SIZE+D_HIGH[esp] ! xu
+ jmp compare
diff --git a/bin86-0.3/bccfp/fdiv.x b/bin86-0.3/bccfp/fdiv.x
new file mode 100644
index 0000000..4a5cf74
--- /dev/null
+++ b/bin86-0.3/bccfp/fdiv.x
@@ -0,0 +1,312 @@
+#define EF_SIZE 4
+
+! bcc 386 floating point routines (version 2) -- Fdiv, Fdivd, Fdivf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE)
+
+ .extern Fpushf
+ .extern fpdivzero
+ .extern fpoverflow
+ .extern fpunderflow
+
+! double Fdiv(double x, double y) returns x / y
+
+! pop 2 doubles from stack, divide first by second, and push quotient on stack
+
+! we denote upper and lower dwords of x and y (or their fractions)
+! by (xu,xl), (yu,yl)
+
+ .globl Fdivf
+ .align ALIGNMENT
+Fdivf:
+ sub esp,#D_SIZE ! make space for dummy double on stack
+ push ebp
+ push edi ! save some regs
+ push esi
+ mov eax,FRAME_SIZE-PC_SIZE+D_SIZE[esp] ! move return address ...
+ mov FRAME_SIZE-PC_SIZE[esp],eax ! ... to usual spot
+ call Fpushf
+ pop esi ! yl
+ pop edi ! yu
+ mov eax,FRAME_SIZE+D_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! xu
+ jmp division
+
+ .globl Fdiv
+ .align ALIGNMENT
+Fdiv:
+ push ebp
+ push edi ! save some regs
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
+ mov esi,FRAME_SIZE+D_SIZE+D_LOW[esp] ! yl
+ mov edi,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! yu
+ jmp division
+
+ .align ALIGNMENT
+exp_y_0:
+ mov ebx,edi
+ or ebx,esi
+ beq zerodivide
+ mov ebx,#1
+fix_y:
+ test edi,edi ! XXX - sloow
+ js y_unpacked
+ shld edi,esi,#1
+ shl esi,#1
+ dec bx
+ jmp fix_y
+
+ .align ALIGNMENT
+exp_x_0:
+ mov ecx,edx
+ or ecx,eax
+ beq retz
+ mov ecx,#1 ! change exponent from 0 to 1
+fix_x:
+ test edx,#1 << (REG_BIT-1-2) ! XXX - sloow
+ jnz x_unpacked
+ shld edx,eax,#1
+ shl eax,#1
+ dec cx
+ jmp fix_x
+
+! Fdivd pops double from stack, divides it by double at [ebx],
+! and pushes quotient back on stack
+
+ .globl Fdivd
+ .align ALIGNMENT
+Fdivd:
+ sub esp,#D_SIZE ! make space for dummy double on stack
+ push ebp
+ push edi ! save some regs
+ push esi
+ mov eax,FRAME_SIZE-PC_SIZE+D_SIZE[esp] ! move return address ...
+ mov FRAME_SIZE-PC_SIZE[esp],eax ! ... to usual spot
+ mov eax,FRAME_SIZE+D_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! xu
+ mov esi,D_LOW[ebx] ! yl
+ mov edi,D_HIGH[ebx] ! yu
+
+division:
+
+! The full calculations are
+
+! (xu,xl,0) = yu * (zu,zl) + (0,r,0) (normal 96/32 -> 64 bit division)
+! yl * zu = yu * q1 + r1 (32*32 -> 64 bit mul and 64/32 -> 32 bit div)
+
+! so
+
+! (xu,xl,0,0) = (yu,yl) * (zu,zl-q1) + (0,0,r-r1,yl*(q1-zl))
+
+! where the calculations zl-q1, r-r1 and yl*(q1-zl) are more complicated
+! than the notation suggests. They may be negative and the one with the
+! multiplication may not fit in 32 bits and in both cases the overflow
+! has to be moved into higher bit positions.
+
+! See Knuth for why (zu,zl-q1) is the correct 64-bit quotient to within
+! 1 bit either way (assuming the normalization x < 2 * y).
+
+! We only need to calculate the remainder (0,0,r-r1,yl*(q1-zl)) to resolve
+! tie cases. It tells whether the approximate quotient is too high or too
+! low.
+
+#define NTEMPS 5
+
+ sub esp,#NTEMPS*GENREG_SIZE ! space to remember values for rounding of tie case
+
+! Offsets from esp for these values (offsets using FRAME_SIZE are invalid
+! while these temps are active)
+r = 0
+q1 = 4
+r1 = 8
+yl = 12
+zl = 16
+
+! Step 1: unpack and normalize x to fraction in edx:eax (left shifted as
+! far as possible less 2 so that x < y, and later z < y); unpack and normalize
+! y to a fraction in edi:esi (left shifted as far as possible), put difference
+! of signs (= sign of quotient) in ecx(D_SIGN_MASK) and difference of exponents
+! (= exponent of quotient before normalization) in cx.
+
+ mov ebp,edx ! xu
+ xor ebp,edi ! xu ^ yu
+ and ebp,#D_SIGN_MASK ! sign of result is difference of signs
+
+! Unpack y first to trap 0 / 0
+
+ mov ebx,edi ! remember yu for exponent of y
+ shld edi,esi,#D_BIT-D_FRAC_BIT ! extract fraction of y ...
+ shl esi,#D_BIT-D_FRAC_BIT
+ and ebx,#D_EXP_MASK ! exponent of y
+ jz exp_y_0
+ shr ebx,#D_EXP_SHIFT ! in ebx (actually in bx, with high bits 0)
+ or edi,#D_NORM_MASK << (D_BIT-D_FRAC_BIT) ! normalize
+y_unpacked:
+
+! Unpack x
+
+ mov ecx,edx ! remember xu for exponent of x
+ shld edx,eax,#D_BIT-D_FRAC_BIT-2 ! extract fraction of x ...
+ shl eax,#D_BIT-D_FRAC_BIT-2
+ and edx,#(D_NORM_MASK << (D_BIT-D_FRAC_BIT-2+1))-1
+ ! XXX - above may be shifted 1 extra unnecessarily
+ and ecx,#D_EXP_MASK ! exponent of x
+ jz exp_x_0
+ shr ecx,#D_EXP_SHIFT ! in ecx (actually in cx, with high bits 0)
+ or edx,#D_NORM_MASK << (D_BIT-D_FRAC_BIT-2) ! normalize
+x_unpacked:
+
+ sub cx,bx ! not ecx,ebx because we want to use high bit for sign
+ add cx,#D_EXP_BIAS ! adjust exponent of quotient
+
+ or ecx,ebp ! include sign with exponent
+
+! Step 2: quotient of fractions -> (edx,eax)
+
+! 2a: (xu,xl,0) div yu = (zu,zl) -> (ebx,esi)
+
+ div eax,edi ! (xu,xl) div yu = zu in eax; remainder (rem) in edx
+ mov ebx,eax ! save zu in ebx
+ sub eax,eax ! clear eax: (edx,eax) = (rem,0)
+ div eax,edi ! (rem,0) div yu = zl in eax
+ mov r[esp],edx
+ mov zl[esp],eax
+ xchg eax,esi ! store zl in esi; save yl in eax
+ mov yl[esp],eax
+
+! 2b: (yl * zu) div yu -> (0,eax)
+
+ mul eax,ebx ! yl * zu -> (edx,eax)
+ div eax,edi ! (yl * zu) div yu in eax
+ mov q1[esp],eax
+ mov r1[esp],edx
+
+! 2c: (xu,xl) / (yu,yl) = (zu,zl) - (yl * zu) div yu -> (edx,eax)
+
+ mov edx,ebx ! zu
+ xchg eax,esi ! eax <- zl; esi <- (yl * zu) div yu
+ sub eax,esi
+ sbb edx,#0
+
+! Step 3: normalise quotient
+
+ test edx,#1 << (REG_BIT-2) ! is fraction too small? (can only be by 1 bit)
+ jnz div4
+ shld edx,eax,#1 ! yes; multiply fraction ...
+ shl eax,#1 ! ... by 2 ...
+ dec cx ! ... and decrement exponent
+
+! Step 4: shift and round
+
+div4:
+ mov ebx,eax ! save for rounding
+ shrd eax,edx,#D_BIT-D_FRAC_BIT-1 ! shift fraction of result ...
+ shr edx,#D_BIT-D_FRAC_BIT-1 ! ... to proper position
+ and ebx,#(1 << (D_BIT-D_FRAC_BIT-1))-1 ! look at bits shifted out
+ cmp ebx,#D_NORM_MASK >> (D_BIT-D_FRAC_BIT) ! compare with middle value
+ jb div5 ! below middle, don't round up
+ ja roundup ! above middle, round up
+
+! The low bits don't contain enough information to resolve the tie case,
+! because the quotient itself is only an approximation.
+! Calculate the exact remainder.
+! This case is not very common, so don't worry much about speed.
+! Unfortunately we had to save extra in all cases to prepare for it.
+
+ push edx
+ push eax
+
+ sub esi,esi ! the calculation requires 33 bits - carry to here
+ mov eax,2*GENREG_SIZE+q1[esp]
+ sub eax,2*GENREG_SIZE+zl[esp]
+ pushfd
+ mul dword EF_SIZE+2*GENREG_SIZE+yl[esp]
+ popfd
+ jnc foo
+ sub edx,2*GENREG_SIZE+yl[esp]
+ sbb esi,#0
+foo:
+ add edx,2*GENREG_SIZE+r[esp]
+ adc esi,#0
+ sub edx,2*GENREG_SIZE+r1[esp]
+ sbb esi,#0
+ mov ebx,eax
+ mov edi,edx
+
+ pop eax
+ pop edx
+
+! Can finally decide rounding of tie case
+
+ js div5 ! remainder < 0 from looking at top 64 bits
+ jnz roundup ! remainder > 0 from looking at top 64 bits
+ or edi,ebx ! test bottom 64 bits
+ jnz roundup ! remainder > 0
+
+ test al,#1 ! at last we know it is the tie case, check parity bit
+ jz div5 ! already even, otherwise round up to make even
+
+roundup:
+ add eax,#1 ! add rounding bit
+ adc edx,#0
+ test edx,#D_NORM_MASK << 1 ! has fraction overflowed (very unlikely)
+ jz div5
+! Why were the shifts commented out?
+ shrd eax,edx,#1 ! yes, divide fraction ...
+ shr edx,#1 ! ... by 2 ...
+ inc cx ! ... and increment exponent
+
+! Step 5: put it all together
+
+div5:
+ mov ebx,ecx ! extract sign
+ and ebx,D_SIGN_MASK
+ cmp cx,#D_EXP_INFINITE ! is exponent too big?
+ jge overflow
+ test cx,cx
+ jle underflow
+ shl ecx,#D_EXP_SHIFT
+
+ and edx,#D_FRAC_MASK ! remove norm bit
+ or edx,ecx ! include exponent ...
+ or edx,ebx ! ... and sign
+
+return:
+ add esp,#NTEMPS*GENREG_SIZE ! reclaim temp space
+ mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax ! "push" lower dword of product ...
+ mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx ! ... and upper dword
+ pop esi ! restore registers
+ pop edi
+ pop ebp
+ ret #D_SIZE
+
+retz:
+ sub edx,edx ! clear upper dword
+ sub eax,eax ! ... and lower dword
+ jmp return
+
+overflow:
+ mov edx,ecx ! put sign in usual reg
+ call fpoverflow
+ mov eax,ecx ! XXX - wrong reg
+ jmp return
+
+underflow:
+ mov esi,edx ! put upper part of fraction in usual reg
+ mov edx,ecx ! sign
+ movsx edi,cx ! put shift in usual reg
+ neg edi
+ inc edi
+ call fpunderflow
+ jmp return
+
+zerodivide:
+ mov edx,ebp ! sign
+ call fpdivzero
+ mov eax,ecx ! XXX - wrong reg
+ jmp return
diff --git a/bin86-0.3/bccfp/fmul.x b/bin86-0.3/bccfp/fmul.x
new file mode 100644
index 0000000..aa62b5c
--- /dev/null
+++ b/bin86-0.3/bccfp/fmul.x
@@ -0,0 +1,150 @@
+! bcc 386 floating point routines (version 2) -- Fmul, Fmuld, Fmulf
+! author: Bruce Evans
+
+#include "fplib.h"
+
+#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE)
+
+ .extern Fpushf
+ .extern fpoverflow
+ .extern fpunderflow
+ .extern normalize2
+
+ .globl Fmul
+ .align ALIGNMENT
+Fmul:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp]
+ mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp]
+ call multiplication
+ mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret #D_SIZE
+
+ .globl Fmuld
+ .align ALIGNMENT
+Fmuld:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ecx,D_HIGH[ebx]
+ mov ebx,D_LOW[ebx]
+ call multiplication
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .globl Fmulf
+ .align ALIGNMENT
+Fmulf:
+ push ebp
+ push edi
+ push esi
+ call Fpushf
+ pop ebx ! yl
+ pop ecx ! xu
+ mov eax,FRAME_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
+ call multiplication
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .align ALIGNMENT
+exp_x_0:
+ mov edx,#1 << D_EXP_SHIFT ! change exponent from 0 to 1
+ jmp x_unpacked ! XXX - check for denormal?
+
+ .align ALIGNMENT
+exp_y_0:
+ mov ecx,#1 << D_EXP_SHIFT
+ jmp y_unpacked
+
+ .align ALIGNMENT
+multiplication:
+ mov ebp,edx ! xu
+ xor ebp,ecx ! xu ^ yu
+ and ebp,#D_SIGN_MASK ! sign of result is difference of signs
+
+ mov esi,edx ! free edx for multiplications
+ and esi,#D_FRAC_MASK ! discard sign and exponent
+ and edx,#D_EXP_MASK ! exponent(x)
+ jz exp_x_0
+ or esi,#D_NORM_MASK ! normalize
+x_unpacked:
+
+ mov edi,ecx ! this mainly for consistent naming
+ and edi,#D_FRAC_MASK
+ and ecx,#D_EXP_MASK ! exponent(y)
+ jz exp_y_0
+ or edi,#D_NORM_MASK
+y_unpacked:
+
+ add ecx,edx ! add exponents
+
+! exponent is in ecx, sign in ebp, operands in esi:eax and edi:ebx, edx is free
+! product to go in esi:eax:ebp:ebx
+! terminology: x * y = (xu,xl) * (yu,yl)
+! = (xu * yu,0,0) + (0,xu * yl + xl * yu,0) + (0,0,xl * yl)
+
+ push ecx
+ push ebp
+ mov ecx,eax
+ mul ebx ! xl * yl
+ mov ebp,edx ! (xl * yl).u in ebp
+ xchg ebx,eax ! (xl * yl).l in ebx (final), yl in eax
+ mul esi ! xu * yl
+ push eax ! (xu * yl).l on stack
+ push edx ! (xu * yl).u on stack
+ mov eax,esi ! xu
+ mul edi ! xu * yu
+ mov esi,edx ! (xu * yu).u in esi (final except carries)
+ xchg ecx,eax ! (xu * yu).l in ecx, xl in eax
+ mul edi ! xl * yu
+
+ add ebp,eax ! (xl * yl).u + (xl * yu).l
+ pop eax ! (xu * yl).u
+ adc eax,edx ! (xu * yl).u + (xl * yu).u
+ adc esi,#0
+ pop edx ! (xu * yl).l
+ add ebp,edx ! ((xl * yl).u + (xl * yu).l) + (xu * yl).l
+ adc eax,ecx ! ((xu * yl).u + (xl * yu).u) + (xu * yu).l
+ adc esi,#0
+ pop edx ! sign
+ pop edi ! exponent
+ sub edi,#(D_EXP_BIAS+1-(D_EXP_BIT+2)) << D_EXP_SHIFT ! adjust
+! cmp edi,#(D_EXP_INFINITE-1+(D_EXP_BIT+2)) << D_EXP_SHIFT
+! jae outofbounds ! 0 will be caught as underflow by normalize2
+cmp edi,#(2*D_EXP_INFINITE-(D_EXP_BIAS+1)+(D_EXP_BIT+2)) << D_EXP_SHIFT
+ja underflow
+ br normalize2
+
+ .align ALIGNMENT
+overflow:
+ mov edx,ebp ! put sign in usual reg
+ call fpoverflow
+ mov eax,ecx ! XXX - wrong reg
+ ret
+
+ .align ALIGNMENT
+underflow:
+ mov edx,ebp ! put sign in usual reg
+ neg edi
+ shr edi,#D_EXP_SHIFT
+ inc edi
+ br fpunderflow
diff --git a/bin86-0.3/bccfp/fpbsr.x b/bin86-0.3/bccfp/fpbsr.x
new file mode 100644
index 0000000..8ff38d7
--- /dev/null
+++ b/bin86-0.3/bccfp/fpbsr.x
@@ -0,0 +1,25 @@
+! bcc 386 floating point routines (version 2) -- bsr_table
+! author: Bruce Evans
+
+#include "fplib.h"
+
+ .globl bsr_table
+ .data
+ .align ALIGNMENT
+bsr_table: ! table to replace bsr on range 0-255
+.byte -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
+.byte 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+.byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+.byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
diff --git a/bin86-0.3/bccfp/fperr.c b/bin86-0.3/bccfp/fperr.c
new file mode 100644
index 0000000..d5372dc
--- /dev/null
+++ b/bin86-0.3/bccfp/fperr.c
@@ -0,0 +1,50 @@
+/*
+ * bin86/bccfp/fperr.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+#include <stdio.h>
+#include <signal.h>
+
+#include "fperr.h"
+
+void fperr(errno)
+int errno;
+{
+
+#if defined(DEBUG) || 0
+ switch(errno) {
+
+ case EFDENORMAL:
+ fputs("\nDenormal - ", stderr);
+ break;
+
+ case EFINFINITY:
+ fputs("\nInfinity - ", stderr);
+ break;
+
+ case EFNAN:
+ fputs("\nNaN - ", stderr);
+ break;
+
+ case EFOVERFLOW:
+ fputs("\nOverflow - ", stderr);
+ break;
+
+ case EFUNDERFLOW:
+ fputs("\nUnderflow - ", stderr);
+ break;
+
+ case EFDIVZERO:
+ fputs("\nZero divide - ", stderr);
+ break;
+
+ default:
+ fprintf(stderr, "\nUnknown error 0x%x - ", errno);
+ }
+ fflush(stderr);
+#endif
+
+ kill(getpid(), SIGFPE);
+}
diff --git a/bin86-0.3/bccfp/fperr.h b/bin86-0.3/bccfp/fperr.h
new file mode 100644
index 0000000..42d54fd
--- /dev/null
+++ b/bin86-0.3/bccfp/fperr.h
@@ -0,0 +1,14 @@
+/*
+ * bin86/bccfp/fperr.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* fperr.h */
+
+#define EFDENORMAL 1
+#define EFINFINITY 2
+#define EFNAN 3
+#define EFOVERFLOW 4
+#define EFUNDERFLOW 5
+#define EFDIVZERO 6
diff --git a/bin86-0.3/bccfp/fperror.x b/bin86-0.3/bccfp/fperror.x
new file mode 100644
index 0000000..04f3f74
--- /dev/null
+++ b/bin86-0.3/bccfp/fperror.x
@@ -0,0 +1,126 @@
+! bcc 386 floating point routines (version 2)
+! --- fpdenormal, fperror, fpinfinity, fpNaN, fpoverflow, fpunderflow,fpdivzero
+! author: Bruce Evans
+
+#include "fperr.h"
+#include "fplib.h"
+
+ .extern _fperr
+
+! Cause a denormal-operand exception
+! Preserves all general registers if signal handler returns
+
+ .globl fpdenormal
+ .align ALIGNMENT
+fpdenormal:
+#if 0
+ push eax
+ mov eax,#EFDENORMAL
+ call fperror
+ pop eax
+#endif
+ ret
+
+! Cause an exception with error code eax, preserving all genregs except eax
+
+ .globl fperror
+ .align ALIGNMENT
+fperror:
+ push ebp ! set up usual frame ...
+ mov ebp,esp ! ... for debugging
+ push edx ! save default
+ push ecx
+ push eax ! error code is arg to C routine
+ call _fperr
+ add esp,#GENREG_SIZE
+ pop ecx ! restore default
+ pop edx
+ pop ebp
+ ret
+
+ .align ALIGNMENT
+fphuge:
+ mov ecx,#D_HUGE_LOW ! prepare number +-HUGEVAL
+ or edx,#D_HUGE_HIGH ! ... in case signal handler returns
+ jmp fperror
+
+! Cause an infinite-operand exception
+! Return +-HUGEVAL in edx:ecx with sign from edx
+
+ .globl fpinfinity
+ .align ALIGNMENT
+fpinfinity:
+ mov eax,#EFINFINITY
+ jmp fphuge ! almost right
+
+! Cause an NaN-operand exception
+! Return +-HUGEVAL in edx:ecx with sign from edx
+
+ .globl fpNaN
+ .align ALIGNMENT
+fpNaN:
+ mov eax,#EFNAN ! there are different types of NaNs but...
+ jmp fphuge ! WRONG
+
+! Cause an overflow exception
+! Return +-HUGEVAL in edx:ecx with sign from edx
+
+ .globl fpoverflow
+ .align ALIGNMENT
+fpoverflow:
+ mov eax,#EFOVERFLOW
+ jmp fphuge ! almost right
+
+! Cause an underflow exception (actually assume it is masked for now)
+! Return denormal or 0.0 in edx:ecx
+! XXX - this should cause a denormal exception or none for the denormal case
+! Args: sign in edx, fraction in esi:eax, right shift in edi
+! Returns: denormalized number in edx:eax
+
+ .globl fpunderflow
+ .align ALIGNMENT
+fpunderflow:
+#if 0
+ mov eax,#EFUNDERFLOW
+ jmp fperror
+#endif
+ cmp edi,#REG_BIT
+ jb denormalize1
+ mov eax,esi
+ sub esi,esi
+ sub edi,#REG_BIT
+ cmp edi,#REG_BIT
+ jb denormalize1
+denormalize_underflow:
+#if 0
+ mov eax,#EFUNDERFLOW
+ jmp fperror
+#endif
+ sub eax,eax
+ mov edx,eax
+ ret
+
+ .align ALIGNMENT
+denormalize1:
+ mov ecx,edi
+ shrd eax,esi,cl
+ shr esi,cl
+ mov ecx,esi
+ or ecx,eax
+ jz denormalize_underflow
+ and edx,#D_SIGN_MASK
+ or edx,esi
+ ret
+
+! Cause an fp division by zero exception
+! Return +-HUGEVAL in edx:ecx with sign from edx
+
+ .globl fpdivzero
+ .align ALIGNMENT
+fpdivzero:
+ mov eax,#EFDIVZERO
+ test edx,#D_EXP_MASK
+ jnz fphuge ! almost right
+ sub ecx,ecx
+ mov edx,ecx
+ jmp fperror
diff --git a/bin86-0.3/bccfp/fplib.h b/bin86-0.3/bccfp/fplib.h
new file mode 100644
index 0000000..b346c61
--- /dev/null
+++ b/bin86-0.3/bccfp/fplib.h
@@ -0,0 +1,49 @@
+/*
+ * bin86/bccfp/fplib.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+#define ALIGNMENT 4
+#define CHAR_BIT 8
+#define D_BIT (D_SIZE * CHAR_BIT)
+#define D_EXP_BIAS ((1 << (D_EXP_BIT - 1)) - 1)
+#define D_EXP_BIT 11
+#define D_EXP_INFINITE ((1 << D_EXP_BIT) - 1)
+#define D_EXP_MASK (((1 << D_EXP_BIT) - 1) << D_EXP_SHIFT)
+#define D_EXP_SHIFT (REG_BIT - (1 + D_EXP_BIT))
+#define D_FRAC_BIT 53
+#define D_FRAC_MASK (D_NORM_MASK - 1)
+#define D_HIGH 4
+#define D_HUGE_HIGH (D_EXP_MASK - 1)
+#define D_HUGE_LOW 0xFFFFFFFF
+#define D_LOW 0
+#define D_NORM_BIT (D_FRAC_BIT - 1 - REG_BIT)
+#define D_NORM_MASK (1 << D_NORM_BIT)
+#define D_SIGN_BIT 63
+#define D_SIGN_MASK (1 << (D_SIGN_BIT - REG_BIT))
+#define D_SIZE 8
+#define F_BIT (F_SIZE * CHAR_BIT)
+#define F_EXP_BIAS ((1 << (F_EXP_BIT - 1)) - 1)
+#define F_EXP_BIT 8
+#define F_EXP_INFINITE ((1 << F_EXP_BIT) - 1)
+#define F_EXP_MASK (((1 << F_EXP_BIT) - 1) << F_EXP_SHIFT)
+#define F_EXP_SHIFT (REG_BIT - (1 + F_EXP_BIT))
+#define F_FRAC_BIT 24
+#define F_FRAC_MASK (F_NORM_MASK - 1)
+#define F_HIGH 0
+#define F_HUGE_HIGH (F_EXP_MASK - 1)
+#define F_NORM_BIT (F_FRAC_BIT - 1)
+#define F_NORM_MASK (1 << F_NORM_BIT)
+#define F_SIGN_BIT 31
+#define F_SIGN_MASK (1 << F_SIGN_BIT)
+#define F_SIZE 4
+#define FREE_D_SIGN_BIT_TEST (D_SIGN_BIT % REG_BIT == REG_BIT - 1)
+#define GENREG_SIZE 4
+#define INT_BIT 32
+#define INT_MAX 0x7FFFFFFF
+#define INT_MIN (-0x7FFFFFFF - 1)
+#define PC_SIZE 4
+#define REG_BIT 32
+#define SHORT_BIT 16
+#define UINT_MAX 0xFFFFFFFF
diff --git a/bin86-0.3/bccfp/fptoi.x b/bin86-0.3/bccfp/fptoi.x
new file mode 100644
index 0000000..30de729
--- /dev/null
+++ b/bin86-0.3/bccfp/fptoi.x
@@ -0,0 +1,117 @@
+! bcc 386 floating point routines (version 2)
+! -- dtoi, dtol, dtoui, dtoul, ftoi, ftol (todo: ftoui, ftoul)
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpoverflow
+ .extern Fpushf
+
+! Convert double x at [ebx] to int and return in eax
+
+ .globl dtoi
+ .globl dtol
+ .align ALIGNMENT
+dtoi:
+dtol:
+ mov eax,D_HIGH[ebx]
+ mov ecx,eax
+ and ecx,#D_EXP_MASK ! extract exponent
+ jz retz ! if 0 return 0
+ test eax,#D_SIGN_MASK
+ jnz negative
+ call into_dtoui
+ cmp eax,#INT_MAX
+ ja overflow_int_max
+ ret
+
+ .align ALIGNMENT
+negative:
+ and eax,#~D_SIGN_MASK
+ call into_dtoui
+ cmp eax,#INT_MIN
+ ja overflow_int_min
+ neg eax
+ ret
+
+ .align ALIGNMENT
+overflow_int_max:
+ call fpoverflow
+ mov eax,#INT_MAX
+ ret
+
+ .align ALIGNMENT
+overflow_int_min:
+ js return ! actually INT_MIN is OK
+ call fpoverflow
+ mov eax,#INT_MIN
+return:
+ ret
+
+ .align ALIGNMENT
+retz:
+ sub eax,eax ! clear return value
+ ret
+
+! Convert double x at [ebx] to unsigned and return in eax
+
+ .globl dtoui
+ .globl dtoul
+ .align ALIGNMENT
+dtoui:
+dtoul:
+ mov eax,D_HIGH[ebx]
+ mov ecx,eax
+ and ecx,#D_EXP_MASK ! extract exponent
+ jz retz ! if 0 return 0
+ test eax,#D_SIGN_MASK
+ jnz overflow_0
+into_dtoui:
+ mov edx,D_LOW[ebx]
+
+ and eax,#D_FRAC_MASK ! extract fraction
+ or eax,#D_NORM_MASK ! restore normalization bit
+
+ shr ecx,#D_EXP_SHIFT ! convert exponent to number
+ sub ecx,#D_EXP_BIAS+D_NORM_BIT ! adjust radix point
+ jl dtoui_rightshift ! should we shift left or right?
+ cmp ecx,#D_BIT-D_FRAC_BIT ! can shift left by at most this
+ ja overflow_uint_max ! if more, overflow
+ shld eax,edx,cl
+ ret
+
+ .align ALIGNMENT
+dtoui_rightshift:
+ neg ecx ! make shift count > 0
+ cmp ecx,#REG_BIT ! big shifts would be taken mod REG_BIT ...
+ jae retz ! ... no good
+ shr eax,cl ! otherwise it is faster to do the shift ...
+ ret ! ... then to jump for the slightly smaller
+ ! ... shift counts that shift out all bits
+
+ .align ALIGNMENT
+overflow_0:
+ call fpoverflow
+ sub eax,eax
+ ret
+
+ .align ALIGNMENT
+overflow_uint_max:
+ call fpoverflow
+ mov eax,#UINT_MAX
+ ret
+
+! ftoi is like dtoi except ebx points to a float instead of a double.
+! This is a quickly-written slowish version that does not take advantage
+! of the float being smaller.
+
+ .globl ftoi
+ .globl ftol
+ .align ALIGNMENT
+ftoi:
+ftol:
+ call Fpushf
+ mov ebx,esp
+ call dtoi
+ add esp,#D_SIZE
+ ret
diff --git a/bin86-0.3/bccfp/fpulld.x b/bin86-0.3/bccfp/fpulld.x
new file mode 100644
index 0000000..928a846
--- /dev/null
+++ b/bin86-0.3/bccfp/fpulld.x
@@ -0,0 +1,20 @@
+! bcc 386 floating point routines (version 2) -- Fpulld
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+! Pop double from stack and store at address [ebx]
+
+ .globl Fpulld
+ .align ALIGNMENT
+Fpulld:
+ pop ecx
+ pop dword D_LOW[ebx]
+ pop dword D_HIGH[ebx]
+ jmp ecx ! return
+
+! This popping method is much slower on 486's because popping to memory
+! takes 5+ while moving twice takes 2 and the return address doesn't
+! have to be moved. However, popping is a little faster on a non-cached
+! 386/20 with static column RAM although the memory access pattern is
+! better for a double-width move than for popping. What about a cached 386?
diff --git a/bin86-0.3/bccfp/fpullf.x b/bin86-0.3/bccfp/fpullf.x
new file mode 100644
index 0000000..417ef92
--- /dev/null
+++ b/bin86-0.3/bccfp/fpullf.x
@@ -0,0 +1,101 @@
+! bcc 386 floating point routines (version 2) -- Fpullf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpoverflow
+ .extern fpunderflow
+
+! pop double from stack, convert to float and store at address [ebx]
+
+ .globl Fpullf
+ .align ALIGNMENT
+Fpullf:
+
+! Step 1: load and shift left
+
+ mov eax,PC_SIZE+D_LOW[esp] ! lower dword
+ mov edx,PC_SIZE+D_HIGH[esp] ! upper dword
+ mov ecx,edx ! copy upper dword into ecx ...
+ and ecx,#D_SIGN_MASK ! ... and extract sign
+ and edx,#D_EXP_MASK | D_FRAC_MASK ! extract exponent and fraction
+ sub edx,#(D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT ! adjust exponent bias
+ jz underflow
+ cmp edx,#F_EXP_INFINITE << D_EXP_SHIFT ! check if exponent lies in reduced range
+ jae outofbounds
+ shld edx,eax,#D_EXP_BIT-F_EXP_BIT ! shift exponent and fraction
+
+! Step 2: round
+
+ test eax,#1 << (REG_BIT-1-(D_EXP_BIT-F_EXP_BIT)) ! test upper rounding bit
+ jz step3 ! below middle, don't round up
+ test eax,#(1 << (REG_BIT-1-(D_EXP_BIT-F_EXP_BIT)))-1 ! test other rounding bits
+ jnz roundup ! above middle, round up
+ test dl,#1 ! in middle, check parity bit
+ jz step3 ! already even, otherwise round up to make even
+
+roundup:
+ inc edx ! carry 1
+ test edx,#F_FRAC_MASK ! is fraction now 0? (carry into F_EXPMASK)
+ jnz step3 ! no -- carry complete
+ cmp edx,#(F_EXP_INFINITE << F_EXP_SHIFT) & ~F_NORM_MASK ! yes (very unlikely): check for overflow
+ ! XXX - I think these tests say 0x7e7fffff overflows
+ jae overflow
+
+! Step 3: put it all together
+
+step3:
+ or edx,ecx ! include sign
+ mov F_HIGH[ebx],edx ! store the result in [ebx]
+ ret #D_SIZE ! return and release double from stack
+
+ .align ALIGNMENT
+outofbounds:
+ jns overflow ! have just compared exponent with the max
+underflow:
+! call fpunderflow ! XXX
+ push ecx ! save sign
+ mov ecx,edx
+ and ecx,#~D_FRAC_MASK ! assume fraction is below exp
+ cmp ecx,#-((D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT) ! was exp = 0?
+ jz exp_x_0
+ shr ecx,#D_EXP_SHIFT
+ neg ecx
+ and edx,#D_FRAC_MASK
+ or edx,#D_NORM_MASK
+ shld edx,eax,#D_EXP_BIT-F_EXP_BIT-1
+ shl eax,#D_EXP_BIT-F_EXP_BIT-1
+ push ebx ! save to use for rounding
+ sub ebx,ebx
+ shrd ebx,eax,cl
+ shrd eax,edx,cl
+ shr edx,cl
+ cmp eax,#1 << (REG_BIT-1)
+ jb over_denorm_roundup
+ ja denorm_roundup
+ test dl,#1
+ jz over_denorm_roundup
+denorm_roundup:
+#if F_NORM_BIT != F_EXP_SHIFT
+#include "carry into norm bit doesn't go into low exp bit"
+#endif
+ inc edx
+over_denorm_roundup:
+ pop ebx
+ pop ecx
+ or edx,ecx
+ mov F_HIGH[ebx],edx
+ ret #D_SIZE
+
+ .align ALIGNMENT
+exp_x_0: ! XXX check for denormals - they underflow
+ pop ecx
+ mov dword F_HIGH[ebx],#0
+ ret #D_SIZE
+
+ .align ALIGNMENT
+overflow:
+ mov edx,ebx ! put sign in usual reg
+ call fpoverflow
+ mov F_HIGH[ebx],dword #F_HUGE_HIGH ! XXX - should use infinity
+ ret #D_SIZE ! ... if fpoverflow does
diff --git a/bin86-0.3/bccfp/fpushd.x b/bin86-0.3/bccfp/fpushd.x
new file mode 100644
index 0000000..68caab0
--- /dev/null
+++ b/bin86-0.3/bccfp/fpushd.x
@@ -0,0 +1,60 @@
+! bcc 386 floating point routines (version 2) -- dtof, Fpushd, Fneg, Fnegd
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern Fpullf
+
+! dtof converts the double at [ebx] to a float and pushes the float onto
+! the stack (D_SIZE bytes are allocated for the float although only the bottom
+! F_SIZE are used).
+! This is a quickly-written slowish version.
+
+ .globl dtof
+ .align ALIGNMENT
+dtof:
+ pop eax
+ sub esp,#D_SIZE ! build result here
+ push eax ! put back return address
+ call Fpushd
+ lea ebx,D_SIZE+PC_SIZE[esp]
+ call Fpullf
+ ret
+
+! Push double at address [ebx] onto stack
+
+ .globl Fpushd
+ .align ALIGNMENT
+Fpushd:
+ pop ecx
+ push dword D_HIGH[ebx]
+ push dword D_LOW[ebx]
+ jmp ecx ! return
+
+! Push double at address [ebx] onto stack, negating it on the way.
+
+! Don't worry about generating -0 because other routines have to allow for
+! it anyway.
+
+! Perhaps this and Fneg should check for denormals and illegal operands
+! (I think only signalling NaNs are illegal).
+! fchs doesn't check, but fld does.
+! Our Fpushd is not quite like fld because no conversions are involved.
+
+ .globl Fnegd
+ .align ALIGNMENT
+Fnegd:
+ pop ecx
+ mov eax,D_HIGH[ebx]
+ xor eax,#D_SIGN_MASK ! toggle sign
+ push eax
+ push dword D_LOW[ebx]
+ jmp ecx ! return
+
+! Negate double on stack
+
+ .globl Fneg
+ .align ALIGNMENT
+Fneg:
+ xorb PC_SIZE+D_SIZE-1[esp],D_SIGN_MASK >> (REG_BIT-CHAR_BIT) ! toggle sign
+ ret
diff --git a/bin86-0.3/bccfp/fpushf.x b/bin86-0.3/bccfp/fpushf.x
new file mode 100644
index 0000000..7cb2f8d
--- /dev/null
+++ b/bin86-0.3/bccfp/fpushf.x
@@ -0,0 +1,74 @@
+! bcc 386 floating point routines (version 2) -- Fpushf, Fnegf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpdenormal
+
+! Load float at [ebx], convert to double and push on stack
+
+ .globl Fpushf
+ .align ALIGNMENT
+Fpushf:
+ mov edx,F_HIGH[ebx]
+into_Fpushf:
+ test edx,#F_EXP_MASK ! is exponent 0?
+ jz exp_x_0
+
+ mov ecx,edx ! extract sign
+ and ecx,#F_SIGN_MASK
+
+ and edx,#F_EXP_MASK | F_FRAC_MASK ! extract exponent and fraction
+ sub eax,eax ! clear lower dword
+ shrd eax,edx,#D_EXP_BIT-F_EXP_BIT ! shift exponent and fraction to new position
+ shr edx,#D_EXP_BIT-F_EXP_BIT
+
+ add edx,#(D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT ! adjust exponent bias
+ or edx,ecx ! include sign
+
+ pop ecx
+ push edx ! upper dword
+ push eax ! lower dword
+ jmp ecx ! return
+
+ .align ALIGNMENT
+exp_x_0:
+ mov eax,edx
+ and eax,#F_FRAC_MASK
+ jnz x_denorm
+ pop ecx
+ push eax ! upper dword = 0
+ push eax ! lower dword = 0
+ jmp ecx ! return
+
+ .align ALIGNMENT
+x_denorm:
+ call fpdenormal
+ bsr ecx,eax ! zzzz
+ neg ecx
+ add ecx,#F_NORM_BIT
+ shl eax,cl
+ and eax,#F_FRAC_MASK
+ neg ecx
+ add ecx,#D_EXP_BIAS-F_EXP_BIAS+1
+ shl ecx,#D_EXP_SHIFT
+ and edx,#F_SIGN_MASK ! assumed same as D_SIGN_MASK
+ or edx,ecx
+ sub ecx,ecx
+ shrd ecx,eax,#D_EXP_BIT-F_EXP_BIT
+ shr eax,#D_EXP_BIT-F_EXP_BIT
+ or edx,eax
+
+ pop eax
+ push edx ! upper dword
+ push ecx ! lower dword
+ jmp eax ! return
+
+! Fnegf: as Fpushf, but negate double before pushing onto stack
+
+ .globl Fnegf
+ .align ALIGNMENT
+Fnegf:
+ mov edx,F_HIGH[ebx]
+ xor edx,#F_SIGN_MASK ! toggle sign
+ jmp into_Fpushf ! join Fpushf
diff --git a/bin86-0.3/bccfp/fpushi.x b/bin86-0.3/bccfp/fpushi.x
new file mode 100644
index 0000000..b19aae2
--- /dev/null
+++ b/bin86-0.3/bccfp/fpushi.x
@@ -0,0 +1,126 @@
+! bcc 386 floating point routines (version 2)
+! -- Fpushi, Fpushl, Fpushs, Fpushc, Fpushuc, Fpushui, Fpushul, Fpushus
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+! Convert the short in ax to double and push on stack
+
+ .globl Fpushs
+ .align ALIGNMENT
+Fpushs:
+ cwde
+ add eax,#0 ! fast 3-byte instruction to align
+
+! Convert the int or long in eax to double and push on stack
+
+ .globl Fpushi
+ .globl Fpushl
+! .align ALIGNMENT ! don't do this until it pads with nop's
+Fpushi:
+Fpushl:
+ test eax,eax
+ jz return_eax ! got 0 in eax
+ mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent
+ jns normalize ! sign and fraction bits already set up
+ mov ebx,#D_SIGN_MASK | ((D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT) ! adjust sign
+ neg eax ! adjust fraction
+ jmp normalize
+
+ .align ALIGNMENT
+ret1:
+ mov eax,#D_EXP_BIAS << D_EXP_SHIFT
+ add eax,#0 ! fast 3-byte instruction to align
+
+! .align ALIGNMENT ! don't do this until it pads with nop's
+return_eax:
+ pop ecx
+ push eax ! upper dword
+ push dword #0 ! lower dword = 0
+ jmp ecx ! return
+
+! Convert the (unsigned) char in al to double and push on stack
+
+ .globl Fpushc
+ .globl Fpushuc
+ .align ALIGNMENT
+Fpushc:
+Fpushuc:
+ and eax,#(1 << CHAR_BIT)-1
+ add eax,#0 ! fast 3-byte instruction to align
+
+! Convert the unsigned short in ax to double and push on stack
+
+ .globl Fpushus
+! .align ALIGNMENT ! don't do this until it pads with nop's
+Fpushus:
+ and eax,#(1 << SHORT_BIT)-1
+ add eax,#0 ! fast 3-byte instruction to align
+
+! Convert the unsigned int or long in eax to double and push on stack
+
+ .globl Fpushui
+ .globl Fpushul
+! .align ALIGNMENT ! don't do this until it pads with nop's
+Fpushui:
+Fpushul:
+ cmp eax,#1 ! this tests for both 0 and 1
+ jb return_eax ! got 0 in eax
+ jz ret1
+ mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent
+
+! .align ALIGNMENT ! don't do this until it pads with nop's
+normalize:
+ sub edx,edx ! clear lower dword of result
+
+! Find first nonzero bit
+! Don't use bsr, it is slow (const + 3n on 386, const + n on 486)
+
+ sub ecx,ecx ! prepare unsigned extension of cl
+ test eax,#~D_FRAC_MASK
+ jnz large
+ test eax,#0xFF << (D_NORM_BIT-8)
+ jnz middle
+ shl eax,#8
+ sub ebx,#8 << D_EXP_SHIFT
+ test eax,#0xFF << (D_NORM_BIT-8)
+ jnz middle
+ shl eax,#8
+ sub ebx,#8 << D_EXP_SHIFT
+middle:
+ shld ecx,eax,#D_NORM_BIT
+ mov cl,bsr_table[ecx]
+ add ecx,#REG_BIT-D_NORM_BIT-D_NORM_BIT
+ neg ecx
+ shl eax,cl
+ shl ecx,#D_EXP_SHIFT
+ sub ebx,ecx
+return:
+ and eax,#D_FRAC_MASK ! remove normalization bit
+ or eax,ebx ! include exponent (and sign) to fraction
+ pop ecx
+ push eax ! upper dword
+ push edx ! lower dword
+ jmp ecx ! return
+
+ .align ALIGNMENT
+large:
+ shld ecx,eax,#REG_BIT-(D_NORM_BIT+8)
+ jnz huge
+ shld ecx,eax,#REG_BIT-D_NORM_BIT
+ mov cl,bsr_table[ecx]
+got_shift_right:
+ shrd edx,eax,cl
+ shr eax,cl
+ shl ecx,#D_EXP_SHIFT
+ add ebx,ecx
+ jmp return
+
+ .align ALIGNMENT
+huge:
+ mov cl,bsr_table[ecx]
+ add cl,#8
+ jmp got_shift_right
+
+ .data
+ .extern bsr_table
diff --git a/bin86-0.3/bccfp/frexp.x b/bin86-0.3/bccfp/frexp.x
new file mode 100644
index 0000000..318fc34
--- /dev/null
+++ b/bin86-0.3/bccfp/frexp.x
@@ -0,0 +1,66 @@
+! bcc 386 floating point routines (version 2) -- _frexp
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpdenormal
+
+! void frexp(double value, int *exponent);
+! splits a double into exponent and fraction (where 0.5 <= fraction < 1.0)
+
+ .globl _frexp
+ .align ALIGNMENT
+_frexp:
+push ebx
+#undef PC_SIZE
+#define PC_SIZE 8
+ mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x
+ mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x
+ mov edx,PC_SIZE+D_SIZE[esp] ! exponent pointer
+ mov ecx,ebx ! extract exponent here
+ and ecx,#D_EXP_MASK
+ jz exp_x_0
+
+ shr ecx,#D_EXP_SHIFT ! exponent + bias
+got_x:
+ sub ecx,#D_EXP_BIAS-1 ! D_EXP_BIAS is for 1.x form, we want 0.1x form
+ mov [edx],ecx ! return exponent
+ and ebx,#D_SIGN_MASK | D_FRAC_MASK ! extract sign and fraction
+ or ebx,#(D_EXP_BIAS-1) << D_EXP_SHIFT ! set new exponent for 0.1x
+mov edx,ebx
+pop ebx
+ ret
+
+ .align ALIGNMENT
+exp_x_0:
+ test ebx,#D_FRAC_MASK
+ jnz xu_denorm
+ test eax,eax
+ jnz xl_denorm
+ mov [edx],ecx ! return zero exponent
+ mov ebx,ecx ! guard against -0 (may not be necessary)
+mov edx,ebx
+pop ebx
+ ret
+
+ .align ALIGNMENT
+xl_denorm:
+ call fpdenormal
+ bsr ecx,eax ! zzzz
+ neg ecx
+ add ecx,#REG_BIT-1
+ shl eax,cl
+ shld ebx,eax,#D_NORM_BIT+1
+ shl eax,#D_NORM_BIT+1
+ sub ecx,#D_NORM_BIT+1
+ jmp got_x
+
+ .align ALIGNMENT
+xu_denorm:
+ call fpdenormal
+ bsr ecx,ebx
+ neg ecx
+ add ecx,#D_NORM_BIT
+ shld ebx,eax,cl
+ shl eax,cl
+ jmp got_x
diff --git a/bin86-0.3/bccfp/ftst.x b/bin86-0.3/bccfp/ftst.x
new file mode 100644
index 0000000..2a92ef1
--- /dev/null
+++ b/bin86-0.3/bccfp/ftst.x
@@ -0,0 +1,28 @@
+! bcc 386 floating point routines (version 2) -- Ftst, Ftstd, Ftstf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+#if 0 /* bcc doesn't generate Ftst (but it might in future) */
+ .globl Ftst
+#endif
+ .align ALIGNMENT
+Ftst:
+ cmp dword PC_SIZE+D_HIGH[esp],#0 ! need only test upper dword of x
+ ret #D_SIZE
+
+! Compare double at address [ebx] with 0
+
+ .globl Ftstd
+ .align ALIGNMENT
+Ftstd:
+ cmp dword D_HIGH[ebx],#0 ! need only test upper dword of x
+ ret
+
+! Compare float at address [ebx] with 0
+
+ .globl Ftstf
+ .align ALIGNMENT
+Ftstf:
+ cmp dword F_HIGH[ebx],#0
+ ret
diff --git a/bin86-0.3/bccfp/ldexp.x b/bin86-0.3/bccfp/ldexp.x
new file mode 100644
index 0000000..bc9dd03
--- /dev/null
+++ b/bin86-0.3/bccfp/ldexp.x
@@ -0,0 +1,74 @@
+! bcc 386 floating point routines (version 2) -- _ldexp
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpoverflow
+ .extern fpunderflow
+
+! void ldexp(double value, int exponent);
+! returns value * (2 ** exponent)
+
+ .globl _ldexp
+ .align ALIGNMENT
+_ldexp:
+push ebx
+#undef PC_SIZE
+#define PC_SIZE 8
+ mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x
+ mov ecx,PC_SIZE+D_SIZE[esp] ! exponent arg
+ mov eax,ebx ! extract exponent (of x) here
+ and eax,#D_EXP_MASK
+! jz exp_y_0 ! may need check for preposterous exponent arg too
+
+ shr eax,#D_EXP_SHIFT ! shift to low bits just for testing
+ jz underflow ! denormal?
+ add eax,ecx ! test-add the exponents
+ jz underflow ! XXX probably need to fiddle norm bit
+ cmp eax,#D_EXP_INFINITE ! check if still within range
+ jae outofbounds ! the unsigned compare catches all overflow cases
+ ! because the exponent of x is non-negative
+
+ shl ecx,#D_EXP_SHIFT ! shift exponent arg bits into final position ...
+ add ebx,ecx ! ... safe to add it to exponent of x now
+ mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x
+mov edx,ebx
+pop ebx
+ ret
+
+
+ .align ALIGNMENT
+outofbounds:
+ test ecx,ecx ! overflow or underflow?
+ jns overflow
+underflow:
+ mov edx,ebx ! put sign in usual reg
+ push edi
+ push esi
+ mov edi,eax ! put exponent in usual reg
+ mov eax,2*GENREG_SIZE+PC_SIZE+D_LOW[esp]
+ ! put lower dword of x in usual reg
+ mov esi,ebx ! put upper dword of x in usual reg
+ and esi,#D_EXP_MASK | D_FRAC_MASK
+ test esi,#D_EXP_MASK
+ jz foo
+ and esi,#D_FRAC_MASK
+ or esi,#D_NORM_MASK
+foo:
+ neg edi
+! inc edi ! XXX ?
+ call fpunderflow
+ pop esi
+ pop edi
+ mov ebx,edx ! XXX = wrong reg
+pop ebx
+ ret
+
+ .align ALIGNMENT
+overflow:
+ mov edx,ebx ! put sign in usual reg
+ call fpoverflow
+ mov eax,ecx ! XXX = wrong reg
+ mov ebx,edx ! XXX = wrong reg
+pop ebx
+ ret
diff --git a/bin86-0.3/bccfp/modf.c b/bin86-0.3/bccfp/modf.c
new file mode 100644
index 0000000..a83f801
--- /dev/null
+++ b/bin86-0.3/bccfp/modf.c
@@ -0,0 +1,20 @@
+/*
+ * bin86/bccfp/modf.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+#include <math.h>
+
+/* Slooow version. */
+
+double modf(x, pint)
+double x;
+double *pint;
+{
+ if (x >= 0)
+ *pint = floor(x);
+ else
+ *pint = ceil(x);
+ return x - *pint;
+}
diff --git a/bin86-0.3/bccfp/test.c b/bin86-0.3/bccfp/test.c
new file mode 100644
index 0000000..05b5d84
--- /dev/null
+++ b/bin86-0.3/bccfp/test.c
@@ -0,0 +1,124 @@
+/*
+ * bin86/bccfp/test.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+#include <sys/times.h>
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+
+#define CONVTYPE int
+#define MAX (MIN + NITER - 1)
+#define MIN INT_MIN
+
+#define NITER 100000
+
+double one = 1;
+double two = 2;
+double big = 1e99;
+
+double d;
+double d1;
+float f;
+
+int main()
+{
+ CONVTYPE cti;
+ CONVTYPE cto;
+ clock_t delta;
+ struct tms finish;
+ int i;
+ struct tms start;
+
+#if 0
+ times(&start);
+ for (cti = MIN; cti <= MAX; ++cti)
+ {
+ d = cti;
+ cto = d;
+ if (cti != cto)
+ printf("%08x %08x\n", cti, cto);
+ if (cti % 10000000 == 0)
+ {
+ printf("%8x ok ", cti);
+ fflush(stdout);
+ }
+ }
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for %d i -> d and d -> i conversions was %g s (%d t)\n",
+ MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta);
+#endif
+
+ times(&start);
+ for (cti = MIN; cti <= MAX; ++cti)
+ d = cti;
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for %d i -> d conversions was %g s (%d t)\n",
+ MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta);
+
+ times(&start);
+ for (cti = MIN; cti <= MAX; ++cti)
+ {
+ d = cti;
+ cto = d;
+ }
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime - delta;
+ printf("Time for %d d -> i conversions was %g s (%d t)\n",
+ MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta);
+
+ d = 0;
+ times(&start);
+ for (i = 0; i < NITER; ++i)
+ d = d + 1;
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for adding %d 1.0's to 0.0 was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, d);
+
+ d = 0;
+ times(&start);
+ for (; d < NITER;)
+ d = d + 1;
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for adding %d 1.0's to 0.0 (d index) was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, d);
+
+ times(&start);
+ for (i = 1; i <= NITER; ++i)
+ {
+ d1 = i;
+ d = d1 * d1;
+ }
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for %d mults was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, d);
+
+ times(&start);
+ for (i = 1; i <= NITER; ++i)
+ {
+ d1 = i;
+ d = 1 / d1;
+ }
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for %d divs was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, d);
+
+ f = 0;
+ times(&start);
+ for (i = 0; i < NITER; ++i)
+ f = f + 1;
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for adding %d 1.0f's to 0.0f was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, f);
+
+ return 0;
+}
diff --git a/bin86-0.3/ld/6809/config.h b/bin86-0.3/ld/6809/config.h
new file mode 100644
index 0000000..b2203ab
--- /dev/null
+++ b/bin86-0.3/ld/6809/config.h
@@ -0,0 +1,34 @@
+/*
+ * bin86/ld/6809/config.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* config.h - configuration for linker */
+
+/* one of these target processors must be defined */
+
+#undef I8086 /* Intel 8086 */
+#undef I80386 /* Intel 80386 */
+#define MC6809 /* Motorola 6809 */
+
+/* one of these target operating systems must be defined */
+
+#define EDOS /* generate EDOS executable */
+#undef MINIX /* generate Minix executable */
+
+/* these may need to be defined to suit the source processor */
+
+#undef S_ALIGNMENT 4 /* source memory alignment, power of 2 */
+ /* don't use for 8 bit processors */
+ /* don't use even for 80386 - overhead for */
+ /* alignment cancels improved access */
+
+/* these should be defined if they are supported by the source compiler */
+
+#undef PROTO /* compiler handles prototypes */
+
+/* these must be defined to suit the source libraries */
+
+#define CREAT_PERMS 0666 /* permissions for creat() */
+#define EXEC_PERMS 0111 /* extra permissions to set for executable */
diff --git a/bin86-0.3/ld/Makefile b/bin86-0.3/ld/Makefile
new file mode 100644
index 0000000..a7da6d7
--- /dev/null
+++ b/bin86-0.3/ld/Makefile
@@ -0,0 +1,29 @@
+CC =gcc
+CFLAGS =-O1 -fomit-frame-pointer
+INC_CFLAGS =-DBSD_A_OUT -I../a.out.h -D__linux__
+LDFLAGS =-s
+
+OBJS =dumps.o io.o ld.o readobj.o table.o typeconv.o \
+ writebin.o
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+
+.c.o:
+ $(CC) $(CFLAGS) $(INC_CFLAGS) -c $<
+
+all: ld86
+
+ld86: $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+clean:
+ $(RM) $(OBJS) ld86 core
+
+dumps.o: dumps.c const.h config.h obj.h type.h globvar.h
+io.o: io.c const.h config.h type.h globvar.h
+ld.o: ld.c const.h config.h type.h byteord.h globvar.h
+readobj.o: readobj.c const.h config.h byteord.h obj.h type.h globvar.h
+table.o: table.c const.h config.h align.h obj.h type.h globvar.h
+typeconv.o: typeconv.c const.h config.h type.h globvar.h
+writebin.o: writebin.c const.h config.h obj.h type.h globvar.h
diff --git a/bin86-0.3/ld/align.h b/bin86-0.3/ld/align.h
new file mode 100644
index 0000000..f34652c
--- /dev/null
+++ b/bin86-0.3/ld/align.h
@@ -0,0 +1,14 @@
+/*
+ * bin86/ld/align.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* align.h - memory alignment requirements for linker */
+
+#ifndef S_ALIGNMENT
+# define align(x)
+#else
+# define align(x) ((x) = (void *)(((int) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1)))
+ /* assumes sizeof(int) == sizeof(char *) */
+#endif
diff --git a/bin86-0.3/ld/ar.h b/bin86-0.3/ld/ar.h
new file mode 100644
index 0000000..780d457
--- /dev/null
+++ b/bin86-0.3/ld/ar.h
@@ -0,0 +1,24 @@
+/*
+ * bin86/ld/ar.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+#ifndef _AR_H
+#define _AR_H
+
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+struct ar_hdr {
+ char ar_name[16];
+ char ar_date[12];
+ char ar_uid[6];
+ char ar_gid[6];
+ char ar_mode[8];
+ char ar_size[10];
+ char ar_fmag[2];
+};
+
+#endif /* _AR_H */
diff --git a/bin86-0.3/ld/bugs b/bin86-0.3/ld/bugs
new file mode 100644
index 0000000..b671f30
--- /dev/null
+++ b/bin86-0.3/ld/bugs
@@ -0,0 +1,17 @@
+1. Should cause error when an address which requires > 16 bits is referenced
+ using 16 bits.
+
+TODO:
+ integrate byteord.h with compiler as well as assembler
+
+TODO:
+ integrate align.h with compiler and assembler
+ use alignment for *86 like compiler - use more portable macro
+ ((x) + (-(int) (x) & MASK)) when it is either necessary or
+ faster
+
+TODO:
+ do malloc stuff better, as in compiler
+
+2. Error message about "foo.a is not an object file" is confusing - should
+ name archive member.
diff --git a/bin86-0.3/ld/byteord.h b/bin86-0.3/ld/byteord.h
new file mode 100644
index 0000000..0e2b403
--- /dev/null
+++ b/bin86-0.3/ld/byteord.h
@@ -0,0 +1,24 @@
+/*
+ * bin86/ld/byteord.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* byteord.h - byte order dependencies for C compiler, assembler, linker */
+
+/* These are for the targets of everything and for linker source too. */
+
+#ifdef I8086
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */
+#endif
+
+#ifdef I80386
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0
+#endif
+
+#ifdef MC6809
+# define BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
diff --git a/bin86-0.3/ld/config.h b/bin86-0.3/ld/config.h
new file mode 100644
index 0000000..173d1c4
--- /dev/null
+++ b/bin86-0.3/ld/config.h
@@ -0,0 +1,34 @@
+/*
+ * bin86/ld/config.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* config.h - configuration for linker */
+
+/* one of these target processors must be defined */
+
+#undef I8086 /* Intel 8086 */
+#define I80386 /* Intel 80386 */
+#undef MC6809 /* Motorola 6809 */
+
+/* one of these target operating systems must be defined */
+
+#undef EDOS /* generate EDOS executable */
+#define MINIX /* generate Minix executable */
+
+/* these may need to be defined to suit the source processor */
+
+#define S_ALIGNMENT 4 /* source memory alignment, power of 2 */
+ /* don't use for 8 bit processors */
+ /* don't use even for 80386 - overhead for */
+ /* alignment cancels improved access */
+
+/* these should be defined if they are supported by the source compiler */
+
+#define PROTO /* compiler handles prototypes */
+
+/* these must be defined to suit the source libraries */
+
+#define CREAT_PERMS 0666 /* permissions for creat() */
+#define EXEC_PERMS 0111 /* extra permissions to set for executable */
diff --git a/bin86-0.3/ld/const.h b/bin86-0.3/ld/const.h
new file mode 100644
index 0000000..a933bdc
--- /dev/null
+++ b/bin86-0.3/ld/const.h
@@ -0,0 +1,20 @@
+/*
+ * bin86/ld/const.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* const.h - constants for linker */
+
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+
+#include "config.h"
diff --git a/bin86-0.3/ld/dumps.c b/bin86-0.3/ld/dumps.c
new file mode 100644
index 0000000..c91653f
--- /dev/null
+++ b/bin86-0.3/ld/dumps.c
@@ -0,0 +1,72 @@
+/*
+ * bin86/ld/dumps.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* dumps.c - print data about symbols and modules for linker */
+
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+/* print list of modules and whether they are loaded */
+
+PUBLIC void dumpmods()
+{
+ struct modstruct *modptr;
+
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ {
+ putstr(modptr->loadflag ? "L " : " ");
+ putbstr(20, modptr->modname);
+ putbyte('\n');
+ }
+}
+
+/* print data about symbols (in loaded modules only) */
+
+PUBLIC void dumpsyms()
+{
+ flags_t flags;
+ struct modstruct *modptr;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+ char uflag;
+
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr)
+ {
+ uflag = FALSE;
+ if (((flags = symptr->flags) & (C_MASK | I_MASK)) == I_MASK)
+ uflag = TRUE;
+ putbstr(20, uflag ? "" : modptr->modname);
+ putstr(" ");
+ putbstr(20, symptr->name);
+ putstr(" ");
+ putbyte(hexdigit[flags & SEGM_MASK]);
+ putstr(" ");
+ if (uflag)
+ putstr(" ");
+ else
+#ifdef LONG_OFFSETS
+ put08lx(symptr->value);
+#else
+ put08x(symptr->value);
+#endif
+ putstr(flags & A_MASK ? " A" : " R");
+ if (uflag)
+ putstr(" U");
+ if (flags & C_MASK)
+ putstr(" C");
+ if (flags & N_MASK)
+ putstr(" N");
+ putbyte('\n');
+ }
+ }
+}
diff --git a/bin86-0.3/ld/globvar.h b/bin86-0.3/ld/globvar.h
new file mode 100644
index 0000000..0c382c7
--- /dev/null
+++ b/bin86-0.3/ld/globvar.h
@@ -0,0 +1,18 @@
+/*
+ * bin86/ld/globvar.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* globvar.h - global variables for linker */
+
+#ifdef EXTERN
+EXTERN char hexdigit[];
+#else
+#define EXTERN
+PUBLIC char hexdigit[] = "0123456789abcdef";
+#endif
+EXTERN unsigned errcount; /* count of errors */
+EXTERN struct entrylist *entryfirst; /* first on list of entry symbols */
+EXTERN struct modstruct *modfirst; /* data for 1st module */
+EXTERN struct redlist *redfirst; /* first on list of redefined symbols */
diff --git a/bin86-0.3/ld/io.c b/bin86-0.3/ld/io.c
new file mode 100644
index 0000000..999dbd3
--- /dev/null
+++ b/bin86-0.3/ld/io.c
@@ -0,0 +1,583 @@
+/*
+ * bin86/ld/io.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* io.c - input/output and error modules for linker */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef __linux__
+#define MY_STAT_H
+#endif
+#include <fcntl.h>
+#include <unistd.h>
+#include "const.h"
+#include "obj.h" /* needed for LONG_OFFSETS and offset_t */
+#include "type.h"
+#include "globvar.h"
+
+#define DRELBUFSIZE 2048
+#define ERR (-1)
+#define ERRBUFSIZE 1024
+#define INBUFSIZE 1024
+#define OUTBUFSIZE 2048
+#define TRELBUFSIZE 1024
+
+#ifdef BSD_A_OUT
+PRIVATE char *drelbuf; /* extra output buffer for data relocations */
+PRIVATE char *drelbufptr; /* data relocation output buffer ptr */
+PRIVATE char *drelbuftop; /* data relocation output buffer top */
+#endif
+PRIVATE char *errbuf; /* error buffer (actually uses STDOUT) */
+PRIVATE char *errbufptr; /* error buffer ptr */
+PRIVATE char *errbuftop; /* error buffer top */
+PRIVATE char *inbuf; /* input buffer */
+PRIVATE char *inbufend; /* input buffer top */
+PRIVATE char *inbufptr; /* end of input in input buffer */
+PRIVATE int infd; /* input file descriptor */
+PRIVATE char *inputname; /* name of current input file */
+PRIVATE char *outbuf; /* output buffer */
+PRIVATE char *outbufptr; /* output buffer ptr */
+PRIVATE char *outbuftop; /* output buffer top */
+PRIVATE int outfd; /* output file descriptor */
+PRIVATE unsigned outputperms; /* permissions of output file */
+PRIVATE char *outputname; /* name of output file */
+PRIVATE char *refname; /* name of program for error reference */
+#ifdef BSD_A_OUT
+PRIVATE char *trelbuf; /* extra output buffer for text relocations */
+PRIVATE char *trelbufptr; /* text relocation output buffer ptr */
+PRIVATE char *trelbuftop; /* text relocation output buffer top */
+PRIVATE int trelfd; /* text relocation output file descriptor */
+#endif
+PRIVATE unsigned warncount; /* count of warnings */
+
+FORWARD void errexit P((char *message));
+FORWARD void flushout P((void));
+#ifdef BSD_A_OUT
+FORWARD void flushtrel P((void));
+#endif
+FORWARD void outhexdigs P((offset_t num));
+FORWARD void outputerror P((char *message));
+FORWARD void put04x P((unsigned num));
+FORWARD void putstrn P((char *message));
+FORWARD void refer P((void));
+
+PUBLIC void ioinit(progname)
+char *progname;
+{
+ infd = ERR;
+ if (*progname)
+ refname = progname; /* name must be static (is argv[0]) */
+ else
+ refname = "link";
+#ifdef BSD_A_OUT
+ drelbuf = malloc(DRELBUFSIZE);
+ drelbuftop = drelbuf + DRELBUFSIZE;
+#endif
+ errbuf = malloc(ERRBUFSIZE);
+ errbufptr = errbuf;
+ errbuftop = errbuf + ERRBUFSIZE;
+ inbuf = malloc(INBUFSIZE);
+ outbuf = malloc(OUTBUFSIZE);/* outbuf invalid if this fails but then */
+ /* will not be used - tableinit() aborts */
+ outbuftop = outbuf + OUTBUFSIZE;
+#ifdef BSD_A_OUT
+ trelbuf = malloc(TRELBUFSIZE);
+ trelbuftop = trelbuf + TRELBUFSIZE;
+#endif
+}
+
+PUBLIC void closein()
+{
+ if (infd != ERR && close(infd) < 0)
+ inputerror("cannot close");
+ infd = ERR;
+}
+
+PUBLIC void closeout()
+{
+#ifdef BSD_A_OUT
+ unsigned nbytes;
+#endif
+
+ flushout();
+#ifdef BSD_A_OUT
+ flushtrel();
+ nbytes = drelbufptr - drelbuf;
+ if (write(trelfd, drelbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+#endif
+ if (close(outfd) == ERR)
+ outputerror("cannot close");
+#ifdef BSD_A_OUT
+ if (close(trelfd) == ERR)
+ outputerror("cannot close");
+#endif
+}
+
+PUBLIC void errtrace(name, level)
+char *name;
+{
+ while (level-- > 0)
+ putbyte(' ');
+ putstrn(name);
+}
+
+PUBLIC void executable()
+{
+ int oldmask;
+
+ if (errcount == 0)
+ {
+ oldmask = umask(0);
+ umask(oldmask);
+ chmod(outputname, outputperms | (EXEC_PERMS & ~oldmask));
+ }
+}
+
+PUBLIC void flusherr()
+{
+ write(STDOUT_FILENO, errbuf, errbufptr - errbuf);
+ errbufptr = errbuf;
+}
+
+PRIVATE void flushout()
+{
+ unsigned nbytes;
+
+ nbytes = outbufptr - outbuf;
+ if (write(outfd, outbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+ outbufptr = outbuf;
+}
+
+#ifdef BSD_A_OUT
+PRIVATE void flushtrel()
+{
+ unsigned nbytes;
+
+ nbytes = trelbufptr - trelbuf;
+ if (write(trelfd, trelbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+ trelbufptr = trelbuf;
+}
+#endif
+
+PUBLIC void openin(filename)
+char *filename;
+{
+#if 0 /* XXX - this probably won't work with constructed lib names? */
+ if (infd == ERR || strcmp(inputname, filename) != 0)
+#endif
+ {
+ closein();
+ inputname = filename; /* this relies on filename being static */
+ if ((infd = open(filename, O_RDONLY)) < 0)
+ inputerror("cannot open");
+ inbufptr = inbufend = inbuf;
+ }
+}
+
+PUBLIC void openout(filename)
+char *filename;
+{
+ struct stat statbuf;
+
+ outputname = filename;
+ if ((outfd = creat(filename, CREAT_PERMS)) == ERR)
+ outputerror("cannot open");
+ if (fstat(outfd, &statbuf) != 0)
+ outputerror("cannot stat");
+ outputperms = statbuf.st_mode;
+ chmod(filename, outputperms & ~EXEC_PERMS);
+#ifdef BSD_A_OUT
+ drelbufptr = drelbuf;
+#endif
+ outbufptr = outbuf;
+#ifdef BSD_A_OUT
+ if ((trelfd = open(filename, O_WRONLY)) == ERR)
+ outputerror("cannot reopen");
+ trelbufptr = trelbuf;
+#endif
+}
+
+PRIVATE void outhexdigs(num)
+register offset_t num;
+{
+ if (num >= 0x10)
+ {
+ outhexdigs(num / 0x10);
+ num %= 0x10;
+ }
+ putbyte(hexdigit[num]);
+}
+
+PRIVATE void put04x(num)
+register unsigned num;
+{
+ putbyte(hexdigit[num / 0x1000]);
+ putbyte(hexdigit[(num / 0x100) & 0x0F]);
+ putbyte(hexdigit[(num / 0x10) & 0x0F]);
+ putbyte(hexdigit[num & 0x0F]);
+}
+
+#ifdef LONG_OFFSETS
+
+PUBLIC void put08lx(num)
+register offset_t num;
+{
+ put04x(num / 0x10000);
+ put04x(num % 0x10000);
+}
+
+#else /* not LONG_OFFSETS */
+
+PUBLIC void put08x(num)
+register offset_t num;
+{
+ putstr("0000");
+ put04x(num);
+}
+
+#endif /* not LONG_OFFSETS */
+
+PUBLIC void putbstr(width, str)
+unsigned width;
+char *str;
+{
+ unsigned length;
+
+ for (length = strlen(str); length < width; ++length)
+ putbyte(' ');
+ putstr(str);
+}
+
+PUBLIC void putbyte(ch)
+int ch;
+{
+ register char *ebuf;
+
+ ebuf = errbufptr;
+ if (ebuf >= errbuftop)
+ {
+ flusherr();
+ ebuf = errbufptr;
+ }
+ *ebuf++ = ch;
+ errbufptr = ebuf;
+}
+
+PUBLIC void putstr(message)
+char *message;
+{
+ while (*message != 0)
+ putbyte(*message++);
+}
+
+PRIVATE void putstrn(message)
+char *message;
+{
+ putstr(message);
+ putbyte('\n');
+ flusherr();
+}
+
+PUBLIC int readchar()
+{
+ int ch;
+
+ register char *ibuf;
+ int nread;
+
+ ibuf = inbufptr;
+ if (ibuf >= inbufend)
+ {
+ ibuf = inbufptr = inbuf;
+ nread = read(infd, ibuf, INBUFSIZE);
+ if (nread <= 0)
+ {
+ inbufend = ibuf;
+ return ERR;
+ }
+ inbufend = ibuf + nread;
+ }
+ ch = (unsigned char) *ibuf++;
+ inbufptr = ibuf;
+ return ch;
+}
+
+PUBLIC void readin(buf, count)
+char *buf;
+unsigned count;
+{
+ int ch;
+
+ while (count--)
+ {
+ if ((ch = readchar()) < 0)
+ prematureeof();
+ *buf++ = ch;
+ }
+}
+
+PUBLIC bool_pt readineofok(buf, count)
+char *buf;
+unsigned count;
+{
+ int ch;
+
+ while (count--)
+ {
+ if ((ch = readchar()) < 0)
+ return TRUE;
+ *buf++ = ch;
+ }
+ return FALSE;
+}
+
+PUBLIC void seekin(offset)
+long offset;
+{
+ inbufptr = inbufend = inbuf;
+ if (lseek(infd, offset, SEEK_SET) < 0)
+ prematureeof();
+}
+
+PUBLIC void seekout(offset)
+long offset;
+{
+ flushout();
+ if (lseek(outfd, offset, SEEK_SET) != offset)
+ outputerror("cannot seek in");
+}
+
+#ifdef BSD_A_OUT
+PUBLIC void seektrel(offset)
+long offset;
+{
+ flushtrel();
+ if (lseek(trelfd, offset, SEEK_SET) != offset)
+ outputerror("cannot seek in");
+}
+#endif
+
+PUBLIC void writechar(ch)
+int ch;
+{
+ register char *obuf;
+
+ obuf = outbufptr;
+ if (obuf >= outbuftop)
+ {
+ flushout();
+ obuf = outbufptr;
+ }
+ *obuf++ = ch;
+ outbufptr = obuf;
+}
+
+#ifdef BSD_A_OUT
+PUBLIC void writedrel(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *rbuf;
+
+ rbuf = drelbufptr;
+ while (count--)
+ {
+ if (rbuf >= drelbuftop)
+ inputerror("data relocation buffer full while processing");
+ *rbuf++ = *buf++;
+ }
+ drelbufptr = rbuf;
+}
+#endif
+
+PUBLIC void writeout(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *obuf;
+
+ obuf = outbufptr;
+ while (count--)
+ {
+ if (obuf >= outbuftop)
+ {
+ outbufptr = obuf;
+ flushout();
+ obuf = outbufptr;
+ }
+ *obuf++ = *buf++;
+ }
+ outbufptr = obuf;
+}
+
+#ifdef BSD_A_OUT
+PUBLIC void writetrel(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *rbuf;
+
+ rbuf = trelbufptr;
+ while (count--)
+ {
+ if (rbuf >= trelbuftop)
+ {
+ trelbufptr = rbuf;
+ flushtrel();
+ rbuf = trelbufptr;
+ }
+ *rbuf++ = *buf++;
+ }
+ trelbufptr = rbuf;
+}
+#endif
+
+/* error module */
+
+PRIVATE void errexit(message)
+char *message;
+{
+ putstrn(message);
+ exit(2);
+}
+
+PUBLIC void fatalerror(message)
+char *message;
+{
+ refer();
+ errexit(message);
+}
+
+PUBLIC void inputerror(message)
+char *message;
+{
+ refer();
+ putstr(message);
+ putstr(" input file ");
+ errexit(inputname);
+}
+
+PUBLIC void input1error(message)
+char *message;
+{
+ refer();
+ putstr(inputname);
+ errexit(message);
+}
+
+PRIVATE void outputerror(message)
+char *message;
+{
+ refer();
+ putstr(message);
+ putstr(" output file ");
+ errexit(outputname);
+}
+
+PUBLIC void outofmemory()
+{
+ inputerror("out of memory while processing");
+}
+
+PUBLIC void prematureeof()
+{
+ inputerror("premature end of");
+}
+
+PUBLIC void redefined(name, message, archentry, deffilename, defarchentry)
+char *name;
+char *message;
+char *archentry;
+char *deffilename;
+char *defarchentry;
+{
+ ++warncount;
+ refer();
+ putstr("warning: ");
+ putstr(name);
+ putstr(" redefined");
+ putstr(message);
+ putstr(" in file ");
+ putstr(inputname);
+ if (archentry != NULL)
+ {
+ putbyte('(');
+ putstr(archentry);
+ putbyte(')');
+ }
+ putstr("; using definition in ");
+ putstr(deffilename);
+ if (defarchentry != NULL)
+ {
+ putbyte('(');
+ putstr(defarchentry);
+ putbyte(')');
+ }
+ putbyte('\n');
+}
+
+PRIVATE void refer()
+{
+ putstr(refname);
+ putstr(": ");
+}
+
+PUBLIC void reserved(name)
+char *name;
+{
+ ++errcount;
+ putstr("incorrect use of reserved symbol: ");
+ putstrn(name);
+}
+
+PUBLIC void size_error(seg, count, size)
+char seg;
+offset_t count;
+offset_t size;
+{
+ refer();
+ putstr("seg ");
+ outhexdigs((offset_t) seg);
+ putstr(" has wrong size ");
+ outhexdigs(count);
+ putstr(", supposed to be ");
+ outhexdigs(size);
+ errexit("\n");
+}
+
+PUBLIC void undefined(name)
+char *name;
+{
+ ++errcount;
+ putstr("undefined symbol: ");
+ putstrn(name);
+}
+
+PUBLIC void usage()
+{
+ putstr("usage: ");
+ putstr(refname);
+#ifdef BSD_A_OUT
+ errexit("\
+ [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-L libdir] [-Olibfile] [-T textaddr] infile...");
+#else
+ errexit("\
+ [-03Mimstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-L libdir] [-Olibfile] [-T textaddr] infile...");
+#endif
+}
+
+PUBLIC void use_error(message)
+char *message;
+{
+ refer();
+ putstrn(message);
+ usage();
+}
diff --git a/bin86-0.3/ld/ld.c b/bin86-0.3/ld/ld.c
new file mode 100644
index 0000000..04ffe83
--- /dev/null
+++ b/bin86-0.3/ld/ld.c
@@ -0,0 +1,180 @@
+/*
+ * bin86/ld/ld.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */
+
+#ifdef STDC_HEADERS_MISSING
+extern int errno;
+#else
+#include <errno.h>
+#endif
+
+#include "const.h"
+#include "byteord.h"
+#include "type.h"
+#include "globvar.h"
+
+#define MAX_LIBS (NR_STDLIBS + 5)
+#define NR_STDLIBS 1
+
+PUBLIC long text_base_address; /* XXX */
+
+PRIVATE bool_t flag[128];
+PRIVATE char *libs[MAX_LIBS] = {
+#ifdef MC6809
+ "/usr/local/lib/m09/",
+#else
+ /* One of the following values will be inserted at run time. */
+# define std386lib "/usr/local/lib/i386/"
+# define std86lib "/usr/local/lib/i86/"
+#endif
+ 0
+};
+PRIVATE int lastlib = NR_STDLIBS;
+
+FORWARD char *buildname P((char *pre, char *mid, char *suf));
+FORWARD char *expandlib P((char *fn));
+
+PRIVATE char *buildname(pre, mid, suf)
+char *pre;
+char *mid;
+char *suf;
+{
+ char *name;
+
+ name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1);
+ strcpy(name, pre);
+ strcat(name, mid);
+ strcat(name, suf);
+ return name;
+}
+
+PRIVATE char *expandlib(fn)
+char *fn;
+{
+ char *path;
+ int i;
+
+#ifndef MC6809
+ libs[0] = flag['3'] ? std386lib : std86lib;
+#endif
+
+ for (i = lastlib - 1; i >= 0; --i)
+ {
+ path = ourmalloc(strlen(libs[i]) + strlen(fn) + 1);
+ strcpy(path, libs[i]);
+ strcat(path, fn);
+ if (access(path, R_OK) == 0)
+ return path;
+ ourfree(path);
+ }
+ return NULL;
+}
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ register char *arg;
+ int argn;
+ static char crtprefix[] = "crt";
+ static char crtsuffix[] = ".o";
+ char *infilename;
+ static char libprefix[] = "lib";
+ static char libsuffix[] = ".a";
+ char *outfilename;
+ char *tfn;
+
+ ioinit(argv[0]);
+ objinit();
+ syminit();
+ typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN);
+#if 0
+ flag['z'] = flag['3'] = sizeof(char *) >= 4;
+#else
+ flag['z'] = 0;
+ flag['3'] = sizeof(char *) >= 4;
+#endif
+ outfilename = NULL;
+ for (argn = 1; argn < argc; ++argn)
+ {
+ arg = argv[argn];
+ if (*arg != '-')
+ readsyms(arg, flag['t']);
+ else
+ switch (arg[1])
+ {
+ case '0': /* use 16-bit libraries */
+ case '3': /* use 32-bit libraries */
+ case 'M': /* print symbols linked */
+ case 'i': /* separate I & D output */
+ case 'm': /* print modules linked */
+#ifdef BSD_A_OUT
+ case 'r': /* relocatable output */
+#endif
+ case 's': /* strip symbols */
+ case 't': /* trace modules linked */
+ case 'z': /* unmapped zero page */
+ if (arg[2] == 0)
+ flag[arg[1]] = TRUE;
+ else if (arg[2] == '-' && arg[3] == 0)
+ flag[arg[1]] = FALSE;
+ else
+ usage();
+ if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
+ flag['3'] = !flag['0'];
+ break;
+ case 'C': /* startfile name */
+ tfn = buildname(crtprefix, arg + 2, crtsuffix);
+ if ((infilename = expandlib(tfn)) == NULL)
+ fatalerror(tfn);
+ readsyms(infilename, flag['t']);
+ break;
+ case 'L': /* library path */
+ if (lastlib < MAX_LIBS)
+ libs[lastlib++] = arg + 2;
+ else
+ fatalerror("too many library paths");
+ break;
+ case 'O': /* library file name */
+ if ((infilename = expandlib(arg + 2)) == NULL)
+ fatalerror(arg);
+ readsyms(infilename, flag['t']);
+ break;
+ case 'T': /* text base address */
+ if (arg[2] != 0 || ++argn >= argc)
+ usage();
+ errno = 0;
+ text_base_address = strtoul(argv[argn], (char **) NULL, 16);
+ if (errno != 0)
+ use_error("invalid text address");
+ break;
+ case 'l': /* library name */
+ tfn = buildname(libprefix, arg + 2, libsuffix);
+ if ((infilename = expandlib(tfn)) == NULL)
+ fatalerror(tfn);
+ readsyms(infilename, flag['t']);
+ break;
+ case 'o': /* output file name */
+ if (arg[2] != 0 || ++argn >= argc || outfilename != NULL)
+ usage();
+ outfilename = argv[argn];
+ break;
+ default:
+ usage();
+ }
+ }
+ linksyms(flag['r']);
+ if (outfilename == NULL)
+ outfilename = "a.out";
+ writebin(outfilename, flag['i'], flag['3'], flag['s'], flag['z']);
+ if (flag['m'])
+ dumpmods();
+ if (flag['M'])
+ dumpsyms();
+ flusherr();
+ return errcount ? 1 : 0;
+}
diff --git a/bin86-0.3/ld/obj.h b/bin86-0.3/ld/obj.h
new file mode 100644
index 0000000..d9ba2ba
--- /dev/null
+++ b/bin86-0.3/ld/obj.h
@@ -0,0 +1,58 @@
+/*
+ * bin86/ld/obj.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* obj.h - constants for Introl object modules */
+
+#define OBJ_H
+
+#ifdef I80386
+# define LONG_OFFSETS /* others can use this, but wasteful */
+#endif
+
+#ifndef OMAGIC
+# ifdef I80386
+# define OMAGIC 0x86A3
+# endif
+
+# ifdef I8086
+# define OMAGIC 0x86A0
+# endif
+
+# ifdef MC6809
+# define OMAGIC 0x5331
+# endif
+#endif
+
+#ifdef LONG_OFFSETS
+# define cntooffset cnu4
+# define offtocn u4cn
+#else
+# define cntooffset cnu2
+# define offtocn u2cn
+#endif
+
+#ifdef MC6809 /* temp don't support alignment at all */
+# define ld_roundup( num, boundary, type ) (num)
+#else
+# define ld_roundup( num, boundary, type ) \
+ (((num) + ((boundary) - 1)) & (type) ~((boundary) - 1))
+#endif
+
+#define MAX_OFFSET_SIZE 4
+#define NSEG 16
+
+/* flag values |SZ|LXXXX|N|E|I|R|A|SEGM|, X not used */
+
+#define A_MASK 0x0010 /* absolute */
+#define C_MASK 0x0020 /* common (internal only) */
+#define E_MASK 0x0080 /* exported */
+#define I_MASK 0x0040 /* imported */
+#define N_MASK 0x0100 /* entry point */
+#define R_MASK 0x0020 /* relative (in text only) */
+#define SEGM_MASK 0x000F /* segment (if not absolute) */
+#define SA_MASK 0x2000 /* offset is storage allocation */
+#define SZ_MASK 0xC000 /* size descriptor for value */
+#define SZ_SHIFT 14
diff --git a/bin86-0.3/ld/readobj.c b/bin86-0.3/ld/readobj.c
new file mode 100644
index 0000000..5c4dd72
--- /dev/null
+++ b/bin86-0.3/ld/readobj.c
@@ -0,0 +1,368 @@
+/*
+ * bin86/ld/readobj.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* readobj.c - read object file for linker */
+
+#include "ar.h" /* maybe local copy of <ar.h> for cross-link */
+#include "const.h"
+#include "byteord.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+/*
+ Linking takes 2 passes. The 1st pass reads through all files specified
+in the command line, and all libraries. All public symbols are extracted
+and stored in a chained hash table. For each module, its file and header
+data recorded, and the resulting structures are chained together
+(interleaved with the symbols).
+
+ The symbol descriptors are separated from the symbol names, so we must
+record all the descriptors of a module before putting the symbols in the
+symbol table (poor design). The descriptors are stored in the symbol
+table, then moved to the top of the table to make room for the symols.
+The symbols referred to in a given module are linked together by a chain
+beginning in the module descriptor.
+*/
+
+PRIVATE char convertsize[NSEG / 4] = {0, 1, 2, 4};
+PRIVATE struct entrylist *entrylast; /* last on list of entry symbols */
+PRIVATE struct redlist *redlast; /* last on list of redefined symbols */
+PRIVATE struct modstruct *modlast; /* data for last module */
+
+FORWARD long readarheader P((char **parchentry));
+FORWARD unsigned readfileheader P((void));
+FORWARD void readmodule P((char *filename, char *archentry));
+FORWARD void reedmodheader P((void));
+FORWARD bool_pt redsym P((struct symstruct *symptr, offset_t value));
+FORWARD unsigned checksum P((char *string, unsigned length));
+FORWARD unsigned segbits P((unsigned seg, char *sizedesc));
+
+/* initialise object file handler */
+
+PUBLIC void objinit()
+{
+ modfirst = modlast = NULL;
+ entryfirst = entrylast = NULL;
+ redfirst = redlast = NULL;
+}
+
+/* read all symbol definitions in an object file */
+
+PUBLIC void readsyms(filename, trace)
+char *filename;
+bool_pt trace;
+{
+ char *archentry;
+ long filelength;
+ char filemagic[SARMAG];
+ long filepos;
+ unsigned modcount;
+
+ if (trace)
+ errtrace(filename, 0);
+ openin(filename); /* input is not open, so position is start */
+ switch ((unsigned) readsize(2))
+ {
+ case OMAGIC:
+ seekin(0L);
+ for (modcount = readfileheader(); modcount-- != 0;)
+ readmodule(filename, (char *) NULL);
+ break;
+ default:
+ seekin(0L);
+ readin(filemagic, sizeof filemagic);
+ if (strncmp(filemagic, ARMAG, sizeof filemagic) != 0)
+ input1error(" has bad magic number");
+ filepos = SARMAG;
+ while ((filelength = readarheader(&archentry)) > 0)
+ {
+ if (trace)
+ errtrace(archentry, 2);
+ filepos += sizeof(struct ar_hdr);
+ for (modcount = readfileheader(); modcount-- != 0;)
+ {
+ readmodule(stralloc(filename), archentry);
+ modlast->textoffset += filepos;
+ }
+ seekin(filepos += ld_roundup(filelength, 2, long));
+ }
+ break;
+ }
+ closein();
+}
+
+/* read archive header and return length */
+
+PRIVATE long readarheader(parchentry)
+char **parchentry;
+{
+ struct ar_hdr arheader;
+ char *endptr;
+ char *nameptr;
+
+ if (readineofok((char *) &arheader, sizeof arheader))
+ return 0;
+ strncpy (*parchentry = nameptr = ourmalloc(sizeof arheader.ar_name + 1),
+ arheader.ar_name, sizeof arheader.ar_name);
+ endptr = nameptr + sizeof arheader.ar_name;
+ do
+ *endptr = 0;
+ while (endptr > nameptr && *--endptr == ' ');
+ return strtoul(arheader.ar_size, (char **) NULL, 0);
+}
+
+/* read and check file header of the object file just opened */
+
+PRIVATE unsigned readfileheader()
+{
+ struct
+ {
+ char magic[2];
+ char count[2]; /* really an int */
+ }
+ fileheader;
+ char filechecksum; /* part of fileheader but would unalign */
+
+ readin((char *) &fileheader, sizeof fileheader);
+ readin(&filechecksum, sizeof filechecksum);
+ if (filechecksum != checksum((char *) &fileheader, sizeof fileheader))
+ input1error(" is not an object file");
+ return c2u2(fileheader.count);
+}
+
+/* read the next module */
+
+PRIVATE void readmodule(filename, archentry)
+char *filename;
+char *archentry;
+{
+ struct symdstruct /* to save parts of symbol before name known */
+ {
+ offset_t dvalue;
+ flags_t dflags;
+ };
+ struct symdstruct *endsymdptr;
+ flags_t flags;
+ unsigned nsymbol;
+ struct symdstruct *symdptr;
+ char *symname;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+
+ reedmodheader();
+ modlast->filename = filename;
+ modlast->archentry = archentry;
+ nsymbol = readsize(2);
+ symdptr = (struct symdstruct *)
+ ourmalloc(nsymbol * sizeof(struct symdstruct));
+ for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; ++symdptr)
+ {
+ readsize(2); /* discard string offset, assume strings seq */
+ symdptr->dflags = flags = readsize(2);
+ symdptr->dvalue = readconvsize((flags & SZ_MASK) >> SZ_SHIFT);
+ /* NB unsigned flags to give logical shift */
+ /* bug in Xenix 2.5 cc causes (int) of the */
+ /* argument to turn flags into an int */
+ }
+ symdptr = (struct symdstruct *)
+ moveup(nsymbol * sizeof(struct symdstruct));
+ modlast->symparray = symparray = (struct symstruct **)
+ ourmalloc((nsymbol + 1) * sizeof(struct symstruct *));
+ symname = readstring(); /* module name */
+ modlast->modname = stralloc(symname); /* likely OK overlapped copy */
+ for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr;
+ *symparray++ = symptr, release((char *) ++symdptr))
+ {
+ symname = readstring();
+ if ((flags = symdptr->dflags) & (E_MASK | I_MASK) &&
+ (symptr = findsym(symname)) != NULL)
+ {
+ /*
+ weaken segment-checking by letting the maximum segment
+ (SEGM_MASK) mean any segment
+ */
+ if ((symptr->flags & SEGM_MASK) == SEGM_MASK)
+ symptr->flags &= ~SEGM_MASK | (flags & SEGM_MASK);
+ else if ((flags & SEGM_MASK) == SEGM_MASK)
+ flags &= ~SEGM_MASK | (symptr->flags & SEGM_MASK);
+ if ((flags ^ symptr->flags) & (N_MASK | A_MASK | SEGM_MASK))
+ {
+ redefined(symname, " with different segment or relocatability",
+ archentry, symptr->modptr->filename,
+ symptr->modptr->archentry);
+ continue;
+ }
+ if (symptr->flags & E_MASK)
+ {
+ if (flags & E_MASK && redsym(symptr, symdptr->dvalue))
+ redefined(symname, "", archentry, symptr->modptr->filename,
+ symptr->modptr->archentry);
+ continue;
+ }
+ if (flags & I_MASK && symdptr->dvalue <= symptr->value)
+ continue;
+ }
+ else
+ symptr = addsym(symname);
+ symptr->modptr = modlast;
+ symptr->value = symdptr->dvalue;
+ symptr->flags = flags;
+ if (flags & N_MASK)
+ entrysym(symptr);
+ }
+ *symparray = NULL;
+}
+
+/* put symbol on entry symbol list if it is not already */
+
+PUBLIC void entrysym(symptr)
+struct symstruct *symptr;
+{
+ register struct entrylist *elptr;
+
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ if (symptr == elptr->elsymptr)
+ return;
+ elptr = (struct entrylist *) ourmalloc(sizeof(struct entrylist));
+ elptr->elnext = NULL;
+ elptr->elsymptr = symptr;
+ if (entryfirst == NULL)
+ entryfirst = elptr;
+ else
+ entrylast->elnext = elptr;
+ entrylast = elptr;
+}
+
+/* read the header of the next module */
+
+PRIVATE void reedmodheader()
+{
+ struct
+ {
+ char htextoffset[4]; /* offset to module text in file */
+ char htextsize[4]; /* size of text (may be 0 for last mod) */
+ char stringssize[2]; /* size of string area */
+ char hclass; /* module class */
+ char revision; /* module revision */
+ }
+ modheader;
+ unsigned seg;
+ unsigned count;
+ char *cptr;
+ struct modstruct *modptr;
+
+ readin((char *) &modheader, sizeof modheader);
+ modptr = (struct modstruct *) ourmalloc(sizeof(struct modstruct));
+ modptr->modnext = NULL;
+ modptr->textoffset = c4u4(modheader.htextoffset);
+ modptr->class = modheader.hclass;
+ readin(modptr->segmaxsize, sizeof modptr->segmaxsize);
+ readin(modptr->segsizedesc, sizeof modptr->segsizedesc);
+ cptr = modptr->segsize;
+ for (seg = 0; seg < NSEG; ++seg)
+ {
+ if ((count = segsizecount(seg, modptr)) != 0)
+ {
+ if (cptr == modptr->segsize)
+ ourmalloc(count - 1); /* 1st byte reserved in struct */
+ else
+ ourmalloc(count);
+ readin(cptr, count);
+ cptr += count;
+ }
+ }
+ if (modfirst == NULL)
+ modfirst = modptr;
+ else
+ modlast->modnext = modptr;
+ modlast = modptr;
+}
+
+PRIVATE bool_pt redsym(symptr, value)
+register struct symstruct *symptr;
+offset_t value;
+{
+ register struct redlist *rlptr;
+ char class;
+
+ if (symptr->modptr->class != (class = modlast->class))
+ for (rlptr = redfirst;; rlptr = rlptr->rlnext)
+ {
+ if (rlptr == NULL)
+ {
+ rlptr = (struct redlist *)
+ ourmalloc(sizeof(struct redlist));
+ rlptr->rlnext = NULL;
+ rlptr->rlsymptr = symptr;
+ if (symptr->modptr->class < class)
+ /* prefer lower class - put other on redlist */
+ {
+ rlptr->rlmodptr = modlast;
+ rlptr->rlvalue = value;
+ }
+ else
+ {
+ rlptr->rlmodptr = symptr->modptr;
+ symptr->modptr = modlast;
+ rlptr->rlvalue = symptr->value;
+ symptr->value = value;
+ }
+ if (redfirst == NULL)
+ redfirst = rlptr;
+ else
+ redlast->rlnext = rlptr;
+ redlast = rlptr;
+ return FALSE;
+ }
+ if (symptr == rlptr->rlsymptr && class == rlptr->rlmodptr->class)
+ break;
+ }
+ return TRUE;
+}
+
+PRIVATE unsigned checksum(string, length)
+char *string;
+unsigned length;
+{
+ unsigned char sum; /* this is a 1-byte checksum */
+
+ for (sum = 0; length-- != 0;)
+ sum += *string++ & 0xFF;
+ return sum;
+}
+
+PUBLIC offset_t readconvsize(countindex)
+unsigned countindex;
+{
+ return readsize(convertsize[countindex]);
+}
+
+PUBLIC offset_t readsize(count)
+unsigned count;
+{
+ char buf[MAX_OFFSET_SIZE];
+
+ if (count == 0)
+ return 0;
+ readin(buf, count);
+ return cntooffset(buf, count);
+}
+
+PRIVATE unsigned segbits(seg, sizedesc)
+unsigned seg;
+char *sizedesc;
+{
+ return 3 & ((unsigned) sizedesc[((NSEG - 1) - seg) / 4] >> (2 * (seg % 4)));
+ /* unsigned to give logical shift */
+}
+
+PUBLIC unsigned segsizecount(seg, modptr)
+unsigned seg;
+struct modstruct *modptr;
+{
+ return convertsize[segbits(seg, modptr->segsizedesc)];
+}
diff --git a/bin86-0.3/ld/table.c b/bin86-0.3/ld/table.c
new file mode 100644
index 0000000..557eec6
--- /dev/null
+++ b/bin86-0.3/ld/table.c
@@ -0,0 +1,202 @@
+/*
+ * bin86/ld/table.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* table.c - table-handler module for linker */
+
+#include "const.h"
+#include "align.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */
+#define HASHTABSIZE 256
+
+PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* hash table */
+PRIVATE char *tableptr; /* next free spot in catchall table */
+PRIVATE char *tableend; /* ptr to spot after last in table */
+
+FORWARD struct symstruct **gethashptr P((char *name));
+
+/* initialise symbol table */
+
+PUBLIC void syminit()
+{
+ unsigned i;
+
+ for (i = sizeof(int) <= 2 ? 0xE000 : (unsigned) 0x38000;
+ i != 0; i -= 512)
+ if ((tableptr = malloc(i)) != NULL)
+ break;
+ if (tableptr == NULL)
+ outofmemory();
+ tableend = tableptr + i;
+ for (i = 0; i < HASHTABSIZE; i++)
+ hashtab[i] = NULL;
+}
+
+/* add named symbol to end of table - initialise only name and next fields */
+/* caller must not duplicate names of externals for findsym() to work */
+
+PUBLIC struct symstruct *addsym(name)
+char *name;
+{
+ struct symstruct **hashptr;
+ struct symstruct *oldsymptr;
+ struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ {
+ oldsymptr = symptr;
+ symptr = symptr->next;
+ }
+ align(tableptr);
+ symptr = (struct symstruct *) tableptr;
+ if ((tableptr = symptr->name + (strlen(name) + 1)) > tableend)
+ outofmemory();
+ symptr->modptr = NULL;
+ symptr->next = NULL;
+ if (name != symptr->name)
+ strcpy(symptr->name, name); /* should't happen */
+ if (*hashptr == NULL)
+ *hashptr = symptr;
+ else
+ oldsymptr->next = symptr;
+ return symptr;
+}
+
+/* lookup named symbol */
+
+PUBLIC struct symstruct *findsym(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (!(symptr->flags & (E_MASK | I_MASK)) ||
+ strcmp(symptr->name, name) != 0))
+ symptr = symptr->next;
+ return symptr;
+}
+
+/* convert name to a hash table ptr */
+
+PRIVATE struct symstruct **gethashptr(name)
+register char *name;
+{
+ register unsigned hashval;
+
+ hashval = 0;
+ while (*name)
+ hashval = hashval * 2 + *name++;
+ return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1));
+
+/*
+
+#asm
+
+GOLDEN EQU 157
+HASHTABSIZE EQU 256
+
+ CLRB can build value here since HASHTABSIZE <= 256
+ LDA ,X
+ BEQ HASHVAL.EXIT
+HASHVAL.LOOP
+ ADDB ,X+
+ LSLB
+ LDA ,X
+ BNE HASHVAL.LOOP
+ RORB
+ LDA #GOLDEN
+ MUL
+HASHVAL.EXIT
+HASHVAL.EXIT
+ LDX #_hashtab
+ ABX discard A - same as taking mod HASHTABSIZE
+ ABX
+#endasm
+
+*/
+
+}
+
+/* move symbol descriptor entries to top of table (no error checking) */
+
+PUBLIC char *moveup(nbytes)
+unsigned nbytes;
+{
+ register char *source;
+ register char *target;
+
+ source = tableptr;
+ target = tableend;
+ while (nbytes--)
+ *--target = *--source;
+ tableptr = source;
+ return tableend = target;
+}
+
+/* our version of malloc */
+
+PUBLIC char *ourmalloc(nbytes)
+unsigned nbytes;
+{
+ char *allocptr;
+
+ align(tableptr);
+ allocptr = tableptr;
+ if ((tableptr += nbytes) > tableend)
+ outofmemory();
+ return allocptr;
+}
+
+/* our version of free (release from bottom of table) */
+
+PUBLIC void ourfree(cptr)
+char *cptr;
+{
+ tableptr = cptr;
+}
+
+/* read string from file into table at offset suitable for next symbol */
+
+PUBLIC char *readstring()
+{
+ int c;
+ char *s;
+ char *start;
+
+ align(tableptr);
+ start = s = ((struct symstruct *) tableptr)->name;
+ while (TRUE)
+ {
+ if (s >= tableend)
+ outofmemory();
+ if ((c = readchar()) < 0)
+ prematureeof();
+ if ((*s++ = c) == 0)
+ return start;
+ }
+ /* NOTREACHED */
+}
+
+/* release from top of table */
+
+PUBLIC void release(cptr)
+char *cptr;
+{
+ tableend = cptr;
+}
+
+/* allocate space for string */
+
+PUBLIC char *stralloc(s)
+char *s;
+{
+ return strcpy(ourmalloc((unsigned) strlen(s) + 1), s);
+}
diff --git a/bin86-0.3/ld/type.h b/bin86-0.3/ld/type.h
new file mode 100644
index 0000000..d5d9a8d
--- /dev/null
+++ b/bin86-0.3/ld/type.h
@@ -0,0 +1,228 @@
+/*
+ * bin86/ld/type.h
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* type.h - types for linker */
+
+typedef unsigned bool_pt;
+typedef unsigned char bool_t;
+
+typedef unsigned short u2_t;
+typedef unsigned u2_pt;
+typedef unsigned long u4_t;
+typedef unsigned long u4_pt;
+
+#ifdef OBJ_H /* obj.h is included */
+
+/* Prevent the use of offset_t */
+#ifndef offset_t
+#define offset_t offset_T
+#endif
+
+typedef unsigned flags_t; /* unsigned makes shifts logical */
+
+#ifdef LONG_OFFSETS
+typedef unsigned long offset_t;
+#else
+typedef unsigned offset_t;
+#endif
+
+struct entrylist /* list of entry symbols */
+{
+ struct entrylist *elnext; /* next on list */
+ struct symstruct *elsymptr; /* entry on list */
+};
+
+struct modstruct /* module table entry format */
+{
+ char *filename; /* file containing this module */
+ char *archentry; /* name of component file for archives */
+ char *modname; /* name of module */
+ long textoffset; /* offset to module text in file */
+ char class; /* class of module */
+ char loadflag; /* set if module to be loaded */
+ char segmaxsize[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for seg max size */
+ /* 00 = 1, 01 = 2, 10 = 3, 11 = 4 */
+ char segsizedesc[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for #bytes for size */
+ /* 00 = 0, 01 = 1, 10 = 2, 11 = 4 */
+ struct symstruct **symparray; /* ^array of ptrs to referenced syms */
+ struct modstruct *modnext; /* next module in order of initial reading */
+ char segsize[1]; /* up to 64 size bytes begin here */
+}; /* careful with sizeof( struct modstruct )!! */
+
+struct redlist /* list of redefined (exported) symbols */
+{
+ struct redlist *rlnext; /* next on list */
+ struct symstruct *rlsymptr; /* to symbol with same name, flags */
+ struct modstruct *rlmodptr; /* module for this redefinition */
+ offset_t rlvalue; /* value for this redefinition */
+};
+
+struct symstruct /* symbol table entry format */
+{
+ struct modstruct *modptr; /* module where symbol is defined */
+ offset_t value; /* value of symbol */
+ flags_t flags; /* see below (unsigned makes shifts logical) */
+ struct symstruct *next; /* next symbol with same hash value */
+ char name[1]; /* name is any string beginning here */
+}; /* don't use sizeof( struct symstruct )!! */
+
+#endif /* obj.h is included */
+
+/* prototypes */
+
+#if defined(PROTO) || __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+/* dump.c */
+void dumpmods P((void));
+void dumpsyms P((void));
+
+/* io.c */
+void ioinit P((char *progname));
+void closein P((void));
+void closeout P((void));
+void errtrace P((char *name, int level));
+void executable P((void));
+void flusherr P((void));
+void openin P((char *filename));
+void openout P((char *filename));
+void putstr P((char *message));
+#ifdef OBJ_H
+void put08x P((offset_t num));
+void put08lx P((offset_t num));
+#endif
+void putbstr P((unsigned width, char *str));
+void putbyte P((int ch));
+int readchar P((void));
+void readin P((char *buf, unsigned count));
+bool_pt readineofok P((char *buf, unsigned count));
+void seekin P((long offset));
+void seekout P((long offset));
+void seektrel P((long offset));
+void writechar P((int c));
+void writedrel P((char *buf, unsigned count));
+void writeout P((char *buf, unsigned count));
+void writetrel P((char *buf, unsigned count));
+void fatalerror P((char *message));
+void inputerror P((char *message));
+void input1error P((char *message));
+void outofmemory P((void));
+void prematureeof P((void));
+void redefined P((char *name, char *message, char *archentry,
+ char *deffilename, char *defarchentry));
+void reserved P((char *name));
+#ifdef OBJ_H
+void size_error P((int seg, offset_t count, offset_t size));
+#endif
+void undefined P((char *name));
+void usage P((void));
+void use_error P((char *message));
+
+/* ld.c */
+int main P((int argc, char **argv));
+
+/* readobj.c */
+void objinit P((void));
+void readsyms P((char *filename, bool_pt trace));
+#ifdef OBJ_H
+void entrysym P((struct symstruct *symptr));
+offset_t readconvsize P((unsigned countindex));
+offset_t readsize P((unsigned count));
+unsigned segsizecount P((unsigned seg, struct modstruct *modptr));
+#endif
+
+/* table.c */
+void syminit P((void));
+struct symstruct *addsym P((char *name));
+struct symstruct *findsym P((char *name));
+char *moveup P((unsigned nbytes));
+char *ourmalloc P((unsigned nbytes));
+void ourfree P((char *cptr));
+char *readstring P((void));
+void release P((char *cptr));
+char *stralloc P((char *s));
+
+/* typeconvert.c */
+u2_pt c2u2 P((char *buf));
+u4_t c4u4 P((char *buf));
+u2_pt cnu2 P((char *buf, unsigned count));
+u4_t cnu4 P((char *buf, unsigned count));
+void u2c2 P((char *buf, u2_pt offset));
+void u4c4 P((char *buf, u4_t offset));
+void u2cn P((char *buf, u2_pt offset, unsigned count));
+void u4cn P((char *buf, u4_t offset, unsigned count));
+bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian));
+
+/* writebin.c */
+void writebin P((char *outfilename, bool_pt argsepid, bool_pt argbits32,
+ bool_pt argstripflag, bool_pt arguzp));
+void linksyms P((bool_pt argreloc_output));
+
+/* Make offset_t safe for the standard includes */
+#undef offset_t
+
+/* library - fcntl.h */
+#undef NULL
+#include <fcntl.h>
+/*
+int creat P((const char *_path, int _mode));
+int open P((const char *_path, int _oflag, ...));
+*/
+
+/* library - sys/stat.h */
+#include <sys/stat.h>
+#ifdef MY_STAT_H
+int chmod P((const char *_path, mode_t _mode));
+int fstat P((int _fd, struct stat *_statbuf));
+mode_t umask P((mode_t _oldmask));
+ /* it should be mode_t but it's hard to
+ * decide which systems define it, and where */
+#endif
+
+/* library - stdlib.h */
+#include <stdlib.h>
+/*
+void exit P((int _status));
+void *malloc P((unsigned _nbytes));
+unsigned long strtoul P((const char *_nptr, char **_endptr, int _base));
+*/
+
+/* library - string.h */
+#include <string.h>
+/*
+void *memset P((void *_s, int _c, unsigned _nbytes));
+char *strcat P((char *_target, const char *_source));
+char *strchr P((const char *_s, int _ch));
+int strcmp P((const char *_s1, const char *_s2));
+char *strcpy P((char *_target, const char *_source));
+unsigned strlen P((const char *_s));
+char *strncat P((char *_target, const char *_source, unsigned _maxlength));
+int strncmp P((const char *_s1, const char *_s2, unsigned _nbytes));
+char *strncpy P((char *_target, const char *_source, unsigned _maxlength));
+char *strrchr P((const char *_s, int _ch));
+*/
+
+/* library - unistd.h */
+#include <unistd.h>
+/*
+int access P((char *_path, int _amode));
+int close P((int _fd));
+long lseek P((int _fd, long _offset, int _whence));
+int read P((int _fd, char *_buf, unsigned _nbytes));
+int write P((int _fd, char *_buf, unsigned _nbytes));
+*/
+
+#ifdef OBJ_H /* obj.h is included */
+
+/* Prevent the use of offset_t */
+#ifndef offset_t
+#define offset_t offset_T
+#endif
+
+#endif
diff --git a/bin86-0.3/ld/typeconv.c b/bin86-0.3/ld/typeconv.c
new file mode 100644
index 0000000..1465106
--- /dev/null
+++ b/bin86-0.3/ld/typeconv.c
@@ -0,0 +1,540 @@
+/*
+ * bin86/ld/typeconv.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+/* typeconv.c - convert between char arrays and unsigneds */
+
+/*
+ c2u2(): 2 byte array to 2 byte unsigned
+ c4u4(): 4 byte array to 4 byte unsigned
+ cnu2(): n byte array to 2 byte unsigned
+ cnu4(): n byte array to 4 byte unsigned
+ u2c2(): 2 byte unsigned to 2 byte array
+ u2cn(): 2 byte unsigned to n byte array
+ u4c4(): 4 byte unsigned to 4 byte array
+ u4cn(): 4 byte unsigned to n byte array
+ typeconv_init: (re)initialise for given byte order.
+ Default is no swapping, but the initialisation should be done
+ anyway to provide some validity checks (returns FALSE if error).
+
+ Not provided:
+ c2u4(), c4u2(), u2c4(), u4c2().
+ Each of these is best done by truncating or extending a return value
+ or argument to the appropiate fixed-count function.
+ c4u2() has too many cases to do in-line conveniently, and the others
+ are hardly more efficient when done in-line.
+
+ 4 byte orderings for both char arrays and unsigneds are supported:
+ 0123 - little-endian
+ 3210 - big-endian
+ 2301 - little-endian with long words big-endian (pdp11)
+ 1032 - big-endian with long words little_endian (who knows?)
+
+ The unsigned's byte order is that of the machine on which these
+ routines are running.
+ It is determined at run time initialisation since the compiler/
+ preprocessor is too dumb to tell us at compile time.
+*/
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+
+FORWARD u2_pt c2u2_00 P((char *buf));
+FORWARD u4_pt c4u4_00 P((char *buf));
+FORWARD u2_pt c2u2_ss P((char *buf));
+FORWARD u4_pt c4u4_ss P((char *buf));
+FORWARD u4_pt c4u4_s0 P((char *buf));
+FORWARD u4_pt c4u4_0s P((char *buf));
+FORWARD void u2c2_00 P((char *buf, u2_pt offset));
+FORWARD void u4c4_00 P((char *buf, u4_t offset));
+FORWARD void u2c2_ss P((char *buf, u2_pt offset));
+FORWARD void u4c4_ss P((char *buf, u4_t offset));
+FORWARD void u4c4_s0 P((char *buf, u4_t offset));
+FORWARD void u4c4_0s P((char *buf, u4_t offset));
+
+PRIVATE u2_pt (*pc2u2) P((char *buf)) = c2u2_00;
+PRIVATE u4_pt (*pc4u4) P((char *buf)) = c4u4_00;
+PRIVATE void (*pu2c2) P((char *buf, u2_pt offset)) = u2c2_00;
+PRIVATE void (*pu4c4) P((char *buf, u4_t offset)) = u4c4_00;
+
+/* === char arrays to unsigneds === */
+
+/* no bytes swapped, longwinded to avoid alignment problems */
+
+PRIVATE u2_pt c2u2_00(buf)
+register char *buf;
+{
+ u2_t offset;
+
+ ((char *) &offset)[0] = buf[0];
+ ((char *) &offset)[1] = buf[1];
+ return offset;
+}
+
+PRIVATE u4_pt c4u4_00(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[0];
+ ((char *) &offset)[1] = buf[1];
+ ((char *) &offset)[2] = buf[2];
+ ((char *) &offset)[3] = buf[3];
+ return offset;
+}
+
+/* straight swapping for little-endian to big-endian and vice versa */
+
+PRIVATE u2_pt c2u2_ss(buf)
+register char *buf;
+{
+ u2_t offset;
+
+ ((char *) &offset)[0] = buf[1];
+ ((char *) &offset)[1] = buf[0];
+ return offset;
+}
+
+PRIVATE u4_pt c4u4_ss(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[3];
+ ((char *) &offset)[1] = buf[2];
+ ((char *) &offset)[2] = buf[1];
+ ((char *) &offset)[3] = buf[0];
+ return offset;
+}
+
+/* wierd swapping for different-endian u2's, same-endian u4's */
+
+PRIVATE u4_pt c4u4_s0(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[1];
+ ((char *) &offset)[1] = buf[0];
+ ((char *) &offset)[2] = buf[3];
+ ((char *) &offset)[3] = buf[2];
+ return offset;
+}
+
+/* very wierd swapping for same-endian u2's, different-endian u4's */
+
+PRIVATE u4_pt c4u4_0s(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[2];
+ ((char *) &offset)[1] = buf[3];
+ ((char *) &offset)[2] = buf[0];
+ ((char *) &offset)[3] = buf[1];
+ return offset;
+}
+
+/* === entry points === */
+
+PUBLIC u2_pt c2u2(buf)
+char *buf;
+{
+ return (*pc2u2) (buf);
+}
+
+PUBLIC u4_t c4u4(buf)
+char *buf;
+{
+ return (*pc4u4) (buf);
+}
+
+PUBLIC u2_pt cnu2(buf, count)
+char *buf;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ return buf[0] & 0xFF;
+ case 2:
+ return (*pc2u2) (buf);
+ case 4:
+ return (u2_pt) (*pc4u4) (buf);
+ default:
+ return 0;
+ }
+}
+
+PUBLIC u4_t cnu4(buf, count)
+char *buf;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ return buf[0] & 0xFF;
+ case 2:
+ return (*pc2u2) (buf);
+ case 4:
+ return (*pc4u4) (buf);
+ default:
+ return 0;
+ }
+}
+
+/* === unsigneds to char arrays === */
+
+/* no bytes swapped, longwinded to avoid alignment problems */
+
+PRIVATE void u2c2_00(buf, offset)
+register char *buf;
+u2_pt offset;
+{
+
+ buf[0] = ((char *) &offset)[0];
+ buf[1] = ((char *) &offset)[1];
+}
+
+PRIVATE void u4c4_00(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[0];
+ buf[1] = ((char *) &offset)[1];
+ buf[2] = ((char *) &offset)[2];
+ buf[3] = ((char *) &offset)[3];
+}
+
+/* straight swapping for little-endian to big-endian and vice versa */
+
+PRIVATE void u2c2_ss(buf, offset)
+register char *buf;
+u2_pt offset;
+{
+ u2_t offset2;
+
+ offset2 = offset;
+ buf[0] = ((char *) &offset2)[1];
+ buf[1] = ((char *) &offset2)[0];
+}
+
+PRIVATE void u4c4_ss(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[3];
+ buf[1] = ((char *) &offset)[2];
+ buf[2] = ((char *) &offset)[1];
+ buf[3] = ((char *) &offset)[0];
+}
+
+/* wierd swapping for different-endian u2's, same-endian u4's */
+
+PRIVATE void u4c4_s0(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[1];
+ buf[1] = ((char *) &offset)[0];
+ buf[2] = ((char *) &offset)[3];
+ buf[3] = ((char *) &offset)[2];
+}
+
+/* very wierd swapping for same-endian u2's, different-endian u4's */
+
+PRIVATE void u4c4_0s(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[2];
+ buf[1] = ((char *) &offset)[3];
+ buf[2] = ((char *) &offset)[0];
+ buf[3] = ((char *) &offset)[1];
+}
+
+/* === entry points === */
+
+PUBLIC void u2c2(buf, offset)
+register char *buf;
+u2_pt offset;
+{
+ (*pu2c2) (buf, offset);
+}
+
+PUBLIC void u4c4(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ (*pu4c4) (buf, offset);
+}
+
+PUBLIC void u2cn(buf, offset, count)
+register char *buf;
+u2_pt offset;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ buf[0] = (char) offset;
+ return;
+ case 2:
+ (*pu2c2) (buf, offset);
+ return;
+ case 4:
+ (*pu4c4) (buf, (u4_t) offset);
+ return;
+ }
+}
+
+PUBLIC void u4cn(buf, offset, count)
+register char *buf;
+u4_t offset;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ buf[0] = (char) offset;
+ return;
+ case 2:
+ (*pu2c2) (buf, (u2_pt) (u2_t) offset);
+ return;
+ case 4:
+ (*pu4c4) (buf, offset);
+ return;
+ }
+}
+
+/* initialise type conversion, return FALSE if it cannot be handled */
+
+PUBLIC bool_pt typeconv_init(big_endian, long_big_endian)
+bool_pt big_endian;
+bool_pt long_big_endian;
+{
+ u2_pt conv2;
+ u4_pt conv4;
+ char *conv2ptr;
+ char *conv4ptr;
+
+ if (sizeof(u2_t) != 2 || sizeof(u4_t) != 4)
+ /* dumb preprocessor's don't accept sizeof in #if expressions */
+ return FALSE;
+
+ if (big_endian)
+ {
+ conv2ptr = (conv4ptr = "\1\2\3\4") + 2;
+ if (!long_big_endian)
+ conv4ptr = "\3\4\1\2";
+ }
+ else
+ {
+ conv2ptr = conv4ptr = "\4\3\2\1";
+ if (long_big_endian)
+ conv4ptr = "\2\1\4\3";
+ }
+ conv2 = c2u2_00(conv2ptr);
+ conv4 = c4u4_00(conv4ptr);
+ if (conv2 == 0x0304)
+ {
+ pc2u2 = c2u2_00;
+ pc4u4 = c4u4_00;
+ pu2c2 = u2c2_00;
+ pu4c4 = u4c4_00;
+ if (conv4 == 0x03040102L)
+ {
+ pc4u4 = c4u4_0s;
+ pu4c4 = u4c4_0s;
+ }
+ else if (conv4 != 0x01020304L)
+ return FALSE;
+ }
+ else if (conv2 == 0x0403)
+ {
+ pc2u2 = c2u2_ss;
+ pc4u4 = c4u4_ss;
+ pu2c2 = u2c2_ss;
+ pu4c4 = u4c4_ss;
+ if (conv4 == 0x02010403L)
+ {
+ pc4u4 = c4u4_s0;
+ pu4c4 = u4c4_s0;
+ }
+ else if (conv4 != 0x04030201L)
+ return FALSE;
+ }
+ else
+ return FALSE;
+ return TRUE;
+}
+
+#ifdef DEBUG_TYPECONV
+
+main(int argc,char **argv)
+{
+ char *source;
+ char target[4];
+ u2_t u2;
+ u2_t u2a;
+ u4_t u4;
+ u4_t u4a;
+
+ printf("%u\n", typeconv_init(FALSE, FALSE));
+ printf("%u\n", typeconv_init(FALSE, TRUE));
+ printf("%u\n", typeconv_init(TRUE, FALSE));
+ printf("%u\n", typeconv_init(TRUE, TRUE));
+
+ typeconv_init(FALSE, FALSE);
+ source = "\4\3\2\1";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source, target, 2))
+ printf("oops9\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source, target, 2))
+ printf("oops10\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\4\3\0\0", 4))
+ printf("oops11\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops12\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+
+ typeconv_init(FALSE, TRUE);
+ source = "\2\1\4\3";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source + 2, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops13\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source + 2, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops14\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\0\0\4\3", 4))
+ printf("oops15\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops16\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+
+ typeconv_init(TRUE, FALSE);
+ source = "\3\4\1\2";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source, target, 2))
+ printf("oops5\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source, target, 2))
+ printf("oops6\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\3\4\0\0", 4))
+ printf("oops7\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops8\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+
+ typeconv_init(TRUE, TRUE);
+ source = "\1\2\3\4";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source + 2, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops1\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source + 2, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops2\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\0\0\3\4", 4))
+ printf("oops3\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops4\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+}
+
+#endif /* DEBUG_TYPECONV */
diff --git a/bin86-0.3/ld/writebin.c b/bin86-0.3/ld/writebin.c
new file mode 100644
index 0000000..56b329d
--- /dev/null
+++ b/bin86-0.3/ld/writebin.c
@@ -0,0 +1,949 @@
+/*
+ * bin86/ld/writebin.c
+ *
+ * Copyright (C) 1992 Bruce Evans
+ */
+
+extern long text_base_address;
+#define btextoffset text_base_address
+static long bdataoffset;
+#define page_size() 4096
+
+/* writebin.c - write binary file for linker */
+
+#ifdef A_OUT_H
+# include A_OUT_H
+#else
+# ifdef BSD_A_OUT
+# include "bsd-a.out.h"
+# define A_MINHDR 0
+# define C_EXT N_EXT
+# define C_STAT 0
+# define n_was_name n_un.n_name
+# define n_was_numaux n_other
+# define n_was_other n_numaux
+# define n_was_sclass n_type
+# define n_was_strx n_un.n_strx
+# define n_was_type n_desc
+# else /* not BSD_A_OUT */
+# include "a.out.h" /* maybe local copy of <a.out.h> for X-link */
+# define n_was_name n_name
+# define n_was_numaux n_numaux
+# define n_was_other n_other
+# define n_was_sclass n_sclass
+# define n_was_strx n_value
+# define n_was_type n_type
+# endif /* BSD_A_OUT */
+#endif
+
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#undef EXTERN
+#include "globvar.h"
+
+#ifdef EDOS
+# define FILEHEADERLENGTH 0
+#endif
+#ifdef MINIX
+# ifdef BSD_A_OUT
+# define FILEHEADERLENGTH sizeof (struct exec)
+# else
+# define FILEHEADERLENGTH A_MINHDR
+ /* part of header not counted in offsets */
+# endif
+#endif
+#define DPSEG 2
+
+#define CM_MASK 0xC0
+#define MODIFY_MASK 0x3F
+#define S_MASK 0x04
+#define OF_MASK 0x03
+
+#define CM_SPECIAL 0
+#define CM_ABSOLUTE 0x40
+#define CM_OFFSET_RELOC 0x80
+#define CM_SYMBOL_RELOC 0xC0
+
+#define CM_EOT 0
+#define CM_BYTE_SIZE 1
+#define CM_WORD_SIZE 2
+#define CM_LONG_SIZE 3
+#define CM_1_SKIP 17
+#define CM_2_SKIP 18
+#define CM_4_SKIP 19
+#define CM_0_SEG 32
+
+#define ABS_TEXT_MAX 64
+
+#define offsetof(struc, mem) ((int) &((struc *) 0)->mem)
+#define memsizeof(struc, mem) sizeof(((struc *) 0)->mem)
+
+PRIVATE bool_t bits32; /* nonzero for 32-bit executable */
+PRIVATE offset_t combase[NSEG]; /* bases of common parts of segments */
+PRIVATE offset_t comsz[NSEG]; /* sizes of common parts of segments */
+PRIVATE char curseg; /* current segment, 0 to $F */
+PRIVATE offset_t edataoffset; /* end of data */
+PRIVATE offset_t endoffset; /* end of bss */
+PRIVATE offset_t etextoffset; /* end of text */
+PRIVATE offset_t etextpadoff; /* end of padded text */
+#ifdef BSD_A_OUT
+PRIVATE unsigned ndreloc; /* number of data relocations */
+#endif
+PRIVATE unsigned nsym; /* number of symbols written */
+#ifdef BSD_A_OUT
+PRIVATE unsigned ntreloc; /* number of text relocations */
+PRIVATE bool_t reloc_output; /* nonzero to leave reloc info in output */
+#endif
+PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */
+PRIVATE offset_t segadj[NSEG]; /* adjusts (file offset - seg offset) */
+ /* depends on zero init */
+PRIVATE offset_t segbase[NSEG]; /* bases of data parts of segments */
+PRIVATE char segboundary[9] = "__seg0DH";
+ /* name of seg boundary __seg0DL to __segfCH */
+PRIVATE offset_t segpos[NSEG]; /* segment positions for current module */
+PRIVATE offset_t segsz[NSEG]; /* sizes of data parts of segments */
+ /* depends on zero init */
+PRIVATE bool_t sepid; /* nonzero for separate I & D */
+PRIVATE bool_t stripflag; /* nonzero to strip symbols */
+PRIVATE offset_t spos; /* position in current seg */
+PRIVATE bool_t uzp; /* nonzero for unmapped zero page */
+
+#ifdef EDOS
+FORWARD unsigned binheaderlength P((char *commandname));
+FORWARD char *idconvert P((struct entrylist *elptr, char *commandname));
+#endif
+FORWARD void linkmod P((struct modstruct *modptr));
+FORWARD void linkrefs P((struct modstruct *modptr));
+FORWARD void padmod P((struct modstruct *modptr));
+FORWARD void setsym P((char *name, offset_t value));
+FORWARD void symres P((char *name));
+FORWARD void setseg P((unsigned newseg));
+FORWARD void skip P((unsigned countsize));
+#ifdef EDOS
+FORWARD void writeheader P((char *commandname));
+#else
+FORWARD void writeheader P((void));
+#endif
+FORWARD void writenulls P((offset_t count));
+
+/* link all symbols connected to entry symbols */
+
+PUBLIC void linksyms(argreloc_output)
+bool_pt argreloc_output;
+{
+ char needlink;
+ struct entrylist *elptr;
+ struct modstruct *modptr;
+ struct symstruct *symptr;
+
+#ifdef BSD_A_OUT
+ reloc_output = argreloc_output;
+ if (argreloc_output)
+ {
+ if (modfirst->modnext != NULL)
+ fatalerror("relocatable output only works for one input file");
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ modptr->loadflag = TRUE;
+ return;
+ }
+#endif
+ if ((symptr = findsym("_main")) != NULL)
+ entrysym(symptr);
+ do
+ {
+ if ((elptr = entryfirst) == NULL)
+ fatalerror("no start symbol");
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ modptr->loadflag = FALSE;
+ for (; elptr != NULL; elptr = elptr->elnext)
+ linkrefs(elptr->elsymptr->modptr);
+ if ((symptr = findsym("start")) != NULL ||
+ (symptr = findsym("crtso")) != NULL)
+ linkrefs(symptr->modptr);
+ needlink = FALSE;
+ {
+ struct redlist *prlptr;
+ struct redlist *rlptr;
+
+ for (rlptr = redfirst; rlptr != NULL;
+ rlptr = (prlptr = rlptr)->rlnext)
+ if (rlptr->rlmodptr->loadflag &&
+ rlptr->rlmodptr->class > rlptr->rlsymptr->modptr->class)
+ {
+ rlptr->rlsymptr->modptr = rlptr->rlmodptr;
+ rlptr->rlsymptr->value = rlptr->rlvalue;
+ if (rlptr == redfirst)
+ redfirst = rlptr->rlnext;
+ else
+ prlptr->rlnext = rlptr->rlnext;
+ needlink = TRUE;
+ }
+ }
+ }
+ while (needlink);
+}
+
+/* write binary file */
+
+PUBLIC void writebin(outfilename, argsepid, argbits32, argstripflag, arguzp)
+char *outfilename;
+bool_pt argsepid;
+bool_pt argbits32;
+bool_pt argstripflag;
+bool_pt arguzp;
+{
+ char buf4[4];
+#ifdef EDOS
+ char *commandname;
+#endif
+ char *cptr;
+ struct nlist extsym;
+ flags_t flags;
+ struct modstruct *modptr;
+ char seg;
+ unsigned sizecount;
+ offset_t tempoffset;
+ struct symstruct *symptr;
+
+ sepid = argsepid;
+ bits32 = argbits32;
+ stripflag = argstripflag;
+#ifdef BSD_A_OUT
+ uzp = arguzp && !reloc_output;
+#else
+ uzp = arguzp;
+#endif
+ if (uzp)
+ {
+ if (btextoffset == 0)
+ btextoffset = page_size();
+ if (bdataoffset == 0 && sepid)
+ bdataoffset = page_size();
+ }
+#ifdef EDOS
+ commandname = stralloc(outfilename);
+ if ((cptr = strchr(commandname, ':')) != NULL)
+ commandname = cptr + 1;
+ if ((cptr = strrchr(commandname, '.')) != NULL)
+ *cptr = 0;
+#endif
+
+ /* reserve special symbols use curseg to pass parameter to symres() */
+ for (curseg = 0; curseg < NSEG; ++curseg)
+ {
+ segboundary[5] = hexdigit[curseg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ symres(segboundary); /* __segXDH */
+ segboundary[7] = 'L';
+ symres(segboundary); /* __segXDL */
+ segboundary[6] = 'C';
+ symres(segboundary); /* __segXCL */
+ segboundary[7] = 'H';
+ symres(segboundary); /* __segXCH */
+ }
+#ifdef EDOS
+ curseg = 0; /* data seg, s.b. variable */
+#else
+ curseg = 3;
+#endif
+ symres("__edata");
+ symres("__end");
+ curseg = 0; /* text seg, s.b. variable */
+ symres("__etext");
+
+ /* calculate segment and common sizes (sum over loaded modules) */
+ /* use zero init of segsz[] */
+ /* also relocate symbols relative to starts of their segments */
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (!(symptr->flags & (I_MASK | SA_MASK)))
+ {
+ /* relocate by offset of module in segment later */
+ /* relocate by offset of segment in memory special */
+ /* symbols get relocated improperly */
+ symptr->value += segsz[symptr->flags & SEGM_MASK];
+ }
+ else if (symptr->value == 0)
+ {
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ undefined(symptr->name);
+ }
+ else
+ {
+#ifdef BSD_A_OUT
+#if 0
+ if (!reloc_output)
+#else
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+#endif
+ {
+ tempoffset = ld_roundup(symptr->value, 4, offset_t);
+ /* temp kludge quad alignment for 386 */
+ symptr->value = comsz[seg = symptr->flags & SEGM_MASK];
+ comsz[seg] += tempoffset;
+ }
+ if (!(symptr->flags & SA_MASK))
+ symptr->flags |= C_MASK;
+ }
+ }
+ for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ segsz[seg] += cntooffset(cptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+#ifndef EDOS
+
+ /* adjust sizes to even to get quad boundaries */
+ /* this should be specifiable dynamically */
+ segsz[seg] = ld_roundup(segsz[seg], 4, offset_t);
+ comsz[seg] = ld_roundup(comsz[seg], 4, offset_t);
+#endif
+ cptr += sizecount;
+ }
+ }
+
+ /* calculate seg positions now their sizes are known */
+ /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */
+ /* assume seg 0 is text and rest are data */
+#ifdef EDOS
+ if (btextoffset == 0)
+ btextoffset = binheaderlength(commandname);
+#endif
+ segpos[0] = segbase[0] = spos = btextoffset;
+ combase[0] = segbase[0] + segsz[0];
+ segadj[1] = segadj[0] = -btextoffset;
+ etextpadoff = etextoffset = combase[0] + comsz[0];
+ if (sepid)
+ {
+ etextpadoff = ld_roundup(etextoffset, 0x10, offset_t);
+ segadj[1] += etextpadoff - bdataoffset;
+ }
+ else if (bdataoffset == 0)
+ bdataoffset = etextpadoff;
+ segpos[1] = segbase[1] = edataoffset = bdataoffset;
+ combase[1] = segbase[1] + segsz[1];
+ for (seg = 2; seg < NSEG; ++seg)
+ {
+ segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1];
+ if (seg == DPSEG)
+ {
+ /* temporarily have fixed DP seg */
+ /* adjust if nec so it only spans 1 page */
+ tempoffset = segsz[seg] + comsz[seg];
+ if (tempoffset > 0x100)
+ fatalerror("direct page segment too large");
+ if ((((segbase[seg] + tempoffset) ^ segbase[seg]) & ~0xFF) != 0)
+ segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF) & ~0xFF;
+ }
+ combase[seg] = segbase[seg] + segsz[seg];
+ segadj[seg] = segadj[seg - 1];
+ }
+
+ /* relocate symbols by offsets of segments in memory */
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (symptr->flags & (C_MASK | SA_MASK))
+ {
+#ifdef BSD_A_OUT
+#if 0
+ if (!reloc_output)
+#else
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+#endif
+ symptr->value += combase[symptr->flags & SEGM_MASK];
+ }
+ else
+#ifdef BSD_A_OUT
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+ symptr->value += segbase[symptr->flags & SEGM_MASK];
+ }
+ }
+
+ /* adjust special symbols */
+ for (seg = 0; seg < NSEG; ++seg)
+ {
+ if (segsz[seg] != 0)
+ /* only count data of nonzero length */
+ edataoffset = segbase[seg] + segsz[seg];
+ segboundary[5] = hexdigit[seg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]);
+ /* __segXDH */
+ segboundary[7] = 'L';
+ setsym(segboundary, tempoffset); /* __segXDL */
+ segboundary[6] = 'C';
+ setsym(segboundary, tempoffset = combase[seg]);
+ /* __segXCL */
+ segboundary[7] = 'H';
+ setsym(segboundary, tempoffset + comsz[seg]);
+ /* __segXCH */
+ }
+ setsym("__etext", etextoffset);
+ setsym("__edata", edataoffset);
+ setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]);
+
+ openout(outfilename);
+#ifdef BSD_A_OUT
+ if (reloc_output)
+ seektrel(FILEHEADERLENGTH
+ + (long) (etextpadoff - btextoffset)
+ + (long) (edataoffset - bdataoffset));
+#endif
+#ifdef EDOS
+ writeheader(commandname);
+#else
+ writeheader();
+#endif
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ linkmod(modptr);
+ padmod(modptr);
+ }
+
+ /* dump symbol table */
+#ifdef MINIX
+ if (!stripflag)
+ {
+#ifdef BSD_A_OUT
+ unsigned stringoff;
+#endif
+
+ seekout(FILEHEADERLENGTH
+ + (long) (etextpadoff - btextoffset)
+ + (long) (edataoffset - bdataoffset)
+#ifdef BSD_A_OUT
+ + ((long) ndreloc + ntreloc)
+ * (long) sizeof(struct relocation_info)
+#endif
+ );
+ extsym.n_was_numaux = extsym.n_was_type = 0;
+#ifdef BSD_A_OUT
+ stringoff = 4;
+#endif
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr)
+ {
+#ifdef BSD_A_OUT
+ offtocn((char *) &extsym.n_was_strx,
+ (offset_t) stringoff, 4);
+#else
+ strncpy((char *) &extsym.n_was_name, symptr->name,
+ sizeof extsym.n_was_name);
+#endif
+ u4cn((char *) &extsym.n_value, (u4_t) symptr->value,
+ sizeof extsym.n_value);
+ if ((flags = symptr->flags) & A_MASK)
+ extsym.n_was_sclass = N_ABS;
+ else if (flags & (E_MASK | I_MASK))
+ extsym.n_was_sclass = C_EXT;
+ else
+ extsym.n_was_sclass = C_STAT;
+ if (!(flags & I_MASK) ||
+#ifdef BSD_A_OUT
+ !reloc_output &&
+#endif
+ flags & C_MASK)
+ switch (flags & (A_MASK | SEGM_MASK))
+ {
+ case 0:
+ extsym.n_was_sclass |= N_TEXT;
+ case A_MASK:
+ break;
+ default:
+ if (flags & (C_MASK | SA_MASK))
+ extsym.n_was_sclass |= N_BSS;
+ else
+ extsym.n_was_sclass |= N_DATA;
+ break;
+ }
+ writeout((char *) &extsym, sizeof extsym);
+ ++nsym;
+#ifdef BSD_A_OUT
+ stringoff += strlen(symptr->name) + 1;
+#endif
+ }
+ }
+#ifdef BSD_A_OUT
+ offtocn((char *) &extsym.n_was_strx, (offset_t) stringoff, 4);
+ writeout((char *) &extsym.n_was_strx, 4);
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr)
+ writeout(symptr->name, strlen(symptr->name) + 1);
+ }
+#endif
+ seekout((long) offsetof(struct exec, a_syms));
+ u4cn(buf4, (u4_t) nsym * sizeof extsym,
+ memsizeof(struct exec, a_syms));
+ writeout(buf4, memsizeof(struct exec, a_syms));
+#if defined (BSD_A_OUT) && !defined(__linux__)
+ seekout((long) offsetof(struct exec, a_trsize));
+ u4cn(buf4, (u4_t) ntreloc * sizeof(struct relocation_info),
+ memsizeof(struct exec, a_trsize));
+ writeout(buf4, memsizeof(struct exec, a_trsize));
+ seekout((long) offsetof(struct exec, a_drsize));
+ u4cn(buf4, (u4_t) ndreloc * sizeof(struct relocation_info),
+ memsizeof(struct exec, a_drsize));
+ writeout(buf4, memsizeof(struct exec, a_drsize));
+#endif
+ }
+#endif /* MINIX */
+ closeout();
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ executable();
+}
+
+#ifdef EDOS
+
+PRIVATE unsigned binheaderlength(commandname)
+char *commandname;
+{
+ unsigned count;
+ char *name;
+ struct entrylist *elptr;
+ struct symstruct *startptr;
+
+ count = 2 + 2 + 1; /* len len nul */
+ startptr = findsym("start");
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ {
+ name = idconvert(elptr, commandname);
+ count += strlen(name) + 1 + 2 + 1; /* nul off flg */
+ ourfree(name);
+ if (startptr != NULL)
+ count += 6; /* LBSR $xxxx and LBRA $xxxx */
+ }
+ return count;
+}
+
+/* convert name of symbol (entry) list element to a Basic identifier */
+/* new name is built in storage obtained from stralloc() */
+/* the special name _main is converted to the command name first */
+/* copy upper case and numerals, convert lower case to upper, ignore rest */
+
+PRIVATE char *idconvert(elptr, commandname)
+struct entrylist *elptr;
+char *commandname;
+{
+ char *name;
+ char *newname;
+
+ if (strcmp(name = elptr->elsymptr->name, "_main") == 0)
+ name = commandname;
+ newname = stralloc(name);
+ {
+ register char *t;
+ register char *s;
+
+ t = newname;
+ s = name;
+ do
+ {
+ if (*s >= '0' && *s <= '9' || *s >= 'A' && *s <= 'Z')
+ *t++ = *s;
+ if (*s >= 'a' && *s <= 'z')
+ *t++ = *s + ('A' - 'a');
+ }
+ while (*s++);
+ *t = 0;
+ }
+ if (*newname < 'A') /* numeral or null */
+ fatalerror("bad entry name");
+ return newname;
+}
+
+#endif /* EDOS */
+
+PRIVATE void linkmod(modptr)
+struct modstruct *modptr;
+{
+ char buf[ABS_TEXT_MAX];
+ int command;
+ unsigned char modify;
+ offset_t offset;
+ int symbolnum;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+
+ setseg(0);
+ relocsize = 2;
+ symparray = modptr->symparray;
+ openin(modptr->filename); /* does nothing if already open */
+ seekin((long) modptr->textoffset);
+ while (TRUE)
+ {
+ if ((command = readchar()) < 0)
+ prematureeof();
+ modify = command & MODIFY_MASK;
+ switch (command & CM_MASK)
+ {
+ case CM_SPECIAL:
+ switch (modify)
+ {
+ case CM_EOT:
+ segpos[curseg] = spos;
+ return;
+ case CM_BYTE_SIZE:
+ relocsize = 1;
+ break;
+ case CM_WORD_SIZE:
+ relocsize = 2;
+ break;
+ case CM_LONG_SIZE:
+#ifdef LONG_OFFSETS
+ relocsize = 4;
+ break;
+#else
+ fatalerror("relocation by long offsets not implemented");
+#endif
+ case CM_1_SKIP:
+ skip(1);
+ break;
+ case CM_2_SKIP:
+ skip(2);
+ break;
+ case CM_4_SKIP:
+ skip(4);
+ break;
+ default:
+ if ((modify -= CM_0_SEG) >= NSEG)
+ inputerror("bad data in");
+ setseg((unsigned) modify);
+ break;
+ }
+ break;
+ case CM_ABSOLUTE:
+ if (modify == 0)
+ modify = ABS_TEXT_MAX;
+ readin(buf, (unsigned) modify);
+ writeout(buf, (unsigned) modify);
+ spos += (int) modify;
+ break;
+ case CM_OFFSET_RELOC:
+ offset = readsize(relocsize);
+ if (modify & R_MASK)
+ offset -= (spos + relocsize);
+ offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize);
+ writeout(buf, relocsize);
+#ifdef BSD_A_OUT
+ if (reloc_output)
+ {
+ u4_t bitfield;
+
+ if (curseg == 0)
+ {
+ ++ntreloc;
+ offtocn(buf, spos, 4);
+ writetrel(buf, 4);
+ }
+ else
+ {
+ ++ndreloc;
+ offtocn(buf, spos - segbase[1], 4);
+ writedrel(buf, 4);
+ }
+ if ((modify & SEGM_MASK) == 0)
+ bitfield = N_TEXT;
+ else
+ bitfield = N_DATA;
+ if (modify & R_MASK)
+ bitfield |= 1L << 24;
+ if (relocsize == 2)
+ bitfield |= 1L << 25;
+ else if (relocsize == 4)
+ bitfield |= 1L << 26;
+ u4cn(buf, bitfield, 4);
+ if (curseg == 0)
+ writetrel(buf, 4);
+ else
+ writedrel(buf, 4);
+ }
+#endif /* BSD_A_OUT */
+ spos += relocsize;
+ break;
+ case CM_SYMBOL_RELOC:
+ symptr = symparray[symbolnum = readconvsize((unsigned)
+ (modify & S_MASK ? 2 : 1))];
+ offset = readconvsize((unsigned) modify & OF_MASK);
+ if (modify & R_MASK)
+ offset -= (spos + relocsize);
+#ifdef BSD_A_OUT
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+ offset += symptr->value;
+ offtocn(buf, offset, relocsize);
+ writeout(buf, relocsize);
+#ifdef BSD_A_OUT
+ if (reloc_output)
+ {
+ u4_t bitfield;
+
+ if (curseg == 0)
+ {
+ ++ntreloc;
+ offtocn(buf, spos, 4);
+ writetrel(buf, 4);
+ }
+ else
+ {
+ ++ndreloc;
+ offtocn(buf, spos - segbase[1], 4);
+ writedrel(buf, 4);
+ }
+ if (symptr->flags & I_MASK)
+ bitfield = (1L << 27) | symbolnum;
+ else if ((symptr->flags & SEGM_MASK) == 0)
+ bitfield = N_TEXT;
+ else if (symptr->flags & (C_MASK | SA_MASK))
+ bitfield = N_BSS;
+ else
+ bitfield = N_DATA;
+ if (modify & R_MASK)
+ bitfield |= 1L << 24;
+ if (relocsize == 2)
+ bitfield |= 1L << 25;
+ else if (relocsize == 4)
+ bitfield |= 1L << 26;
+ u4cn(buf, bitfield, 4);
+ if (curseg == 0)
+ writetrel(buf, 4);
+ else
+ writedrel(buf, 4);
+ }
+#endif /* BSD_A_OUT */
+ spos += relocsize;
+ }
+ }
+}
+
+PRIVATE void linkrefs(modptr)
+struct modstruct *modptr;
+{
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ modptr->loadflag = TRUE;
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr->loadflag == FALSE)
+ linkrefs(symptr->modptr);
+}
+
+PRIVATE void padmod(modptr)
+struct modstruct *modptr;
+{
+ offset_t count;
+ char seg;
+ offset_t size;
+ unsigned sizecount;
+ char *sizeptr;
+
+ for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ size = cntooffset(sizeptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+ sizeptr += sizecount;
+ if ((count = segpos[seg] - segbase[seg]) != size)
+ size_error(seg, count, size);
+
+ /* pad to quad boundary */
+ /* not padding in-between common areas which sometimes get into file */
+ if ((size = ld_roundup(segpos[seg], 4, offset_t) - segpos[seg]) != 0)
+ {
+ setseg(seg);
+ writenulls(size);
+ segpos[seg] = spos;
+ }
+ segbase[seg] = segpos[seg];
+ }
+}
+
+PRIVATE void setsym(name, value)
+char *name;
+offset_t value;
+{
+ struct symstruct *symptr;
+
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ if ((symptr = findsym(name)) != NULL)
+ symptr->value = value;
+}
+
+PRIVATE void symres(name)
+register char *name;
+{
+ register struct symstruct *symptr;
+
+ if ((symptr = findsym(name)) != NULL)
+ {
+ if ((symptr->flags & SEGM_MASK) == SEGM_MASK)
+ symptr->flags &= ~SEGM_MASK | curseg;
+ if (symptr->flags != (I_MASK | curseg) || symptr->value != 0)
+ reserved(name);
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ symptr->flags = E_MASK | curseg; /* show defined, not common */
+ }
+}
+
+/* set new segment */
+
+PRIVATE void setseg(newseg)
+unsigned newseg;
+{
+ if (newseg != curseg)
+ {
+ segpos[curseg] = spos;
+ spos = segpos[curseg = newseg];
+ seekout(FILEHEADERLENGTH + (long) spos + (long) segadj[curseg]);
+ }
+}
+
+PRIVATE void skip(countsize)
+unsigned countsize;
+{
+ writenulls((offset_t) readsize(countsize));
+}
+
+#ifdef EDOS
+
+PRIVATE void writeheader(commandname)
+char *commandname;
+{
+ char buf[MAX_OFFSET_SIZE];
+ offset_t offset;
+ unsigned headlength;
+ char *name;
+ struct entrylist *elptr;
+ struct symstruct *startptr;
+
+ headlength = binheaderlength(commandname);
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ headlength -= 6;
+ offset = headlength;
+ startptr = findsym("start");
+ offtocn(buf, edataoffset, 2);
+ writeout(buf, 2);
+ writechar(0xFF); /* dummy data length 0xFFFF takes everything */
+ writechar(0xFF);
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ {
+ name = idconvert(elptr, commandname);
+ writeout(name, (unsigned) strlen(name) + 1);
+ ourfree(name);
+ offtocn(buf, startptr == NULL ? elptr->elsymptr->value : offset, 2);
+ writeout(buf, 2);
+ writechar(0x82); /* 8 = set flags from here, 2 = cmd line */
+ offset += 6; /* LBSR $xxxx and LBRA $xxxx */
+ }
+ writechar(0);
+ if (startptr != NULL)
+ {
+ offset = headlength + 3; /* over 1st LBSR */
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ {
+ writechar(0x17); /* LBSR */
+ offtocn(buf, startptr->value - offset, 2);
+ writeout(buf, 2);
+ writechar(0x16); /* LBRA */
+ offtocn(buf, elptr->elsymptr->value - offset - 3, 2);
+ writeout(buf, 2);
+ offset += 6;
+ }
+ }
+}
+
+#endif /* EDOS */
+
+#ifdef MINIX
+
+PRIVATE void writeheader()
+{
+ struct exec header;
+
+ memset(&header, 0, sizeof header);
+ header.a_magic[0] = A_MAGIC0;
+ header.a_magic[1] = A_MAGIC1;
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ {
+ header.a_flags = sepid ? A_SEP : A_EXEC;
+ if (uzp)
+ header.a_flags |= A_UZP;
+ }
+#ifdef BSD_A_OUT
+ header.a_cpu = (bits32 || reloc_output) ? A_I80386 : A_I8086;
+#else
+ header.a_cpu = bits32 ? A_I80386 : A_I8086;
+#endif
+ header.a_hdrlen = FILEHEADERLENGTH;
+ offtocn((char *) &header.a_text, etextpadoff - btextoffset,
+ sizeof header.a_text);
+ offtocn((char *) &header.a_data, edataoffset - bdataoffset,
+ sizeof header.a_data);
+ offtocn((char *) &header.a_bss, endoffset - edataoffset,
+ sizeof header.a_bss);
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ {
+ if (uzp)
+ offtocn((char *) &header.a_entry, page_size(),
+ sizeof header.a_entry);
+ offtocn((char *) &header.a_total, (offset_t)
+ (endoffset < 0x00010000L ? 0x00010000L : endoffset + 0x0008000L),
+ sizeof header.a_total);
+ }
+ writeout((char *) &header, FILEHEADERLENGTH);
+}
+
+#endif /* MINIX */
+
+PRIVATE void writenulls(count)
+offset_t count;
+{
+ spos += count;
+ while (count--)
+ writechar(0);
+}
diff --git a/ld/6809/config.h b/ld/6809/config.h
new file mode 100644
index 0000000..dc5fed4
--- /dev/null
+++ b/ld/6809/config.h
@@ -0,0 +1,28 @@
+/* config.h - configuration for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/* one of these target processors must be defined */
+
+#undef I8086 /* Intel 8086 */
+#undef I80386 /* Intel 80386 */
+#define MC6809 /* Motorola 6809 */
+
+/* one of these target operating systems must be defined */
+
+#define EDOS /* generate EDOS executable */
+#undef MINIX /* generate Minix executable */
+
+/* these may need to be defined to suit the source processor */
+
+#define HOST_8BIT /* enable some 8-bit optimizations */
+
+/* #define S_ALIGNMENT 4 */ /* source memory alignment, power of 2 */
+ /* don't use for 8 bit processors */
+ /* don't use even for 80386 - overhead for */
+ /* alignment cancels improved access */
+
+/* these must be defined to suit the source libraries */
+
+#define CREAT_PERMS 0666 /* permissions for creat() */
+#define EXEC_PERMS 0111 /* extra permissions to set for executable */
diff --git a/ld/Makefile b/ld/Makefile
new file mode 100644
index 0000000..756a25c
--- /dev/null
+++ b/ld/Makefile
@@ -0,0 +1,18 @@
+CFLAGS =-O -DBSD_A_OUT -DSTANDARD_GNU_A_OUT
+LDFLAGS =-N -s
+
+OBJS =dumps.o io.o ld.o readobj.o table.o typeconv.o writebin.o
+
+ld: $(OBJS)
+ $(CC) $(LDFLAGS) $(OBJS) -o $@
+
+clean:
+ rm -f $(OBJS) ld
+
+dumps.o: dumps.c const.h config.h obj.h type.h globvar.h
+io.o: io.c const.h config.h obj.h type.h globvar.h
+ld.o: ld.c const.h config.h byteord.h type.h globvar.h
+readobj.o: readobj.c const.h config.h byteord.h obj.h type.h globvar.h
+table.o: table.c const.h config.h align.h obj.h type.h globvar.h
+typeconv.o: typeconv.c const.h config.h type.h globvar.h
+writebin.o: writebin.c const.h config.h obj.h type.h globvar.h
diff --git a/ld/Makefile.minix b/ld/Makefile.minix
new file mode 100644
index 0000000..7f819fa
--- /dev/null
+++ b/ld/Makefile.minix
@@ -0,0 +1,20 @@
+CFLAGS =-O -DBSD_A_OUT
+LDFLAGS =
+
+OBJS =dumps.o io.o ld.o readobj.o table.o typeconv.o writebin.o
+
+ld: $(OBJS)
+ $(CC) $(LDFLAGS) $(OBJS) -o $@
+ chmem =232000 $@
+
+clean:
+ rm -f $(OBJS) ld
+
+dumps.o: dumps.c const.h config.h obj.h type.h globvar.h
+io.o: io.c const.h config.h obj.h type.h globvar.h
+ld.o: ld.c const.h config.h byteord.h type.h globvar.h
+readobj.o: readobj.c ar.h const.h config.h byteord.h obj.h type.h globvar.h
+table.o: table.c const.h config.h align.h obj.h type.h globvar.h
+typeconv.o: typeconv.c const.h config.h type.h globvar.h
+writebin.o: writebin.c bsd-a.out.h a.out.gnu.h const.h config.h obj.h type.h \
+ globvar.h
diff --git a/ld/README.1994 b/ld/README.1994
new file mode 100644
index 0000000..669c8a8
--- /dev/null
+++ b/ld/README.1994
@@ -0,0 +1,17 @@
+The `bcc' and `ld' parts of the bin86 distribution are now covered by the
+GNU GPL. The next release of the `as' part will be covered by the GPL.
+The `a.out.h' part is no longer used and should be deleted. The `bccfp'
+belongs in another package and may be deleted.
+
+`ld' is now correctly ported to linux. It now defaults to the target
+a.out format for output. However, it still requires its own special
+format for input. It is best used as a post-processor for `as' to
+produce objects in a.out format. Then the target ld can be used to
+link the objects. The post-processing step is:
+
+ ld86 -r -o tmpfile.o file.o && mv tmpfile.o file.o
+
+This can be handled more simply by using the `bcc' compiler driver as
+the assembler and never calling as86 or ld86 directly:
+
+ AS86="bcc -G -0 -c"
diff --git a/ld/align.h b/ld/align.h
new file mode 100644
index 0000000..ba33fb8
--- /dev/null
+++ b/ld/align.h
@@ -0,0 +1,10 @@
+/* align.h - memory alignment requirements for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#ifndef S_ALIGNMENT
+# define align(x)
+#else
+# define align(x) ((x) = ((int) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))
+ /* assumes sizeof(int) == sizeof(char *) */
+#endif
diff --git a/ld/bugs b/ld/bugs
new file mode 100644
index 0000000..b671f30
--- /dev/null
+++ b/ld/bugs
@@ -0,0 +1,17 @@
+1. Should cause error when an address which requires > 16 bits is referenced
+ using 16 bits.
+
+TODO:
+ integrate byteord.h with compiler as well as assembler
+
+TODO:
+ integrate align.h with compiler and assembler
+ use alignment for *86 like compiler - use more portable macro
+ ((x) + (-(int) (x) & MASK)) when it is either necessary or
+ faster
+
+TODO:
+ do malloc stuff better, as in compiler
+
+2. Error message about "foo.a is not an object file" is confusing - should
+ name archive member.
diff --git a/ld/byteord.h b/ld/byteord.h
new file mode 100644
index 0000000..57d17b9
--- /dev/null
+++ b/ld/byteord.h
@@ -0,0 +1,20 @@
+/* byteord.h - byte order dependencies for C compiler, assembler, linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/* These are for the targets of everything and for linker source too. */
+
+#ifdef I8086
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */
+#endif
+
+#ifdef I80386
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0
+#endif
+
+#ifdef MC6809
+# define BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
diff --git a/ld/config.h b/ld/config.h
new file mode 100644
index 0000000..201c153
--- /dev/null
+++ b/ld/config.h
@@ -0,0 +1,28 @@
+/* config.h - configuration for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/* one of these target processors must be defined */
+
+#undef I8086 /* Intel 8086 */
+#define I80386 /* Intel 80386 */
+#undef MC6809 /* Motorola 6809 */
+
+/* one of these target operating systems must be defined */
+
+#undef EDOS /* generate EDOS executable */
+#define MINIX /* generate Minix executable */
+
+/* these may need to be defined to suit the source processor */
+
+#undef HOST_8BIT /* enable some 8-bit optimizations */
+
+/* #define S_ALIGNMENT 4 */ /* source memory alignment, power of 2 */
+ /* don't use for 8 bit processors */
+ /* don't use even for 80386 - overhead for */
+ /* alignment cancels improved access */
+
+/* these must be defined to suit the source libraries */
+
+#define CREAT_PERMS 0666 /* permissions for creat() */
+#define EXEC_PERMS 0111 /* extra permissions to set for executable */
diff --git a/ld/const.h b/ld/const.h
new file mode 100644
index 0000000..7705e15
--- /dev/null
+++ b/ld/const.h
@@ -0,0 +1,14 @@
+/* const.h - constants for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#define FALSE 0
+#define NULL 0
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+
+#include "config.h"
diff --git a/ld/dumps.c b/ld/dumps.c
new file mode 100644
index 0000000..5027fac
--- /dev/null
+++ b/ld/dumps.c
@@ -0,0 +1,68 @@
+/* dumps.c - print data about symbols and modules for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+/* print list of modules and whether they are loaded */
+
+PUBLIC void dumpmods()
+{
+ struct modstruct *modptr;
+
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ {
+ putstr(modptr->loadflag ? "L " : " ");
+ putbstr(20, modptr->modname);
+ putbyte('\n');
+ }
+}
+
+/* print data about symbols (in loaded modules only) */
+
+PUBLIC void dumpsyms()
+{
+ flags_t flags;
+ struct modstruct *modptr;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+ char uflag;
+
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr)
+ {
+ uflag = FALSE;
+ if (((flags = symptr->flags) & (C_MASK | I_MASK)) == I_MASK)
+ uflag = TRUE;
+ putbstr(20, uflag ? "" : modptr->modname);
+ putstr(" ");
+ putbstr(20, symptr->name);
+ putstr(" ");
+ putbyte(hexdigit[flags & SEGM_MASK]);
+ putstr(" ");
+ if (uflag)
+ putstr(" ");
+ else
+#ifdef LONG_OFFSETS
+ put08lx(symptr->value);
+#else
+ put08x(symptr->value);
+#endif
+ putstr(flags & A_MASK ? " A" : " R");
+ if (uflag)
+ putstr(" U");
+ if (flags & C_MASK)
+ putstr(" C");
+ if (flags & N_MASK)
+ putstr(" N");
+ putbyte('\n');
+ }
+ }
+}
diff --git a/ld/globvar.h b/ld/globvar.h
new file mode 100644
index 0000000..0351a6b
--- /dev/null
+++ b/ld/globvar.h
@@ -0,0 +1,14 @@
+/* globvar.h - global variables for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#ifdef EXTERN
+EXTERN char hexdigit[];
+#else
+#define EXTERN
+PUBLIC char hexdigit[] = "0123456789abcdef";
+#endif
+EXTERN unsigned errcount; /* count of errors */
+EXTERN struct entrylist *entryfirst; /* first on list of entry symbols */
+EXTERN struct modstruct *modfirst; /* data for 1st module */
+EXTERN struct redlist *redfirst; /* first on list of redefined symbols */
diff --git a/ld/io.c b/ld/io.c
new file mode 100644
index 0000000..aef49d0
--- /dev/null
+++ b/ld/io.c
@@ -0,0 +1,606 @@
+/* io.c - input/output and error modules for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "const.h"
+#include "obj.h" /* needed for LONG_OFFSETS and offset_t */
+#include "type.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void exit P((int status));
+void *malloc P((unsigned size));
+#else
+#undef NULL
+#include <stdlib.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+#define O_RDONLY 0
+#define O_WRONLY 1
+#define SEEK_SET 0
+#define STDOUT_FILENO 0
+#include <sys/stat.h>
+#define mode_t unsigned short
+#define off_t long
+int chmod P((const char *path, int mode));
+int close P((int fd));
+int creat P((const char *path, int mode));
+int fstat P((int fd, struct stat *statbuf));
+off_t lseek P((int fd, off_t offset, int whence));
+int open P((const char *path, int oflag, ...));
+int read P((int fd, void *buf, unsigned nbytes));
+mode_t umask P((int oldmask));
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#undef NULL
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+#define DRELBUFSIZE 3072
+#define ERR (-1)
+#define ERRBUFSIZE 1024
+#define INBUFSIZE 1024
+#define OUTBUFSIZE 2048
+#define TRELBUFSIZE 1024
+
+#ifdef BSD_A_OUT
+PRIVATE char *drelbuf; /* extra output buffer for data relocations */
+PRIVATE char *drelbufptr; /* data relocation output buffer ptr */
+PRIVATE char *drelbuftop; /* data relocation output buffer top */
+#endif
+PRIVATE char *errbuf; /* error buffer (actually uses STDOUT) */
+PRIVATE char *errbufptr; /* error buffer ptr */
+PRIVATE char *errbuftop; /* error buffer top */
+PRIVATE char *inbuf; /* input buffer */
+PRIVATE char *inbufend; /* input buffer top */
+PRIVATE char *inbufptr; /* end of input in input buffer */
+PRIVATE int infd; /* input file descriptor */
+PRIVATE char *inputname; /* name of current input file */
+PRIVATE char *outbuf; /* output buffer */
+PRIVATE char *outbufptr; /* output buffer ptr */
+PRIVATE char *outbuftop; /* output buffer top */
+PRIVATE int outfd; /* output file descriptor */
+PRIVATE mode_t outputperms; /* permissions of output file */
+PRIVATE char *outputname; /* name of output file */
+PRIVATE char *refname; /* name of program for error reference */
+#ifdef BSD_A_OUT
+PRIVATE char *trelbuf; /* extra output buffer for text relocations */
+PRIVATE char *trelbufptr; /* text relocation output buffer ptr */
+PRIVATE char *trelbuftop; /* text relocation output buffer top */
+PRIVATE int trelfd; /* text relocation output file descriptor */
+#endif
+PRIVATE unsigned warncount; /* count of warnings */
+
+FORWARD void errexit P((char *message));
+FORWARD void flushout P((void));
+#ifdef BSD_A_OUT
+FORWARD void flushtrel P((void));
+#endif
+FORWARD void outhexdigs P((offset_t num));
+FORWARD void outputerror P((char *message));
+FORWARD void put04x P((unsigned num));
+FORWARD void putstrn P((char *message));
+FORWARD void refer P((void));
+
+PUBLIC void ioinit(progname)
+char *progname;
+{
+ infd = ERR;
+ if (*progname)
+ refname = progname; /* name must be static (is argv[0]) */
+ else
+ refname = "link";
+#ifdef BSD_A_OUT
+ drelbuf = malloc(DRELBUFSIZE);
+ drelbuftop = drelbuf + DRELBUFSIZE;
+#endif
+ errbuf = malloc(ERRBUFSIZE);
+ errbufptr = errbuf;
+ errbuftop = errbuf + ERRBUFSIZE;
+ inbuf = malloc(INBUFSIZE);
+ outbuf = malloc(OUTBUFSIZE);/* outbuf invalid if this fails but then */
+ /* will not be used - tableinit() aborts */
+ outbuftop = outbuf + OUTBUFSIZE;
+#ifdef BSD_A_OUT
+ trelbuf = malloc(TRELBUFSIZE);
+ trelbuftop = trelbuf + TRELBUFSIZE;
+#endif
+}
+
+PUBLIC void closein()
+{
+ if (infd != ERR && close(infd) < 0)
+ inputerror("cannot close");
+ infd = ERR;
+}
+
+PUBLIC void closeout()
+{
+#ifdef BSD_A_OUT
+ unsigned nbytes;
+#endif
+
+ flushout();
+#ifdef BSD_A_OUT
+ flushtrel();
+ nbytes = drelbufptr - drelbuf;
+ if (write(trelfd, drelbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+#endif
+ if (close(outfd) == ERR)
+ outputerror("cannot close");
+#ifdef BSD_A_OUT
+ if (close(trelfd) == ERR)
+ outputerror("cannot close");
+#endif
+}
+
+PUBLIC void errtrace(name, level)
+char *name;
+int level;
+{
+ while (level-- > 0)
+ putbyte(' ');
+ putstrn(name);
+}
+
+PUBLIC void executable()
+{
+ mode_t oldmask;
+
+ if (errcount == 0)
+ {
+ oldmask = umask(0);
+ umask(oldmask);
+ chmod(outputname, outputperms | (EXEC_PERMS & ~oldmask));
+ }
+}
+
+PUBLIC void flusherr()
+{
+ write(STDOUT_FILENO, errbuf, (unsigned) (errbufptr - errbuf));
+ errbufptr = errbuf;
+}
+
+PRIVATE void flushout()
+{
+ unsigned nbytes;
+
+ nbytes = outbufptr - outbuf;
+ if (write(outfd, outbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+ outbufptr = outbuf;
+}
+
+#ifdef BSD_A_OUT
+PRIVATE void flushtrel()
+{
+ unsigned nbytes;
+
+ nbytes = trelbufptr - trelbuf;
+ if (write(trelfd, trelbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+ trelbufptr = trelbuf;
+}
+#endif
+
+PUBLIC void openin(filename)
+char *filename;
+{
+#if 0 /* XXX - this probably won't work with constructed lib names? */
+ if (infd == ERR || strcmp(inputname, filename) != 0)
+#endif
+ {
+ closein();
+ inputname = filename; /* this relies on filename being static */
+ if ((infd = open(filename, O_RDONLY)) < 0)
+ inputerror("cannot open");
+ inbufptr = inbufend = inbuf;
+ }
+}
+
+PUBLIC void openout(filename)
+char *filename;
+{
+ struct stat statbuf;
+
+ outputname = filename;
+ if ((outfd = creat(filename, CREAT_PERMS)) == ERR)
+ outputerror("cannot open");
+ if (fstat(outfd, &statbuf) != 0)
+ outputerror("cannot stat");
+ outputperms = statbuf.st_mode;
+ chmod(filename, outputperms & ~EXEC_PERMS);
+#ifdef BSD_A_OUT
+ drelbufptr = drelbuf;
+#endif
+ outbufptr = outbuf;
+#ifdef BSD_A_OUT
+ if ((trelfd = open(filename, O_WRONLY)) == ERR)
+ outputerror("cannot reopen");
+ trelbufptr = trelbuf;
+#endif
+}
+
+PRIVATE void outhexdigs(num)
+register offset_t num;
+{
+ if (num >= 0x10)
+ {
+ outhexdigs(num / 0x10);
+ num %= 0x10;
+ }
+ putbyte(hexdigit[num]);
+}
+
+PRIVATE void put04x(num)
+register unsigned num;
+{
+ putbyte(hexdigit[num / 0x1000]);
+ putbyte(hexdigit[(num / 0x100) & 0x0F]);
+ putbyte(hexdigit[(num / 0x10) & 0x0F]);
+ putbyte(hexdigit[num & 0x0F]);
+}
+
+#ifdef LONG_OFFSETS
+
+PUBLIC void put08lx(num)
+register offset_t num;
+{
+ put04x(num / 0x10000);
+ put04x(num % 0x10000);
+}
+
+#else /* not LONG_OFFSETS */
+
+PUBLIC void put08x(num)
+register offset_t num;
+{
+ putstr("0000");
+ put04x(num);
+}
+
+#endif /* not LONG_OFFSETS */
+
+PUBLIC void putbstr(width, str)
+unsigned width;
+char *str;
+{
+ unsigned length;
+
+ for (length = strlen(str); length < width; ++length)
+ putbyte(' ');
+ putstr(str);
+}
+
+PUBLIC void putbyte(ch)
+int ch;
+{
+ register char *ebuf;
+
+ ebuf = errbufptr;
+ if (ebuf >= errbuftop)
+ {
+ flusherr();
+ ebuf = errbufptr;
+ }
+ *ebuf++ = ch;
+ errbufptr = ebuf;
+}
+
+PUBLIC void putstr(message)
+char *message;
+{
+ while (*message != 0)
+ putbyte(*message++);
+}
+
+PRIVATE void putstrn(message)
+char *message;
+{
+ putstr(message);
+ putbyte('\n');
+ flusherr();
+}
+
+PUBLIC int readchar()
+{
+ int ch;
+
+ register char *ibuf;
+ int nread;
+
+ ibuf = inbufptr;
+ if (ibuf >= inbufend)
+ {
+ ibuf = inbufptr = inbuf;
+ nread = read(infd, ibuf, INBUFSIZE);
+ if (nread <= 0)
+ {
+ inbufend = ibuf;
+ return ERR;
+ }
+ inbufend = ibuf + nread;
+ }
+ ch = (unsigned char) *ibuf++;
+ inbufptr = ibuf;
+ return ch;
+}
+
+PUBLIC void readin(buf, count)
+char *buf;
+unsigned count;
+{
+ int ch;
+
+ while (count--)
+ {
+ if ((ch = readchar()) < 0)
+ prematureeof();
+ *buf++ = ch;
+ }
+}
+
+PUBLIC bool_pt readineofok(buf, count)
+char *buf;
+unsigned count;
+{
+ int ch;
+
+ while (count--)
+ {
+ if ((ch = readchar()) < 0)
+ return TRUE;
+ *buf++ = ch;
+ }
+ return FALSE;
+}
+
+PUBLIC void seekin(offset)
+unsigned long offset;
+{
+ inbufptr = inbufend = inbuf;
+ if (lseek(infd, (off_t) offset, SEEK_SET) != offset)
+ prematureeof();
+}
+
+PUBLIC void seekout(offset)
+unsigned long offset;
+{
+ flushout();
+ if (lseek(outfd, (off_t) offset, SEEK_SET) != offset)
+ outputerror("cannot seek in");
+}
+
+#ifdef BSD_A_OUT
+PUBLIC void seektrel(offset)
+unsigned long offset;
+{
+ flushtrel();
+ if (lseek(trelfd, (off_t) offset, SEEK_SET) != offset)
+ outputerror("cannot seek in");
+}
+#endif
+
+PUBLIC void writechar(ch)
+int ch;
+{
+ register char *obuf;
+
+ obuf = outbufptr;
+ if (obuf >= outbuftop)
+ {
+ flushout();
+ obuf = outbufptr;
+ }
+ *obuf++ = ch;
+ outbufptr = obuf;
+}
+
+#ifdef BSD_A_OUT
+PUBLIC void writedrel(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *rbuf;
+
+ rbuf = drelbufptr;
+ while (count--)
+ {
+ if (rbuf >= drelbuftop)
+ inputerror("data relocation buffer full while processing");
+ *rbuf++ = *buf++;
+ }
+ drelbufptr = rbuf;
+}
+#endif
+
+PUBLIC void writeout(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *obuf;
+
+ obuf = outbufptr;
+ while (count--)
+ {
+ if (obuf >= outbuftop)
+ {
+ outbufptr = obuf;
+ flushout();
+ obuf = outbufptr;
+ }
+ *obuf++ = *buf++;
+ }
+ outbufptr = obuf;
+}
+
+#ifdef BSD_A_OUT
+PUBLIC void writetrel(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *rbuf;
+
+ rbuf = trelbufptr;
+ while (count--)
+ {
+ if (rbuf >= trelbuftop)
+ {
+ trelbufptr = rbuf;
+ flushtrel();
+ rbuf = trelbufptr;
+ }
+ *rbuf++ = *buf++;
+ }
+ trelbufptr = rbuf;
+}
+#endif
+
+/* error module */
+
+PRIVATE void errexit(message)
+char *message;
+{
+ putstrn(message);
+ exit(2);
+}
+
+PUBLIC void fatalerror(message)
+char *message;
+{
+ refer();
+ errexit(message);
+}
+
+PUBLIC void inputerror(message)
+char *message;
+{
+ refer();
+ putstr(message);
+ putstr(" input file ");
+ errexit(inputname);
+}
+
+PUBLIC void input1error(message)
+char *message;
+{
+ refer();
+ putstr(inputname);
+ errexit(message);
+}
+
+PRIVATE void outputerror(message)
+char *message;
+{
+ refer();
+ putstr(message);
+ putstr(" output file ");
+ errexit(outputname);
+}
+
+PUBLIC void outofmemory()
+{
+ inputerror("out of memory while processing");
+}
+
+PUBLIC void prematureeof()
+{
+ inputerror("premature end of");
+}
+
+PUBLIC void redefined(name, message, archentry, deffilename, defarchentry)
+char *name;
+char *message;
+char *archentry;
+char *deffilename;
+char *defarchentry;
+{
+ ++warncount;
+ refer();
+ putstr("warning: ");
+ putstr(name);
+ putstr(" redefined");
+ putstr(message);
+ putstr(" in file ");
+ putstr(inputname);
+ if (archentry != NULL)
+ {
+ putbyte('(');
+ putstr(archentry);
+ putbyte(')');
+ }
+ putstr("; using definition in ");
+ putstr(deffilename);
+ if (defarchentry != NULL)
+ {
+ putbyte('(');
+ putstr(defarchentry);
+ putbyte(')');
+ }
+ putbyte('\n');
+}
+
+PRIVATE void refer()
+{
+ putstr(refname);
+ putstr(": ");
+}
+
+PUBLIC void reserved(name)
+char *name;
+{
+ ++errcount;
+ putstr("incorrect use of reserved symbol: ");
+ putstrn(name);
+}
+
+PUBLIC void size_error(seg, count, size)
+char seg;
+offset_t count;
+offset_t size;
+{
+ refer();
+ putstr("seg ");
+ outhexdigs((offset_t) seg);
+ putstr(" has wrong size ");
+ outhexdigs(count);
+ putstr(", supposed to be ");
+ outhexdigs(size);
+ errexit("\n");
+}
+
+PUBLIC void undefined(name)
+char *name;
+{
+ ++errcount;
+ putstr("undefined symbol: ");
+ putstrn(name);
+}
+
+PUBLIC void usage()
+{
+ putstr("usage: ");
+ putstr(refname);
+#ifdef BSD_A_OUT
+ errexit("\
+ [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-Llibdir] [-Olibfile] [-T textaddr] infile...");
+#else
+ errexit("\
+ [-03Mimstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-Llibdir] [-Olibfile] [-T textaddr] infile...");
+#endif
+}
+
+PUBLIC void use_error(message)
+char *message;
+{
+ refer();
+ putstrn(message);
+ usage();
+}
diff --git a/ld/ld.c b/ld/ld.c
new file mode 100644
index 0000000..c19b98d
--- /dev/null
+++ b/ld/ld.c
@@ -0,0 +1,187 @@
+/* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "const.h"
+#include "byteord.h"
+#include "type.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+extern int errno;
+char *strcat P((char *dest, const char *src));
+unsigned long strtoul P((const char *s, char **endptr, int base));
+#else
+#undef NULL
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+#define R_OK 0
+int access P((const char *path, int amode));
+#else
+#undef NULL
+#include <unistd.h>
+#endif
+
+#define MAX_LIBS (NR_STDLIBS + 5)
+#define NR_STDLIBS 1
+
+PUBLIC long text_base_address; /* XXX */
+
+PRIVATE bool_t flag[128];
+PRIVATE char *libs[MAX_LIBS] = {
+#ifdef MC6809
+ "/usr/local/lib/m09/",
+#else
+ /* One of the following values will be inserted at run time. */
+# define std386lib "/usr/local/lib/i386/"
+# define std86lib "/usr/local/lib/i86/"
+#endif
+ 0
+};
+PRIVATE int lastlib = NR_STDLIBS;
+
+FORWARD char *buildname P((char *pre, char *mid, char *suf));
+FORWARD char *expandlib P((char *fn));
+
+PRIVATE char *buildname(pre, mid, suf)
+char *pre;
+char *mid;
+char *suf;
+{
+ char *name;
+
+ name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1);
+ strcpy(name, pre);
+ strcat(name, mid);
+ strcat(name, suf);
+ return name;
+}
+
+PRIVATE char *expandlib(fn)
+char *fn;
+{
+ char *path;
+ int i;
+
+#ifndef MC6809
+ libs[0] = flag['3'] ? std386lib : std86lib;
+#endif
+
+ for (i = lastlib - 1; i >= 0; --i)
+ {
+ path = ourmalloc(strlen(libs[i]) + strlen(fn) + 1);
+ strcpy(path, libs[i]);
+ strcat(path, fn);
+ if (access(path, R_OK) == 0)
+ return path;
+ ourfree(path);
+ }
+ return NULL;
+}
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ register char *arg;
+ int argn;
+ static char crtprefix[] = "crt";
+ static char crtsuffix[] = ".o";
+ char *infilename;
+ static char libprefix[] = "lib";
+ static char libsuffix[] = ".a";
+ char *outfilename;
+ char *tfn;
+
+ ioinit(argv[0]);
+ objinit();
+ syminit();
+ typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN);
+#ifndef MC6809
+ flag['z'] = flag['3'] = sizeof(char *) >= 4;
+#endif
+ outfilename = NULL;
+ for (argn = 1; argn < argc; ++argn)
+ {
+ arg = argv[argn];
+ if (*arg != '-')
+ readsyms(arg, flag['t']);
+ else
+ switch (arg[1])
+ {
+ case '0': /* use 16-bit libraries */
+ case '3': /* use 32-bit libraries */
+ case 'M': /* print symbols linked */
+ case 'i': /* separate I & D output */
+ case 'm': /* print modules linked */
+#ifdef BSD_A_OUT
+ case 'r': /* relocatable output */
+#endif
+ case 's': /* strip symbols */
+ case 't': /* trace modules linked */
+ case 'z': /* unmapped zero page */
+ if (arg[2] == 0)
+ flag[(int) arg[1]] = TRUE;
+ else if (arg[2] == '-' && arg[3] == 0)
+ flag[(int) arg[1]] = FALSE;
+ else
+ usage();
+ if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
+ flag['3'] = !flag['0'];
+ break;
+ case 'C': /* startfile name */
+ tfn = buildname(crtprefix, arg + 2, crtsuffix);
+ if ((infilename = expandlib(tfn)) == NULL)
+ fatalerror(tfn); /* XXX - need to describe failure */
+ readsyms(infilename, flag['t']);
+ break;
+ case 'L': /* library path */
+ if (lastlib < MAX_LIBS)
+ libs[lastlib++] = arg + 2;
+ else
+ fatalerror("too many library paths");
+ break;
+ case 'O': /* library file name */
+ if ((infilename = expandlib(arg + 2)) == NULL)
+ fatalerror(arg); /* XXX */
+ readsyms(infilename, flag['t']);
+ break;
+ case 'T': /* text base address */
+ if (arg[2] != 0 || ++argn >= argc)
+ usage();
+ errno = 0;
+ text_base_address = strtoul(argv[argn], (char **) NULL, 16);
+ if (errno != 0)
+ use_error("invalid text address");
+ break;
+ case 'l': /* library name */
+ tfn = buildname(libprefix, arg + 2, libsuffix);
+ if ((infilename = expandlib(tfn)) == NULL)
+ fatalerror(tfn); /* XXX */
+ readsyms(infilename, flag['t']);
+ break;
+ case 'o': /* output file name */
+ if (arg[2] != 0 || ++argn >= argc || outfilename != NULL)
+ usage();
+ outfilename = argv[argn];
+ break;
+ default:
+ usage();
+ }
+ }
+ linksyms(flag['r']);
+ if (outfilename == NULL)
+ outfilename = "a.out";
+ writebin(outfilename, flag['i'], flag['3'], flag['s'],
+ flag['z'] & flag['3']);
+ if (flag['m'])
+ dumpmods();
+ if (flag['M'])
+ dumpsyms();
+ flusherr();
+ return errcount ? 1 : 0;
+}
diff --git a/ld/obj.h b/ld/obj.h
new file mode 100644
index 0000000..e0a52dc
--- /dev/null
+++ b/ld/obj.h
@@ -0,0 +1,54 @@
+/* obj.h - constants for Introl object modules */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#define OBJ_H
+
+#ifdef I80386
+# define LONG_OFFSETS /* others can use this, but wasteful */
+#endif
+
+#ifndef OMAGIC
+# ifdef I80386
+# define OMAGIC 0x86A3
+# endif
+
+# ifdef I8086
+# define OMAGIC 0x86A0
+# endif
+
+# ifdef MC6809
+# define OMAGIC 0x5331
+# endif
+#endif
+
+#ifdef LONG_OFFSETS
+# define cntooffset cnu4
+# define offtocn u4cn
+#else
+# define cntooffset cnu2
+# define offtocn u2cn
+#endif
+
+#ifdef MC6809 /* temp don't support alignment at all */
+# define roundup( num, boundary, type ) (num)
+#else
+# define roundup( num, boundary, type ) \
+ (((num) + ((boundary) - 1)) & (type) ~((boundary) - 1))
+#endif
+
+#define MAX_OFFSET_SIZE 4
+#define NSEG 16
+
+/* flag values |SZ|LXXXX|N|E|I|R|A|SEGM|, X not used */
+
+#define A_MASK 0x0010 /* absolute */
+#define C_MASK 0x0020 /* common (internal only) */
+#define E_MASK 0x0080 /* exported */
+#define I_MASK 0x0040 /* imported */
+#define N_MASK 0x0100 /* entry point */
+#define R_MASK 0x0020 /* relative (in text only) */
+#define SEGM_MASK 0x000F /* segment (if not absolute) */
+#define SA_MASK 0x2000 /* offset is storage allocation */
+#define SZ_MASK 0xC000 /* size descriptor for value */
+#define SZ_SHIFT 14
diff --git a/ld/readobj.c b/ld/readobj.c
new file mode 100644
index 0000000..791436f
--- /dev/null
+++ b/ld/readobj.c
@@ -0,0 +1,374 @@
+/* readobj.c - read object file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "ar.h" /* maybe local copy of <ar.h> for cross-link */
+#include "const.h"
+#include "byteord.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+int strncmp P((const char *s1, const char *s2, unsigned n));
+char *strncpy P((char *dest, const char *src, unsigned n));
+unsigned long strtoul P((const char *s, char **endptr, int base));
+#else
+#undef NULL
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+/*
+ Linking takes 2 passes. The 1st pass reads through all files specified
+in the command line, and all libraries. All public symbols are extracted
+and stored in a chained hash table. For each module, its file and header
+data recorded, and the resulting structures are chained together
+(interleaved with the symbols).
+
+ The symbol descriptors are separated from the symbol names, so we must
+record all the descriptors of a module before putting the symbols in the
+symbol table (poor design). The descriptors are stored in the symbol
+table, then moved to the top of the table to make room for the symols.
+The symbols referred to in a given module are linked together by a chain
+beginning in the module descriptor.
+*/
+
+PRIVATE unsigned convertsize[NSEG / 4] = {0, 1, 2, 4};
+PRIVATE struct entrylist *entrylast; /* last on list of entry symbols */
+PRIVATE struct redlist *redlast; /* last on list of redefined symbols */
+PRIVATE struct modstruct *modlast; /* data for last module */
+
+FORWARD long readarheader P((char **parchentry));
+FORWARD unsigned readfileheader P((void));
+FORWARD void readmodule P((char *filename, char *archentry));
+FORWARD void reedmodheader P((void));
+FORWARD bool_pt redsym P((struct symstruct *symptr, offset_t value));
+FORWARD unsigned checksum P((char *string, unsigned length));
+FORWARD unsigned segbits P((unsigned seg, char *sizedesc));
+
+/* initialise object file handler */
+
+PUBLIC void objinit()
+{
+ modfirst = modlast = NULL;
+ entryfirst = entrylast = NULL;
+ redfirst = redlast = NULL;
+}
+
+/* read all symbol definitions in an object file */
+
+PUBLIC void readsyms(filename, trace)
+char *filename;
+bool_pt trace;
+{
+ char *archentry;
+ long filelength;
+ char filemagic[SARMAG];
+ unsigned long filepos;
+ unsigned modcount;
+
+ if (trace)
+ errtrace(filename, 0);
+ openin(filename); /* input is not open, so position is start */
+ switch ((unsigned) readsize(2))
+ {
+ case OMAGIC:
+ seekin((unsigned long) 0);
+ for (modcount = readfileheader(); modcount-- != 0;)
+ readmodule(filename, (char *) NULL);
+ break;
+ default:
+ seekin((unsigned long) 0);
+ readin(filemagic, sizeof filemagic);
+ if (strncmp(filemagic, ARMAG, sizeof filemagic) != 0)
+ input1error(" has bad magic number");
+ filepos = SARMAG;
+ while ((filelength = readarheader(&archentry)) > 0)
+ {
+ if (trace)
+ errtrace(archentry, 2);
+ filepos += sizeof(struct ar_hdr);
+ for (modcount = readfileheader(); modcount-- != 0;)
+ {
+ readmodule(stralloc(filename), archentry);
+ modlast->textoffset += filepos;
+ }
+ seekin(filepos += roundup(filelength, 2, long));
+ }
+ break;
+ }
+ closein();
+}
+
+/* read archive header and return length */
+
+PRIVATE long readarheader(parchentry)
+char **parchentry;
+{
+ struct ar_hdr arheader;
+ char *endptr;
+ char *nameptr;
+
+ if (readineofok((char *) &arheader, sizeof arheader))
+ return 0;
+ strncpy (*parchentry = nameptr = ourmalloc(sizeof arheader.ar_name + 1),
+ arheader.ar_name, sizeof arheader.ar_name);
+ endptr = nameptr + sizeof arheader.ar_name;
+ do
+ *endptr = 0;
+ while (endptr > nameptr && *--endptr == ' ');
+ return strtoul(arheader.ar_size, (char **) NULL, 0);
+}
+
+/* read and check file header of the object file just opened */
+
+PRIVATE unsigned readfileheader()
+{
+ struct
+ {
+ char magic[2];
+ char count[2]; /* really an int */
+ }
+ fileheader;
+ char filechecksum; /* part of fileheader but would unalign */
+
+ readin((char *) &fileheader, sizeof fileheader);
+ readin(&filechecksum, sizeof filechecksum);
+ if (filechecksum != checksum((char *) &fileheader, sizeof fileheader))
+ input1error(" is not an object file");
+ return c2u2(fileheader.count);
+}
+
+/* read the next module */
+
+PRIVATE void readmodule(filename, archentry)
+char *filename;
+char *archentry;
+{
+ struct symdstruct /* to save parts of symbol before name known */
+ {
+ offset_t dvalue;
+ flags_t dflags;
+ };
+ struct symdstruct *endsymdptr;
+ flags_t flags;
+ unsigned nsymbol;
+ struct symdstruct *symdptr;
+ char *symname;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+
+ reedmodheader();
+ modlast->filename = filename;
+ modlast->archentry = archentry;
+ nsymbol = readsize(2);
+ symdptr = (struct symdstruct *)
+ ourmalloc(nsymbol * sizeof(struct symdstruct));
+ for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; ++symdptr)
+ {
+ readsize(2); /* discard string offset, assume strings seq */
+ symdptr->dflags = flags = readsize(2);
+ symdptr->dvalue = readconvsize((flags & SZ_MASK) >> SZ_SHIFT);
+ /* NB unsigned flags to give logical shift */
+ /* bug in Xenix 2.5 cc causes (int) of the */
+ /* argument to turn flags into an int */
+ }
+ symdptr = (struct symdstruct *)
+ moveup(nsymbol * sizeof(struct symdstruct));
+ modlast->symparray = symparray = (struct symstruct **)
+ ourmalloc((nsymbol + 1) * sizeof(struct symstruct *));
+ symname = readstring(); /* module name */
+ modlast->modname = stralloc(symname); /* likely OK overlapped copy */
+ for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr;
+ *symparray++ = symptr, release((char *) ++symdptr))
+ {
+ symname = readstring();
+ if ((flags = symdptr->dflags) & (E_MASK | I_MASK) &&
+ (symptr = findsym(symname)) != NULL)
+ {
+ /*
+ weaken segment-checking by letting the maximum segment
+ (SEGM_MASK) mean any segment
+ */
+ if ((symptr->flags & SEGM_MASK) == SEGM_MASK)
+ symptr->flags &= ~(flags_t) SEGM_MASK | (flags & SEGM_MASK);
+ else if ((flags & SEGM_MASK) == SEGM_MASK)
+ flags &= ~(flags_t) SEGM_MASK | (symptr->flags & SEGM_MASK);
+ if ((flags ^ symptr->flags) & (N_MASK | A_MASK | SEGM_MASK))
+ {
+ redefined(symname, " with different segment or relocatability",
+ archentry, symptr->modptr->filename,
+ symptr->modptr->archentry);
+ continue;
+ }
+ if (symptr->flags & E_MASK)
+ {
+ if (flags & E_MASK && redsym(symptr, symdptr->dvalue))
+ redefined(symname, "", archentry, symptr->modptr->filename,
+ symptr->modptr->archentry);
+ continue;
+ }
+ if (flags & I_MASK && symdptr->dvalue <= symptr->value)
+ continue;
+ }
+ else
+ symptr = addsym(symname);
+ symptr->modptr = modlast;
+ symptr->value = symdptr->dvalue;
+ symptr->flags = flags;
+ if (flags & N_MASK)
+ entrysym(symptr);
+ }
+ *symparray = NULL;
+}
+
+/* put symbol on entry symbol list if it is not already */
+
+PUBLIC void entrysym(symptr)
+struct symstruct *symptr;
+{
+ register struct entrylist *elptr;
+
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ if (symptr == elptr->elsymptr)
+ return;
+ elptr = (struct entrylist *) ourmalloc(sizeof(struct entrylist));
+ elptr->elnext = NULL;
+ elptr->elsymptr = symptr;
+ if (entryfirst == NULL)
+ entryfirst = elptr;
+ else
+ entrylast->elnext = elptr;
+ entrylast = elptr;
+}
+
+/* read the header of the next module */
+
+PRIVATE void reedmodheader()
+{
+ struct
+ {
+ char htextoffset[4]; /* offset to module text in file */
+ char htextsize[4]; /* size of text (may be 0 for last mod) */
+ char stringssize[2]; /* size of string area */
+ char hclass; /* module class */
+ char revision; /* module revision */
+ }
+ modheader;
+ unsigned seg;
+ unsigned count;
+ char *cptr;
+ struct modstruct *modptr;
+
+ readin((char *) &modheader, sizeof modheader);
+ modptr = (struct modstruct *) ourmalloc(sizeof(struct modstruct));
+ modptr->modnext = NULL;
+ modptr->textoffset = c4u4(modheader.htextoffset);
+ modptr->class = modheader.hclass;
+ readin(modptr->segmaxsize, sizeof modptr->segmaxsize);
+ readin(modptr->segsizedesc, sizeof modptr->segsizedesc);
+ cptr = modptr->segsize;
+ for (seg = 0; seg < NSEG; ++seg)
+ {
+ if ((count = segsizecount(seg, modptr)) != 0)
+ {
+ if (cptr == modptr->segsize)
+ ourmalloc(count - 1); /* 1st byte reserved in struct */
+ else
+ ourmalloc(count);
+ readin(cptr, count);
+ cptr += count;
+ }
+ }
+ if (modfirst == NULL)
+ modfirst = modptr;
+ else
+ modlast->modnext = modptr;
+ modlast = modptr;
+}
+
+PRIVATE bool_pt redsym(symptr, value)
+register struct symstruct *symptr;
+offset_t value;
+{
+ register struct redlist *rlptr;
+ char class;
+
+ if (symptr->modptr->class != (class = modlast->class))
+ for (rlptr = redfirst;; rlptr = rlptr->rlnext)
+ {
+ if (rlptr == NULL)
+ {
+ rlptr = (struct redlist *)
+ ourmalloc(sizeof(struct redlist));
+ rlptr->rlnext = NULL;
+ rlptr->rlsymptr = symptr;
+ if (symptr->modptr->class < class)
+ /* prefer lower class - put other on redlist */
+ {
+ rlptr->rlmodptr = modlast;
+ rlptr->rlvalue = value;
+ }
+ else
+ {
+ rlptr->rlmodptr = symptr->modptr;
+ symptr->modptr = modlast;
+ rlptr->rlvalue = symptr->value;
+ symptr->value = value;
+ }
+ if (redfirst == NULL)
+ redfirst = rlptr;
+ else
+ redlast->rlnext = rlptr;
+ redlast = rlptr;
+ return FALSE;
+ }
+ if (symptr == rlptr->rlsymptr && class == rlptr->rlmodptr->class)
+ break;
+ }
+ return TRUE;
+}
+
+PRIVATE unsigned checksum(string, length)
+char *string;
+unsigned length;
+{
+ unsigned char sum; /* this is a 1-byte checksum */
+
+ for (sum = 0; length-- != 0;)
+ sum += *string++ & 0xFF;
+ return sum;
+}
+
+PUBLIC offset_t readconvsize(countindex)
+unsigned countindex;
+{
+ return readsize(convertsize[countindex]);
+}
+
+PUBLIC offset_t readsize(count)
+unsigned count;
+{
+ char buf[MAX_OFFSET_SIZE];
+
+ if (count == 0)
+ return 0;
+ readin(buf, count);
+ return cntooffset(buf, count);
+}
+
+PRIVATE unsigned segbits(seg, sizedesc)
+unsigned seg;
+char *sizedesc;
+{
+ return 3 & ((unsigned) sizedesc[((NSEG - 1) - seg) / 4] >> (2 * (seg % 4)));
+ /* unsigned to give logical shift */
+}
+
+PUBLIC unsigned segsizecount(seg, modptr)
+unsigned seg;
+struct modstruct *modptr;
+{
+ return convertsize[segbits(seg, modptr->segsizedesc)];
+}
diff --git a/ld/table.c b/ld/table.c
new file mode 100644
index 0000000..5260741
--- /dev/null
+++ b/ld/table.c
@@ -0,0 +1,205 @@
+/* table.c - table-handler module for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "const.h"
+#include "align.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void *malloc P((unsigned size));
+#else
+#undef NULL
+#include <stdlib.h>
+#endif
+
+#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */
+#define HASHTABSIZE 256
+
+PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* hash table */
+PRIVATE char *tableptr; /* next free spot in catchall table */
+PRIVATE char *tableend; /* ptr to spot after last in table */
+
+FORWARD struct symstruct **gethashptr P((char *name));
+
+/* initialise symbol table */
+
+PUBLIC void syminit()
+{
+ unsigned i;
+
+ for (i = sizeof(int) <= 2 ? 0xE000 : (unsigned) 0x38000;
+ i != 0; i -= 512)
+ if ((tableptr = malloc(i)) != NULL)
+ break;
+ if (tableptr == NULL)
+ outofmemory();
+ tableend = tableptr + i;
+ for (i = 0; i < HASHTABSIZE; i++)
+ hashtab[i] = NULL;
+}
+
+/* add named symbol to end of table - initialise only name and next fields */
+/* caller must not duplicate names of externals for findsym() to work */
+
+PUBLIC struct symstruct *addsym(name)
+char *name;
+{
+ struct symstruct **hashptr;
+ struct symstruct *oldsymptr;
+ struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ {
+ oldsymptr = symptr;
+ symptr = symptr->next;
+ }
+ align(tableptr);
+ symptr = (struct symstruct *) tableptr;
+ if ((tableptr = symptr->name + (strlen(name) + 1)) > tableend)
+ outofmemory();
+ symptr->modptr = NULL;
+ symptr->next = NULL;
+ if (name != symptr->name)
+ strcpy(symptr->name, name); /* should't happen */
+ if (*hashptr == NULL)
+ *hashptr = symptr;
+ else
+ oldsymptr->next = symptr;
+ return symptr;
+}
+
+/* lookup named symbol */
+
+PUBLIC struct symstruct *findsym(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (!(symptr->flags & (E_MASK | I_MASK)) ||
+ strcmp(symptr->name, name) != 0))
+ symptr = symptr->next;
+ return symptr;
+}
+
+/* convert name to a hash table ptr */
+
+PRIVATE struct symstruct **gethashptr(name)
+register char *name;
+{
+ register unsigned hashval;
+
+ hashval = 0;
+ while (*name)
+ hashval = hashval * 2 + *name++;
+ return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1));
+
+/*
+
+#asm
+
+GOLDEN EQU 157
+HASHTABSIZE EQU 256
+
+ CLRB can build value here since HASHTABSIZE <= 256
+ LDA ,X
+ BEQ HASHVAL.EXIT
+HASHVAL.LOOP
+ ADDB ,X+
+ LSLB
+ LDA ,X
+ BNE HASHVAL.LOOP
+ RORB
+ LDA #GOLDEN
+ MUL
+HASHVAL.EXIT
+HASHVAL.EXIT
+ LDX #_hashtab
+ ABX discard A - same as taking mod HASHTABSIZE
+ ABX
+#endasm
+
+*/
+
+}
+
+/* move symbol descriptor entries to top of table (no error checking) */
+
+PUBLIC char *moveup(nbytes)
+unsigned nbytes;
+{
+ register char *source;
+ register char *target;
+
+ source = tableptr;
+ target = tableend;
+ while (nbytes--)
+ *--target = *--source;
+ tableptr = source;
+ return tableend = target;
+}
+
+/* our version of malloc */
+
+PUBLIC char *ourmalloc(nbytes)
+unsigned nbytes;
+{
+ char *allocptr;
+
+ align(tableptr);
+ allocptr = tableptr;
+ if ((tableptr += nbytes) > tableend)
+ outofmemory();
+ return allocptr;
+}
+
+/* our version of free (release from bottom of table) */
+
+PUBLIC void ourfree(cptr)
+char *cptr;
+{
+ tableptr = cptr;
+}
+
+/* read string from file into table at offset suitable for next symbol */
+
+PUBLIC char *readstring()
+{
+ int c;
+ char *s;
+ char *start;
+
+ align(tableptr);
+ start = s = ((struct symstruct *) tableptr)->name;
+ while (TRUE)
+ {
+ if (s >= tableend)
+ outofmemory();
+ if ((c = readchar()) < 0)
+ prematureeof();
+ if ((*s++ = c) == 0)
+ return start;
+ }
+ /* NOTREACHED */
+}
+
+/* release from top of table */
+
+PUBLIC void release(cptr)
+char *cptr;
+{
+ tableend = cptr;
+}
+
+/* allocate space for string */
+
+PUBLIC char *stralloc(s)
+char *s;
+{
+ return strcpy(ourmalloc((unsigned) strlen(s) + 1), s);
+}
diff --git a/ld/type.h b/ld/type.h
new file mode 100644
index 0000000..142ea53
--- /dev/null
+++ b/ld/type.h
@@ -0,0 +1,163 @@
+/* type.h - types for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+typedef int bool_pt;
+typedef unsigned char bool_t;
+
+typedef unsigned short u2_t;
+typedef unsigned u2_pt;
+typedef unsigned long u4_t;
+typedef unsigned long u4_pt;
+
+#ifdef HOST_8BIT
+typedef char fastin_t;
+#else
+typedef int fastin_t;
+#endif
+typedef int fastin_pt;
+
+#ifdef OBJ_H /* obj.h is included */
+
+typedef unsigned flags_t; /* unsigned makes shifts logical */
+
+#ifdef LONG_OFFSETS
+typedef unsigned long offset_t;
+#else
+typedef unsigned offset_t;
+#endif
+
+struct entrylist /* list of entry symbols */
+{
+ struct entrylist *elnext; /* next on list */
+ struct symstruct *elsymptr; /* entry on list */
+};
+
+struct modstruct /* module table entry format */
+{
+ char *filename; /* file containing this module */
+ char *archentry; /* name of component file for archives */
+ char *modname; /* name of module */
+ unsigned long textoffset; /* offset to module text in file */
+ char class; /* class of module */
+ char loadflag; /* set if module to be loaded */
+ char segmaxsize[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for seg max size */
+ /* 00 = 1, 01 = 2, 10 = 3, 11 = 4 */
+ char segsizedesc[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for #bytes for size */
+ /* 00 = 0, 01 = 1, 10 = 2, 11 = 4 */
+ struct symstruct **symparray; /* ^array of ptrs to referenced syms */
+ struct modstruct *modnext; /* next module in order of initial reading */
+ char segsize[1]; /* up to 64 size bytes begin here */
+}; /* careful with sizeof( struct modstruct )!! */
+
+struct redlist /* list of redefined (exported) symbols */
+{
+ struct redlist *rlnext; /* next on list */
+ struct symstruct *rlsymptr; /* to symbol with same name, flags */
+ struct modstruct *rlmodptr; /* module for this redefinition */
+ offset_t rlvalue; /* value for this redefinition */
+};
+
+struct symstruct /* symbol table entry format */
+{
+ struct modstruct *modptr; /* module where symbol is defined */
+ offset_t value; /* value of symbol */
+ flags_t flags; /* see below (unsigned makes shifts logical) */
+ struct symstruct *next; /* next symbol with same hash value */
+ char name[1]; /* name is any string beginning here */
+}; /* don't use sizeof( struct symstruct )!! */
+
+#endif /* obj.h is included */
+
+/* prototypes */
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+/* dump.c */
+void dumpmods P((void));
+void dumpsyms P((void));
+
+/* io.c */
+void ioinit P((char *progname));
+void closein P((void));
+void closeout P((void));
+void errtrace P((char *name, int level));
+void executable P((void));
+void flusherr P((void));
+void openin P((char *filename));
+void openout P((char *filename));
+void putstr P((char *message));
+#ifdef OBJ_H
+void put08x P((offset_t num));
+void put08lx P((offset_t num));
+#endif
+void putbstr P((unsigned width, char *str));
+void putbyte P((int ch));
+int readchar P((void));
+void readin P((char *buf, unsigned count));
+bool_pt readineofok P((char *buf, unsigned count));
+void seekin P((unsigned long offset));
+void seekout P((unsigned long offset));
+void seektrel P((unsigned long offset));
+void writechar P((int c));
+void writedrel P((char *buf, unsigned count));
+void writeout P((char *buf, unsigned count));
+void writetrel P((char *buf, unsigned count));
+void fatalerror P((char *message));
+void inputerror P((char *message));
+void input1error P((char *message));
+void outofmemory P((void));
+void prematureeof P((void));
+void redefined P((char *name, char *message, char *archentry,
+ char *deffilename, char *defarchentry));
+void reserved P((char *name));
+#ifdef OBJ_H
+void size_error P((int seg, offset_t count, offset_t size));
+#endif
+void undefined P((char *name));
+void usage P((void));
+void use_error P((char *message));
+
+/* ld.c */
+int main P((int argc, char **argv));
+
+/* readobj.c */
+void objinit P((void));
+void readsyms P((char *filename, bool_pt trace));
+#ifdef OBJ_H
+void entrysym P((struct symstruct *symptr));
+offset_t readconvsize P((unsigned countindex));
+offset_t readsize P((unsigned count));
+unsigned segsizecount P((unsigned seg, struct modstruct *modptr));
+#endif
+
+/* table.c */
+void syminit P((void));
+struct symstruct *addsym P((char *name));
+struct symstruct *findsym P((char *name));
+char *moveup P((unsigned nbytes));
+char *ourmalloc P((unsigned nbytes));
+void ourfree P((char *cptr));
+char *readstring P((void));
+void release P((char *cptr));
+char *stralloc P((char *s));
+
+/* typeconvert.c */
+u2_pt c2u2 P((char *buf));
+u4_t c4u4 P((char *buf));
+u2_pt cnu2 P((char *buf, unsigned count));
+u4_t cnu4 P((char *buf, unsigned count));
+void u2c2 P((char *buf, u2_pt offset));
+void u4c4 P((char *buf, u4_t offset));
+void u2cn P((char *buf, u2_pt offset, unsigned count));
+void u4cn P((char *buf, u4_t offset, unsigned count));
+bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian));
+
+/* writebin.c */
+void writebin P((char *outfilename, bool_pt argsepid, bool_pt argbits32,
+ bool_pt argstripflag, bool_pt arguzp));
+void linksyms P((bool_pt argreloc_output));
diff --git a/ld/typeconv.c b/ld/typeconv.c
new file mode 100644
index 0000000..82dafdd
--- /dev/null
+++ b/ld/typeconv.c
@@ -0,0 +1,536 @@
+/* typeconv.c - convert between char arrays and unsigneds */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/*
+ c2u2(): 2 byte array to 2 byte unsigned
+ c4u4(): 4 byte array to 4 byte unsigned
+ cnu2(): n byte array to 2 byte unsigned
+ cnu4(): n byte array to 4 byte unsigned
+ u2c2(): 2 byte unsigned to 2 byte array
+ u2cn(): 2 byte unsigned to n byte array
+ u4c4(): 4 byte unsigned to 4 byte array
+ u4cn(): 4 byte unsigned to n byte array
+ typeconv_init: (re)initialise for given byte order.
+ Default is no swapping, but the initialisation should be done
+ anyway to provide some validity checks (returns FALSE if error).
+
+ Not provided:
+ c2u4(), c4u2(), u2c4(), u4c2().
+ Each of these is best done by truncating or extending a return value
+ or argument to the appropiate fixed-count function.
+ c4u2() has too many cases to do in-line conveniently, and the others
+ are hardly more efficient when done in-line.
+
+ 4 byte orderings for both char arrays and unsigneds are supported:
+ 0123 - little-endian
+ 3210 - big-endian
+ 2301 - little-endian with long words big-endian (pdp11)
+ 1032 - big-endian with long words little_endian (who knows?)
+
+ The unsigned's byte order is that of the machine on which these
+ routines are running.
+ It is determined at run time initialisation since the compiler/
+ preprocessor is too dumb to tell us at compile time.
+*/
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+
+FORWARD u2_pt c2u2_00 P((char *buf));
+FORWARD u4_pt c4u4_00 P((char *buf));
+FORWARD u2_pt c2u2_ss P((char *buf));
+FORWARD u4_pt c4u4_ss P((char *buf));
+FORWARD u4_pt c4u4_s0 P((char *buf));
+FORWARD u4_pt c4u4_0s P((char *buf));
+FORWARD void u2c2_00 P((char *buf, u2_pt offset));
+FORWARD void u4c4_00 P((char *buf, u4_t offset));
+FORWARD void u2c2_ss P((char *buf, u2_pt offset));
+FORWARD void u4c4_ss P((char *buf, u4_t offset));
+FORWARD void u4c4_s0 P((char *buf, u4_t offset));
+FORWARD void u4c4_0s P((char *buf, u4_t offset));
+
+PRIVATE u2_pt (*pc2u2) P((char *buf)) = c2u2_00;
+PRIVATE u4_pt (*pc4u4) P((char *buf)) = c4u4_00;
+PRIVATE void (*pu2c2) P((char *buf, u2_pt offset)) = u2c2_00;
+PRIVATE void (*pu4c4) P((char *buf, u4_t offset)) = u4c4_00;
+
+/* === char arrays to unsigneds === */
+
+/* no bytes swapped, longwinded to avoid alignment problems */
+
+PRIVATE u2_pt c2u2_00(buf)
+register char *buf;
+{
+ u2_t offset;
+
+ ((char *) &offset)[0] = buf[0];
+ ((char *) &offset)[1] = buf[1];
+ return offset;
+}
+
+PRIVATE u4_pt c4u4_00(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[0];
+ ((char *) &offset)[1] = buf[1];
+ ((char *) &offset)[2] = buf[2];
+ ((char *) &offset)[3] = buf[3];
+ return offset;
+}
+
+/* straight swapping for little-endian to big-endian and vice versa */
+
+PRIVATE u2_pt c2u2_ss(buf)
+register char *buf;
+{
+ u2_t offset;
+
+ ((char *) &offset)[0] = buf[1];
+ ((char *) &offset)[1] = buf[0];
+ return offset;
+}
+
+PRIVATE u4_pt c4u4_ss(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[3];
+ ((char *) &offset)[1] = buf[2];
+ ((char *) &offset)[2] = buf[1];
+ ((char *) &offset)[3] = buf[0];
+ return offset;
+}
+
+/* wierd swapping for different-endian u2's, same-endian u4's */
+
+PRIVATE u4_pt c4u4_s0(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[1];
+ ((char *) &offset)[1] = buf[0];
+ ((char *) &offset)[2] = buf[3];
+ ((char *) &offset)[3] = buf[2];
+ return offset;
+}
+
+/* very wierd swapping for same-endian u2's, different-endian u4's */
+
+PRIVATE u4_pt c4u4_0s(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[2];
+ ((char *) &offset)[1] = buf[3];
+ ((char *) &offset)[2] = buf[0];
+ ((char *) &offset)[3] = buf[1];
+ return offset;
+}
+
+/* === entry points === */
+
+PUBLIC u2_pt c2u2(buf)
+char *buf;
+{
+ return (*pc2u2) (buf);
+}
+
+PUBLIC u4_t c4u4(buf)
+char *buf;
+{
+ return (*pc4u4) (buf);
+}
+
+PUBLIC u2_pt cnu2(buf, count)
+char *buf;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ return buf[0] & 0xFF;
+ case 2:
+ return (*pc2u2) (buf);
+ case 4:
+ return (u2_pt) (*pc4u4) (buf);
+ default:
+ return 0;
+ }
+}
+
+PUBLIC u4_t cnu4(buf, count)
+char *buf;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ return buf[0] & 0xFF;
+ case 2:
+ return (*pc2u2) (buf);
+ case 4:
+ return (*pc4u4) (buf);
+ default:
+ return 0;
+ }
+}
+
+/* === unsigneds to char arrays === */
+
+/* no bytes swapped, longwinded to avoid alignment problems */
+
+PRIVATE void u2c2_00(buf, offset)
+register char *buf;
+u2_pt offset;
+{
+
+ buf[0] = ((char *) &offset)[0];
+ buf[1] = ((char *) &offset)[1];
+}
+
+PRIVATE void u4c4_00(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[0];
+ buf[1] = ((char *) &offset)[1];
+ buf[2] = ((char *) &offset)[2];
+ buf[3] = ((char *) &offset)[3];
+}
+
+/* straight swapping for little-endian to big-endian and vice versa */
+
+PRIVATE void u2c2_ss(buf, offset)
+register char *buf;
+u2_pt offset;
+{
+ u2_t offset2;
+
+ offset2 = offset;
+ buf[0] = ((char *) &offset2)[1];
+ buf[1] = ((char *) &offset2)[0];
+}
+
+PRIVATE void u4c4_ss(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[3];
+ buf[1] = ((char *) &offset)[2];
+ buf[2] = ((char *) &offset)[1];
+ buf[3] = ((char *) &offset)[0];
+}
+
+/* wierd swapping for different-endian u2's, same-endian u4's */
+
+PRIVATE void u4c4_s0(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[1];
+ buf[1] = ((char *) &offset)[0];
+ buf[2] = ((char *) &offset)[3];
+ buf[3] = ((char *) &offset)[2];
+}
+
+/* very wierd swapping for same-endian u2's, different-endian u4's */
+
+PRIVATE void u4c4_0s(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[2];
+ buf[1] = ((char *) &offset)[3];
+ buf[2] = ((char *) &offset)[0];
+ buf[3] = ((char *) &offset)[1];
+}
+
+/* === entry points === */
+
+PUBLIC void u2c2(buf, offset)
+register char *buf;
+u2_pt offset;
+{
+ (*pu2c2) (buf, offset);
+}
+
+PUBLIC void u4c4(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ (*pu4c4) (buf, offset);
+}
+
+PUBLIC void u2cn(buf, offset, count)
+register char *buf;
+u2_pt offset;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ buf[0] = (char) offset;
+ return;
+ case 2:
+ (*pu2c2) (buf, offset);
+ return;
+ case 4:
+ (*pu4c4) (buf, (u4_t) offset);
+ return;
+ }
+}
+
+PUBLIC void u4cn(buf, offset, count)
+register char *buf;
+u4_t offset;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ buf[0] = (char) offset;
+ return;
+ case 2:
+ (*pu2c2) (buf, (u2_pt) (u2_t) offset);
+ return;
+ case 4:
+ (*pu4c4) (buf, offset);
+ return;
+ }
+}
+
+/* initialise type conversion, return FALSE if it cannot be handled */
+
+PUBLIC bool_pt typeconv_init(big_endian, long_big_endian)
+bool_pt big_endian;
+bool_pt long_big_endian;
+{
+ u2_pt conv2;
+ u4_pt conv4;
+ char *conv2ptr;
+ char *conv4ptr;
+
+ if (sizeof(u2_t) != 2 || sizeof(u4_t) != 4)
+ /* dumb preprocessor's don't accept sizeof in #if expressions */
+ return FALSE;
+
+ if (big_endian)
+ {
+ conv2ptr = (conv4ptr = "\1\2\3\4") + 2;
+ if (!long_big_endian)
+ conv4ptr = "\3\4\1\2";
+ }
+ else
+ {
+ conv2ptr = conv4ptr = "\4\3\2\1";
+ if (long_big_endian)
+ conv4ptr = "\2\1\4\3";
+ }
+ conv2 = c2u2_00(conv2ptr);
+ conv4 = c4u4_00(conv4ptr);
+ if (conv2 == 0x0304)
+ {
+ pc2u2 = c2u2_00;
+ pc4u4 = c4u4_00;
+ pu2c2 = u2c2_00;
+ pu4c4 = u4c4_00;
+ if (conv4 == 0x03040102L)
+ {
+ pc4u4 = c4u4_0s;
+ pu4c4 = u4c4_0s;
+ }
+ else if (conv4 != 0x01020304L)
+ return FALSE;
+ }
+ else if (conv2 == 0x0403)
+ {
+ pc2u2 = c2u2_ss;
+ pc4u4 = c4u4_ss;
+ pu2c2 = u2c2_ss;
+ pu4c4 = u4c4_ss;
+ if (conv4 == 0x02010403L)
+ {
+ pc4u4 = c4u4_s0;
+ pu4c4 = u4c4_s0;
+ }
+ else if (conv4 != 0x04030201L)
+ return FALSE;
+ }
+ else
+ return FALSE;
+ return TRUE;
+}
+
+#ifdef DEBUG_TYPECONV
+
+main()
+{
+ char *source;
+ char target[4];
+ u2_t u2;
+ u2_t u2a;
+ u4_t u4;
+ u4_t u4a;
+
+ printf("%u\n", typeconv_init(FALSE, FALSE));
+ printf("%u\n", typeconv_init(FALSE, TRUE));
+ printf("%u\n", typeconv_init(TRUE, FALSE));
+ printf("%u\n", typeconv_init(TRUE, TRUE));
+
+ typeconv_init(FALSE, FALSE);
+ source = "\4\3\2\1";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source, target, 2))
+ printf("oops9\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source, target, 2))
+ printf("oops10\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\4\3\0\0", 4))
+ printf("oops11\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops12\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+
+ typeconv_init(FALSE, TRUE);
+ source = "\2\1\4\3";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source + 2, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops13\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source + 2, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops14\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\0\0\4\3", 4))
+ printf("oops15\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops16\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+
+ typeconv_init(TRUE, FALSE);
+ source = "\3\4\1\2";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source, target, 2))
+ printf("oops5\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source, target, 2))
+ printf("oops6\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\3\4\0\0", 4))
+ printf("oops7\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops8\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+
+ typeconv_init(TRUE, TRUE);
+ source = "\1\2\3\4";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source + 2, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops1\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source + 2, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops2\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\0\0\3\4", 4))
+ printf("oops3\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops4\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+}
+
+#endif /* DEBUG_TYPECONV */
diff --git a/ld/writebin.c b/ld/writebin.c
new file mode 100644
index 0000000..a95280c
--- /dev/null
+++ b/ld/writebin.c
@@ -0,0 +1,989 @@
+extern long text_base_address;
+#define btextoffset text_base_address
+static long bdataoffset;
+#define page_size() 4096
+
+/* writebin.c - write binary file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#ifdef A_OUT_H
+# include A_OUT_H
+#else
+# ifdef BSD_A_OUT
+# ifdef STANDARD_GNU_A_OUT
+# include <a.out.h>
+# define RELOC_INFO_SIZE 8 /* unportable bitfields - bcc doesn't pack */
+# else
+# include "bsd-a.out.h"
+# define RELOC_INFO_SIZE (sizeof (struct relocation_info))
+# endif
+# define C_EXT N_EXT
+# define C_STAT 0
+# define n_was_name n_un.n_name
+# define n_was_numaux n_other
+# define n_was_other n_numaux
+# define n_was_sclass n_type
+# define n_was_strx n_un.n_strx
+# define n_was_type n_desc
+# else /* not BSD_A_OUT */
+# include "a.out.h" /* maybe local copy of <a.out.h> for X-link */
+# define n_was_name n_name
+# define n_was_numaux n_numaux
+# define n_was_other n_other
+# define n_was_sclass n_sclass
+# define n_was_strx n_value
+# define n_was_type n_type
+# endif /* BSD_A_OUT */
+#endif
+
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#undef EXTERN
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void *memset P((void *s, int c, unsigned n));
+#else
+#undef NULL
+#include <string.h>
+#endif
+
+#ifdef EDOS
+# define FILEHEADERLENGTH 0
+#endif
+#ifdef MINIX
+# ifdef BSD_A_OUT
+# ifdef STANDARD_GNU_A_OUT
+# define FILEHEADERLENGTH 32
+# else
+# define FILEHEADERLENGTH 48
+# endif
+# else
+# define FILEHEADERLENGTH A_MINHDR
+ /* part of header not counted in offsets */
+# endif
+#endif
+#define DPSEG 2
+
+#define CM_MASK 0xC0
+#define MODIFY_MASK 0x3F
+#define S_MASK 0x04
+#define OF_MASK 0x03
+
+#define CM_SPECIAL 0
+#define CM_ABSOLUTE 0x40
+#define CM_OFFSET_RELOC 0x80
+#define CM_SYMBOL_RELOC 0xC0
+
+#define CM_EOT 0
+#define CM_BYTE_SIZE 1
+#define CM_WORD_SIZE 2
+#define CM_LONG_SIZE 3
+#define CM_1_SKIP 17
+#define CM_2_SKIP 18
+#define CM_4_SKIP 19
+#define CM_0_SEG 32
+
+#define ABS_TEXT_MAX 64
+
+#define offsetof(struc, mem) ((int) &((struc *) 0)->mem)
+#define memsizeof(struc, mem) sizeof(((struc *) 0)->mem)
+
+PRIVATE bool_t bits32; /* nonzero for 32-bit executable */
+PRIVATE offset_t combase[NSEG]; /* bases of common parts of segments */
+PRIVATE offset_t comsz[NSEG]; /* sizes of common parts of segments */
+PRIVATE fastin_t curseg; /* current segment, 0 to $F */
+PRIVATE offset_t edataoffset; /* end of data */
+PRIVATE offset_t endoffset; /* end of bss */
+PRIVATE offset_t etextoffset; /* end of text */
+PRIVATE offset_t etextpadoff; /* end of padded text */
+#ifdef BSD_A_OUT
+PRIVATE unsigned ndreloc; /* number of data relocations */
+#endif
+PRIVATE unsigned nsym; /* number of symbols written */
+#ifdef BSD_A_OUT
+PRIVATE unsigned ntreloc; /* number of text relocations */
+PRIVATE bool_t reloc_output; /* nonzero to leave reloc info in output */
+#endif
+PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */
+PRIVATE offset_t segadj[NSEG]; /* adjusts (file offset - seg offset) */
+ /* depends on zero init */
+PRIVATE offset_t segbase[NSEG]; /* bases of data parts of segments */
+PRIVATE char segboundary[9] = "__seg0DH";
+ /* name of seg boundary __seg0DL to __segfCH */
+PRIVATE offset_t segpos[NSEG]; /* segment positions for current module */
+PRIVATE offset_t segsz[NSEG]; /* sizes of data parts of segments */
+ /* depends on zero init */
+PRIVATE bool_t sepid; /* nonzero for separate I & D */
+PRIVATE bool_t stripflag; /* nonzero to strip symbols */
+PRIVATE offset_t spos; /* position in current seg */
+PRIVATE bool_t uzp; /* nonzero for unmapped zero page */
+
+#ifdef EDOS
+FORWARD unsigned binheaderlength P((char *commandname));
+FORWARD char *idconvert P((struct entrylist *elptr, char *commandname));
+#endif
+FORWARD void linkmod P((struct modstruct *modptr));
+FORWARD void linkrefs P((struct modstruct *modptr));
+FORWARD void padmod P((struct modstruct *modptr));
+FORWARD void setsym P((char *name, offset_t value));
+FORWARD void symres P((char *name));
+FORWARD void setseg P((fastin_pt newseg));
+FORWARD void skip P((unsigned countsize));
+#ifdef EDOS
+FORWARD void writeheader P((char *commandname));
+#else
+FORWARD void writeheader P((void));
+#endif
+FORWARD void writenulls P((offset_t count));
+
+/* link all symbols connected to entry symbols */
+
+PUBLIC void linksyms(argreloc_output)
+bool_pt argreloc_output;
+{
+ char needlink;
+ struct entrylist *elptr;
+ struct modstruct *modptr;
+ struct symstruct *symptr;
+
+#ifdef BSD_A_OUT
+ reloc_output = argreloc_output;
+ if (argreloc_output)
+ {
+ if (modfirst->modnext != NULL)
+ fatalerror("relocatable output only works for one input file");
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ modptr->loadflag = TRUE;
+ return;
+ }
+#endif
+ if ((symptr = findsym("_main")) != NULL)
+ entrysym(symptr);
+ do
+ {
+ if ((elptr = entryfirst) == NULL)
+ fatalerror("no start symbol");
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ modptr->loadflag = FALSE;
+ for (; elptr != NULL; elptr = elptr->elnext)
+ linkrefs(elptr->elsymptr->modptr);
+ if ((symptr = findsym("start")) != NULL)
+ linkrefs(symptr->modptr);
+ needlink = FALSE;
+ {
+ struct redlist *prlptr;
+ struct redlist *rlptr;
+
+ for (rlptr = redfirst; rlptr != NULL;
+ rlptr = (prlptr = rlptr)->rlnext)
+ if (rlptr->rlmodptr->loadflag &&
+ rlptr->rlmodptr->class > rlptr->rlsymptr->modptr->class)
+ {
+ rlptr->rlsymptr->modptr = rlptr->rlmodptr;
+ rlptr->rlsymptr->value = rlptr->rlvalue;
+ if (rlptr == redfirst)
+ redfirst = rlptr->rlnext;
+ else
+ prlptr->rlnext = rlptr->rlnext;
+ needlink = TRUE;
+ }
+ }
+ }
+ while (needlink);
+}
+
+/* write binary file */
+
+PUBLIC void writebin(outfilename, argsepid, argbits32, argstripflag, arguzp)
+char *outfilename;
+bool_pt argsepid;
+bool_pt argbits32;
+bool_pt argstripflag;
+bool_pt arguzp;
+{
+ char buf4[4];
+#ifdef EDOS
+ char *commandname;
+#endif
+ char *cptr;
+ struct nlist extsym;
+ flags_t flags;
+ struct modstruct *modptr;
+ fastin_t seg;
+ unsigned sizecount;
+ offset_t tempoffset;
+
+ sepid = argsepid;
+ bits32 = argbits32;
+ stripflag = argstripflag;
+#ifdef BSD_A_OUT
+ uzp = arguzp && !reloc_output;
+#else
+ uzp = arguzp;
+#endif
+ if (uzp)
+ {
+ if (btextoffset == 0)
+ btextoffset = page_size();
+ if (bdataoffset == 0 && sepid)
+ bdataoffset = page_size();
+ }
+#ifdef EDOS
+ commandname = stralloc(outfilename);
+ if ((cptr = strchr(commandname, ':')) != NULL)
+ commandname = cptr + 1;
+ if ((cptr = strrchr(commandname, '.')) != NULL)
+ *cptr = 0;
+#endif
+
+ /* reserve special symbols use curseg to pass parameter to symres() */
+ for (curseg = 0; curseg < NSEG; ++curseg)
+ {
+ segboundary[5] = hexdigit[curseg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ symres(segboundary); /* __segXDH */
+ segboundary[7] = 'L';
+ symres(segboundary); /* __segXDL */
+ segboundary[6] = 'C';
+ symres(segboundary); /* __segXCL */
+ segboundary[7] = 'H';
+ symres(segboundary); /* __segXCH */
+ }
+#ifdef EDOS
+ curseg = 0; /* data seg, s.b. variable */
+#else
+ curseg = 3;
+#endif
+ symres("__edata");
+ symres("__end");
+ curseg = 0; /* text seg, s.b. variable */
+ symres("__etext");
+
+ /* calculate segment and common sizes (sum over loaded modules) */
+ /* use zero init of segsz[] */
+ /* also relocate symbols relative to starts of their segments */
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (!(symptr->flags & (I_MASK | SA_MASK)))
+ {
+ /* relocate by offset of module in segment later */
+ /* relocate by offset of segment in memory special */
+ /* symbols get relocated improperly */
+ symptr->value += segsz[symptr->flags & SEGM_MASK];
+ }
+ else if (symptr->value == 0)
+ {
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ undefined(symptr->name);
+ }
+ else
+ {
+#ifdef BSD_A_OUT
+#if 0
+ if (!reloc_output)
+#else
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+#endif
+ {
+ tempoffset = roundup(symptr->value, 4, offset_t);
+ /* temp kludge quad alignment for 386 */
+ symptr->value = comsz[seg = symptr->flags & SEGM_MASK];
+ comsz[seg] += tempoffset;
+ }
+ if (!(symptr->flags & SA_MASK))
+ symptr->flags |= C_MASK;
+ }
+ }
+ for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ segsz[seg] += cntooffset(cptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+#ifndef EDOS
+
+ /* adjust sizes to even to get quad boundaries */
+ /* this should be specifiable dynamically */
+ segsz[seg] = roundup(segsz[seg], 4, offset_t);
+ comsz[seg] = roundup(comsz[seg], 4, offset_t);
+#endif
+ cptr += sizecount;
+ }
+ }
+
+ /* calculate seg positions now their sizes are known */
+ /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */
+ /* assume seg 0 is text and rest are data */
+#ifdef EDOS
+ if (btextoffset == 0)
+ btextoffset = binheaderlength(commandname);
+#endif
+ segpos[0] = segbase[0] = spos = btextoffset;
+ combase[0] = segbase[0] + segsz[0];
+ segadj[1] = segadj[0] = -btextoffset;
+ etextpadoff = etextoffset = combase[0] + comsz[0];
+ if (sepid)
+ {
+ etextpadoff = roundup(etextoffset, 0x10, offset_t);
+ segadj[1] += etextpadoff - bdataoffset;
+ }
+ else if (bdataoffset == 0)
+ bdataoffset = etextpadoff;
+ segpos[1] = segbase[1] = edataoffset = bdataoffset;
+ combase[1] = segbase[1] + segsz[1];
+ for (seg = 2; seg < NSEG; ++seg)
+ {
+ segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1];
+ if (seg == DPSEG)
+ {
+ /* temporarily have fixed DP seg */
+ /* adjust if nec so it only spans 1 page */
+ tempoffset = segsz[seg] + comsz[seg];
+ if (tempoffset > 0x100)
+ fatalerror("direct page segment too large");
+ if ((((segbase[seg] + tempoffset) ^ segbase[seg])
+ & ~(offset_t) 0xFF) != 0)
+ segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF)
+ & ~(offset_t) 0xFF;
+ }
+ combase[seg] = segbase[seg] + segsz[seg];
+ segadj[seg] = segadj[seg - 1];
+ }
+
+ /* relocate symbols by offsets of segments in memory */
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (symptr->flags & (C_MASK | SA_MASK))
+ {
+#ifdef BSD_A_OUT
+#if 0
+ if (!reloc_output)
+#else
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+#endif
+ symptr->value += combase[symptr->flags & SEGM_MASK];
+ }
+ else
+#ifdef BSD_A_OUT
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+ symptr->value += segbase[symptr->flags & SEGM_MASK];
+ }
+ }
+
+ /* adjust special symbols */
+ for (seg = 0; seg < NSEG; ++seg)
+ {
+ if (segsz[seg] != 0)
+ /* only count data of nonzero length */
+ edataoffset = segbase[seg] + segsz[seg];
+ segboundary[5] = hexdigit[seg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]);
+ /* __segXDH */
+ segboundary[7] = 'L';
+ setsym(segboundary, tempoffset); /* __segXDL */
+ segboundary[6] = 'C';
+ setsym(segboundary, tempoffset = combase[seg]);
+ /* __segXCL */
+ segboundary[7] = 'H';
+ setsym(segboundary, tempoffset + comsz[seg]);
+ /* __segXCH */
+ }
+ setsym("__etext", etextoffset);
+ setsym("__edata", edataoffset);
+ setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]);
+
+ openout(outfilename);
+#ifdef BSD_A_OUT
+ if (reloc_output)
+ seektrel(FILEHEADERLENGTH
+ + (unsigned long) (etextpadoff - btextoffset)
+ + (unsigned long) (edataoffset - bdataoffset));
+#endif
+#ifdef EDOS
+ writeheader(commandname);
+#else
+ writeheader();
+#endif
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ linkmod(modptr);
+ padmod(modptr);
+ }
+
+ /* dump symbol table */
+#ifdef MINIX
+ if (!stripflag)
+ {
+#ifdef BSD_A_OUT
+ unsigned stringoff;
+#endif
+
+ seekout(FILEHEADERLENGTH
+ + (unsigned long) (etextpadoff - btextoffset)
+ + (unsigned long) (edataoffset - bdataoffset)
+#ifdef BSD_A_OUT
+ + ((unsigned long) ndreloc + ntreloc) * RELOC_INFO_SIZE
+#endif
+ );
+ extsym.n_was_numaux = extsym.n_was_type = 0;
+#ifdef BSD_A_OUT
+ stringoff = 4;
+#endif
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr)
+ {
+#ifdef BSD_A_OUT
+ offtocn((char *) &extsym.n_was_strx,
+ (offset_t) stringoff, 4);
+#else
+ strncpy((char *) &extsym.n_was_name, symptr->name,
+ sizeof extsym.n_was_name);
+#endif
+ u4cn((char *) &extsym.n_value, (u4_t) symptr->value,
+ sizeof extsym.n_value);
+ if ((flags = symptr->flags) & A_MASK)
+ extsym.n_was_sclass = N_ABS;
+ else if (flags & (E_MASK | I_MASK))
+ extsym.n_was_sclass = C_EXT;
+ else
+ extsym.n_was_sclass = C_STAT;
+ if (!(flags & I_MASK) ||
+#ifdef BSD_A_OUT
+ !reloc_output &&
+#endif
+ flags & C_MASK)
+ switch (flags & (A_MASK | SEGM_MASK))
+ {
+ case 0:
+ extsym.n_was_sclass |= N_TEXT;
+ case A_MASK:
+ break;
+ default:
+ if (flags & (C_MASK | SA_MASK))
+ extsym.n_was_sclass |= N_BSS;
+ else
+ extsym.n_was_sclass |= N_DATA;
+ break;
+ }
+ writeout((char *) &extsym, sizeof extsym);
+ ++nsym;
+#ifdef BSD_A_OUT
+ stringoff += strlen(symptr->name) + 1;
+#endif
+ }
+ }
+#ifdef BSD_A_OUT
+ offtocn((char *) &extsym.n_was_strx, (offset_t) stringoff, 4);
+ writeout((char *) &extsym.n_was_strx, 4);
+ for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr == modptr)
+ writeout(symptr->name, strlen(symptr->name) + 1);
+ }
+#endif
+ seekout((unsigned long) offsetof(struct exec, a_syms));
+ u4cn(buf4, (u4_t) nsym * sizeof extsym,
+ memsizeof(struct exec, a_syms));
+ writeout(buf4, memsizeof(struct exec, a_syms));
+#ifdef BSD_A_OUT
+ seekout((unsigned long) offsetof(struct exec, a_trsize));
+ u4cn(buf4, (u4_t) ntreloc * RELOC_INFO_SIZE,
+ memsizeof(struct exec, a_trsize));
+ writeout(buf4, memsizeof(struct exec, a_trsize));
+ seekout((unsigned long) offsetof(struct exec, a_drsize));
+ u4cn(buf4, (u4_t) ndreloc * RELOC_INFO_SIZE,
+ memsizeof(struct exec, a_drsize));
+ writeout(buf4, memsizeof(struct exec, a_drsize));
+#endif
+ }
+#endif /* MINIX */
+ closeout();
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ executable();
+}
+
+#ifdef EDOS
+
+PRIVATE unsigned binheaderlength(commandname)
+char *commandname;
+{
+ unsigned count;
+ char *name;
+ struct entrylist *elptr;
+ struct symstruct *startptr;
+
+ count = 2 + 2 + 1; /* len len nul */
+ startptr = findsym("start");
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ {
+ name = idconvert(elptr, commandname);
+ count += strlen(name) + 1 + 2 + 1; /* nul off flg */
+ ourfree(name);
+ if (startptr != NULL)
+ count += 6; /* LBSR $xxxx and LBRA $xxxx */
+ }
+ return count;
+}
+
+/* convert name of symbol (entry) list element to a Basic identifier */
+/* new name is built in storage obtained from stralloc() */
+/* the special name _main is converted to the command name first */
+/* copy upper case and numerals, convert lower case to upper, ignore rest */
+
+PRIVATE char *idconvert(elptr, commandname)
+struct entrylist *elptr;
+char *commandname;
+{
+ char *name;
+ char *newname;
+
+ if (strcmp(name = elptr->elsymptr->name, "_main") == 0)
+ name = commandname;
+ newname = stralloc(name);
+ {
+ register char *t;
+ register char *s;
+
+ t = newname;
+ s = name;
+ do
+ {
+ if (*s >= '0' && *s <= '9' || *s >= 'A' && *s <= 'Z')
+ *t++ = *s;
+ if (*s >= 'a' && *s <= 'z')
+ *t++ = *s + ('A' - 'a');
+ }
+ while (*s++);
+ *t = 0;
+ }
+ if (*newname < 'A') /* numeral or null */
+ fatalerror("bad entry name");
+ return newname;
+}
+
+#endif /* EDOS */
+
+PRIVATE void linkmod(modptr)
+struct modstruct *modptr;
+{
+ char buf[ABS_TEXT_MAX];
+ int command;
+ unsigned char modify;
+ offset_t offset;
+ int symbolnum;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+
+ setseg(0);
+ relocsize = 2;
+ symparray = modptr->symparray;
+ openin(modptr->filename); /* does nothing if already open */
+ seekin(modptr->textoffset);
+ while (TRUE)
+ {
+ if ((command = readchar()) < 0)
+ prematureeof();
+ modify = command & MODIFY_MASK;
+ switch (command & CM_MASK)
+ {
+ case CM_SPECIAL:
+ switch (modify)
+ {
+ case CM_EOT:
+ segpos[curseg] = spos;
+ return;
+ case CM_BYTE_SIZE:
+ relocsize = 1;
+ break;
+ case CM_WORD_SIZE:
+ relocsize = 2;
+ break;
+ case CM_LONG_SIZE:
+#ifdef LONG_OFFSETS
+ relocsize = 4;
+ break;
+#else
+ fatalerror("relocation by long offsets not implemented");
+#endif
+ case CM_1_SKIP:
+ skip(1);
+ break;
+ case CM_2_SKIP:
+ skip(2);
+ break;
+ case CM_4_SKIP:
+ skip(4);
+ break;
+ default:
+ if ((modify -= CM_0_SEG) >= NSEG)
+ inputerror("bad data in");
+ setseg(modify);
+ break;
+ }
+ break;
+ case CM_ABSOLUTE:
+ if (modify == 0)
+ modify = ABS_TEXT_MAX;
+ readin(buf, (unsigned) modify);
+ writeout(buf, (unsigned) modify);
+ spos += (int) modify;
+ break;
+ case CM_OFFSET_RELOC:
+ offset = readsize(relocsize);
+ if (modify & R_MASK)
+ offset -= (spos + relocsize);
+ offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize);
+ writeout(buf, relocsize);
+#ifdef BSD_A_OUT
+ if (reloc_output)
+ {
+ u4_t bitfield;
+
+ if (curseg == 0)
+ {
+ ++ntreloc;
+ offtocn(buf, spos, 4);
+ writetrel(buf, 4);
+ }
+ else
+ {
+ ++ndreloc;
+ offtocn(buf, spos - segbase[1], 4);
+ writedrel(buf, 4);
+ }
+ if ((modify & SEGM_MASK) == 0)
+ bitfield = N_TEXT;
+ else
+ bitfield = N_DATA;
+ if (modify & R_MASK)
+ bitfield |= 1L << 24;
+ if (relocsize == 2)
+ bitfield |= 1L << 25;
+ else if (relocsize == 4)
+ bitfield |= 1L << 26;
+ u4cn(buf, bitfield, 4);
+ if (curseg == 0)
+ writetrel(buf, 4);
+ else
+ writedrel(buf, 4);
+ }
+#endif /* BSD_A_OUT */
+ spos += relocsize;
+ break;
+ case CM_SYMBOL_RELOC:
+ symptr = symparray[symbolnum = readconvsize((unsigned)
+ (modify & S_MASK ? 2 : 1))];
+ offset = readconvsize((unsigned) modify & OF_MASK);
+ if (modify & R_MASK)
+ offset -= (spos + relocsize);
+#ifdef BSD_A_OUT
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+ offset += symptr->value;
+ offtocn(buf, offset, relocsize);
+ writeout(buf, relocsize);
+#ifdef BSD_A_OUT
+ if (reloc_output)
+ {
+ u4_t bitfield;
+
+ if (curseg == 0)
+ {
+ ++ntreloc;
+ offtocn(buf, spos, 4);
+ writetrel(buf, 4);
+ }
+ else
+ {
+ ++ndreloc;
+ offtocn(buf, spos - segbase[1], 4);
+ writedrel(buf, 4);
+ }
+ if (symptr->flags & I_MASK)
+ bitfield = (1L << 27) | symbolnum;
+ else if ((symptr->flags & SEGM_MASK) == 0)
+ bitfield = N_TEXT;
+ else if (symptr->flags & (C_MASK | SA_MASK))
+ bitfield = N_BSS;
+ else
+ bitfield = N_DATA;
+ if (modify & R_MASK)
+ bitfield |= 1L << 24;
+ if (relocsize == 2)
+ bitfield |= 1L << 25;
+ else if (relocsize == 4)
+ bitfield |= 1L << 26;
+ u4cn(buf, bitfield, 4);
+ if (curseg == 0)
+ writetrel(buf, 4);
+ else
+ writedrel(buf, 4);
+ }
+#endif /* BSD_A_OUT */
+ spos += relocsize;
+ }
+ }
+}
+
+PRIVATE void linkrefs(modptr)
+struct modstruct *modptr;
+{
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ modptr->loadflag = TRUE;
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NULL; ++symparray)
+ if (symptr->modptr->loadflag == FALSE)
+ linkrefs(symptr->modptr);
+}
+
+PRIVATE void padmod(modptr)
+struct modstruct *modptr;
+{
+ offset_t count;
+ fastin_t seg;
+ offset_t size;
+ unsigned sizecount;
+ char *sizeptr;
+
+ for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ size = cntooffset(sizeptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+ sizeptr += sizecount;
+ if ((count = segpos[seg] - segbase[seg]) != size)
+ size_error(seg, count, size);
+
+ /* pad to quad boundary */
+ /* not padding in-between common areas which sometimes get into file */
+ if ((size = roundup(segpos[seg], 4, offset_t) - segpos[seg]) != 0)
+ {
+ setseg(seg);
+ writenulls(size);
+ segpos[seg] = spos;
+ }
+ segbase[seg] = segpos[seg];
+ }
+}
+
+PRIVATE void setsym(name, value)
+char *name;
+offset_t value;
+{
+ struct symstruct *symptr;
+
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ if ((symptr = findsym(name)) != NULL)
+ symptr->value = value;
+}
+
+PRIVATE void symres(name)
+register char *name;
+{
+ register struct symstruct *symptr;
+
+ if ((symptr = findsym(name)) != NULL)
+ {
+ if ((symptr->flags & SEGM_MASK) == SEGM_MASK)
+ symptr->flags &= ~SEGM_MASK | curseg;
+ if (symptr->flags != (I_MASK | curseg) || symptr->value != 0)
+ reserved(name);
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ symptr->flags = E_MASK | curseg; /* show defined, not common */
+ }
+}
+
+/* set new segment */
+
+PRIVATE void setseg(newseg)
+fastin_pt newseg;
+{
+ if (newseg != curseg)
+ {
+ segpos[curseg] = spos;
+ spos = segpos[curseg = newseg];
+ seekout(FILEHEADERLENGTH + (unsigned long) spos
+ + (unsigned long) segadj[curseg]);
+ }
+}
+
+PRIVATE void skip(countsize)
+unsigned countsize;
+{
+ writenulls((offset_t) readsize(countsize));
+}
+
+#ifdef EDOS
+
+PRIVATE void writeheader(commandname)
+char *commandname;
+{
+ char buf[MAX_OFFSET_SIZE];
+ offset_t offset;
+ unsigned headlength;
+ char *name;
+ struct entrylist *elptr;
+ struct symstruct *startptr;
+
+ headlength = binheaderlength(commandname);
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ headlength -= 6;
+ offset = headlength;
+ startptr = findsym("start");
+ offtocn(buf, edataoffset, 2);
+ writeout(buf, 2);
+ writechar(0xFF); /* dummy data length 0xFFFF takes everything */
+ writechar(0xFF);
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ {
+ name = idconvert(elptr, commandname);
+ writeout(name, (unsigned) strlen(name) + 1);
+ ourfree(name);
+ offtocn(buf, startptr == NULL ? elptr->elsymptr->value : offset, 2);
+ writeout(buf, 2);
+ writechar(0x82); /* 8 = set flags from here, 2 = cmd line */
+ offset += 6; /* LBSR $xxxx and LBRA $xxxx */
+ }
+ writechar(0);
+ if (startptr != NULL)
+ {
+ offset = headlength + 3; /* over 1st LBSR */
+ for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext)
+ {
+ writechar(0x17); /* LBSR */
+ offtocn(buf, startptr->value - offset, 2);
+ writeout(buf, 2);
+ writechar(0x16); /* LBRA */
+ offtocn(buf, elptr->elsymptr->value - offset - 3, 2);
+ writeout(buf, 2);
+ offset += 6;
+ }
+ }
+}
+
+#endif /* EDOS */
+
+#ifdef MINIX
+
+PRIVATE void writeheader()
+{
+ struct exec header;
+
+ memset(&header, 0, sizeof header);
+#ifdef STANDARD_GNU_A_OUT
+#ifdef N_SET_MAGIC
+ N_SET_MAGIC(header, OMAGIC);
+#else
+ *(unsigned short *) &header.a_magic = OMAGIC; /* XXX - works for 386BSD */
+#endif
+#else
+ header.a_magic[0] = A_MAGIC0;
+ header.a_magic[1] = A_MAGIC1;
+#endif
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ {
+#ifdef STANDARD_GNU_A_OUT
+#ifdef N_SET_FLAGS
+ N_SET_FLAGS(header, 0);
+#else
+ /* XXX - works for 386BSD */
+#endif
+#else
+ header.a_flags = sepid ? A_SEP : A_EXEC;
+ if (uzp)
+ header.a_flags |= A_UZP;
+#endif
+ }
+#ifdef BSD_A_OUT
+#ifdef STANDARD_GNU_A_OUT
+#ifdef N_SET_FLAGS
+ N_SET_MACHTYPE(header, M_386);
+#else
+ /* XXX - works for 386BSD which doesn't define its own machtype :-( */
+#endif
+#else
+ header.a_cpu = (bits32 || reloc_output) ? A_I80386 : A_I8086;
+#endif
+#else
+ header.a_cpu = bits32 ? A_I80386 : A_I8086;
+#endif
+#ifndef STANDARD_GNU_A_OUT
+ header.a_hdrlen = FILEHEADERLENGTH;
+#endif
+ offtocn((char *) &header.a_text, etextpadoff - btextoffset,
+ sizeof header.a_text);
+ offtocn((char *) &header.a_data, edataoffset - bdataoffset,
+ sizeof header.a_data);
+ offtocn((char *) &header.a_bss, endoffset - edataoffset,
+ sizeof header.a_bss);
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ {
+ if (uzp)
+ offtocn((char *) &header.a_entry, page_size(),
+ sizeof header.a_entry);
+#ifndef STANDARD_GNU_A_OUT
+ offtocn((char *) &header.a_total, (offset_t)
+ (endoffset < 0x00010000L ? 0x00010000L : endoffset + 0x0008000L),
+ sizeof header.a_total);
+#endif
+ }
+ writeout((char *) &header, FILEHEADERLENGTH);
+}
+
+#endif /* MINIX */
+
+PRIVATE void writenulls(count)
+offset_t count;
+{
+ spos += count;
+ while (count--)
+ writechar(0);
+}