From a7aba15e8efffb1c5d3097656f1a93955a64f01f Mon Sep 17 00:00:00 2001 From: Robert de Bath Date: Sat, 27 Jul 2002 09:23:57 +0200 Subject: Import origs.tar.gz --- as/6809/const.h | 501 +++++++++ as/Makefile | 27 + as/TODO | 1 + as/address.h | 30 + as/as.c | 296 ++++++ as/asm/calljmp.asm | 70 ++ as/asm/ea.asm | 109 ++ as/asm/each.asm | 145 +++ as/asm/easlow.as | 1219 ++++++++++++++++++++++ as/asm/f.asm | 114 ++ as/asm/fadd.asm | 271 +++++ as/asm/farcall.asm | 10 + as/asm/group1.asm | 31 + as/asm/group6.asm | 24 + as/asm/group7.asm | 34 + as/asm/imul.asm | 33 + as/asm/incdec.asm | 83 ++ as/asm/inher.asm | 127 +++ as/asm/inout.asm | 25 + as/asm/movspec.asm | 246 +++++ as/asm/pushpop.asm | 86 ++ as/asm/seg.asm | 6 + as/asm/shdouble.asm | 34 + as/asm/shift.asm | 119 +++ as/asm/summary.as | 385 +++++++ as/asm/xchg.asm | 103 ++ as/assemble.c | 309 ++++++ as/bin/calljmp.bin | Bin 0 -> 146 bytes as/bin/ea.bin | Bin 0 -> 441 bytes as/bin/each.bin | Bin 0 -> 657 bytes as/bin/f.bin | Bin 0 -> 181 bytes as/bin/fadd.bin | Bin 0 -> 605 bytes as/bin/farcall.bin | Bin 0 -> 41 bytes as/bin/group1.bin | Bin 0 -> 115 bytes as/bin/group6.bin | Bin 0 -> 38 bytes as/bin/group7.bin | Bin 0 -> 53 bytes as/bin/imul.bin | Bin 0 -> 119 bytes as/bin/incdec.bin | Bin 0 -> 116 bytes as/bin/inher.bin | Bin 0 -> 129 bytes as/bin/inout.bin | Bin 0 -> 54 bytes as/bin/movspec.bin | Bin 0 -> 682 bytes as/bin/pushpop.bin | Bin 0 -> 128 bytes as/bin/seg.bin | Bin 0 -> 16 bytes as/bin/shdouble.bin | Bin 0 -> 61 bytes as/bin/shift.bin | Bin 0 -> 276 bytes as/bin/xchg.bin | Bin 0 -> 234 bytes as/byteord.h | 18 + as/chk | 9 + as/const.h | 409 ++++++++ as/error.c | 106 ++ as/express.c | 382 +++++++ as/file.h | 12 + as/flag.h | 5 + as/genbin.c | 220 ++++ as/genlist.c | 463 +++++++++ as/genobj.c | 682 ++++++++++++ as/gensym.c | 212 ++++ as/globvar.h | 93 ++ as/macro.c | 175 ++++ as/macro.h | 10 + as/mops.c | 2835 ++++++++++++++++++++++++++++++++++++++++++++++++++ as/obj1/calljmp.obj | Bin 0 -> 200 bytes as/obj1/ea.obj | Bin 0 -> 472 bytes as/obj1/each.obj | Bin 0 -> 715 bytes as/obj1/f.obj | Bin 0 -> 207 bytes as/obj1/fadd.obj | Bin 0 -> 1069 bytes as/obj1/farcall.obj | Bin 0 -> 71 bytes as/obj1/group1.obj | Bin 0 -> 145 bytes as/obj1/group6.obj | Bin 0 -> 67 bytes as/obj1/group7.obj | Bin 0 -> 82 bytes as/obj1/imul.obj | Bin 0 -> 147 bytes as/obj1/incdec.obj | Bin 0 -> 146 bytes as/obj1/inher.obj | Bin 0 -> 158 bytes as/obj1/inout.obj | Bin 0 -> 82 bytes as/obj1/movspec.obj | Bin 0 -> 722 bytes as/obj1/pushpop.obj | Bin 0 -> 159 bytes as/obj1/seg.obj | Bin 0 -> 42 bytes as/obj1/shdouble.obj | Bin 0 -> 106 bytes as/obj1/shift.obj | Bin 0 -> 308 bytes as/obj1/xchg.obj | Bin 0 -> 264 bytes as/opcode.h | 157 +++ as/pops.c | 1048 +++++++++++++++++++ as/proto.h | 218 ++++ as/readsrc.c | 341 ++++++ as/scan.c | 247 +++++ as/scan.h | 12 + as/source.h | 4 + as/table.c | 945 +++++++++++++++++ as/todo | 14 + as/type.h | 167 +++ 90 files changed, 13222 insertions(+) create mode 100644 as/6809/const.h create mode 100644 as/Makefile create mode 100644 as/TODO create mode 100644 as/address.h create mode 100644 as/as.c create mode 100644 as/asm/calljmp.asm create mode 100644 as/asm/ea.asm create mode 100644 as/asm/each.asm create mode 100644 as/asm/easlow.as create mode 100644 as/asm/f.asm create mode 100644 as/asm/fadd.asm create mode 100644 as/asm/farcall.asm create mode 100644 as/asm/group1.asm create mode 100644 as/asm/group6.asm create mode 100644 as/asm/group7.asm create mode 100644 as/asm/imul.asm create mode 100644 as/asm/incdec.asm create mode 100644 as/asm/inher.asm create mode 100644 as/asm/inout.asm create mode 100644 as/asm/movspec.asm create mode 100644 as/asm/pushpop.asm create mode 100644 as/asm/seg.asm create mode 100644 as/asm/shdouble.asm create mode 100644 as/asm/shift.asm create mode 100644 as/asm/summary.as create mode 100644 as/asm/xchg.asm create mode 100644 as/assemble.c create mode 100644 as/bin/calljmp.bin create mode 100644 as/bin/ea.bin create mode 100644 as/bin/each.bin create mode 100644 as/bin/f.bin create mode 100644 as/bin/fadd.bin create mode 100644 as/bin/farcall.bin create mode 100644 as/bin/group1.bin create mode 100644 as/bin/group6.bin create mode 100644 as/bin/group7.bin create mode 100644 as/bin/imul.bin create mode 100644 as/bin/incdec.bin create mode 100644 as/bin/inher.bin create mode 100644 as/bin/inout.bin create mode 100644 as/bin/movspec.bin create mode 100644 as/bin/pushpop.bin create mode 100644 as/bin/seg.bin create mode 100644 as/bin/shdouble.bin create mode 100644 as/bin/shift.bin create mode 100644 as/bin/xchg.bin create mode 100644 as/byteord.h create mode 100755 as/chk create mode 100644 as/const.h create mode 100644 as/error.c create mode 100644 as/express.c create mode 100644 as/file.h create mode 100644 as/flag.h create mode 100644 as/genbin.c create mode 100644 as/genlist.c create mode 100644 as/genobj.c create mode 100644 as/gensym.c create mode 100644 as/globvar.h create mode 100644 as/macro.c create mode 100644 as/macro.h create mode 100644 as/mops.c create mode 100644 as/obj1/calljmp.obj create mode 100644 as/obj1/ea.obj create mode 100644 as/obj1/each.obj create mode 100644 as/obj1/f.obj create mode 100644 as/obj1/fadd.obj create mode 100644 as/obj1/farcall.obj create mode 100644 as/obj1/group1.obj create mode 100644 as/obj1/group6.obj create mode 100644 as/obj1/group7.obj create mode 100644 as/obj1/imul.obj create mode 100644 as/obj1/incdec.obj create mode 100644 as/obj1/inher.obj create mode 100644 as/obj1/inout.obj create mode 100644 as/obj1/movspec.obj create mode 100644 as/obj1/pushpop.obj create mode 100644 as/obj1/seg.obj create mode 100644 as/obj1/shdouble.obj create mode 100644 as/obj1/shift.obj create mode 100644 as/obj1/xchg.obj create mode 100644 as/opcode.h create mode 100644 as/pops.c create mode 100644 as/proto.h create mode 100644 as/readsrc.c create mode 100644 as/scan.c create mode 100644 as/scan.h create mode 100644 as/source.h create mode 100644 as/table.c create mode 100644 as/todo create mode 100644 as/type.h (limited to 'as') 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 +#include +#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 +#include +#include +#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 Binary files /dev/null and b/as/bin/calljmp.bin differ diff --git a/as/bin/ea.bin b/as/bin/ea.bin new file mode 100644 index 0000000..5edc0b0 Binary files /dev/null and b/as/bin/ea.bin differ diff --git a/as/bin/each.bin b/as/bin/each.bin new file mode 100644 index 0000000..211155f Binary files /dev/null and b/as/bin/each.bin differ diff --git a/as/bin/f.bin b/as/bin/f.bin new file mode 100644 index 0000000..ce695a0 Binary files /dev/null and b/as/bin/f.bin differ diff --git a/as/bin/fadd.bin b/as/bin/fadd.bin new file mode 100644 index 0000000..9afa6fc Binary files /dev/null and b/as/bin/fadd.bin differ diff --git a/as/bin/farcall.bin b/as/bin/farcall.bin new file mode 100644 index 0000000..797a87c Binary files /dev/null and b/as/bin/farcall.bin differ diff --git a/as/bin/group1.bin b/as/bin/group1.bin new file mode 100644 index 0000000..64a01bf Binary files /dev/null and b/as/bin/group1.bin differ diff --git a/as/bin/group6.bin b/as/bin/group6.bin new file mode 100644 index 0000000..22ff663 Binary files /dev/null and b/as/bin/group6.bin differ diff --git a/as/bin/group7.bin b/as/bin/group7.bin new file mode 100644 index 0000000..9570eee Binary files /dev/null and b/as/bin/group7.bin differ diff --git a/as/bin/imul.bin b/as/bin/imul.bin new file mode 100644 index 0000000..2b8ea16 Binary files /dev/null and b/as/bin/imul.bin differ diff --git a/as/bin/incdec.bin b/as/bin/incdec.bin new file mode 100644 index 0000000..676e5fa Binary files /dev/null and b/as/bin/incdec.bin differ diff --git a/as/bin/inher.bin b/as/bin/inher.bin new file mode 100644 index 0000000..b37b3eb Binary files /dev/null and b/as/bin/inher.bin differ diff --git a/as/bin/inout.bin b/as/bin/inout.bin new file mode 100644 index 0000000..a215490 Binary files /dev/null and b/as/bin/inout.bin differ diff --git a/as/bin/movspec.bin b/as/bin/movspec.bin new file mode 100644 index 0000000..6a5ef0a Binary files /dev/null and b/as/bin/movspec.bin differ diff --git a/as/bin/pushpop.bin b/as/bin/pushpop.bin new file mode 100644 index 0000000..f95d6b5 Binary files /dev/null and b/as/bin/pushpop.bin differ diff --git a/as/bin/seg.bin b/as/bin/seg.bin new file mode 100644 index 0000000..43445a6 Binary files /dev/null and b/as/bin/seg.bin differ diff --git a/as/bin/shdouble.bin b/as/bin/shdouble.bin new file mode 100644 index 0000000..91bda37 Binary files /dev/null and b/as/bin/shdouble.bin differ diff --git a/as/bin/shift.bin b/as/bin/shift.bin new file mode 100644 index 0000000..1e31fac Binary files /dev/null and b/as/bin/shift.bin differ diff --git a/as/bin/xchg.bin b/as/bin/xchg.bin new file mode 100644 index 0000000..6455b67 Binary files /dev/null and b/as/bin/xchg.bin 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 +#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 (,) + 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 +#endif + +#ifdef POSIX_HEADERS_MISSING +int write P((int fd, const void *buf, unsigned nbytes)); +#else +#undef NULL +#include +#include +#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 +#endif + +#ifdef POSIX_HEADERS_MISSING +int write P((int fd, const void *buf, unsigned nbytes)); +#else +#undef NULL +#include +#include +#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 +#endif + +#ifdef POSIX_HEADERS_MISSING +int write P((int fd, const void *buf, unsigned nbytes)); +#else +#undef NULL +#include +#include +#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 +#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 Binary files /dev/null and b/as/obj1/calljmp.obj differ diff --git a/as/obj1/ea.obj b/as/obj1/ea.obj new file mode 100644 index 0000000..6b53beb Binary files /dev/null and b/as/obj1/ea.obj differ diff --git a/as/obj1/each.obj b/as/obj1/each.obj new file mode 100644 index 0000000..5426253 Binary files /dev/null and b/as/obj1/each.obj differ diff --git a/as/obj1/f.obj b/as/obj1/f.obj new file mode 100644 index 0000000..4dbe2d9 Binary files /dev/null and b/as/obj1/f.obj differ diff --git a/as/obj1/fadd.obj b/as/obj1/fadd.obj new file mode 100644 index 0000000..28b3dd4 Binary files /dev/null and b/as/obj1/fadd.obj differ diff --git a/as/obj1/farcall.obj b/as/obj1/farcall.obj new file mode 100644 index 0000000..259703c Binary files /dev/null and b/as/obj1/farcall.obj differ diff --git a/as/obj1/group1.obj b/as/obj1/group1.obj new file mode 100644 index 0000000..26d4a8c Binary files /dev/null and b/as/obj1/group1.obj differ diff --git a/as/obj1/group6.obj b/as/obj1/group6.obj new file mode 100644 index 0000000..27e81ae Binary files /dev/null and b/as/obj1/group6.obj differ diff --git a/as/obj1/group7.obj b/as/obj1/group7.obj new file mode 100644 index 0000000..37af051 Binary files /dev/null and b/as/obj1/group7.obj differ diff --git a/as/obj1/imul.obj b/as/obj1/imul.obj new file mode 100644 index 0000000..34ef370 Binary files /dev/null and b/as/obj1/imul.obj differ diff --git a/as/obj1/incdec.obj b/as/obj1/incdec.obj new file mode 100644 index 0000000..03f583a Binary files /dev/null and b/as/obj1/incdec.obj differ diff --git a/as/obj1/inher.obj b/as/obj1/inher.obj new file mode 100644 index 0000000..aaea0b9 Binary files /dev/null and b/as/obj1/inher.obj differ diff --git a/as/obj1/inout.obj b/as/obj1/inout.obj new file mode 100644 index 0000000..58aa820 Binary files /dev/null and b/as/obj1/inout.obj differ diff --git a/as/obj1/movspec.obj b/as/obj1/movspec.obj new file mode 100644 index 0000000..15eab78 Binary files /dev/null and b/as/obj1/movspec.obj differ diff --git a/as/obj1/pushpop.obj b/as/obj1/pushpop.obj new file mode 100644 index 0000000..2ff789e Binary files /dev/null and b/as/obj1/pushpop.obj differ diff --git a/as/obj1/seg.obj b/as/obj1/seg.obj new file mode 100644 index 0000000..2ba948c Binary files /dev/null and b/as/obj1/seg.obj differ diff --git a/as/obj1/shdouble.obj b/as/obj1/shdouble.obj new file mode 100644 index 0000000..ab75750 Binary files /dev/null and b/as/obj1/shdouble.obj differ diff --git a/as/obj1/shift.obj b/as/obj1/shift.obj new file mode 100644 index 0000000..520be81 Binary files /dev/null and b/as/obj1/shift.obj differ diff --git a/as/obj1/xchg.obj b/as/obj1/xchg.obj new file mode 100644 index 0000000..c39b703 Binary files /dev/null and b/as/obj1/xchg.obj 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 +#include +#include +#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 +#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" -- cgit v1.2.1