From 1ebba8bd130becd303aeb6b87eb27fab8b0ef29c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 8 Jun 2015 22:03:48 +0100 Subject: [PATCH] as09: 6809 assembler for native asm work Right now this won't *quite* fit on the Dragon32, but I think it would with a tiny bit of tidying up and if 6809 is fixed to not suck in stdio always (or has a stdio free link option as Z80 has for now) --- Applications/as09/6809/const.h | 501 +++++ Applications/as09/Makefile | 49 + Applications/as09/address.h | 30 + Applications/as09/align.h | 23 + Applications/as09/alloc.c | 94 + Applications/as09/as.c | 337 +++ Applications/as09/as86_encap.sh | 124 ++ Applications/as09/as86_to_data | 94 + Applications/as09/asm/calljmp.asm | 70 + Applications/as09/asm/ea.asm | 109 + Applications/as09/asm/each.asm | 211 ++ Applications/as09/asm/easlow.as | 1219 +++++++++++ Applications/as09/asm/f.asm | 114 ++ Applications/as09/asm/fadd.asm | 271 +++ Applications/as09/asm/farcall.asm | 10 + Applications/as09/asm/group1.asm | 31 + Applications/as09/asm/group6.asm | 24 + Applications/as09/asm/group7.asm | 34 + Applications/as09/asm/imul.asm | 33 + Applications/as09/asm/incdec.asm | 83 + Applications/as09/asm/inher.asm | 127 ++ Applications/as09/asm/inout.asm | 25 + Applications/as09/asm/movspec.asm | 246 +++ Applications/as09/asm/pushpop.asm | 86 + Applications/as09/asm/seg.asm | 6 + Applications/as09/asm/shdouble.asm | 34 + Applications/as09/asm/shift.asm | 119 ++ Applications/as09/asm/summary.as | 385 ++++ Applications/as09/asm/xchg.asm | 103 + Applications/as09/assemble.c | 364 ++++ Applications/as09/bin/calljmp.bin | Bin 0 -> 146 bytes Applications/as09/bin/ea.bin | Bin 0 -> 441 bytes Applications/as09/bin/each.bin | Bin 0 -> 657 bytes Applications/as09/bin/f.bin | Bin 0 -> 181 bytes Applications/as09/bin/fadd.bin | Bin 0 -> 605 bytes Applications/as09/bin/farcall.bin | Bin 0 -> 41 bytes Applications/as09/bin/group1.bin | Bin 0 -> 115 bytes Applications/as09/bin/group6.bin | Bin 0 -> 38 bytes Applications/as09/bin/group7.bin | Bin 0 -> 53 bytes Applications/as09/bin/imul.bin | Bin 0 -> 119 bytes Applications/as09/bin/incdec.bin | Bin 0 -> 116 bytes Applications/as09/bin/inher.bin | Bin 0 -> 129 bytes Applications/as09/bin/inout.bin | Bin 0 -> 54 bytes Applications/as09/bin/movspec.bin | Bin 0 -> 682 bytes Applications/as09/bin/pushpop.bin | Bin 0 -> 128 bytes Applications/as09/bin/seg.bin | Bin 0 -> 16 bytes Applications/as09/bin/shdouble.bin | Bin 0 -> 61 bytes Applications/as09/bin/shift.bin | Bin 0 -> 276 bytes Applications/as09/bin/xchg.bin | Bin 0 -> 234 bytes Applications/as09/byteord.h | 18 + Applications/as09/chk | 19 + Applications/as09/const.h | 315 +++ Applications/as09/errors.c | 111 + Applications/as09/errors.h | 113 + Applications/as09/express.c | 410 ++++ Applications/as09/file.h | 17 + Applications/as09/flag.h | 5 + Applications/as09/genbin.c | 272 +++ Applications/as09/genlist.c | 468 +++++ Applications/as09/genobj.c | 672 ++++++ Applications/as09/gensym.c | 223 ++ Applications/as09/globvar.h | 124 ++ Applications/as09/keywords.c | 746 +++++++ Applications/as09/macro.c | 174 ++ Applications/as09/macro.h | 10 + Applications/as09/mops.c | 2945 +++++++++++++++++++++++++++ Applications/as09/obj1/calljmp.obj | Bin 0 -> 200 bytes Applications/as09/obj1/ea.obj | Bin 0 -> 472 bytes Applications/as09/obj1/each.obj | Bin 0 -> 715 bytes Applications/as09/obj1/f.obj | Bin 0 -> 207 bytes Applications/as09/obj1/fadd.obj | Bin 0 -> 1069 bytes Applications/as09/obj1/farcall.obj | Bin 0 -> 71 bytes Applications/as09/obj1/group1.obj | Bin 0 -> 145 bytes Applications/as09/obj1/group6.obj | Bin 0 -> 67 bytes Applications/as09/obj1/group7.obj | Bin 0 -> 82 bytes Applications/as09/obj1/imul.obj | Bin 0 -> 147 bytes Applications/as09/obj1/incdec.obj | Bin 0 -> 146 bytes Applications/as09/obj1/inher.obj | Bin 0 -> 158 bytes Applications/as09/obj1/inout.obj | Bin 0 -> 82 bytes Applications/as09/obj1/movspec.obj | Bin 0 -> 722 bytes Applications/as09/obj1/pushpop.obj | Bin 0 -> 159 bytes Applications/as09/obj1/seg.obj | Bin 0 -> 42 bytes Applications/as09/obj1/shdouble.obj | Bin 0 -> 106 bytes Applications/as09/obj1/shift.obj | Bin 0 -> 308 bytes Applications/as09/obj1/xchg.obj | Bin 0 -> 264 bytes Applications/as09/opcode.h | 159 ++ Applications/as09/pops.c | 1105 ++++++++++ Applications/as09/proto.h | 233 +++ Applications/as09/readsrc.c | 494 +++++ Applications/as09/scan.c | 252 +++ Applications/as09/scan.h | 12 + Applications/as09/source.h | 4 + Applications/as09/syshead.h | 62 + Applications/as09/table.c | 216 ++ Applications/as09/type.h | 171 ++ Applications/as09/typeconv.c | 181 ++ Applications/as09/version.h | 1 + 97 files changed, 14488 insertions(+) create mode 100644 Applications/as09/6809/const.h create mode 100644 Applications/as09/Makefile create mode 100644 Applications/as09/address.h create mode 100644 Applications/as09/align.h create mode 100644 Applications/as09/alloc.c create mode 100644 Applications/as09/as.c create mode 100644 Applications/as09/as86_encap.sh create mode 100644 Applications/as09/as86_to_data create mode 100644 Applications/as09/asm/calljmp.asm create mode 100644 Applications/as09/asm/ea.asm create mode 100644 Applications/as09/asm/each.asm create mode 100644 Applications/as09/asm/easlow.as create mode 100644 Applications/as09/asm/f.asm create mode 100644 Applications/as09/asm/fadd.asm create mode 100644 Applications/as09/asm/farcall.asm create mode 100644 Applications/as09/asm/group1.asm create mode 100644 Applications/as09/asm/group6.asm create mode 100644 Applications/as09/asm/group7.asm create mode 100644 Applications/as09/asm/imul.asm create mode 100644 Applications/as09/asm/incdec.asm create mode 100644 Applications/as09/asm/inher.asm create mode 100644 Applications/as09/asm/inout.asm create mode 100644 Applications/as09/asm/movspec.asm create mode 100644 Applications/as09/asm/pushpop.asm create mode 100644 Applications/as09/asm/seg.asm create mode 100644 Applications/as09/asm/shdouble.asm create mode 100644 Applications/as09/asm/shift.asm create mode 100644 Applications/as09/asm/summary.as create mode 100644 Applications/as09/asm/xchg.asm create mode 100644 Applications/as09/assemble.c create mode 100644 Applications/as09/bin/calljmp.bin create mode 100644 Applications/as09/bin/ea.bin create mode 100644 Applications/as09/bin/each.bin create mode 100644 Applications/as09/bin/f.bin create mode 100644 Applications/as09/bin/fadd.bin create mode 100644 Applications/as09/bin/farcall.bin create mode 100644 Applications/as09/bin/group1.bin create mode 100644 Applications/as09/bin/group6.bin create mode 100644 Applications/as09/bin/group7.bin create mode 100644 Applications/as09/bin/imul.bin create mode 100644 Applications/as09/bin/incdec.bin create mode 100644 Applications/as09/bin/inher.bin create mode 100644 Applications/as09/bin/inout.bin create mode 100644 Applications/as09/bin/movspec.bin create mode 100644 Applications/as09/bin/pushpop.bin create mode 100644 Applications/as09/bin/seg.bin create mode 100644 Applications/as09/bin/shdouble.bin create mode 100644 Applications/as09/bin/shift.bin create mode 100644 Applications/as09/bin/xchg.bin create mode 100644 Applications/as09/byteord.h create mode 100755 Applications/as09/chk create mode 100644 Applications/as09/const.h create mode 100644 Applications/as09/errors.c create mode 100644 Applications/as09/errors.h create mode 100644 Applications/as09/express.c create mode 100644 Applications/as09/file.h create mode 100644 Applications/as09/flag.h create mode 100644 Applications/as09/genbin.c create mode 100644 Applications/as09/genlist.c create mode 100644 Applications/as09/genobj.c create mode 100644 Applications/as09/gensym.c create mode 100644 Applications/as09/globvar.h create mode 100644 Applications/as09/keywords.c create mode 100644 Applications/as09/macro.c create mode 100644 Applications/as09/macro.h create mode 100644 Applications/as09/mops.c create mode 100644 Applications/as09/obj1/calljmp.obj create mode 100644 Applications/as09/obj1/ea.obj create mode 100644 Applications/as09/obj1/each.obj create mode 100644 Applications/as09/obj1/f.obj create mode 100644 Applications/as09/obj1/fadd.obj create mode 100644 Applications/as09/obj1/farcall.obj create mode 100644 Applications/as09/obj1/group1.obj create mode 100644 Applications/as09/obj1/group6.obj create mode 100644 Applications/as09/obj1/group7.obj create mode 100644 Applications/as09/obj1/imul.obj create mode 100644 Applications/as09/obj1/incdec.obj create mode 100644 Applications/as09/obj1/inher.obj create mode 100644 Applications/as09/obj1/inout.obj create mode 100644 Applications/as09/obj1/movspec.obj create mode 100644 Applications/as09/obj1/pushpop.obj create mode 100644 Applications/as09/obj1/seg.obj create mode 100644 Applications/as09/obj1/shdouble.obj create mode 100644 Applications/as09/obj1/shift.obj create mode 100644 Applications/as09/obj1/xchg.obj create mode 100644 Applications/as09/opcode.h create mode 100644 Applications/as09/pops.c create mode 100644 Applications/as09/proto.h create mode 100644 Applications/as09/readsrc.c create mode 100644 Applications/as09/scan.c create mode 100644 Applications/as09/scan.h create mode 100644 Applications/as09/source.h create mode 100644 Applications/as09/syshead.h create mode 100644 Applications/as09/table.c create mode 100644 Applications/as09/type.h create mode 100644 Applications/as09/typeconv.c create mode 100644 Applications/as09/version.h diff --git a/Applications/as09/6809/const.h b/Applications/as09/6809/const.h new file mode 100644 index 00000000..abd94694 --- /dev/null +++ b/Applications/as09/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/Applications/as09/Makefile b/Applications/as09/Makefile new file mode 100644 index 00000000..65050360 --- /dev/null +++ b/Applications/as09/Makefile @@ -0,0 +1,49 @@ +PLATFORM = 6809 +CC = m6809-unknown-gcc +# These are wrappers for lwasm and lwar +ASM = m6809-unknown-as +AR = m6809-unknown-ar +LINKER = lwlink +CFLAGS = -I../../Library/include -I../../Library/include/6502 -Wall -pedantic -fno-strict-aliasing +COPT = -Os +LINKER_OPT = --format=raw -L../../Library/libs -lc6809 +LIBGCCDIR = $(dir $(shell $(CC) -print-libgcc-file-name)) +LINKER_OPT += -L$(LIBGCCDIR) -lgcc -m as09.map +LINKER_OPT += --script=../util/$(TARGET).link +ASM_OPT = -o +CRT0 = ../../Library/libs/crt0_6809.o + +OBJS =as.o assemble.o errors.o express.o \ + genbin.o genlist.o genobj.o gensym.o \ + keywords.o macro.o mops.o pops.o readsrc.o \ + scan.o table.o typeconv.o alloc.o + +all: as09 + +as09: $(OBJS) + $(LINKER) -o $@ $(LINKER_OPT) $(CRT0) $(OBJS) + +clean realclean clobber: + rm -f *.o as09 *~ + +.c.o: + $(CC) $(CFLAGS) $(COPT) -c $< + +$(OBJS): const.h errors.h + +as.o: const.h type.h byteord.h macro.h file.h flag.h globvar.h +assemble.o: const.h type.h address.h globvar.h opcode.h scan.h +error.o: const.h type.h +express.o: const.h type.h address.h globvar.h scan.h source.h +genbin.o: const.h type.h address.h file.h globvar.h +genlist.o: const.h type.h address.h flag.h file.h globvar.h macro.h scan.h \ + source.h +genobj.o: const.h type.h address.h file.h globvar.h +gensym.o: const.h type.h flag.h file.h globvar.h +keywords.o: const.h type.h globvar.h opcode.h +macro.o: const.h type.h globvar.h scan.h macro.h +mops.o: const.h type.h globvar.h opcode.h scan.h address.h +pops.o: const.h type.h address.h flag.h globvar.h opcode.h scan.h +readsrc.o: const.h type.h flag.h file.h globvar.h macro.h scan.h source.h +scan.o: const.h type.h globvar.h scan.h +table.o: const.h type.h globvar.h opcode.h scan.h diff --git a/Applications/as09/address.h b/Applications/as09/address.h new file mode 100644 index 00000000..26fcf33b --- /dev/null +++ b/Applications/as09/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/Applications/as09/align.h b/Applications/as09/align.h new file mode 100644 index 00000000..52b1e897 --- /dev/null +++ b/Applications/as09/align.h @@ -0,0 +1,23 @@ +/* align.h - memory alignment requirements for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#ifndef S_ALIGNMENT +# define align(x) +#else + +#if defined(__STDC__) && defined(_POSIX_SOURCE) +# define align(x) ((x)=(void *) \ + (((ssize_t)(x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))) +#else +# define align(x) ((x)=(void *) \ + ((char *)(x) + ((S_ALIGNMENT-(char)(x)) & (S_ALIGNMENT-1)))) +#endif +#endif + + + + + + + diff --git a/Applications/as09/alloc.c b/Applications/as09/alloc.c new file mode 100644 index 00000000..2ca84f3b --- /dev/null +++ b/Applications/as09/alloc.c @@ -0,0 +1,94 @@ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "align.h" + +static char NOMEMEORY[] = "Cannot allocate sufficient memory"; + +#ifdef USE_FIXED_HEAP +static char *heapend; /* end of free space for symbol list */ +static char *heapptr; /* next free space in symbol list */ +#endif + +#ifndef USE_FIXED_HEAP +static char tempbuf[2048]; +#endif + +void init_heap(void) +{ +#ifdef USE_FIXED_HEAP +#ifndef USERMEM +#define USERMEM 0xAC00U +#endif + +#if defined(__AS386_16__) || defined(__m6809__) + int stk; + heapptr = sbrk(0); + heapend = ((char*)&stk) - STAKSIZ - 16; + brk(heapend); + if(sbrk(0) != heapend) + as_abort(NOMEMEORY); +#else +#ifdef SOS_EDOS + heapend = stackreg() - STAKSIZ; +#else + heapptr = malloc(USERMEM); + heapend = heapptr + USERMEM; + if (heapptr == 0) + as_abort(NOMEMEORY); +#endif +#endif +#endif +} + +void *temp_buf(void) +{ +#ifdef USE_FIXED_HEAP + return heapptr; +#else + return tempbuf; +#endif +} + +void *asalloc(unsigned int size) +{ + void * rv; +#ifdef USE_FIXED_HEAP + align(heapptr); + if (heapptr+size < heapend) + { + rv = heapptr; + heapptr += size; + } + else + rv = 0; +#else + rv = malloc(size); +#endif + if (rv == 0 && size) as_abort(NOMEMEORY); + return rv; +} + + +void *asrealloc(void *oldptr, unsigned int size) +{ + void * rv; +#ifdef USE_FIXED_HEAP + if (oldptr == 0) return asalloc(size); + + if ((char*)oldptr+size < heapend) + { + heapptr = (char*)oldptr + size; + rv = oldptr; + } + else + rv = 0; +#else + rv = realloc(oldptr, size); +#endif + + if (rv == 0) as_abort(NOMEMEORY); + return rv; +} + diff --git a/Applications/as09/as.c b/Applications/as09/as.c new file mode 100644 index 00000000..70ca16eb --- /dev/null +++ b/Applications/as09/as.c @@ -0,0 +1,337 @@ +/* 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 "syshead.h" +#include "const.h" +#include "type.h" +#include "byteord.h" +#include "macro.h" +#undef EXTERN +#define EXTERN +#include "file.h" +#include "flag.h" +#include "globvar.h" +#include "version.h" + +char hexdigit[] = "0123456789ABCDEF"; /* XXX - ld uses lower case */ + +static struct block_s hid_blockstak[MAXBLOCK]; /* block stack */ +static struct lc_s hid_lctab[NLOC]; /* location counter table */ +static struct if_s hid_ifstak[MAXBLOCK]; /* if stack */ +static struct schain_s hid_mcpar[MACPSIZ]; /* MACRO params */ +static struct macro_s hid_macstak[MAXBLOCK]; /* macro stack */ +static struct sym_s *hid_spt[SPTSIZ]; /* hash table */ + +static char * binfilename = 0; +static char * objfilename = 0; +static int keep_bad_output = 0; + +static void initp1 P((void)); +static int my_creat P((char *name, char *message)); +static void process_args P((int argc, char **argv)); +static void summary P((fd_t fd)); +static void summ_number P((unsigned num)); +static void usage P((void)); + +int main(int argc, char *argv[]) +{ + init_heap(); + initp1(); + initp1p2(); + inst_keywords(); + initbin(); + initobj(); + initsource(); + typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN); + as_warn.global = TRUE; /* constant */ + as_warn.semaphore = -1; + last_pass=1; + process_args(argc, argv); + initscan(); + line_zero(); + + assemble(); /* doesn't return, maybe use setjmp */ + + /* NOTREACHED */ + return 0; +} + +void as_abort(char *message) +{ + write(STDOUT, "as: ", 4); + write(STDOUT, message, strlen(message)); + write(STDOUT, "\n", 1); + exit(1); +} + +void finishup(void) +{ + 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(); + + /* If an output binary is in error remove it */ + close(binfil); binfil=0; + close(objfil); objfil=0; + if (toterr != 0 && !keep_bad_output) + { + if(binfilename) unlink(binfilename); + if(objfilename) unlink(objfilename); + } + + exit(toterr != 0 ? 1 : 0); /* should close output files and check */ +} + +/* initialise constant nonzero values */ + +static void initp1(void) +{ +#ifdef I80386 + idefsize = defsize = 2; /* I think this is probably safer (RDB) */ +#endif +#if 0 + 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 */ + +void initp1p2(void) +{ + register struct lc_s *lcp; + + dirty_pass = 0; + 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) + { + lcp->data = lcdata = RELBIT; /* lc relocatable until 1st ORG */ + lcp->lc = lc = 0; + } +} + +void line_zero(void) +{ + if( textseg >= 0 ) + ptext(); +} + +static int my_creat(char *name, char *message) +{ + int fd; + +#ifdef O_BINARY + if ((fd = open(name, O_RDWR|O_BINARY|O_CREAT|O_TRUNC, CREAT_PERMS)) < 0 || fd > 255) +#else + if ((fd = creat(name, CREAT_PERMS)) < 0 || fd > 255) +#endif + as_abort(message); + return fd; +} + +static void process_args(int argc, char *argv[]) +{ + char *arg; + bool_t isnextarg; + char *nextarg = 0; + int opened_file = 0; + int flag_state; + +#ifdef I80386 + setcpu(0xF); +#endif + textseg = -1; + + if (argc <= 1) + usage(); + do + { + arg = *++argv; + if (arg[0] == '-' && arg[1] != '\0') + { + flag_state = 1; + if (arg[2] == '-' && arg[3] == 0 ) + flag_state = 0; + else + 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]) + { + case 'v': + outfd = STDOUT; + writes("as86 version: "); +#ifdef VERSION + writesn(VERSION); +#else + writesn("Unknown!"); +#endif + exit(1); +#ifdef I80386 + case '0': case '1': case '2': + idefsize = defsize = 0x2; + setcpu(arg[1]-'0'); + break; + case '3': + idefsize = defsize = 0x4; + setcpu(0xF); + break; + case 'a': + asld_compatible = flag_state; + break; +#endif + case 'b': + if (!isnextarg || binfil != 0) + usage(); + binfil = my_creat(binfilename=nextarg, "error creating binary file"); + binaryg = TRUE; + --argc; + ++argv; + break; + case 'g': + globals_only_in_obj = flag_state; + break; +#ifdef I80386 + case 'j': + jumps_long = flag_state; + break; + case 'O': + if( flag_state ) last_pass = 2; + else last_pass = 1; + 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(objfilename=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 't': + if (!isnextarg || binfil != 0) + usage(); + textseg = atoi(nextarg); if(textseg>0) textseg+=BSSLOC; + --argc; + ++argv; + break; + case 'u': + if( flag_state ) inidata = IMPBIT | SEGM; + else inidata = 0; + break; + case 'w': + if( flag_state ) as_warn.semaphore = -1; + else as_warn.semaphore = 0; + break; + case 'k': + keep_bad_output = 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"); + infiln = infil0 = 1; + infil = open_input(strcpy(filnamptr, arg)); + opened_file = 1; + } + } + while (--argc != 1); + if( !opened_file ) + { + infiln = infil0 = 1; + infil = open_input(strcpy(filnamptr, "-")); + } +#ifdef I80386 + origcpuid = cpuid; +#endif + inidata = (~binaryg & inidata) | (RELBIT | UNDBIT); +} /* IMPBIT from inidata unless binaryg */ + +static void summary(int fd) +{ + outfd = fd; + writenl(); + summ_number(toterr); + writesn(" errors"); + summ_number(totwarn); + writesn(" warnings"); +} + +static void summ_number(unsigned num) +{ + /* format number like line numbers */ + char buf[16]; + *build_number(num, LINUM_LEN, buf) = 0; + writes(buf); +} + +static void usage(void) +{ + as_abort( +#ifdef I80386 +"usage: as [-03agjuwO] [-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/Applications/as09/as86_encap.sh b/Applications/as09/as86_encap.sh new file mode 100644 index 00000000..cba2b3c8 --- /dev/null +++ b/Applications/as09/as86_encap.sh @@ -0,0 +1,124 @@ +#!/bin/sh - +# +# This file is simply an example of what can be done using the new binary +# and symbol table output functions. As shown it can be used to produce +# a C file containing the encapsulated binary of the assembly, plus any +# public symbols in the source are accessable to the C program. +# +# Use it in a makefile: +# +# .s.v: +# as86_encap $*.s $*.v $*_ $(AS86FLAGS) +# + +[ $# -lt 2 ] && { + echo "Usage: `basename $0` infile outfile prefix [as86 opts]" 1>&2 + exit 1 +} + +trap "rm -f _$$.* ; exit 99" 1 2 3 15 + +LIBDIR='%%LIBDIR%%' # Set by make install +BINDIR='%%BINDIR%%' # Set by make install + +# If the one set by install fails then try a couple of others. +[ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`" +[ -x "$LIBDIR/as86" ] || LIBDIR="$BINDIR" +[ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`/../lib" +[ -x "$LIBDIR/as86" ] || LIBDIR=/usr/bin + +IFILE="$1" +OFILE="$2" +PREFIX="`basename $IFILE .s`_" + +shift ; shift +if [ $# -ge 1 ] +then case "$1" in + -* ) ;; + [A-Za-z_]* ) PREFIX="$1" + shift + ;; + esac +fi +RV=0 + +$LIBDIR/as86 "$@" "$IFILE" -b _$$.bin -s _$$.sym || RV=$? + +echo '#ifndef __ASSEMBLY__' > _$$.0 +echo >> _$$.0 +echo '#else' > _$$.3 +echo >> _$$.3 +echo '#endif' > _$$.5 + +[ "$RV" = 0 ] && { + ( + sort _$$.sym + echo %%%% + od -v -t uC _$$.bin + ) | \ + awk -v prefix=$PREFIX -v ofile=_$$ ' BEGIN{ + sname = prefix "start"; + sn_file= ofile ".1"; + bn_file= ofile ".2"; + as_file= ofile ".4"; + } + /^%%%%$/ { flg++; + if( flg == 1 ) + { + if( !started ) + { + printf "#define %s 0\n", sname > sn_file; + printf "%s = 0\n", sname > as_file; + } + + printf "static char %sdata[] = {\n", prefix >bn_file; + bincount=0; + } + next; + } + flg==0 { + if(NF == 0) next; + if( substr($2,1,4) == "0000" ) $2=substr($2,5); + if( $1 == "+" && $4 == "$start" ) + { + printf "#define %s 0x%s\n", sname, $2 > sn_file; + printf "%s = $%s\n", sname, $2 > as_file; + started = 1; + } + else if( substr($3, 1, 1) == "E" && $4 != "start" && $4 != "size" && $4 != "data" ) + { + printf "#define %s%s 0x%s\n", prefix, $4, $2 > sn_file; + printf "%s%s = $%s\n", prefix, $4, $2 > as_file; + } + next; + } + flg==1 { + if(NF == 0) next; + printf " " > bn_file; + for(i=2;i<=NF;i++) { + if( $i >= 32 && $i < 127 && $i != 39 && $i != 92 ) + printf("\047%c\047,", $i) > bn_file; + else + printf("%3d,", $i) > bn_file; + bincount++; + } + printf "\n" > bn_file; + } + END { + printf "};\n\n" > bn_file; + printf "#define %ssize %d\n\n", prefix, bincount > sn_file; + printf "%ssize = $%04x\n\n", prefix, bincount > as_file; + } + ' + RV=$? +} + +[ "$RV" = 0 ] && { + if [ "X$OFILE" = "X-" ] + then cat _$$.[0-9] + else cat _$$.[0-9] > "$OFILE" || RV=$? + fi +} + +rm -f _$$.* +exit $RV diff --git a/Applications/as09/as86_to_data b/Applications/as09/as86_to_data new file mode 100644 index 00000000..d53e5009 --- /dev/null +++ b/Applications/as09/as86_to_data @@ -0,0 +1,94 @@ +#!/bin/sh - +# +# This file is simply an example of what can be done using the new binary +# and symbol table output functions. It produces a byte array with the +# symbols in the object as array references within it. +# +# The output is a Linux OMAGIC binary created by ld86 -N, this means the +# object can be linked directly to C-functions created by the same GCC that +# compiled ld86. +# +# Use it in a makefile: +# +# .s86.o: +# as86_to_data $*.s86 $*.o $(AS86FLAGS) +# + +[ $# -lt 2 ] && { + echo "Usage: `basename $0` infile outfile [as86 opts]" 1>&2 + exit 1 +} + +trap "rm -f _$$.* ; exit 99" 1 2 3 15 + +LIBDIR='%%LIBDIR%%' # Set by make install +[ -d "$LIBDIR" ] || LIBDIR='%%BINDIR%%' +[ -d "$LIBDIR" ] || LIBDIR=/usr/bin + +IFILE="$1" +OFILE="$2" + +shift ; shift +RV=0 + +$LIBDIR/as86 "$@" "$IFILE" -b _$$.bin -s _$$.sym || RV=$? + +[ "$RV" = 0 ] && { + ( + cat _$$.sym + echo %%%% + od -v -t uC _$$.bin + echo %%%% + ) | \ + awk > _$$.v ' BEGIN{ + startaddr=""; + printf ".text\n.data\n"; + } + /^%%%%$/ { flg++; + next; + } + flg==0 { + if(NF == 0) next; + if( substr($2,1,4) == "0000" ) $2=substr($2,5); + if( $1 == "+" && $4 == "$start" ) + { + if( $2 != "0000" ) startaddr=" - $" $2; + } + else if( substr($3, 1, 1) == "E" && $4 != "start" && $4 != "size" && $4 != "data" ) + { + printf "export _%s\n", $4 + printf "_%s = * + $%s%s\n\n", $4, $2, startaddr; + } + next; + } + flg==1 { + if(NF <= 1) next; + printf " .byte "; + for(i=2;i 2 + pfqb, +#endif + 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 */ +}; + +static void asline(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. +*/ + +void assemble(void) +{ + while (TRUE) + { + asline(); + if (label != NUL_PTR) /* must be confirmed if still set */ + { /* it is nulled by EQU, COMM and SET */ +#ifndef MC6809 +#define NEEDENDLABEL ILLAB + if (nocolonlabel) + error(NEEDENDLABEL); +#endif + if(pass && label->value_reg_or_op.value != oldlabel) + { + dirty_pass = TRUE; + if( pass == last_pass ) + error(UNSTABLE_LABEL); + } + + 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 = NUL_PTR; /* reset for next line */ + } + skipline(); + listline(); + genbin(); + genobj(); + binmbuf = lc += lcjump +#ifdef I80386 + + immcount +#endif + ; + } +} + +static void asline(void) +{ + 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; + cpuwarn(); + readline(); + getsym(); + if (sym != IDENT) /* expect label, mnemonic or macro */ + { + /* Warn if not a comment marker or a hash (for /lib/cpp) */ + if( sym != EOLSYM && sym != IMMEDIATE ) + list_force = TRUE; + return; /* anything else is a comment */ + } + symptr = gsymptr; + if (!ifflag) + /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */ + { + if (symptr == NUL_PTR || !(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 */ + { + oldlabel = symptr->value_reg_or_op.value; + + if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */ + { + sym = COLON; + ++lineptr; + } + if (symptr->type & (LABIT | VARBIT)) + { + if (symptr->type & REDBIT) + labelerror(RELAB); + label = symptr; + + if (pass && !(symptr->type & VARBIT) /*&& last_pass>1*/) + { + label->data = (label->data & FORBIT) | lcdata; + label->value_reg_or_op.value = lc; + } + } + else if (checksegrel(symptr)) + { + symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */ +#ifdef MC6809 +#if 0 + if (sym == COLON) + symptr->type |= EXPBIT; +#endif +#endif + /* remember if forward referenced */ + symptr->data = (symptr->data & FORBIT) | lcdata; + 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; +#ifdef I80386 + needcpu((page==0 && ((opcode&0xF0) == 0x60||(opcode&0xF6)==0xC0))?1:0); +#endif + routine = rout_table[symptr->value_reg_or_op.op.routine]; + getsym(); + (*routine)(); +#ifdef I80386 + /* We handle "rep[ne]" refix as separate instruction; check if its use is valid */ + if (opcode == 0xF2 || opcode == 0xF3) { /* REP */ + rep = opcode; + /* Not another prefix */ + } else if (opcode != 0x2E && /* CSEG */ + opcode != 0x3E && /* DSEG */ + opcode != 0x26 && /* ESEG */ + opcode != 0x64 && /* FSEG */ + opcode != 0x65 && /* GSEG */ + opcode != 0x36 && /* SSEG */ + opcode != 0xF0) { /* LOCK */ + if (rep == 0xF2 && (opcode&0xF6) != 0xA6) /* REPNE CMPS/SCAS */ + error (REPNE_STRING); + if (rep == 0xF3 && !((opcode&0xFC) == 0x6C || /* REP INS/OUTS */ + (opcode&0xFC) == 0xA4 || /* REP MOVS/CMPS */ + (opcode&0xFC) == 0xAC || /* REP SCAS/LODS */ + (opcode&0xFE) == 0xAA)) /* REP STOS */ + error (REP_STRING); + rep = 0; + } +#endif + if (sym != EOLSYM) + error(JUNK_AFTER_OPERANDS); +#ifdef I80386 + needcpu(page==PAGE1_OPCODE?2:0); + + if (aprefix != 0) + ++mcount; + if (oprefix != 0) + ++mcount; + if (sprefix != 0) + ++mcount; +#endif +} diff --git a/Applications/as09/bin/calljmp.bin b/Applications/as09/bin/calljmp.bin new file mode 100644 index 0000000000000000000000000000000000000000..90c022f7bbdb7526d298b8dea6b13e1b15820d27 GIT binary patch literal 146 zcmaKkxe>wu5Cg9SG6znaQ2@2j!qNl~O#lC!9%~$MFMF CL0D)2 literal 0 HcmV?d00001 diff --git a/Applications/as09/bin/ea.bin b/Applications/as09/bin/ea.bin new file mode 100644 index 0000000000000000000000000000000000000000..5edc0b0e9bdbbcbe994f124ad3268bb97e71ddda GIT binary patch literal 441 zcmXYtJ92|S5JZuM?VK~{2pqs4*}8#_FiQCe99j~Bozf|E0$qWSkdTm&P@yurdv~eo z*8{av`-_z4OvAK~f|`a-=}^ZY3-+SNI1BZd#{AM&v|6 itcX2P5*1J7iQj5HDS*pCj{0!vGxh5!Hn literal 0 HcmV?d00001 diff --git a/Applications/as09/bin/f.bin b/Applications/as09/bin/f.bin new file mode 100644 index 0000000000000000000000000000000000000000..ce695a0dcbbe2125149f2bab775c9b2dbfbb5f54 GIT binary patch literal 181 zcmWO0$!)_h5I|7^EI}pcs3VUmbxKGT?7+J5do&{H1&Cuih_idQ@fvvU#W^?nK=;EXor_d7jd$U)&``?6V)(Vnot)4b>Yw2 zj?zs>x{u65>$^;fCO{Uxi z#%q3^41GHeeE#r`2r}Kwk;wc4^&FWgd=c0_WcKVYH2M$>2kPPllC6m6sl<=dVJ*T; zu#vTKa(RfCg2|*wsEMYzf(mivkT5<{4w7lz|NfB;LgmF-oU_;p4P|?6l!FL z%cM24|4j#ChMQ@OHyLlHGw`RUG4iJa5fhNb%%9H8FK|=gro~N;n;JJIZW`SD544N{ E04TsB1^@s6 literal 0 HcmV?d00001 diff --git a/Applications/as09/bin/group6.bin b/Applications/as09/bin/group6.bin new file mode 100644 index 0000000000000000000000000000000000000000..22ff663c12c3d60a28d635148580364569754cc7 GIT binary patch literal 38 ocmZROVPIh3XSk5g&mhjvAi&RX8_044ig5EYJOnaz{sZM10BEoU`2YX_ literal 0 HcmV?d00001 diff --git a/Applications/as09/bin/group7.bin b/Applications/as09/bin/group7.bin new file mode 100644 index 0000000000000000000000000000000000000000..9570eee031f1d9210961bbc7825838258c869c03 GIT binary patch literal 53 ucmZS3W?*1Q=Vug0#{7%|{EYTM5jO^YMs9w_4?w0lKcfLZ+qF=R{Uz3E~Js7iTvC#j>Mn7_f;!OS>v<-&s#H_qHcbOEPKrE(Rj yRI5=N6kS&4MO8O#51KZ}C^=*R literal 0 HcmV?d00001 diff --git a/Applications/as09/bin/inher.bin b/Applications/as09/bin/inher.bin new file mode 100644 index 0000000000000000000000000000000000000000..b37b3eb13dec148eaf37491bcb3ad23edc20458d GIT binary patch literal 129 zcmWm7Ee^sk0D#ddEXP11kzA!UpQ2Q94dfPDFq9^YuIIo|xoZ#x3BQ5jU-HC42r-%7 z-_POTwi}JFr`hIsK5UoszQ3&7$LF@%Z3^m2*!2CnnZJKB8A6tDOK2lmb$QJ8i zkJu+R!?wf%u}18n1@r=~q3JVpi}&zH{1czyTSAUdA#{)&a)wlp^a--TI@mq-j!m!) zF-NQrJ7^9)Ln~NUqXq{Bn*)fa*Z^R^d)k@hS&@CgDtTGu|#YVhiD1CMw@8* z5S7kEhK$~9I+Ahiv7b@*pXN!wumFNjNYIvG<}60@e%%t z|HD`Kk#It&6Z*&ra*5QD^f|J_`q&fph0U=Y@q}0>_R$mc60M`@b99II@hAKXpW{11 zki{+LPr14*Co A(f|Me literal 0 HcmV?d00001 diff --git a/Applications/as09/bin/pushpop.bin b/Applications/as09/bin/pushpop.bin new file mode 100644 index 0000000000000000000000000000000000000000..f95d6b53527ff1a9c4bdb5750727c53cdf1df793 GIT binary patch literal 128 zcmW-ayA6Xd6aZhExQiu<&?QSCu?AoBhwh9R0A&kSfDWcKR+_6$ce0Ae@~|#uaU|rV zWE7MbDqeheqIdMkdyWDTJS{Fx@-!<-Q_VjU1%LR2-4rz)4J|zbBNJZ~`aoZVmQB@N M)AqwSdDZ!|+?i7<2><{9 literal 0 HcmV?d00001 diff --git a/Applications/as09/bin/seg.bin b/Applications/as09/bin/seg.bin new file mode 100644 index 0000000000000000000000000000000000000000..43445a6bb12998baac0942e391c667e7ff131f48 GIT binary patch literal 16 WcmZQzV_;y=vr|h+HTw@_F#rG(NCKAt literal 0 HcmV?d00001 diff --git a/Applications/as09/bin/shdouble.bin b/Applications/as09/bin/shdouble.bin new file mode 100644 index 0000000000000000000000000000000000000000..91bda373e3e321ff977715309ed2a47f604ad080 GIT binary patch literal 61 zcmZQDW?*1Q<6m+EM4V>kU-F4DjeqG){w3EK(}5!V%;`V^#9S(q4#a8vYfdw#@vpu4 IAE=E108|eXr~m)} literal 0 HcmV?d00001 diff --git a/Applications/as09/bin/shift.bin b/Applications/as09/bin/shift.bin new file mode 100644 index 0000000000000000000000000000000000000000..1e31face5de2a6cfcd2413d430ac6d40f6e0e695 GIT binary patch literal 276 zcmXYpF-`z63@Bpo2xi(#Vo$I_y1II``f2v=?lU!J z52zqPgc@4Vh7R;hXs9Gnt);Ewn?_ZwQa#1m)paJvtN|7%kYIxg+~5KIgo8zqY%Xpd z-#D@&SEM4JNJj3+jyy5%5i>_*UAQZ7%h0r0W}9Q4m~iXHi3#_H!kJTZ7K osbo?}DV0R|zt>u|Vzo+DD)b27!H@7g`~W|}&+rTU`qGWz4O2K@Bme*a literal 0 HcmV?d00001 diff --git a/Applications/as09/byteord.h b/Applications/as09/byteord.h new file mode 100644 index 00000000..baf02d0e --- /dev/null +++ b/Applications/as09/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 INT_BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ +#endif + +#ifdef I80386 +# define INT_BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 +#endif + +#ifdef MC6809 +# define INT_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/Applications/as09/chk b/Applications/as09/chk new file mode 100755 index 00000000..44f316ac --- /dev/null +++ b/Applications/as09/chk @@ -0,0 +1,19 @@ + +compile() +{ + # /lib/elksemu ./as86 -3 -k "$@" + ./as86 -3 -k "$@" +} + +for i in `ls asm/*.asm` +do + j=`basename $i .asm` + compile asm/$j.asm -b $j.bin -o $j.obj > /dev/null + cmp $j.obj obj1/$j.obj + + # compile asm/$j.asm -b $j.bin > /dev/null + # cmp $j.bin bin/$j.bin + + rm -f $j.bin $j.obj $j.asm +done + diff --git a/Applications/as09/const.h b/Applications/as09/const.h new file mode 100644 index 00000000..881e5110 --- /dev/null +++ b/Applications/as09/const.h @@ -0,0 +1,315 @@ + +/* Speed and space hacks for BCC */ +#ifdef __AS386_16__ +#define LOW_BYTE 0 /* must be changed for big-endian */ +#else + +#define S_ALIGNMENT sizeof(long) +#endif + +/* const.h - constants for assembler */ + +/* major switches */ + +#define MC6809 /* generate 6809 code */ +#ifndef MC6809 +#define I80386 /* generate 80386 code */ +#endif +#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 + +#ifdef __AS386_16__ +# undef INBUFSIZE +# define INBUFSIZE 512 +# define STAKSIZ 512 /* 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 NUL_PTR ((void*)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 +}; + +/* 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 + +#include "errors.h" + diff --git a/Applications/as09/errors.c b/Applications/as09/errors.c new file mode 100644 index 00000000..1c68950d --- /dev/null +++ b/Applications/as09/errors.c @@ -0,0 +1,111 @@ + +#include "syshead.h" +#include "const.h" +#include "errors.h" + +/* Error codes. */ + +/* Syntax errors. */ +char COMEXP[] = "comma expected"; +char DELEXP[] = "delimiter expected"; +char FACEXP[] = "factor expected"; +char IREGEXP[] = "index register expected"; +char LABEXP[] = "label expected"; +char LPEXP[] = "left parentheses expected"; +char OPEXP[] = "opcode expected"; +char RBEXP[] = "right bracket expected"; +char REGEXP[] = "register expected"; +char RPEXP[] = "right parentheses expected"; +char SPEXP[] = "space expected"; + +/* Expression errors. */ +char ABSREQ[] = "absolute expression required"; +char NONIMPREQ[] = "non-imported expression required"; +char RELBAD[] = "relocation impossible"; + +/* Label errors. */ +char ILLAB[] = "illegal label"; +char MACUID[] = "MACRO used as identifier"; +char MISLAB[] = "missing label"; +char MNUID[] = "opcode used as identifier"; +char REGUID[] = "register used as identifier"; +char RELAB[] = "redefined label"; +char UNBLAB[] = "unbound label"; +char UNLAB[] = "undefined label"; +char VARLAB[] = "variable used as label"; + +/* Addressing errors. */ +char ABOUNDS[] = "address out of bounds"; +char DBOUNDS[] = "data out of bounds"; +char ILLMOD[] = "illegal address mode"; +char ILLREG[] = "illegal register"; + +/* Control structure errors. */ +char ELSEBAD[] = "no matching IF"; +char ENDBBAD[] = "no matching BLOCK"; +char EOFBLOCK[] = "end of file in BLOCK"; +char EOFIF[] = "end of file in IF"; +char EOFLC[] = "location counter was undefined at end"; +char EOFMAC[] = "end of file in MACRO"; +char FAILERR[] = "user-generated error"; + +/* Overflow errors. */ +char BLOCKOV[] = "BLOCK stack overflow"; +char BWRAP[] = "binary file wrap-around"; +char COUNTOV[] = "counter overflow"; +char COUNTUN[] = "counter underflow"; +char GETOV[] = "GET stack overflow"; +char IFOV[] = "IF stack overflow"; + +char LINLONG[] = "line too long"; +char MACOV[] = "MACRO stack overflow"; +char OBJSYMOV[] = "object symbol table overflow"; +char OWRITE[] = "program overwrite"; +char PAROV[] = "parameter table overflow"; +char SYMOV[] = "symbol table overflow"; +char SYMOUTOV[] = "output symbol table overflow"; + +/* I/O errors. */ +char OBJOUT[] = "error writing object file"; + +/* Miscellaneous errors. */ +char AL_AX_EAX_EXP[] = "al ax or eax expected"; +char CTLINS[] = "control character in string"; +char FURTHER[] = "futher errors suppressed"; +char ILL_IMM_MODE[] = "illegal immediate mode"; +char ILL_IND_TO_IND[] = "illegal indirect to indirect"; +char ILL_IND[] = "illegal indirection"; +char ILL_IND_PTR[] = "illegal indirection from previous 'ptr'"; +char ILL_SCALE[] = "illegal scale"; +char ILL_SECTION[] = "illegal section"; +char ILL_SEG_REG[] = "illegal segment register"; +char ILL_SOURCE_EA[] = "illegal source effective address"; +char ILL_SIZE[] = "illegal size"; +char IMM_REQ[] = "immediate expression expected"; +char INDEX_REG_EXP[] = "index register expected"; +char IND_REQ[] = "indirect expression required"; +char MISMATCHED_SIZE[] = "mismatched size"; +char NOIMPORT[] = "no imports with binary file output"; +char REENTER[] = "multiple ENTER pseudo-ops"; +char REL_REQ[] = "relative expression required"; +char REPEATED_DISPL[] = "repeated displacement"; +char SEGREL[] = "segment or relocatability redefined"; +char SEG_REG_REQ[] = "segment register required"; +char SIZE_UNK[] = "size unknown"; +char UNKNOWN_ESCAPE_SEQUENCE[] = "unknown escape sequence"; + +char FP_REG_REQ[] = "FP register required"; +char FP_REG_NOT_ALLOWED[] = "FP register not allowed"; +char ILL_FP_REG[] = "illegal FP register"; +char ILL_FP_REG_PAIR[] = "illegal FP register pair"; +char JUNK_AFTER_OPERANDS[] = "junk after operands"; + +char ALREADY[] = "already defined"; +char UNSTABLE_LABEL[] = "label moved in last pass add -O?"; + +char REPNE_STRING[] = "CMPS or SCAS expected"; +char REP_STRING[] = "string instruction expected"; + +/* Warnings. */ +char CPUCLASH[] = "instruction illegal for current cpu"; +char SHORTB[] = "short branch would do"; diff --git a/Applications/as09/errors.h b/Applications/as09/errors.h new file mode 100644 index 00000000..451ac41f --- /dev/null +++ b/Applications/as09/errors.h @@ -0,0 +1,113 @@ + +#ifndef _H_ERRORS +#define _H_ERRORS +/* Error codes. */ + +/* Syntax errors. */ +EXTERN char COMEXP[]; /* "comma expected" */ +EXTERN char DELEXP[]; /* "delimiter expected" */ +EXTERN char FACEXP[]; /* "factor expected" */ +EXTERN char IREGEXP[]; /* "index register expected" */ +EXTERN char LABEXP[]; /* "label expected" */ +EXTERN char LPEXP[]; /* "left parentheses expected" */ +EXTERN char OPEXP[]; /* "opcode expected" */ +EXTERN char RBEXP[]; /* "right bracket expected" */ +EXTERN char REGEXP[]; /* "register expected" */ +EXTERN char RPEXP[]; /* "right parentheses expected" */ +EXTERN char SPEXP[]; /* "space expected" */ + +/* Expression errors. */ +EXTERN char ABSREQ[]; /* "absolute expression required" */ +EXTERN char NONIMPREQ[]; /* "non-imported expression required" */ +EXTERN char RELBAD[]; /* "relocation impossible" */ + +/* Label errors. */ +EXTERN char ILLAB[]; /* "illegal label" */ +EXTERN char MACUID[]; /* "MACRO used as identifier" */ +EXTERN char MISLAB[]; /* "missing label" */ +EXTERN char MNUID[]; /* "opcode used as identifier" */ +EXTERN char REGUID[]; /* "register used as identifier" */ +EXTERN char RELAB[]; /* "redefined label" */ +EXTERN char UNBLAB[]; /* "unbound label" */ +EXTERN char UNLAB[]; /* "undefined label" */ +EXTERN char VARLAB[]; /* "variable used as label" */ + +/* Addressing errors. */ +EXTERN char ABOUNDS[]; /* "address out of bounds" */ +EXTERN char DBOUNDS[]; /* "data out of bounds" */ +EXTERN char ILLMOD[]; /* "illegal address mode" */ +EXTERN char ILLREG[]; /* "illegal register" */ + +/* Control structure errors. */ +EXTERN char ELSEBAD[]; /* "no matching IF" */ +#define ELSEIFBAD ELSEBAD +EXTERN char ENDBBAD[]; /* "no matching BLOCK" */ +#define ENDIFBAD ELSEBAD +EXTERN char EOFBLOCK[]; /* "end of file in BLOCK" */ +EXTERN char EOFIF[]; /* "end of file in IF" */ +EXTERN char EOFLC[]; /* "location counter was undefined at end" */ +EXTERN char EOFMAC[]; /* "end of file in MACRO" */ +EXTERN char FAILERR[]; /* "user-generated error" */ + +/* Overflow errors. */ +EXTERN char BLOCKOV[]; /* "BLOCK stack overflow" */ +EXTERN char BWRAP[]; /* "binary file wrap-around" */ +EXTERN char COUNTOV[]; /* "counter overflow" */ +EXTERN char COUNTUN[]; /* "counter underflow" */ +EXTERN char GETOV[]; /* "GET stack overflow" */ +EXTERN char IFOV[]; /* "IF stack overflow" */ + +EXTERN char LINLONG[]; /* "line too long" */ +EXTERN char MACOV[]; /* "MACRO stack overflow" */ +EXTERN char OBJSYMOV[]; /* "object symbol table overflow" */ +EXTERN char OWRITE[]; /* "program overwrite" */ +EXTERN char PAROV[]; /* "parameter table overflow" */ +EXTERN char SYMOV[]; /* "symbol table overflow" */ +EXTERN char SYMOUTOV[]; /* "output symbol table overflow" */ + +/* I/O errors. */ +EXTERN char OBJOUT[]; /* "error writing object file" */ + +/* Miscellaneous errors. */ +EXTERN char AL_AX_EAX_EXP[]; /* "al ax or eax expected" */ +EXTERN char CTLINS[]; /* "control character in string" */ +EXTERN char FURTHER[]; /* "futher errors suppressed" */ +EXTERN char ILL_IMM_MODE[]; /* "illegal immediate mode" */ +EXTERN char ILL_IND_TO_IND[]; /* "illegal indirect to indirect" */ +EXTERN char ILL_IND[]; /* "illegal indirection" */ +EXTERN char ILL_IND_PTR[]; /* "illegal indirection from previous 'ptr'" */ +EXTERN char ILL_SCALE[]; /* "illegal scale" */ +EXTERN char ILL_SECTION[]; /* "illegal section" */ +EXTERN char ILL_SEG_REG[]; /* "illegal segment register" */ +EXTERN char ILL_SOURCE_EA[]; /* "illegal source effective address" */ +EXTERN char ILL_SIZE[]; /* "illegal size" */ +EXTERN char IMM_REQ[]; /* "immediate expression expected" */ +EXTERN char INDEX_REG_EXP[]; /* "index register expected" */ +EXTERN char IND_REQ[]; /* "indirect expression required" */ +EXTERN char MISMATCHED_SIZE[]; /* "mismatched size" */ +EXTERN char NOIMPORT[]; /* "no imports with binary file output" */ +EXTERN char REENTER[]; /* "multiple ENTER pseudo-ops" */ +EXTERN char REL_REQ[]; /* "relative expression required" */ +EXTERN char REPEATED_DISPL[]; /* "repeated displacement" */ +EXTERN char SEGREL[]; /* "segment or relocatability redefined" */ +EXTERN char SEG_REG_REQ[]; /* "segment register required" */ +EXTERN char SIZE_UNK[]; /* "size unknown" */ +EXTERN char UNKNOWN_ESCAPE_SEQUENCE[]; /* "unknown escape sequence" */ + +EXTERN char FP_REG_REQ[]; /* "FP register required" */ +EXTERN char FP_REG_NOT_ALLOWED[]; /* "FP register not allowed" */ +EXTERN char ILL_FP_REG[]; /* "illegal FP register" */ +EXTERN char ILL_FP_REG_PAIR[]; /* "illegal FP register pair" */ +EXTERN char JUNK_AFTER_OPERANDS[]; /* "junk after operands" */ + +EXTERN char ALREADY[]; /* "already defined" */ +EXTERN char UNSTABLE_LABEL[]; /* "label moved in last pass add -O?" */ + +EXTERN char REPNE_STRING[]; /* "CMPS or SCAS expected" */ +EXTERN char REP_STRING[]; /* "string instruction expected" */ + +/* Warnings. */ +EXTERN char CPUCLASH[]; /* "instruction illegal for current cpu" */ +EXTERN char SHORTB[]; /* "short branch would do" */ + +#endif diff --git a/Applications/as09/express.c b/Applications/as09/express.c new file mode 100644 index 00000000..a43a9194 --- /dev/null +++ b/Applications/as09/express.c @@ -0,0 +1,410 @@ +/* express.c - expression handler for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "address.h" +#include "globvar.h" +#include "scan.h" +#include "source.h" + +static void experror P((char * err_str)); +static void expundefined P((void)); +static void simple2 P((void)); +static void simple P((void)); +static void term P((void)); +static void factor2 P((void)); + +void absexpres(void) +{ + expres(); + chkabs(); +} + +/* check lastexp.data is abs */ + +void chkabs(void) +{ + if (lastexp.data & RELBIT) + { + if (pass == last_pass) + error(ABSREQ); + expundefined(); + } +} + +void experror(char *err_str) +{ + error(err_str); + expundefined(); +} + +void expundefined(void) +{ + if( last_pass == 1 ) + lastexp.data = FORBIT | UNDBIT; + else + lastexp.data = UNDBIT; +} + +void nonimpexpres(void) +{ + expres(); + if (lastexp.data & IMPBIT) + experror(NONIMPREQ); +} + +/* generate relocation error if pass 2, make lastexp.data forward&undefined */ + +void showrelbad(void) +{ + if (pass == last_pass) + error(RELBAD); + expundefined(); +} + +void symabsexpres(void) +{ + getsym(); + absexpres(); +} + +void symexpres(void) +{ + 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. +*/ + +void expres(void) +{ + 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 */ + +void simple2(void) +{ + 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). +*/ + +void simple(void) +{ + 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 >>. */ + +void term(void) +{ + 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 */ + +void factor2(void) +{ + 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. +*/ + +void factor(void) +{ + 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))) + { + if( last_pass == 1 ) + symptr->data |= FORBIT; + lastexp.sym = symptr; + } + if (pass != last_pass) + { + if( last_pass == 1 ) + lastexp.data = symptr->data & + (FORBIT | RELBIT | UNDBIT | SEGM); + else + lastexp.data = symptr->data & + (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; + } +#ifndef MC6809 + case LBRACKET: + if (!asld_compatible) + break; /* error, LPAREN is the grouping symbol */ + getsym(); + expres(); + if (sym != RBRACKET) + error(RBEXP); + else + getsym(); + return; +#endif + case LPAREN: +#ifndef MC6809 + if (asld_compatible) + break; /* error, LBRACKET is the grouping symbol */ +#endif + getsym(); + expres(); + if (sym != RPAREN) + error(RPEXP); + else + getsym(); + return; + case NOTOP: + getsym(); + factor(); + chkabs(); + lastexp.offset = ~lastexp.offset; + return; + case ADDOP: + getsym(); + factor(); + return; + case SUBOP: + 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 == last_pass) + experror(UNBLAB); + getsym(); + return; + } + experror(FACEXP); +} + +/* + string compare for IFC/ELSEIFC + expects (,) + returns logical value in lastexp +*/ + +void scompare(void) +{ + /* 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; + } + string2++; + while (*string1++ == *string2++) + ; + if (string2[-1] == ')') + { + if (string1[-1] == ',') + lastexp.offset = TRUE; /* else leave FALSE */ + lineptr = string2; + } + else /* FALSE, keep reading to verify syntax */ + { + for (; *string2 != ')'; ++string2) + if (*string2 == 0 || *string2 == ',') + { + symname = string2; + experror(RPEXP); + } + lineptr = ++string2; + } + getsym(); + } +} diff --git a/Applications/as09/file.h b/Applications/as09/file.h new file mode 100644 index 00000000..11dea710 --- /dev/null +++ b/Applications/as09/file.h @@ -0,0 +1,17 @@ +/* file.h - global variables involving files for assembler */ + +EXTERN char *filnamptr; /* file name pointer */ +EXTERN char *truefilename; /* in case actual source name is a tmpname */ + +EXTERN fd_t infil; /* current input file (stacked, 0 = memory) */ + +/* Output fds */ +EXTERN unsigned char outfd; /* output fd for writer fns */ +EXTERN fd_t binfil; /* binary output file (0 = memory) */ +EXTERN fd_t lstfil; /* list output file (0 = standard) */ +EXTERN fd_t objfil; /* object output file */ +EXTERN fd_t symfil; /* symbol table output file */ + +/* readsrc internals */ +EXTERN unsigned infil0; /* Number of first input area */ +EXTERN unsigned infiln; /* Number of current input area */ diff --git a/Applications/as09/flag.h b/Applications/as09/flag.h new file mode 100644 index 00000000..d9124e06 --- /dev/null +++ b/Applications/as09/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 as_warn; /* warnings on/off */ diff --git a/Applications/as09/genbin.c b/Applications/as09/genbin.c new file mode 100644 index 00000000..a6228e9b --- /dev/null +++ b/Applications/as09/genbin.c @@ -0,0 +1,272 @@ +/* genbin.c - binary code generation routines for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "address.h" +#include "file.h" +#include "globvar.h" + +#ifdef USE_FIXED_HEAP +static char *asmbeg; /* beginning of assembler code */ + /* for overwrite check */ + /* bss-init to zero = NULL and not changed */ +#endif + +/* Sneaky stuff, the start of a binary file can be _negative_ for the I80386 + assembler. The -ve addresses are ones over 2GB (or "org -32") */ +#ifdef I80386 +static soffset_t binfbuf; /* binary code buffer for file (counter) */ +static soffset_t binmax; /* maximum value of binmbuf for pass 1 */ +static soffset_t binmin; /* minimum value of binmbuf for pass 1 */ +#define PT soffset_t +#else +static offset_t binfbuf; /* binary code buffer for file (counter) */ +static offset_t binmax; /* maximum value of binmbuf for pass 1 */ +static offset_t binmin; /* minimum value of binmbuf for pass 1 */ +#define PT offset_t +#endif + +static void putbinoffset P((offset_t offset, count_t size)); + +/* write header to binary file */ + +void binheader(void) +{ +#ifdef BINSYM + if ((outfd = binfil) != 0x0 && binmbuf_set && binmax >= binmin) + { + 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 + } +#else + if ( ( outfd = symfil ) && binmbuf_set && binmax >= binmin) + { + int sft; + writec('+'); writec(' '); + for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) + writec(hexdigit[(binmin>>sft) & 0xF]); + writesn(" ----- $start"); + + writec('+'); writec(' '); + for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) + writec(hexdigit[(binmax>>sft) & 0xF]); + writesn(" ----- $end"); + + binfbuf = binmin; /* program start */ + } +#endif +} + +/* write trailer to binary file */ + +void bintrailer() +{ +#ifdef BINSYM + if ((outfd = binfil) != 0x0 && (pedata & UNDBIT) != UNDBIT && binmbuf_set) + { + 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 + } +#endif +} + +/* generate binary code for current line */ + +void genbin(void) +{ + 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 */ + +void initbin(void) +{ +#ifdef I80386 + binmin = ((offset_t)-1 >>1); /* greater than anything */ +#else + binmin = -1; /* greater than anything */ +#endif +} + +/* write char to binary file or directly to memory */ + +void putbin(opcode_pt ch) +{ + if (binfil != 0x0) + { + if (!binaryc) /* pass 1, just record limits */ + { + if ((PT)binmbuf < binmin) + binmin = binmbuf; + binmbuf++; + if ((PT)binmbuf > binmax) + binmax = binmbuf; + } + else + { +#if 0 + if (binfbuf > (PT)binmbuf) + { + error(BWRAP); /* file buffer ahead of memory buffer */ + } + else +#endif + { +#ifdef MSDOS +static PT zapptr = 0; +#endif + outfd = binfil; +#ifdef MSDOS + while (binfbuf < (PT)binmbuf && binfbuf >= zapptr+binmin) + { + writec(0); + ++binfbuf; + ++zapptr; + } +#endif + if( binfbuf != (PT)binmbuf) + if( lseek(binfil, (long)((PT)binmbuf-binfbuf), 1) < 0 ) + error(BWRAP); + binfbuf = binmbuf; + writec(ch); + binmbuf = ++binfbuf; + } + } + } +#ifdef USE_FIXED_HEAP + else if (binaryc && !(lcdata & UNDBIT)) + /* memory output, and enabled */ + { + register char *bufptr; + + if ((bufptr = (char *) binmbuf) >= asmbeg && bufptr < temp_buf()) + error(OWRITE); + else + *bufptr = ch; + ++binmbuf; + } +#endif +} + +/* write sized offset to binary file or directly to memory */ + +static void putbinoffset(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/Applications/as09/genlist.c b/Applications/as09/genlist.c new file mode 100644 index 00000000..82c13dd2 --- /dev/null +++ b/Applications/as09/genlist.c @@ -0,0 +1,468 @@ +/* genlist.c - generate listing and error reports for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "address.h" +#include "flag.h" +#include "file.h" +#include "globvar.h" +#include "macro.h" +#include "scan.h" +#include "source.h" + +#define CODE_LIST_LENGTH (sizeof (struct code_listing_s) - 1) + /* length of formatted code listing */ +#define MAXERR 6 /* maximum errors listed per line */ + +struct error_s /* to record error info */ +{ + char * err_str; + 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; +}; + +static struct error_s errbuf[MAXERR]; /* error buffer */ +static unsigned char errcount; /* # errors in line */ +static bool_t erroverflow; /* set if too many errors on line */ + +static char *build_1hex_number(opcode_pt num, char *where); +static void list1(fd_t fd); +static void listcode(void); +static void listerrors(void); +static void paderrorline(unsigned nspaces); + +/* format 1 byte number as 2 hex digits, return ptr to end */ + +static char *build_1hex_number(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 */ + +char *build_2hex_number(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 */ + +char *build_number(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) */ + +void warning(char * err_str) +{ + if (!as_warn.current) return; + ++totwarn; + --toterr; + error(err_str); +} + +void error(char *err_str) +{ + register struct error_s *errptr; + register struct error_s *errptrlow; + unsigned char position; + + if (errcount >= MAXERR) + erroverflow = TRUE; + else + { + position = symname - linebuf; + for (errptr = errbuf + errcount; + errptr > errbuf && errptr->position > position; + errptr = errptrlow) + { + errptrlow = errptr - 1; + errptr->err_str = errptrlow->err_str; + errptr->position = errptrlow->position; + } + errptr->err_str = err_str; + errptr->position = position; + ++errcount; + ++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 */ + +void listline(void) +{ + if (!listpre && lineptr != 0) + { + if (errcount || (list.current && (!macflag || mcount != 0)) || + (macflag && maclist.current) || list_force ) + list1(lstfil); + if (errcount) + { + if (lstfil != STDOUT) + list1(STDOUT); + errcount = 0; + erroverflow = FALSE; + } + } +} + +/* list 1 line unconditionally */ + +static void list1(fd_t fd) +{ + outfd = fd; + listcode(); + write(outfd, linebuf, (unsigned) (lineptr - linebuf)); + writenl(); + if (errcount != 0) + listerrors(); + listpre = TRUE; + list_force=FALSE; +} + +/* list object code for 1 line */ + +static void listcode(void) +{ + unsigned char count; + struct code_listing_s *listptr; + unsigned numlength; + char *numptr; + + listptr = (struct code_listing_s *) temp_buf(); + 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 */ + +static void listerrors(void) +{ + 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; + +#ifdef I80386 + paderrorline(1); +#else + paderrorline(CODE_LIST_LENGTH - LINUM_LEN); +#endif + 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 + { +#ifdef I80386 + if(errcol != CODE_LIST_LENGTH) + { + writenl(); paderrorline(1); + } + writes(errmsg = errptr->err_str); + errcol = strlen(errmsg)+LINUM_LEN+1; + column = 0; linep = linebuf; + errcolw = CODE_LIST_LENGTH; + while (errcolw > errcol) + { + writec('.'); + ++errcol; + } +#endif + while (errptr && errptr->position < 132 && column < errptr->position) + { + ++column; + if (*linep++ == '\t') /* next tab (standard tabs only) */ + errcolw = (errcolw + 8) & 0xf8; + else + ++errcolw; + while (errcolw > errcol) + { +#ifdef I80386 + writec('.'); +#else + writec(' '); +#endif + ++errcol; + } + } +#ifdef I80386 + writec('^'); ++errcol; +#else + if (errcolw < errcol) /* position under error on new line */ + { + writenl(); + paderrorline((unsigned) errcolw - LINUM_LEN); + } + writec('^'); + writes(errmsg = errptr->err_str); + errcol += strlen(errmsg); +#endif + ++errptr; + } + while (--remaining != 0); + writenl(); + if (erroverflow) + { +#ifdef I80386 + paderrorline(1); +#else + paderrorline(CODE_LIST_LENGTH - LINUM_LEN); +#endif + writesn(FURTHER); + } +} + +/* pad out error line to begin under 1st char of source listing */ + +static void paderrorline(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 */ + +void writec(char ch) +{ + write(outfd, &ch, 1); +} + +/* write newline */ + +void writenl(void) +{ + writes(SOS_EOLSTR); +} + +/* write 1 offset_t, order to suit target */ + +void writeoff(offset) +offset_t offset; +{ + char buf[sizeof offset]; + +#if SIZEOF_OFFSET_T > 2 + u4c4(buf, offset); +#else + u2c2(buf, offset); +#endif + write(outfd, buf, sizeof buf); +} + +/* write string */ + +void writes(const char *s) +{ + write(outfd, s, strlen(s)); +} + +/* write string followed by newline */ + +void writesn(const char *s) +{ + writes(s); + writenl(); +} + +/* write 1 word, order to suit target */ + +void writew(unsigned word) +{ + char buf[2]; + + u2c2(buf, (u16_T) word); + write(outfd, buf, sizeof buf); +} diff --git a/Applications/as09/genobj.c b/Applications/as09/genobj.c new file mode 100644 index 00000000..b4ba994e --- /dev/null +++ b/Applications/as09/genobj.c @@ -0,0 +1,672 @@ +/* genobj.c - object code generation routines for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "address.h" +#include "file.h" +#include "globvar.h" + +#define OBJBUFSIZE 512 /* size of object code output buffer */ +#define isge2byteoffset(offset) ((offset) >= 0x100) +#define isge4byteoffset(offset) ((offset) >= 0x10000L) + +static char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */ +static char *absbuf; /* start */ +static char *absbufend; /* last location + 1 */ +static char *absbufptr; /* current location */ +static struct sym_s **arrext; /* array of external symbol ptrs */ +static char hid_objbuf[OBJBUFSIZE]; /* object code buffer */ +static unsigned numext; /* number of external symbols */ +static char *objbuf; /* start */ +static char *objbufend; /* last location + 1 */ +static char *objbufptr; /* current location */ +static unsigned char relsize; /* current relocation size, 0 init */ + /* local to genobjadr, but here */ + /* because of static re-init bug */ +static offset_t rmbcount; /* accumulator for repeated RMB's */ + +static void flushabs(void); +static void flushrmb(void); +static void genobjadr(struct address_s *adrptr, smallcount_t size); +static void putobj1(opcode_pt ch); +static void putobj4(u32_T offset); +static void putobjoffset(offset_t offset, count_t size); +static void putobjword(unsigned word); +static void writeobj(char *buf, unsigned count); + +/* accumulate RMB requests into 1 (so + and - requests cancel) */ + +void accumulate_rmb(offset_t offset) +{ + if (objectc) + { + flushabs(); + rmbcount += offset; + } +} + +/* flush absolute object code buffer to object code buffer if necessary */ + +static void flushabs(void) +{ + 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 */ + +void flushobj(void) +{ + 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 */ + +static void flushrmb(void) +{ + 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 +*/ + +void genobj(void) +{ + 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 */ + +static void genobjadr(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 */ + +void initobj(void) +{ + 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 +*/ + +void objheader(void) +{ + 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; + int symcount = 0; + + 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 == NUL_PTR) + truefilename = filnamptr; + nameptr = strrchr(truefilename, DIRCHAR); + strcpy(module_name, nameptr != NUL_PTR ? nameptr + 1 : truefilename); + if ((nameptr = strrchr(module_name, '.')) != NUL_PTR) + *nameptr = 0; + strsiz = strlen(module_name) + 1; + + for (hashptr = spt; hashptr < spt_top;) + if ((symptr = *hashptr++) != NUL_PTR) + do + { + if ((symptr->type & EXPBIT || symptr->data & IMPBIT) || + (!globals_only_in_obj && symptr->name[0] != '.' && + !(symptr->type & (MNREGBIT | MACBIT | VARBIT)))) + { + symcount ++; + } + } + while ((symptr = symptr->next) != NUL_PTR); + arrext = copyptr = asalloc( sizeof(struct sym_s *) * symcount); + + for (hashptr = spt; hashptr < spt_top;) + if ((symptr = *hashptr++) != NUL_PTR) + do + { + if ((symptr->type & EXPBIT || symptr->data & IMPBIT) || + (!globals_only_in_obj && symptr->name[0] != '.' && + !(symptr->type & (MNREGBIT | MACBIT | VARBIT)))) + { + *copyptr++ = symptr; + strsiz += symptr->length + 1; + if (textseg>=0 && (symptr->data & SEGM) == textseg) + strsiz+=2; +#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) != NUL_PTR); + 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; + if (textseg>=0 && (symptr->data & SEGM) == textseg) + offset+=2; + } + + /* strings */ + + writeobj(module_name, strlen(module_name)); + putobj1(0); + for (copyptr = arrext; copyptr < copytop;) + { + symptr = *copyptr++; + writeobj(symptr->name, symptr->length); + if (textseg>=0 && (symptr->data & SEGM) == textseg) + { + putobj1('.'); + putobj1(hexdigit[textseg]); + } + putobj1(0); + } + putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */ +} + +/* write trailer to object file */ + +void objtrailer(void) +{ + if (objectc) + { + putobj(0); /* end of object file */ + flushobj(); + } +} + +/* write char to absolute object code buffer, flush if necessary */ + +void putabs(opcode_pt ch) +{ + if (objectc) + { + if (rmbcount != 0) + flushrmb(); + if (absbufptr >= absbufend) + flushabs(); + *absbufptr++ = ch; + } +} + +/* write char to object code buffer, flush if necessary */ + +void putobj(opcode_pt ch) +{ + if (objectc) + { + flushabs(); + flushrmb(); + putobj1(ch); + } +} + +/* write char to object code buffer assuming nothing in absolute & rmb bufs */ + +static void putobj1(opcode_pt ch) +{ + if (objbufptr >= objbufend) + flushobj(); + *objbufptr++ = ch; +} + +/* write 32 bit offset to object code buffer assuming ... */ + +static void putobj4(u32_T offset) +{ + char buf[sizeof offset]; + + u4c4(buf, offset); + writeobj(buf, 4); +} + +/* write sized offset to object code buffer assuming ... */ + +static void putobjoffset(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 ... */ + +static void putobjword(unsigned word) +{ + char buf[sizeof word]; + + u2c2(buf, word); + putobj1(buf[0]); + putobj1(buf[1]); +} + +/* write several bytes to object code buffer assuming ... */ + +static void writeobj(char *buf, unsigned count) +{ + do + putobj1(*buf++); + while (--count); +} diff --git a/Applications/as09/gensym.c b/Applications/as09/gensym.c new file mode 100644 index 00000000..fc20b00a --- /dev/null +++ b/Applications/as09/gensym.c @@ -0,0 +1,223 @@ +/* gensym.c - generate symbol table for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "flag.h" +#include "file.h" +#include "globvar.h" + +static int printsym(register struct sym_s *symptr, unsigned column); +static void sort(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 */ + +void gensym(void) +{ + 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 */ + struct sym_s **symlptr; /* start of symbol output list */ + register struct sym_s *symptr; +#ifdef BINSYM + unsigned label_stringptr; /* offset of label str from start of file */ +#endif + int symcount = 0; + + 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 */ + + for (hashptr = spt; hashptr < spt_top;) + if ((symptr = *hashptr++) != NUL_PTR) + do + if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) + symcount++; + while ((symptr = symptr->next) != NUL_PTR); + symlptr = copyptr = asalloc( sizeof(struct sym_s *) * symcount); + + for (hashptr = spt; hashptr < spt_top;) + if ((symptr = *hashptr++) != NUL_PTR) + do + if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) + { + *copyptr++ = symptr; + ++label_count; + labels_length += symptr->length + 3; /* 3 for type, value */ + } + while ((symptr = symptr->next) != NUL_PTR); + + sort(symlptr, copyptr, TRUE); /* sort on name */ + copytop = copyptr; + if (list.global) + { + outfd = lstfil; + writenl(); + writesn("Symbols:"); + for (copyptr = symlptr, column = 0; copyptr < copytop;) + column = printsym(*copyptr++, column); + if (column != 0) + writenl(); + } + if ((outfd = symfil) != 0) + { +#ifndef BINSYM + for (copyptr = symlptr; copyptr < copytop;) + /* for (copyptr = spt; copyptr < spt_top;) */ + { + int sft; + if((symptr = *copyptr++) == NUL_PTR ) continue; + if( globals_only_in_obj && + !(symptr->type & EXPBIT)) continue; + + writec(hexdigit[symptr->data & SEGM]); + writec(' '); + + for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) + writec(hexdigit[(symptr->value_reg_or_op.value>>sft) & 0xF]); + + writec(' '); + writec(symptr->type & EXPBIT ? 'E' : '-'); + writec(symptr->type & ENTBIT ? 'N' : '-'); + writec(symptr->data & IMPBIT ? 'I' : '-'); + writec(symptr->data & RELBIT ? 'R' : 'A'); + writec(symptr->type & COMMBIT ? 'C' : '-'); + + writec(' '); + write(outfd, symptr->name, (unsigned) (symptr->length)); + + /* printsym(*copyptr++, 0); */ + writenl(); + } +#else + 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(outfd, 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 */ + } +#endif + } +} + +/* print symbol nicely formatted for given column */ + +static int printsym(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 *) temp_buf(); + 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; /*(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 */ + +static void sort(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/Applications/as09/globvar.h b/Applications/as09/globvar.h new file mode 100644 index 00000000..edd9419e --- /dev/null +++ b/Applications/as09/globvar.h @@ -0,0 +1,124 @@ +/* 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 bool_t binmbuf_set; /* set to 1 when binmbuf set by org */ + +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 */ + +EXTERN bool_t list_force; /* Force line to be listed - no error */ + +/* bookeeping for current line */ + +EXTERN char *linebuf; /* buffer */ + +/* for symbol table routines */ + +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 */ + +EXTERN offset_t oldlabel; /* Used for checking for moving labels */ +#ifdef LOW_BYTE +#define mcount (((unsigned char *) &lcjump)[LOW_BYTE]) + /* low byte of lcjump */ +#else +#define mcount lcjump /* I think this is just a speed hack */ +#endif +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 */ +EXTERN int last_pass; /* Pass number of last pass */ +EXTERN int dirty_pass; /* Set if this pass had a label movement */ + +EXTERN int textseg; /* Text segment id */ + +#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 */ + +EXTERN int cpuid; /* Assembler instruction limit flag */ +EXTERN int origcpuid; /* Assembler instruction limit flag */ + +#endif + +/* miscellaneous */ + +extern char hexdigit[]; + +/* cpuid functions */ +#ifdef I80386 +#ifndef __AS386_16__ +#define iscpu(x) (cpuid>=(x)) +#define needcpu(x) do{ if(cpuid<(x)) {warning(CPUCLASH); cpuid|=0x10;} }while(0) +#define setcpu(x) (cpuid=(x)) +#define cpuwarn() (cpuid&=0xF) +#endif +#endif + +#ifndef setcpu +#define needcpu(x) +#define setcpu(x) +#define cpuwarn() +#endif + diff --git a/Applications/as09/keywords.c b/Applications/as09/keywords.c new file mode 100644 index 00000000..c61ea9db --- /dev/null +++ b/Applications/as09/keywords.c @@ -0,0 +1,746 @@ +/* keywords.c - keyword tables for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "globvar.h" +#include "opcode.h" + +/* --- start of keywords --- */ + +/* registers */ +/* the register code (internal to assembler) is given in 1 byte */ +/* the "opcode" field is not used */ + +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 */ + +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, + 4, 'N', 'E', 'A', 'R', WORDOP, 2, + 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) */ + +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, +#if SIZEOF_OFFSET_T > 2 + 6, '.', 'D', 'A', 'T', 'A', '4', FQBOP, 0, +#endif + 2, 'D', 'B', FCBOP, 0, +#if SIZEOF_OFFSET_T > 2 + 2, 'D', 'D', FQBOP, 0, +#endif + 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, + 6, '.', '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, + 7, '.', 'G', 'L', 'O', 'B', 'A', 'L', GLOBLOP, 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, +#if SIZEOF_OFFSET_T > 2 + 5, '.', 'L', 'O', 'N', 'G', FQBOP, 0, +#endif + 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, +#ifndef MC6809 + 5, 'U', 'S', 'E', '1', '6', USE16OP, 0, + 5, 'U', 'S', 'E', '3', '2', USE32OP, 0, +#endif + 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 */ +}; + +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, + 5, 'R', 'D', 'M', 'S', 'R', INHER, 0x32, + 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, + 5, 'W', 'R', 'M', 'S', 'R', INHER, 0x30, + 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 */ +}; + +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 +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 --- */ diff --git a/Applications/as09/macro.c b/Applications/as09/macro.c new file mode 100644 index 00000000..036bdc90 --- /dev/null +++ b/Applications/as09/macro.c @@ -0,0 +1,174 @@ +/* macro.c - expand macros for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "globvar.h" +#include "scan.h" +#undef EXTERN +#define EXTERN +#include "macro.h" + +/* + Enter macro: stack macro and get its parameters. + Parameters form a linked list of null-terminated strings of form + next:string. The first string is the macro number in 4 bytes. +*/ + +void entermac(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 = NUL_PTR; + *(stringptr = build_number(++macnum, 3, param1->string)) = 0; + macpar = (struct schain_s *) (stringptr + 1); + /* TODO: alignment */ + getsym(); + if (sym == EOLSYM) + return; /* no other params */ + if (sym != LPAREN) + reglineptr = symname; + else + 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 == ')' || ch == '!' || ch == ';' + || ch == '\n' || ch == 0) + { + if (stringptr >= (char *) macptop) + { + symname = reglineptr; + error(PAROV); /* no room for null */ + return; + } + *stringptr = 0; + param1->next = macpar; /* ptr from previous */ + (param1 = macpar)->next = NUL_PTR; + /* 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 */ + +void pmacro(void) +{ + bool_t saving; + bool_t savingc; + struct sym_s *symptr=0; + int maclen = 8; + int macoff = 0; + char * macbuf = asalloc(8); + + saving = /* prepare for bad macro */ + savingc = FALSE; /* normally don't save comments */ + macload = TRUE; /* show loading */ + if (label != NUL_PTR) + 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 != last_pass || 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 = (offset_t) macbuf; + 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 || strncmp(symname, "mend", 4) == 0) ) + { + getsym(); + break; + } + } + else if (sym != MACROARG) + { + if (!savingc) + continue; /* don't save comment */ + } + if (!saving) + continue; + { + char * p = strchr(linebuf, EOLCHAR); + int len = (p-linebuf+1); + + if ( macoff + len > maclen-4 ) + { + maclen = maclen * 2 + len; + macbuf = asrealloc(macbuf, maclen); + } + memcpy(macbuf+macoff, linebuf, len); + macoff += len; + + } + } + macload = FALSE; + if (saving) + { + macbuf[macoff] = ETB; + symptr->value_reg_or_op.value = (offset_t) macbuf; + symptr->data = 0; + } +} diff --git a/Applications/as09/macro.h b/Applications/as09/macro.h new file mode 100644 index 00000000..c37bd00e --- /dev/null +++ b/Applications/as09/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/Applications/as09/mops.c b/Applications/as09/mops.c new file mode 100644 index 00000000..73c3a4f4 --- /dev/null +++ b/Applications/as09/mops.c @@ -0,0 +1,2945 @@ +/* mops.c - handle pseudo-ops */ + +#include "syshead.h" +#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==last_pass) + +static void mshort2 P((void)); +static reg_pt regchk P((void)); +static void reldata P((void)); +static void segadj 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 + +static 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 */ +}; + +static 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) */ +}; + +static 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 */ +}; + +static 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 */ +}; + +static 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 */ +}; + +static opcode_t rmfunny[] = +{ + 0x06, /* BP */ + 0x07, /* BX */ + 0x05, /* DI */ + 0x04, /* SI */ +}; + +static opcode_t segoverride[] = +{ + 0x2E, /* CS */ + 0x3E, /* DS */ + 0x26, /* ES */ + 0x64, /* FS */ + 0x65, /* GS */ + 0x36, /* SS */ +}; + +static 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 */ +}; + +static unsigned char calljmp_kludge; +static opcode_t direction; +static bool_t fpreg_allowed; +static 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 +*/ + +static struct ea_s source; +static struct ea_s source2; +static struct ea_s target; + +static void Eb(struct ea_s *eap); +static void Ew(struct ea_s *eap); +static void Ev(struct ea_s *eap); +static void Ex(struct ea_s *eap); +static void Gd(struct ea_s *eap); +static void Gw(struct ea_s *eap); +static void Gv(struct ea_s *eap); +static void Gx(struct ea_s *eap); +static void buildea(struct ea_s *eap); +static void buildfloat(void); +static void buildfreg(void); +static void buildimm(struct ea_s *eap, bool_pt signflag); +static void buildregular(void); +static void buildsegword(struct ea_s *eap); +static void buildunary(opcode_pt opc); +static opsize_pt displsize(struct ea_s *eap); +static reg_pt fpregchk(void); +static bool_pt getaccumreg(struct ea_s *eap); +static void getbinary(void); +static bool_pt getdxreg(struct ea_s *eap); +static void getea(struct ea_s *eap); +static void getimmed(struct ea_s *eap, count_t immed_count); +static void getindirect(struct ea_s *eap); +static void getshift(struct ea_s *eap); +static reg_pt indregchk(reg_pt matchreg); +static void kgerror(char * err_str); +static void lbranch(int backamount); +static void notbytesize(struct ea_s *eap); +static void notimmed(struct ea_s *eap); +static void notindirect(struct ea_s *eap); +static void notsegorspecreg(struct ea_s *eap); +static void yesimmed(struct ea_s *eap); +static void yes_samesize(void); + +static 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); + } +} + +static 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); + } +} + +static void Ev(eap) +register struct ea_s *eap; +{ + Ex(eap); + notbytesize(eap); +} + +static void Ex(eap) +register struct ea_s *eap; +{ + getea(eap); + notimmed(eap); + notsegorspecreg(eap); +} + +static void Gd(eap) +register struct ea_s *eap; +{ + Gx(eap); + if (eap->size != 0x4) + kgerror(ILL_SIZE); +} + +static void Gw(eap) +register struct ea_s *eap; +{ + Gx(eap); + if (eap->size != 0x2) + kgerror(ILL_SIZE); +} + +static void Gv(eap) +register struct ea_s *eap; +{ + Gx(eap); + notbytesize(eap); +} + +static void Gx(eap) +register struct ea_s *eap; +{ + Ex(eap); + notindirect(eap); +} + +static 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]; + } + } + needcpu(asize==4?3:0); + 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; + } + } +} + +static void buildfloat(void) +{ + if (mcount != 0x0) + { + buildea(&source); + oprefix = 0x0; + postb |= (opcode & 0x07) << REG_SHIFT; + opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); + } +} + +static void buildfreg(void) +{ + mcount += 0x2; + oprefix = 0x0; + postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG); + opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); +} + +static 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(); + } + } +} + +static void buildregular(void) +{ + if (mcount != 0x0) + { + buildea(&target); + postb |= regbits[source.base]; + } +} + +/* Check size and build segword. */ + +static 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]; +} + +static void buildunary(opc) +opcode_pt opc; +{ + if (mcount != 0x0) + { + buildea(&target); + postb |= opcode; + opcode = opc; + } +} + +static 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; +} + +static reg_pt fpregchk(void) +{ + 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; +} + +static 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. +*/ + +static void getbinary(void) +{ + ++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); +} + +static 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 +*/ + +static 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( last_pass == 1 ) + 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; + needcpu(eap->size==4?3:0); + 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) + { + needcpu(3); + /* 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(); + } + /* RDB */ + else if (!leading_immed && defsize <= 0x2) + eap->indcount = 0x1; /* compatibility kludge */ + if (!leading_displ) + eap->displ = lastexp; + + needcpu(eap->size==4?3:0); +} + +static 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); + } +} + +static void getindirect(eap) +register struct ea_s *eap; +{ + getea(eap); + if (eap->indcount == 0x0) + kgerror(IND_REQ); +} + +static 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. +*/ + +static 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; +} + +static void kgerror(err_str) +char * err_str; +{ + error(err_str); + sprefix = oprefix = aprefix = mcount = 0x0; +} + +static void lbranch(backamount) +int backamount; +{ + mcount += defsize + 0x1; + segadj(); + if (pass2) + { + reldata(); + if (!(lastexp.data & (RELBIT | UNDBIT))) + { + lastexp.offset = lastexp.offset - lc - lcjump; + if ( last_pass<2 && backamount != 0x0 && + !(lastexp.data & IMPBIT) && + lastexp.offset + backamount < 0x80 + backamount) + warning(SHORTB); /* -0x8? to 0x7F, warning */ + } + } +} + +/* BCC (long branches emulated by short branch over & long jump) */ + +void mbcc(void) +{ + getea(&target); + if (target.indcount >= 0x2 || target.base != NOREG) + kgerror(REL_REQ); + else + { +#ifdef iscpu + if (iscpu(3)) +#else + if (defsize != 0x2) +#endif + { + 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 */ + +void mbswap(void) +{ + needcpu(4); + ++mcount; + Gd(&target); + opcode |= rm[target.base]; +} + +/* BR, CALL, J, JMP */ + +void mcall(void) +{ + opcode_pt far_diff; + bool_t indirect; + register struct sym_s *symptr; + + far_diff = 0x0; + if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT && + symptr->data & SIZEBIT ) + { + if(symptr->value_reg_or_op.op.routine == FAROP) + { + far_diff = 0x8; + getsym(); + } + if(symptr->value_reg_or_op.op.routine == WORDOP && + opcode == JMP_SHORT_OPCODE) + { + opcode = JMP_OPCODE; + getsym(); + } + } + indirect = FALSE; + + if (asld_compatible && defsize <= 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) + { + int tsize = target.size?target.size:defsize; + 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)) && + tsize == 0x2 && + (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) + datatoobig(); + mcount += tsize; + 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_diff; + opcode = 0xFF; + } + } + else if (opcode == JMP_SHORT_OPCODE) + { + if (jumps_long && + ((pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) || + (last_pass==1))) + { + 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 */ + +void mcalli(void) +{ + 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 + { + int tsize = target.size?target.size:defsize; + getcomma(); + getea(&source); + yesimmed(&source); + if (mcount != 0x0) + { + lastexp = target.displ; + if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && + tsize == 0x2 && + (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) + { + tsize=4; + if( tsize != defsize ) oprefix = 0x66; + /* datatoobig(); */ + } + needcpu(tsize==4?3:0); + mcount += tsize; + source.size = 0x2; + buildimm(&source, FALSE); + } + } +} + +/* DIV, IDIV, MUL */ + +void mdivmul(void) +{ + if (getaccumreg(&source)) + { + ++mcount; + getcomma(); + Ex(&target); + yes_samesize(); + buildunary(0xF6 | regsegword[source.base]); + } + else + mnegnot(); +} + +/* ENTER */ + +void menter(void) +{ + ++mcount; + getimmed(&target, 0x2); + getcomma(); + getimmed(&source, 0x1); + if (mcount != 0x0) + { + mcount += 2; + lastexp = target.displ; /* getimmed(&source) wiped it out */ + } + needcpu(1); +} + +/* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */ + +void mEwGw(void) +{ + ++mcount; + Ew(&target); + getcomma(); + Gw(&source); + oprefix = 0x0; + buildregular(); +} + +/* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */ + +void mExGx(void) +{ + ++mcount; + Ex(&target); + getcomma(); + Gx(&source); + yes_samesize(); + opcode |= segword; + buildregular(); +} + +void mf_inher(void) +{ + 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 */ + +void mf_m(void) +{ + ++mcount; + getindirect(&source); + if (source.size != 0x0) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* [fldcw fnstcw] mem2i */ + +void mf_m2(void) +{ + ++mcount; + getindirect(&source); + if (source.size != 0x0 && source.size != 0x2) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* fnstsw [mem2i ax] */ + +void mf_m2_ax(void) +{ + 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] */ + +void mf_m2_m4(void) +{ + ++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] */ + +void mf_m2_m4_m8(void) +{ + ++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)] */ + +void mf_m4_m8_optst(void) +{ + 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] */ + +void mf_m4_m8_stst(void) +{ + 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)] */ + +void mf_m4_m8_st(void) +{ + 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)] */ + +void mf_m4_m8_m10_st(void) +{ + 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 */ + +void mf_m10(void) +{ + ++mcount; + getindirect(&source); + if (source.size != 0xA) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* ffree st(i) */ + +void mf_st(void) +{ + target.base = fpregchk(); + if (target.base == NOREG) + kgerror(FP_REG_REQ); + buildfreg(); +} + +/* [fucom fucomp fxch] optional-st(i) */ + +void mf_optst(void) +{ + if (sym == EOLSYM) + { + target.base = ST1REG; + buildfreg(); + } + else + mf_st(); +} + +/* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */ + +void mf_stst(void) +{ + 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(); +} + +void mf_w_inher(void) +{ + sprefix = WAIT_OPCODE; + mf_inher(); +} + +/* [fsave fstenv] mem */ + +void mf_w_m(void) +{ + sprefix = WAIT_OPCODE; + mf_m(); +} + +/* fstcw mem2i */ + +void mf_w_m2(void) +{ + sprefix = WAIT_OPCODE; + mf_m2(); +} + +/* fstsw [mem2i ax] */ + +void mf_w_m2_ax(void) +{ + sprefix = WAIT_OPCODE; + mf_m2_ax(); +} + +/* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */ + +void mgroup1(void) +{ + 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 */ + +void mgroup2(void) +{ + ++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) + { + needcpu(1); + opcode -= 0x10; + source.size = 0x1; + buildimm(&source, FALSE); + } + } +} + +/* LLDT, LTR, SLDT, STR, VERR, VERW */ + +void mgroup6(void) +{ + needcpu(2); + ++mcount; + Ew(&target); + oprefix = 0x0; + buildunary(0x0); +} + +/* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */ + +void mgroup7(void) +{ + needcpu(2); /* I think INVLPG is actually 386 */ + ++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 */ + +void mgroup8(void) +{ + needcpu(3); + ++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*) */ + +void mGvEv(void) +{ + needcpu(2); + ++mcount; + Gv(&source); + getcomma(); + Ev(&target); + yes_samesize(); + buildregular(); +} + +/* bound [r16,m16&16 r32,m32&32] */ + +void mGvMa(void) +{ + ++mcount; + Gv(&source); + getcomma(); + getindirect(&target); + yes_samesize(); + buildregular(); +} + +/* LDS, LES, LFS, LGS, LSS */ + +void mGvMp(void) +{ + ++mcount; + Gv(&source); + getcomma(); + getindirect(&target); + if (target.size != 0x0 && target.size != 0x2 + source.size) + error(MISMATCHED_SIZE); + buildregular(); +} + +/* IMUL */ + +void mimul(void) +{ + ++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)) + { + needcpu(3); + 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 */ + +void min(void) +{ + ++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 */ + +void mincdec(void) +{ + ++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 */ + +void minher16(void) +{ + minher(); + if (defsize != 0x2) + oprefix = 0x66; +} + +/* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */ +/* MOVSD, OUTSD, SCASD, STOSD */ + +void minher32(void) +{ + minher(); + if (defsize != 0x4) + oprefix = 0x66; + needcpu(3); +} + +/* AAD, AAM */ + +void minhera(void) +{ + ++mcount; + if (sym == EOLSYM) + { + target.displ.offset = 0xA; + target.size = 0x1; + buildimm(&target, FALSE); + } + else + getimmed(&target, 0x1); +} + +/* INT */ + +void mint(void) +{ + ++mcount; + getimmed(&target, 0x1); + if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) && + (opcode_t) immadr.offset == 0x3) + { + immcount = 0x0; + opcode = 0xCC; + } +} + +/* JCC */ + +void mjcc(void) +{ + /* First look for j* near */ + if (sym == IDENT && + gsymptr->type & MNREGBIT && + gsymptr->data & SIZEBIT && + gsymptr->value_reg_or_op.op.routine == WORDOP && + opcode < 0x80) + { + getsym(); + getea(&target); + if (target.indcount >= 0x2 || target.base != NOREG) + kgerror(REL_REQ); + else + { + needcpu(3); + page = PAGE1_OPCODE; + ++mcount; + opcode += 0x10; + lbranch(0x84); + } + } + else if (!jumps_long || opcode > 0x80) /* above 0x80 means loop, not long */ + mshort(); + else /* mbcc */ + { + getea(&target); + lastexp = target.displ; + + if ( (pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) || + last_pass==1) + { + if (target.indcount >= 0x2 || target.base != NOREG) + kgerror(REL_REQ); + + aprefix = opcode ^ 0x1; /* kludged storage for short branch + over */ + oprefix = defsize + 0x1; + mcount += 0x2; + opcode = JMP_OPCODE; + lbranch(0x83); + mcount -= 0x2; + } + else + { + /* 8 bit */ + if (lastexp.data & IMPBIT) + { + error(NONIMPREQ); + lastexp.data = FORBIT | UNDBIT; + } + mshort2(); + } + } +} + +/* JCXZ, JECXZ */ + +void mjcxz(void) +{ + 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 */ + +void mlea(void) +{ + Gv(&source); /* back to front */ + getcomma(); + ++mcount; + getindirect(&target); + yes_samesize(); + buildregular(); +} + +/* MOV */ + +void mmov(void) +{ + 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; + needcpu(source.size==4?3:0); + } + 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)) + { + needcpu(3); + page = PAGE1_OPCODE; + ++mcount; + opcode = 0x0; + } + opcode |= direction | segword; + buildregular(); + } + } +} + +/* MOVSX, MOVZX */ + +void mmovx(void) +{ + ++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 */ + +void mnegnot(void) +{ + ++mcount; + Ex(&target); + buildsegword(&target); + buildunary(0xF6 | segword); +} + +/* OUT */ + +void mout(void) +{ + ++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 */ + +void mpushpop(void) +{ + 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 + { + needcpu(1); /* On 8086 PUSH does not allow immediate */ + opcode = 0x68; + if (oldopcode == POP_OPCODE) + ++opcode; + buildimm(&target, TRUE); + } + } + else + { + buildea(&target); + if (oldopcode == PUSH_OPCODE) + postb |= 0x6 << REG_SHIFT; + } + } +} + +/* RET, RETF */ + +void mret(void) +{ + ++mcount; + if (sym != EOLSYM) + { + --opcode; + getimmed(&target, 0x2); + } +} + +/* SEG CS/DS/ES/FS/GS/SS */ + +void mseg(void) +{ + reg_pt reg; + + if (regsegword[reg = regchk()] != SEGMOV) + error(SEG_REG_REQ); + else + { + getsym(); + ++mcount; + opcode = (segoverride - CSREG)[reg]; + } +} + +/* SETCC */ + +void msetcc(void) +{ + ++mcount; + Eb(&target); + if (mcount != 0x0) + buildea(&target); +} + +/* SHLD, SHRD */ + +void mshdouble(void) +{ + needcpu(3); + ++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. +*/ + +void mtest(void) +{ + 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. +*/ + +void mxchg(void) +{ + 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(); +} + +static void notbytesize(eap) +register struct ea_s *eap; +{ + if (eap->size == 0x1) + kgerror(ILL_SIZE); +} + +static void notimmed(eap) +register struct ea_s *eap; +{ + if (eap->indcount == 0x0 && eap->base == NOREG) + kgerror(ILL_IMM_MODE); +} + +static void notindirect(eap) +register struct ea_s *eap; +{ + if (eap->indcount != 0x0) + kgerror(ILL_IND); +} + +static void notsegorspecreg(eap) +register struct ea_s *eap; +{ + if (regsegword[eap->base] >= SEGMOV) + kgerror(ILLREG); +} + +static 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); +} + +static void yes_samesize(void) +{ + 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 */ + +static 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 */ +}; + +static 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 */ +}; + +static 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 */ +}; + +static 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 */ +}; + +static void checkpostinc(void); +static void doaltind(void); +static void do1altind(void); +static void fixupind(void); +static void getindexnopost(void); +static void inderror(char * err_str); +static reg_pt indreg(reg_pt maxindex); +static void predec1(void); +static void sustack(reg_pt stackreg); + +void checkpostinc(void) +{ + 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 */ + +void doaltind(void) +{ + mcount += 0x2; + if (sym == LBRACKET) + { + postb = INDIRECTBIT; + getsym(); + do1altind(); + if (sym != RBRACKET) + error(RBEXP); + } + else + do1altind(); +} + +void do1altind(void) +{ + 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 */ + warning(SHORTB); + } + } +} + +void fixupind(void) +{ + if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */ + { + if (opcode < 0x80) + opcode |= 0x60; + else + opcode |= 0x20; + } +} + +void getindexnopost(void) +{ + getsym(); + if (indreg(MAXINDREG) != NOREG) + fixupind(); +} + +void inderror(char *err_str) +{ + error(err_str); + 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 */ + +reg_pt indreg(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 */ + +void mall(void) +{ + if (sym == IMMEDIATE) + mimmed(); + else + malter(); +} + +/* alterable mode ops */ + +void malter(void) +{ + postb = 0x0; /* not yet indexed or indirect */ + doaltind(); +} + +/* indexed mode ops */ + +void mindex(void) +{ + postb = INDEXBIT; /* indexed but not yet indirect */ + doaltind(); +} + +/* immediate ops */ + +void mimmed(void) +{ + 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 */ + +void mlong(void) +{ + mcount += 0x3; /* may be 0x0 or 0x1 here */ + expres(); + segadj(); + if (pass2) + { + reldata(); + if (!(lastexp.data & (RELBIT | UNDBIT))) + { + lastexp.offset = lastexp.offset - lc - lcjump; + if ( last_pass<2 && !(lastexp.data & IMPBIT) && + lastexp.offset + 0x81 < 0x101) + warning(SHORTB); /* -0x81 to 0x7F, warning */ + } + } +} + +/* PSHS and PULS */ + +void msstak(void) +{ + sustack(SREG); +} + +/* TFR and EXG */ + +void mswap(void) +{ + 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 */ + +void mustak(void) +{ + sustack(UREG); +} + +void predec1(void) +{ + if (postb & INDIRECTBIT) + inderror(ILLMOD); /* single-dec indirect illegal */ + else + { + postb |= 0x82; + getindexnopost(); + } +} + +/* common routine for PSHS/PULS/PSHU/PULU */ + +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 */ + +void getcomma(void) +{ + 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 */ + +void minher(void) +{ + ++mcount; +} + +/* short branches */ + +void mshort(void) +{ + nonimpexpres(); + mshort2(); +} + +void mshort2(void) +{ + 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 */ + +reg_pt regchk(void) +{ + register struct sym_s *symptr; + + if (sym == IDENT) + { + if ((symptr = gsymptr)->type & MNREGBIT) + { + if (symptr->data & REGBIT) + { + int regno = symptr->value_reg_or_op.reg; +#ifdef I80386 + if (regno == ST0REG && !fpreg_allowed) + error(FP_REG_NOT_ALLOWED); + + /* Check cpu */ + needcpu((regno==FSREG||regno==GSREG)?3:0); + needcpu((regno>=EAXREG && regno<=ESPREG)?3:0); + needcpu((regno>=CR0REG && regno<=TR7REG)?3:0); +#endif + return regno; + } + } + else + if( last_pass == 1 ) + if (!(symptr->type & (LABIT | MACBIT | VARBIT))) + symptr->data |= FORBIT; /* show seen in advance */ + } + return NOREG; +} + +/* convert lastexp.data for PC relative */ + +void reldata(void) +{ + 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); +} + +void segadj(void) +{ + if ((lastexp.data & UNDBIT) && textseg >= 0 ) + { + lastexp.sym->data &= ~SEGM; + lastexp.sym->data |= (lcdata & SEGM); + } +} diff --git a/Applications/as09/obj1/calljmp.obj b/Applications/as09/obj1/calljmp.obj new file mode 100644 index 0000000000000000000000000000000000000000..522d6f72e203df5804db23642cbaea471c58932a GIT binary patch literal 200 zcmY+6I|{;J5QNuMR$?Kfut^uN(}0al8o|O!@Bku=AQ3!(wftwW^+LXF^G+~_829gV zXJ@AQnDenEgNcY3bx*z2({hYB(iRC#$HsaUMcdt87Ss7~Y%>^%7oI#NyHX#tzzcW> zuiy=QfKTuRzBhF3gKlki|FH0fQ{dz2SQ9X2#)K(z7A#rOw`%%e3}#>greF>hn6U&a G(3dZ=|6=a| literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/ea.obj b/Applications/as09/obj1/ea.obj new file mode 100644 index 0000000000000000000000000000000000000000..6b53beb6fcc9a680a70446d86eedc454a732382d GIT binary patch literal 472 zcmXYtJ95G>6h*}+N$(XDNF48aJD!Bb4vFu?Evve znP@JGM2jHSR4rv(iFWqN-uhsDv@Wer)@SQW7?|30rZxIuZl*Vlxf9pKH{yo4CGLoO zVr)Lp5Czc>_2~NZ5e8H}qnQ*#FVPIl!2&G73hdm;y^Dj3ql=S^vkhHcB)R4rH{5c^ zJ>TWoaRSz015%KIt-CtTF&Fp`NkF=a)_5@5h*D7|nu@lfTvR}1;%=8~pBtOsRhjyY P%;(gnf3D2^x{y@=X?3mf literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/each.obj b/Applications/as09/obj1/each.obj new file mode 100644 index 0000000000000000000000000000000000000000..5426253a42c02e7796e4028eabbbb572689c50ff GIT binary patch literal 715 zcmXv~O)ErU6h8O*h@sAc9g7L2P!^O0<=y!O_AWVD7_(tvXTvNcHi~>L22;kE^0o01 zp-4=($X>FRq3g5jy3hN*o98*_eV*r>PIAJchBhKf*hCy)cklwR6Shr7L@E~{8f&-u zoxTBzIYXo54915ks@m=&cacu1sNM_IBn294fqlB{)yRj29D%U97EYSxfgwAFq(S^j z#Lvxr{CsioyR@UfE-94~PHFl4e0{TD9!kB|5H86sc=I~YY6{^g>KBG&P-3y0=&j-s zwxEz)ZiM{0@OMSn*0EE-E4Hu(Tl(W7L`8D08@y}Co*~;HOva1FUN$9@c_iWBV(R~N zOxiJt?PO9LYfe^WZB6*tB<_QF*wYKD|9}|}1EdV!&(R@?$ES6e)BZ)(P5G)Vva i{oW9jPBUpwBZM*zWP*+fgBQ3|_*82Wzz6AS0i!>)m9Dt} literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/f.obj b/Applications/as09/obj1/f.obj new file mode 100644 index 0000000000000000000000000000000000000000..4dbe2d9468d3f619dd537813c316c22a1e657178 GIT binary patch literal 207 zcmWlMOHRWu6h#eQLKXm0X3fyUOu7lSz=VCUi8t(!Rd@$v=2Pdzb}3R@plbR5Aw5?| zx@UHIWF{xZn5)s_(X)}mJ@mObo%S}^;CtV@;KF|JsZK6beHFUUsn?=quydPiw5h?W zjSZfLmRcQ7>#4RWQ)#80(2BN_vZxar*JKJyZdtKr!yWfLuw}=dN1k}*g;y@#c;|yp czWC;cU;gH6i8*G8B^HT`xR7`=ZaHB70VfuMW&i*H literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/fadd.obj b/Applications/as09/obj1/fadd.obj new file mode 100644 index 0000000000000000000000000000000000000000..28b3dd41b963e7759618e6edbc78a6494383ef5c GIT binary patch literal 1069 zcmZuvT}V@57=Axf{40*yF)$40O?147=1rIcn{Af0Hr=15sipGmrb6b1MHlTbN)Ee- z@XCw2Q6WO3F6u%EU8aQM&k{u$%Tm;x#4K-)E86M(R{jL-;`yHMecto_Jm0z>5GWcW z0JbE6!+1LI2LMU7qigG*HEsYMd!DuZvS*pQmLGGx8 zy@&zhKR)kf# zC{K0;oN2B=!$DWToE7EK;O+xxDnOZ(>tpY%qxHig8Vf#0wNsjs=EPN1Rqu&w3`^qe zneOD0`L>jfv5t5rlQ>`!;v_&8h*O}$BPjF1FT6BCg%DL1s6TePt(a<)|=!ZJmdg_#|T`XlFPkOJzLbj zSwNLVT1BN8*E`DfM!DX|%rd<~g_v7cD*nP`Uwel8=>4!a`6=<__=kvp4ulOM%vxx` zTR_DnNTcav!6p9B9_d>RjrGIA2WeWzNa$;5J`@Rssh)~49J_A-;FBs0G0i7ycIV&5 zx*ZYuEc(OsjPhJhl;?Ck5k9!g`()nzQoe|au)&r-w)2q^$(zsHx3+v7bM_TgbYUgp z4@2Iz|05RPaYqJBlj{-Ik+h%D})N55ycm90~+LiV4I|ODsxG%*kO;h@Zs-k+h!oa|g3B>F`90~+LiV4I|FUl`1Fl110U|~*UH4$R12s06CILw^Zc-Ta! z@i2&&-oVbB-r&y6lHS0;lAhMc4isu+hs&fjv;R#8;!K8{X^b}+Z>BTwr>8OUrvnia bkj2cO&de`xQ{kq?O^%xyHzjTw+++X%wkIcS literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/group6.obj b/Applications/as09/obj1/group6.obj new file mode 100644 index 0000000000000000000000000000000000000000..27e81ae61020f5323cca608bf40e8baaa09f76b3 GIT binary patch literal 67 zcmZ47#>k+h!oa{F1H|k=90~+LiV4I|FUl`1Fk?`N;b*vz&d(su&mh3ha2v>SW8i1t M=4W^aWa=;g0A1_~$^ZZW literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/group7.obj b/Applications/as09/obj1/group7.obj new file mode 100644 index 0000000000000000000000000000000000000000..37af05115bf1a7a0db17c0ba48a27755dd249d78 GIT binary patch literal 82 zcmZ47#>k+h!oa|w4aDp~90~+LiV4I|FUl`1FlSK6PUmM7N5=e&0{o2jKoK_venxJ7 Q#t%TIIX|NTKjUKt0QwdTdjJ3c literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/imul.obj b/Applications/as09/obj1/imul.obj new file mode 100644 index 0000000000000000000000000000000000000000..34ef370cb1a5f2257b736f7457299dd2e7efb69d GIT binary patch literal 147 zcmZ47#>k+h#K6Fi3&gBI90~+LiV4Ke%q`7fP;mJ6`kP+b_t$CP^}fIUu9wEY{xA@; z0VyDvmVH<(Et^dYNCC-okc1dRI+#q$J|G4}X_>i)br{n!*>o5)4?md9!jQ=ZBEd>^ T82Q(;f_Q0}2Y}KCKuiVz74t7O literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/incdec.obj b/Applications/as09/obj1/incdec.obj new file mode 100644 index 0000000000000000000000000000000000000000..03f583aee1ef803ec0c4032e58436eed1027e751 GIT binary patch literal 146 zcmWlQxeWp_6hsY)L$^RcL>1oq-i@eWVJtSF3>u*k?)&Iy%x9#h(MWH$n~|DLl~RMC zg}Fp({NJl}zgYHaV!7jqM_#$-nFn5+*Nz$%5dwsWksw9p;I)l{Fiz4;4Bq(SlV9FB ey!qhAdE;o1qe6iaH5#<&U-RaV z(+nvx1H-{RyoJ@!0)l}lC<>ZLNC#IGWm%V@HwK);dsqvtAp{tMQlJ!4!Z{QOG5G^R Cx=L>V literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/inout.obj b/Applications/as09/obj1/inout.obj new file mode 100644 index 0000000000000000000000000000000000000000..58aa820fd628670a67c8f8bde57111f7d49b3b28 GIT binary patch literal 82 zcmWlM!3lss33&A`nrfGE88Li7|cnN+2l! literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/movspec.obj b/Applications/as09/obj1/movspec.obj new file mode 100644 index 0000000000000000000000000000000000000000..15eab78336eff0594947fec782a55a9207c54474 GIT binary patch literal 722 zcmWm1Np6!-5Jh2=5wo*}SFeg1u!?^Z%#jd71QHTUU>!(o#7W$wj~zR)o!II7-f^2a zj(Ob4`R?D}?{XhMHSsWu%HEcQfP}Yhg#&71qU` ziSxuNv4zf~%V-r%?xN3l3qQiI@GkyLSRe~qgk59-SwXgt+r^HtYwQVoAubTN zh`Z*zMxK?mp*@8DxF(0 q#Yx)U62~6?u0Pahl5rxZproRvVT+0N#QLySjAnMqi?XU4J(VxSjxam` literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/seg.obj b/Applications/as09/obj1/seg.obj new file mode 100644 index 0000000000000000000000000000000000000000..2ba948cfc670badb8ea817825abb73234b87b516 GIT binary patch literal 42 pcmZ47#>k+h$iTqB2E;5t90~+LiV4IoPEBV}aMQC>OG!0j004Dx1`+@O literal 0 HcmV?d00001 diff --git a/Applications/as09/obj1/shdouble.obj b/Applications/as09/obj1/shdouble.obj new file mode 100644 index 0000000000000000000000000000000000000000..ab757503974d0b2bcf2b320879947b9bab1a5028 GIT binary patch literal 106 zcmZ47#>k*$!oa{_48%e}90~+LipiLPk%5yzz=5$iBPG8yDJPY|)5piv-O(qQL7_N} xf5{C7AaRS}vrik7OX=_$Mc R@4?&fE_?`|z^CwecmZS=WWWFb literal 0 HcmV?d00001 diff --git a/Applications/as09/opcode.h b/Applications/as09/opcode.h new file mode 100644 index 00000000..1d91dc23 --- /dev/null +++ b/Applications/as09/opcode.h @@ -0,0 +1,159 @@ +/* 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, +#if SIZEOF_OFFSET_T > 2 + FQBOP, +#endif + 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/Applications/as09/pops.c b/Applications/as09/pops.c new file mode 100644 index 00000000..f3673353 --- /dev/null +++ b/Applications/as09/pops.c @@ -0,0 +1,1105 @@ +/* pops.c - handle pseudo-ops for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "address.h" +#include "flag.h" +#include "globvar.h" +#include "opcode.h" +#include "scan.h" + +static bool_t elseflag; /* set if ELSE/ELSEIF are enabled */ + /* depends on zero = FALSE init */ +static bool_t lcommflag; + +static void bumpsem P((struct flags_s *flagptr, int defval)); +static void constdata P((unsigned size)); +static void docomm P((void)); +static void doelseif P((pfv func)); +static void doequset P((unsigned char labits)); +static void doentexp P((unsigned char entbits, unsigned char impbits)); +static void dofcc P((void)); +static void doif P((pfv func)); +static struct sym_s *needlabel P((void)); +static void showredefinedlabel P((void)); +static void setloc P((unsigned seg)); + +static void bumpsem(flagptr, defval) +register struct flags_s *flagptr; +int defval; +{ + int newcount; + + if (flagptr->global && pass == last_pass) + { + /* bump semaphore count by an expression (default 1), */ + /* then set currentflag iff semaphore count is plus */ + if (sym == EOLSYM) + lastexp.offset = defval; + 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 */ + +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) */ + +void checkdatabounds(void) +{ + if (!(lastexp.data & UNDBIT) && + (offset_t) (lastexp.offset + 0x80) >= 0x180) + datatoobig(); +} + +/* allocate constant data (zero except for size 1), default zero for size 1 */ + +static void constdata(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); + } +} + +void datatoobig(void) +{ + error(DBOUNDS); +} + +/* common routine for COMM/.COMM */ + +static void docomm(void) +{ + 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 */ + if( last_pass == 1 ) + labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT); + else + labptr->data = (lcdata & SEGM) | (IMPBIT | RELBIT); + showlabel(); + } + } + lcommflag = FALSE; +} + +/* common routine for ELSEIF/ELSEIFC */ + +static void doelseif(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; + } + } + else + { + /* Skip to EOL */ + while (sym != EOLSYM) + getsym(); + } + } +} + +/* common routine for EQU/SET */ + +static void doequset(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) && !pass) + /* 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(); + + if(pass && !(labits & VARBIT) && labptr->value_reg_or_op.value != oldlabel) + { + dirty_pass = TRUE; + if( pass == last_pass ) + error(UNSTABLE_LABEL); + } +} + +/* common routine for ENTRY/EXPORT */ + +static void doentexp(unsigned char entbits, unsigned char impbits) +{ + struct sym_s *symptr; + + while (TRUE) + { + if ((symptr = needlabel()) != NUL_PTR) + { + if (symptr->type & COMMBIT) + error(ALREADY); + else if (impbits != 0) + { + if (pass == last_pass) + ; + else if (symptr->type & (EXPBIT | LABIT)) + symptr->type |= EXPBIT; + else + { + symptr->type |= REDBIT; + if (!(symptr->data & IMPBIT)) + symptr->data |= IMPBIT | SEGM; + } + } + else + { + if (pass == last_pass) + { + 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 */ + +static void dofcc(void) +{ + 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 */ + +static void doif(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 */ + } + } + else + { + /* Skip to EOL */ + while (sym != EOLSYM) + getsym(); + } + } +} + +void fatalerror(char *err_str) +{ + error(err_str); + skipline(); + listline(); + finishup(); +} + +/* swap position with label position, do error, put back posn */ +/* also clear label ptr */ + +void labelerror(char *err_str) +{ + 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(err_str); + gsymptr = oldgsymptr; + lineptr = oldlineptr; + sym = oldsym; + symname = oldsymname; + label = NUL_PTR; +} + +static struct sym_s *needlabel(void) +{ + register struct sym_s *symptr; + + if (sym != IDENT || + (symptr = gsymptr)->type & (MACBIT | MNREGBIT | VARBIT)) + { + error(LABEXP); + return NUL_PTR; + } + return symptr; +} + +/* .ALIGN pseudo-op */ + +void palign(void) +{ + 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 */ + +void pasciz(void) +{ + dofcc(); + databuf.fcbuf[mcount++] = 0; + fcflag = TRUE; + popflags = POPLO | POPLC; +} + +/* .BLKW pseudo-op */ + +void pblkw(void) +{ + constdata(2); +} + +/* BLOCK pseudo-op */ + +void pblock(void) +{ + 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 */ + +void pbss(void) +{ + setloc(BSSLOC); +} + +/* COMM pseudo-op */ + +void pcomm(void) +{ + if (label == NUL_PTR) + labelerror(MISLAB); + else if (label->type & VARBIT) + labelerror(VARLAB); /* variable cannot be COMM'd */ + else + docomm(); +} + +/* .COMM pseudo-op */ + +void pcomm1(void) +{ + static unsigned oldseg; + + if (label != NUL_PTR) + labelerror(ILLAB); + oldseg = lcdata & SEGM; + setloc(BSSLOC); + if ((label = needlabel()) != NUL_PTR && checksegrel(label)) + { + /* Like import. */ + if (label->type & (EXPBIT | LABIT)) + error(ALREADY); + else if( last_pass == 1 ) + label->data = lcdata | (FORBIT | IMPBIT | RELBIT); + else + label->data = lcdata | (IMPBIT | RELBIT); + getsym(); + getcomma(); + if (label->type & (EXPBIT | LABIT)) + absexpres(); /* just to check it */ + else + docomm(); + } + setloc(oldseg); +} + +/* .DATA pseudo-op */ + +void pdata(void) +{ + setloc(DATALOC); +} + +/* ELSE pseudo-op */ + +void pelse(void) +{ + if (iflevel == 0) + error(ELSEBAD); + else + { + ifflag = FALSE; /* assume ELSE disabled */ + if (elseflag) + { + ifflag = TRUE; /* ELSE enabled */ + elseflag = FALSE; + } + } +} + +/* ELSEIF pseudo-op */ + +void pelseif(void) +{ + doelseif(absexpres); +} + +/* ELSEIFC pseudo-op */ + +void pelsifc(void) +{ + doelseif(scompare); +} + +/* ENDB pseudo-op */ + +void pendb(void) +{ + if (label != NUL_PTR) + 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 */ + +void pendif(void) +{ + if (iflevel == 0) + error(ENDIFBAD); + else + { + ifflag = ifstak->ifflag; + elseflag = ifstak->elseflag; + ++ifstak; + --iflevel; + } +} + +/* ENTER pseudo-op */ + +void penter(void) +{ + if (!(pedata & UNDBIT)) + error(REENTER); + else + { + if (!((pedata = (pedata & ~UNDBIT) | lcdata) & UNDBIT)) + { + progent = lc; + popflags = POPLC; + } + } +} + +/* ENTRY pseudo-op */ + +void pentry(void) +{ + doentexp(ENTBIT, 0); +} + +/* EQU pseudo-op */ + +void pequ(void) +{ + register struct sym_s *labptr; + + if ((labptr = label) == NUL_PTR) + 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 */ + +void peven(void) +{ + popflags = POPLONG | POPHI | POPLO | POPLC; + accumulate_rmb(lcjump = lastexp.data = lc & 1); +} + +/* EXPORT pseudo-op */ + +void pexport(void) +{ + doentexp(0, 0); +} + +/* FAIL pseudo-op */ + +void pfail(void) +{ + if(pass==last_pass) error(FAILERR); +} + +/* FCB pseudo-op */ + +void pfcb(void) +{ + 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 */ + +void pfcc(void) +{ + dofcc(); + if (mcount != 0) + { + fcflag = TRUE; + popflags = POPLO | POPLC; + } +} + +/* FDB pseudo-op */ + +void pfdb(void) +{ + 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 */ + +void pfqb(void) +{ + 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 */ + +void pglobl(void) +{ + if (binaryg) + error(NOIMPORT); + doentexp(0, IMPBIT); +} + +/* IDENT pseudo-op (not complete) */ + +void pident(void) +{ + if (sym != IDENT) + error(LABEXP); + else + getsym_nolookup(); /* should save ident string */ +} + +/* IF pseudo-op */ + +void pif(void) +{ + doif(absexpres); +} + +/* IFC pseudo-op */ + +void pifc(void) +{ + doif(scompare); +} + +/* IMPORT pseudo-op */ + +void pimport(void) +{ + struct sym_s *symptr; + + if (binaryg) + error(NOIMPORT); + while (TRUE) + { + if ((symptr = needlabel()) != NUL_PTR && checksegrel(symptr)) + { + if (symptr->type & (COMMBIT | EXPBIT | LABIT)) + /* IMPORT is null if label (to be) declared */ + error(ALREADY); + else if( last_pass == 1 ) + /* get current segment from lcdata, no need to mask rest */ + symptr->data = lcdata | (FORBIT | IMPBIT | RELBIT); + else + symptr->data = lcdata | (IMPBIT | RELBIT); + } + getsym(); + if (sym != COMMA) + break; + getsym(); + } +} + +/* LCOMM pseudo-op */ + +void plcomm(void) +{ + lcommflag = TRUE; + pcomm(); +} + +/* .LCOMM pseudo-op */ + +void plcomm1(void) +{ + lcommflag = TRUE; + pcomm1(); +} + +/* .LIST pseudo-op */ + +void plist(void) +{ + bumpsem(&list, 1); +} + +/* .NOLIST pseudo-op */ + +void pnolist(void) +{ + bumpsem(&list, -1); +} + +/* LOC pseudo-op */ + +void ploc(void) +{ + if (label != NUL_PTR) + labelerror(ILLAB); + absexpres(); + if (!(lastexp.data & UNDBIT)) + { + if (lastexp.offset >= NLOC) + datatoobig(); + else + setloc((unsigned) lastexp.offset); + } +} + +/* .MACLIST pseudo-op */ + +void pmaclist(void) +{ + bumpsem(&maclist, 1); +} + +/* .MAP pseudo-op */ + +void pmap(void) +{ + absexpres(); + if (!(lastexp.data & UNDBIT)) + { + mapnum = lastexp.offset; + popflags = POPLO; + if (lastexp.offset >= 0x100) + datatoobig(); + } +} + +/* ORG pseudo-op */ + +void porg(void) +{ + if (label != NUL_PTR) + labelerror(ILLAB); + absexpres(); + if (!((lcdata = lastexp.data) & UNDBIT)) + { + accumulate_rmb(lastexp.offset - lc); + binmbuf = lc = lastexp.offset; + binmbuf_set = 1; + popflags = POPLC; + } +} + +/* RMB pseudo-op */ + +void prmb(void) +{ + constdata(1); +} + +/* .SECT pseudo-op */ + +void psect(void) +{ + if (label != NUL_PTR) + 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 */ + +void pset(void) +{ + register struct sym_s *labptr; + + if ((labptr = label) == NUL_PTR) + labelerror(MISLAB); + else if (labptr->type & COMMBIT) + labelerror(RELAB); /* common cannot be SET'd */ + else + doequset(labptr->type & LABIT ? 0 : VARBIT); +} + +/* SETDP pseudo-op */ + +void psetdp(void) +{ + absexpres(); + if (!(lastexp.data & UNDBIT)) + { + dirpag = lastexp.offset; + popflags = POPLO; + if (lastexp.offset >= 0x100) + datatoobig(); + } +} + +/* .TEXT pseudo-op */ + +void ptext(void) +{ + if( textseg <= 0 ) + setloc(TEXTLOC); + else + setloc(textseg); +} + +/* .WARN pseudo-op */ + +void pwarn(void) +{ + bumpsem(&as_warn, -1); +} + +#ifdef I80386 + +/* USE16 pseudo-op */ + +void puse16(void) +{ + defsize = 2; +#ifdef iscpu + if( sym != EOLSYM ) + { + absexpres(); + if (lastexp.data & UNDBIT) + return; + if( lastexp.offset > 8000 ) + setcpu((int) lastexp.offset / 100 % 10); + else if( lastexp.offset > 15 ) + setcpu((int) lastexp.offset / 100); + else + setcpu((int) lastexp.offset); + } +#endif +} + +/* USE16 pseudo-op */ + +void puse32(void) +{ + defsize = 4; +#ifdef iscpu + if(!iscpu(3)) setcpu(3); + if( sym != EOLSYM ) + { + absexpres(); + if (lastexp.data & UNDBIT) + return; + if( lastexp.offset > 15 ) + setcpu((int) lastexp.offset / 100); + else + setcpu((int) lastexp.offset); + } +#endif +} + +#endif + +/* show redefined label and error, and set REDBIT */ + +static void showredefinedlabel(void) +{ + register struct sym_s *labptr; + + labptr = label; /* showlabel() will kill label prematurely */ + showlabel(); + if (!(labptr->type & REDBIT)) + { + labptr->type |= REDBIT; + labelerror(RELAB); + } +} + +void showlabel(void) +{ + register struct sym_s *labptr; + + labptr = label; + lastexp.data = labptr->data; + lastexp.offset = labptr->value_reg_or_op.value; + popflags = POPLONG | POPHI | POPLO; + label = NUL_PTR; /* show handled by COMM, EQU or SET */ +} + +/* set location segment */ + +static void setloc(unsigned seg) +{ + if (pass == last_pass && 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/Applications/as09/proto.h b/Applications/as09/proto.h new file mode 100644 index 00000000..38786334 --- /dev/null +++ b/Applications/as09/proto.h @@ -0,0 +1,233 @@ +/* extern functions */ + +/* as.c */ +int main(int argc, char **argv); +void as_abort(char *message); +void finishup(void); +void initp1p2(void); +void line_zero(void); + +/* assemble.c */ +void assemble(void); + +/* express.c */ +void absexpres(void); +void chkabs(void); +void nonimpexpres(void); +void showrelbad(void); +void symabsexpres(void); +void symexpres(void); +void expres(void); +void factor(void); +void scompare(void); + +/* genbin.c */ +void binheader(void); +void bintrailer(void); +void genbin(void); +void initbin(void); +void putbin(int ch); + +/* genlist.c */ +char *build_2hex_number(unsigned num, char *where); +char *build_number(unsigned num, unsigned width, char *where); +void warning(char * errorstr); +void error(char * errorstr); +void listline(void); +void writec(char ch); +void writenl(void); +void writeoff(offset_t offset); +void writes(const char *s); +void writesn(const char *s); +void writew(unsigned word); + +/* genobj.c */ +void accumulate_rmb(offset_t offset); +void flushobj(void); +void genobj(void); +void initobj(void); +void objheader(void); +void objtrailer(void); +void putabs(opcode_pt ch); +void putobj(opcode_pt ch); + +/* gensym.c */ +void gensym(void); + +/* macro.c */ +void entermac(struct sym_s *symptr); +void pmacro(void); + +/* mops.c */ +#ifdef I80386 +void mbcc(void); +void mbswap(void); +void mcall(void); +void mcalli(void); +void mdivmul(void); +void menter(void); +void mEwGw(void); +void mExGx(void); +void mf_inher(void); +void mf_m(void); +void mf_m2(void); +void mf_m2_ax(void); +void mf_m2_m4(void); +void mf_m2_m4_m8(void); +void mf_m4_m8_optst(void); +void mf_m4_m8_st(void); +void mf_m4_m8_stst(void); +void mf_m4_m8_m10_st(void); +void mf_m10(void); +void mf_optst(void); +void mf_st(void); +void mf_stst(void); +void mf_w_inher(void); +void mf_w_m(void); +void mf_w_m2(void); +void mf_w_m2_ax(void); +void mgroup1(void); +void mgroup2(void); +void mgroup6(void); +void mgroup7(void); +void mgroup8(void); +void mGvEv(void); +void mGvMa(void); +void mGvMp(void); +void mimul(void); +void min(void); +void mincdec(void); +void minher(void); +void minher16(void); +void minher32(void); +void minhera(void); +void mint(void); +void mjcc(void); +void mjcxz(void); +void mlea(void); +void mmov(void); +void mmovx(void); +void mnegnot(void); +void mout(void); +void mpushpop(void); +void mret(void); +void mseg(void); +void msetcc(void); +void mshdouble(void); +void mtest(void); +void mxchg(void); +#endif /* I80386 */ + +#ifdef MC6809 +void mall(void); +void malter(void); +void mimmed(void); +void mindex(void); +void minher(void); +void mlong(void); +void msstak(void); +void mswap(void); +void mustak(void); +#endif /* MC6809 */ + +void getcomma(void); +void mshort(void); + +/* pops.c */ +bool_pt checksegrel(struct sym_s *symptr); +void checkdatabounds(void); +void datatoobig(void); +void fatalerror(char * errorstr); +void labelerror(char * errorstr); +void palign(void); +void pasciz(void); +void pblkw(void); +void pblock(void); +void pbss(void); +void pcomm(void); +void pcomm1(void); +void pdata(void); +void pelse(void); +void pelseif(void); +void pelsifc(void); +void pendb(void); +void pendif(void); +void penter(void); +void pentry(void); +void pequ(void); +void peven(void); +void pexport(void); +void pfail(void); +void pfcb(void); +void pfcc(void); +void pfdb(void); +#if SIZEOF_OFFSET_T > 2 +void pfqb(void); +#endif +void pglobl(void); +void pident(void); +void pif(void); +void pifc(void); +void pimport(void); +void plcomm(void); +void plcomm1(void); +void plist(void); +void pnolist(void); +void ploc(void); +void pmaclist(void); +void pmap(void); +void porg(void); +void prmb(void); +void psect(void); +void pset(void); +void psetdp(void); +void ptext(void); +void puse16(void); +void puse32(void); +void pwarn(void); +void showlabel(void); + +/* readsrc.c */ +void initsource(void); +fd_t open_input(char *name); +void pget(void); +void pproceof(void); +void readline(void); +void skipline(void); + +/* scan.c */ +void context_hexconst(void); +void getsym(void); +void getsym_nolookup(void); +void initscan(void); + +/* table.c */ +void inst_keywords(void); +struct sym_s *lookup(void); +void statistics(void); + +/* type.c */ +#if defined(__m6809__) && defined(MC6809) +#define NATIVE_ENDIAN +extern inline u2_pt c2u2(char *buf) { return *((u2_pt *)buf); } +extern inline u4_t c4u4(char *buf) { return *((u4_t *)buf); } +extern inline void u2c2(char *buf, u2_t offset) { *((unsigned short *)buf) = offset;} +extern inline void u4c4(char *buf, u4_t offset) { *((unsigned long *)buf) = offset;} +#else +u2_pt c2u2(char *buf); +u4_t c4u4(char *buf); +void u2c2(char *buf, u2_t offset); +void u4c4(char *buf, u32_T offset); +#endif +u2_pt cnu2(char *buf, unsigned count); +u4_t cnu4(char *buf, unsigned count); +void u2cn(char *buf, u16_pt offset, unsigned count); +void u4cn(char *buf, u32_T offset, unsigned count); +bool_pt typeconv_init(bool_pt big_endian, bool_pt long_big_endian); + +/* alloc.c */ +void * asalloc(unsigned int size); +void * asrealloc(void * oldptr, unsigned int size); +void * temp_buf(void); +void init_heap(void); + diff --git a/Applications/as09/readsrc.c b/Applications/as09/readsrc.c new file mode 100644 index 00000000..79b53e40 --- /dev/null +++ b/Applications/as09/readsrc.c @@ -0,0 +1,494 @@ +/* readsrc.c - read source files for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "flag.h" +#include "file.h" +#include "globvar.h" +#include "macro.h" +#include "scan.h" +#undef EXTERN +#define EXTERN +#include "source.h" + +/* + * Ok, lots of hack & slash here. + * 1) Added BIG buffer to load entire _primary_ file into memory. + * 2) This means the primary file can be standard input. + * 3) Fixed so 'get/include' processing now works. + * 4) Altered for a 'normal' style buffer otherwise (MINIBUF) + * 5) Have the option of completely unbuffered if you need the last Kb. + * + * RDB. + */ + +#if !defined(__AS386_16__) && !defined(__m6809__) +#ifndef BIGBUFFER +#define BIGBUFFER 1 /* For most machines we have the memory */ +#endif +#endif + +#if !defined(__m6809__) +#ifndef MINIBUF +#define MINIBUF 1 /* Add in a reasonable buffer */ +#endif +#endif + +struct get_s /* to record included files */ +{ + fd_t fd; + unsigned line; + off_t position; +}; + +static char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */ + +static struct get_s hid_getstak[MAXGET]; /* GET stack */ +static struct get_s *getstak; /* ptr */ + +#if BIGBUFFER == 1 +static char *mem_start = 0, *mem_end; +#endif + +static char hid_linebuf[LINLEN]; /* line buffer */ +static char *eol_ptr; + +static char *maclinebuf; +static char *maclineptr; + +#if MINIBUF == 1 +static void inp_seek(int fd, long posn); +static long inp_tell(int fd); +static int inp_line(int fd, char * buf, int size); +#endif + +static void clearsource(void); +static void line_too_long(void); + +static void clearsource(void) +{ +} + +static void line_too_long(void) +{ + symname = linebuf + (LINLEN - 1); /* spot for the error */ + error(LINLONG); /* so error is shown in column LINLEN - 1 */ +} + +/* initialise private variables */ + +void initsource(void) +{ + filnamptr = hid_filnambuf; + getstak = hid_getstak; + clearsource(); /* sentinel to invoke blank skipping */ +} + +fd_t open_input(char *name) +{ + fd_t fd; +#if BIGBUFFER == 1 + off_t filelength = -1; + + if( mem_start == 0 && strcmp(name, "-") == 0 ) + fd = 0; + else +#endif +#ifdef O_BINARY + if ((unsigned) (fd = open(name, O_RDONLY|O_BINARY)) > 255) + as_abort("error opening input file"); +#else + if ((unsigned) (fd = open(name, O_RDONLY)) > 255) + as_abort("error opening input file"); +#endif + +#if BIGBUFFER == 1 + if( mem_start == 0 ) + { + size_t memsize = 0; + int cc; + + if(fd) + { + struct stat st; + if( fstat(fd, &st) >= 0 ) + filelength = st.st_size; + if( filelength > (((unsigned)-1)>>1)-3 ) + { + mem_end = mem_start = "\n\n"; + goto cant_do_this; + } + } + + if (filelength > 0) { + if( (mem_start = malloc(filelength+4)) == 0 ) + { + mem_end = mem_start = "\n\n"; + goto cant_do_this; + } + memsize = filelength; + + filelength = read(fd, mem_start, filelength); + } else + filelength = 0; + + for(;;) + { + if( filelength >= memsize ) + { + if (memsize > 16000) + mem_start = asrealloc(mem_start, (memsize+=16384)+4); + else + mem_start = asrealloc(mem_start, (memsize+=memsize+32)+4); + } + cc = read(fd, mem_start+filelength, + (size_t)(memsize-filelength)); + if( cc <= 0 ) break; + filelength+=cc; + } + + *(mem_end=mem_start+filelength) = '\n'; + mem_end[1] = '\0'; + + infiln = infil0 = 0; /* Assemble from memory */ + if(fd) close(fd); + fd = -1; + } +cant_do_this: +#endif + + 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 +*/ + +void pget(void) +{ + if (infiln >= MAXGET) + error(GETOV); + else + { + char save; + + skipline(); + listline(); + + getstak->fd = infil; + getstak->line = linum; + if (infiln != 0) +#if MINIBUF == 1 + getstak->position = inp_tell(infil); +#else + getstak->position = lseek(infil, 0L, 1); +#endif + else + getstak->position = (off_t)eol_ptr; + ++getstak; + ++infiln; + linum = 0; + + for(lineptr=symname; *lineptr != EOLCHAR; lineptr++) + if( *lineptr <= ' ' ) break; + save = *lineptr; *lineptr = '\0'; + infil = open_input(symname); + *lineptr = save; + getsym(); + } +} + +/* 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 */ + +void pproceof(void) +{ + if (infiln != 0) + close(infil); + 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 (pass && (lcdata & UNDBIT)) + error(EOFLC); + lcptr->data = lcdata; + lcptr->lc = lc; + } + /* macros must be closed before end of all files */ + if (macload) + error(EOFMAC); + if (linebuf != lineptr) + listline(); /* last line or line after last if error */ + if (infiln != infil0) + { + --getstak; + infil = getstak->fd; + linum = getstak->line; + if (--infiln == 0) + eol_ptr = (void*)getstak->position; + else +#if MINIBUF == 1 + inp_seek(infil, getstak->position); +#else + lseek(infil, getstak->position, 0); +#endif + } + else if (pass!=last_pass) + { + pass++; + if( last_pass>1 && last_pass<30 && dirty_pass && pass==last_pass ) + last_pass++; + + if( pass==last_pass ) + objheader(); /* while pass 1 data all valid */ + binmbuf = 0; /* reset zero variables */ + maclevel = iflevel = blocklevel = + totwarn = toterr = linum = macnum = 0; + initp1p2(); /* reset other varaiables */ + if(pass==last_pass) + binaryc = binaryg; +#ifdef I80386 + defsize = idefsize; + cpuid = origcpuid; +#endif + if(pass==last_pass) + { + list.current = list.global; + maclist.current = maclist.global; + as_warn.current = TRUE; + if (as_warn.semaphore < 0) + as_warn.current = FALSE; + } + + if (infiln != 0) + infil = open_input(filnamptr); + else + eol_ptr=0; + + if(pass==last_pass) + binheader(); + + line_zero(); + } + 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. +*/ + +void readline(void) +{ + int cc = 0; + + 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 int 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) == NUL_PTR) + break; + if (parameters != NUL_PTR) + { + 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; +#if 0 + *reglineptr = 0; + printf("MLINE:%s.\n", lineptr); +#endif + *reglineptr = EOLCHAR; + return; + } + } + if (macflag) + { + linebuf = maclinebuf; + lineptr = maclineptr; + macflag = FALSE; + } + /* End of macro expansion processing */ + +again: /* On EOF for main or included files */ + ++linum; + +#if BIGBUFFER == 1 + if( infiln == 0 ) + { + if( eol_ptr == 0 ) eol_ptr = mem_start-1; + else *eol_ptr = '\n'; + linebuf = lineptr = eol_ptr + 1; + cc = (mem_end - linebuf); + + /* memchr not strchr 'cause some implementations of strchr are like: + memchr(x,y,strlen(x)); this is _BAD_ with BIGBUFFER + */ + if((eol_ptr = memchr(linebuf, '\n', cc)) == 0 && cc > 0) + cc = -1; + } + else +#endif + { + lineptr = linebuf = hid_linebuf; + *(hid_linebuf+sizeof(hid_linebuf)-2) = '\0'; /* Term */ + +#if MINIBUF == 1 + cc = inp_line(infil, linebuf, sizeof(hid_linebuf)-2); + if( cc >= 0 ) + eol_ptr = linebuf+cc-1; +#else + cc = read(infil, linebuf, sizeof(hid_linebuf)-2); + if( cc > 0 ) + { + eol_ptr = memchr(linebuf, '\n', cc); + if( eol_ptr == 0 ) + eol_ptr = hid_linebuf+sizeof(hid_linebuf)-2; + else + lseek(infil, (long)(eol_ptr+1-hid_linebuf)-cc, 1); + } +#endif + } + + if( cc <= 0 ) + { + if( cc < 0 ) as_abort("error reading input"); + + clearsource(); + pproceof(); + listpre = FALSE; + if (macload) + { + symname = lineptr; + return; /* macro not allowed across eof */ + } + goto again; + } + +#if 0 + *eol_ptr = 0; + printf("LINE:%s.\n", lineptr); +#endif + *eol_ptr = EOLCHAR; +} + +void skipline(void) +{ + if(macflag) + lineptr = strchr(hid_linebuf, EOLCHAR); + else + lineptr = eol_ptr; +} + +#if MINIBUF == 1 +static char input_buf[1024]; /* input buffer */ +static int in_start=0, in_end=0; +static long ftpos = 0; +static int lastfd = -1; + +static int inp_line(int fd, char *buf, int size) +{ + int offt = 0; + if( fd!=lastfd ) inp_seek(-1, 0L); + for(;;) + { + if(in_start >= in_end) + { + lastfd = -1; + ftpos = lseek(fd, 0L, 1); + in_start = 0; + in_end = read(fd, input_buf, sizeof(input_buf)); + if( in_end <=0 ) return in_end; + lastfd = fd; + } + if( (buf[offt++] = input_buf[in_start++]) == '\n' || offt >= size ) + break; + } + return offt; +} + +static long inp_tell(int fd) +{ + if( fd != lastfd ) + return lseek(fd, 0L, 1); + else + return ftpos + in_start; +} + +static void inp_seek(int fd, long posn) +{ + if( lastfd != -1 ) + lseek(lastfd, ftpos+in_start, 0); + lastfd = -1; + in_end = 0; + if( fd >= 0 ) + lseek(fd, posn, 0); +} + +#endif diff --git a/Applications/as09/scan.c b/Applications/as09/scan.c new file mode 100644 index 00000000..0115677a --- /dev/null +++ b/Applications/as09/scan.c @@ -0,0 +1,252 @@ +/* scan.c - lexical analyser for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "globvar.h" +#undef EXTERN +#define EXTERN +#include "scan.h" + +static int numbase; /* base for number */ + +static char symofchar[256] = /* table to convert chars to their symbols */ +{ + EOLSYM, 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 +}; + +static void intconst P((void)); + +void context_hexconst(void) +{ + numbase = 16; + intconst(); +} + +void getsym(void) +{ + 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; +} + +void getsym_nolookup(void) +{ + bool_t old_ifflag; + + old_ifflag = ifflag; + ifflag = FALSE; + getsym(); + ifflag = old_ifflag; +} + +static void intconst(void) +{ + 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; +} + +void initscan(void) +{ +#ifndef MC6809 + if (asld_compatible) + { + lindirect = LPAREN; + rindexp = RPEXP; + rindirect = RPAREN; + } + else + { +#endif + lindirect = LBRACKET; + rindexp = RBEXP; + rindirect = RBRACKET; +#ifndef MC6809 + } +#endif +} diff --git a/Applications/as09/scan.h b/Applications/as09/scan.h new file mode 100644 index 00000000..baffefb9 --- /dev/null +++ b/Applications/as09/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 char * 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/Applications/as09/source.h b/Applications/as09/source.h new file mode 100644 index 00000000..0181e54d --- /dev/null +++ b/Applications/as09/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/Applications/as09/syshead.h b/Applications/as09/syshead.h new file mode 100644 index 00000000..82d2cc95 --- /dev/null +++ b/Applications/as09/syshead.h @@ -0,0 +1,62 @@ + +#ifndef POSIX_HEADERS_MISSING +#include +#include +#include +#include +#endif + +#ifndef STDC_HEADERS_MISSING +#include +#include +#include +#endif + +#ifdef MSDOS +#include +#include +#include +#include +#undef min +#undef POSIX_HEADERS_MISSING +#define VERSION "MSDOS Compile" +#endif + +#if __STDC__ && !defined(__minix) +#define P(x) x +#else +#define P(x) () +#endif + +#ifdef STDC_HEADERS_MISSING +char *strcpy P((char *s1, const char *s2)); +char *strrchr P((const char *s, int c)); +int memcmp P((const void *s1, const void *s2, unsigned n)); +int strcmp P((const char *s1, const char *s2)); +int strncmp P((const char *s1, const char *s2, unsigned n)); +unsigned strlen P((const char *s)); +void *malloc P((unsigned size)); +void *memset P((void *s, int c, unsigned n)); +void exit P((int status)); +#endif + +#ifdef POSIX_HEADERS_MISSING +int close P((int fd)); +int creat P((const char *path, int mode)); +int open P((const char *path, int oflag, ...)); +int read P((int fd, void *buf, unsigned nbytes)); +int write P((int fd, const void *buf, unsigned nbytes)); +typedef long off_t; +off_t lseek P((int fd, off_t offset, int whence)); +#define BIGBUFFER 0 /* Can't use a big buffer ... sorry */ +#endif + +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif +#ifndef O_WRONLY +#define O_WRONLY 1 +#endif +#ifndef O_RDWR +#define O_RDWR 2 +#endif diff --git a/Applications/as09/table.c b/Applications/as09/table.c new file mode 100644 index 00000000..fa135d85 --- /dev/null +++ b/Applications/as09/table.c @@ -0,0 +1,216 @@ +/* table.c - keyword tables and symbol table lookup for assembler */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "globvar.h" +#include "opcode.h" +#include "scan.h" + +#define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */ + +#ifdef I80386 +# ifdef MNSIZE +EXTERN char bytesizeops[]; +# endif +#endif +EXTERN char ops[]; +EXTERN char page1ops[]; +EXTERN char page2ops[]; +EXTERN char regs[]; +#ifdef I80386 +EXTERN char typesizes[]; +#endif + +#ifdef DEBUG_HASH +unsigned nhash; +unsigned nlookup; +unsigned nsym; +unsigned nx[30]; +static void printchain P((void)); +#endif + +static void install P((register char *keyptr, unsigned char data)); + +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 +} + +static void install(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 (NUL_PTR if not found and not installed) + * unless symbol table overflows, when routine aborts. + */ + +struct sym_s *lookup(void) +{ + struct sym_s **hashptr; + register char *nameptr; + register struct sym_s *symptr; + register unsigned hashval; + register unsigned length; +#ifdef DEBUG_HASH + 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(symname[length-(length / 2)]) * MULTIPLIER, + hashval ^= hconv(nameptr[-2]) << 2, + hashval ^= hconv(nameptr[-1]); + nameptr = symname; + if ((symptr = *(hashptr = spt + + (hashval ^ (hconv(nameptr[0]) << 1)) % SPTSIZ)) + != NUL_PTR) + { + do + { +#ifdef DEBUG_HASH + 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) != NUL_PTR); + + /* Calculate last non-NUL_PTR 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 != NUL_PTR); + } + if (!ifflag) + return NUL_PTR; +#ifdef DEBUG_HASH + ++nsym; + if (hashptr >= spt && hashptr < spt + SPTSIZ) + ++nhash; +#endif + *hashptr = symptr = asalloc(sizeof(struct sym_s) + length); + symptr->type = 0; + symptr->data = inidata; + symptr->length = length; + symptr->value_reg_or_op.value = (offset_t) (symptr->next = NUL_PTR); + memcpy(symptr->name, nameptr, length); + symptr->name[length] = 0; + return symptr; +} + +#ifdef DEBUG_HASH + +static void printchain(unsigned hashval) +{ + register struct sym_s *symptr; + + printf("%04x ", hashval); + for (symptr = spt[hashval]; symptr != NUL_PTR; symptr = symptr->next) + printf("%s ", symptr->name); + printf("\n"); +} + +#endif + +void statistics(void) +{ +#ifdef DEBUG_HASH + 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", weight); +#endif +} diff --git a/Applications/as09/type.h b/Applications/as09/type.h new file mode 100644 index 00000000..171790e9 --- /dev/null +++ b/Applications/as09/type.h @@ -0,0 +1,171 @@ +/* type.h - types for assembler */ + +typedef unsigned short u2_t; +typedef unsigned u2_pt; +typedef unsigned long u4_t; +typedef unsigned long u4_pt; + +/* 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 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 (NUL_PTR if none) */ + /* zero offset because it is accessed most */ + unsigned char type; + unsigned char data; /* flags valid for expressions as well as syms*/ + union + { + offset_t value; /* value, if sym is a label */ + unsigned char reg; /* register code, if sym is a register */ + struct + { + unsigned char routine; /* routine number */ + opcode_t opcode; /* opcode, if sym is a hardware op */ + } + op; /* if sym is pseudo-op or hardware op */ + } + value_reg_or_op; + unsigned char length; /* length of symbol string */ + char name[1]; /* string of variable length */ +}; + +/* address */ + +struct address_s +{ + offset_t offset; + unsigned char data; + struct sym_s *sym; +}; + +#ifdef I80386 + +/* effective address */ + +struct ea_s +{ + indcount_t indcount; + opsize_t size; + reg_pt base; + reg_pt index; + scale_t scale; + struct address_s displ; +}; + +#endif + +/* flags */ + +struct flags_s +{ + bool_t global; + bool_t current; + int semaphore; +}; + +/* location counter */ + +struct lc_s +{ + unsigned char data; + offset_t lc; +}; + +/* string chain */ + +struct schain_s +{ + struct schain_s *next; + char string[2]; /* variable length */ +}; + +/* block stack */ + +struct block_s +{ + unsigned char data; + unsigned char dp; + offset_t lc; +}; + +/* if stack */ + +struct if_s +{ + bool_t ifflag; + bool_t elseflag; +}; + +/* macro stack */ + +struct macro_s +{ + char *text; + struct schain_s *parameters; +}; + +/* symbol listing format */ + +struct sym_listing_s +{ + char name[SYMLIS_NAMELEN]; + char zname[2]; + char segm[1]; + char pad1[1]; + char value[4]; + char pad2[1]; + char ar[1]; + char pad3[1]; + char cein[1]; + char pad4[1]; + char nullterm; +}; + +#if __STDC__ +typedef void (*pfv)(void); +#else +typedef void (*pfv)(); +#endif + +#include "proto.h" diff --git a/Applications/as09/typeconv.c b/Applications/as09/typeconv.c new file mode 100644 index 00000000..2af5aff9 --- /dev/null +++ b/Applications/as09/typeconv.c @@ -0,0 +1,181 @@ + +/* + * Type conversion routines, these have been rewritten for portability. + * + * The only requirement is now that the u2_t and u4_t must be big enough. + */ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "globvar.h" + +#if defined(__m6809__) && defined(MC6809) +#define NATIVE_ENDIAN +#endif + +void xxerr P((char *)); +void xxerr(x) char * x; { write(2, x, strlen(x)); } + +#ifdef __AS386_16__ +static int no_swap = 1; +#endif + +static int long_off[4] = {0,1,2,3}; +static int int_off[2] = {0,1}; + +bool_pt typeconv_init(bool_pt big_endian, bool_pt long_big_endian) +{ + int i; +#ifdef __AS386_16__ + no_swap = (!big_endian && !long_big_endian); +#endif + + for(i=0; i<4; i++) long_off[i] = i; + for(i=0; i<2; i++) int_off[i] = i; + + if( long_big_endian ) + { + i = long_off[0]; long_off[0] = long_off[2]; long_off[2] = i; + i = long_off[1]; long_off[1] = long_off[3]; long_off[3] = i; + } + if( big_endian ) + { + i = long_off[2]; long_off[2] = long_off[3]; long_off[3] = i; + i = long_off[0]; long_off[0] = long_off[1]; long_off[1] = i; + + i = int_off[0]; int_off[0] = int_off[1]; int_off[1] = i; + } + return 1; +} + +void u2c2(char *buf, u2_t offset) +{ +#ifdef __AS386_16__ + if( no_swap ) + { + *((unsigned short*)buf) = offset; /* UNALIGNED ACCESS! */ + return; + } +#endif + buf[int_off[0]] = offset; + buf[int_off[1]] = (offset>>8); +} + +void u4c4(char *buf, u4_t offset) +{ + int i; +#ifdef __AS386_16__ + if( no_swap ) + { + *((unsigned long*)buf) = offset; /* UNALIGNED ACCESS! */ + return; + } +#endif + for(i=0; i<4; i++) + { + buf[long_off[i]] = offset; + offset >>= 8; + } +} + +void u4cn(char *buf, u4_t offset, unsigned count) +{ + switch(count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + u2c2(buf, (u2_pt) offset); + return; + case 4: + u4c4(buf, (u4_t) offset); + return; + default: + xxerr("WARNING: typeconv.c(u4cn) illegal count\n"); + return; + } +} + +void u2cn(char *buf, u2_pt offset, unsigned count) +{ + switch(count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + u2c2(buf, (u2_pt) offset); + return; + case 4: + u4c4(buf, (u4_t) offset); + return; + default: + xxerr("WARNING: typeconv.c(u2cn) illegal count\n"); + return; + } +} + +u2_pt c2u2(char *buf) +{ + u2_pt res; +#ifdef __AS386_16__ + if( no_swap ) return *((u2_pt *)buf); /* UNALIGNED ACCESS! */ +#endif + + res = ((unsigned char *)buf) [int_off[0]] + + ((((unsigned char *)buf) [int_off[1]]) << 8); + return res; +} + +u4_t c4u4(char *buf) +{ + u4_t res; + int i; +#ifdef __AS386_16__ + if( no_swap ) return *((u4_t *)buf); /* UNALIGNED ACCESS! */ +#endif + res = 0; + for(i=3; i>=0; i--) + { + res = (res<<8) + ((unsigned char *)buf) [long_off[i]]; + } + return res; +} + +u4_t cnu4(char *buf, unsigned count) +{ + switch (count) + { + case 0: + return 0; + case 1: + return buf[0] & 0xFF; + case 2: + return c2u2(buf); + case 4: + return c4u4(buf); + default: + xxerr("WARNING: typeconv.c(cnu4) illegal count\n"); + return 0; + } +} + +u2_pt cnu2(char *buf, unsigned count) +{ + switch (count) + { + case 0: + return 0; + case 1: + return buf[0] & 0xFF; + case 2: + return c2u2(buf); + case 4: + return (u2_pt) c4u4(buf); + default: + xxerr("WARNING: typeconv.c(cnu2) illegal count\n"); + return 0; + } +} diff --git a/Applications/as09/version.h b/Applications/as09/version.h new file mode 100644 index 00000000..0af81ac2 --- /dev/null +++ b/Applications/as09/version.h @@ -0,0 +1 @@ +#define VERSION "0.16.21" -- 2.34.1