diff options
author | Robert de Bath <rdebath@poboxes.com> | 2002-07-27 09:23:57 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2013-10-23 23:16:11 +0200 |
commit | a7aba15e8efffb1c5d3097656f1a93955a64f01f (patch) | |
tree | 4bb9d6d1d1528bc5647670d510aca6cc5fb300a8 | |
download | dev86-a7aba15e8efffb1c5d3097656f1a93955a64f01f.tar.gz |
Import origs.tar.gzorigs
296 files changed, 59590 insertions, 0 deletions
diff --git a/as/6809/const.h b/as/6809/const.h new file mode 100644 index 0000000..abd9469 --- /dev/null +++ b/as/6809/const.h @@ -0,0 +1,501 @@ +#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */ +#define LOW_BYTE 0 /* must be changed for big-endian */ + +/* const.h - constants for assembler */ + +/* major switches */ + +#undef I80386 /* generate 80386 code */ +#define MC6809 /* generate 6809 code */ +#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */ +#undef SOS_EDOS /* source OS is EDOS */ + +/* defaults */ + +#define DIRCHAR '/' /* character separating filename from dir */ +#define INBUFSIZE 8192 +#define SOS_EOLSTR "\012" + +/* defaults modified by switches */ + +#ifdef SOS_EDOS +# undef INBUFSIZE +# define INBUFSIZE 512 +# undef SOS_EOLSTR +# define SOS_EOLSTR "\015\012" +# define STAKSIZ 256 /* table grows up to stack less this */ +#endif + +/* booleans */ + +#define FALSE 0 +#define TRUE 1 + +/* ASCII constants */ + +#define ETB 23 + +/* C tricks */ + +#define EXTERN extern +#define FORWARD static +#define PRIVATE static +#define PUBLIC +#define NULL 0 + +/* O/S constants */ + +#define CREAT_PERMS 0666 +#define EOF (-1) +#define STDIN 0 +#define STDOUT 1 + +/* register codes (internal to assembler) */ + +#ifdef I80386 + +/* index regs must be first */ + +#define BPREG 0 +#define BXREG 1 +#define DIREG 2 +#define SIREG 3 +#define MAX16BITINDREG 3 + +#define EAXREG 4 +#define EBPREG 5 +#define EBXREG 6 +#define ECXREG 7 +#define EDIREG 8 +#define EDXREG 9 +#define ESIREG 10 +#define ESPREG 11 +#define MAXINDREG 11 + +#define AXREG 12 +#define CXREG 13 +#define DXREG 14 +#define SPREG 15 + +#define AHREG 16 +#define ALREG 17 +#define BHREG 18 +#define BLREG 19 +#define CHREG 20 +#define CLREG 21 +#define DHREG 22 +#define DLREG 23 + +#define CSREG 24 +#define DSREG 25 +#define ESREG 26 +#define FSREG 27 +#define GSREG 28 +#define SSREG 29 + +#define CR0REG 30 +#define CR2REG 31 +#define CR3REG 32 +#define DR0REG 33 +#define DR1REG 34 +#define DR2REG 35 +#define DR3REG 36 +#define DR6REG 37 +#define DR7REG 38 +#define TR6REG 39 +#define TR7REG 40 + +#define NOREG 41 + +#endif /* I80386 */ + +#ifdef MC6809 + +/* index regs must be first, then PC, then other regs */ + +#define AREG 5 +#define BREG 6 +#define CCREG 7 +#define DPREG 8 +#define DREG 9 +#define MAXINDREG 3 +#define NOREG 10 +#define PCREG 4 +#define SREG 0 +#define UREG 1 +#define XREG 2 +#define YREG 3 + +#endif + +#ifdef I80386 + +/* type and size keywords */ + +#define BYTEOP 0 +#define DWORDOP 1 +#define FWORDOP 2 +#define FAROP 3 +#define PTROP 4 +#define PWORDOP 5 +#define QWORDOP 6 +#define TBYTEOP 7 +#define WORDOP 8 +#endif + +/* special chars */ + +#define EOL 0 +#define MACROCHAR '?' + +/* symbol codes */ + +/* the first 2 must be from chars in identifiers */ +#define IDENT 0 +#define INTCONST 1 + +/* the next few are best for other possibly-multi-char tokens */ +#define ADDOP 2 /* also ++ */ +#define BINCONST 3 +#define CHARCONST 4 +#define GREATERTHAN 5 /* also >> and context-sensitive */ +#define HEXCONST 6 +#define LESSTHAN 7 /* also << and context-sensitive */ +#define SUBOP 8 /* also -- */ +#define WHITESPACE 9 + +#define ANDOP 10 +#define COMMA 11 +#define EOLSYM 12 +#define EQOP 13 +#define IMMEDIATE 14 +#define INDIRECT 15 +#define LBRACKET 16 +#define LPAREN 17 +#define MACROARG 18 +#define NOTOP 19 +#define OROP 20 +#define OTHERSYM 21 +#define POSTINCOP 22 +#define PREDECOP 23 +#define RBRACKET 24 +#define RPAREN 25 +#define SLASH 26 /* context-sensitive */ +#define SLOP 27 +#define SROP 28 +#define STAR 29 /* context-sensitive */ +#define STRINGCONST 30 +#define COLON 31 + +/* these are from assembler errors module */ + +/* syntax errors */ + +#define COMEXP 0 +#define DELEXP 1 +#define FACEXP 2 +#define IREGEXP 3 +#define LABEXP 4 +#define LPEXP 5 +#define OPEXP 6 +#define RBEXP 7 +#define REGEXP 8 +#define RPEXP 9 +#define SPEXP 10 + +/* expression errors */ + +#define ABSREQ 11 +#define NONIMPREQ 12 +#define RELBAD 13 + +/* label errors */ + +#define ILLAB 14 +#define MACUID 15 +#define MISLAB 16 +#define MNUID 17 +#define REGUID 18 +#define RELAB 19 +#define UNBLAB 20 +#define UNLAB 21 +#define VARLAB 22 + +/* addressing errors */ + +#define ABOUNDS 23 +#define DBOUNDS 24 +#define ILLMOD 25 +#define ILLREG 26 + +/* control structure errors */ + +#define ELSEBAD 27 +#define ELSEIFBAD 27 +#define ENDBBAD 28 +#define ENDIFBAD 27 +#define EOFBLOCK 29 +#define EOFIF 30 + +#define EOFLC 31 +#define EOFMAC 32 +#define FAILERR 33 + +/* overflow errors */ + +#define BLOCKOV 34 +#define BWRAP 35 +#define COUNTOV 36 +#define COUNTUN 37 +#define GETOV 38 +#define IFOV 39 + +#define LINLONG 40 +#define MACOV 41 +#define OBJSYMOV 42 +#define OWRITE 43 +#define PAROV 44 +#define SYMOV 45 +#define SYMOUTOV 46 + +/* i/o errors */ + +#define OBJOUT 47 + +/* miscellaneous errors */ + +#define CTLINS 48 +#define FURTHER 49 +#define NOIMPORT 50 +#define NOTIMPLEMENTED 51 +#define REENTER 52 +#define SEGREL 53 + +/* warnings */ + +#define MINWARN 54 +#define ALREADY 54 +#define SHORTB 55 + +/* symbol table entry */ + + /* type entry contains following flags */ +#define ENTBIT (1<<0) /* entry point (=OBJ_N_MASK) */ +#define COMMBIT (1<<1) /* common */ +#define LABIT (1<<2) /* label (a PC location or defined by EQU) */ +#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */ +#define MACBIT (1<<4) /* macro */ +#define REDBIT (1<<5) /* redefined */ +#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */ +#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */ + + /* data entry contains following flags, valid */ + /* for expressions as well as syms */ +#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT \ PAGE1 */ +#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT \ PAGE2 */ +#define REGBIT (1<<2) /* register = MNREGBIT \ REGBIT */ +#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT \ SIZEBIT */ +#define SEGM 15 /* 1st 4 bits reused for segment if !MNREGBIT */ +#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */ +#define FORBIT (1<<5) /* forward referenced */ +#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */ +#define UNDBIT (1<<7) /* undefined */ + +/* pseudo-op routine numbers */ +/* conditionals are first, this is used to test if op is a conditional */ + +#define ELSEOP 0 +#define ELSEIFOP 1 +#define ELSEIFCOP 2 +#define ENDIFOP 3 +#define IFOP 4 +#define IFCOP 5 +#define MAXCOND 6 /* limit of conditionals */ + +#define BLOCKOP 6 +#define COMMOP 7 +#define ENDOP 8 +#define ENDBOP 9 +#define ENTEROP 10 +#define ENTRYOP 11 +#define EQUOP 12 +#define EXPORTOP 13 +#define FAILOP 14 +#define FCBOP 15 +#define FCCOP 16 +#define FDBOP 17 +#define GETOP 18 +#define IDENTOP 19 +#define IMPORTOP 20 +#define _LISTOP 21 +#define LOCOP 22 +#define _MACLISTOP 23 +#define MACROOP 24 +#define _MAPOP 25 +#define ORGOP 26 +#define RMBOP 27 +#define SETOP 28 +#define SETDPOP 29 +#define _WARNOP 30 + +#ifdef I80386 + +/* further pseudo-ops */ + +#define BSSOP 31 +#define COMMOP1 32 +#define DATAOP 33 +#define TEXTOP 34 +#define USE16OP 35 +#define USE32OP 36 + +/* machine-op routine numbers */ + +#define ARPL 37 +#define BCC 38 +#define BOUND 39 +#define CALL 40 +#define DIVMUL 41 +#define ENTER 42 +#define GROUP1 43 +#define GROUP2 44 +#define GROUP6 45 +#define GROUP7 46 +#define GROUP8 47 +#define GvEv 48 +#define IMUL 49 +#define IN 50 +#define INCDEC 51 +#define INHER 52 +#define INHER16 53 +#define INHER32 54 +#define INHER_A 55 +#define INT 56 +#define JCC 57 +#define JCXZ 58 +#define LEA 59 +#define LOAD_FULL_POINTER 60 +#define MOV 61 +#define MOVX 62 +#define NEGNOT 63 +#define OUT 64 +#define PUSHPOP 65 +#define RET 66 +#define RETF 67 +#define SEG 68 +#define SETCC 69 +#define SH_DOUBLE 70 +#define TEST 71 +#define XCHG 72 + +/* further pseudo-ops */ + +#define BLKWOP 73 +#define EVENOP 74 +#define FQBOP 75 +#define ALIGNOP 76 + +/* further machine-ops */ + +#define CALLI 77 + +/* yet further pseudo-ops */ + +#define LCOMMOP 78 +#define LCOMMOP1 79 + +#endif /* I80386 */ + +#ifdef MC6809 + +/* machine-op routine numbers */ + +#define ALL 31 /* all address modes allowed, like LDA */ +#define ALTER 32 /* all but immediate, like STA */ +#define IMMED 33 /* immediate only (ANDCC, ORCC) */ +#define INDEXD 34 /* indexed (LEA's) */ +#define INHER 35 /* inherent, like CLC or CLRA */ +#define LONG 36 /* long branches */ +#define SHORT 37 /* short branches */ +#define SSTAK 38 /* S-stack (PSHS, PULS) */ +#define SWAP 39 /* TFR, EXG */ +#define USTAK 40 /* U-stack (PSHU,PULU) */ + +/* yet further pseudo-ops */ + +#define LCOMMOP 41 + +#endif + +/* object code format (Introl) */ + +#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */ + +#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */ + +#define OBJ_ABS 0x40 /* absolute code command */ +#define OBJ_OFFSET_REL 0x80 /* offset relocation command */ +#define OBJ_SET_SEG 0x20 /* set segment command */ +#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */ +#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */ +#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */ +#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */ + +#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */ +#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */ +oops - RELBIT misplaced +#endif +#define OBJ_E_MASK 0x80 /* exported bit (symbols) */ +#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */ +oops - EXPBIT misplaced +#endif +#define OBJ_I_MASK 0x40 /* imported bit (symbols) */ +#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */ +oops - IMPBIT misplaced +#endif +#define OBJ_N_MASK 0x01 /* entry bit (symbols) */ +#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */ +oops - ENTBIT misplaced +#endif +#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */ +#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */ +#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */ +#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */ + +#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */ +#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */ + +#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */ +#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */ + +#define SYMLIS_NAMELEN 26 +#define SYMLIS_LEN (sizeof (struct sym_listing_s)) + +#define FILNAMLEN 64 /* max length of a file name */ +#define LINLEN 256 /* max length of input line */ +#define LINUM_LEN 5 /* length of formatted line number */ + +#define SPTSIZ 1024 /* number of symbol ptrs */ + /* pseudo-op flags */ +#define POPHI 1 /* set to print hi byte of adr */ +#define POPLO 2 /* to print lo byte of ADR */ +#define POPLC 4 /* to print LC */ +#define POPLONG 8 /* to print high word of ADR */ +#define MAXBLOCK 8 /* max nesting level of BLOCK stack */ +#define MAXGET 8 /* max nesting level of GET stack */ +#define MAXIF 8 /* max nesting level of IF stack */ +#define MACPSIZ (128/sizeof (struct schain_s)) + /* size of macro param buffer */ +#define MAXMAC 8 /* max nesting level of macro stack */ +#define NLOC 16 /* number of location counters */ +#ifdef I80386 +#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */ +#endif + +/* special segments */ + +#define BSSLOC 3 +#define DATALOC 3 +#define DPLOC 2 +#define STRLOC 1 +#define TEXTLOC 0 diff --git a/as/Makefile b/as/Makefile new file mode 100644 index 0000000..d7468a9 --- /dev/null +++ b/as/Makefile @@ -0,0 +1,27 @@ +CFLAGS =-O +LDFLAGS = + +OBJS =as.o assemble.o error.o express.o \ + genbin.o genlist.o genobj.o gensym.o \ + macro.o mops.o pops.o readsrc.o \ + scan.o table.o typeconv.o + +as: $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -o as + chmem =182000 as + +as.o: const.h type.h byteord.h macro.h file.h flag.h globvar.h +assemble.o: const.h type.h address.h globvar.h opcode.h scan.h +error.o: const.h type.h +express.o: const.h type.h address.h globvar.h scan.h source.h +genbin.o: const.h type.h address.h file.h globvar.h +genlist.o: const.h type.h address.h flag.h file.h globvar.h macro.h scan.h \ + source.h +genobj.o: const.h type.h address.h file.h globvar.h +gensym.o: const.h type.h flag.h file.h globvar.h +macro.o: const.h type.h globvar.h scan.h macro.h +mops.o: const.h type.h globvar.h opcode.h scan.h address.h +pops.o: const.h type.h address.h flag.h globvar.h opcode.h scan.h +readsrc.o: const.h type.h flag.h file.h globvar.h macro.h scan.h source.h +scan.o: const.h type.h globvar.h scan.h +table.o: const.h type.h globvar.h opcode.h scan.h @@ -0,0 +1 @@ +6809/const.h is out of date. diff --git a/as/address.h b/as/address.h new file mode 100644 index 0000000..26fcf33 --- /dev/null +++ b/as/address.h @@ -0,0 +1,30 @@ +/* address.h - global variables involving addresses for assembler */ + +EXTERN struct address_s lastexp;/* last expression parsed */ + +EXTERN union +{ + char fcbuf[LINLEN - 6]; /* buffer for fcb and fcc data */ + /* data is absolute in 1 char pieces */ + /* limited by FCC\t"" etc on line */ + struct address_s fdbuf[(LINLEN - 4) / 2]; + /* buffer for fdb data */ + /* data can be of any 2-byte adr type */ + /* limited by FDB\t and commas on line */ +#if SIZEOF_OFFSET_T > 2 + struct address_s fqbuf[(LINLEN - 4) / 4]; + /* buffer for fqb data */ + /* data can be of any 4-byte adr type */ + /* limited by FQB\t and commas on line */ +#endif +} + databuf; + +EXTERN bool_t fcflag; +EXTERN bool_t fdflag; +#if SIZEOF_OFFSET_T > 2 +EXTERN bool_t fqflag; +#endif + +EXTERN struct address_s immadr; +EXTERN smallcount_t immcount; @@ -0,0 +1,296 @@ +/* as.c - assembler */ + +/* + usage: as source [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] [-guw] + in any order (but no repeated file options) +*/ + +#include "const.h" +#include "type.h" +#include "byteord.h" +#include "macro.h" +#undef EXTERN +#define EXTERN +#include "file.h" +#include "flag.h" +#include "globvar.h" + +#ifdef STDC_HEADERS_MISSING +void exit P((int status)); +void *malloc P((unsigned size)); +char *strcpy P((char *s1, const char *s2)); +unsigned strlen P((const char *s)); +#else +#undef NULL +#include <stdlib.h> +#include <string.h> +#endif + +#ifdef POSIX_HEADERS_MISSING +int close P((int fd)); +int creat P((const char *path, int mode)); +int write P((int fd, const void *buf, unsigned nbytes)); +#else +#undef NULL +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#endif + +PUBLIC char hexdigit[] = "0123456789ABCDEF"; /* XXX - ld uses lower case */ + +PRIVATE struct block_s hid_blockstak[MAXBLOCK]; /* block stack */ +PRIVATE struct lc_s hid_lctab[NLOC]; /* location counter table */ +PRIVATE struct if_s hid_ifstak[MAXBLOCK]; /* if stack */ +PRIVATE struct schain_s hid_mcpar[MACPSIZ]; /* MACRO params */ +PRIVATE struct macro_s hid_macstak[MAXBLOCK]; /* macro stack */ +PRIVATE struct sym_s *hid_spt[SPTSIZ]; /* hash table */ + +FORWARD void initp1 P((void)); +FORWARD int my_creat P((char *name, char *message)); +FORWARD void process_args P((int argc, char **argv)); +FORWARD void summary P((fd_t fd)); +FORWARD void summ_number P((unsigned num)); +FORWARD void usage P((void)); + +#define USERMEM (sizeof(int) <= 2 ? (unsigned) 0xAC00 : (unsigned) 0x28000L) + +PUBLIC int main(argc, argv) +int argc; +char **argv; +{ + heapptr = malloc(USERMEM); + heapend = heapptr + USERMEM; + if (heapptr == 0) + as_abort("cannot allocate memory"); +#ifdef SOS_EDOS + heapend = stackreg() - STAKSIZ; +#endif + initp1(); + initp1p2(); + inst_keywords(); + initbin(); + initobj(); + initsource(); /* only nec to init for unsupported mem file */ + typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN); + warn.global = TRUE; /* constant */ + process_args(argc, argv); + initscan(); + + assemble(); /* doesn't return, maybe use setjmp */ + + /* NOTREACHED */ + return 0; +} + +PUBLIC void as_abort(message) +char *message; +{ + write(STDOUT, "as: ", 4); + write(STDOUT, message, strlen(message)); + write(STDOUT, "\n", 1); + exit(1); +} + +PUBLIC void finishup() +{ + bintrailer(); + objtrailer(); + if (list.global ||symgen) + gensym(); /* output to lstfil and/or symfil */ + if (list.global ||toterr != 0 || totwarn != 0) + summary(lstfil); + if (lstfil != STDOUT && (toterr != 0 || totwarn != 0)) + summary(STDOUT); + statistics(); + exit(toterr != 0 ? 1 : 0); /* should close output files and check */ +} + +/* initialise constant nonzero values */ + +PRIVATE void initp1() +{ +#ifdef I80386 + idefsize = defsize = sizeof (char *) > 2 ? 4 : 2; +#endif + lctabtop = lctab + NLOC; + lstfil = STDOUT; + mapnum = 15; /* default map number for symbol table */ + spt_top = (spt = hid_spt) + SPTSIZ; +} + +/* initialise nonzero values which start same each pass */ + +PUBLIC void initp1p2() +{ + register struct lc_s *lcp; + + ifflag = TRUE; + pedata = UNDBIT; /* program entry point not defined */ + blockstak = hid_blockstak + MAXBLOCK; + ifstak = hid_ifstak + MAXIF; + macstak = hid_macstak + MAXMAC; + macptop = (macpar = hid_mcpar) + MACPSIZ; + lctabtop = (lcptr = lctab = hid_lctab) + NLOC; + for (lcp = lctab; lcp < lctabtop; ++lcp) + /* init of lcdata/lc (many times) in loop to save space */ + { + lcp->data = lcdata = RELBIT; /* lc relocatable until 1st ORG */ + lcp->lc = lc = 0; + } +} + +PRIVATE int my_creat(name, message) +char *name; +char *message; +{ + int fd; + + if ((fd = creat(name, CREAT_PERMS)) < 0 || fd > 255) + as_abort(message); + return fd; +} + +PRIVATE void process_args(argc, argv) +int argc; +char **argv; +{ + char *arg; + bool_t isnextarg; + char *nextarg; + + if (argc <= 1) + usage(); + do + { + arg = *++argv; + if (arg[0] == '-') + { + if (arg[2] != 0) + usage(); /* no multiple options */ + isnextarg = FALSE; + if (argc > 2) + { + nextarg = argv[1]; + if (nextarg[0] != 0 && nextarg[0] != '-') + isnextarg = TRUE; + } + switch (arg[1]) + { +#ifdef I80386 + case '0': + idefsize = defsize = 0x2; + break; + case '3': + idefsize = defsize = 0x4; + break; + case 'a': + asld_compatible = TRUE; + break; +#endif + case 'b': + if (!isnextarg || binfil != 0) + usage(); + binfil = my_creat(nextarg, "error creating binary file"); + binaryg = TRUE; + --argc; + ++argv; + break; + case 'g': + globals_only_in_obj = TRUE; + break; +#ifdef I80386 + case 'j': + jumps_long = TRUE; + break; +#endif + case 'l': + list.global = TRUE; + goto get_any_list_file; + case 'm': + maclist.global = TRUE; + get_any_list_file: + if (isnextarg) + { + if (lstfil != STDOUT) + usage(); + lstfil = my_creat(nextarg, "error creating list file"); + --argc; + ++argv; + } + break; + case 'n': + if (!isnextarg) + usage(); + truefilename = nextarg; + --argc; + ++argv; + break; + case 'o': + if (!isnextarg || objfil != 0) + usage(); + objectg = TRUE; + objfil = my_creat(nextarg, "error creating object file"); + --argc; + ++argv; + break; + case 's': + if (!isnextarg || symfil != 0) + usage(); + symgen = TRUE; + symfil = my_creat(nextarg, "error creating symbol file"); + --argc; + ++argv; + break; + case 'u': + inidata = IMPBIT | SEGM; + break; + case 'w': + warn.semaphore = -1; + break; + default: + usage(); /* bad option */ + } + } + else if (infil != 0) + usage(); /* no multiple sources */ + else + { + if (strlen(arg) > FILNAMLEN) + as_abort("source file name too long"); + infil = open_input(strcpy(filnamptr, arg)); + infiln = infil0 = 1; + } + } + while (--argc != 1); + inidata = (~binaryg & inidata) | (RELBIT | UNDBIT); +} /* IMPBIT from inidata unless binaryg */ + +PRIVATE void summary(fd) +int fd; +{ + innum = fd; + writenl(); + summ_number(toterr); + writesn(" errors"); + summ_number(totwarn); + writesn(" warnings"); +} + +PRIVATE void summ_number(num) +unsigned num; +{ + /* format number like line numbers, build it at free spot heapptr */ + *build_number(num, LINUM_LEN, heapptr) = 0; + writes(heapptr); +} + +PRIVATE void usage() +{ + as_abort( +#ifdef I80386 +"usage: as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src"); +#else + "usage: as [-guw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src"); +#endif +} diff --git a/as/asm/calljmp.asm b/as/asm/calljmp.asm new file mode 100644 index 0000000..36a6ea4 --- /dev/null +++ b/as/asm/calljmp.asm @@ -0,0 +1,70 @@ + CALL 0x10:0x20 ; not implemented + CALL AL; ; illeg + CALL DS ; illeg + + CALL REL16 + + CALL AX + CALL BX + CALL CX + CALL DX + CALL SP + CALL BP + CALL SI + CALL DI + + CALL BYTE [BX] ; illeg + CALL [BX] + CALL WORD [BX] + + USE32 + CALL REL32 + + USE16 + CALL EAX + CALL EBX + CALL ECX + CALL EDX + CALL ESP + CALL EBP + CALL ESI + CALL EDI + + CALL DWORD [BX] + + JMP 0x10:0x20 ; not implemented + JMP AL; ; illeg + JMP DS ; illeg + + JMP REL16 + + JMP AX + JMP BX + JMP CX + JMP DX + JMP SP + JMP BP + JMP SI + JMP DI + + JMP BYTE [BX] ; illeg + JMP [BX] + JMP WORD [BX] + + USE32 + JMP REL32 + + USE16 + JMP EAX + JMP EBX + JMP ECX + JMP EDX + JMP ESP + JMP EBP + JMP ESI + JMP EDI + + JMP DWORD [BX] + +REL16: +REL32: diff --git a/as/asm/ea.asm b/as/asm/ea.asm new file mode 100644 index 0000000..8717a73 --- /dev/null +++ b/as/asm/ea.asm @@ -0,0 +1,109 @@ + MOV AX,[BX+SI] + MOV AX,[BX+DI] + MOV AX,[BP+SI] + MOV AX,[BP+DI] + MOV AX,[SI] + MOV AX,[DI] + MOV AX,[0x1234] + MOV AX,[BX] + + MOV AX,[BX+SI+0x12] + MOV AX,[BX+DI+0x12] + MOV AX,[BP+SI+0x12] + MOV AX,[BP+DI+0x12] + MOV AX,[SI+0x12] + MOV AX,[DI+0x12] + MOV AX,[BP+0x12] + MOV AX,[BX+0x12] + + MOV AX,[BX+SI+0x1234] + MOV AX,[BX+DI+0x1234] + MOV AX,[BP+SI+0x1234] + MOV AX,[BP+DI+0x1234] + MOV AX,[SI+0x1234] + MOV AX,[DI+0x1234] + MOV AX,[BP+0x1234] + MOV AX,[BX+0x1234] + + MOV AL,AL + MOV AL,AH + MOV AL,BL + MOV AL,BH + MOV AL,CL + MOV AL,CH + MOV AL,DL + MOV AL,DH + + MOV AX,AX + MOV AX,CX + MOV AX,DX + MOV AX,BX + MOV AX,SP + MOV AX,BP + MOV AX,SI + MOV AX,DI + + MOV AX,[EAX] + MOV AX,[ECX] + MOV AX,[EDX] + MOV AX,[EBX] + + MOV AX,[0x12345678] + MOV AX,[ESI] + MOV AX,[EDI] + + MOV AX,[EAX+0x12] + MOV AX,[ECX+0x12] + MOV AX,[EDX+0x12] + MOV AX,[EBX+0x12] + + MOV AX,[EBP+0x12] + MOV AX,[ESI+0x12] + MOV AX,[EDI+0x12] + + MOV AX,[EAX+0x12345678] + MOV AX,[ECX+0x12345678] + MOV AX,[EDX+0x12345678] + MOV AX,[EBX+0x12345678] + + MOV AX,[EBP+0x12345678] + MOV AX,[ESI+0x12345678] + MOV AX,[EDI+0x12345678] + + MOV EAX,EAX + MOV EAX,ECX + MOV EAX,EDX + MOV EAX,EBX + MOV EAX,ESP + MOV EAX,EBP + MOV EAX,ESI + MOV EAX,EDI + + MOV AX,[EAX+ESI*2] + MOV AX,[ECX+ESI*2] + MOV AX,[EDX+ESI*2] + MOV AX,[EBX+ESI*2] + MOV AX,[ESP+ESI*2] + MOV AX,[ESI*2+0x12345678] + MOV AX,[ESI+ESI*2] + MOV AX,[EDI+ESI*2] + + MOV AX,[EAX+ESI*2+0x12] + MOV AX,[ECX+ESI*2+0x12] + MOV AX,[EDX+ESI*2+0x12] + MOV AX,[EBX+ESI*2+0x12] + MOV AX,[ESP+ESI*2+0x12] + MOV AX,[ESP+0x12] + MOV AX,[EBP+ESI*2+0x12] + MOV AX,[ESI+ESI*2+0x12] + MOV AX,[EDI+ESI*2+0x12] + + MOV AX,[EAX+ESI*2+0x12345678] + MOV AX,[ECX+ESI*2+0x12345678] + MOV AX,[EDX+ESI*2+0x12345678] + MOV AX,[EBX+ESI*2+0x12345678] + MOV AX,[ESP+ESI*2+0x12345678] + MOV AX,[ESP+0x12345678] + MOV AX,[EBP+ESI*2+0x12345678] + MOV AX,[ESI+ESI*2+0x12345678] + MOV AX,[EDI+ESI*2+0x12345678] diff --git a/as/asm/each.asm b/as/asm/each.asm new file mode 100644 index 0000000..2145489 --- /dev/null +++ b/as/asm/each.asm @@ -0,0 +1,145 @@ +aaa +aad +aam +aas +adc bx,[esi*4] +add bx,[esi*4] +and bx,[esi*4] +arpl [esi*4],bx +bound bx,[esi*4] +bsf bx,[esi*4] +bsr bx,[esi*4] +bswap ebx +bt [esi*4],bx +btc [esi*4],bx +btr [esi*4],bx +bts [esi*4],bx +call [esi*4] +cbw +cwde +clc +cld +cli +clts +cmc +cmp bx,[esi*4] +cmpsb +cmpsw +cmpsd +cmpxchg [esi*4],bx +cwd +cdq +daa +das +dec [esi*4] +div [esi*4] +enter 0x200,3 +hlt +idiv [esi*4] +imul [esi*4] +in al,0x20 +inc [esi*4] +insb +insw +insd +int 0x20 +into +invd +invlpg [esi*4] +iret +iretd +jnz many +many: +jmp [esi*4] +lahf +lar bx,[esi*4] +lea bx,[esi*4] +leave +lgdt [esi*4] +lidt [esi*4] +lds bx,[esi*4] +les bx,[esi*4] +lfs bx,[esi*4] +lgs bx,[esi*4] +lss bx,[esi*4] +lldt [esi*4] +lmsw [esi*4] +lock +lodsb +lodsw +lodsd +loop alot +alot: +lsl bx,[esi*4] +ltr [esi*4] +mov ax,[esi*4] +mov bx,[esi*4] +mov cr0,eax +movsb +movsw +movsd +movsx bx,byte [esi*4] +movzx bx,byte [esi*4] +mul [esi*4] +neg [esi*4] +nop +not [esi*4] +or bx,[esi*4] +out 0x20,al +outsb +outsw +outsd +pop [esi*4] +popa +popad +popf +popfd +push [esi*4] +pusha +pushad +pushf +pushfd +rcl [esi*4],1 +rcr [esi*4],1 +rol [esi*4],1 +ror [esi*4],1 +rep +repe +repz +repne +repnz +ret +retf +sahf +sal [esi*4],1 +sar [esi*4],1 +shl [esi*4],1 +shr [esi*4],1 +sbb bx,[esi*4] +scasb +scasw +scasd +setnz byte [esi*4] +sgdt [esi*4] +sidt [esi*4] +shld [esi*4],bx,1 +shrd [esi*4],bx,1 +sldt [esi*4] +smsw [esi*4] +stc +std +sti +stosb +stosw +stosd +str [esi*4] +sub bx,[esi*4] +test bx,[esi*4] +verr [esi*4] +verw [esi*4] +wait +wbinvd +xadd [esi*4],bx +xchg bx,[esi*4] +xlat +xor bx,[esi*4] diff --git a/as/asm/easlow.as b/as/asm/easlow.as new file mode 100644 index 0000000..75d71e2 --- /dev/null +++ b/as/asm/easlow.as @@ -0,0 +1,1219 @@ + MOV AL,[0] + MOV AH,[1] + MOV BL,[-1] ; illeg + MOV BH,[127] + MOV CL,[-128] ; illeg + MOV CH,[128] + MOV DL,[-129] ; illeg + MOV DH,[32767] + MOV AL,[-32768] ; illeg + MOV AH,[32768] + MOV BL,[-32769] ; illeg + MOV BH,[$7FFFFFFF] ; illeg + MOV CL,[$80000000] ; illeg + + MOV AL,AL + MOV AL,AH + MOV AL,BL + MOV AL,BH + MOV AL,CL + MOV AL,CH + MOV AL,DL + MOV AL,DH + + MOV AL,AX ; illeg + MOV AL,BX ; illeg + MOV AL,CX ; illeg + MOV AL,DX ; illeg + MOV AL,BP ; illeg + MOV AL,DI ; illeg + MOV AL,SI ; illeg + MOV AL,SP ; illeg + + MOV AH,AL + MOV AH,AH + MOV AH,BL + MOV AH,BH + MOV AH,CL + MOV AH,CH + MOV AH,DL + MOV AH,DH + + MOV AH,AX ; illeg + MOV AH,BX ; illeg + MOV AH,CX ; illeg + MOV AH,DX ; illeg + MOV AH,BP ; illeg + MOV AH,DI ; illeg + MOV AH,SI ; illeg + MOV AH,SP ; illeg + + MOV BL,AL + MOV BL,AH + MOV BL,BL + MOV BL,BH + MOV BL,CL + MOV BL,CH + MOV BL,DL + MOV BL,DH + + MOV BL,AX ; illeg + MOV BL,BX ; illeg + MOV BL,CX ; illeg + MOV BL,DX ; illeg + MOV BL,BP ; illeg + MOV BL,DI ; illeg + MOV BL,SI ; illeg + MOV BL,SP ; illeg + + MOV BH,AL + MOV BH,AH + MOV BH,BL + MOV BH,BH + MOV BH,CL + MOV BH,CH + MOV BH,DL + MOV BH,DH + + MOV BH,AX ; illeg + MOV BH,BX ; illeg + MOV BH,CX ; illeg + MOV BH,DX ; illeg + MOV BH,BP ; illeg + MOV BH,DI ; illeg + MOV BH,SI ; illeg + MOV BH,SP ; illeg + + MOV CL,AL + MOV CL,AH + MOV CL,BL + MOV CL,BH + MOV CL,CL + MOV CL,CH + MOV CL,DL + MOV CL,DH + + MOV CL,AX ; illeg + MOV CL,BX ; illeg + MOV CL,CX ; illeg + MOV CL,DX ; illeg + MOV CL,BP ; illeg + MOV CL,DI ; illeg + MOV CL,SI ; illeg + MOV CL,SP ; illeg + + MOV CH,AL + MOV CH,AH + MOV CH,BL + MOV CH,BH + MOV CH,CL + MOV CH,CH + MOV CH,DL + MOV CH,DH + + MOV CH,AX ; illeg + MOV CH,BX ; illeg + MOV CH,CX ; illeg + MOV CH,DX ; illeg + MOV CH,BP ; illeg + MOV CH,DI ; illeg + MOV CH,SI ; illeg + MOV CH,SP ; illeg + + MOV DL,AL + MOV DL,AH + MOV DL,BL + MOV DL,BH + MOV DL,CL + MOV DL,CH + MOV DL,DL + MOV DL,DH + + MOV DL,AX ; illeg + MOV DL,BX ; illeg + MOV DL,CX ; illeg + MOV DL,DX ; illeg + MOV DL,BP ; illeg + MOV DL,DI ; illeg + MOV DL,SI ; illeg + MOV DL,SP ; illeg + + MOV DH,AL + MOV DH,AH + MOV DH,BL + MOV DH,BH + MOV DH,CL + MOV DH,CH + MOV DH,DL + MOV DH,DH + + MOV DH,AX ; illeg + MOV DH,BX ; illeg + MOV DH,CX ; illeg + MOV DH,DX ; illeg + MOV DH,BP ; illeg + MOV DH,DI ; illeg + MOV DH,SI ; illeg + MOV DH,SP ; illeg + + MOV AL,[AL] ; illeg + MOV AH,[AH] ; illeg + MOV BL,[BL] ; illeg + MOV BH,[BH] ; illeg + MOV CL,[CL] ; illeg + MOV CH,[CH] ; illeg + MOV DL,[DL] ; illeg + MOV DH,[DH] ; illeg + + MOV AL,[AX] ; illeg + MOV AH,[BX] + MOV BL,[CX] ; illeg + MOV BH,[DX] ; illeg + MOV CL,[BP] + MOV CH,[DI] + MOV DL,[SI] + MOV DH,[SP] ; illeg + + MOV AL,[AX+1] ; illeg + MOV AH,[BX+1] + MOV BL,[CX+1] ; illeg + MOV BH,[DX+1] ; illeg + MOV CL,[BP+1] + MOV CH,[DI+1] + MOV DL,[SI+1] + MOV DH,[SP+1] ; illeg + + MOV AL,[AX-1] ; illeg + MOV AH,[BX-1] + MOV BL,[CX-1] ; illeg + MOV BH,[DX-1] ; illeg + MOV CL,[BP-1] + MOV CH,[DI-1] + MOV DL,[SI-1] + MOV DH,[SP-1] ; illeg + + MOV AL,[AX+127] ; illeg + MOV AH,[BX+127] + MOV BL,[CX+127] ; illeg + MOV BH,[DX+127] ; illeg + MOV CL,[BP+127] + MOV CH,[DI+127] + MOV DL,[SI+127] + MOV DH,[SP+127] ; illeg + + MOV AL,[AX-128] ; illeg + MOV AH,[BX-128] + MOV BL,[CX-128] ; illeg + MOV BH,[DX-128] ; illeg + MOV CL,[BP-128] + MOV CH,[DI-128] + MOV DL,[SI-128] + MOV DH,[SP-128] ; illeg + + MOV AL,[AX+128] ; illeg + MOV AH,[BX+128] + MOV BL,[CX+128] ; illeg + MOV BH,[DX+128] ; illeg + MOV CL,[BP+128] + MOV CH,[DI+128] + MOV DL,[SI+128] + MOV DH,[SP+128] ; illeg + + MOV AL,[AX-129] ; illeg + MOV AH,[BX-129] + MOV BL,[CX-129] ; illeg + MOV BH,[DX-129] ; illeg + MOV CL,[BP-129] + MOV CH,[DI-129] + MOV DL,[SI-129] + MOV DH,[SP-129] ; illeg + + MOV AL,[AX+32767] ; illeg + MOV AH,[BX+32767] + MOV BL,[CX+32767] ; illeg + MOV BH,[DX+32767] ; illeg + MOV CL,[BP+32767] + MOV CH,[DI+32767] + MOV DL,[SI+32767] + MOV DH,[SP+32767] ; illeg + + MOV AL,[AX-32768] ; illeg + MOV AH,[BX-32768] + MOV BL,[CX-32768] ; illeg + MOV BH,[DX-32768] ; illeg + MOV CL,[BP-32768] + MOV CH,[DI-32768] + MOV DL,[SI-32768] + MOV DH,[SP-32768] ; illeg + + MOV AL,[AX+32768] ; illeg + MOV AH,[BX+32768] + MOV BL,[CX+32768] ; illeg + MOV BH,[DX+32768] ; illeg + MOV CL,[BP+32768] + MOV CH,[DI+32768] + MOV DL,[SI+32768] + MOV DH,[SP+32768] ; illeg + + MOV AL,[AX-32769] ; illeg + MOV AH,[BX-32769] + MOV BL,[CX-32769] ; illeg + MOV BH,[DX-32769] ; illeg + MOV CL,[BP-32769] + MOV CH,[DI-32769] + MOV DL,[SI-32769] + MOV DH,[SP-32769] ; illeg + + MOV AL,[AX+$7FFFFFFF] ; illeg + MOV AH,[BX+$7FFFFFFF] ; illeg (bounds) + MOV BL,[CX+$7FFFFFFF] ; illeg + MOV BH,[DX+$7FFFFFFF] ; illeg + MOV CL,[BP+$7FFFFFFF] ; illeg (bounds) + MOV CH,[DI+$7FFFFFFF] ; illeg (bounds) + MOV DL,[SI+$7FFFFFFF] ; illeg (bounds) + MOV DH,[SP+$7FFFFFFF] ; illeg + + MOV AL,[AX-$80000000] ; illeg + MOV AH,[BX-$80000000] ; illeg (bounds) + MOV BL,[CX-$80000000] ; illeg + MOV BH,[DX-$80000000] ; illeg + MOV CL,[BP-$80000000] ; illeg (bounds) + MOV CH,[DI-$80000000] ; illeg (bounds) + MOV DL,[SI-$80000000] ; illeg (bounds) + MOV DH,[SP-$80000000] ; illeg + + MOV AL,[AX+AX] ; illeg + MOV AH,[AX+BX] ; illeg + MOV BL,[AX+CX] ; illeg + MOV BH,[AX+DX] ; illeg + MOV CL,[AX+BP] ; illeg + MOV CH,[AX+DI] ; illeg + MOV DL,[AX+SI] ; illeg + MOV DH,[AX+SP] ; illeg + + MOV AL,[BX+AX] ; illeg + MOV AH,[BX+BX] ; illeg + MOV BL,[BX+CX] ; illeg + MOV BH,[BX+DX] ; illeg + MOV CL,[BX+BP] ; illeg + MOV CH,[BX+DI] + MOV DL,[BX+SI] + MOV DH,[BX+SP] ; illeg + + MOV AL,[CX+AX] ; illeg + MOV AH,[CX+BX] ; illeg + MOV BL,[CX+CX] ; illeg + MOV BH,[CX+DX] ; illeg + MOV CL,[CX+BP] ; illeg + MOV CH,[CX+DI] ; illeg + MOV DL,[CX+SI] ; illeg + MOV DH,[CX+SP] ; illeg + + MOV AL,[DX+AX] ; illeg + MOV AH,[DX+BX] ; illeg + MOV BL,[DX+CX] ; illeg + MOV BH,[DX+DX] ; illeg + MOV CL,[DX+BP] ; illeg + MOV CH,[DX+DI] ; illeg + MOV DL,[DX+SI] ; illeg + MOV DH,[DX+SP] ; illeg + + MOV AL,[BP+AX] ; illeg + MOV AH,[BP+BX] ; illeg + MOV BL,[BP+CX] ; illeg + MOV BH,[BP+DX] ; illeg + MOV CL,[BP+BP] ; illeg + MOV CH,[BP+DI] + MOV DL,[BP+SI] + MOV DH,[BP+SP] ; illeg + + MOV AL,[DI+AX] ; illeg + MOV AH,[DI+BX] + MOV BL,[DI+CX] ; illeg + MOV BH,[DI+DX] ; illeg + MOV CL,[DI+BP] + MOV CH,[DI+DI] ; illeg + MOV DL,[DI+SI] ; illeg + MOV DH,[DI+SP] ; illeg + + MOV AL,[SI+AX] ; illeg + MOV AH,[SI+BX] + MOV BL,[SI+CX] ; illeg + MOV BH,[SI+DX] ; illeg + MOV CL,[SI+BP] + MOV CH,[SI+DI] ; illeg + MOV DL,[SI+SI] ; illeg + MOV DH,[SI+SP] ; illeg + + MOV AL,[SP+AX] ; illeg + MOV AH,[SP+BX] ; illeg + MOV BL,[SP+CX] ; illeg + MOV BH,[SP+DX] ; illeg + MOV CL,[SP+BP] ; illeg + MOV CH,[SP+DI] ; illeg + MOV DL,[SP+SI] ; illeg + MOV DH,[SP+SP] ; illeg + + MOV AL,[AX+AX+1] ; illeg + MOV AH,[AX+BX+1] ; illeg + MOV BL,[AX+CX+1] ; illeg + MOV BH,[AX+DX+1] ; illeg + MOV CL,[AX+BP+1] ; illeg + MOV CH,[AX+DI+1] ; illeg + MOV DL,[AX+SI+1] ; illeg + MOV DH,[AX+SP+1] ; illeg + + MOV AL,[BX+AX+1] ; illeg + MOV AH,[BX+BX+1] ; illeg + MOV BL,[BX+CX+1] ; illeg + MOV BH,[BX+DX+1] ; illeg + MOV CL,[BX+BP+1] ; illeg + MOV CH,[BX+DI+1] + MOV DL,[BX+SI+1] + MOV DH,[BX+SP+1] ; illeg + + MOV AL,[CX+AX+1] ; illeg + MOV AH,[CX+BX+1] ; illeg + MOV BL,[CX+CX+1] ; illeg + MOV BH,[CX+DX+1] ; illeg + MOV CL,[CX+BP+1] ; illeg + MOV CH,[CX+DI+1] ; illeg + MOV DL,[CX+SI+1] ; illeg + MOV DH,[CX+SP+1] ; illeg + + MOV AL,[DX+AX+1] ; illeg + MOV AH,[DX+BX+1] ; illeg + MOV BL,[DX+CX+1] ; illeg + MOV BH,[DX+DX+1] ; illeg + MOV CL,[DX+BP+1] ; illeg + MOV CH,[DX+DI+1] ; illeg + MOV DL,[DX+SI+1] ; illeg + MOV DH,[DX+SP+1] ; illeg + + MOV AL,[BP+AX+1] ; illeg + MOV AH,[BP+BX+1] ; illeg + MOV BL,[BP+CX+1] ; illeg + MOV BH,[BP+DX+1] ; illeg + MOV CL,[BP+BP+1] ; illeg + MOV CH,[BP+DI+1] + MOV DL,[BP+SI+1] + MOV DH,[BP+SP+1] ; illeg + + MOV AL,[DI+AX+1] ; illeg + MOV AH,[DI+BX+1] + MOV BL,[DI+CX+1] ; illeg + MOV BH,[DI+DX+1] ; illeg + MOV CL,[DI+BP+1] + MOV CH,[DI+DI+1] ; illeg + MOV DL,[DI+SI+1] ; illeg + MOV DH,[DI+SP+1] ; illeg + + MOV AL,[SI+AX+1] ; illeg + MOV AH,[SI+BX+1] + MOV BL,[SI+CX+1] ; illeg + MOV BH,[SI+DX+1] ; illeg + MOV CL,[SI+BP+1] + MOV CH,[SI+DI+1] ; illeg + MOV DL,[SI+SI+1] ; illeg + MOV DH,[SI+SP+1] ; illeg + + MOV AL,[SP+AX+1] ; illeg + MOV AH,[SP+BX+1] ; illeg + MOV BL,[SP+CX+1] ; illeg + MOV BH,[SP+DX+1] ; illeg + MOV CL,[SP+BP+1] ; illeg + MOV CH,[SP+DI+1] ; illeg + MOV DL,[SP+SI+1] ; illeg + MOV DH,[SP+SP+1] ; illeg + + MOV AL,[AX+AX-1] ; illeg + MOV AH,[AX+BX-1] ; illeg + MOV BL,[AX+CX-1] ; illeg + MOV BH,[AX+DX-1] ; illeg + MOV CL,[AX+BP-1] ; illeg + MOV CH,[AX+DI-1] ; illeg + MOV DL,[AX+SI-1] ; illeg + MOV DH,[AX+SP-1] ; illeg + + MOV AL,[BX+AX-1] ; illeg + MOV AH,[BX+BX-1] ; illeg + MOV BL,[BX+CX-1] ; illeg + MOV BH,[BX+DX-1] ; illeg + MOV CL,[BX+BP-1] ; illeg + MOV CH,[BX+DI-1] + MOV DL,[BX+SI-1] + MOV DH,[BX+SP-1] ; illeg + + MOV AL,[CX+AX-1] ; illeg + MOV AH,[CX+BX-1] ; illeg + MOV BL,[CX+CX-1] ; illeg + MOV BH,[CX+DX-1] ; illeg + MOV CL,[CX+BP-1] ; illeg + MOV CH,[CX+DI-1] ; illeg + MOV DL,[CX+SI-1] ; illeg + MOV DH,[CX+SP-1] ; illeg + + MOV AL,[DX+AX-1] ; illeg + MOV AH,[DX+BX-1] ; illeg + MOV BL,[DX+CX-1] ; illeg + MOV BH,[DX+DX-1] ; illeg + MOV CL,[DX+BP-1] ; illeg + MOV CH,[DX+DI-1] ; illeg + MOV DL,[DX+SI-1] ; illeg + MOV DH,[DX+SP-1] ; illeg + + MOV AL,[BP+AX-1] ; illeg + MOV AH,[BP+BX-1] ; illeg + MOV BL,[BP+CX-1] ; illeg + MOV BH,[BP+DX-1] ; illeg + MOV CL,[BP+BP-1] ; illeg + MOV CH,[BP+DI-1] + MOV DL,[BP+SI-1] + MOV DH,[BP+SP-1] ; illeg + + MOV AL,[DI+AX-1] ; illeg + MOV AH,[DI+BX-1] + MOV BL,[DI+CX-1] ; illeg + MOV BH,[DI+DX-1] ; illeg + MOV CL,[DI+BP-1] + MOV CH,[DI+DI-1] ; illeg + MOV DL,[DI+SI-1] ; illeg + MOV DH,[DI+SP-1] ; illeg + + MOV AL,[SI+AX-1] ; illeg + MOV AH,[SI+BX-1] + MOV BL,[SI+CX-1] ; illeg + MOV BH,[SI+DX-1] ; illeg + MOV CL,[SI+BP-1] + MOV CH,[SI+DI-1] ; illeg + MOV DL,[SI+SI-1] ; illeg + MOV DH,[SI+SP-1] ; illeg + + MOV AL,[SP+AX-1] ; illeg + MOV AH,[SP+BX-1] ; illeg + MOV BL,[SP+CX-1] ; illeg + MOV BH,[SP+DX-1] ; illeg + MOV CL,[SP+BP-1] ; illeg + MOV CH,[SP+DI-1] ; illeg + MOV DL,[SP+SI-1] ; illeg + MOV DH,[SP+SP-1] ; illeg + + MOV AL,[AX+AX+127] ; illeg + MOV AH,[AX+BX+127] ; illeg + MOV BL,[AX+CX+127] ; illeg + MOV BH,[AX+DX+127] ; illeg + MOV CL,[AX+BP+127] ; illeg + MOV CH,[AX+DI+127] ; illeg + MOV DL,[AX+SI+127] ; illeg + MOV DH,[AX+SP+127] ; illeg + + MOV AL,[BX+AX+127] ; illeg + MOV AH,[BX+BX+127] ; illeg + MOV BL,[BX+CX+127] ; illeg + MOV BH,[BX+DX+127] ; illeg + MOV CL,[BX+BP+127] ; illeg + MOV CH,[BX+DI+127] + MOV DL,[BX+SI+127] + MOV DH,[BX+SP+127] ; illeg + + MOV AL,[CX+AX+127] ; illeg + MOV AH,[CX+BX+127] ; illeg + MOV BL,[CX+CX+127] ; illeg + MOV BH,[CX+DX+127] ; illeg + MOV CL,[CX+BP+127] ; illeg + MOV CH,[CX+DI+127] ; illeg + MOV DL,[CX+SI+127] ; illeg + MOV DH,[CX+SP+127] ; illeg + + MOV AL,[DX+AX+127] ; illeg + MOV AH,[DX+BX+127] ; illeg + MOV BL,[DX+CX+127] ; illeg + MOV BH,[DX+DX+127] ; illeg + MOV CL,[DX+BP+127] ; illeg + MOV CH,[DX+DI+127] ; illeg + MOV DL,[DX+SI+127] ; illeg + MOV DH,[DX+SP+127] ; illeg + + MOV AL,[BP+AX+127] ; illeg + MOV AH,[BP+BX+127] ; illeg + MOV BL,[BP+CX+127] ; illeg + MOV BH,[BP+DX+127] ; illeg + MOV CL,[BP+BP+127] ; illeg + MOV CH,[BP+DI+127] + MOV DL,[BP+SI+127] + MOV DH,[BP+SP+127] ; illeg + + MOV AL,[DI+AX+127] ; illeg + MOV AH,[DI+BX+127] + MOV BL,[DI+CX+127] ; illeg + MOV BH,[DI+DX+127] ; illeg + MOV CL,[DI+BP+127] + MOV CH,[DI+DI+127] ; illeg + MOV DL,[DI+SI+127] ; illeg + MOV DH,[DI+SP+127] ; illeg + + MOV AL,[SI+AX+127] ; illeg + MOV AH,[SI+BX+127] + MOV BL,[SI+CX+127] ; illeg + MOV BH,[SI+DX+127] ; illeg + MOV CL,[SI+BP+127] + MOV CH,[SI+DI+127] ; illeg + MOV DL,[SI+SI+127] ; illeg + MOV DH,[SI+SP+127] ; illeg + + MOV AL,[SP+AX+127] ; illeg + MOV AH,[SP+BX+127] ; illeg + MOV BL,[SP+CX+127] ; illeg + MOV BH,[SP+DX+127] ; illeg + MOV CL,[SP+BP+127] ; illeg + MOV CH,[SP+DI+127] ; illeg + MOV DL,[SP+SI+127] ; illeg + MOV DH,[SP+SP+127] ; illeg + + MOV AL,[AX+AX-128] ; illeg + MOV AH,[AX+BX-128] ; illeg + MOV BL,[AX+CX-128] ; illeg + MOV BH,[AX+DX-128] ; illeg + MOV CL,[AX+BP-128] ; illeg + MOV CH,[AX+DI-128] ; illeg + MOV DL,[AX+SI-128] ; illeg + MOV DH,[AX+SP-128] ; illeg + + MOV AL,[BX+AX-128] ; illeg + MOV AH,[BX+BX-128] ; illeg + MOV BL,[BX+CX-128] ; illeg + MOV BH,[BX+DX-128] ; illeg + MOV CL,[BX+BP-128] ; illeg + MOV CH,[BX+DI-128] + MOV DL,[BX+SI-128] + MOV DH,[BX+SP-128] ; illeg + + MOV AL,[CX+AX-128] ; illeg + MOV AH,[CX+BX-128] ; illeg + MOV BL,[CX+CX-128] ; illeg + MOV BH,[CX+DX-128] ; illeg + MOV CL,[CX+BP-128] ; illeg + MOV CH,[CX+DI-128] ; illeg + MOV DL,[CX+SI-128] ; illeg + MOV DH,[CX+SP-128] ; illeg + + MOV AL,[DX+AX-128] ; illeg + MOV AH,[DX+BX-128] ; illeg + MOV BL,[DX+CX-128] ; illeg + MOV BH,[DX+DX-128] ; illeg + MOV CL,[DX+BP-128] ; illeg + MOV CH,[DX+DI-128] ; illeg + MOV DL,[DX+SI-128] ; illeg + MOV DH,[DX+SP-128] ; illeg + + MOV AL,[BP+AX-128] ; illeg + MOV AH,[BP+BX-128] ; illeg + MOV BL,[BP+CX-128] ; illeg + MOV BH,[BP+DX-128] ; illeg + MOV CL,[BP+BP-128] ; illeg + MOV CH,[BP+DI-128] + MOV DL,[BP+SI-128] + MOV DH,[BP+SP-128] ; illeg + + MOV AL,[DI+AX-128] ; illeg + MOV AH,[DI+BX-128] + MOV BL,[DI+CX-128] ; illeg + MOV BH,[DI+DX-128] ; illeg + MOV CL,[DI+BP-128] + MOV CH,[DI+DI-128] ; illeg + MOV DL,[DI+SI-128] ; illeg + MOV DH,[DI+SP-128] ; illeg + + MOV AL,[SI+AX-128] ; illeg + MOV AH,[SI+BX-128] + MOV BL,[SI+CX-128] ; illeg + MOV BH,[SI+DX-128] ; illeg + MOV CL,[SI+BP-128] + MOV CH,[SI+DI-128] ; illeg + MOV DL,[SI+SI-128] ; illeg + MOV DH,[SI+SP-128] ; illeg + + MOV AL,[SP+AX-128] ; illeg + MOV AH,[SP+BX-128] ; illeg + MOV BL,[SP+CX-128] ; illeg + MOV BH,[SP+DX-128] ; illeg + MOV CL,[SP+BP-128] ; illeg + MOV CH,[SP+DI-128] ; illeg + MOV DL,[SP+SI-128] ; illeg + MOV DH,[SP+SP-128] ; illeg + + MOV AL,[AX+AX+128] ; illeg + MOV AH,[AX+BX+128] ; illeg + MOV BL,[AX+CX+128] ; illeg + MOV BH,[AX+DX+128] ; illeg + MOV CL,[AX+BP+128] ; illeg + MOV CH,[AX+DI+128] ; illeg + MOV DL,[AX+SI+128] ; illeg + MOV DH,[AX+SP+128] ; illeg + + MOV AL,[BX+AX+128] ; illeg + MOV AH,[BX+BX+128] ; illeg + MOV BL,[BX+CX+128] ; illeg + MOV BH,[BX+DX+128] ; illeg + MOV CL,[BX+BP+128] ; illeg + MOV CH,[BX+DI+128] + MOV DL,[BX+SI+128] + MOV DH,[BX+SP+128] ; illeg + + MOV AL,[CX+AX+128] ; illeg + MOV AH,[CX+BX+128] ; illeg + MOV BL,[CX+CX+128] ; illeg + MOV BH,[CX+DX+128] ; illeg + MOV CL,[CX+BP+128] ; illeg + MOV CH,[CX+DI+128] ; illeg + MOV DL,[CX+SI+128] ; illeg + MOV DH,[CX+SP+128] ; illeg + + MOV AL,[DX+AX+128] ; illeg + MOV AH,[DX+BX+128] ; illeg + MOV BL,[DX+CX+128] ; illeg + MOV BH,[DX+DX+128] ; illeg + MOV CL,[DX+BP+128] ; illeg + MOV CH,[DX+DI+128] ; illeg + MOV DL,[DX+SI+128] ; illeg + MOV DH,[DX+SP+128] ; illeg + + MOV AL,[BP+AX+128] ; illeg + MOV AH,[BP+BX+128] ; illeg + MOV BL,[BP+CX+128] ; illeg + MOV BH,[BP+DX+128] ; illeg + MOV CL,[BP+BP+128] ; illeg + MOV CH,[BP+DI+128] + MOV DL,[BP+SI+128] + MOV DH,[BP+SP+128] ; illeg + + MOV AL,[DI+AX+128] ; illeg + MOV AH,[DI+BX+128] + MOV BL,[DI+CX+128] ; illeg + MOV BH,[DI+DX+128] ; illeg + MOV CL,[DI+BP+128] + MOV CH,[DI+DI+128] ; illeg + MOV DL,[DI+SI+128] ; illeg + MOV DH,[DI+SP+128] ; illeg + + MOV AL,[SI+AX+128] ; illeg + MOV AH,[SI+BX+128] + MOV BL,[SI+CX+128] ; illeg + MOV BH,[SI+DX+128] ; illeg + MOV CL,[SI+BP+128] + MOV CH,[SI+DI+128] ; illeg + MOV DL,[SI+SI+128] ; illeg + MOV DH,[SI+SP+128] ; illeg + + MOV AL,[SP+AX+128] ; illeg + MOV AH,[SP+BX+128] ; illeg + MOV BL,[SP+CX+128] ; illeg + MOV BH,[SP+DX+128] ; illeg + MOV CL,[SP+BP+128] ; illeg + MOV CH,[SP+DI+128] ; illeg + MOV DL,[SP+SI+128] ; illeg + MOV DH,[SP+SP+128] ; illeg + + MOV AL,[AX+AX-129] ; illeg + MOV AH,[AX+BX-129] ; illeg + MOV BL,[AX+CX-129] ; illeg + MOV BH,[AX+DX-129] ; illeg + MOV CL,[AX+BP-129] ; illeg + MOV CH,[AX+DI-129] ; illeg + MOV DL,[AX+SI-129] ; illeg + MOV DH,[AX+SP-129] ; illeg + + MOV AL,[BX+AX-129] ; illeg + MOV AH,[BX+BX-129] ; illeg + MOV BL,[BX+CX-129] ; illeg + MOV BH,[BX+DX-129] ; illeg + MOV CL,[BX+BP-129] ; illeg + MOV CH,[BX+DI-129] + MOV DL,[BX+SI-129] + MOV DH,[BX+SP-129] ; illeg + + MOV AL,[CX+AX-129] ; illeg + MOV AH,[CX+BX-129] ; illeg + MOV BL,[CX+CX-129] ; illeg + MOV BH,[CX+DX-129] ; illeg + MOV CL,[CX+BP-129] ; illeg + MOV CH,[CX+DI-129] ; illeg + MOV DL,[CX+SI-129] ; illeg + MOV DH,[CX+SP-129] ; illeg + + MOV AL,[DX+AX-129] ; illeg + MOV AH,[DX+BX-129] ; illeg + MOV BL,[DX+CX-129] ; illeg + MOV BH,[DX+DX-129] ; illeg + MOV CL,[DX+BP-129] ; illeg + MOV CH,[DX+DI-129] ; illeg + MOV DL,[DX+SI-129] ; illeg + MOV DH,[DX+SP-129] ; illeg + + MOV AL,[BP+AX-129] ; illeg + MOV AH,[BP+BX-129] ; illeg + MOV BL,[BP+CX-129] ; illeg + MOV BH,[BP+DX-129] ; illeg + MOV CL,[BP+BP-129] ; illeg + MOV CH,[BP+DI-129] + MOV DL,[BP+SI-129] + MOV DH,[BP+SP-129] ; illeg + + MOV AL,[DI+AX-129] ; illeg + MOV AH,[DI+BX-129] + MOV BL,[DI+CX-129] ; illeg + MOV BH,[DI+DX-129] ; illeg + MOV CL,[DI+BP-129] + MOV CH,[DI+DI-129] ; illeg + MOV DL,[DI+SI-129] ; illeg + MOV DH,[DI+SP-129] ; illeg + + MOV AL,[SI+AX-129] ; illeg + MOV AH,[SI+BX-129] + MOV BL,[SI+CX-129] ; illeg + MOV BH,[SI+DX-129] ; illeg + MOV CL,[SI+BP-129] + MOV CH,[SI+DI-129] ; illeg + MOV DL,[SI+SI-129] ; illeg + MOV DH,[SI+SP-129] ; illeg + + MOV AL,[SP+AX-129] ; illeg + MOV AH,[SP+BX-129] ; illeg + MOV BL,[SP+CX-129] ; illeg + MOV BH,[SP+DX-129] ; illeg + MOV CL,[SP+BP-129] ; illeg + MOV CH,[SP+DI-129] ; illeg + MOV DL,[SP+SI-129] ; illeg + MOV DH,[SP+SP-129] ; illeg + + MOV AL,[AX+AX+32767] ; illeg + MOV AH,[AX+BX+32767] ; illeg + MOV BL,[AX+CX+32767] ; illeg + MOV BH,[AX+DX+32767] ; illeg + MOV CL,[AX+BP+32767] ; illeg + MOV CH,[AX+DI+32767] ; illeg + MOV DL,[AX+SI+32767] ; illeg + MOV DH,[AX+SP+32767] ; illeg + + MOV AL,[BX+AX+32767] ; illeg + MOV AH,[BX+BX+32767] ; illeg + MOV BL,[BX+CX+32767] ; illeg + MOV BH,[BX+DX+32767] ; illeg + MOV CL,[BX+BP+32767] ; illeg + MOV CH,[BX+DI+32767] + MOV DL,[BX+SI+32767] + MOV DH,[BX+SP+32767] ; illeg + + MOV AL,[CX+AX+32767] ; illeg + MOV AH,[CX+BX+32767] ; illeg + MOV BL,[CX+CX+32767] ; illeg + MOV BH,[CX+DX+32767] ; illeg + MOV CL,[CX+BP+32767] ; illeg + MOV CH,[CX+DI+32767] ; illeg + MOV DL,[CX+SI+32767] ; illeg + MOV DH,[CX+SP+32767] ; illeg + + MOV AL,[DX+AX+32767] ; illeg + MOV AH,[DX+BX+32767] ; illeg + MOV BL,[DX+CX+32767] ; illeg + MOV BH,[DX+DX+32767] ; illeg + MOV CL,[DX+BP+32767] ; illeg + MOV CH,[DX+DI+32767] ; illeg + MOV DL,[DX+SI+32767] ; illeg + MOV DH,[DX+SP+32767] ; illeg + + MOV AL,[BP+AX+32767] ; illeg + MOV AH,[BP+BX+32767] ; illeg + MOV BL,[BP+CX+32767] ; illeg + MOV BH,[BP+DX+32767] ; illeg + MOV CL,[BP+BP+32767] ; illeg + MOV CH,[BP+DI+32767] + MOV DL,[BP+SI+32767] + MOV DH,[BP+SP+32767] ; illeg + + MOV AL,[DI+AX+32767] ; illeg + MOV AH,[DI+BX+32767] + MOV BL,[DI+CX+32767] ; illeg + MOV BH,[DI+DX+32767] ; illeg + MOV CL,[DI+BP+32767] + MOV CH,[DI+DI+32767] ; illeg + MOV DL,[DI+SI+32767] ; illeg + MOV DH,[DI+SP+32767] ; illeg + + MOV AL,[SI+AX+32767] ; illeg + MOV AH,[SI+BX+32767] + MOV BL,[SI+CX+32767] ; illeg + MOV BH,[SI+DX+32767] ; illeg + MOV CL,[SI+BP+32767] + MOV CH,[SI+DI+32767] ; illeg + MOV DL,[SI+SI+32767] ; illeg + MOV DH,[SI+SP+32767] ; illeg + + MOV AL,[SP+AX+32767] ; illeg + MOV AH,[SP+BX+32767] ; illeg + MOV BL,[SP+CX+32767] ; illeg + MOV BH,[SP+DX+32767] ; illeg + MOV CL,[SP+BP+32767] ; illeg + MOV CH,[SP+DI+32767] ; illeg + MOV DL,[SP+SI+32767] ; illeg + MOV DH,[SP+SP+32767] ; illeg + + MOV AL,[AX+AX-32768] ; illeg + MOV AH,[AX+BX-32768] ; illeg + MOV BL,[AX+CX-32768] ; illeg + MOV BH,[AX+DX-32768] ; illeg + MOV CL,[AX+BP-32768] ; illeg + MOV CH,[AX+DI-32768] ; illeg + MOV DL,[AX+SI-32768] ; illeg + MOV DH,[AX+SP-32768] ; illeg + + MOV AL,[BX+AX-32768] ; illeg + MOV AH,[BX+BX-32768] ; illeg + MOV BL,[BX+CX-32768] ; illeg + MOV BH,[BX+DX-32768] ; illeg + MOV CL,[BX+BP-32768] ; illeg + MOV CH,[BX+DI-32768] + MOV DL,[BX+SI-32768] + MOV DH,[BX+SP-32768] ; illeg + + MOV AL,[CX+AX-32768] ; illeg + MOV AH,[CX+BX-32768] ; illeg + MOV BL,[CX+CX-32768] ; illeg + MOV BH,[CX+DX-32768] ; illeg + MOV CL,[CX+BP-32768] ; illeg + MOV CH,[CX+DI-32768] ; illeg + MOV DL,[CX+SI-32768] ; illeg + MOV DH,[CX+SP-32768] ; illeg + + MOV AL,[DX+AX-32768] ; illeg + MOV AH,[DX+BX-32768] ; illeg + MOV BL,[DX+CX-32768] ; illeg + MOV BH,[DX+DX-32768] ; illeg + MOV CL,[DX+BP-32768] ; illeg + MOV CH,[DX+DI-32768] ; illeg + MOV DL,[DX+SI-32768] ; illeg + MOV DH,[DX+SP-32768] ; illeg + + MOV AL,[BP+AX-32768] ; illeg + MOV AH,[BP+BX-32768] ; illeg + MOV BL,[BP+CX-32768] ; illeg + MOV BH,[BP+DX-32768] ; illeg + MOV CL,[BP+BP-32768] ; illeg + MOV CH,[BP+DI-32768] + MOV DL,[BP+SI-32768] + MOV DH,[BP+SP-32768] ; illeg + + MOV AL,[DI+AX-32768] ; illeg + MOV AH,[DI+BX-32768] + MOV BL,[DI+CX-32768] ; illeg + MOV BH,[DI+DX-32768] ; illeg + MOV CL,[DI+BP-32768] + MOV CH,[DI+DI-32768] ; illeg + MOV DL,[DI+SI-32768] ; illeg + MOV DH,[DI+SP-32768] ; illeg + + MOV AL,[SI+AX-32768] ; illeg + MOV AH,[SI+BX-32768] + MOV BL,[SI+CX-32768] ; illeg + MOV BH,[SI+DX-32768] ; illeg + MOV CL,[SI+BP-32768] + MOV CH,[SI+DI-32768] ; illeg + MOV DL,[SI+SI-32768] ; illeg + MOV DH,[SI+SP-32768] ; illeg + + MOV AL,[SP+AX-32768] ; illeg + MOV AH,[SP+BX-32768] ; illeg + MOV BL,[SP+CX-32768] ; illeg + MOV BH,[SP+DX-32768] ; illeg + MOV CL,[SP+BP-32768] ; illeg + MOV CH,[SP+DI-32768] ; illeg + MOV DL,[SP+SI-32768] ; illeg + MOV DH,[SP+SP-32768] ; illeg + + MOV AL,[AX+AX+32768] ; illeg + MOV AH,[AX+BX+32768] ; illeg + MOV BL,[AX+CX+32768] ; illeg + MOV BH,[AX+DX+32768] ; illeg + MOV CL,[AX+BP+32768] ; illeg + MOV CH,[AX+DI+32768] ; illeg + MOV DL,[AX+SI+32768] ; illeg + MOV DH,[AX+SP+32768] ; illeg + + MOV AL,[BX+AX+32768] ; illeg + MOV AH,[BX+BX+32768] ; illeg + MOV BL,[BX+CX+32768] ; illeg + MOV BH,[BX+DX+32768] ; illeg + MOV CL,[BX+BP+32768] ; illeg + MOV CH,[BX+DI+32768] + MOV DL,[BX+SI+32768] + MOV DH,[BX+SP+32768] ; illeg + + MOV AL,[CX+AX+32768] ; illeg + MOV AH,[CX+BX+32768] ; illeg + MOV BL,[CX+CX+32768] ; illeg + MOV BH,[CX+DX+32768] ; illeg + MOV CL,[CX+BP+32768] ; illeg + MOV CH,[CX+DI+32768] ; illeg + MOV DL,[CX+SI+32768] ; illeg + MOV DH,[CX+SP+32768] ; illeg + + MOV AL,[DX+AX+32768] ; illeg + MOV AH,[DX+BX+32768] ; illeg + MOV BL,[DX+CX+32768] ; illeg + MOV BH,[DX+DX+32768] ; illeg + MOV CL,[DX+BP+32768] ; illeg + MOV CH,[DX+DI+32768] ; illeg + MOV DL,[DX+SI+32768] ; illeg + MOV DH,[DX+SP+32768] ; illeg + + MOV AL,[BP+AX+32768] ; illeg + MOV AH,[BP+BX+32768] ; illeg + MOV BL,[BP+CX+32768] ; illeg + MOV BH,[BP+DX+32768] ; illeg + MOV CL,[BP+BP+32768] ; illeg + MOV CH,[BP+DI+32768] + MOV DL,[BP+SI+32768] + MOV DH,[BP+SP+32768] ; illeg + + MOV AL,[DI+AX+32768] ; illeg + MOV AH,[DI+BX+32768] + MOV BL,[DI+CX+32768] ; illeg + MOV BH,[DI+DX+32768] ; illeg + MOV CL,[DI+BP+32768] + MOV CH,[DI+DI+32768] ; illeg + MOV DL,[DI+SI+32768] ; illeg + MOV DH,[DI+SP+32768] ; illeg + + MOV AL,[SI+AX+32768] ; illeg + MOV AH,[SI+BX+32768] + MOV BL,[SI+CX+32768] ; illeg + MOV BH,[SI+DX+32768] ; illeg + MOV CL,[SI+BP+32768] + MOV CH,[SI+DI+32768] ; illeg + MOV DL,[SI+SI+32768] ; illeg + MOV DH,[SI+SP+32768] ; illeg + + MOV AL,[SP+AX+32768] ; illeg + MOV AH,[SP+BX+32768] ; illeg + MOV BL,[SP+CX+32768] ; illeg + MOV BH,[SP+DX+32768] ; illeg + MOV CL,[SP+BP+32768] ; illeg + MOV CH,[SP+DI+32768] ; illeg + MOV DL,[SP+SI+32768] ; illeg + MOV DH,[SP+SP+32768] ; illeg + + MOV AL,[AX+AX-32769] ; illeg + MOV AH,[AX+BX-32769] ; illeg + MOV BL,[AX+CX-32769] ; illeg + MOV BH,[AX+DX-32769] ; illeg + MOV CL,[AX+BP-32769] ; illeg + MOV CH,[AX+DI-32769] ; illeg + MOV DL,[AX+SI-32769] ; illeg + MOV DH,[AX+SP-32769] ; illeg + + MOV AL,[BX+AX-32769] ; illeg + MOV AH,[BX+BX-32769] ; illeg + MOV BL,[BX+CX-32769] ; illeg + MOV BH,[BX+DX-32769] ; illeg + MOV CL,[BX+BP-32769] ; illeg + MOV CH,[BX+DI-32769] + MOV DL,[BX+SI-32769] + MOV DH,[BX+SP-32769] ; illeg + + MOV AL,[CX+AX-32769] ; illeg + MOV AH,[CX+BX-32769] ; illeg + MOV BL,[CX+CX-32769] ; illeg + MOV BH,[CX+DX-32769] ; illeg + MOV CL,[CX+BP-32769] ; illeg + MOV CH,[CX+DI-32769] ; illeg + MOV DL,[CX+SI-32769] ; illeg + MOV DH,[CX+SP-32769] ; illeg + + MOV AL,[DX+AX-32769] ; illeg + MOV AH,[DX+BX-32769] ; illeg + MOV BL,[DX+CX-32769] ; illeg + MOV BH,[DX+DX-32769] ; illeg + MOV CL,[DX+BP-32769] ; illeg + MOV CH,[DX+DI-32769] ; illeg + MOV DL,[DX+SI-32769] ; illeg + MOV DH,[DX+SP-32769] ; illeg + + MOV AL,[BP+AX-32769] ; illeg + MOV AH,[BP+BX-32769] ; illeg + MOV BL,[BP+CX-32769] ; illeg + MOV BH,[BP+DX-32769] ; illeg + MOV CL,[BP+BP-32769] ; illeg + MOV CH,[BP+DI-32769] + MOV DL,[BP+SI-32769] + MOV DH,[BP+SP-32769] ; illeg + + MOV AL,[DI+AX-32769] ; illeg + MOV AH,[DI+BX-32769] + MOV BL,[DI+CX-32769] ; illeg + MOV BH,[DI+DX-32769] ; illeg + MOV CL,[DI+BP-32769] + MOV CH,[DI+DI-32769] ; illeg + MOV DL,[DI+SI-32769] ; illeg + MOV DH,[DI+SP-32769] ; illeg + + MOV AL,[SI+AX-32769] ; illeg + MOV AH,[SI+BX-32769] + MOV BL,[SI+CX-32769] ; illeg + MOV BH,[SI+DX-32769] ; illeg + MOV CL,[SI+BP-32769] + MOV CH,[SI+DI-32769] ; illeg + MOV DL,[SI+SI-32769] ; illeg + MOV DH,[SI+SP-32769] ; illeg + + MOV AL,[SP+AX-32769] ; illeg + MOV AH,[SP+BX-32769] ; illeg + MOV BL,[SP+CX-32769] ; illeg + MOV BH,[SP+DX-32769] ; illeg + MOV CL,[SP+BP-32769] ; illeg + MOV CH,[SP+DI-32769] ; illeg + MOV DL,[SP+SI-32769] ; illeg + MOV DH,[SP+SP-32769] ; illeg + + MOV AL,[AX+AX+$7FFFFFFF] ; illeg + MOV AH,[AX+BX+$7FFFFFFF] ; illeg + MOV BL,[AX+CX+$7FFFFFFF] ; illeg + MOV BH,[AX+DX+$7FFFFFFF] ; illeg + MOV CL,[AX+BP+$7FFFFFFF] ; illeg + MOV CH,[AX+DI+$7FFFFFFF] ; illeg + MOV DL,[AX+SI+$7FFFFFFF] ; illeg + MOV DH,[AX+SP+$7FFFFFFF] ; illeg + + MOV AL,[BX+AX+$7FFFFFFF] ; illeg + MOV AH,[BX+BX+$7FFFFFFF] ; illeg + MOV BL,[BX+CX+$7FFFFFFF] ; illeg + MOV BH,[BX+DX+$7FFFFFFF] ; illeg + MOV CL,[BX+BP+$7FFFFFFF] ; illeg + MOV CH,[BX+DI+$7FFFFFFF] ; illeg (bounds) + MOV DL,[BX+SI+$7FFFFFFF] ; illeg (bounds) + MOV DH,[BX+SP+$7FFFFFFF] ; illeg + + MOV AL,[CX+AX+$7FFFFFFF] ; illeg + MOV AH,[CX+BX+$7FFFFFFF] ; illeg + MOV BL,[CX+CX+$7FFFFFFF] ; illeg + MOV BH,[CX+DX+$7FFFFFFF] ; illeg + MOV CL,[CX+BP+$7FFFFFFF] ; illeg + MOV CH,[CX+DI+$7FFFFFFF] ; illeg + MOV DL,[CX+SI+$7FFFFFFF] ; illeg + MOV DH,[CX+SP+$7FFFFFFF] ; illeg + + MOV AL,[DX+AX+$7FFFFFFF] ; illeg + MOV AH,[DX+BX+$7FFFFFFF] ; illeg + MOV BL,[DX+CX+$7FFFFFFF] ; illeg + MOV BH,[DX+DX+$7FFFFFFF] ; illeg + MOV CL,[DX+BP+$7FFFFFFF] ; illeg + MOV CH,[DX+DI+$7FFFFFFF] ; illeg + MOV DL,[DX+SI+$7FFFFFFF] ; illeg + MOV DH,[DX+SP+$7FFFFFFF] ; illeg + + MOV AL,[BP+AX+$7FFFFFFF] ; illeg + MOV AH,[BP+BX+$7FFFFFFF] ; illeg + MOV BL,[BP+CX+$7FFFFFFF] ; illeg + MOV BH,[BP+DX+$7FFFFFFF] ; illeg + MOV CL,[BP+BP+$7FFFFFFF] ; illeg + MOV CH,[BP+DI+$7FFFFFFF] ; illeg (bounds) + MOV DL,[BP+SI+$7FFFFFFF] ; illeg (bounds) + MOV DH,[BP+SP+$7FFFFFFF] ; illeg + + MOV AL,[DI+AX+$7FFFFFFF] ; illeg + MOV AH,[DI+BX+$7FFFFFFF] ; illeg (bounds) + MOV BL,[DI+CX+$7FFFFFFF] ; illeg + MOV BH,[DI+DX+$7FFFFFFF] ; illeg + MOV CL,[DI+BP+$7FFFFFFF] ; illeg (bounds) + MOV CH,[DI+DI+$7FFFFFFF] ; illeg + MOV DL,[DI+SI+$7FFFFFFF] ; illeg + MOV DH,[DI+SP+$7FFFFFFF] ; illeg + + MOV AL,[SI+AX+$7FFFFFFF] ; illeg + MOV AH,[SI+BX+$7FFFFFFF] ; illeg (bounds) + MOV BL,[SI+CX+$7FFFFFFF] ; illeg + MOV BH,[SI+DX+$7FFFFFFF] ; illeg + MOV CL,[SI+BP+$7FFFFFFF] ; illeg (bounds) + MOV CH,[SI+DI+$7FFFFFFF] ; illeg + MOV DL,[SI+SI+$7FFFFFFF] ; illeg + MOV DH,[SI+SP+$7FFFFFFF] ; illeg + + MOV AL,[SP+AX+$7FFFFFFF] ; illeg + MOV AH,[SP+BX+$7FFFFFFF] ; illeg + MOV BL,[SP+CX+$7FFFFFFF] ; illeg + MOV BH,[SP+DX+$7FFFFFFF] ; illeg + MOV CL,[SP+BP+$7FFFFFFF] ; illeg + MOV CH,[SP+DI+$7FFFFFFF] ; illeg + MOV DL,[SP+SI+$7FFFFFFF] ; illeg + MOV DH,[SP+SP+$7FFFFFFF] ; illeg + + MOV AL,[AX+AX-$80000000] ; illeg + MOV AH,[AX+BX-$80000000] ; illeg + MOV BL,[AX+CX-$80000000] ; illeg + MOV BH,[AX+DX-$80000000] ; illeg + MOV CL,[AX+BP-$80000000] ; illeg + MOV CH,[AX+DI-$80000000] ; illeg + MOV DL,[AX+SI-$80000000] ; illeg + MOV DH,[AX+SP-$80000000] ; illeg + + MOV AL,[BX+AX-$80000000] ; illeg + MOV AH,[BX+BX-$80000000] ; illeg + MOV BL,[BX+CX-$80000000] ; illeg + MOV BH,[BX+DX-$80000000] ; illeg + MOV CL,[BX+BP-$80000000] ; illeg + MOV CH,[BX+DI-$80000000] ; illeg (bounds) + MOV DL,[BX+SI-$80000000] ; illeg (bounds) + MOV DH,[BX+SP-$80000000] ; illeg + + MOV AL,[CX+AX-$80000000] ; illeg + MOV AH,[CX+BX-$80000000] ; illeg + MOV BL,[CX+CX-$80000000] ; illeg + MOV BH,[CX+DX-$80000000] ; illeg + MOV CL,[CX+BP-$80000000] ; illeg + MOV CH,[CX+DI-$80000000] ; illeg + MOV DL,[CX+SI-$80000000] ; illeg + MOV DH,[CX+SP-$80000000] ; illeg + + MOV AL,[DX+AX-$80000000] ; illeg + MOV AH,[DX+BX-$80000000] ; illeg + MOV BL,[DX+CX-$80000000] ; illeg + MOV BH,[DX+DX-$80000000] ; illeg + MOV CL,[DX+BP-$80000000] ; illeg + MOV CH,[DX+DI-$80000000] ; illeg + MOV DL,[DX+SI-$80000000] ; illeg + MOV DH,[DX+SP-$80000000] ; illeg + + MOV AL,[BP+AX-$80000000] ; illeg + MOV AH,[BP+BX-$80000000] ; illeg + MOV BL,[BP+CX-$80000000] ; illeg + MOV BH,[BP+DX-$80000000] ; illeg + MOV CL,[BP+BP-$80000000] ; illeg + MOV CH,[BP+DI-$80000000] ; illeg (bounds) + MOV DL,[BP+SI-$80000000] ; illeg (bounds) + MOV DH,[BP+SP-$80000000] ; illeg + + MOV AL,[DI+AX-$80000000] ; illeg + MOV AH,[DI+BX-$80000000] ; illeg (bounds) + MOV BL,[DI+CX-$80000000] ; illeg + MOV BH,[DI+DX-$80000000] ; illeg + MOV CL,[DI+BP-$80000000] ; illeg (bounds) + MOV CH,[DI+DI-$80000000] ; illeg + MOV DL,[DI+SI-$80000000] ; illeg + MOV DH,[DI+SP-$80000000] ; illeg + + MOV AL,[SI+AX-$80000000] ; illeg + MOV AH,[SI+BX-$80000000] ; illeg (bounds) + MOV BL,[SI+CX-$80000000] ; illeg + MOV BH,[SI+DX-$80000000] ; illeg + MOV CL,[SI+BP-$80000000] ; illeg (bounds) + MOV CH,[SI+DI-$80000000] ; illeg + MOV DL,[SI+SI-$80000000] ; illeg + MOV DH,[SI+SP-$80000000] ; illeg + + MOV AL,[SP+AX-$80000000] ; illeg + MOV AH,[SP+BX-$80000000] ; illeg + MOV BL,[SP+CX-$80000000] ; illeg + MOV BH,[SP+DX-$80000000] ; illeg + MOV CL,[SP+BP-$80000000] ; illeg + MOV CH,[SP+DI-$80000000] ; illeg + MOV DL,[SP+SI-$80000000] ; illeg + MOV DH,[SP+SP-$80000000] ; illeg diff --git a/as/asm/f.asm b/as/asm/f.asm new file mode 100644 index 0000000..c067bf9 --- /dev/null +++ b/as/asm/f.asm @@ -0,0 +1,114 @@ +; [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] + fadd qword [ebx] + fadd dword [ebx] + fadd st,st(1) + fadd st(1),st + fdiv qword [ebx] + fdiv dword [ebx] + fdiv st,st(1) ; special swapping for this + +; [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st + faddp st(1),st + +; [fbld fbstp] mem10r + fbld tbyte [ebx] + fbstp tbyte [ebx] + +; [fcom fcomp] [mem4r mem8r optional-st(i)] + fcom dword [ebx] + fcom qword [ebx] + fcom + fcom st(1) + +; ffree st(i) + ffree st(1) + +; [fucom fucomp fxch] optional-st(i) + fucom + fucom st(1) + +; [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] + fiadd word [ebx] + fiadd dword [ebx] + +; [fild fistp] [mem2i mem4i mem8i] + fild word [ebx] + fild dword [ebx] + fild qword [ebx] + +; [fld fstp] [mem4r mem8r mem10r st(i)] + fld dword [ebx] + fld qword [ebx] + fld tbyte [ebx] + fld st(1) + +; [fldcw fnstcw] mem2i + fldcw word [ebx] + fnstcw word [ebx] + +; [fldenv fnsave fnstenv frstor] mem + fldenv [ebx] + fnsave [ebx] + fnstenv [ebx] + frstor [ebx] + +; fnstsw [mem2i ax] + fnstsw word [ebx] + fnstsw ax + +; fst [mem4r mem8r st(i)] + fst dword [ebx] + fst qword [ebx] + fst st(1) + +; fstcw mem2i (wait) + fstcw word [ebx] + +; fstsw [mem2i ax] (wait) + fstsw word [ebx] + fstsw ax + +; [fsave fstenv] mem (wait) + fsave [ebx] + fstenv [ebx] + +; [fxxx] (no operands) + fnop ; D9D0 + fchs ; D9E0 + fabs ; D9E1 + ftst ; D9E4 + fxam ; D9E5 + fld1 ; D9E8 + fldl2t ; D9E9 + fldl2e ; D9EA + fldpi ; D9EB + fldlg2 ; D9EC + fldln2 ; D9ED + fldz ; D9EE + f2xm1 ; D9F0 + fyl2x ; D9F1 + fptan ; D9F2 + fpatan ; D9F3 + fxtract ; D9F4 + fprem1 ; D9F5 + fdecstp ; D9F6 + fincstp ; D9F7 + fprem ; D9F8 + fyl2xp1 ; D9F9 + fsqrt ; D9FA + fsincos ; D9FB + frndint ; D9FC + fscale ; D9FD + fsin ; D9FE + fcos ; D9FF + fucompp ; DAE9 + feni ; 9BDBE0 + fneni ; DBE0 + fdisi ; 9BDBE1 + fndisi ; DBE1 + fclex ; 9BDBE2 + fnclex ; DBE2 + finit ; 9BDBE3 + fninit ; DBE3 + fsetpm ; DBE4 + fcompp ; DED9 diff --git a/as/asm/fadd.asm b/as/asm/fadd.asm new file mode 100644 index 0000000..d18f002 --- /dev/null +++ b/as/asm/fadd.asm @@ -0,0 +1,271 @@ +_fadd: + PUSH BP + MOV BP,SP + MOV EAX,DWORD PTR [BP+4] + MOV EDX,DWORD PTR [BP+8] + MOV EBX,DWORD PTR [BP+12] + MOV ECX,DWORD PTR [BP+16] + CALL faddfxfy + MOV DWORD PTR _facc,EAX + MOV DWORD PTR _facc+4,EDX + POP BP + RET + +fsubfxfy: + XOR ECX,#$80000000 ; complement sign bit, fall into add routine +faddfxfy: + PUSH EBP + PUSH EDI + PUSH ESI + MOV EDI,ECX ; free CL for shifts + MOV ESI,EDX ; this mainly for consistent naming + AND ESI,#$7FFFFFFF ; discard sign so comparison is simple + AND EDI,#$7FFFFFFF + + CMP ESI,EDI + JA XBIG + JB SWAP + CMP EAX,EBX + JAE XBIG +SWAP: + XCHG EDX,ECX + XCHG ESI,EDI + XCHG EAX,EBX +XBIG: + AND ESI,#$000FFFFF ; discard exponent + AND EDI,#$000FFFFF + OR ESI,#$00100000 ; normalize + OR EDI,#$00100000 + + SHR ECX,32-(1+11) + SHR EDX,32-(1+11) + MOV EBP,ECX ; prepare to compare signs (want high bits 0) + SUB CX,DX ; get difference of signs in CX + NEG CX ; D holds sign and exponent of both throughout + CMP CX,#(64-11)+2 + JAE TO_DONE1 ; x dominates y + XOR BP,DX + AND BP,#$0800 ; see if signs are same + JNZ TO_SUBTRACT ; else roundoff reg EBP is 0 + + CMP CL,#32 + JAE TO_ADD_BIGSHIFT + SHRD EBP,EBX,CL + SHRD EBX,EDI,CL + SHR EDI,CL + ADD EAX,EBX + ADC ESI,EDI + SUB EBX,EBX + +; result DX(1+11):SI:AX:BP:BX but needs normalization + +NORMALIZE: + MOV CX,DX + AND CX,#$07FF + TEST ESI,#$00200000 + JZ NORMALIZE2 + BR LOVERFLOW + +TO_DONE1: + JMP DONE1 + +TO_SUBTRACT: + BR SUBTRACT + +TO_ADD_BIGSHIFT: + BR ADD_BIGSHIFT + +TO_NORMLITTLE: + BR NORMLITTLE + +; result DX(1):CX(11):SI:AX:BP:BX + +NORMALIZE2: + SHRD EDI,ESI,32-11 + ; top 11 bits of ESI known 0 and BSR is slooow + BSR EDI,EDI ; index of leading 1 bit in EDI is 11..31 in DI + JZ TO_NORMLITTLE ; ESI is zero (flag wrong in Intel Manual) + SUB DI,#31 + NEG DI + PUSH CX ; gr + MOV CX,DI ; rr + SHLD ESI,EAX,CL + SHLD EAX,EBP,CL + SHLD EBP,EBX,CL + SHL EBX,CL + POP CX ; rr + SUB CX,DI + JC UNDERFLOW + +ROUND: + CMP EBP,#$80000000 ; test roundoff register + JA ROUNDUP + JB DONE ; no rounding + TEST EBX,EBX + JNZ ROUNDUP + TEST AL,#1 ; ambiguous case, round to even + JZ DONE ; even, no rounding +ROUNDUP: + ADD EAX,#1 + ADC ESI,#0 + SUB EBP,EBP + SUB EBX,EBX + TEST ESI,#$00200000 + JNZ LOVERFLOW ; rounding may cause overflow! + +DONE: + AND DX,#$0800 ; extract sign of largest and result + OR DX,CX ; include exponent with sign +DONE1: + SHL EDX,32-(1+11) + AND ESI,#$000FFFFF ; discard normalization bit + OR EDX,ESI + POP ESI + POP EDI + POP EBP + RET + +UNDERFLOW: ; should have error message here +ANSWER0: + SUB EDX,EDX + MOV EAX,EDX + POP ESI + POP EDI + POP EBP + RET + +LOVERFLOW: ; carry bit must be right-shifted back in + SHR ESI,1 + RCR EAX,1 + RCR EBP,1 + RCR EBX,1 + INC CX + CMP CX,#$0800 + JNZ ROUND + +OVERFLOW: ; should have error message here + MOV EDX,#$FFE00000 ; + infinity + SUB EAX,EAX + POP ESI + POP EDI + POP EBP + RET + +ADD_BIGSHIFT: + SUB CL,#32 + SHRD EBP,EBX,CL + SHRD EBX,EDI,CL + SHR EDI,CL + ADD EAX,EDI + ADC ESI,#0 + XCHG EBP,EBX + BR NORMALIZE + +NORMLITTLE: + SHLD ESI,EAX,32-(1+11) + SHLD EAX,EBP,32-(1+11) + SHLD EBP,EBX,32-(1+11) + SHL EBX,20 + SUB CL,#32-(1+11) + JC UNDERFLOW + BR NORMALIZE2 + +SUBTRACT: + SUB EBP,EBP ; set up roundoff register + CMP CL,#32 + JAE SUBTRACT_BIGSHIFT + SHRD EBP,EBX,CL + SHRD EBX,EDI,CL + SHR EDI,CL + NEG EBP + SBB EAX,EBX + SBB ESI,EDI + SUB EBX,EBX + MOV CX,DX + AND CX,#$07FF + BR NORMALIZE2 + +SUBTRACT_BIGSHIFT: + SUB CL,#32 + SHRD EBP,EBX,CL + SHRD EBX,EDI,CL + SHR EDI,CL + NEG EBX + NEG EBP + SBB EBX,#0 + SBB EAX,EDI + SBB ESI,#0 + XCHG EBP,EBX + MOV CX,DX + AND CX,#$07FF + BR NORMALIZE2 + +TO_ANSWER0: + BR ANSWER0 + +TO_OVERFLOW: + JMP TO_OVERFLOW + +TO_UNDERFLOW: + BR UNDERFLOW + +fmulfxfy: + PUSH EBP + PUSH EDI + PUSH ESI + MOV ESI,EDX ; free DX for multiplications + MOV EDI,ECX ; this mainly for consistent naming + SHR EDX,32-(1+11) + SHR ECX,32-(1+11) + MOV BP,DX + XOR BP,CX + AND BP,#$0800 ; extract sign + AND DX,#$07FF ; exp(x) + JZ TO_ANSWER0 + AND CX,#$07FF ; exp(y) + JZ TO_ANSWER0 + ADD CX,DX + SUB CX,#$0400 + JB TO_UNDERFLOW + CMP CX,#$07FF + JA TO_OVERFLOW ; probably not quite right + + AND ESI,#$000FFFFF ; discard sign and exponent + AND EDI,#$000FFFFF + OR ESI,#$00100000 ; normalize + OR EDI,#$00100000 + +; exponent is in CX, sign in BP, operands in ESI:EAX and EDI:EBX, DX is free +; product to go in ESI:EAX:EBP:EBX +; terminology: x * y = (x32:x0) * (y32:y0) = x32y32 + x32y0 + x0y32 +x0y0 + + PUSH CX + PUSH BP + MOV ECX,EAX + MUL EBX ; x0y0 + MOV EBP,EDX ; x0y0.high in EBP + XCHG EBX,EAX ; x0y0.low in EBX (final), y0 in EAX + MUL ESI ; x32y0 + PUSH EAX ; x32y0.low on stack + PUSH EDX ; x32y0.high on stack + MOV EAX,ESI + MUL EDI ; x32y32 + MOV ESI,EDX ; x32y32.high in ESI (final except carries) + XCHG ECX,EAX ; x32y32.low in ECX, x0 in EAX + MUL EDI ; x0y32 + + ADD EBP,EAX ; x0y0.high + x0y32.low + POP EAX ; x32y0.high + ADC EAX,EDX ; x32y0.high + x0y32.high + ADC ESI,#0 + POP EDX ; x32y0.low + ADD EBP,EDX ; (x0y0.high + x0y32.low) + x32y0.low + ADC EAX,ECX ; (x32y0.high + x0y32.high) + x32y32.low + ADC ESI,#0 + POP DX ; sign + POP CX ; exponent + ADD CX,#13 ; temp fixup + BR NORMALIZE2 + +_facc: + .word 0,0 diff --git a/as/asm/farcall.asm b/as/asm/farcall.asm new file mode 100644 index 0000000..6a779d9 --- /dev/null +++ b/as/asm/farcall.asm @@ -0,0 +1,10 @@ +call 1:2 +call far [1] +use32 +call far [1] + +use16 +jmp 1:2 +jmp far [1] +use32 +jmp far [1] diff --git a/as/asm/group1.asm b/as/asm/group1.asm new file mode 100644 index 0000000..fe2fb45 --- /dev/null +++ b/as/asm/group1.asm @@ -0,0 +1,31 @@ + ADD AL,#3 + ADD AX,#$1234 + ADD EAX,#$12345678 + ADD BL,#3 + ADD BX,#$1234 + ADD EBX,#$12345678 + ADD BYTE [BX],#3 + ADD BYTE 3[BX],#4 + ADD BYTE [BX+SI],#4 + ADD WORD [BX],#$1234 + ADD DWORD [BX],#$12345678 + ADD BYTE [BX],#3 + ADD WORD [BX],#-3 + ADD DWORD [BX],#-3 + ADD CL,BL + ADD CX,BX + ADD ECX,EBX + ADD [BX],CL + ADD [BX],CX + ADD [BX],ECX + ADD CL,[BX] + ADD CX,[BX] + ADD ECX,[BX] + + ADC CL,BL + AND CL,BL + CMP CL,BL + OR CL,BL + SUB CL,BL + SBB CL,BL + XOR CL,BL diff --git a/as/asm/group6.asm b/as/asm/group6.asm new file mode 100644 index 0000000..f742672 --- /dev/null +++ b/as/asm/group6.asm @@ -0,0 +1,24 @@ +; group6.asm +; 0F 00 /nnn + +; LLDT r/m16 nnn = 010 +; LTR r/m16 nnn = 011 +; SLDT r/m16 nnn = 000 +; STR r/m16 nnn = 001 +; VERR r/m16 nnn = 100 +; VERW r/m16 nnn = 101 + + LLDT AL ; illeg size + LLDT EAX ; illeg size + LLDT WORD $1234 ; immed not allowed + LLDT DS ; segreg not allowed + + LLDT AX + LLDT [BX] + LLDT [EAX] + + LTR BX + SLDT [BP] + STR [EBX] + VERR CX + VERW [SI] diff --git a/as/asm/group7.asm b/as/asm/group7.asm new file mode 100644 index 0000000..0df497c --- /dev/null +++ b/as/asm/group7.asm @@ -0,0 +1,34 @@ +; group7.asm +; 0F 01 /nnn + +; INVLPG m nnn = 111 +; LGDT m16&32 nnn = 010 +; LIDT m16&32 nnn = 011 +; LMSW r/m16 nnn = 110 +; SGDT m nnn = 000 +; SIDT m nnn = 001 +; SMSW r/m16 nnn = 100 + + LGDT EAX ; register not allowed + LGDT #$1234 ; immed not allowed + LGDT WORD PTR [BX] ; illegal size + + LGDT [BX] + LGDT PWORD PTR [BX] + LGDT FWORD PTR [BX] + LGDT [EAX] + + INVLPG [EDI] + SGDT [BP] + SIDT [EBX] + + LMSW AL ; illeg size + LMSW EAX ; illeg size + LMSW #$1234 ; immed not allowed + LMSW DS ; segreg not allowed + + LMSW AX + LMSW [BX] + LMSW [EAX] + + SMSW BX diff --git a/as/asm/imul.asm b/as/asm/imul.asm new file mode 100644 index 0000000..e2772c2 --- /dev/null +++ b/as/asm/imul.asm @@ -0,0 +1,33 @@ + use32 + + imul bl + imul byte ptr [esi] + imul bx + imul word ptr [esi] + imul ebx + imul dword ptr [esi] + + imul ax,bx + imul ax,[esi] + imul eax,ebx + imul eax,[esi] + + imul ax,bx,22 + imul ax,[esi],22 + imul eax,ebx,22 + imul eax,[esi],22 + + imul ax,[22] + imul eax,[22] + imul ax,#22 + imul eax,#22 + + imul ax,bx,300 + imul ax,[esi],300 + imul eax,ebx,300000 + imul eax,[esi],300000 + + imul ax,[300] + imul eax,[300000] + imul ax,#300 + imul eax,#300000 diff --git a/as/asm/incdec.asm b/as/asm/incdec.asm new file mode 100644 index 0000000..573861c --- /dev/null +++ b/as/asm/incdec.asm @@ -0,0 +1,83 @@ + INC AL + INC AH + INC BL + INC BH + INC CL + INC CH + INC DL + INC DH + INC #1 ; illeg + INC BYTE #1 ; illeg + INC [BX] ; illeg + INC BYTE [BX] + + INC AX + INC BX + INC CX + INC DX + INC SP + INC BP + INC SI + INC DI + INC CS ; illeg + INC DS ; illeg + INC ES ; illeg + INC FS ; illeg + INC GS ; illeg + INC #$1234 ; illeg + INC WORD #$1234 ; illeg + INC WORD [BX] + + INC EAX + INC EBX + INC ECX + INC EDX + INC ESP + INC EBP + INC ESI + INC EDI + INC #$12345678 ; illeg + INC DWORD #$12345678 ; illeg + INC DWORD [BX] + + DEC AL + DEC AH + DEC BL + DEC BH + DEC CL + DEC CH + DEC DL + DEC DH + DEC #1 ; illeg + DEC BYTE #1 ; illeg + DEC [BX] ; illeg + DEC BYTE [BX] + + DEC AX + DEC BX + DEC CX + DEC DX + DEC SP + DEC BP + DEC SI + DEC DI + DEC CS ; illeg + DEC DS ; illeg + DEC ES ; illeg + DEC FS ; illeg + DEC GS ; illeg + DEC #$1234 ; illeg + DEC WORD #$1234 ; illeg + DEC WORD [BX] + + DEC EAX + DEC EBX + DEC ECX + DEC EDX + DEC ESP + DEC EBP + DEC ESI + DEC EDI + DEC #$12345678 ; illeg + DEC DWORD #$12345678 ; illeg + DEC DWORD [BX] diff --git a/as/asm/inher.asm b/as/asm/inher.asm new file mode 100644 index 0000000..f1343fa --- /dev/null +++ b/as/asm/inher.asm @@ -0,0 +1,127 @@ +; INHER.ASM + +; INHER opcodes + + AAA + AAS + + CLC + CLD + CLI + CLTS + CMC + CMPSB + + DAA + DAS + + HLT + + INTO + INSB + + LAHF + LEAVE + LOCK + LODSB + + MOVSB + + NOP + + OUTSB + + REP + REPE + REPNE + + SAHF + SCASB + STC + STD + STI + STOSB + + WAIT + +; INHER16 and INHER32 opcodes + + USE16 + + CBW + CWD + CWDE + CDQ + CMPSW + CMPSD + + INSW + INSD + IRET + IRETD + + LODSW + LODSD + + MOVSW + MOVSD + + OUTSW + OUTSD + + POPA + POPAD + POPF + POPFD + PUSHA + PUSHAD + PUSHF + PUSHFD + + SCASW + SCASD + STOSW + STOSW + + XLAT + XLATB + + USE32 + + CBW + CWD + CWDE + CDQ + CMPSW + CMPSD + + INSW + INSD + IRET + IRETD + + LODSW + LODSD + + MOVSW + MOVSD + + OUTSW + OUTSD + + POPA + POPAD + POPF + POPFD + PUSHA + PUSHAD + PUSHF + PUSHFD + + SCASW + SCASD + STOSW + STOSW + + XLAT + XLATB diff --git a/as/asm/inout.asm b/as/asm/inout.asm new file mode 100644 index 0000000..3f0a3f2 --- /dev/null +++ b/as/asm/inout.asm @@ -0,0 +1,25 @@ + IN EAX,DX ; plain IN is no longer allowed + INB + IN AL,DX + INW + IN AX,DX + IN EAX,DX + IN AL,$20 + IN AL,$101 + IN AX,$20 + IN AX,$101 + IN EAX,$20 + IN EAX,$101 + + OUTB DX,EAX ; plain OUT is no longer allowed + OUTB + OUT DX,AL + OUTW + OUT DX,AX + OUT DX,EAX + OUT $20,AL + OUT $101,AL + OUT $20,AX + OUT #101,AX + OUT $20,EAX + OUT $101,EAX diff --git a/as/asm/movspec.asm b/as/asm/movspec.asm new file mode 100644 index 0000000..a4f9c15 --- /dev/null +++ b/as/asm/movspec.asm @@ -0,0 +1,246 @@ +mov eax,cr0 +mov eax,cr2 +mov eax,cr3 +mov eax,dr0 +mov eax,dr1 +mov eax,dr2 +mov eax,dr3 +mov eax,dr6 +mov eax,dr7 +mov eax,tr3 +mov eax,tr4 +mov eax,tr5 +mov eax,tr6 +mov eax,tr7 + +mov cr0,eax +mov cr2,eax +mov cr3,eax +mov dr0,eax +mov dr1,eax +mov dr2,eax +mov dr3,eax +mov dr6,eax +mov dr7,eax +mov tr3,eax +mov tr4,eax +mov tr5,eax +mov tr6,eax +mov tr7,eax + + +mov ebx,cr0 +mov ebx,cr2 +mov ebx,cr3 +mov ebx,dr0 +mov ebx,dr1 +mov ebx,dr2 +mov ebx,dr3 +mov ebx,dr6 +mov ebx,dr7 +mov ebx,tr3 +mov ebx,tr4 +mov ebx,tr5 +mov ebx,tr6 +mov ebx,tr7 + +mov cr0,ebx +mov cr2,ebx +mov cr3,ebx +mov dr0,ebx +mov dr1,ebx +mov dr2,ebx +mov dr3,ebx +mov dr6,ebx +mov dr7,ebx +mov tr3,ebx +mov tr4,ebx +mov tr5,ebx +mov tr6,ebx +mov tr7,ebx + + +mov ecx,cr0 +mov ecx,cr2 +mov ecx,cr3 +mov ecx,dr0 +mov ecx,dr1 +mov ecx,dr2 +mov ecx,dr3 +mov ecx,dr6 +mov ecx,dr7 +mov ecx,tr3 +mov ecx,tr4 +mov ecx,tr5 +mov ecx,tr6 +mov ecx,tr7 + +mov cr0,ecx +mov cr2,ecx +mov cr3,ecx +mov dr0,ecx +mov dr1,ecx +mov dr2,ecx +mov dr3,ecx +mov dr6,ecx +mov dr7,ecx +mov tr3,ecx +mov tr4,ecx +mov tr5,ecx +mov tr6,ecx +mov tr7,ecx + + +mov edx,cr0 +mov edx,cr2 +mov edx,cr3 +mov edx,dr0 +mov edx,dr1 +mov edx,dr2 +mov edx,dr3 +mov edx,dr6 +mov edx,dr7 +mov edx,tr3 +mov edx,tr4 +mov edx,tr5 +mov edx,tr6 +mov edx,tr7 + +mov cr0,edx +mov cr2,edx +mov cr3,edx +mov dr0,edx +mov dr1,edx +mov dr2,edx +mov dr3,edx +mov dr6,edx +mov dr7,edx +mov tr3,edx +mov tr4,edx +mov tr5,edx +mov tr6,edx +mov tr7,edx + + +mov esi,cr0 +mov esi,cr2 +mov esi,cr3 +mov esi,dr0 +mov esi,dr1 +mov esi,dr2 +mov esi,dr3 +mov esi,dr6 +mov esi,dr7 +mov esi,tr3 +mov esi,tr4 +mov esi,tr5 +mov esi,tr6 +mov esi,tr7 + +mov cr0,esi +mov cr2,esi +mov cr3,esi +mov dr0,esi +mov dr1,esi +mov dr2,esi +mov dr3,esi +mov dr6,esi +mov dr7,esi +mov tr3,esi +mov tr4,esi +mov tr5,esi +mov tr6,esi +mov tr7,esi + + +mov edi,cr0 +mov edi,cr2 +mov edi,cr3 +mov edi,dr0 +mov edi,dr1 +mov edi,dr2 +mov edi,dr3 +mov edi,dr6 +mov edi,dr7 +mov edi,tr3 +mov edi,tr4 +mov edi,tr5 +mov edi,tr6 +mov edi,tr7 + +mov cr0,edi +mov cr2,edi +mov cr3,edi +mov dr0,edi +mov dr1,edi +mov dr2,edi +mov dr3,edi +mov dr6,edi +mov dr7,edi +mov tr3,edi +mov tr4,edi +mov tr5,edi +mov tr6,edi +mov tr7,edi + + +mov esp,cr0 +mov esp,cr2 +mov esp,cr3 +mov esp,dr0 +mov esp,dr1 +mov esp,dr2 +mov esp,dr3 +mov esp,dr6 +mov esp,dr7 +mov esp,tr3 +mov esp,tr4 +mov esp,tr5 +mov esp,tr6 +mov esp,tr7 + +mov cr0,esp +mov cr2,esp +mov cr3,esp +mov dr0,esp +mov dr1,esp +mov dr2,esp +mov dr3,esp +mov dr6,esp +mov dr7,esp +mov tr3,esp +mov tr4,esp +mov tr5,esp +mov tr6,esp +mov tr7,esp + + +mov ebp,cr0 +mov ebp,cr2 +mov ebp,cr3 +mov ebp,dr0 +mov ebp,dr1 +mov ebp,dr2 +mov ebp,dr3 +mov ebp,dr6 +mov ebp,dr7 +mov ebp,tr3 +mov ebp,tr4 +mov ebp,tr5 +mov ebp,tr6 +mov ebp,tr7 + +mov cr0,ebp +mov cr2,ebp +mov cr3,ebp +mov dr0,ebp +mov dr1,ebp +mov dr2,ebp +mov dr3,ebp +mov dr6,ebp +mov dr7,ebp +mov tr3,ebp +mov tr4,ebp +mov tr5,ebp +mov tr6,ebp +mov tr7,ebp diff --git a/as/asm/pushpop.asm b/as/asm/pushpop.asm new file mode 100644 index 0000000..b45117a --- /dev/null +++ b/as/asm/pushpop.asm @@ -0,0 +1,86 @@ + PUSH AL ; illeg + PUSH AH ; illeg + PUSH BL ; illeg + PUSH BH ; illeg + PUSH CL ; illeg + PUSH CH ; illeg + PUSH DL ; illeg + PUSH DH ; illeg + PUSH #1 ; illeg + PUSH BYTE #1 ; illeg + PUSH [BX] ; illeg + PUSH BYTE [BX] ; illeg + PUSH WORD #-1 ; right way to push a signed byte value + + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SP + PUSH BP + PUSH SI + PUSH DI + PUSH CS + PUSH DS + PUSH ES + PUSH FS + PUSH GS + PUSH SS + PUSH #$1234 ; illeg + PUSH WORD #$1234 + PUSH WORD [BX] + + PUSH EAX + PUSH EBX + PUSH ECX + PUSH EDX + PUSH ESP + PUSH EBP + PUSH ESI + PUSH EDI + PUSH #$12345678 ; illeg + PUSH DWORD #$12345678 + PUSH DWORD [BX] + + POP AL ; illeg + POP AH ; illeg + POP BL ; illeg + POP BH ; illeg + POP CL ; illeg + POP CH ; illeg + POP DL ; illeg + POP DH ; illeg + POP #1 ; illeg + POP BYTE #1 ; illeg + POP [BX] ; illeg + POP BYTE [BX] ; illeg + + POP AX + POP BX + POP CX + POP DX + POP SP + POP BP + POP SI + POP DI + POP CS ; illeg + POP DS + POP ES + POP FS + POP GS + POP SS + POP #$1234 ; illeg + POP WORD #$1234 ; illeg + POP WORD [BX] + + POP EAX + POP EBX + POP ECX + POP EDX + POP ESP + POP EBP + POP ESI + POP EDI + POP #$12345678 ; illeg + POP DWORD #$12345678 ; illeg + POP DWORD [BX] diff --git a/as/asm/seg.asm b/as/asm/seg.asm new file mode 100644 index 0000000..0394615 --- /dev/null +++ b/as/asm/seg.asm @@ -0,0 +1,6 @@ + SEG CS + SEG DS + SEG ES + SEG FS + SEG GS + SEG SS diff --git a/as/asm/shdouble.asm b/as/asm/shdouble.asm new file mode 100644 index 0000000..1080ece --- /dev/null +++ b/as/asm/shdouble.asm @@ -0,0 +1,34 @@ +; SHDOUBLE.ASM + +ILLEGALS EQU 1 + +; 0F A4 SHLD r/m16,r16,imm8 3/7 +; 0F A4 SHLD r/m32,r32,imm8 3/7 +; 0F A5 SHLD r/m16,r16,CL 3/7 +; 0F A5 SHLD r/m32,r32,CL 3/7 + +; 0F AC SHRD r/m16,r16,imm8 3/7 +; 0F AC SHRD r/m32,r32,imm8 3/7 +; 0F AD SHRD r/m16,r16,CL 3/7 +; 0F AD SHRD r/m32,r32,CL 3/7 + +IF ILLEGALS + SHLD AL,BL,8 ; byte size + SHLD AX,8,8 ; immediate source + SHLD AX,DS,8 ; segment register + SHLD AX,[BX],8 ; non-register source + SHLD AX,BX,256 ; shift count too big + SHLD AL,BL,8 ; byte size +ENDIF + + SHLD BX,CX,3 + SHLD EDX,ESI,1 + SHLD CX,BX,CL + SHLD ESI,EDX,1 + SHLD [BX],CX,3 + SHLD [BX],ECX,1 + SHLD [SI],BX,CL + SHLD [SI],EBX,CL + + SHRD BX,CX,3 + SHRD CX,BX,CL diff --git a/as/asm/shift.asm b/as/asm/shift.asm new file mode 100644 index 0000000..35cc23f --- /dev/null +++ b/as/asm/shift.asm @@ -0,0 +1,119 @@ + RCL AL,CL + RCL AH,CL + RCL BL,CL + RCL BH,CL + RCL CL,CL + RCL CH,CL + RCL DL,CL + RCL DH,CL + RCL #1,CL ; illeg + RCL [BX],CL ; illeg + RCL BYTE [BX],CL + + RCL AX,CL + RCL BX,CL + RCL CX,CL + RCL DX,CL + RCL SP,CL + RCL BP,CL + RCL SI,CL + RCL DI,CL + RCL CS,CL ; illeg + RCL DS,CL ; illeg + RCL ES,CL ; illeg + RCL FS,CL ; illeg + RCL GS,CL ; illeg + RCL WORD [BX],CL + + RCL EAX,CL + RCL EBX,CL + RCL ECX,CL + RCL EDX,CL + RCL ESP,CL + RCL EBP,CL + RCL ESI,CL + RCL EDI,CL + RCL DWORD [BX],CL + + RCL AL,1 + RCL AH,1 + RCL BL,1 + RCL BH,1 + RCL CL,1 + RCL CH,1 + RCL DL,1 + RCL DH,1 + RCL #1,1 ; illeg + RCL [BX],1 ; illeg + RCL BYTE [BX],1 + + RCL AX,1 + RCL BX,1 + RCL CX,1 + RCL DX,1 + RCL SP,1 + RCL BP,1 + RCL SI,1 + RCL DI,1 + RCL CS,1 ; illeg + RCL DS,1 ; illeg + RCL ES,1 ; illeg + RCL FS,1 ; illeg + RCL GS,1 ; illeg + RCL WORD [BX],1 + + RCL EAX,1 + RCL EBX,1 + RCL ECX,1 + RCL EDX,1 + RCL ESP,1 + RCL EBP,1 + RCL ESI,1 + RCL EDI,1 + RCL DWORD [BX],1 + + RCL AL,15 + RCL AH,15 + RCL BL,15 + RCL BH,15 + RCL CL,15 + RCL CH,15 + RCL DL,15 + RCL DH,15 + RCL #1,15 ; illeg + RCL [BX],15 ; illeg + RCL BYTE [BX],15 + RCL AL,$1000 + + RCL AX,15 + RCL BX,15 + RCL CX,15 + RCL DX,15 + RCL SP,15 + RCL BP,15 + RCL SI,15 + RCL DI,15 + RCL CS,15 ; illeg + RCL DS,15 ; illeg + RCL ES,15 ; illeg + RCL FS,15 ; illeg + RCL GS,15 ; illeg + RCL WORD [BX],15 + + RCL EAX,15 + RCL EBX,15 + RCL ECX,15 + RCL EDX,15 + RCL ESP,15 + RCL EBP,15 + RCL ESI,15 + RCL EDI,15 + RCL DWORD [BX],15 + + RCR AX,7 + ROL AX,7 + ROR AX,7 + SAL AX,7 + SAR AX,7 + SHL AX,7 + SHR AX,7 diff --git a/as/asm/summary.as b/as/asm/summary.as new file mode 100644 index 0000000..cd62e37 --- /dev/null +++ b/as/asm/summary.as @@ -0,0 +1,385 @@ +general: + ; AL,imm8 + ; AX,imm16 + ; EAX,imm32 + ; r/m8,imm8 + ; r/m16,imm16 + ; r/m32.imm32 + ; r/m16,signed imm8 + ; r/m32,signed imm8 + ; r/m8,r8 + ; r/m16,r16 + ; r/m32,r32 + ; r8,r/m8 + ; r16,r/m16 + ; r32,r/m32 + +shiftcount: + ; 1 + ; CL + ; imm8 +unary alterable: + ; r/m8 + ; r/m16 + ; r/m32 + + AAA + AAD ; [unsupported base] + AAM ; [unsupported base] + AAS + ADC ; general + ADD ; general + AND ; general + ARPL ; r/m16,r16 + BOUND ; r16,m16&16 + BOUND ; r32,m32&32 + BSF ; r16,r/m16 + BSF ; r32,r/m32 + BSR ; r16,r/m16 + BSR ; r32,r/m32 + BSWAP ; r32 + BT ; r/m16,r16 + BT ; r/m32,r32 + BT ; r/m16,imm8 + BT ; r/m32,imm8 + BTC ; r/m16,r16 + BTC ; r/m32,r32 + BTC ; r/m16,imm8 + BTC ; r/m32,imm8 + BTR ; r/m16,r16 + BTR ; r/m32,r32 + BTR ; r/m16,imm8 + BTR ; r/m32,imm8 + BTS ; r/m16,r16 + BTS ; r/m32,r32 + BTS ; r/m16,imm8 + BTS ; r/m32,imm8 + CALL ; rel16 + CALL ; r/m16 + CALL ; ptr16:16 + CALL ; m16:16 + CALL ; rel32 + CALL ; r/m32 + CALL ; ptr16:32 + CALL ; m16:32 + CBW + CDQ + CLC + CLD + CLI + CLTS + CMC + CMP ; general + CMPS ; [segreg:]m8,m8 + CMPS ; [segreg:]m16,m16 + CMPS ; [segreg:]m32,m32 + CMPSB + CMPSW + CMPSD + CMPXCHG ; r/m8,r8 + CMPXCHG ; r/m16,r16 + CMPXCHG ; r/m32,r32 + CWD + CWDE + DAA + DAS + DEC ; unary alterable + DEC ; r16 + DEC ; r32 + DIV ; AL,r/m8 + DIV ; AX,r/m16 + DIV ; EAX,r/m32 + ENTER ; imm16,imm8 + HLT + IDIV ; AL,r/m8 + IDIV ; AX,r/m16 + IDIV ; EAX,r/m32 + IMUL ; r/m8 + IMUL ; r/m16 + IMUL ; r/m32 + IMUL ; r16,r/m16 + IMUL ; r32,r/m32 + IMUL ; r16,r/m16,imm8 + IMUL ; r32,r/m32,imm8 + IMUL ; r16,imm8 + IMUL ; r32,imm8 + IMUL ; r16,r/m16,imm16 + IMUL ; r32,r/m32,imm32 + IMUL ; r16,imm16 + IMUL ; r32,imm32 + IN ; AL,imm8 + IN ; AX,imm8 + IN ; EAX,imm8 + IN ; AL,DX + IN ; AX,DX + IN ; EAX,DX + INC ; unary alterable + INC ; r16 + INC ; r32 + INSB + INSW + INSD + INT ; imm8 + INTO + INVD + INVLPG ; m + IRET + IRETD + JCC ; rel8 + JCC ; rel16/32 + JA + JAE + JB + JBE + JC + JCXZ + JECXZ + JE + JG + JGE + JL + JLE + JNA + JNAE + JNB + JNBE + JNC + JNE + JNG + JNGE + JNL + JNLE + JNO + JNP + JNS + JNZ + JO + JP + JPE + JPO + JS + JZ + JMP ; rel8 + JMP ; rel16 + JMP ; r/m16 + JMP ; ptr16:16 + JMP ; m16:16 + JMP ; rel32 + JMP ; r/m32 + JMP ; ptr16:32 + JMP ; m16:32 + LAHF + LAR ; r16,r/m16 + LAR ; r32,r/m32 + LEA ; r16,m + LEA ; r32,m + LEAVE + LGDT ; m16&32 + LIDT ; m16&32 + LDS ; r16,m16:16 + LDS ; r32,m16:32 + LES ; r16,m16:16 + LES ; r32,m16:32 + LFS ; r16,m16:16 + LFS ; r32,m16:32 + LGS ; r16,m16:16 + LGS ; r32,m16:32 + LSS ; r16,m16:16 + LSS ; r32,m16:32 + LLDT ; r/m16 + LMSW ; r/m16 + LOCK + LODS ; [segreg:]m8 + LODS ; [segreg:]m16 + LODS ; [segreg:]m32 + LODSB + LODSW + LODSD + LOOP ; rel8 + LOOPE ; rel8 + LOOPZ ; rel8 + LOOPNE ; rel8 + LOOPNZ ; rel8 + LSL ; r16,r/m16 + LSL ; r32,r/m32 + LTR ; r/m16 + MOV ; r/m8,r8 + MOV ; r/m16,r16 + MOV ; r/m32,r32 + MOV ; r8,r/m8 + MOV ; r16,r/m16 + MOV ; r32,r/m32 + MOV ; r/m16,Sreg + MOV ; Sreg,r/m16 + MOV ; AL,moffs8 + MOV ; AX,moffs16 + MOV ; EAX,moffs32 + MOV ; moffs8,AL + MOV ; moffs16,AX + MOV ; moffs32,EAX + MOV ; r8,imm8 + MOV ; r16,imm16 + MOV ; r32,imm32 + MOV ; r32,CR0/CR2/CR3 + MOV ; r/m8,imm8 + MOV ; r/m16,imm16 + MOV ; r/m32,imm32 + MOV ; r32,CR0/CR2/CR3 + MOV ; CR0/CR2/CR3,r32 + MOV ; r32,DR0/DR1/DR2/DR3/DR6/DR7 + MOV ; DR0/DR1/DR2/DR3/DR6/DR7,r32 + MOV ; r32,TR6/TR7 + MOV ; TR6/TR7,r32 + MOVS ; [segreg:]m8,m8 + MOVS ; [segreg:]m16,m16 + MOVS ; [segreg:]m32,m32 + MOVSB + MOVSW + MOVSD + MOVSX ; r16,r/m8 + MOVSX ; r32,r/m8 + MOVSX ; r32,r/m16 + MOVZX ; r16,r/m8 + MOVZX ; r32,r/m8 + MOVZX ; r32,r/m16 + MUL ; AL,r/m8 + MUL ; AX,r/m16 + MUL ; EAX,r/m32 + NEG ; unary alterable + NOP + NOT ; unary alterable + OR ; general + OUT ; imm8,AL + OUT ; imm8,AX + OUT ; imm8,EAX + OUT ; DX,AL + OUT ; DX,AX + OUT ; DX,EAX + OUTS ; [segreg:]m8 + OUTS ; [segreg:]m16 + OUTS ; [segreg:]m32 + OUTSB + OUTSW + OUTSD + POP ; m16 + POP ; m32 + POP ; r16 + POP ; r32 + POP ; DS + POP ; ES + POP ; FS + POP ; GS + POP ; SS + POPA + POPAD + POPF + POPFD + PUSH ; m16 + PUSH ; m32 + PUSH ; r16 + PUSH ; r32 + PUSH ; imm8 + PUSH ; imm16 + PUSH ; imm32 + PUSH ; CS + PUSH ; DS + PUSH ; ES + PUSH ; FS + PUSH ; GS + PUSH ; SS + PUSHA + PUSHAD + PUSHF + PUSHFD + RCL ; shiftcount + RCR ; shiftcount + ROL ; shiftcount + ROR ; shiftcount + REP ; INS/MOVS/OUTS/STOS + REPE ; CMPS/SCAS + REPNE ; CMPS/SCAS + RET + RET ; imm16 + SAHF + SAL ; shiftcount + SAR ; shiftcount + SHL ; shiftcount + SHR ; shiftcount + SBB ; general + SCASB + SCASW + SCASD + SETA ; r/m8 + SETAE ; r/m8 + SETB ; r/m8 + SETBE ; r/m8 + SETC ; r/m8 + SETE ; r/m8 + SETG ; r/m8 + SETGE ; r/m8 + SETL ; r/m8 + SETLE ; r/m8 + SETNA ; r/m8 + SETNAE ; r/m8 + SETNB ; r/m8 + SETNBE ; r/m8 + SETNC ; r/m8 + SETNE ; r/m8 + SETNG ; r/m8 + SETNGE ; r/m8 + SETNL ; r/m8 + SETNLE ; r/m8 + SETNO ; r/m8 + SETNP ; r/m8 + SETNS ; r/m8 + SETNZ ; r/m8 + SETO ; r/m8 + SETP ; r/m8 + SETPE ; r/m8 + SETPO ; r/m8 + SETS ; r/m8 + SETZ ; r/m8 + SGDT ; m + SHLD ; r/m16,r16,imm8 + SHLD ; r/m32,r32,imm8 + SHLD ; r/m16,r16,CL + SHLD ; r/m32,r32,CL + SHRD ; r/m16,r16,imm8 + SHRD ; r/m32,r32,imm8 + SHRD ; r/m16,r16,CL + SHRD ; r/m32,r32,CL + SIDT ; m + SLDT ; r/m16 + SMSW ; r/m16 + STC + STD + STI + STOSB + STOSW + STOSD + STR ; r/m16 + SUB ; general + TEST ; AL,imm8 + TEST ; AX,imm16 + TEST ; EAX,imm32 + TEST ; r/m8,imm8 + TEST ; r/m16,imm16 + TEST ; r/m32,imm32 + TEST ; r/m8,r8 + TEST ; r/m16,r16 + TEST ; r/m32/r32 + VERR ; r/m16 + VERW ; r/m16 + WAIT + WBINVD + XADD ; r/m8,r8 + XADD ; r/m16,r16 + XADD ; r/m32,r32 + XCHG ; AX,r16 + XCHG ; EAX,r32 + XCHG ; r/m8,r8 + XCHG ; r/m16,r16 + XCHG ; r/m32,r32 + XLAT ; [segreg:]m8 + XLATB + XOR ; general diff --git a/as/asm/xchg.asm b/as/asm/xchg.asm new file mode 100644 index 0000000..f05157f --- /dev/null +++ b/as/asm/xchg.asm @@ -0,0 +1,103 @@ + XCHG AX,BL ; illeg + XCHG AX,BYTE [BX] ; illeg + XCHG AX,DS ; illeg + XCHG AX,#1 ; illeg + + XCHG AX,AX + XCHG AX,BX + XCHG AX,CX + XCHG AX,DX + XCHG AX,SP + XCHG AX,BP + XCHG AX,SI + XCHG AX,DI + + XCHG AX,AX + XCHG BX,AX + XCHG CX,AX + XCHG DX,AX + XCHG SP,AX + XCHG BP,AX + XCHG SI,AX + XCHG DI,AX + + XCHG EAX,EAX + XCHG EAX,EBX + XCHG EAX,ECX + XCHG EAX,EDX + XCHG EAX,ESP + XCHG EAX,EBP + XCHG EAX,ESI + XCHG EAX,EDI + + XCHG EAX,EAX + XCHG EBX,EAX + XCHG ECX,EAX + XCHG EDX,EAX + XCHG ESP,EAX + XCHG EBP,EAX + XCHG ESI,EAX + XCHG EDI,EAX + + XCHG AL,AL + XCHG AL,AH + XCHG AL,BL + XCHG AL,BH + XCHG BL,CL + XCHG BL,CH + XCHG BL,DL + XCHG BL,DH + + XCHG [BX],AL + XCHG [BX],AH + XCHG [BX],BL + XCHG [BX],BH + XCHG [BX],CL + XCHG [BX],CH + XCHG [BX],DL + XCHG [BX],DH + + XCHG AL,[BX] + XCHG AH,[BX] + XCHG BL,[BX] + XCHG BH,[BX] + XCHG CL,[BX] + XCHG CH,[BX] + XCHG DL,[BX] + XCHG DH,[BX] + + XCHG [BX],AX + XCHG [BX],BX + XCHG [BX],CX + XCHG [BX],DX + XCHG [BX],SP + XCHG [BX],BP + XCHG [BX],SI + XCHG [BX],DI + + XCHG AX,[BX] + XCHG BX,[BX] + XCHG CX,[BX] + XCHG DX,[BX] + XCHG SP,[BX] + XCHG BP,[BX] + XCHG SI,[BX] + XCHG DI,[BX] + + XCHG [BX],EAX + XCHG [BX],EBX + XCHG [BX],ECX + XCHG [BX],EDX + XCHG [BX],ESP + XCHG [BX],EBP + XCHG [BX],ESI + XCHG [BX],EDI + + XCHG AX,[EBX] + XCHG BX,[EBX] + XCHG CX,[EBX] + XCHG DX,[EBX] + XCHG SP,[EBX] + XCHG BP,[EBX] + XCHG SI,[EBX] + XCHG DI,[EBX] diff --git a/as/assemble.c b/as/assemble.c new file mode 100644 index 0000000..c438ce6 --- /dev/null +++ b/as/assemble.c @@ -0,0 +1,309 @@ +/* assemble.c - main loop for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "globvar.h" +#include "opcode.h" +#include "scan.h" + +PRIVATE bool_t nocolonlabel; /* set for labels not followed by ':' */ +PRIVATE void (*routine) P((void)); +PRIVATE pfv rout_table[] = +{ + pelse, + pelseif, + pelsifc, + pendif, + pif, + pifc, + + /* start of non-conditionals */ + palign, + pasciz, + pblkw, + pblock, + pbss, + pcomm, + pcomm1, + pdata, + pendb, + penter, + pentry, + pequ, + peven, + pexport, + pfail, + pfcb, + pfcc, + pfdb, + pfqb, + pget, + pglobl, + pident, + pimport, + plcomm, + plcomm1, + plist, + ploc, + pmaclist, + pmacro, + pmap, + porg, + pproceof, + prmb, + psect, + pset, + psetdp, + ptext, +#ifdef I80386 + puse16, + puse32, +#endif + pwarn, + /* end of pseudo-ops */ + +#ifdef I80386 + mbcc, + mbswap, + mcall, + mcalli, + mdivmul, + menter, + mEwGw, + mExGx, + mf_inher, + mf_m, + mf_m2, + mf_m2_ax, + mf_m2_m4, + mf_m2_m4_m8, + mf_m4_m8_optst, + mf_m4_m8_st, + mf_m4_m8_stst, + mf_m4_m8_m10_st, + mf_m10, + mf_optst, + mf_st, + mf_stst, + mf_w_inher, + mf_w_m, + mf_w_m2, + mf_w_m2_ax, + mgroup1, + mgroup2, + mgroup6, + mgroup7, + mgroup8, + mGvEv, + mGvMa, + mGvMp, + mimul, + min, + mincdec, + minher, + minher16, + minher32, + minhera, + mint, + mjcc, + mjcxz, + mlea, + mmov, + mmovx, + mnegnot, + mout, + mpushpop, + mret, + mseg, + msetcc, + mshdouble, + mtest, + mxchg, +#endif /* I80386 */ + +#ifdef MC6809 + mall, /* all address modes allowed, like LDA */ + malter, /* all but immediate, like STA */ + mimmed, /* immediate only (ANDCC, ORCC) */ + mindex, /* indexed (LEA's) */ + minher, /* inherent, like CLC or CLRA */ + mlong, /* long branches */ + mshort, /* short branches */ + msstak, /* S-stack (PSHS, PULS) */ + mswap, /* TFR, EXG */ + mustak, /* U-stack (PSHU,PULU) */ +#endif /* MC6809 */ +}; + +FORWARD void asline P((void)); + +/* + This uses registers as follows: A is for work and is not preserved by + the subroutines.B holds the last symbol code, X usually points to data + about the last symbol, U usually holds the value of last expression + or symbol, and Y points to the current char. The value in Y is needed + by READCH and GETSYM. EXPRES needs B and Y, and returns a value in U. + If the expression starts with an identifier, X must point to its string. + LOOKUP needs a string pointer in X and length in A. It returns a table + pointer in X (unless not assembling and not found), symbol type in A + and overflow in CC. +*/ + +PUBLIC void assemble() +{ + while (TRUE) + { + asline(); + if (label != NULL) /* must be confirmed if still set */ + { /* it is nulled by EQU, COMM and SET */ +#ifndef MC6809 +#define NEEDENDLABEL ILLAB + if (nocolonlabel) + error(NEEDENDLABEL); +#endif + label->type |= LABIT; /* confirm, perhaps redundant */ + if (label->type & REDBIT) + { + /* REDBIT meant 'GLOBLBIT' while LABIT was not set. */ + label->type |= EXPBIT; + label->type &= ~REDBIT; + } + if ((mcount | popflags) == 0) + /* unaccompanied label, display adr like EQU and SET */ + showlabel(); + label = NULL; /* reset for next line */ + } + skipline(); + listline(); + genbin(); + genobj(); + binmbuf = lc += lcjump +#ifdef I80386 + + immcount +#endif + ; + } +} + +PRIVATE void asline() +{ + register struct sym_s *symptr; + + postb = popflags = pcrflag = +#ifdef I80386 + sprefix = oprefix = aprefix = +#endif + immcount = lastexp.data = lcjump = 0; +#ifdef I80386 + sib = NO_SIB; +#endif +#if SIZEOF_OFFSET_T > 2 + fqflag = +#endif + fdflag = fcflag = FALSE; + readline(); + getsym(); + if (sym != IDENT) /* expect label, mnemonic or macro */ + return; /* anything else is a comment */ + symptr = gsymptr; + if (!ifflag) + /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */ + { + if (symptr == NULL || !(symptr->type & MNREGBIT) || + symptr->data & REGBIT || + symptr->value_reg_or_op.op.routine >= MIN_NONCOND) + return; + } + else if (!(symptr->type & (MACBIT | MNREGBIT))) + /* not macro, op, pseudo-op or register, expect label */ + { + if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */ + { + sym = COLON; + ++lineptr; + } + if (symptr->type & (LABIT | VARBIT)) + { + if (symptr->type & REDBIT) + labelerror(RELAB); + label = symptr; + } + else if (checksegrel(symptr)) + { + symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */ +#ifdef MC6809 +#if 0 + if (sym == COLON) + symptr->type |= EXPBIT; +#endif +#endif + symptr->data = (symptr->data & FORBIT) | lcdata; + /* remember if forward referenced */ + symptr->value_reg_or_op.value = lc; + /* unless changed by EQU,COMM or SET */ + label = symptr; + } + getsym(); + if (sym != IDENT) + { + if (sym == EQOP) + { + getsym(); + pequ(); + } + return; /* anything but ident is comment */ + } + symptr = gsymptr; + } + if (symptr->type & MACBIT) + { + entermac(symptr); + return; + } + if (!(symptr->type & MNREGBIT)) + { + error(OPEXP); + return; + } + if (symptr->data & REGBIT) + { + error(REGUID); + return; + } + mnsize = 0; + if ((page = (symptr->data & (PAGE1 | PAGE2))) != 0) + { +#ifdef MNSIZE + if (page == (PAGE1 | PAGE2)) + { + mnsize = 1; + page = 0; + } + else +#endif + { +#ifdef PAGE2_OPCODE + if (page == PAGE2) + page = PAGE2_OPCODE; + else +#endif + page = PAGE1_OPCODE; + mcount = 1; + } + } + opcode = symptr->value_reg_or_op.op.opcode; + routine = rout_table[symptr->value_reg_or_op.op.routine]; + getsym(); + (*routine)(); + if (sym != EOLSYM) + error(JUNK_AFTER_OPERANDS); +#ifdef I80386 + if (aprefix != 0) + ++mcount; + if (oprefix != 0) + ++mcount; + if (sprefix != 0) + ++mcount; +#endif +} diff --git a/as/bin/calljmp.bin b/as/bin/calljmp.bin Binary files differnew file mode 100644 index 0000000..90c022f --- /dev/null +++ b/as/bin/calljmp.bin diff --git a/as/bin/ea.bin b/as/bin/ea.bin Binary files differnew file mode 100644 index 0000000..5edc0b0 --- /dev/null +++ b/as/bin/ea.bin diff --git a/as/bin/each.bin b/as/bin/each.bin Binary files differnew file mode 100644 index 0000000..211155f --- /dev/null +++ b/as/bin/each.bin diff --git a/as/bin/f.bin b/as/bin/f.bin Binary files differnew file mode 100644 index 0000000..ce695a0 --- /dev/null +++ b/as/bin/f.bin diff --git a/as/bin/fadd.bin b/as/bin/fadd.bin Binary files differnew file mode 100644 index 0000000..9afa6fc --- /dev/null +++ b/as/bin/fadd.bin diff --git a/as/bin/farcall.bin b/as/bin/farcall.bin Binary files differnew file mode 100644 index 0000000..797a87c --- /dev/null +++ b/as/bin/farcall.bin diff --git a/as/bin/group1.bin b/as/bin/group1.bin Binary files differnew file mode 100644 index 0000000..64a01bf --- /dev/null +++ b/as/bin/group1.bin diff --git a/as/bin/group6.bin b/as/bin/group6.bin Binary files differnew file mode 100644 index 0000000..22ff663 --- /dev/null +++ b/as/bin/group6.bin diff --git a/as/bin/group7.bin b/as/bin/group7.bin Binary files differnew file mode 100644 index 0000000..9570eee --- /dev/null +++ b/as/bin/group7.bin diff --git a/as/bin/imul.bin b/as/bin/imul.bin Binary files differnew file mode 100644 index 0000000..2b8ea16 --- /dev/null +++ b/as/bin/imul.bin diff --git a/as/bin/incdec.bin b/as/bin/incdec.bin Binary files differnew file mode 100644 index 0000000..676e5fa --- /dev/null +++ b/as/bin/incdec.bin diff --git a/as/bin/inher.bin b/as/bin/inher.bin Binary files differnew file mode 100644 index 0000000..b37b3eb --- /dev/null +++ b/as/bin/inher.bin diff --git a/as/bin/inout.bin b/as/bin/inout.bin Binary files differnew file mode 100644 index 0000000..a215490 --- /dev/null +++ b/as/bin/inout.bin diff --git a/as/bin/movspec.bin b/as/bin/movspec.bin Binary files differnew file mode 100644 index 0000000..6a5ef0a --- /dev/null +++ b/as/bin/movspec.bin diff --git a/as/bin/pushpop.bin b/as/bin/pushpop.bin Binary files differnew file mode 100644 index 0000000..f95d6b5 --- /dev/null +++ b/as/bin/pushpop.bin diff --git a/as/bin/seg.bin b/as/bin/seg.bin Binary files differnew file mode 100644 index 0000000..43445a6 --- /dev/null +++ b/as/bin/seg.bin diff --git a/as/bin/shdouble.bin b/as/bin/shdouble.bin Binary files differnew file mode 100644 index 0000000..91bda37 --- /dev/null +++ b/as/bin/shdouble.bin diff --git a/as/bin/shift.bin b/as/bin/shift.bin Binary files differnew file mode 100644 index 0000000..1e31fac --- /dev/null +++ b/as/bin/shift.bin diff --git a/as/bin/xchg.bin b/as/bin/xchg.bin Binary files differnew file mode 100644 index 0000000..6455b67 --- /dev/null +++ b/as/bin/xchg.bin diff --git a/as/byteord.h b/as/byteord.h new file mode 100644 index 0000000..a0d14e1 --- /dev/null +++ b/as/byteord.h @@ -0,0 +1,18 @@ +/* byteord.h - byte order dependencies for C compiler, assembler, linker */ + +/* These are for the targets of everything and for linker source too. */ + +#ifdef I8086 +# define BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ +#endif + +#ifdef I80386 +# define BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 +#endif + +#ifdef MC6809 +# define BIG_ENDIAN 1 /* byte order in words is high-low */ +# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ +#endif @@ -0,0 +1,9 @@ +for i in `ls asm/*.asm` +do + j=`basename $i .asm` + ./as asm/$j.asm -b $j.bin -o $j.obj > /dev/null + cmp $j.bin bin/$j.bin + cmp $j.obj obj1/$j.obj + rm $j.bin $j.obj +done + diff --git a/as/const.h b/as/const.h new file mode 100644 index 0000000..78523e5 --- /dev/null +++ b/as/const.h @@ -0,0 +1,409 @@ +#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */ +#define LOW_BYTE 0 /* must be changed for big-endian */ + +/* const.h - constants for assembler */ + +/* major switches */ + +#define I80386 /* generate 80386 code */ +#undef MC6809 /* generate 6809 code */ +#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */ +#undef SOS_EDOS /* source OS is EDOS */ + +/* defaults */ + +#define DIRCHAR '/' /* character separating filename from dir */ +#define INBUFSIZE 8192 +#define SOS_EOLSTR "\012" + +/* defaults modified by switches */ + +#ifdef SOS_EDOS +# undef INBUFSIZE +# define INBUFSIZE 512 +# undef SOS_EOLSTR +# define SOS_EOLSTR "\015\012" +# define STAKSIZ 256 /* table grows up to stack less this */ +#endif + +/* booleans */ + +#define FALSE 0 +#define TRUE 1 + +/* ASCII constants */ + +#define ETB 23 + +/* C tricks */ + +#define EXTERN extern +#define FORWARD static +#define PRIVATE static +#define PUBLIC +#define NULL 0 + +/* O/S constants */ + +#define CREAT_PERMS 0666 +#define EOF (-1) +#define STDIN 0 +#define STDOUT 1 + +enum +{ +/* Register codes (internal to assembler). */ +#ifdef I80386 + +/* Index regs must be first. */ + BPREG, + BXREG, + DIREG, + SIREG, +#define MAX16BITINDREG SIREG + + EAXREG, + EBPREG, + EBXREG, + ECXREG, + EDIREG, + EDXREG, + ESIREG, + ESPREG, +#define MAXINDREG ESPREG + + AXREG, + CXREG, + DXREG, + SPREG, + + AHREG, + ALREG, + BHREG, + BLREG, + CHREG, + CLREG, + DHREG, + DLREG, + + CSREG, + DSREG, + ESREG, + FSREG, + GSREG, + SSREG, + + CR0REG, + CR2REG, + CR3REG, + DR0REG, + DR1REG, + DR2REG, + DR3REG, + DR6REG, + DR7REG, + TR3REG, + TR4REG, + TR5REG, + TR6REG, + TR7REG, + + ST0REG, + ST1REG, + ST2REG, + ST3REG, + ST4REG, + ST5REG, + ST6REG, + ST7REG, +#endif /* I80386 */ + +#ifdef MC6809 + +/* Index regs must be first, then PC. */ + SREG, + UREG, + XREG, + YREG, +#define MAXINDREG YREG + + PCREG, + AREG, + BREG, + CCREG, + DPREG, + DREG, +#endif /* MC6809 */ + + NOREG +}; + +#ifdef I80386 +enum +{ +/* Type and size keywords. */ + BYTEOP, + DWORDOP, + FWORDOP, + FAROP, + PTROP, + PWORDOP, + QWORDOP, + TBYTEOP, + WORDOP +}; +#endif /* I80386 */ + +/* special chars */ + +#define EOL 0 +#define MACROCHAR '?' + +enum +{ +/* Symbol codes. */ + +/* The first 2 must be from chars in identifiers. */ + IDENT, + INTCONST, + +/* The next few are best for other possibly-multi-char tokens. */ + ADDOP, /* also ++ */ + BINCONST, + CHARCONST, + GREATERTHAN, /* also >> and context-sensitive */ + HEXCONST, + LESSTHAN, /* also << and context-sensitive */ + SUBOP, /* also -- */ + WHITESPACE, + + ANDOP, + COMMA, + EOLSYM, + EQOP, + IMMEDIATE, + INDIRECT, + LBRACKET, + LPAREN, + MACROARG, + NOTOP, + OROP, + OTHERSYM, + POSTINCOP, + PREDECOP, + RBRACKET, + RPAREN, + SLASH, /* context-sensitive */ + SLOP, + SROP, + STAR, /* context-sensitive */ + STRINGCONST, + COLON +}; + +enum +{ +/* Error codes. */ + +/* Syntax errors. */ + COMEXP, + DELEXP, + FACEXP, + IREGEXP, + LABEXP, + LPEXP, + OPEXP, + RBEXP, + REGEXP, + RPEXP, + SPEXP, + +/* Expression errors. */ + ABSREQ, + NONIMPREQ, + RELBAD, + +/* Label errors. */ + ILLAB, + MACUID, + MISLAB, + MNUID, + REGUID, + RELAB, + UNBLAB, + UNLAB, + VARLAB, + +/* Addressing errors. */ + ABOUNDS, + DBOUNDS, + ILLMOD, + ILLREG, + +/* Control structure errors. */ + ELSEBAD, +#define ELSEIFBAD ELSEBAD + ENDBBAD, +#define ENDIFBAD ELSEBAD + EOFBLOCK, + EOFIF, + EOFLC, + EOFMAC, + FAILERR, + +/* Overflow errors. */ + BLOCKOV, + BWRAP, + COUNTOV, + COUNTUN, + GETOV, + IFOV, + + LINLONG, + MACOV, + OBJSYMOV, + OWRITE, + PAROV, + SYMOV, + SYMOUTOV, + +/* I/O errors. */ + OBJOUT, + +/* Miscellaneous errors. */ + AL_AX_EAX_EXP, + CTLINS, + FURTHER, + ILL_IMM_MODE, + ILL_IND_TO_IND, + ILL_IND, + ILL_IND_PTR, + ILL_SCALE, + ILL_SECTION, + ILL_SEG_REG, + ILL_SOURCE_EA, + ILL_SIZE, + IMM_REQ, + INDEX_REG_EXP, + IND_REQ, + MISMATCHED_SIZE, + NOIMPORT, + REENTER, + REL_REQ, + REPEATED_DISPL, + SEGREL, + SEG_REG_REQ, + SIZE_UNK, + UNKNOWN_ESCAPE_SEQUENCE, + + FP_REG_REQ, + FP_REG_NOT_ALLOWED, + ILL_FP_REG, + ILL_FP_REG_PAIR, + JUNK_AFTER_OPERANDS, + + ALREADY, + +/* Warnings. */ +#define MINWARN SHORTB + SHORTB +}; + +/* symbol table entry */ + + /* type entry contains following flags */ +#define ENTBIT (1<<0) /* entry point (= OBJ_N_MASK) */ +#define COMMBIT (1<<1) /* common */ +#define LABIT (1<<2) /* label (a PC location or defined by EQU) */ +#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */ +#define MACBIT (1<<4) /* macro */ +#define REDBIT (1<<5) /* redefined (if with LABIT or VARBIT), to do + * with SA_MASK (if with COMMBIT), otherwise + * means globl */ +#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */ +#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */ + + /* data entry contains following flags, valid */ + /* for expressions as well as syms */ +#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT | PAGE1 */ +#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT | PAGE2 */ +#define REGBIT (1<<2) /* register = MNREGBIT | REGBIT */ +#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT | SIZEBIT */ +#define SEGM 0x0F /* 1st 4 bits reused for segment if !MNREGBIT */ +#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */ +#define FORBIT (1<<5) /* forward referenced */ +#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */ +#define UNDBIT (1<<7) /* undefined */ + +/* object code format (Introl) */ + +#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */ + +#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */ + +#define OBJ_ABS 0x40 /* absolute code command */ +#define OBJ_OFFSET_REL 0x80 /* offset relocation command */ +#define OBJ_SET_SEG 0x20 /* set segment command */ +#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */ +#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */ +#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */ +#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */ + +#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */ +#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */ +oops - RELBIT misplaced +#endif +#define OBJ_E_MASK 0x80 /* exported bit (symbols) */ +#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */ +oops - EXPBIT misplaced +#endif +#define OBJ_I_MASK 0x40 /* imported bit (symbols) */ +#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */ +oops - IMPBIT misplaced +#endif +#define OBJ_N_MASK 0x01 /* entry bit (symbols) */ +#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */ +oops - ENTBIT misplaced +#endif +#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */ +#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */ +#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */ +#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */ + +#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */ +#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */ + +#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */ +#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */ + +#define SYMLIS_NAMELEN 26 +#define SYMLIS_LEN (sizeof (struct sym_listing_s)) + +#define FILNAMLEN 64 /* max length of a file name */ +#define LINLEN 256 /* max length of input line */ +#define LINUM_LEN 5 /* length of formatted line number */ + +#define SPTSIZ 1024 /* number of symbol ptrs */ + /* pseudo-op flags */ +#define POPHI 1 /* set to print hi byte of adr */ +#define POPLO 2 /* to print lo byte of ADR */ +#define POPLC 4 /* to print LC */ +#define POPLONG 8 /* to print high word of ADR */ +#define MAXBLOCK 8 /* max nesting level of BLOCK stack */ +#define MAXGET 8 /* max nesting level of GET stack */ +#define MAXIF 8 /* max nesting level of IF stack */ +#define MACPSIZ (128 / sizeof (struct schain_s)) + /* size of macro param buffer */ +#define MAXMAC 8 /* max nesting level of macro stack */ +#define NLOC 16 /* number of location counters */ +#ifdef I80386 +#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */ +#endif + +/* special segments */ + +#define BSSLOC 3 +#define DATALOC 3 +#define DPLOC 2 +#define STRLOC 1 +#define TEXTLOC 0 diff --git a/as/error.c b/as/error.c new file mode 100644 index 0000000..6cb4da7 --- /dev/null +++ b/as/error.c @@ -0,0 +1,106 @@ +/* error.c - error routines for assembler */ + +#include "const.h" +#include "type.h" + +#ifdef STDC_HEADERS_MISSING +char *strcpy P((char *s1, const char *s2)); +#else +#undef NULL +#include <string.h> +#endif + +PRIVATE char *errormessage[] = +{ + "comma expected", + "delimiter expected", + "factor expected", + "index register expected", + "label expected", + "left parentheses expected", + "opcode expected", + "right bracket expected", + "register expected", + "right parentheses expected", + "space expected", + "absolute expression required", + "non-imported expression required", + "relocation impossible", + "illegal label", + "MACRO used as identifier", + "missing label", + "opcode used as identifier", + "register used as identifier", + "redefined label", + "unbound label", + "undefined label", + "variable used as label", + "address out of bounds", + "data out of bounds", + "illegal address mode", + "illegal register", + "no matching IF", + "no matching BLOCK", + "end of file in BLOCK", + "end of file in IF", + "location counter was undefined at end", + "end of file in MACRO", + "user-generated error", + "BLOCK stack overflow", + "binary file wrap-around", + "counter overflow", + "counter underflow", + "GET stack overflow", + "IF stack overflow", + "line too long", + "MACRO stack overflow", + "object symbol table overflow", + "program overwrite", + "parameter table overflow", + "symbol table overflow", + "output symbol table overflow", + "error writing object file", + "al, ax or eax expected", + "control character in string", + "futher errors suppressed", + "illegal immediate mode", + "illegal indirect to indirect", + "illegal indirection", + "illegal indirection from previous 'ptr'", + "illegal scale", + "illegal section", + "illegal segment register", + "illegal source effective address", + "illegal size", + "immediate expression expected", + "index register expected", + "indirect expression required", + "mismatched size", + "no imports with binary file output", + "multiple ENTER pseudo-ops", + "relative expression required", + "repeated displacement", + "segment or relocatability redefined", + "segment register required", + "size unknown", + "unknown escape sequence", + "FP register required", + "FP register not allowed", + "illegal FP register", + "illegal FP register pair", + "junk after operands", + "already defined", + "short branch would do", + "unknown error", +}; + +/* build null-terminated error message for given error at given spot */ + +PUBLIC char *build_error_message(errnum, buf) +error_pt errnum; +char *buf; +{ + if (errnum >= sizeof errormessage / sizeof errormessage[0]) + errnum = sizeof errormessage / sizeof errormessage[0] - 1; + return strcpy(buf, errormessage[errnum]); +} diff --git a/as/express.c b/as/express.c new file mode 100644 index 0000000..54dff2f --- /dev/null +++ b/as/express.c @@ -0,0 +1,382 @@ +/* express.c - expression handler for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "globvar.h" +#include "scan.h" +#include "source.h" + +FORWARD void experror P((error_pt errnum)); +FORWARD void expundefined P((void)); +FORWARD void simple2 P((void)); +FORWARD void simple P((void)); +FORWARD void term P((void)); +FORWARD void factor2 P((void)); + +PUBLIC void absexpres() +{ + expres(); + chkabs(); +} + +/* check lastexp.data is abs */ + +PUBLIC void chkabs() +{ + if (lastexp.data & RELBIT) + { + if (pass != 0) + error(ABSREQ); + expundefined(); + } +} + +PRIVATE void experror(errnum) +error_pt errnum; +{ + error(errnum); + expundefined(); +} + +PRIVATE void expundefined() +{ + lastexp.data = FORBIT | UNDBIT; +} + +PUBLIC void nonimpexpres() +{ + expres(); + if (lastexp.data & IMPBIT) + experror(NONIMPREQ); +} + +/* generate relocation error if pass 2, make lastexp.data forward&undefined */ + +PUBLIC void showrelbad() +{ + if (pass != 0) + error(RELBAD); + expundefined(); +} + +PUBLIC void symabsexpres() +{ + getsym(); + absexpres(); +} + +PUBLIC void symexpres() +{ + getsym(); + expres(); +} + +/* + expres() parses expression = simple expression [op simple expression], + where op is =, < or >. + Parameters: sym, number in number, identifier from symname to lineptr - 1. + Returns value in lastexp. +*/ + +PUBLIC void expres() +{ + offset_t leftoffset; + + simple(); + leftoffset = lastexp.offset; + if (sym == EQOP) + { + simple2(); + if (leftoffset == lastexp.offset) + lastexp.offset = -1; + else + lastexp.offset = 0; + } + else if (sym == LESSTHAN) + { + /* context-sensitive, LESSTHAN really means less than here */ + simple2(); + if (leftoffset < lastexp.offset) + lastexp.offset = -1; + else + lastexp.offset = 0; + } + else if (sym == GREATERTHAN) + { + /* context-sensitive, GREATERTHAN really means greater than here */ + simple2(); + if (leftoffset > lastexp.offset) + lastexp.offset = -1; + else + lastexp.offset = 0; + } +} + +/* get symbol and 2nd simple expression, check both rel or both abs */ + +PRIVATE void simple2() +{ + unsigned char leftdata; + + leftdata = lastexp.data; + getsym(); + simple(); + if ((leftdata | lastexp.data) & IMPBIT || + (leftdata ^ lastexp.data) & (RELBIT | SEGM)) + showrelbad(); + else + lastexp.data = (leftdata & lastexp.data) & ~(RELBIT | SEGM); +} + +/* + simple() parses simple expression = [+-] term {op term}, + where op is +, -, or \ (OR). +*/ + +PRIVATE void simple() +{ + offset_t leftoffset; + unsigned char leftdata; + + if (sym == ADDOP || sym == SUBOP) + lastexp.data = lastexp.offset = 0; + else + term(); + while (TRUE) + { + leftoffset = lastexp.offset; + leftdata = lastexp.data; + if (sym == ADDOP) + { + getsym(); + term(); + if (leftdata & lastexp.data & RELBIT) + showrelbad(); /* rel + rel no good */ + else + lastexp.data |= leftdata; + lastexp.offset += leftoffset; + } + else if (sym == SUBOP) + { + getsym(); + term(); + /* check not abs - rel or rel - rel with mismatch */ + if (lastexp.data & RELBIT && + (!(leftdata & RELBIT) || + (leftdata | lastexp.data) & IMPBIT || + (leftdata ^ lastexp.data) & (RELBIT | SEGM))) + showrelbad(); + else + lastexp.data = ((leftdata | lastexp.data) & ~(RELBIT | SEGM)) + | ((leftdata ^ lastexp.data) & (RELBIT | SEGM)); + lastexp.offset = leftoffset - lastexp.offset; + } + else if (sym == OROP) + { + getsym(); + term(); + lastexp.data |= leftdata; + chkabs(); /* both must be absolute */ + lastexp.offset |= leftoffset; + } + else + return; + } +} + +/* term() parses term = factor {op factor}, where op is *, /, &, <<, or >>. */ + +PRIVATE void term() +{ + offset_t leftoffset; + + factor(); + while (TRUE) + { + leftoffset = lastexp.offset; + if (sym == STAR) + { + /* context-sensitive, STAR means multiplication here */ + factor2(); + lastexp.offset *= leftoffset; + } + else if (sym == SLASH) + { + /* context-sensitive, SLASH means division here */ + factor2(); + lastexp.offset = leftoffset / lastexp.offset; + } + else if (sym == ANDOP) + { + factor2(); + lastexp.offset &= leftoffset; + } + else if (sym == SLOP) + { + factor2(); + lastexp.offset = leftoffset << lastexp.offset; + } + else if (sym == SROP) + { + factor2(); + lastexp.offset = leftoffset >> lastexp.offset; + } + else + return; + } +} + +/* get symbol and 2nd or later factor, check both abs */ + +PRIVATE void factor2() +{ + unsigned char leftdata; + + leftdata = lastexp.data; + getsym(); + factor(); + lastexp.data |= leftdata; + chkabs(); +} + +/* + factor() parses factor = number | identifier | * | (expression) | ! factor, + ! is complementation. Returns value in lastexp.offset, possible flags + IMPBIT, FORBIT, RELBIT and UNDBIT in lastexp.data, and segment in SEGM + part of lastexp.data, and lastexp.sym at imported symbol if IMPBIT. + If the factor is an identifier, LOOKUP is used to get its value + (so the ident is installed in the symbol table if necessary, with + default flags inidata). If the identifier is not a label, + (could be imported, or later in the program), its FORBIT is set. + The expression FORBIT, IMPBIT, RELBIT, UNDBIT and SEGM are then + taken from the identifier. +*/ + +PUBLIC void factor() +{ + switch (sym) + { + case SLASH: + /* context-sensitive, SLASH means a hex number here */ + context_hexconst(); + case INTCONST: + lastexp.data = 0; /* absolute & not forward or undefined */ + lastexp.offset = number; + getsym(); + return; + case IDENT: + { + register struct sym_s *symptr; + + symptr = gsymptr; + if (symptr->type & (MNREGBIT | MACBIT)) + experror(symptr->type & MACBIT ? MACUID : + symptr->data & REGBIT ? REGUID : MNUID); + else + { + if (!(symptr->type & (LABIT | VARBIT))) + { + symptr->data |= FORBIT; + lastexp.sym = symptr; + } + if (pass == 0) + { + lastexp.data = symptr->data & + (FORBIT | RELBIT | UNDBIT | SEGM); + /* possible flags for pass 1 */ + lastexp.offset = symptr->value_reg_or_op.value; + } + else + { + if ((lastexp.data = symptr->data) & IMPBIT) + lastexp.offset = 0; /* value != 0 for commons */ + /* OK even if UNDBIT */ + else + { + lastexp.offset = symptr->value_reg_or_op.value; + if (lastexp.data & UNDBIT) + experror(UNBLAB); + } + } + } + getsym(); + return; + } + case LBRACKET: + if (!asld_compatible) + break; /* error, LPAREN is the grouping symbol */ + getsym(); + expres(); + if (sym != RBRACKET) + error(RBEXP); + else + getsym(); + return; + case LPAREN: + if (asld_compatible) + break; /* error, LBRACKET is the grouping symbol */ + getsym(); + expres(); + if (sym != RPAREN) + error(RPEXP); + else + getsym(); + return; + case NOTOP: + getsym(); + factor(); + chkabs(); + lastexp.offset = ~lastexp.offset; + return; + case STAR: + /* context-sensitive, STAR means location counter here */ + lastexp.offset = lc; + if ((lastexp.data = lcdata) & UNDBIT && pass != 0) + experror(UNBLAB); + getsym(); + return; + } + experror(FACEXP); +} + +/* + string compare for IFC/ELSEIFC + expects (<string1>,<string2>) + returns logical value in lastexp +*/ + +PUBLIC void scompare() +{ + /* prepare flags for OK, lastexp.offset for error */ + lastexp.data = lastexp.offset = 0; + if (sym != LPAREN) + experror(LPEXP); + else + { + register char *string1; + register char *string2; + + for (string2 = string1 = lineptr; *string2 != ')'; ++string2) + if (*string2 == 0 || *string2 == ')') + { + symname = string2; + experror(COMEXP); + return; + } + while (*string1++ == *string2++) + ; + if (string2[-1] == ')') + { + if (string1[-1] == ',') + lastexp.offset = TRUE; /* else leave FALSE */ + } + else /* FALSE, keep reading to verify syntax */ + for (; *string2 != ')'; ++string2) + if (*string2 == 0 || *string2 == ',') + { + symname = string2; + experror(RPEXP); + } + } +} diff --git a/as/file.h b/as/file.h new file mode 100644 index 0000000..1272d47 --- /dev/null +++ b/as/file.h @@ -0,0 +1,12 @@ +/* file.h - global variables involving files for assembler */ + +EXTERN fd_t binfil; /* binary output file (0 = memory) */ +EXTERN char *filnamptr; /* file name pointer */ +EXTERN fd_t infil0; /* initial input file */ +EXTERN fd_t infil; /* current input file (stacked, 0 = memory) */ +EXTERN unsigned char infiln; /* innum when file was opened */ +EXTERN unsigned char innum; /* counter for calls to open */ +EXTERN fd_t lstfil; /* list output file (0 = standard) */ +EXTERN fd_t objfil; /* object output file */ +EXTERN fd_t symfil; /* symbol table output file */ +EXTERN char *truefilename; /* in case actual source name is a tmpname */ diff --git a/as/flag.h b/as/flag.h new file mode 100644 index 0000000..791dcc1 --- /dev/null +++ b/as/flag.h @@ -0,0 +1,5 @@ +/* flag.h - global structured-flag variables for assembler */ + +EXTERN struct flags_s list; /* listing on/off */ +EXTERN struct flags_s maclist; /* list macros on/off */ +EXTERN struct flags_s warn; /* warnings on/off */ diff --git a/as/genbin.c b/as/genbin.c new file mode 100644 index 0000000..ce16405 --- /dev/null +++ b/as/genbin.c @@ -0,0 +1,220 @@ +/* genbin.c - binary code generation routines for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "file.h" +#include "globvar.h" + +PRIVATE char *asmbeg; /* beginning of assembler code */ + /* for overwrite check */ + /* bss-init to zero = NULL and not changed */ +PRIVATE offset_t binfbuf; /* binary code buffer for file (counter) */ +PRIVATE offset_t binmax; /* maximum value of binmbuf for pass 1 */ +PRIVATE offset_t binmin; /* minimum value of binmbuf for pass 1 */ + +FORWARD void putbinoffset P((offset_t offset, count_t size)); + +/* write header to binary file */ + +PUBLIC void binheader() +{ + if ((innum = binfil) != 0x0) + { + writec(0x0); /* binary header byte */ +#ifdef LONG_BINHEADER + writeoff(binmax - binmin); /* program length */ + writeoff(binfbuf = binmin); /* program start */ +#else + writew((unsigned) (binmax - binmin)); /* program length */ + writew((unsigned) (binfbuf = binmin)); /* program start */ +#endif + } +} + +/* write trailer to binary file */ + +PUBLIC void bintrailer() +{ + if ((innum = binfil) != 0x0) + { + writec(0xFF); /* binary trailer byte */ + writew(0x0); /* further trailer bytes */ +#ifdef LONG_BINHEADER + writeoff(pedata & UNDBIT ? binmin : progent); /* entry point */ +#else + writew(pedata & UNDBIT ? (unsigned) binmin : (unsigned) progent); +#endif + } +} + +/* generate binary code for current line */ + +PUBLIC void genbin() +{ + struct address_s *adrptr; + char *bufptr; + unsigned char remaining; + + if (binaryg && mcount != 0x0) + { + if (popflags) + { + if (fcflag) + { + bufptr = databuf.fcbuf; + remaining = mcount; + do + putbin(*bufptr++); + while (--remaining != 0x0); + } + if (fdflag) + { + adrptr = databuf.fdbuf; + remaining = mcount; + do + { + putbinoffset(adrptr->offset, 0x2); + ++adrptr; + } + while ((remaining -= 0x2) != 0x0); + } +#if SIZEOF_OFFSET_T > 0x2 + if (fqflag) + { + adrptr = databuf.fqbuf; + remaining = mcount; + do + { + putbinoffset(adrptr->offset, 0x4); + ++adrptr; + } + while ((remaining -= 0x4) != 0x0); + } +#endif + } + else + { + remaining = mcount - 0x1; /* count opcode immediately */ +#ifdef I80386 + if (aprefix != 0x0) + { + putbin(aprefix); + --remaining; + } + if (oprefix != 0x0) + { + putbin(oprefix); + --remaining; + } + if (sprefix != 0x0) + { + putbin(sprefix); + --remaining; + } +#endif + if (page != 0x0) + { + putbin(page); + --remaining; + } + putbin(opcode); + if (remaining != 0x0) + { + if (postb != 0x0) + { + putbin(postb); + --remaining; + } +#ifdef I80386 + if (sib != NO_SIB) + { + putbin(sib); + --remaining; + } +#endif + if (remaining != 0x0) + putbinoffset(lastexp.offset, remaining); + } +#ifdef I80386 + if (immcount != 0x0) + putbinoffset(immadr.offset, immcount); +#endif + } + /* else no code for this instruction, or already generated */ + } +} + +/* initialise private variables */ + +PUBLIC void initbin() +{ + binmin = -1; /* greater than anything */ +} + +/* write char to binary file or directly to memory */ + +PUBLIC void putbin(ch) +opcode_pt ch; +{ + if (binfil != 0x0) + { + if (!binaryc) /* pass 1, just record limits */ + { + if (binmbuf < binmin) + binmin = binmbuf; + if (++binmbuf > binmax) + binmax = binmbuf; + } + else + { + if (binfbuf > binmbuf) + error(BWRAP); /* file buffer ahead of memory buffer */ + else + { + innum = binfil; + while (binfbuf < binmbuf) + { + writec(0x0);/* pad with nulls if file buffer behind */ + ++binfbuf; + } + writec(ch); + binmbuf = ++binfbuf; + } + } + } + else if (binaryc && !(lcdata & UNDBIT)) + /* memory output, and enabled */ + { + register char *bufptr; + + if ((bufptr = (char *) binmbuf) >= asmbeg && bufptr < heapptr) + error(OWRITE); + else + *bufptr = ch; + ++binmbuf; + } +} + +/* write sized offset to binary file or directly to memory */ + +PRIVATE void putbinoffset(offset, size) +offset_t offset; +count_t size; +{ + char buf[sizeof offset]; + +#if SIZEOF_OFFSET_T > 0x2 + u4cn(buf, offset, size); +#else + u2cn(buf, offset, size); +#endif + putbin(buf[0]); + if (size > 0x1) + putbin(buf[1]); + if (size > 0x2) + { + putbin(buf[2]); + putbin(buf[3]); + } +} diff --git a/as/genlist.c b/as/genlist.c new file mode 100644 index 0000000..e179fcf --- /dev/null +++ b/as/genlist.c @@ -0,0 +1,463 @@ +/* genlist.c - generate listing and error reports for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "flag.h" +#include "file.h" +#include "globvar.h" +#include "macro.h" +#include "scan.h" +#include "source.h" + +#ifdef STDC_HEADERS_MISSING +void *memset P((void *s, int c, unsigned n)); +unsigned strlen P((const char *s)); +#else +#undef NULL +#include <string.h> +#endif + +#ifdef POSIX_HEADERS_MISSING +int write P((int fd, const void *buf, unsigned nbytes)); +#else +#undef NULL +#include <sys/types.h> +#include <unistd.h> +#endif + +#define CODE_LIST_LENGTH (sizeof (struct code_listing_s) - 1) + /* length of formatted code listing */ +#define MAXERR 6 /* maximum errors listed per line */ + +struct error_s /* to record error info */ +{ + unsigned char errnum; + unsigned char position; +}; + +/* code listing format */ + +struct code_listing_s +{ + union linum_macro_u + { + char linum[LINUM_LEN]; + struct + { + char pad[1]; + char mark[1]; + char level[1]; + } + macro; + } + linum_or_macro; + char padlinum[1]; + char lc[4]; + char padlc[1]; +#ifdef I80386 + char lprefix[2]; + char aprefix[2]; + char oprefix[2]; + char sprefix[2]; +#endif + char page[2]; + char opcode[2]; + char postb[2]; +#ifdef I80386 + char sib[2]; +#endif + char padopcode[1]; +#if SIZEOF_OFFSET_T > 2 + char displ4[2]; + char displ3[2]; +#endif + char displ2[2]; + char displ1[2]; + char reldispl[1]; + char paddispl[1]; +#ifdef I80386 + char imm4[2]; + char imm3[2]; + char imm2[2]; + char imm1[2]; + char relimm[1]; + char padimm[1]; +#endif + char nullterm; +}; + +PRIVATE struct error_s errbuf[MAXERR]; /* error buffer */ +PRIVATE unsigned char errcount; /* # errors in line */ +PRIVATE bool_t erroverflow; /* set if too many errors on line */ + +FORWARD char *build_1hex_number P((opcode_pt num, char *where)); +FORWARD void list1 P((fd_t fd)); +FORWARD void listcode P((void)); +FORWARD void listerrors P((void)); +FORWARD void paderrorline P((unsigned nspaces)); + +/* format 1 byte number as 2 hex digits, return ptr to end */ + +PRIVATE char *build_1hex_number(num, where) +opcode_pt num; +register char *where; +{ + where[0] = hexdigit[((unsigned) num % 256) / 16]; + where[1] = hexdigit[(unsigned) num % 16]; + return where + 2; +} + +/* format 2 byte number as 4 hex digits, return ptr to end */ + +PUBLIC char *build_2hex_number(num, where) +unsigned num; +char *where; +{ + return build_1hex_number((opcode_pt) num, + build_1hex_number((opcode_pt) (num / 256), where)); +} + +/* format 2 byte number as decimal with given width (pad with leading '0's) */ +/* return ptr to end */ + +PUBLIC char *build_number(num, width, where) +unsigned num; +unsigned width; +register char *where; +{ + static unsigned powers_of_10[] = {1, 10, 100, 1000, 10000,}; + unsigned char digit; + unsigned char power; + register unsigned power_of_10; + + power = 5; /* actually 1 more than power */ + do + { + for (digit = '0', power_of_10 = (powers_of_10 - 1)[power]; + num >= power_of_10; num -= power_of_10) + ++digit; + if (power <= width) + *where++ = digit; + } + while (--power != 0); + return where; +} + +/* record number and position of error (or error buffer overflow) */ + +PUBLIC void error(errnum) +error_pt errnum; +{ + register struct error_s *errptr; + register struct error_s *errptrlow; + unsigned char position; + + if ((unsigned) errnum < MINWARN || warn.current) + { + if (errcount >= MAXERR) + erroverflow = TRUE; + else + { + position = symname - linebuf; + for (errptr = errbuf + errcount; + errptr > errbuf && errptr->position > position; + errptr = errptrlow) + { + errptrlow = errptr - 1; + errptr->errnum = errptrlow->errnum; + errptr->position = errptrlow->position; + } + errptr->errnum = errnum; + errptr->position = position; + ++errcount; + if ((unsigned)errnum >= MINWARN) + ++totwarn; + else + ++toterr; + } + } +} + +/* list 1 line to list file if any errors or flags permit */ +/* list line to console as well if any errors and list file is not console */ + +PUBLIC void listline() +{ + if (!listpre) + { + if (errcount || list.current && (!macflag || mcount != 0) || + macflag && maclist.current) + list1(lstfil); + if (errcount) + { + if (lstfil != STDOUT) + list1(STDOUT); + errcount = 0; + erroverflow = FALSE; + } + } +} + +/* list 1 line unconditionally */ + +PRIVATE void list1(fd) +fd_t fd; +{ + innum = fd; + listcode(); + write(innum, linebuf, (unsigned) (lineptr - linebuf)); + writenl(); + if (errcount != 0) + listerrors(); + listpre = TRUE; +} + +/* list object code for 1 line */ + +PRIVATE void listcode() +{ + unsigned char count; + struct code_listing_s *listptr; + unsigned numlength; + char *numptr; + + listptr = (struct code_listing_s *) heapptr; + memset((char *) listptr, ' ', sizeof *listptr); + listptr->nullterm = 0; + if (macflag) + { + listptr->linum_or_macro.macro.mark[0] = '+'; + listptr->linum_or_macro.macro.level[0] = maclevel + ('a' - 1); + } + else + { + numlength = LINUM_LEN; + numptr = listptr->linum_or_macro.linum; + if (infiln != infil0) + { + *numptr++ = infiln - infil0 + ('a' - 1); + numlength = LINUM_LEN - 1; + } + build_number(linum, numlength, numptr); + } + if ((count = mcount) != 0 || popflags & POPLC) + build_2hex_number((u16_T) lc, listptr->lc); + if (popflags & POPLO) + { +#if SIZEOF_OFFSET_T > 2 + if (popflags & POPLONG) + build_2hex_number((u16_T) (lastexp.offset / (offset_t) 0x10000L), + listptr->displ4); +#endif + if (popflags & POPHI) + build_2hex_number((u16_T) lastexp.offset, listptr->displ2); + else + build_1hex_number((opcode_pt) /* XXX */(u16_T) lastexp.offset, listptr->displ1); + if (lastexp.data & RELBIT) + listptr->reldispl[0] = '>'; + } + else if (count != 0) + { +#ifdef I80386 + if (aprefix != 0) + { + --count; + build_1hex_number(aprefix, listptr->aprefix); + } + if (oprefix != 0) + { + --count; + build_1hex_number(oprefix, listptr->oprefix); + } + if (sprefix != 0) + { + --count; + build_1hex_number(sprefix, listptr->sprefix); + } +#endif + if (page != 0) + { + build_1hex_number(page, listptr->page); + --count; + } + build_1hex_number(opcode, listptr->opcode); + --count; + if (postb != 0) + { + --count; + build_1hex_number(postb, +#ifdef MC6809 + count == 0 ? listptr->displ1 : +#endif + listptr->postb); + } +#ifdef I80386 + if (sib != NO_SIB) + { + --count; + build_1hex_number(sib, listptr->sib); + } +#endif + if (count > 0) + { + build_1hex_number((opcode_pt) lastexp.offset, listptr->displ1); + if (lastexp.data & RELBIT) + listptr->reldispl[0] = '>'; + } + if (count > 1) + build_1hex_number((opcode_pt) (lastexp.offset >> 0x8), + listptr->displ2); +#if SIZEOF_OFFSET_T > 2 + if (count > 2) + { + build_1hex_number((opcode_pt) (lastexp.offset >> 0x10), + listptr->displ3); + build_1hex_number((opcode_pt) (lastexp.offset >> 0x18), + listptr->displ4); + } +#endif +#ifdef I80386 + if (immcount > 0) + { + build_1hex_number((opcode_pt) immadr.offset, listptr->imm1); + if (immadr.data & RELBIT) + listptr->relimm[0] = '>'; + } + if (immcount > 1) + build_1hex_number((opcode_pt) (immadr.offset >> 0x8), + listptr->imm2); + if (immcount > 2) + { + build_1hex_number((opcode_pt) (immadr.offset >> 0x10), + listptr->imm3); + build_1hex_number((opcode_pt) (immadr.offset >> 0x18), + listptr->imm4); + } +#endif + } + writes((char *) listptr); +} + +/* list errors, assuming some */ + +PRIVATE void listerrors() +{ + unsigned char column; + unsigned char errcol; /* column # in error line */ + unsigned char errcolw; /* working column in error line */ + char *errmsg; + struct error_s *errptr; + char *linep; + unsigned char remaining; + + paderrorline(CODE_LIST_LENGTH - LINUM_LEN); + remaining = errcount; + column = 0; /* column to match with error column */ + errcolw = errcol = CODE_LIST_LENGTH; /* working & col number on err line */ + errptr = errbuf; + linep = linebuf; + do + { + while (column < errptr->position) + { + ++column; + if (*linep++ == '\t') /* next tab (standard tabs only) */ + errcolw = (errcolw + 8) & 0xf8; + else + ++errcolw; + while (errcolw > errcol) + { + writec(' '); + ++errcol; + } + } + if (errcolw < errcol) /* position under error on new line */ + { + writenl(); + paderrorline((unsigned) errcolw - LINUM_LEN); + } + writec('^'); + writes(errmsg = build_error_message(errptr->errnum, heapptr)); + errcol += strlen(errmsg); + ++errptr; + } + while (--remaining != 0); + writenl(); + if (erroverflow) + { + paderrorline(CODE_LIST_LENGTH - LINUM_LEN); + writesn(build_error_message(FURTHER, heapptr)); + } +} + +/* pad out error line to begin under 1st char of source listing */ + +PRIVATE void paderrorline(nspaces) +unsigned nspaces; +{ + int nstars = LINUM_LEN; + + while (nstars-- != 0) + writec('*'); /* stars under line number */ + while (nspaces-- != 0) + writec(' '); /* spaces out to error position */ +} + +/* write 1 character */ + +PUBLIC void writec(ch) +char ch; +{ + write(innum, &ch, 1); +} + +/* write newline */ + +PUBLIC void writenl() +{ + writes(SOS_EOLSTR); +} + +/* write 1 offset_t, order to suit target */ + +PUBLIC void writeoff(offset) +offset_t offset; +{ + char buf[sizeof offset]; + +#if SIZEOF_OFFSET_T > 2 + u4c4(buf, offset); +#else + u2c2(buf, offset); +#endif + write(innum, buf, sizeof buf); +} + +/* write string */ + +PUBLIC void writes(s) +char *s; +{ + write(innum, s, strlen(s)); +} + +/* write string followed by newline */ + +PUBLIC void writesn(s) +char *s; +{ + writes(s); + writenl(); +} + +/* write 1 word, order to suit target */ + +PUBLIC void writew(word) +unsigned word; +{ + char buf[2]; + + u2c2(buf, (u16_T) word); + write(innum, buf, sizeof buf); +} diff --git a/as/genobj.c b/as/genobj.c new file mode 100644 index 0000000..80b03ce --- /dev/null +++ b/as/genobj.c @@ -0,0 +1,682 @@ +/* genobj.c - object code generation routines for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "file.h" +#include "globvar.h" + +#ifdef STDC_HEADERS_MISSING +char *strcpy P((char *s1, const char *s2)); +char *strrchr P((const char *s, int c)); +unsigned strlen P((const char *s)); +#else +#undef NULL +#include <string.h> +#endif + +#ifdef POSIX_HEADERS_MISSING +int write P((int fd, const void *buf, unsigned nbytes)); +#else +#undef NULL +#include <sys/types.h> +#include <unistd.h> +#endif + +#define OBJBUFSIZE 512 /* size of object code output buffer */ +#define isge2byteoffset(offset) ((offset) >= 0x100) +#define isge4byteoffset(offset) ((offset) >= 0x10000L) + +PRIVATE char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */ +PRIVATE char *absbuf; /* start */ +PRIVATE char *absbufend; /* last location + 1 */ +PRIVATE char *absbufptr; /* current location */ +PRIVATE struct sym_s **arrext; /* array of external symbol ptrs */ +PRIVATE char hid_objbuf[OBJBUFSIZE]; /* object code buffer */ +PRIVATE unsigned numext; /* number of external symbols */ +PRIVATE char *objbuf; /* start */ +PRIVATE char *objbufend; /* last location + 1 */ +PRIVATE char *objbufptr; /* current location */ +PRIVATE unsigned char relsize; /* current relocation size, 0 init */ + /* local to genobjadr, but here */ + /* because of static re-init bug */ +PRIVATE offset_t rmbcount; /* accumulator for repeated RMB's */ + +FORWARD void flushabs P((void)); +FORWARD void flushrmb P((void)); +FORWARD void genobjadr P((struct address_s *adrptr, int size)); +FORWARD void putobj1 P((opcode_pt ch)); +FORWARD void putobj4 P((u32_T offset)); +FORWARD void putobjoffset P((offset_t offset, count_t size)); +FORWARD void putobjword P((unsigned word)); +FORWARD void writeobj P((char *buf, unsigned count)); + +/* accumulate RMB requests into 1 (so + and - requests cancel) */ + +PUBLIC void accumulate_rmb(offset) +offset_t offset; +{ + if (objectc) + { + flushabs(); + rmbcount += offset; + } +} + +/* flush absolute object code buffer to object code buffer if necessary */ + +PRIVATE void flushabs() +{ + if (absbufptr > absbuf) + { + putobj1((absbufptr - absbuf) | OBJ_ABS); + { + register char *bufptr; + + bufptr = absbuf; + do + putobj1(*bufptr); + while (++bufptr < absbufptr); + absbufptr = absbuf; + } + } +} + +/* flush object code buffer if necessary */ + +PUBLIC void flushobj() +{ + int ntowrite; + + if ((ntowrite = objbufptr - objbuf) > 0) + { + if (write(objfil, objbuf, (unsigned) ntowrite) != ntowrite) + { + error(OBJOUT); + listline(); + finishup(); + } + objbufptr = objbuf; + } +} + +/* flush RMB count if necessary */ + +PRIVATE void flushrmb() +{ + count_t size; + + if (rmbcount != 0) + { +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(rmbcount)) + { + putobj1(OBJ_SKIP_4); + size = 4; + } + else +#endif + if (isge2byteoffset(rmbcount)) + { + putobj1(OBJ_SKIP_2); + size = 2; + } + else + { + putobj1(OBJ_SKIP_1); + size = 1; + } + putobjoffset(rmbcount, size); + rmbcount = 0; + } +} + +/* generate object code for current line */ + +/* + any address parameter is (regrettably) in lastexp + any immediate parameter is (corectly) in immadr +*/ + +PUBLIC void genobj() +{ + struct address_s *adrptr; + char *bufptr; + unsigned char remaining; + + if (objectc && mcount != 0) + { + if (popflags) + { + if (fcflag) + { + bufptr = databuf.fcbuf; + remaining = mcount; + do + putabs(*bufptr++); + while (--remaining != 0); + } + if (fdflag) + { + adrptr = databuf.fdbuf; + remaining = mcount; + do + genobjadr(adrptr++, 2); + while ((remaining -= 2) != 0); + } +#if SIZEOF_OFFSET_T > 2 + if (fqflag) + { + adrptr = databuf.fqbuf; + remaining = mcount; + do + genobjadr(adrptr++, 4); + while ((remaining -= 4) != 0); + } +#endif + } + else + { + remaining = mcount - 1; /* count opcode immediately */ +#ifdef I80386 + if (aprefix != 0) + { + putabs(aprefix); + --remaining; + } + if (oprefix != 0) + { + putabs(oprefix); + --remaining; + } + if (sprefix != 0) + { + putabs(sprefix); + --remaining; + } +#endif + if (page != 0) + { + putabs(page); + --remaining; + } + putabs(opcode); + if (remaining != 0) + { + if (postb != 0) + { + putabs(postb); + --remaining; + } +#ifdef I80386 + if (sib != NO_SIB) + { + putabs(sib); + --remaining; + } +#endif + if (remaining != 0) + genobjadr(&lastexp, remaining); + } + } +#ifdef I80386 + if (immcount != 0) + genobjadr(&immadr, immcount); +#endif + } +} + +/* generate object code for current address */ + +PRIVATE void genobjadr(adrptr, size) +struct address_s *adrptr; +smallcount_t size; +{ + unsigned char byte; + unsigned symnum; + + if (!(adrptr->data & RELBIT)) + { + /* absolute address */ + + char buf[sizeof(offset_t)]; + +#if SIZEOF_OFFSET_T > 2 + u4cn(buf, adrptr->offset, size); +#else + u2cn(buf, adrptr->offset, size); +#endif + putabs(buf[0]); + if (size > 1) + putabs(buf[1]); + if (size > 2) + { + putabs(buf[2]); + putabs(buf[3]); + } + } + else + { + /* relocatable address */ + if (size != relsize) + /* set reloc size index |00|0000xx| */ + putobj((relsize = size) == 4 ? 0x03 : relsize); + if (!(adrptr->data & IMPBIT)) + { + /* offset relocation (known offset) */ + putobj((adrptr->data & SEGM) | OBJ_OFFSET_REL | pcrflag); + putobjoffset(adrptr->offset, size); + } + else + { + /* symbol relocation (imported symbol + offset) */ + { + register struct sym_s **copyptr; + + for (copyptr = arrext, symnum = 0; + symnum < numext && *copyptr++ != adrptr->sym; ++symnum) + ; + } + byte = OBJ_SYMBOL_REL; + if (isge2byteoffset(symnum)) + byte = OBJ_SYMBOL_REL | OBJ_S_MASK; +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(adrptr->offset)) + { + byte |= 0x03; /* 4 byte offset */ + size = 4; + } + else +#endif + if (isge2byteoffset(adrptr->offset)) + { + byte |= 0x02; /* 2 byte offset */ + size = 2; + } + else if (adrptr->offset != 0) + { + byte |= 0x01; /* 1 byte offset */ + size = 1; + } + else + size = 0; + putobj(byte | pcrflag); + if (isge2byteoffset(symnum)) + putobjword(symnum); + else + putobj1((opcode_pt) symnum); + if (adrptr->offset != 0) + putobjoffset(adrptr->offset, size); + } + } +} + +/* initialise private variables */ + +PUBLIC void initobj() +{ + absbufend = (absbufptr = absbuf = hid_absbuf) + sizeof hid_absbuf; + objbufend = (objbufptr = objbuf = hid_objbuf) + sizeof hid_objbuf; +} + +/* + write header to object file + also build array of imported/exported symbols +*/ + +PUBLIC void objheader() +{ + static char module_header[] = + { +#ifdef I80386 + 0xA3, 0x86, + 1, 0, + (char) (0xA3 + 0x86 + 1 + 0), +#endif +#ifdef MC6809 + 'S', '1', /* 2 byte magic number */ + 0, 1, /* 2 byte number of modules in file */ + 'S' + '1' + 0 + 1, /* 1 byte checksum */ +#endif + }; + static char seg_max_sizes[] = + { + 0x55, /* all segments have maximum size 2^16 */ + 0x55, /* this is encoded by 0b01 4 times per byte */ + 0x55, /* other codes are 0b00 = max size 2^8 */ + 0x55, /* 0b10 = max size 2^24, 0b11 = max 2^32 */ + }; + unsigned char byte; + register struct sym_s **copyptr; + struct sym_s **copytop; + struct sym_s **hashptr; + struct lc_s *lcp; + char module_name[FILNAMLEN + 1]; + char *nameptr; + unsigned offset; + unsigned segsizebytes; + unsigned size; + unsigned char sizebits; + unsigned strsiz; /* size of object string table */ + unsigned symosiz; /* size of object symbol table */ + register struct sym_s *symptr; + u32_T textlength; + + if ((objectc = objectg) == 0) + return; + writeobj(module_header, sizeof module_header); + + /* calculate number of imported/exported symbols */ + /* and lengths of symbol and string tables */ + /* build array of imported/exported symbols */ + + symosiz = 0; + if (truefilename == NULL) + truefilename = filnamptr; + nameptr = strrchr(truefilename, DIRCHAR); + strcpy(module_name, nameptr != NULL ? nameptr + 1 : truefilename); + if ((nameptr = strrchr(module_name, '.')) != NULL) + *nameptr = 0; + strsiz = strlen(module_name) + 1; + align(heapptr); + for (hashptr = spt, arrext = copyptr = (struct sym_s **) heapptr; + hashptr < spt_top;) + if ((symptr = *hashptr++) != NULL) + do + { + if ((symptr->type & EXPBIT || symptr->data & IMPBIT) || + !globals_only_in_obj && symptr->name[0] != '.' && + !(symptr->type & (MNREGBIT | MACBIT | VARBIT))) + { + if (copyptr >= (struct sym_s **) heapend) + { + heapptr = (char *) copyptr; + fatalerror(OBJSYMOV); + } + *copyptr++ = symptr; + strsiz += symptr->length + 1; +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(symptr->value_reg_or_op.value)) + size = 4 + 4; + /* 4 is size of offset into string table and flags */ + /* 2nd 4 is for 4 byte offset */ + else +#endif + if (isge2byteoffset(symptr->value_reg_or_op.value)) + size = 4 + 2; + else if (symptr->value_reg_or_op.value != 0) + size = 4 + 1; + else + size = 4; + symosiz += size; + ++numext; + } + } + while ((symptr = symptr->next) != NULL); + heapptr = (char *) (copytop = copyptr); + + /* calculate length of text, and number of seg size bytes in header */ + + textlength = segsizebytes = 0; + lcp = lctab; + do + if (lcp->lc != 0) + { + textlength += lcp->lc; /* assuming text starts at 0 */ +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(lcp->lc)) + segsizebytes += 4; + else +#endif + segsizebytes += 2; /* use 2 byte size if possible */ + } + while (++lcp < lctabtop); + +/* + offset to text = length of header since only 1 module + header consists of: + module header sizeof module_header + offset to start of text 4 + length of text 4 + length of string area 2 + class 1 + revision 1 + seg max sizes sizeof seg_max_sizes + seg size descriptors 4 + seg sizes segsizebytes + symbol count 2 + symbol offsets and types symosiz + strings strsiz +*/ + + /* offset to start of text */ + + putobj4((u32_T) (sizeof module_header + 4 + 4 + 2 + 1 + 1 + + sizeof seg_max_sizes + 4 + segsizebytes + 2 + + symosiz) + strsiz); + + /* length of text */ + + putobj4((u32_T) textlength); + + /* length of string area */ + + putobjword(strsiz); + + /* class and revision */ + + putobj1(0); + putobj1(0); + + /* segment max sizes (constant) */ + + writeobj(seg_max_sizes, sizeof seg_max_sizes); + + /* segment size descriptors */ + /* produce only 0 and 2 byte sizes */ + + lcp = lctabtop; + byte = 0; + sizebits = OBJ_SEGSZ_TWO << 6; + do + { + --lcp; + if (lcp->lc != 0) + { + byte |= sizebits; +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(lcp->lc)) + byte |= sizebits >> 1; /* XXX - convert size 2 to size 4 */ +#endif + } + if ((sizebits >>= 2) == 0) + { + putobj1(byte); + byte = 0; + sizebits = OBJ_SEGSZ_TWO << 6; + } + } + while (lcp > lctab); + + /* segment sizes */ + + do /* lcp starts at lctab */ + if (lcp->lc != 0) + { +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(lcp->lc)) + putobj4(lcp->lc); + else +#endif + putobjword((unsigned) lcp->lc); + } + while (++lcp < lctabtop); + + /* symbol count */ + + putobjword(numext); + + /* symbol offsets and types */ + + offset = strlen(module_name) + 1; /* 1st symbol begins after name */ + for (copyptr = arrext; copyptr < copytop;) + { + putobjword(offset); + symptr = *copyptr++; + byte = symptr->type & OBJ_N_MASK; +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(symptr->value_reg_or_op.value)) + { + byte |= OBJ_SZ_FOUR; + size = 4; + } + else +#endif + if (isge2byteoffset(symptr->value_reg_or_op.value)) + { + byte |= OBJ_SZ_TWO; + size = 2; + } + else if (symptr->value_reg_or_op.value != 0) + { + byte |= OBJ_SZ_ONE; + size = 1; + } + else + size = 0; + if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT)) + { + byte |= OBJ_SA_MASK; + symptr->data &= ~OBJ_I_MASK; + } + putobjword((unsigned) + (byte << 0x8) | + (symptr->type & OBJ_E_MASK) | /* |E|0000000| */ + ((symptr->data & (OBJ_I_MASK | OBJ_A_MASK | OBJ_SEGM_MASK)) ^ + /* |0|I|0|A|SEGM| */ + RELBIT)); /* RELBIT by negative logic */ + if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT)) + symptr->data |= OBJ_I_MASK; + if (size != 0) + putobjoffset(symptr->value_reg_or_op.value, size); + offset += symptr->length + 1; + } + + /* strings */ + + writeobj(module_name, strlen(module_name)); + putobj1(0); + for (copyptr = arrext; copyptr < copytop;) + { + symptr = *copyptr++; + writeobj(symptr->name, symptr->length); + putobj1(0); + } + putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */ +} + +/* write trailer to object file */ + +PUBLIC void objtrailer() +{ + if (objectc) + { + putobj(0); /* end of object file */ + flushobj(); + } +} + +/* write char to absolute object code buffer, flush if necessary */ + +PUBLIC void putabs(ch) +opcode_pt ch; +{ + if (objectc) + { + if (rmbcount != 0) + flushrmb(); + if (absbufptr >= absbufend) + flushabs(); + *absbufptr++ = ch; + } +} + +/* write char to object code buffer, flush if necessary */ + +PUBLIC void putobj(ch) +opcode_pt ch; +{ + if (objectc) + { + flushabs(); + flushrmb(); + putobj1(ch); + } +} + +/* write char to object code buffer assuming nothing in absolute & rmb bufs */ + +PRIVATE void putobj1(ch) +opcode_pt ch; +{ + if (objbufptr >= objbufend) + flushobj(); + *objbufptr++ = ch; +} + +/* write 32 bit offset to object code buffer assuming ... */ + +PRIVATE void putobj4(offset) +u32_T offset; +{ + char buf[sizeof offset]; + + u4c4(buf, offset); + writeobj(buf, sizeof buf); +} + +/* write sized offset to object code buffer assuming ... */ + +PRIVATE void putobjoffset(offset, size) +offset_t offset; +count_t size; +{ + char buf[sizeof offset]; + +#if SIZEOF_OFFSET_T > 2 + u4cn(buf, offset, size); +#else + u2cn(buf, offset, size); +#endif + putobj1(buf[0]); + if (size > 1) + putobj1(buf[1]); + if (size > 2) + { + putobj1(buf[2]); + putobj1(buf[3]); + } +} + +/* write word to object code buffer assuming ... */ + +PRIVATE void putobjword(word) +unsigned word; +{ + char buf[sizeof word]; + + u2c2(buf, word); + putobj1(buf[0]); + putobj1(buf[1]); +} + +/* write several bytes to object code buffer assuming ... */ + +PRIVATE void writeobj(buf, count) +char *buf; +unsigned count; +{ + do + putobj1(*buf++); + while (--count); +} diff --git a/as/gensym.c b/as/gensym.c new file mode 100644 index 0000000..bc773db --- /dev/null +++ b/as/gensym.c @@ -0,0 +1,212 @@ +/* gensym.c - generate symbol table for assembler */ + +#include "const.h" +#include "type.h" +#include "flag.h" +#include "file.h" +#include "globvar.h" + +#ifdef STDC_HEADERS_MISSING +void *memset P((void *s, int c, unsigned n)); +int strcmp P((const char *s1, const char *s2)); +#else +#undef NULL +#include <string.h> +#endif + +#ifdef POSIX_HEADERS_MISSING +int write P((int fd, const void *buf, unsigned nbytes)); +#else +#undef NULL +#include <sys/types.h> +#include <unistd.h> +#endif + +FORWARD int printsym P((register struct sym_s *symptr, unsigned column)); +FORWARD void sort P((struct sym_s **array, struct sym_s **top, + bool_pt nameflag)); + +/* sort labels in symbol table on name and value */ +/* if listing, write human-readable table to list file */ +/* if symbol file, write machine-readable tables to it */ +/* pointers become relative to start of file */ + +PUBLIC void gensym() +{ + unsigned column; + struct sym_s **copyptr; + struct sym_s **copytop; + register struct sym_s **hashptr; + unsigned label_count; /* number of labels */ + unsigned labels_length; /* length of all label strings */ + unsigned label_stringptr; /* offset of label str from start of file */ + register struct sym_s *symptr; + struct sym_s **symlptr; /* start of symbol output list */ + + labels_length = label_count = 0; + + /* make copy of all relavant symbol ptrs on heap */ + /* original ptrs can now be modified, but need to be an array for sort */ + + align(heapptr); + for (hashptr = spt, symlptr = copyptr = (struct sym_s **) heapptr; + hashptr < spt_top;) + if ((symptr = *hashptr++) != NULL) + do + if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) + { + if (copyptr >= (struct sym_s **) heapend) + { + heapptr = (char *) copyptr; + error(SYMOUTOV); /* avoid recursive fatalerror */ + listline(); /* the main job is OK if here */ + goto sort_symbols; + } + *copyptr++ = symptr; + ++label_count; + labels_length += symptr->length + 3; /* 3 for type, value */ + } + while ((symptr = symptr->next) != NULL); + +sort_symbols: + sort(symlptr, copyptr, TRUE); /* sort on name */ + heapptr = (char *) (copytop = copyptr); + if (list.global) + { + innum = lstfil; + writenl(); + writesn("Symbols:"); + for (copyptr = symlptr, column = 0; copyptr < copytop;) + column = printsym(*copyptr++, column); + if (column != 0) + writenl(); + } + if ((innum = symfil) != 0) + { + writew(mapnum); + label_count *= 2; /* now length of ptr table (2 bytes per ptr) */ + label_stringptr = label_count + 6; + /* offset to current string in symbol file */ + /* 6 is length of header */ + labels_length += label_stringptr; + /* offset to ptr table sorted on value */ + writew(labels_length + label_count); + /* total length of symbol file */ + writew(label_count); + for (copyptr = symlptr; copyptr < copytop;) + { + symptr = *copyptr++; + writew((unsigned) + (symptr->next = (struct sym_s *) label_stringptr)); + /* reuse "next" to record string position */ + label_stringptr += symptr->length + 3; + } + for (copyptr = symlptr; copyptr < copytop;) + { + symptr = *copyptr++; + writew((unsigned) symptr->value_reg_or_op.value); + writec(symptr->type); + write(innum, symptr->name, (unsigned) (symptr->length - 1)); + writec(symptr->name[symptr->length - 1] | 0x80); + } + sort(symlptr, copyptr, FALSE); + /* sort on value */ + for (copyptr = symlptr; copyptr < copytop;) + { + symptr = *copyptr++; + writew((unsigned) symptr->next); /* now has string position */ + } + } +} + +/* print symbol nicely formatted for given column */ + +PRIVATE int printsym(symptr, column) +register struct sym_s *symptr; +unsigned column; +{ + unsigned char length; + register struct sym_listing_s *listptr; + char *outname; + char *symname; + + listptr = (struct sym_listing_s *) heapptr; + memset((char *) listptr, ' ', SYMLIS_LEN); + listptr->nullterm = 0; + if ((length = symptr->length) > SYMLIS_NAMELEN) + { + outname = listptr->name; + outname[length = SYMLIS_NAMELEN] = '+'; + } + else + outname = (listptr->name + SYMLIS_NAMELEN) - length; + symname = symptr->name; + do + *outname++ = *symname++; + while (--length != 0); + listptr->ar[0] = symptr->data & RELBIT ? 'R' : 'A'; + listptr->segm[0] = hexdigit[symptr->data & SEGM]; + if (symptr->type & COMMBIT) + listptr->cein[0] = 'C'; + else if (symptr->type & ENTBIT) + listptr->cein[0] = 'N'; + else if (symptr->type & EXPBIT) + listptr->cein[0] = 'E'; + else if (symptr->data & IMPBIT) + listptr->cein[0] = 'I'; +#if SIZEOF_OFFSET_T > 2 + build_2hex_number((unsigned) (symptr->value_reg_or_op.value >> 16), + listptr->value); +#endif + build_2hex_number((unsigned) symptr->value_reg_or_op.value, + listptr->value); + writes((char *) listptr); + if ((column += SYMLIS_LEN) > (80 - SYMLIS_LEN)) + { + writenl(); + column = 0; + } + return column; +} + +/* shell sort symbols */ + +PRIVATE void sort(array, top, nameflag) +struct sym_s **array; +struct sym_s **top; +bool_pt nameflag; +{ + int gap; + int i; + int j; + register struct sym_s **left; + register struct sym_s **right; + int size; + struct sym_s *swap; + + size = top - array; + /* choose gaps according to Knuth V3 p95 */ + for (gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j) + ; + do + { + for (j = gap; j < size; ++j) + for (i = j - gap; i >= 0; i -= gap) + { + left = &array[i]; + right = &array[i + gap]; + if ((bool_t) nameflag) + { + if (strcmp((*left)->name, (*right)->name) <= 0) + break; + } + else if ((unsigned) (*left)->value_reg_or_op.value <= + (*right)->value_reg_or_op.value) + break; + swap = *left; + *left = *right; + *right = swap; + } + } + while ((gap /= 3) != 0); +} diff --git a/as/globvar.h b/as/globvar.h new file mode 100644 index 0000000..f2896fb --- /dev/null +++ b/as/globvar.h @@ -0,0 +1,93 @@ +/* globvar.h - global variables for assembler */ + +/* global control and bookkeeping */ + +EXTERN bool_t binaryc; /* current binary code flag */ +EXTERN bool_t binaryg; /* global binary code flag */ +EXTERN offset_t binmbuf; /* offset in binary code buffer for memory */ + +EXTERN unsigned char dirpag; /* direct page */ + +EXTERN bool_t globals_only_in_obj; /* global symbols only in object file */ + +EXTERN bool_t jumps_long; /* make all jumps long */ + +EXTERN unsigned char mapnum; /* global map number */ + +EXTERN bool_t objectc; /* current object code flag */ +EXTERN bool_t objectg; /* global object code flag */ + +EXTERN bool_t pass; /* pass, FALSE means 0, TRUE means 1 */ + +EXTERN offset_t progent; /* program entry point */ + +EXTERN bool_t symgen; /* generate symbol table flag */ + +EXTERN unsigned toterr; /* total errors */ +EXTERN unsigned totwarn; /* total warnings */ + +/* bookeeping for current line */ + +EXTERN char *linebuf; /* buffer */ + +/* for symbol table routines */ + +EXTERN char *heapend; /* end of free space for symbol list */ +EXTERN char *heapptr; /* next free space in symbol list */ +EXTERN unsigned char inidata; /* init sym entry data governed by "u" flag */ +EXTERN struct sym_s **spt; /* symbol pointer table */ +EXTERN struct sym_s **spt_top; /* top of symbol ptr table */ + +/* for translator */ + +EXTERN struct sym_s *label; /* non-null if valid label starts line */ +EXTERN unsigned char pedata; /* shows how PROGENT bound, flags like LCDATA*/ +EXTERN unsigned char popflags; /* pseudo-op flags */ + +/* for BLOCK stack */ + +EXTERN struct block_s *blockstak; /* stack ptr */ +EXTERN unsigned char blocklevel; /* nesting level */ + +/* for IF stack */ + +EXTERN struct if_s *ifstak; /* stack ptr */ +EXTERN unsigned char iflevel; /* nesting level */ +EXTERN bool_t ifflag; /* set if assembling */ + +/* location counters for various segments */ + +EXTERN offset_t lc; /* location counter */ +EXTERN unsigned char lcdata; /* shows how lc is bound */ + /* FORBIT is set if lc is forward referenced */ + /* RELBIT is is if lc is relocat. (not ASEG) */ +EXTERN offset_t lcjump; /* lc jump between lines */ +#define mcount (((unsigned char *) &lcjump)[LOW_BYTE]) + /* low byte of lcjump */ +EXTERN struct lc_s *lcptr; /* top of current spot in lctab */ +EXTERN struct lc_s *lctab; /* start of lctab */ +EXTERN struct lc_s *lctabtop; /* top of lctab */ + +/* for code generator */ + +EXTERN opsize_t mnsize; /* 1 if forced byte operand size, else 0 */ +EXTERN opcode_t page; +EXTERN opcode_t opcode; +EXTERN opcode_t postb; /* postbyte, 0 if none */ +EXTERN unsigned char pcrflag; /* OBJ_RMASK set if addressing is PC-relative */ + +#ifdef I80386 + +EXTERN opcode_t aprefix; /* address size prefix or 0 */ +EXTERN bool_t asld_compatible; /* asld compatibility flag */ +EXTERN opsize_t defsize; /* current default size */ +EXTERN opsize_t idefsize; /* initial default size */ +EXTERN opcode_t oprefix; /* operand size prefix or 0 */ +EXTERN opcode_t sprefix; /* segment prefix or 0 */ +EXTERN opcode_t sib; /* scale-index-base byte */ + +#endif + +/* miscellaneous */ + +extern char hexdigit[]; diff --git a/as/macro.c b/as/macro.c new file mode 100644 index 0000000..9363947 --- /dev/null +++ b/as/macro.c @@ -0,0 +1,175 @@ +/* macro.c - expand macros for assembler */ + +#include "const.h" +#include "type.h" +#include "globvar.h" +#include "scan.h" +#undef EXTERN +#define EXTERN +#include "macro.h" + +#ifdef STDC_HEADERS_MISSING +int strncmp P((const char *s1, const char *s2, unsigned n)); +#else +#undef NULL +#include <string.h> +#endif + +/* + Enter macro: stack macro and get its parameters. + Parameters form a linked list of null-terminated strings of form + next:string. The first string is the macro number in 4 bytes. +*/ + +PUBLIC void entermac(symptr) +struct sym_s *symptr; +{ + if (maclevel >= MAXMAC) + error(MACOV); + else if (macpar + 2 > macptop) + error(PAROV); /* no room for 0th param */ + /* (2 structs to fit it!) */ + else + { + char ch; + struct schain_s *param1; + register char *reglineptr; + register char *stringptr; + + ++maclevel; + (--macstak)->text = (char *) symptr->value_reg_or_op.value; + macstak->parameters = param1 = macpar; + param1->next = NULL; + *(stringptr = build_number(++macnum, 3, param1->string)) = 0; + macpar = (struct schain_s *) (stringptr + 1); + /* TODO: alignment */ + getsym(); + if (sym != LPAREN) + return; /* no other params */ + reglineptr = lineptr; + stringptr = macpar->string; + while (TRUE) + { + if (stringptr >= (char *) macptop) + { + symname = reglineptr; + error(PAROV); + return; + } + ch = *reglineptr++; + if (ch == '/') + /* escaped means no special meaning for slash, comma, paren */ + ch = *reglineptr++; + else if (ch == ',' || ch == ')') + { + if (stringptr >= (char *) macptop) + { + symname = reglineptr; + error(PAROV); /* no room for null */ + return; + } + *stringptr = 0; + param1->next = macpar; /* ptr from previous */ + (param1 = macpar)->next = NULL; + /* this goes nowhere */ + macpar = (struct schain_s *) (stringptr + 1); + /* but is finished OK - TODO align */ + stringptr = macpar->string; + if (ch == ')') + return; + continue; + } + if ((*stringptr++ = ch) == 0) + { + symname = reglineptr; + error(RPEXP); + return; + } + } + } +} + +/* MACRO pseudo-op */ + +PUBLIC void pmacro() +{ + bool_t saving; + bool_t savingc; + struct sym_s *symptr; + + saving = /* prepare for bad macro */ + savingc = FALSE; /* normally don't save comments */ + macload = TRUE; /* show loading */ + if (label != NULL) + error(ILLAB); + else if (sym != IDENT) + error(LABEXP); + else + { + symptr = gsymptr; + if (symptr->type & MNREGBIT) + error(LABEXP); + else if (symptr->type & LABIT || symptr->data & FORBIT) + error(RELAB); + else if (pass == 0 || symptr->type & REDBIT) + /* copy on pass 0, also pass 1 if redefined */ + { + saving = TRUE; + if (symptr->type & MACBIT) + symptr->type |= REDBIT; + else + symptr->type |= MACBIT; + symptr->data = UNDBIT; /* undefined till end */ + symptr->value_reg_or_op.value = (unsigned) heapptr; + /* beginning of store for macro */ + /* value s.b. (char *) */ + getsym_nolookup(); /* test for "C" */ + if (sym == IDENT && lineptr == symname + 1 && *symname == 'C') + savingc = TRUE; + } + } + while (TRUE) + { + skipline(); + listline(); + readline(); + if (!macload) + break; /* macload cleared to show eof */ + getsym_nolookup(); + if (sym == IDENT) + { + if (lineptr == symname + 4 && strncmp(symname, "MEND", 4) == 0) + break; + } + else if (sym != MACROARG) + { + if (!savingc) + continue; /* don't save comment */ + } + if (!saving) + continue; + { + register char *reglineptr; + register char *regheapptr; + + reglineptr = linebuf; + regheapptr = heapptr; + do + { + if (regheapptr >= heapend) + { + heapptr = regheapptr; + fatalerror(SYMOV); /* won't fit */ + } + } + while ((*regheapptr++ = *reglineptr++) != EOLCHAR); + heapptr = regheapptr; + } + } + macload = FALSE; + if (saving) + { + *heapptr++ = ETB; + symptr->data = 0; + } +} diff --git a/as/macro.h b/as/macro.h new file mode 100644 index 0000000..c37bd00 --- /dev/null +++ b/as/macro.h @@ -0,0 +1,10 @@ +/* macro.h - global variables for macro expansion for assembler */ + +EXTERN bool_t macflag; /* inside macro flag */ +EXTERN bool_t macload; /* loading macro flag */ +EXTERN unsigned macnum; /* macro call counter */ + +EXTERN unsigned char maclevel; /* nesting level */ +EXTERN struct schain_s *macpar; /* parameter save buffer */ +EXTERN struct schain_s *macptop; /* top of param buffer (+1) */ +EXTERN struct macro_s *macstak; /* stack ptr */ diff --git a/as/mops.c b/as/mops.c new file mode 100644 index 0000000..209f0c8 --- /dev/null +++ b/as/mops.c @@ -0,0 +1,2835 @@ +/* mops.c - handle pseudo-ops */ + +#include "const.h" +#include "type.h" +#include "globvar.h" +#include "opcode.h" +#include "scan.h" +#undef EXTERN +#define EXTERN +#include "address.h" + +#define is8bitadr(offset) ((offset_t) offset < 0x100) +#define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100) +#define pass2 pass + +FORWARD void mshort2 P((void)); +FORWARD reg_pt regchk P((void)); +FORWARD void reldata P((void)); + +#ifdef I80386 + +#define iswordadr(offset) ((offset_t) (offset) < 0x10000L) +#define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L) +#define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL) + +#define BYTE_SEGWORD 0x00 +#define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG) + +#define BASE_MASK 0x07 +#define BASE_SHIFT 0 +#define INDEX_MASK 0x38 +#define INDEX_SHIFT 3 +#define MOD_MASK 0xC0 +# define REG_MOD 0xC0 +# define MEM0_MOD 0x00 +# define MEM1_MOD 0x40 +# define MEM2_MOD 0x80 +#define REG_MASK 0x38 +#define REG_SHIFT 3 +#define RM_MASK 0x07 +#define RM_SHIFT 0 +# define D16_RM 0x06 +# define D32_RM 0x05 +# define SIB_NOBASE 0x05 +# define SIB_RM 0x04 +#define SREG_MASK 0x38 +#define SREG_SHIFT 3 +#define SS_MASK 0xC0 +#define SS_SHIFT 6 + +#define SEGMOV 0x04 +#define SIGNBIT 0x02 +#define TOREGBIT 0x02 +#define WORDBIT 0x01 + +PRIVATE opcode_t baseind16[] = +{ + 0x00, /* BP + BP, illegal */ + 0x00, /* BX + BP, illegal */ + 0x03, /* DI + BP */ + 0x02, /* SI + BP */ + 0x00, /* BP + BX, illegal */ + 0x00, /* BX + BX, illegal */ + 0x01, /* DI + BX */ + 0x00, /* SI + BX */ + 0x03, /* BP + DI */ + 0x01, /* BX + DI */ + 0x00, /* DI + DI, illegal */ + 0x00, /* SI + DI, illegal */ + 0x02, /* BP + SI */ + 0x00, /* BX + SI */ + 0x00, /* DI + SI, illegal */ + 0x00, /* SI + SI, illegal */ +}; + +PRIVATE opcode_t regbits[] = +{ + 0x05 << REG_SHIFT, /* BP */ + 0x03 << REG_SHIFT, /* BX */ + 0x07 << REG_SHIFT, /* DI */ + 0x06 << REG_SHIFT, /* SI */ + + 0x00 << REG_SHIFT, /* EAX */ + 0x05 << REG_SHIFT, /* EBP */ + 0x03 << REG_SHIFT, /* EBX */ + 0x01 << REG_SHIFT, /* ECX */ + 0x07 << REG_SHIFT, /* EDI */ + 0x02 << REG_SHIFT, /* EDX */ + 0x06 << REG_SHIFT, /* ESI */ + 0x04 << REG_SHIFT, /* ESP */ + + 0x00 << REG_SHIFT, /* AX */ + 0x01 << REG_SHIFT, /* CX */ + 0x02 << REG_SHIFT, /* DX */ + 0x04 << REG_SHIFT, /* SP */ + + 0x04 << REG_SHIFT, /* AH */ + 0x00 << REG_SHIFT, /* AL */ + 0x07 << REG_SHIFT, /* BH */ + 0x03 << REG_SHIFT, /* BL */ + 0x05 << REG_SHIFT, /* CH */ + 0x01 << REG_SHIFT, /* CL */ + 0x06 << REG_SHIFT, /* DH */ + 0x02 << REG_SHIFT, /* DL */ + + 0x01 << REG_SHIFT, /* CS */ + 0x03 << REG_SHIFT, /* DS */ + 0x00 << REG_SHIFT, /* ES */ + 0x04 << REG_SHIFT, /* FS */ + 0x05 << REG_SHIFT, /* GS */ + 0x02 << REG_SHIFT, /* SS */ + + 0x00 << REG_SHIFT, /* CR0 */ + 0x02 << REG_SHIFT, /* CR2 */ + 0x03 << REG_SHIFT, /* CR3 */ + + 0x00 << REG_SHIFT, /* DR0 */ + 0x01 << REG_SHIFT, /* DR1 */ + 0x02 << REG_SHIFT, /* DR2 */ + 0x03 << REG_SHIFT, /* DR3 */ + 0x06 << REG_SHIFT, /* DR6 */ + 0x07 << REG_SHIFT, /* DR7 */ + + 0x03 << REG_SHIFT, /* TR3 */ + 0x04 << REG_SHIFT, /* TR4 */ + 0x05 << REG_SHIFT, /* TR5 */ + 0x06 << REG_SHIFT, /* TR6 */ + 0x07 << REG_SHIFT, /* TR7 */ + + 0x00 << REG_SHIFT, /* ST(0) */ + 0x01 << REG_SHIFT, /* ST(1) */ + 0x02 << REG_SHIFT, /* ST(2) */ + 0x03 << REG_SHIFT, /* ST(3) */ + 0x04 << REG_SHIFT, /* ST(4) */ + 0x05 << REG_SHIFT, /* ST(5) */ + 0x06 << REG_SHIFT, /* ST(6) */ + 0x07 << REG_SHIFT, /* ST(7) */ +}; + +PRIVATE opsize_t regsize[] = +{ + 2, /* BP */ + 2, /* BX */ + 2, /* DI */ + 2, /* SI */ + + 4, /* EAX */ + 4, /* EBP */ + 4, /* EBX */ + 4, /* ECX */ + 4, /* EDI */ + 4, /* EDX */ + 4, /* ESI */ + 4, /* ESP */ + + 2, /* AX */ + 2, /* CX */ + 2, /* DX */ + 2, /* SP */ + + 1, /* AH */ + 1, /* AL */ + 1, /* BH */ + 1, /* BL */ + 1, /* CH */ + 1, /* CL */ + 1, /* DH */ + 1, /* DL */ + + 2, /* CS */ + 2, /* DS */ + 2, /* ES */ + 2, /* FS */ + 2, /* GS */ + 2, /* SS */ + + 4, /* CR0 */ + 4, /* CR2 */ + 4, /* CR3 */ + + 4, /* DR0 */ + 4, /* DR1 */ + 4, /* DR2 */ + 4, /* DR3 */ + 4, /* DR6 */ + 4, /* DR7 */ + + 4, /* TR3 */ + 4, /* TR4 */ + 4, /* TR5 */ + 4, /* TR6 */ + 4, /* TR7 */ + + 10, /* ST(0) */ + 10, /* ST(1) */ + 10, /* ST(2) */ + 10, /* ST(3) */ + 10, /* ST(4) */ + 10, /* ST(5) */ + 10, /* ST(6) */ + 10, /* ST(7) */ + + 0, /* NOREG */ +}; + +PRIVATE opcode_t regsegword[] = +{ + WORDBIT, /* BP */ + WORDBIT, /* BX */ + WORDBIT, /* DI */ + WORDBIT, /* SI */ + + WORDBIT, /* EAX */ + WORDBIT, /* EBP */ + WORDBIT, /* EBX */ + WORDBIT, /* ECX */ + WORDBIT, /* EDI */ + WORDBIT, /* EDX */ + WORDBIT, /* ESI */ + WORDBIT, /* ESP */ + + WORDBIT, /* AX */ + WORDBIT, /* CX */ + WORDBIT, /* DX */ + WORDBIT, /* SP */ + + BYTE_SEGWORD, /* AH */ + BYTE_SEGWORD, /* AL */ + BYTE_SEGWORD, /* BH */ + BYTE_SEGWORD, /* BL */ + BYTE_SEGWORD, /* CH */ + BYTE_SEGWORD, /* CL */ + BYTE_SEGWORD, /* DH */ + BYTE_SEGWORD, /* DL */ + + SEGMOV, /* CS */ + SEGMOV, /* DS */ + SEGMOV, /* ES */ + SEGMOV, /* FS */ + SEGMOV, /* GS */ + SEGMOV, /* SS */ + + 0x20, /* CR0 */ + 0x20, /* CR2 */ + 0x20, /* CR3 */ + + 0x21, /* DR0 */ + 0x21, /* DR1 */ + 0x21, /* DR2 */ + 0x21, /* DR3 */ + 0x21, /* DR6 */ + 0x21, /* DR7 */ + + 0x24, /* TR3 */ + 0x24, /* TR4 */ + 0x24, /* TR5 */ + 0x24, /* TR6 */ + 0x24, /* TR7 */ + + 0x00, /* ST(0) */ + 0x00, /* ST(1) */ + 0x00, /* ST(2) */ + 0x00, /* ST(3) */ + 0x00, /* ST(4) */ + 0x00, /* ST(5) */ + 0x00, /* ST(6) */ + 0x00, /* ST(7) */ + + 0x00, /* NOREG */ +}; + +PRIVATE opcode_t rm[] = +{ + 0x05, /* BP */ + 0x03, /* BX */ + 0x07, /* DI */ + 0x06, /* SI */ + + 0x00, /* EAX */ + 0x05, /* EBP */ + 0x03, /* EBX */ + 0x01, /* ECX */ + 0x07, /* EDI */ + 0x02, /* EDX */ + 0x06, /* ESI */ + 0x04, /* ESP */ + + 0x00, /* AX */ + 0x01, /* CX */ + 0x02, /* DX */ + 0x04, /* SP */ + + 0x04, /* AH */ + 0x00, /* AL */ + 0x07, /* BH */ + 0x03, /* BL */ + 0x05, /* CH */ + 0x01, /* CL */ + 0x06, /* DH */ + 0x02, /* DL */ + + 0x01, /* CS */ + 0x03, /* DS */ + 0x00, /* ES */ + 0x04, /* FS */ + 0x05, /* GS */ + 0x02, /* SS */ + + 0x00, /* CR0 */ + 0x00, /* CR2 */ + 0x00, /* CR3 */ + + 0x00, /* DR0 */ + 0x00, /* DR1 */ + 0x00, /* DR2 */ + 0x00, /* DR3 */ + 0x00, /* DR6 */ + 0x00, /* DR7 */ + + 0x00, /* TR3 */ + 0x00, /* TR4 */ + 0x00, /* TR5 */ + 0x00, /* TR6 */ + 0x00, /* TR7 */ + + 0x00, /* ST(0) */ + 0x00, /* ST(1) */ + 0x00, /* ST(2) */ + 0x00, /* ST(3) */ + 0x00, /* ST(4) */ + 0x00, /* ST(5) */ + 0x00, /* ST(6) */ + 0x00, /* ST(7) */ + + 0x04, /* null index reg for sib only */ +}; + +PRIVATE opcode_t rmfunny[] = +{ + 0x06, /* BP */ + 0x07, /* BX */ + 0x05, /* DI */ + 0x04, /* SI */ +}; + +PRIVATE opcode_t segoverride[] = +{ + 0x2E, /* CS */ + 0x3E, /* DS */ + 0x26, /* ES */ + 0x64, /* FS */ + 0x65, /* GS */ + 0x36, /* SS */ +}; + +PRIVATE opcode_t ss[] = /* scale to ss bits */ +{ + 0x00, /* x0, illegal */ + 0x00 << SS_SHIFT, /* x1 */ + 0x01 << SS_SHIFT, /* x2 */ + 0x00, /* x3, illegal */ + 0x02 << SS_SHIFT, /* x4 */ + 0x00, /* x5, illegal */ + 0x00, /* x6, illegal */ + 0x00, /* x7, illegal */ + 0x03 << SS_SHIFT, /* x8 */ +}; + +PRIVATE unsigned char calljmp_kludge; +PRIVATE opcode_t direction; +PRIVATE bool_t fpreg_allowed; +PRIVATE opcode_t segword; +/* + Values of segword: + BYTE_SEGWORD for byte ea's. + SEGMOV for segment registers + opcode for special registers + WORDBIT for other word and dword ea's +*/ + +PRIVATE struct ea_s source; +PRIVATE struct ea_s source2; +PRIVATE struct ea_s target; + +FORWARD void Eb P((struct ea_s *eap)); +FORWARD void Ew P((struct ea_s *eap)); +FORWARD void Ev P((struct ea_s *eap)); +FORWARD void Ex P((struct ea_s *eap)); +FORWARD void Gd P((struct ea_s *eap)); +FORWARD void Gw P((struct ea_s *eap)); +FORWARD void Gv P((struct ea_s *eap)); +FORWARD void Gx P((struct ea_s *eap)); +FORWARD void buildea P((struct ea_s *eap)); +FORWARD void buildfloat P((void)); +FORWARD void buildfreg P((void)); +FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag)); +FORWARD void buildregular P((void)); +FORWARD void buildsegword P((struct ea_s *eap)); +FORWARD void buildunary P((opcode_pt opc)); +FORWARD opsize_pt displsize P((struct ea_s *eap)); +FORWARD reg_pt fpregchk P((void)); +FORWARD bool_pt getaccumreg P((struct ea_s *eap)); +FORWARD void getbinary P((void)); +FORWARD bool_pt getdxreg P((struct ea_s *eap)); +FORWARD void getea P((struct ea_s *eap)); +FORWARD void getimmed P((struct ea_s *eap, count_t immed_count)); +FORWARD void getindirect P((struct ea_s *eap)); +FORWARD void getshift P((struct ea_s *eap)); +FORWARD reg_pt indregchk P((reg_pt matchreg)); +FORWARD void kgerror P((error_pt errnum)); +FORWARD void lbranch P((int backamount)); +FORWARD void notbytesize P((struct ea_s *eap)); +FORWARD void notimmed P((struct ea_s *eap)); +FORWARD void notindirect P((struct ea_s *eap)); +FORWARD void notsegorspecreg P((struct ea_s *eap)); +FORWARD void yesimmed P((struct ea_s *eap)); +FORWARD void yes_samesize P((void)); + +PRIVATE void Eb(eap) +register struct ea_s *eap; +{ + Ex(eap); + if (eap->size != 0x1) + { +#ifndef NODEFAULTSIZE + if (eap->size == 0x0) + eap->size = 0x1; + else +#endif + kgerror(ILL_SIZE); + } +} + +PRIVATE void Ew(eap) +register struct ea_s *eap; +{ + Ex(eap); + if (eap->size != 0x2) + { +#ifndef NODEFAULTSIZE + if (eap->size == 0x0) + eap->size = 0x2; + else +#endif + kgerror(ILL_SIZE); + } +} + +PRIVATE void Ev(eap) +register struct ea_s *eap; +{ + Ex(eap); + notbytesize(eap); +} + +PRIVATE void Ex(eap) +register struct ea_s *eap; +{ + getea(eap); + notimmed(eap); + notsegorspecreg(eap); +} + +PRIVATE void Gd(eap) +register struct ea_s *eap; +{ + Gx(eap); + if (eap->size != 0x4) + kgerror(ILL_SIZE); +} + +PRIVATE void Gw(eap) +register struct ea_s *eap; +{ + Gx(eap); + if (eap->size != 0x2) + kgerror(ILL_SIZE); +} + +PRIVATE void Gv(eap) +register struct ea_s *eap; +{ + Gx(eap); + notbytesize(eap); +} + +PRIVATE void Gx(eap) +register struct ea_s *eap; +{ + Ex(eap); + notindirect(eap); +} + +PRIVATE void buildea(eap) +register struct ea_s *eap; +{ + opsize_t asize; + + ++mcount; + lastexp = eap->displ; + if (eap->indcount == 0x0) + postb = REG_MOD | rm[eap->base]; + else + { + if (eap->base == NOREG) + { + if (eap->index == NOREG) + { + if ((asize = displsize(eap)) > 0x2) + postb = D32_RM; + else + postb = D16_RM; + } + else + { + asize = 0x4; + postb = SIB_NOBASE; /* for sib later */ + } + } + else + { + if (eap->base > MAX16BITINDREG) + { + asize = 0x4; + postb = rm[eap->base]; + } + else + { + asize = 0x2; + if (!(lastexp.data & UNDBIT) && + !iswordorswordoffset(lastexp.offset)) + error(ABOUNDS); + if (eap->index == NOREG) + postb = rmfunny[eap->base]; + else if (eap->base <= MAX16BITINDREG) + postb = baseind16[eap->base + 0x4 * eap->index]; + } + } + if (asize != defsize) + aprefix = 0x67; + if (eap->base == NOREG) + mcount += asize; + else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) || + !is8bitsignedoffset(lastexp.offset)) + { + postb |= MEM2_MOD; + mcount += asize; + } + else if (lastexp.offset != 0x0 || + eap->base == BPREG && eap->index == NOREG || + eap->base == EBPREG) + { + postb |= MEM1_MOD; + ++mcount; + } + if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG)) + { + sib = ss[eap->scale] | + (rm[eap->index] << INDEX_SHIFT) | + (postb & RM_MASK); + postb = (postb & MOD_MASK) | SIB_RM; + ++mcount; + } + } +} + +PRIVATE void buildfloat() +{ + if (mcount != 0x0) + { + buildea(&source); + oprefix = 0x0; + postb |= (opcode & 0x07) << REG_SHIFT; + opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); + } +} + +PRIVATE void buildfreg() +{ + mcount += 0x2; + oprefix = 0x0; + postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG); + opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); +} + +PRIVATE void buildimm(eap, signflag) +register struct ea_s *eap; +bool_pt signflag; +{ + immadr = eap->displ; + immcount = eap->size; + if (!(immadr.data & (FORBIT | RELBIT | UNDBIT))) + { + if (immcount == 0x1) + { + if ((offset_t) (immadr.offset + 0x80) >= 0x180) + datatoobig(); + } + else if (signflag && is8bitsignedoffset(immadr.offset)) + { + opcode |= SIGNBIT; + immcount = 0x1; + } + else if (immcount == 0x2) + { + if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L) + datatoobig(); + } + } +} + +PRIVATE void buildregular() +{ + if (mcount != 0x0) + { + buildea(&target); + postb |= regbits[source.base]; + } +} + +/* Check size and build segword. */ + +PRIVATE void buildsegword(eap) +register struct ea_s *eap; +{ + if (eap->size == 0x0) +#ifdef NODEFAULTSIZE + kgerror(SIZE_UNK); +#else + eap->size = defsize; +#endif + if (eap->indcount != 0x0 || eap->base == NOREG) + { + segword = WORDBIT; + if (eap->size == 0x1) + segword = BYTE_SEGWORD; + } + else + segword = regsegword[eap->base]; +} + +PRIVATE void buildunary(opc) +opcode_pt opc; +{ + if (mcount != 0x0) + { + buildea(&target); + postb |= opcode; + opcode = opc; + } +} + +PRIVATE opsize_pt displsize(eap) +register struct ea_s *eap; +{ + opsize_t asize; + + asize = defsize; + if (!(eap->displ.data & UNDBIT)) + { + if (asize > 0x2) + { + if (!(eap->displ.data & (FORBIT | RELBIT)) && + iswordadr(eap->displ.offset)) + asize = 0x2; + } + else if (!iswordorswordoffset(eap->displ.offset)) + /* should really use iswordadr() */ + /* but compiler generates signed offsets */ + { + if (!(eap->displ.data & (FORBIT | RELBIT))) + asize = 0x4; + else if (pass2) + error(ABOUNDS); + } + } + return asize; +} + +PRIVATE reg_pt fpregchk() +{ + reg_pt fpreg; + + fpreg_allowed = TRUE; + fpreg = regchk(); + fpreg_allowed = FALSE; + if (fpreg != ST0REG) + return NOREG; + getsym(); + if (sym == LPAREN) + { + getsym(); + if (sym != INTCONST || (unsigned) number >= 0x8) + error(ILL_FP_REG); + else + { + fpreg += number; + getsym(); + if (sym != RPAREN) + error(RPEXP); + else + getsym(); + } + } + return fpreg; +} + +PRIVATE bool_pt getaccumreg(eap) +register struct ea_s *eap; +{ + if ((eap->base = regchk()) != AXREG && eap->base != ALREG + && eap->base != EAXREG) + return FALSE; + getsym(); + if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) + oprefix = 0x66; + return TRUE; +} + +/* + Get binary ea's in target & source (flipped if direction is set). + Put size in source if not already. + Initialise direction, segword, bump mcount. +*/ + +PRIVATE void getbinary() +{ + ++mcount; + getea(&target); + if (target.indcount == 0x0 && target.base == NOREG) + { + error(ILL_IMM_MODE); + target.base = AXREG; + target.size = defsize; + } + getcomma(); + getea(&source); + if (source.size == 0x0) + source.size = target.size; + else if (target.size != 0x0 && target.size != source.size) + { + kgerror(MISMATCHED_SIZE); + return; + } + if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV) + direction = 0x0; + else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV) + { + struct ea_s swap; + + direction = TOREGBIT; + swap = source; + source = target; + target = swap; + } + else if (target.indcount != 0x0) + { + kgerror(ILL_IND_TO_IND); + return; + } + else + { + kgerror(ILL_SEG_REG); + return; + } + buildsegword(&source); +} + +PRIVATE bool_pt getdxreg(eap) +register struct ea_s *eap; +{ + if ((eap->base = regchk()) != DXREG) + return FALSE; + getsym(); + return TRUE; +} + +/* parse effective address */ + +/* + Syntax is restrictive in that displacements must be in the right spots + and will not be added up. + + optional size-type prefix, which is + BYTE + BYTE PTR + WORD + WORD PTR + DWORD + DWORD PTR + PTR + reg + segreg + [scaled index] + where scaled index = + indreg + indreg*scale + indreg+indreg + indreg+indreg*scale + [scaled index+displ] + [scaled index-displ] + optional-immediate-prefix displ[scaled index] + [displ] + optional-imediate-prefix displ + (scaled index) -- anachronism + optional-imediate-prefix displ(scaled index) -- anachronism +*/ + +PRIVATE void getea(eap) +register struct ea_s *eap; +{ + bool_t leading_displ; + bool_t leading_immed; + register struct sym_s *symptr; + + leading_immed = leading_displ = lastexp.data = eap->indcount + = lastexp.offset = 0x0; + eap->index = eap->base = NOREG; + eap->scale = 0x1; + eap->size = mnsize; /* 0x1 for byte ops, else 0x0 */ + + if (sym == IDENT) + { + if ((symptr = gsymptr)->type & MNREGBIT) + { + if (symptr->data & SIZEBIT) + { + getsym(); + if (symptr->value_reg_or_op.op.opcode == 0x0) + eap->indcount = 0x2 - calljmp_kludge; + else + { + if (eap->size != 0x0) + { + if (eap->size != symptr->value_reg_or_op.op.opcode) + error(MISMATCHED_SIZE); + } + else + eap->size = symptr->value_reg_or_op.op.opcode; + if (eap->size > 0x1 && eap->size != defsize) + oprefix = 0x66; + if (sym == IDENT && + (symptr = gsymptr)->type & MNREGBIT && + symptr->data & SIZEBIT && + symptr->value_reg_or_op.op.routine == PTROP) + { + getsym(); + eap->indcount = 0x2 - calljmp_kludge; + } + } + } + } + if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT))) + symptr->data |= FORBIT; /* show seen in advance */ + } + if ((eap->base = regchk()) != NOREG) + { + getsym(); + if (eap->indcount != 0x0) + { + error(ILL_IND_PTR); + eap->indcount = 0x0; + } + if (eap->size != 0x0 && eap->size != regsize[eap->base]) + error(MISMATCHED_SIZE); + if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) + oprefix = 0x66; + eap->displ = lastexp; + return; + } + if (sym != lindirect) + { + if (sym == IMMEDIATE || sym == STAR) + { + /* context-sensitive, STAR means signed immediate here */ + leading_immed = TRUE; + getsym(); + } + leading_displ = TRUE; + expres(); + eap->displ = lastexp; + } + if (sym == lindirect) + { + getsym(); + eap->indcount = 0x2 - calljmp_kludge; + if ((eap->base = indregchk((reg_pt) NOREG)) != NOREG) + { + if (eap->indcount == 0x0 && leading_displ) + error(IND_REQ); + getsym(); + if (sym == ADDOP) + { + getsym(); + if ((eap->index = indregchk(eap->base)) != NOREG) + getsym(); + else + { + if (eap->indcount == 0x0) + error(IND_REQ); + if (leading_displ) + error(REPEATED_DISPL); + expres(); /* this eats ADDOP, SUBOP, MULOP */ + } + } + if (sym == STAR) + { + /* context-sensitive, STAR means scaled here*/ + if (eap->index == NOREG && eap->base == ESPREG) + { + error(INDEX_REG_EXP); + eap->base = EAXREG; + } + getsym(); + factor(); + chkabs(); + if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1) + { + if (eap->base <= MAX16BITINDREG || + lastexp.offset != 0x2 && lastexp.offset != 0x4 && + lastexp.offset != 0x8) + error(ILL_SCALE); + else + { + eap->scale = lastexp.offset; + if (eap->index == NOREG) + { + eap->index = eap->base; + eap->base = NOREG; + } + } + } + lastexp.data = lastexp.offset = 0x0; + } + if ((sym == ADDOP || sym == SUBOP)) + { + if (eap->indcount == 0x0) + error(IND_REQ); + if (leading_displ) + error(REPEATED_DISPL); + expres(); + } + } + else + { + if (leading_displ) + error(REPEATED_DISPL); + expres(); + } + if (sym != rindirect) + error(rindexp); + else + getsym(); + } + else if (!leading_immed && idefsize <= 0x2) + eap->indcount = 0x1; /* compatibility kludge */ + if (!leading_displ) + eap->displ = lastexp; +} + +PRIVATE void getimmed(eap, immed_count) +struct ea_s *eap; +count_t immed_count; +{ + getea(eap); + yesimmed(eap); + if (mcount != 0x0) + { + eap->size = immed_count; + buildimm(eap, FALSE); + } +} + +PRIVATE void getindirect(eap) +register struct ea_s *eap; +{ + getea(eap); + if (eap->indcount == 0x0) + kgerror(IND_REQ); +} + +PRIVATE void getshift(eap) +register struct ea_s *eap; +{ + getcomma(); + getea(eap); + if (eap->base != CLREG) + yesimmed(eap); +} + +/* + Check if current symbol is a compatible index register. + Generate error if it is a reg but not a compatible index. + Return register number (adjusted if necessary to a legal index) or NOREG. +*/ + +PRIVATE reg_pt indregchk(matchreg) +reg_pt matchreg; +{ + reg_pt reg; + + if ((reg = regchk()) != NOREG) + { + switch (matchreg) + { + case BPREG: + case BXREG: + if (reg != DIREG && reg != SIREG) + { + reg = SIREG; + error(INDEX_REG_EXP); + } + break; + case DIREG: + case SIREG: + if (reg != BPREG && reg != BXREG) + { + reg = BXREG; + error(INDEX_REG_EXP); + } + break; + case NOREG: + break; + default: + if (reg <= MAX16BITINDREG || reg == ESPREG) + { + reg = EAXREG; + error(INDEX_REG_EXP); + } + break; + } + if (reg > MAXINDREG && calljmp_kludge == 0x0) + { + if (matchreg != NOREG) + reg = EAXREG; + else + reg = BXREG; + error(INDEX_REG_EXP); + } + } + return reg; +} + +PRIVATE void kgerror(errnum) +error_pt errnum; +{ + error(errnum); + sprefix = oprefix = aprefix = mcount = 0x0; +} + +PRIVATE void lbranch(backamount) +int backamount; +{ + mcount += defsize + 0x1; + if (pass2) + { + reldata(); + if (!(lastexp.data & (RELBIT | UNDBIT))) + { + lastexp.offset = lastexp.offset - lc - lcjump; + if (backamount != 0x0 && !(lastexp.data & IMPBIT) && + lastexp.offset + backamount < 0x80 + backamount) + error(SHORTB); /* -0x8? to 0x7F, warning */ + } + } +} + +/* BCC (long branches emulated by short branch over & long jump) */ + +PUBLIC void mbcc() +{ + getea(&target); + if (target.indcount >= 0x2 || target.base != NOREG) + kgerror(REL_REQ); + else + { + if (defsize != 0x2) + { + page = PAGE1_OPCODE; + ++mcount; + opcode += 0x10; + lbranch(0x84); + } + else + { + aprefix = opcode ^ 0x1; /* kludged storage for short branch + over */ + oprefix = defsize + 0x1; + mcount += 0x2; + opcode = JMP_OPCODE; + lbranch(0x83); + mcount -= 0x2; + } + } +} + +/* bswap r32 */ + +PUBLIC void mbswap() +{ + ++mcount; + Gd(&target); + opcode |= rm[target.base]; +} + +/* BR, CALL, J, JMP */ + +PUBLIC void mcall() +{ + opcode_pt far; + bool_t indirect; + register struct sym_s *symptr; + + far = 0x0; + if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT && + symptr->data & SIZEBIT && + symptr->value_reg_or_op.op.routine == FAROP) + { + far = 0x8; + getsym(); + } + indirect = FALSE; + if (asld_compatible && idefsize <= 0x2) + { + calljmp_kludge = 0x2; + if (sym == INDIRECT) + { + calljmp_kludge = 0x0; + indirect = TRUE; + getsym(); + } + } + getea(&target); + if (indirect && target.indcount == 0x1) + target.indcount = 0x2; + calljmp_kludge = 0x0; + if (sym == COLON) + { + if (opcode == JMP_SHORT_OPCODE) + opcode = JMP_OPCODE; + ++mcount; + yesimmed(&target); + getsym(); + getea(&source); + yesimmed(&source); + if (mcount != 0x0) + { + if (opcode == JMP_OPCODE) + opcode = 0xEA; + else + opcode = 0x9A; + lastexp = source.displ; + if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && + defsize == 0x2 && + (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) + datatoobig(); + mcount += defsize; + target.size = 0x2; + buildimm(&target, FALSE); + } + } + else if (target.indcount >= 0x2 || target.base != NOREG) + { + ++mcount; + notsegorspecreg(&target); + if (target.indcount == 0) + notbytesize(&target); + if (mcount != 0x0) + { + if (opcode == JMP_SHORT_OPCODE) + opcode = JMP_OPCODE; + buildea(&target); + if (opcode == JMP_OPCODE) + opcode = 0x20; + else + opcode = 0x10; + postb |= opcode + far; + opcode = 0xFF; + } + } + else if (opcode == JMP_SHORT_OPCODE) + { + if (jumps_long) + { + opcode = JMP_OPCODE; + lbranch(0x83); + } + else + { + lastexp = target.displ; + if (lastexp.data & IMPBIT) + { + error(NONIMPREQ); + lastexp.data = FORBIT | UNDBIT; + } + mshort2(); + } + } + else + lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0); +} + +/* CALLI, JMPI */ + +PUBLIC void mcalli() +{ + bool_t indirect; + + ++mcount; + indirect = FALSE; + if (sym == INDIRECT) + { + getsym(); + indirect = TRUE; + } + getea(&target); + if (target.indcount >= 0x2 || target.base != NOREG) + indirect = TRUE; + if (indirect) + { + buildea(&target); + if (opcode == 0xEA) + opcode = 0x28; + else + opcode = 0x18; + postb |= opcode; + opcode = 0xFF; + } + else + { + getcomma(); + getea(&source); + yesimmed(&source); + if (mcount != 0x0) + { + lastexp = target.displ; + if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && + defsize == 0x2 && + (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) + datatoobig(); + mcount += defsize; + source.size = 0x2; + buildimm(&source, FALSE); + } + } +} + +/* DIV, IDIV, MUL */ + +PUBLIC void mdivmul() +{ + if (getaccumreg(&source)) + { + ++mcount; + getcomma(); + Ex(&target); + yes_samesize(); + buildunary(0xF6 | regsegword[source.base]); + } + else + mnegnot(); +} + +/* ENTER */ + +PUBLIC void menter() +{ + ++mcount; + getimmed(&target, 0x2); + getcomma(); + getimmed(&source, 0x1); + if (mcount != 0x0) + { + mcount += 2; + lastexp = target.displ; /* getimmed(&source) wiped it out */ + } +} + +/* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */ + +PUBLIC void mEwGw() +{ + ++mcount; + Ew(&target); + getcomma(); + Gw(&source); + oprefix = 0x0; + buildregular(); +} + +/* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */ + +PUBLIC void mExGx() +{ + ++mcount; + Ex(&target); + getcomma(); + Gx(&source); + yes_samesize(); + opcode |= segword; + buildregular(); +} + +PUBLIC void mf_inher() +{ + mcount += 0x2; + postb = REG_MOD | (opcode & ~REG_MOD); + opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6); + if (opcode == ESCAPE_OPCODE_BASE) + opcode = ESCAPE_OPCODE_BASE | 0x6; /* fix up encoding of fcompp */ +} + +/* [fldenv fnsave fnstenv frstor] mem */ + +PUBLIC void mf_m() +{ + ++mcount; + getindirect(&source); + if (source.size != 0x0) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* [fldcw fnstcw] mem2i */ + +PUBLIC void mf_m2() +{ + ++mcount; + getindirect(&source); + if (source.size != 0x0 && source.size != 0x2) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* fnstsw [mem2i ax] */ + +PUBLIC void mf_m2_ax() +{ + if (getaccumreg(&target)) + { + if (target.base != AXREG) + kgerror(ILLREG); + else + { + opcode = 0x74; + target.base = ST0REG; /* fake, really ax */ + buildfreg(); + } + } + else + mf_m2(); +} + +/* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */ + +PUBLIC void mf_m2_m4() +{ + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x2) + opcode |= 0x40; + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* [fild fistp] [mem2i mem4i mem8i] */ + +PUBLIC void mf_m2_m4_m8() +{ + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x2) + opcode |= 0x40; + else if (source.size == 0x8) + opcode |= 0x45; /* low bits 0 -> 5 and 3 -> 7 */ + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* [fcom fcomp] [mem4r mem8r optional-st(i)] */ + +PUBLIC void mf_m4_m8_optst() +{ + if (sym == EOLSYM) + { + target.base = ST1REG; + buildfreg(); + } + else + mf_m4_m8_st(); +} + +/* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */ + +PUBLIC void mf_m4_m8_stst() +{ + target.base = fpregchk(); + if (target.base != NOREG) + { + getcomma(); + source.base = fpregchk(); + if (source.base == NOREG) + { + error(FP_REG_REQ); + source.base = ST0REG; + } + if (target.base == ST0REG) + target.base = source.base; + else + { + if (source.base != ST0REG) + error(ILL_FP_REG_PAIR); + opcode |= 0x40; + if ((opcode & 0x07) >= 0x4) + opcode ^= 0x01; /* weird swap of fdiv/fdivr, fsub/fsubr */ + } + buildfreg(); + } + else + { + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x8) + opcode |= 0x40; + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); + } +} + +/* fst [mem4r mem8r st(i)] */ + +PUBLIC void mf_m4_m8_st() +{ + target.base = fpregchk(); + if (target.base != NOREG) + { + if (opcode == FST_ENCODED) + opcode |= 0x40; + buildfreg(); + } + else + { + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x8) + opcode |= 0x40; + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); + } +} + +/* [fld fstp] [mem4r mem8r mem10r st(i)] */ + +PUBLIC void mf_m4_m8_m10_st() +{ + target.base = fpregchk(); + if (target.base != NOREG) + { + if (opcode == FSTP_ENCODED) + opcode |= 0x40; + buildfreg(); + } + else + { + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x8) + opcode |= 0x40; + else if (source.size == 0xA) + opcode |= 0x25; /* low bits 0 -> 5 and 3 -> 7 */ + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); + } +} + +/* [fbld fbstp] mem10r */ + +PUBLIC void mf_m10() +{ + ++mcount; + getindirect(&source); + if (source.size != 0xA) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* ffree st(i) */ + +PUBLIC void mf_st() +{ + target.base = fpregchk(); + if (target.base == NOREG) + kgerror(FP_REG_REQ); + buildfreg(); +} + +/* [fucom fucomp fxch] optional-st(i) */ + +PUBLIC void mf_optst() +{ + if (sym == EOLSYM) + { + target.base = ST1REG; + buildfreg(); + } + else + mf_st(); +} + +/* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */ + +PUBLIC void mf_stst() +{ + target.base = fpregchk(); + if (target.base == NOREG) + { + kgerror(FP_REG_REQ); + return; + } + getcomma(); + source.base = fpregchk(); + if (source.base == NOREG) + { + kgerror(FP_REG_REQ); + return; + } + if (source.base != ST0REG) + { + kgerror(ILL_FP_REG); + return; + } + buildfreg(); +} + +PUBLIC void mf_w_inher() +{ + sprefix = WAIT_OPCODE; + mf_inher(); +} + +/* [fsave fstenv] mem */ + +PUBLIC void mf_w_m() +{ + sprefix = WAIT_OPCODE; + mf_m(); +} + +/* fstcw mem2i */ + +PUBLIC void mf_w_m2() +{ + sprefix = WAIT_OPCODE; + mf_m2(); +} + +/* fstsw [mem2i ax] */ + +PUBLIC void mf_w_m2_ax() +{ + sprefix = WAIT_OPCODE; + mf_m2_ax(); +} + +/* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */ + +PUBLIC void mgroup1() +{ + getbinary(); + notsegorspecreg(&source); + if (mcount != 0x0) + { + if (source.base == NOREG) + { + if (target.indcount == 0x0 && (target.base == ALREG || + target.base == AXREG || + target.base == EAXREG && + (source.displ.data & (FORBIT | RELBIT | UNDBIT) || + !is8bitsignedoffset(source.displ.offset)))) + { + opcode |= 0x04 | segword; + buildimm(&source, FALSE); + } + else + { + buildunary(0x80 | segword); + buildimm(&source, TRUE); + } + } + else + { + opcode |= direction | segword; + buildregular(); + } + } +} + +/* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */ + +PUBLIC void mgroup2() +{ + ++mcount; + Ex(&target); + buildsegword(&target); + getshift(&source); + if (mcount != 0x0) + { + buildunary(0xD0 | segword); + if (source.base == CLREG) + opcode |= 0x2; + else if (source.displ.offset != 0x1) + { + opcode -= 0x10; + source.size = 0x1; + buildimm(&source, FALSE); + } + } +} + +/* LLDT, LTR, SLDT, STR, VERR, VERW */ + +PUBLIC void mgroup6() +{ + ++mcount; + Ew(&target); + oprefix = 0x0; + buildunary(0x0); +} + +/* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */ + +PUBLIC void mgroup7() +{ + ++mcount; + if (opcode == 0x20 || opcode == 0x30) + { + Ew(&target); + oprefix = 0x0; + } + else + { + getindirect(&target); + oprefix = 0x0; + if (target.size != 0x0 && target.size != 0x6) + error(MISMATCHED_SIZE); /* XXX - size 6 wrong for INVLPG? */ + } + buildunary(0x1); +} + +/* BT, BTR, BTS, BTC */ + +PUBLIC void mgroup8() +{ + ++mcount; + Ev(&target); + getcomma(); + /* Gv or Ib */ + getea(&source); + notindirect(&source); + notsegorspecreg(&source); + if (mcount != 0x0) + { + if (source.base == NOREG) + { + buildunary(0xBA); + source.size = 0x1; + buildimm(&source, TRUE); + } + else + { + yes_samesize(); + opcode += 0x83; + buildregular(); + } + } +} + +/* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */ + +PUBLIC void mGvEv() +{ + ++mcount; + Gv(&source); + getcomma(); + Ev(&target); + yes_samesize(); + buildregular(); +} + +/* bound [r16,m16&16 r32,m32&32] */ + +PUBLIC void mGvMa() +{ + ++mcount; + Gv(&source); + getcomma(); + getindirect(&target); + yes_samesize(); + buildregular(); +} + +/* LDS, LES, LFS, LGS, LSS */ + +PUBLIC void mGvMp() +{ + ++mcount; + Gv(&source); + getcomma(); + getindirect(&target); + if (target.size != 0x0 && target.size != 0x2 + source.size) + error(MISMATCHED_SIZE); + buildregular(); +} + +/* IMUL */ + +PUBLIC void mimul() +{ + ++mcount; + Ex(&target); + if (sym != COMMA) + { + buildsegword(&target); + buildunary(0xF6 | segword); + return; + } + getcomma(); + notindirect(&target); + source = target; /* direction is swapped */ + getea(&target); + notsegorspecreg(&target); + yes_samesize(); + if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG)) + { + page = PAGE1_OPCODE; + ++mcount; + opcode = 0xAF; + buildregular(); + } + else + { + if (sym == COMMA) + { + getsym(); + getea(&source2); + yesimmed(&source2); + } + else + { + source2 = target; + target = source; + } + source2.size = target.size; + if (is8bitsignedoffset(source2.displ.offset)) + { + source2.size = 0x1; + opcode = 0x6B; + } + else + { + source2.size = target.size; + opcode = 0x69; + } + buildregular(); + if (mcount != 0x0) + buildimm(&source2, FALSE); + } +} + +/* IN */ + +PUBLIC void min() +{ + ++mcount; + if (opcode & WORDBIT) /* inw; ind not supported */ + mnsize = 0x2; + if (sym == EOLSYM && mnsize != 0x0) + target.size = mnsize; + else + { + if (getaccumreg(&target)) + { + if (mnsize != 0x0 && regsize[target.base] != mnsize) + error(MISMATCHED_SIZE); + getcomma(); + } + else + target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG]; + opcode |= regsegword[target.base]; + if (!getdxreg(&source)) + { + getimmed(&source, 0x1); + opcode -= 0x8; + } + } + if (target.size > 0x1 && target.size != defsize) + oprefix = 0x66; +} + +/* DEC, INC */ + +PUBLIC void mincdec() +{ + ++mcount; + Ex(&target); + buildsegword(&target); + if (target.indcount == 0x0 && segword == WORDBIT) + opcode |= 0x40 | rm[target.base]; + else + buildunary(0xFE | segword); +} + +/* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */ +/* MOVSW, OUTSW, SCASW, STOSW */ + +PUBLIC void minher16() +{ + minher(); + if (defsize != 0x2) + oprefix = 0x66; +} + +/* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */ +/* MOVSD, OUTSD, SCASD, STOSD */ + +PUBLIC void minher32() +{ + minher(); + if (defsize != 0x4) + oprefix = 0x66; +} + +/* AAD, AAM */ + +PUBLIC void minhera() +{ + ++mcount; + if (sym == EOLSYM) + { + target.displ.offset = 0xA; + target.size = 0x1; + buildimm(&target, FALSE); + } + else + getimmed(&target, 0x1); +} + +/* INT */ + +PUBLIC void mint() +{ + ++mcount; + getimmed(&target, 0x1); + if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) && + (opcode_t) immadr.offset == 0x3) + { + immcount = 0x0; + opcode = 0xCC; + } +} + +/* JCC */ + +PUBLIC void mjcc() +{ + if (jumps_long && opcode < 0x80) /* above 0x80 means loop - not long */ + mbcc(); + else + mshort(); +} + +/* JCXZ, JECXZ */ + +PUBLIC void mjcxz() +{ + if (opcode != defsize) + { + aprefix = 0x67; + ++mcount; /* quick fix - mshort() needs to know */ + } + opcode = 0xE3; + mshort(); + if (aprefix != 0x0) + --mcount; /* quick fix - main routine bumps it again */ +} + +/* LEA */ + +PUBLIC void mlea() +{ + Gv(&source); /* back to front */ + getcomma(); + ++mcount; + getindirect(&target); + yes_samesize(); + buildregular(); +} + +/* MOV */ + +PUBLIC void mmov() +{ + getbinary(); + if (segword >= SEGMOV) + { + oprefix = 0x0; + notimmed(&target); /* target is actually the source */ + if (segword > SEGMOV) /* special reg */ + notindirect(&target); + } + if (mcount != 0x0) + { + if (target.base == NOREG && target.index == NOREG && + (source.base == ALREG || source.base == AXREG || + source.base == EAXREG)) + { + opcode = 0xA0 | (direction ^ TOREGBIT) | segword; + lastexp = target.displ; + if ((source.size = displsize(&target)) != defsize) + aprefix = 0x67; + mcount += source.size; + } + else if (source.base == NOREG) + { + if (target.indcount == 0x0) + opcode = 0xB0 | (segword << 0x3) | rm[target.base]; + else + { + buildea(&target); + opcode = 0xC6 | segword; + } + buildimm(&source, FALSE); + } + else + { + if (isspecreg(source.base)) + { + page = PAGE1_OPCODE; + ++mcount; + opcode = 0x0; + } + opcode |= direction | segword; + buildregular(); + } + } +} + +/* MOVSX, MOVZX */ + +PUBLIC void mmovx() +{ + ++mcount; + Gv(&source); + getcomma(); + Ex(&target); + if (target.size == 0x0) + kgerror(SIZE_UNK); + if (target.size > 0x2) + kgerror(ILL_SIZE); + oprefix = 0x0; + if (source.size != defsize) + oprefix = 0x66; + buildsegword(&target); + opcode |= segword; + buildregular(); +} + +/* NEG, NOT */ + +PUBLIC void mnegnot() +{ + ++mcount; + Ex(&target); + buildsegword(&target); + buildunary(0xF6 | segword); +} + +/* OUT */ + +PUBLIC void mout() +{ + ++mcount; + if (opcode & WORDBIT) /* outw; outd not supported */ + mnsize = 0x2; + if (sym == EOLSYM && mnsize != 0x0) + source.size = mnsize; + else + { + if (!getdxreg(&target)) + { + getimmed(&target, 0x1); + opcode -= 0x8; + } + if (sym == COMMA) + { + getsym(); + if (!getaccumreg(&source)) + kgerror(AL_AX_EAX_EXP); + else if (mnsize != 0x0 && regsize[source.base] != mnsize) + error(MISMATCHED_SIZE); + } + else + source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG]; + opcode |= regsegword[source.base]; + } + if (source.size > 0x1 && source.size != defsize) + oprefix = 0x66; +} + +/* POP, PUSH */ + +PUBLIC void mpushpop() +{ + opcode_t oldopcode; + + ++mcount; + getea(&target); + buildsegword(&target); + notbytesize(&target); + if ((oldopcode = opcode) == POP_OPCODE) + { + notimmed(&target); + if (target.base == CSREG) + kgerror(ILL_SEG_REG); + } + if (mcount != 0x0) + { + if (target.indcount == 0x0) + { + if (segword == SEGMOV) + { + switch (target.base) + { + case CSREG: + opcode = 0x0E; + break; + case DSREG: + opcode = 0x1E; + break; + case ESREG: + opcode = 0x06; + break; + case SSREG: + opcode = 0x16; + break; + case FSREG: + opcode = 0xA0; + page = PAGE1_OPCODE; + ++mcount; + break; + case GSREG: + opcode = 0xA8; + page = PAGE1_OPCODE; + ++mcount; + break; + } + if (oldopcode == POP_OPCODE) + ++opcode; + } + else if (target.base != NOREG) + { + opcode = 0x50 | rm[target.base]; + if (oldopcode == POP_OPCODE) + opcode |= 0x8; + } + else + { + opcode = 0x68; + if (oldopcode == POP_OPCODE) + ++opcode; + buildimm(&target, TRUE); + } + } + else + { + buildea(&target); + if (oldopcode == PUSH_OPCODE) + postb |= 0x6 << REG_SHIFT; + } + } +} + +/* RET, RETF */ + +PUBLIC void mret() +{ + ++mcount; + if (sym != EOLSYM) + { + --opcode; + getimmed(&target, 0x2); + } +} + +/* SEG CS/DS/ES/FS/GS/SS */ + +PUBLIC void mseg() +{ + reg_pt reg; + + if (regsegword[reg = regchk()] != SEGMOV) + error(SEG_REG_REQ); + else + { + getsym(); + ++mcount; + opcode = (segoverride - CSREG)[reg]; + } +} + +/* SETCC */ + +PUBLIC void msetcc() +{ + ++mcount; + Eb(&target); + if (mcount != 0x0) + buildea(&target); +} + +/* SHLD, SHRD */ + +PUBLIC void mshdouble() +{ + ++mcount; + Ev(&target); + getcomma(); + Gv(&source); + yes_samesize(); + buildregular(); + getshift(&source2); + lastexp = target.displ; /* getshift() wiped it out */ + if (mcount != 0x0) + { + if (source2.base == CLREG) + opcode |= 0x1; + else + { + source2.size = 0x1; + buildimm(&source2, FALSE); + } + } +} + +/* + TEST + Similar to the regular group1 operators. + It does not allow the sign extended immediate byte forms + and does not use the relevant direction bit. +*/ + +PUBLIC void mtest() +{ + getbinary(); + notsegorspecreg(&source); + if (source.base == NOREG) + { + if (mcount != 0x0) + { + if (target.indcount == 0x0 + && (target.base == ALREG || target.base == AXREG + || target.base == EAXREG)) + opcode = 0xA8 | segword; + else + { + buildea(&target); + opcode = 0xF6 | segword; + } + } + buildimm(&source, FALSE); + } + else + { + opcode |= segword; + buildregular(); + } +} + +/* + XCHG + Similar to the regular group1 operators. + It does not allow any of the immediate forms + and does not use the irrelevant direction bit. +*/ + +PUBLIC void mxchg() +{ + getbinary(); + notimmed(&source); + notsegorspecreg(&source); + if (target.indcount == 0x0) + { + if (target.base == AXREG || target.base == EAXREG) + { + opcode = 0x90 + rm[source.base]; + return; + } + if (source.base == AXREG || source.base == EAXREG) + { + opcode = 0x90 + rm[target.base]; + return; + } + } + opcode |= segword; + buildregular(); +} + +PRIVATE void notbytesize(eap) +register struct ea_s *eap; +{ + if (eap->size == 0x1) + kgerror(ILL_SIZE); +} + +PRIVATE void notimmed(eap) +register struct ea_s *eap; +{ + if (eap->indcount == 0x0 && eap->base == NOREG) + kgerror(ILL_IMM_MODE); +} + +PRIVATE void notindirect(eap) +register struct ea_s *eap; +{ + if (eap->indcount != 0x0) + kgerror(ILL_IND); +} + +PRIVATE void notsegorspecreg(eap) +register struct ea_s *eap; +{ + if (regsegword[eap->base] >= SEGMOV) + kgerror(ILLREG); +} + +PRIVATE void yesimmed(eap) +register struct ea_s *eap; +{ + if (eap->indcount == 0x1) + eap->indcount = 0x0; + if (eap->indcount != 0x0 || eap->base != NOREG) + kgerror(IMM_REQ); +} + +PRIVATE void yes_samesize() +{ + if (target.size == 0x0) + target.size = source.size; + else if (source.size != 0x0 && target.size != source.size) + kgerror(MISMATCHED_SIZE); +} + +#endif /* I80386 */ + +#ifdef MC6809 + +/* 6809 opcode constants */ + +/* bits for indexed addressing */ + +#define INDIRECTBIT 0x10 +#define INDEXBIT 0x80 /* except 5 bit offset */ +#define PCRELBIT 0x04 /* PC relative (in certain cases) */ +#define RRBITS 0x60 /* register select bits */ + +PRIVATE opcode_t rrindex[] = /* register and index bits for indexed adr */ +{ + 0x60 | INDEXBIT, /* S */ + 0x40 | INDEXBIT, /* U */ + 0x00 | INDEXBIT, /* X */ + 0x20 | INDEXBIT, /* Y */ + PCRELBIT | INDEXBIT, /* PC */ +}; + +PRIVATE opcode_t pushpull[] = /* push/pull codes */ +{ + 0x40, /* S */ + 0x40, /* U */ + 0x10, /* X */ + 0x20, /* Y */ + 0x80, /* PC */ + 0x02, /* A */ + 0x04, /* B */ + 0x01, /* CC */ + 0x08, /* DP */ + 0x06, /* D */ +}; + +PRIVATE opcode_t tfrexg1[] = /* transfer/exchange codes for source reg */ +{ + 0x40, /* S */ + 0x30, /* U */ + 0x10, /* X */ + 0x20, /* Y */ + 0x50, /* PC */ + 0x80, /* A */ + 0x90, /* B */ + 0xA0, /* CC */ + 0xB0, /* DP */ + 0x00, /* D */ +}; + +PRIVATE opcode_t tfrexg2[] = /* transfer/exchange codes for target reg */ +{ + 0x04, /* S */ + 0x03, /* U */ + 0x01, /* X */ + 0x02, /* Y */ + 0x05, /* PC */ + 0x08, /* A */ + 0x09, /* B */ + 0x0A, /* CC */ + 0x0B, /* DP */ + 0x00, /* D */ +}; + +FORWARD void checkpostinc P((void)); +FORWARD void doaltind P((void)); +FORWARD void do1altind P((void)); +FORWARD void fixupind P((void)); +FORWARD void getindexnopost P((void)); +FORWARD void inderror P((error_pt errnum)); +FORWARD reg_pt indreg P((reg_pt maxindex)); +FORWARD void predec1 P((void)); +FORWARD void sustack P((reg_pt stackreg)); + +PRIVATE void checkpostinc() +{ + if (sym == ADDOP) + { + if (postb & INDIRECTBIT) + inderror(ILLMOD); /* single-inc indirect illegal */ + else + { + lastexp.offset &= 0xFF00; /* for printing if postbyte is 0: ,X+ */ + getsym(); + } + } + else if (sym == POSTINCOP) + { + postb |= 0x1; + getsym(); + } + else + postb |= 0x4; + fixupind(); +} + +/* common code for all-mode ops, alterable-mode ops, indexed ops */ + +PRIVATE void doaltind() +{ + mcount += 0x2; + if (sym == LBRACKET) + { + postb = INDIRECTBIT; + getsym(); + do1altind(); + if (sym != RBRACKET) + error(RBEXP); + } + else + do1altind(); +} + +PRIVATE void do1altind() +{ + bool_t byteflag; /* set if direct or short indexed adr forced */ + char *oldlineptr; + char *oldsymname; + reg_pt reg; + bool_t wordflag; /* set if extended or long indexed adr forced*/ + + if ((reg = regchk()) != NOREG) + { + switch (reg) + { + case AREG: + postb |= 0x86; + break; + case BREG: + postb |= 0x85; + break; + case DREG: + postb |= 0x8B; + break; + default: + if (indreg(MAXINDREG) != NOREG) + checkpostinc(); + return; + } + getsym(); + if (sym != COMMA) + inderror(COMEXP); + else + getindexnopost(); + return; + } + else if (sym == SUBOP) /* could be -R or - in expression */ + { + oldlineptr = lineptr; /* save state */ + oldsymname = symname; + getsym(); + reg = regchk(); + lineptr = oldlineptr; + symname = oldsymname; + if (reg != NOREG) + { + predec1(); /* it's -R */ + return; + } + sym = SUBOP; + } + else if (sym == COMMA) + { + postb |= INDEXBIT; + getsym(); + if (sym == SUBOP) + { + predec1(); + return; + } + else if (sym != PREDECOP) + { + if (indreg(MAXINDREG) != NOREG) + checkpostinc(); + return; + } + } + if (sym == PREDECOP) + { + postb |= 0x83; + getindexnopost(); + return; + } + + /* should have expression */ + + wordflag = byteflag = FALSE; + if (sym == LESSTHAN) + { + /* context-sensitive, LESSTHAN means byte-sized here */ + byteflag = TRUE; + getsym(); + } + else if (sym == GREATERTHAN) + { + /* context-sensitive, GREATERTHAN means word-sized here */ + wordflag = TRUE; + getsym(); + } + expres(); + if (sym == COMMA) + { /* offset from register */ + getsym(); + if ((reg = indreg(PCREG)) == NOREG) + return; + postb |= 0x8; /* default 8 bit offset */ + if (reg == PCREG) + { + reldata(); + if (!(lastexp.data & (RELBIT | UNDBIT))) + { + lastexp.offset = lastexp.offset - lc; + if (page != 0x0) + lastexp.offset -= 0x4; /* extra for instruction */ + else + lastexp.offset -= 0x3; /* 3 byte instruction + assuming 8 bit offset */ + } + } + if (byteflag) + { + if (!(lastexp.data & (RELBIT | UNDBIT)) && + !is8bitsignedoffset(lastexp.offset)) + error(ABOUNDS); /* forced short form is impossible */ + ++mcount; + } + else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) || + !is8bitsignedoffset(lastexp.offset)) + { /* 16 bit offset */ + if (postb & PCRELBIT && !(lastexp.data & RELBIT)) + --lastexp.offset; /* instruction 1 longer than already + allowed */ + postb |= 0x1; + mcount += 0x2; + } + else if (!(postb & PCRELBIT) && + (offset_t) (lastexp.offset + 0x10) < 0x20 && + !(postb & INDIRECTBIT && lastexp.offset != 0x0)) + { /* 5 bit offset */ + postb &= RRBITS | INDIRECTBIT; + if (lastexp.offset == 0x0) + postb |= 0x84; /* index with zero offset */ + else + postb |= (lastexp.offset & 0x1F); + } + else /* 8 bit offset */ + ++mcount; + fixupind(); + } + else if (postb & INDIRECTBIT) + { /* extended indirect */ + postb = 0x9F; + mcount += 0x2; + fixupind(); + } + else if (postb & INDEXBIT) + inderror(ILLMOD); /* e.g. LEAX $10 */ + else + { + if (byteflag || !wordflag && !(lastexp.data & (FORBIT | RELBIT)) && + (lastexp.offset >> 0x8) == dirpag) + { /* direct addressing */ + if (opcode >= 0x80) + opcode |= 0x10; + } + else /* extended addressing */ + { + if (opcode < 0x80) + opcode |= 0x70; + else + opcode |= 0x30; + ++mcount; + if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) && + !(lastexp.data & IMPBIT) && + lastexp.offset + (0x81 - 0x3) < 0x101) + /* JSR or JMP could be done with BSR or BRA */ + error(SHORTB); + } + } +} + +PRIVATE void fixupind() +{ + if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */ + { + if (opcode < 0x80) + opcode |= 0x60; + else + opcode |= 0x20; + } +} + +PRIVATE void getindexnopost() +{ + getsym(); + if (indreg(MAXINDREG) != NOREG) + fixupind(); +} + +PRIVATE void inderror(errnum) +error_pt errnum; +{ + error(errnum); + if (postb & INDIRECTBIT) + sym = RBRACKET; /* fake right bracket to kill further errors */ + fixupind(); +} + +/* check current symbol is an index register (possibly excepting PC) */ +/* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */ +/* otherwise generate error, return FALSE */ + +PRIVATE reg_pt indreg(maxindex) +reg_pt maxindex; +{ + reg_pt reg; + + if ((reg = regchk()) == NOREG) + inderror(IREGEXP); + else if (reg > maxindex) + { + inderror(ILLREG); + reg = NOREG; + } + else + { + postb |= rrindex[reg]; + getsym(); + } + return reg; +} + +/* all-mode ops */ + +PUBLIC void mall() +{ + if (sym == IMMEDIATE) + mimmed(); + else + malter(); +} + +/* alterable mode ops */ + +PUBLIC void malter() +{ + postb = 0x0; /* not yet indexed or indirect */ + doaltind(); +} + +/* indexed mode ops */ + +PUBLIC void mindex() +{ + postb = INDEXBIT; /* indexed but not yet indirect */ + doaltind(); +} + +/* immediate ops */ + +PUBLIC void mimmed() +{ + opcode_t nybble; + + mcount += 0x2; + if (sym != IMMEDIATE) + error(ILLMOD); + else + { + if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 || + nybble == 0xC || nybble >= 0xE)) + ++mcount; /* magic for long immediate */ + symexpres(); + if (pass2 && mcount <= 0x2) + { + chkabs(); + checkdatabounds(); + } + } +} + +/* long branches */ + +PUBLIC void mlong() +{ + mcount += 0x3; /* may be 0x0 or 0x1 here */ + expres(); + if (pass2) + { + reldata(); + if (!(lastexp.data & (RELBIT | UNDBIT))) + { + lastexp.offset = lastexp.offset - lc - lcjump; + if (!(lastexp.data & IMPBIT) && + lastexp.offset + 0x81 < 0x101) + error(SHORTB); /* -0x81 to 0x7F, warning */ + } + } +} + +/* PSHS and PULS */ + +PUBLIC void msstak() +{ + sustack(SREG); +} + +/* TFR and EXG */ + +PUBLIC void mswap() +{ + reg_pt reg; + + mcount = 0x2; + if ((reg = regchk()) == NOREG) + error(REGEXP); + else + { + postb = tfrexg1[reg]; + getsym(); + if (sym != COMMA) + error(COMEXP); + else + { + getsym(); + if ((reg = regchk()) == NOREG) + error(REGEXP); + else if ((postb |= tfrexg2[reg]) + & 0x88 && (postb & 0x88) != 0x88) + error(ILLREG); /* registers not of same size */ + } + } +} + +/* PSHU and PULU */ + +PUBLIC void mustak() +{ + sustack(UREG); +} + +PRIVATE void predec1() +{ + if (postb & INDIRECTBIT) + inderror(ILLMOD); /* single-dec indirect illegal */ + else + { + postb |= 0x82; + getindexnopost(); + } +} + +/* common routine for PSHS/PULS/PSHU/PULU */ + +PRIVATE void sustack(stackreg) +reg_pt stackreg; +{ + reg_pt reg; + + mcount = 0x2; + while ((reg = regchk()) != NOREG) + { + if (reg == stackreg) + { + error(ILLREG); /* cannot stack self */ + break; + } + postb |= pushpull[reg]; + getsym(); + if (sym != COMMA) + break; + getsym(); + } +} + +#endif /* MC6809 */ + +/* routines common to all processors */ + +PUBLIC void getcomma() +{ + if (sym != COMMA) + error(COMEXP); + else + getsym(); +} + +/* inherent ops */ + +/* for I80386 */ +/* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */ +/* INVD, */ +/* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */ +/* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */ + +PUBLIC void minher() +{ + ++mcount; +} + +/* short branches */ + +PUBLIC void mshort() +{ + nonimpexpres(); + mshort2(); +} + +PRIVATE void mshort2() +{ + mcount += 0x2; + if (pass2) + { + reldata(); + if (lastexp.data & RELBIT) + showrelbad(); + else if (!(lastexp.data & UNDBIT)) + { + lastexp.offset = lastexp.offset - lc - mcount; + if (!is8bitsignedoffset(lastexp.offset)) + error(ABOUNDS); + } + } +} + +/* check if current symbol is a register, return register number or NOREG */ + +PRIVATE reg_pt regchk() +{ + register struct sym_s *symptr; + + if (sym == IDENT) + { + if ((symptr = gsymptr)->type & MNREGBIT) + { + if (symptr->data & REGBIT) + { +#ifdef I80386 + if (symptr->value_reg_or_op.reg == ST0REG && !fpreg_allowed) + error(FP_REG_NOT_ALLOWED); +#endif + return symptr->value_reg_or_op.reg; + } + } + else if (!(symptr->type & (LABIT | MACBIT | VARBIT))) + symptr->data |= FORBIT; /* show seen in advance */ + } + return NOREG; +} + +/* convert lastexp.data for PC relative */ + +PRIVATE void reldata() +{ + if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM)) + { + if ((lastexp.data ^ lcdata) & RELBIT) + showrelbad(); /* rel - abs is weird, abs - rel is bad */ + else + { + pcrflag = OBJ_R_MASK; + lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT; + /* segment is that of lastexp.data */ + } + } + else /* same file, segment and relocation */ + lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM); +} diff --git a/as/obj1/calljmp.obj b/as/obj1/calljmp.obj Binary files differnew file mode 100644 index 0000000..522d6f7 --- /dev/null +++ b/as/obj1/calljmp.obj diff --git a/as/obj1/ea.obj b/as/obj1/ea.obj Binary files differnew file mode 100644 index 0000000..6b53beb --- /dev/null +++ b/as/obj1/ea.obj diff --git a/as/obj1/each.obj b/as/obj1/each.obj Binary files differnew file mode 100644 index 0000000..5426253 --- /dev/null +++ b/as/obj1/each.obj diff --git a/as/obj1/f.obj b/as/obj1/f.obj Binary files differnew file mode 100644 index 0000000..4dbe2d9 --- /dev/null +++ b/as/obj1/f.obj diff --git a/as/obj1/fadd.obj b/as/obj1/fadd.obj Binary files differnew file mode 100644 index 0000000..28b3dd4 --- /dev/null +++ b/as/obj1/fadd.obj diff --git a/as/obj1/farcall.obj b/as/obj1/farcall.obj Binary files differnew file mode 100644 index 0000000..259703c --- /dev/null +++ b/as/obj1/farcall.obj diff --git a/as/obj1/group1.obj b/as/obj1/group1.obj Binary files differnew file mode 100644 index 0000000..26d4a8c --- /dev/null +++ b/as/obj1/group1.obj diff --git a/as/obj1/group6.obj b/as/obj1/group6.obj Binary files differnew file mode 100644 index 0000000..27e81ae --- /dev/null +++ b/as/obj1/group6.obj diff --git a/as/obj1/group7.obj b/as/obj1/group7.obj Binary files differnew file mode 100644 index 0000000..37af051 --- /dev/null +++ b/as/obj1/group7.obj diff --git a/as/obj1/imul.obj b/as/obj1/imul.obj Binary files differnew file mode 100644 index 0000000..34ef370 --- /dev/null +++ b/as/obj1/imul.obj diff --git a/as/obj1/incdec.obj b/as/obj1/incdec.obj Binary files differnew file mode 100644 index 0000000..03f583a --- /dev/null +++ b/as/obj1/incdec.obj diff --git a/as/obj1/inher.obj b/as/obj1/inher.obj Binary files differnew file mode 100644 index 0000000..aaea0b9 --- /dev/null +++ b/as/obj1/inher.obj diff --git a/as/obj1/inout.obj b/as/obj1/inout.obj Binary files differnew file mode 100644 index 0000000..58aa820 --- /dev/null +++ b/as/obj1/inout.obj diff --git a/as/obj1/movspec.obj b/as/obj1/movspec.obj Binary files differnew file mode 100644 index 0000000..15eab78 --- /dev/null +++ b/as/obj1/movspec.obj diff --git a/as/obj1/pushpop.obj b/as/obj1/pushpop.obj Binary files differnew file mode 100644 index 0000000..2ff789e --- /dev/null +++ b/as/obj1/pushpop.obj diff --git a/as/obj1/seg.obj b/as/obj1/seg.obj Binary files differnew file mode 100644 index 0000000..2ba948c --- /dev/null +++ b/as/obj1/seg.obj diff --git a/as/obj1/shdouble.obj b/as/obj1/shdouble.obj Binary files differnew file mode 100644 index 0000000..ab75750 --- /dev/null +++ b/as/obj1/shdouble.obj diff --git a/as/obj1/shift.obj b/as/obj1/shift.obj Binary files differnew file mode 100644 index 0000000..520be81 --- /dev/null +++ b/as/obj1/shift.obj diff --git a/as/obj1/xchg.obj b/as/obj1/xchg.obj Binary files differnew file mode 100644 index 0000000..c39b703 --- /dev/null +++ b/as/obj1/xchg.obj diff --git a/as/opcode.h b/as/opcode.h new file mode 100644 index 0000000..385c096 --- /dev/null +++ b/as/opcode.h @@ -0,0 +1,157 @@ +/* opcode.h - routine numbers and special opcodes for assembler */ + +enum +{ +/* Pseudo-op routine numbers. + * Conditionals are first - this is used to test if op is a conditional. + */ + ELSEOP, + ELSEIFOP, + ELSEIFCOP, + ENDIFOP, + IFOP, + IFCOP, + +#define MIN_NONCOND ALIGNOP + ALIGNOP, + ASCIZOP, + BLKWOP, + BLOCKOP, + BSSOP, + COMMOP, + COMMOP1, + DATAOP, + ENDBOP, + ENTEROP, + ENTRYOP, + EQUOP, + EVENOP, + EXPORTOP, + FAILOP, + FCBOP, + FCCOP, + FDBOP, + FQBOP, + GETOP, + GLOBLOP, + IDENTOP, + IMPORTOP, + LCOMMOP, + LCOMMOP1, + LISTOP, + LOCOP, + MACLISTOP, + MACROOP, + MAPOP, + ORGOP, + PROCEOFOP, + RMBOP, + SECTOP, + SETOP, + SETDPOP, + TEXTOP, +#ifdef I80386 + USE16OP, + USE32OP, +#endif + WARNOP, + +/* Machine-op routine numbers. */ +#ifdef I80386 + BCC, + BSWAP, + CALL, + CALLI, + DIVMUL, + ENTER, + EwGw, + ExGx, + F_INHER, + F_M, + F_M2, + F_M2_AX, + F_M2_M4, + F_M2_M4_M8, + F_M4_M8_OPTST, + F_M4_M8_ST, + F_M4_M8_STST, + F_M4_M8_M10_ST, + F_M10, + F_OPTST, + F_ST, + F_STST, + F_W_INHER, + F_W_M, + F_W_M2, + F_W_M2_AX, + GROUP1, + GROUP2, + GROUP6, + GROUP7, + GROUP8, + GvEv, + GvMa, + GvMp, + IMUL, + IN, + INCDEC, + INHER, + INHER16, + INHER32, + INHER_A, + INT, + JCC, + JCXZ, + LEA, + MOV, + MOVX, + NEGNOT, + OUT, + PUSHPOP, + RET, + SEG, + SETCC, + SH_DOUBLE, + TEST, + XCHG +#endif /* I80386 */ + +#ifdef MC6809 + ALL, /* all address modes allowed, like LDA */ + ALTER, /* all but immediate, like STA */ + IMMED, /* immediate only (ANDCC, ORCC) */ + INDEXD, /* indexed (LEA's) */ + INHER, /* inherent, like CLC or CLRA */ + LONG, /* long branches */ + SHORT, /* short branches */ + SSTAK, /* S-stack (PSHS, PULS) */ + SWAP, /* TFR, EXG */ + USTAK /* U-stack (PSHU,PULU) */ +#endif /* MC6809 */ +}; + +/* Special opcodes. */ +#ifdef I80386 +# define CMP_OPCODE_BASE 0x38 +# define CMPSB_OPCODE 0xA6 +# define CMPSW_OPCODE 0xA7 +# define ESCAPE_OPCODE_BASE 0xD8 +# define FST_ENCODED 0x12 +# define FSTP_ENCODED 0x13 +# define JMP_OPCODE 0xE9 +# define JMP_SHORT_OPCODE 0xEB +# define JSR_OPCODE 0xE8 +# define MOVSB_OPCODE 0xA4 +# define MOVSW_OPCODE 0xA5 +# define PAGE1_OPCODE 0x0F +# define POP_OPCODE 0x8F +# define PUSH_OPCODE 0xFF +# define WAIT_OPCODE 0x9B +#endif + +#ifdef MC6809 +# define JMP_OPCODE 0x7E +# define JSR_OPCODE 0xBD +# define PAGE1_OPCODE 0x10 +# define PAGE2_OPCODE 0x11 +#endif diff --git a/as/pops.c b/as/pops.c new file mode 100644 index 0000000..aca4841 --- /dev/null +++ b/as/pops.c @@ -0,0 +1,1048 @@ +/* pops.c - handle pseudo-ops for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "flag.h" +#include "globvar.h" +#include "opcode.h" +#include "scan.h" + +PRIVATE bool_t elseflag; /* set if ELSE/ELSEIF are enabled */ + /* depends on zero = FALSE init */ +PRIVATE bool_t lcommflag; + +FORWARD void bumpsem P((struct flags_s *flagptr)); +FORWARD void constdata P((unsigned size)); +FORWARD void docomm P((void)); +FORWARD void doelseif P((pfv func)); +FORWARD void doequset P((int labits)); +FORWARD void doentexp P((int entbits, int impbits)); +FORWARD void dofcc P((void)); +FORWARD void doif P((pfv func)); +FORWARD struct sym_s *needlabel P((void)); +FORWARD void showredefinedlabel P((void)); +FORWARD void setloc P((unsigned seg)); + +PRIVATE void bumpsem(flagptr) +register struct flags_s *flagptr; +{ + int newcount; + + if (flagptr->global &&pass != 0) + { + /* bump semaphore count by an expression (default 1), */ + /* then set currentflag iff semaphore count is plus */ + if (sym == EOLSYM) + lastexp.offset = 1; + else + { + absexpres(); + if (lastexp.data & UNDBIT) + return; + } + newcount = (int) lastexp.offset; +#ifdef I80386 /* really sizeof (offset_t) != sizeof (int) */ + if (newcount != lastexp.offset) + datatoobig(); +#endif + newcount += flagptr->semaphore; + if ((int) lastexp.offset >= 0) + { + if (newcount < flagptr->semaphore) + { + error(COUNTOV); + newcount = 0x7fff; + } + } + else if (newcount >= flagptr->semaphore) + { + error(COUNTUN); + newcount = -0x8000; + } + flagptr->semaphore = newcount; + flagptr->current = newcount >= 0; + } +} + +/* check symbol is either undefined */ +/* or has the same segment & relocatability as lc */ + +PUBLIC bool_pt checksegrel(symptr) +register struct sym_s *symptr; +{ + if ((symptr->type & LABIT || + symptr->data & IMPBIT && !(symptr->data & UNDBIT)) && + ((symptr->data ^ lcdata) & (RELBIT | SEGM))) + { + error(SEGREL); + return FALSE; + } + return TRUE; +} + +/* check address fits in 1 byte (possibly with sign truncated) */ + +PUBLIC void checkdatabounds() +{ + if (!(lastexp.data & UNDBIT) && + (offset_t) (lastexp.offset + 0x80) >= 0x180) + datatoobig(); +} + +/* allocate constant data (zero except for size 1), default zero for size 1 */ + +PRIVATE void constdata(size) +unsigned size; +{ + offset_t remaining; + + absexpres(); + if (!((lcdata |= lastexp.data) & UNDBIT)) + { + lcjump = lastexp.offset * size; + popflags = POPLONG | POPHI | POPLO | POPLC; + if (size == 1 && sym == COMMA) + { + symabsexpres(); + checkdatabounds(); + for (remaining = lcjump; remaining != 0; --remaining) + { + putbin((opcode_pt) lastexp.offset); /* fill byte */ + putabs((opcode_pt) lastexp.offset); + } + lastexp.offset = lcjump; + } + else + accumulate_rmb(lastexp.offset * size); + } +} + +PUBLIC void datatoobig() +{ + error(DBOUNDS); +} + +/* common routine for COMM/.COMM */ + +PRIVATE void docomm() +{ + register struct sym_s *labptr; + + absexpres(); /* if undefined, value 0 and size unchanged */ + labptr = label; + if (checksegrel(labptr)) + { + if (labptr->type & (EXPBIT | LABIT)) + labelerror(ALREADY); + else + { + if (!(labptr->type & COMMBIT) || + lastexp.offset > labptr->value_reg_or_op.value) + labptr->value_reg_or_op.value = lastexp.offset; + labptr->type |= COMMBIT; + if (lcommflag) + labptr->type |= REDBIT; /* kludge - COMMBIT | REDBIT => SA */ + labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT); + showlabel(); + } + } + lcommflag = FALSE; +} + +/* common routine for ELSEIF/ELSEIFC */ + +PRIVATE void doelseif(func) +pfv func; +{ + if (iflevel == 0) + error(ELSEIFBAD); + else + { + ifflag = FALSE; + if (elseflag) + { + (*func) (); + if (!(lastexp.data & UNDBIT) && lastexp.offset != 0) + /* expression valid and TRUE, enable assembling */ + { + ifflag = TRUE; + elseflag = FALSE; + } + } + } +} + +/* common routine for EQU/SET */ + +PRIVATE void doequset(labits) +unsigned char labits; +{ + register struct sym_s *labptr; + unsigned char olddata; + unsigned char oldtype; + + labptr = label; + /* set up new label flags in case labe isl used in expression */ + labptr->type = (oldtype = labptr->type) | labits; + labptr->data = (olddata = labptr->data) & ~IMPBIT; + /* non-imported now */ + nonimpexpres(); + lastexp.data |= olddata & FORBIT; /* take all but FORBIT from + expression */ + if (oldtype & LABIT && !(olddata & UNDBIT)) + /* this is a previously defined label */ + + /* + redefinition only allowed if same relocatability, segment and + value + */ + { + if ((olddata ^ lastexp.data) & (RELBIT | UNDBIT) || + labptr->value_reg_or_op.value != lastexp.offset) + { + showredefinedlabel(); + return; + } + } + labptr->data = lastexp.data; + labptr->value_reg_or_op.value = lastexp.offset; + showlabel(); +} + +/* common routine for ENTRY/EXPORT */ + +PRIVATE void doentexp(entbits, impbits) +unsigned char entbits; +unsigned char impbits; +{ + struct sym_s *symptr; + + while (TRUE) + { + if ((symptr = needlabel()) != NULL) + { + if (symptr->type & COMMBIT) + error(ALREADY); + else if (impbits != 0) + { + if (pass != 0) + ; + else if (symptr->type & (EXPBIT | LABIT)) + symptr->type |= EXPBIT; + else + { + symptr->type |= REDBIT; + if (!(symptr->data & IMPBIT)) + symptr->data |= IMPBIT | SEGM; + } + } + else + { + if (pass != 0) + { + if (!(symptr->type & LABIT)) + error(UNLAB); + } + else + { + symptr->type |= entbits | EXPBIT; + symptr->data &= ~IMPBIT; + } + } + } + getsym(); + if (sym != COMMA) + break; + getsym(); + } +} + +/* common routine for FCC (== .ASCII) and .ASCIZ */ + +PRIVATE void dofcc() +{ + register char *bufptr; + char byte; + char delimiter; + register char *reglineptr; + + bufptr = databuf.fcbuf; + reglineptr = symname; + if ((delimiter = *reglineptr) != EOLCHAR) + ++reglineptr; + while (TRUE) + { + if ((byte = *reglineptr) == EOLCHAR) + { + symname = reglineptr; + error(DELEXP); + break; + } + if (byte == delimiter) + { + if ((byte = *++reglineptr) != delimiter) + break; + } + else if (byte == '\\') + { + switch (byte = *++reglineptr) + { + case '"': + case '\'': + case '\\': + case '?': + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + byte -= '0'; + if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8') + { + byte = 8 * byte + *++reglineptr - '0'; + if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8') + byte = 8 * byte + *++reglineptr - '0'; + } + break; + case 'a': + byte = 7; + break; + case 'b': + byte = 8; + break; + case 'f': + byte = 12; + break; + case 'n': + byte = 10; + break; + case 'r': + byte = 13; + break; + case 't': + byte = 9; + break; + case 'v': + byte = 11; + break; + case 'x': + byte = '0'; + while (TRUE) + { + ++reglineptr; + if (*reglineptr >= '0' && *reglineptr <= '9') + byte = 16 * byte + *reglineptr - '0'; + else if (*reglineptr >= 'F' && *reglineptr <= 'F') + byte = 16 * byte + *reglineptr - 'A'; + else if (*reglineptr >= 'a' && *reglineptr <= 'f') + byte = 16 * byte + *reglineptr - 'F'; + else + break; + } + --reglineptr; + break; + default: + symname = reglineptr; + error(UNKNOWN_ESCAPE_SEQUENCE); + break; + } + } + else if (byte < ' ' && byte >= 0) + { + symname = reglineptr; + error(CTLINS); + byte = ' '; + } + ++reglineptr; + *bufptr++ = byte; + } + lineptr = reglineptr; + getsym(); + lastexp.offset = databuf.fcbuf[0]; /* show only 1st char (if any) */ + mcount = bufptr - databuf.fcbuf; + /* won't overflow, line length limits it */ + /* XXX - but now line length is unlimited */ +} + +/* common routine for IF/IFC */ + +PRIVATE void doif(func) +pfv func; +{ + if (iflevel >= MAXIF) + error(IFOV); + else + { + ++iflevel; + --ifstak; + ifstak->elseflag = elseflag; + elseflag = FALSE; /* prepare */ + if ((ifstak->ifflag = ifflag) != FALSE) + /* else not assembling before, so not now & no ELSE's */ + { + (*func) (); + if (!(lastexp.data & UNDBIT) && lastexp.offset == 0) + /* else expression invalid or FALSE, don't change flags */ + { + ifflag = FALSE; /* not assembling */ + elseflag = TRUE;/* but ELSE will change that */ + } + } + } +} + +PUBLIC void fatalerror(errnum) +error_pt errnum; +{ + error(errnum); + skipline(); + listline(); + finishup(); +} + +/* swap position with label position, do error, put back posn */ +/* also clear label ptr */ + +PUBLIC void labelerror(errnum) +error_pt errnum; +{ + struct sym_s *oldgsymptr; + char *oldlineptr; + unsigned char oldsym; + char *oldsymname; + + oldgsymptr = gsymptr; + oldlineptr = lineptr; + oldsym = sym; + oldsymname = symname; + lineptr = linebuf; + getsym(); /* 1st symbol is label or symbol after + * missing one */ + error(errnum); + gsymptr = oldgsymptr; + lineptr = oldlineptr; + sym = oldsym; + symname = oldsymname; + label = NULL; +} + +PRIVATE struct sym_s *needlabel() +{ + register struct sym_s *symptr; + + if (sym != IDENT || + (symptr = gsymptr)->type & (MACBIT | MNREGBIT | VARBIT)) + { + error(LABEXP); + return NULL; + } + return symptr; +} + +/* .ALIGN pseudo-op */ + +PUBLIC void palign() +{ + absexpres(); + if (!((lcdata |= lastexp.data) & UNDBIT)) + { + popflags = POPLONG | POPHI | POPLO | POPLC; + if (lastexp.offset != 0 && + (lcjump = lc % lastexp.offset) != 0) + accumulate_rmb(lcjump = lastexp.offset - lcjump); + } +} + +/* .ASCIZ pseudo-op */ + +PUBLIC void pasciz() +{ + dofcc(); + databuf.fcbuf[mcount++] = 0; + fcflag = TRUE; + popflags = POPLO | POPLC; +} + +/* .BLKW pseudo-op */ + +PUBLIC void pblkw() +{ + constdata(2); +} + +/* BLOCK pseudo-op */ + +PUBLIC void pblock() +{ + if (blocklevel >= MAXBLOCK) + error(BLOCKOV); + else + { + register struct block_s *blockp; + + ++blocklevel; + blockp = blockstak; + blockstak = --blockp; + blockp->data = lcdata; + blockp->dp = dirpag; + blockp->lc = lc; + porg(); /* same as ORG apart from stacking */ + } +} + +/* .BSS pseudo-op */ + +PUBLIC void pbss() +{ + setloc(BSSLOC); +} + +/* COMM pseudo-op */ + +PUBLIC void pcomm() +{ + if (label == NULL) + labelerror(MISLAB); + else if (label->type & VARBIT) + labelerror(VARLAB); /* variable cannot be COMM'd */ + else + docomm(); +} + +/* .COMM pseudo-op */ + +PUBLIC void pcomm1() +{ + unsigned oldseg; + + if (label != NULL) + labelerror(ILLAB); + oldseg = lcdata & SEGM; + setloc(BSSLOC); + if ((label = needlabel()) != NULL && checksegrel(label)) + { + /* Like import. */ + if (label->type & (EXPBIT | LABIT)) + error(ALREADY); + else + label->data = lcdata | (FORBIT | IMPBIT | RELBIT); + getsym(); + getcomma(); + if (label->type & (EXPBIT | LABIT)) + absexpres(); /* just to check it */ + else + docomm(); + } + setloc(oldseg); +} + +/* .DATA pseudo-op */ + +PUBLIC void pdata() +{ + setloc(DATALOC); +} + +/* ELSE pseudo-op */ + +PUBLIC void pelse() +{ + if (iflevel == 0) + error(ELSEBAD); + else + { + ifflag = FALSE; /* assume ELSE disabled */ + if (elseflag) + { + ifflag = TRUE; /* ELSE enabled */ + elseflag = FALSE; + } + } +} + +/* ELSEIF pseudo-op */ + +PUBLIC void pelseif() +{ + doelseif(absexpres); +} + +/* ELSEIFC pseudo-op */ + +PUBLIC void pelsifc() +{ + doelseif(scompare); +} + +/* ENDB pseudo-op */ + +PUBLIC void pendb() +{ + if (label != NULL) + labelerror(ILLAB); + if (blocklevel == 0) + error(ENDBBAD); + else + { + register struct block_s *blockp; + + blockp = blockstak; + lcdata = blockp->data; + dirpag = blockp->dp; + accumulate_rmb(blockp->lc - lc); + lc = blockp->lc; + --blocklevel; + blockstak = blockp + 1; + } +} + +/* ENDIF pseudo-op */ + +PUBLIC void pendif() +{ + if (iflevel == 0) + error(ENDIFBAD); + else + { + ifflag = ifstak->ifflag; + elseflag = ifstak->elseflag; + ++ifstak; + --iflevel; + } +} + +/* ENTER pseudo-op */ + +PUBLIC void penter() +{ + if (!(pedata & UNDBIT)) + error(REENTER); + else + { + if (!((pedata = (pedata & ~UNDBIT) | lcdata) & UNDBIT)) + { + progent = lc; + popflags = POPLC; + } + } +} + +/* ENTRY pseudo-op */ + +PUBLIC void pentry() +{ + doentexp(ENTBIT, 0); +} + +/* EQU pseudo-op */ + +PUBLIC void pequ() +{ + register struct sym_s *labptr; + + if ((labptr = label) == NULL) + labelerror(MISLAB); + else if (labptr->type & COMMBIT) + showredefinedlabel(); /* common cannot be EQU'd */ + else if (labptr->type & VARBIT) + labelerror(VARLAB); /* variable cannot be EQU'd */ + else + doequset(LABIT); +} + +/* .EVEN pseudo-op */ + +PUBLIC void peven() +{ + popflags = POPLONG | POPHI | POPLO | POPLC; + accumulate_rmb(lcjump = lastexp.data = lc & 1); +} + +/* EXPORT pseudo-op */ + +PUBLIC void pexport() +{ + doentexp(0, 0); +} + +/* FAIL pseudo-op */ + +PUBLIC void pfail() +{ + error(FAILERR); +} + +/* FCB pseudo-op */ + +PUBLIC void pfcb() +{ + char *bufptr; + offset_t firstbyte; + + bufptr = databuf.fcbuf; + absexpres(); + firstbyte = lastexp.offset; + while (TRUE) + { + checkdatabounds(); + *bufptr++ = lastexp.offset; + ++mcount; /* won't overflow, line length limits it */ + if (sym != COMMA) + break; + symabsexpres(); + } + lastexp.offset = firstbyte; + popflags = POPLO | POPLC; + fcflag = TRUE; +} + +/* FCC pseudo-op */ + +PUBLIC void pfcc() +{ + dofcc(); + if (mcount != 0) + { + fcflag = TRUE; + popflags = POPLO | POPLC; + } +} + +/* FDB pseudo-op */ + +PUBLIC void pfdb() +{ + struct address_s *adrptr; + unsigned firstdata; + offset_t firstword; + + adrptr = databuf.fdbuf; + expres(); + firstword = lastexp.offset; + firstdata = lastexp.data; + while (TRUE) + { + *adrptr++ = lastexp; + mcount += 2; /* won't overflow, line length limits it */ + if (sym != COMMA) + break; + symexpres(); + } + lastexp.offset = firstword; + lastexp.data = firstdata; + popflags = POPHI | POPLO | POPLC; + fdflag = TRUE; +} + +#if SIZEOF_OFFSET_T > 2 + +/* FQB pseudo-op */ + +PUBLIC void pfqb() +{ + struct address_s *adrptr; + offset_t firstdata; + offset_t firstword; + + adrptr = databuf.fqbuf; + expres(); + firstword = lastexp.offset; + firstdata = lastexp.data; + while (TRUE) + { + *adrptr++ = lastexp; + mcount += 4; /* won't overflow, line length limits it */ + if (sym != COMMA) + break; + symexpres(); + } + lastexp.offset = firstword; + lastexp.data = firstdata; + popflags = POPLONG | POPHI | POPLO | POPLC; + fqflag = TRUE; +} + +#endif /* SIZEOF_OFFSET_T > 2 */ + +/* .GLOBL pseudo-op */ + +PUBLIC void pglobl() +{ + if (binaryg) + error(NOIMPORT); + doentexp(0, IMPBIT); +} + +/* IDENT pseudo-op (not complete) */ + +PUBLIC void pident() +{ + if (sym != IDENT) + error(LABEXP); + else + getsym_nolookup(); /* should save ident string */ +} + +/* IF pseudo-op */ + +PUBLIC void pif() +{ + doif(absexpres); +} + +/* IFC pseudo-op */ + +PUBLIC void pifc() +{ + doif(scompare); +} + +/* IMPORT pseudo-op */ + +PUBLIC void pimport() +{ + struct sym_s *symptr; + + if (binaryg) + error(NOIMPORT); + while (TRUE) + { + if ((symptr = needlabel()) != NULL && checksegrel(symptr)) + { + if (symptr->type & (COMMBIT | EXPBIT | LABIT)) + /* IMPORT is null if label (to be) declared */ + error(ALREADY); + else + /* get current segment from lcdata, no need to mask rest */ + symptr->data = lcdata | (FORBIT | IMPBIT | RELBIT); + } + getsym(); + if (sym != COMMA) + break; + getsym(); + } +} + +/* LCOMM pseudo-op */ + +PUBLIC void plcomm() +{ + lcommflag = TRUE; + pcomm(); +} + +/* .LCOMM pseudo-op */ + +PUBLIC void plcomm1() +{ + lcommflag = TRUE; + pcomm1(); +} + +/* .LIST pseudo-op */ + +PUBLIC void plist() +{ + bumpsem(&list); +} + +/* LOC pseudo-op */ + +PUBLIC void ploc() +{ + if (label != NULL) + labelerror(ILLAB); + absexpres(); + if (!(lastexp.data & UNDBIT)) + { + if (lastexp.offset >= NLOC) + datatoobig(); + else + setloc((unsigned) lastexp.offset); + } +} + +/* .MACLIST pseudo-op */ + +PUBLIC void pmaclist() +{ + bumpsem(&maclist); +} + +/* .MAP pseudo-op */ + +PUBLIC void pmap() +{ + absexpres(); + if (!(lastexp.data & UNDBIT)) + { + mapnum = lastexp.offset; + popflags = POPLO; + if (lastexp.offset >= 0x100) + datatoobig(); + } +} + +/* ORG pseudo-op */ + +PUBLIC void porg() +{ + if (label != NULL) + labelerror(ILLAB); + absexpres(); + if (!((lcdata = lastexp.data) & UNDBIT)) + { + accumulate_rmb(lastexp.offset - lc); + binmbuf = lc = lastexp.offset; + popflags = POPLC; + } +} + +/* RMB pseudo-op */ + +PUBLIC void prmb() +{ + constdata(1); +} + +/* .SECT pseudo-op */ + +PUBLIC void psect() +{ + if (label != NULL) + labelerror(ILLAB); + while (sym == IDENT) + { + if (!(gsymptr->type & MNREGBIT)) + error(ILL_SECTION); + else switch (gsymptr->value_reg_or_op.op.routine) + { + case BSSOP: + pbss(); + break; + case DATAOP: + pdata(); + break; + case TEXTOP: + ptext(); + break; + default: + error(ILL_SECTION); + break; + } + getsym(); + if (sym == COMMA) + getsym(); + } +} + +/* SET pseudo-op */ + +PUBLIC void pset() +{ + register struct sym_s *labptr; + + if ((labptr = label) == NULL) + labelerror(MISLAB); + else if (labptr->type & COMMBIT) + labelerror(RELAB); /* common cannot be SET'd */ + else + doequset(labptr->type & LABIT ? 0 : VARBIT); +} + +/* SETDP pseudo-op */ + +PUBLIC void psetdp() +{ + absexpres(); + if (!(lastexp.data & UNDBIT)) + { + dirpag = lastexp.offset; + popflags = POPLO; + if (lastexp.offset >= 0x100) + datatoobig(); + } +} + +/* .TEXT pseudo-op */ + +PUBLIC void ptext() +{ + setloc(TEXTLOC); +} + +/* .WARN pseudo-op */ + +PUBLIC void pwarn() +{ + bumpsem(&warn); +} + +#ifdef I80386 + +/* USE16 pseudo-op */ + +PUBLIC void puse16() +{ + defsize = 2; +} + +/* USE16 pseudo-op */ + +PUBLIC void puse32() +{ + defsize = 4; +} + +#endif + +/* show redefined label and error, and set REDBIT */ + +PRIVATE void showredefinedlabel() +{ + register struct sym_s *labptr; + + labptr = label; /* showlabel() will kill label prematurely */ + showlabel(); + if (!(labptr->type & REDBIT)) + { + labptr->type |= REDBIT; + labelerror(RELAB); + } +} + +PUBLIC void showlabel() +{ + register struct sym_s *labptr; + + labptr = label; + lastexp.data = labptr->data; + lastexp.offset = labptr->value_reg_or_op.value; + popflags = POPLONG | POPHI | POPLO; + label = NULL; /* show handled by COMM, EQU or SET */ +} + +/* set location segment */ + +PRIVATE void setloc(seg) +unsigned seg; +{ + if (pass != 0 && seg != (lcdata & SEGM)) + putobj((opcode_pt) (seg | OBJ_SET_SEG)); + { + register struct lc_s *lcp; + + lcp = lcptr; + lcp->data = lcdata; + lcp->lc = lc; + lcptr = lcp = lctab + (unsigned char) seg; + lcdata = (lcp->data & ~SEGM) | (unsigned char) seg; + binmbuf = lc = lcp->lc; + popflags = POPLC; + } +} diff --git a/as/proto.h b/as/proto.h new file mode 100644 index 0000000..e348413 --- /dev/null +++ b/as/proto.h @@ -0,0 +1,218 @@ +/* extern functions */ + +#if __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + +/* as.c */ +int main P((int argc, char **argv)); +void as_abort P((char *message)); +void finishup P((void)); +void initp1p2 P((void)); + +/* assemble.c */ +void assemble P((void)); + +/* error.c */ +char *build_error_message P((error_pt errnum, char *buf)); + +/* express.c */ +void absexpres P((void)); +void chkabs P((void)); +void nonimpexpres P((void)); +void showrelbad P((void)); +void symabsexpres P((void)); +void symexpres P((void)); +void expres P((void)); +void factor P((void)); +void scompare P((void)); + +/* genbin.c */ +void binheader P((void)); +void bintrailer P((void)); +void genbin P((void)); +void initbin P((void)); +void putbin P((int ch)); + +/* genlist.c */ +char *build_2hex_number P((unsigned num, char *where)); +char *build_number P((unsigned num, unsigned width, char *where)); +void error P((error_pt errnum)); +void listline P((void)); +void writec P((int ch)); +void writenl P((void)); +void writeoff P((offset_t offset)); +void writes P((char *s)); +void writesn P((char *s)); +void writew P((unsigned word)); + +/* genobj.c */ +void accumulate_rmb P((offset_t offset)); +void flushobj P((void)); +void genobj P((void)); +void initobj P((void)); +void objheader P((void)); +void objtrailer P((void)); +void putabs P((opcode_pt ch)); +void putobj P((opcode_pt ch)); + +/* gensym.c */ +void gensym P((void)); + +/* macro.c */ +void entermac P((struct sym_s *symptr)); +void pmacro P((void)); + +/* mops.c */ +#ifdef I80386 +void mbcc P((void)); +void mbswap P((void)); +void mcall P((void)); +void mcalli P((void)); +void mdivmul P((void)); +void menter P((void)); +void mEwGw P((void)); +void mExGx P((void)); +void mf_inher P((void)); +void mf_m P((void)); +void mf_m2 P((void)); +void mf_m2_ax P((void)); +void mf_m2_m4 P((void)); +void mf_m2_m4_m8 P((void)); +void mf_m4_m8_optst P((void)); +void mf_m4_m8_st P((void)); +void mf_m4_m8_stst P((void)); +void mf_m4_m8_m10_st P((void)); +void mf_m10 P((void)); +void mf_optst P((void)); +void mf_st P((void)); +void mf_stst P((void)); +void mf_w_inher P((void)); +void mf_w_m P((void)); +void mf_w_m2 P((void)); +void mf_w_m2_ax P((void)); +void mgroup1 P((void)); +void mgroup2 P((void)); +void mgroup6 P((void)); +void mgroup7 P((void)); +void mgroup8 P((void)); +void mGvEv P((void)); +void mGvMa P((void)); +void mGvMp P((void)); +void mimul P((void)); +void min P((void)); +void mincdec P((void)); +void minher P((void)); +void minher16 P((void)); +void minher32 P((void)); +void minhera P((void)); +void mint P((void)); +void mjcc P((void)); +void mjcxz P((void)); +void mlea P((void)); +void mmov P((void)); +void mmovx P((void)); +void mnegnot P((void)); +void mout P((void)); +void mpushpop P((void)); +void mret P((void)); +void mseg P((void)); +void msetcc P((void)); +void mshdouble P((void)); +void mtest P((void)); +void mxchg P((void)); +#endif /* I80386 */ + +#ifdef MC6809 +void mall P((void)); +void malter P((void)); +void mimmed P((void)); +void mindex P((void)); +void minher P((void)); +void mlong P((void)); +void msstak P((void)); +void mswap P((void)); +void mustak P((void)); +#endif /* MC6809 */ + +void getcomma P((void)); +void mshort P((void)); + +/* pops.c */ +bool_pt checksegrel P((struct sym_s *symptr)); +void checkdatabounds P((void)); +void datatoobig P((void)); +void fatalerror P((error_pt errnum)); +void labelerror P((error_pt errnum)); +void palign P((void)); +void pasciz P((void)); +void pblkw P((void)); +void pblock P((void)); +void pbss P((void)); +void pcomm P((void)); +void pcomm1 P((void)); +void pdata P((void)); +void pelse P((void)); +void pelseif P((void)); +void pelsifc P((void)); +void pendb P((void)); +void pendif P((void)); +void penter P((void)); +void pentry P((void)); +void pequ P((void)); +void peven P((void)); +void pexport P((void)); +void pfail P((void)); +void pfcb P((void)); +void pfcc P((void)); +void pfdb P((void)); +void pfqb P((void)); +void pglobl P((void)); +void pident P((void)); +void pif P((void)); +void pifc P((void)); +void pimport P((void)); +void plcomm P((void)); +void plcomm1 P((void)); +void plist P((void)); +void ploc P((void)); +void pmaclist P((void)); +void pmap P((void)); +void porg P((void)); +void prmb P((void)); +void psect P((void)); +void pset P((void)); +void psetdp P((void)); +void ptext P((void)); +void puse16 P((void)); +void puse32 P((void)); +void pwarn P((void)); +void showlabel P((void)); + +/* readsrc.c */ +void initsource P((void)); +fd_t open_input P((char *name)); +void pget P((void)); +void pproceof P((void)); +void readline P((void)); +void skipline P((void)); + +/* scan.c */ +void context_hexconst P((void)); +void getsym P((void)); +void getsym_nolookup P((void)); +void initscan P((void)); + +/* table.c */ +void inst_keywords P((void)); +struct sym_s *lookup P((void)); +void statistics P((void)); + +/* type.c */ +void u2c2 P((char *buf, u16_pt offset)); +void u4c4 P((char *buf, u32_T offset)); +void u2cn P((char *buf, u16_pt offset, unsigned count)); +void u4cn P((char *buf, u32_T offset, unsigned count)); +bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian)); diff --git a/as/readsrc.c b/as/readsrc.c new file mode 100644 index 0000000..39bd063 --- /dev/null +++ b/as/readsrc.c @@ -0,0 +1,341 @@ +#define MAXLINE 256 /* when this is made bigger, fix pfcc not + * to store the string length in a byte- + * sized variable */ + +/* readsrc.c - read source files for assembler */ + +#include "const.h" +#include "type.h" +#include "flag.h" +#include "file.h" +#include "globvar.h" +#include "macro.h" +#include "scan.h" +#undef EXTERN +#define EXTERN +#include "source.h" + +#ifdef POSIX_HEADERS_MISSING +#define O_RDONLY 0 +typedef long off_t; +int close P((int fd)); +off_t lseek P((int fd, off_t offset, int whence)); +int open P((const char *path, int oflag, ...)); +int read P((int fd, void *buf, unsigned nbytes)); +#else +#undef NULL +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#endif + +struct fcbstruct /* file control block structure */ +{ + fd_t fd; /* file descriptor */ + char *lineptr; /* current spot in line */ + char *buf; /* start of buffer (after partial line) */ + char *first; /* start of partial line before buf */ + char *limit; /* end of used part of input buffer */ + int blocksize; /* chars from last read and partial line flag */ + struct fbufstruct *includer;/* buffer of file which included current one */ +}; + +struct fbufstruct /* file buffer structure */ +{ + struct fcbstruct fcb; /* status after opening an include sub-file */ + char fpartline[MAXLINE + 1];/* buffer for partial line */ + char fbuf[INBUFSIZE + 1]; /* buffer to read into */ + char fname[1]; /* file name (variable length), 1 for null */ +}; + +struct get_s /* to record included files */ +{ + fd_t fd; + unsigned line; + off_t position; +}; + +PRIVATE char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */ + +PRIVATE struct get_s hid_getstak[MAXGET]; /* GET stack */ +PRIVATE struct get_s *getstak; /* ptr */ + +PRIVATE struct fcbstruct input; /* current input file control block */ + /* input.lineptr is not kept up to date */ + /* input.fd depends on zero init */ +PRIVATE struct fbufstruct xyz; +PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */ + /* its fcb only to date in includes */ + +PRIVATE char hid_linebuf[LINLEN]; /* line buffer */ +PRIVATE char *maclinebuf; +PRIVATE char *maclineptr; + +FORWARD void clearsource P((void)); +FORWARD void line_too_long P((void)); + +PRIVATE void clearsource() +{ + input.includer = inputbuf; + inputbuf = &xyz; + input.first = input.limit = input.buf = inputbuf->fbuf; + *(lineptr = linebuf = input.first - 1) = EOLCHAR; + input.blocksize = 0; +} + +PRIVATE void line_too_long() +{ + symname = linebuf + (LINLEN - 1); /* spot for the error */ + error(LINLONG); /* so error is shown in column LINLEN - 1 */ +} + +/* initialise private variables */ + +PUBLIC void initsource() +{ + filnamptr = hid_filnambuf; + getstak = hid_getstak + MAXGET; + clearsource(); /* sentinel to invoke blank skipping */ +} + +PUBLIC fd_t open_input(name) +char *name; +{ + fd_t fd; + + if ((unsigned) (fd = open(name, O_RDONLY)) > 255) + as_abort("error opening input file"); + clearsource(); + return fd; +} + +/* + handle GET pseudo_op + stack state of current file, open new file and reset global state vars + file must be seekable for the buffer discard/restore method to work +*/ + +PUBLIC void pget() +{ +#if OLD + if (infiln >= MAXGET) + error(GETOV); + else + { + skipline(); + listline(); + if (infiln != 0) + { + --getstak; + getstak->fd = infil; + getstak->line = linum; + getstak->position = lseek(infil, 0L, 1) - (inbufend - inbufptr); + ++infiln; + linum = 0; + infil = open_input(lineptr - 1); + } + } +#else + as_abort("get/include pseudo-op not implemented"); +#endif +} + +/* process end of file */ +/* close file, unstack old file if current one is included */ +/* otherwise switch pass 0 to pass 1 or exit on pass 2 */ +/* end of file may be from phyical end of file or an END statement */ + +PUBLIC void pproceof() +{ + if (infiln != 0) + close(infil); + if (lineptr == linebuf) + list.current = FALSE; /* don't list line after last unless error */ + if (infiln == infil0) + /* all conditionals must be closed before end of main file (not GETs) */ + { + if (blocklevel != 0) + error(EOFBLOCK); + if (iflevel != 0) + error(EOFIF); + if (lcdata & UNDBIT) + error(EOFLC); + lcptr->data = lcdata; + lcptr->lc = lc; + } + /* macros must be closed before end of all files */ + if (macload) + error(EOFMAC); + listline(); /* last line or line after last if error */ + if (infiln != infil0) + { + infil = getstak->fd; + linum = getstak->line; + if (--infiln != 0) + lseek(infil, getstak->position, 0); + ++getstak; + } + else if (!pass) + { + pass = TRUE; + objheader(); /* while pass 1 data all valid */ + binmbuf = 0; /* reset zero variables */ + maclevel = iflevel = blocklevel = + totwarn = toterr = linum = macnum = 0; + initp1p2(); /* reset other varaiables */ + binaryc = binaryg; +#ifdef I80386 + defsize = idefsize; +#endif + list.current = list.global; + maclist.current = maclist.global; + + warn.current = TRUE; + if (warn.semaphore < 0) + warn.current = FALSE; + if (infiln != 0) + infil = open_input(filnamptr); + binheader(); + } + else + finishup(); +} + +/* + read 1 line of source. + Source line ends with '\n', line returned is null terminated without '\n'. + Control characters other than blank, tab and newline are discarded. + Long lines (length > LINLEN) are truncated, and an error is generated. + On EOF, calls pproceof(), and gets next line unless loading a macro. + This is where macro lines are recursively expanded. +*/ + +PUBLIC void readline() +{ + listpre = FALSE; /* not listed yet */ + if (maclevel != 0) + { + register char *bufptr; /* hold *bufptr in a reg char variable */ + register char *reglineptr; /* if possible (not done here) */ + char *oldbufptr; + struct schain_s *parameters; + char paramnum; + unsigned char remaining; /* space remaining in line + 2 */ + /* value 0 not used except for temp predec */ + /* value 1 means error already gen */ + /* values 1 and 2 mean no space */ + + for (; maclevel != 0; + macpar = macstak->parameters, ++macstak, --maclevel) + if (*(bufptr = macstak->text) != ETB) + /* nonempty macro, process it and return without continuing the for loop */ + { + if (!macflag) + { + maclinebuf = linebuf; + maclineptr = lineptr; + macflag = TRUE; + } + remaining = LINLEN + 2; + lineptr = linebuf = reglineptr = hid_linebuf; + while (*bufptr++ != EOLCHAR) + { + if (bufptr[-1] == MACROCHAR && *bufptr >= '0' && *bufptr <= '9') + { + parameters = macstak->parameters; + for (paramnum = *bufptr++; paramnum-- != '0';) + if ((parameters = parameters->next) == NULL) + break; + if (parameters != NULL) + { + for (oldbufptr = bufptr, bufptr = parameters->string; + *bufptr++ != 0;) + { + if (--remaining <= 1) + { + if (remaining != 0) + line_too_long(); + remaining = 1; + break; /* forget rest, param on 1 line */ + } + *reglineptr++ = bufptr[-1]; + } + bufptr = oldbufptr; + } + } + else + { + if (--remaining <= 1) + { + if (remaining != 0) + line_too_long(); + remaining = 1; + } + else + *reglineptr++ = bufptr[-1]; + } + } + macstak->text = bufptr; + *reglineptr = EOLCHAR; + return; + } + } + if (macflag) + { + linebuf = maclinebuf; + lineptr = maclineptr; + macflag = FALSE; + } +again: + ++linum; + ++lineptr; /* if eof, this is input.limit + 1 */ + if (input.blocksize != 0) /* and this routine just resets eof */ + { + if (lineptr < input.limit) /* move back partial line */ + { + register char *col; + + col = input.buf; + while ((*--col = *--input.limit) != EOLCHAR) + ; + input.first = col + 1; + ++input.limit; + input.blocksize = 0; + } + else /* may be non-terminated line, don't stop */ + lineptr = input.limit; + } + if (lineptr == input.limit) + { + lineptr = input.first; + input.blocksize = read(infil, input.buf, INBUFSIZE); + if (input.blocksize < 0) + as_abort("error reading input"); + if (input.blocksize == 0) + { + clearsource(); + pproceof(); + if (macload) + { + symname = lineptr; + return; /* macro not allowed across eof */ + } + goto again; + } + input.first = input.buf; + *(input.limit = input.buf + input.blocksize) = EOLCHAR; + } + linebuf = lineptr; + if (lineptr >= input.limit) + *(lineptr = input.limit = input.buf) = EOLCHAR; +} + +PUBLIC void skipline() +{ + register char *reglineptr; + + reglineptr = lineptr - 1; + while (*reglineptr != EOLCHAR) + ++reglineptr; + lineptr = reglineptr; +} diff --git a/as/scan.c b/as/scan.c new file mode 100644 index 0000000..56c6bf3 --- /dev/null +++ b/as/scan.c @@ -0,0 +1,247 @@ +/* scan.c - lexical analyser for assembler */ + +#include "const.h" +#include "type.h" +#include "globvar.h" +#undef EXTERN +#define EXTERN +#include "scan.h" + +PRIVATE int numbase; /* base for number */ + +PRIVATE char symofchar[256] = /* table to convert chars to their symbols */ +{ + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, EOLSYM, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + + WHITESPACE, EOLSYM, STRINGCONST, IMMEDIATE, /* !"# */ + HEXCONST, BINCONST, ANDOP, CHARCONST, /* $%&' */ + LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */ + COMMA, SUBOP, IDENT, SLASH, /* ,-./ */ + + INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */ + INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */ + INTCONST, INTCONST, COLON, EOLSYM, /* 89:; */ + LESSTHAN, EQOP, GREATERTHAN, MACROARG, /* <=>? */ + + INDIRECT, IDENT, IDENT, IDENT, /* @ABC */ + IDENT, IDENT, IDENT, IDENT, /* DEFG */ + IDENT, IDENT, IDENT, IDENT, /* HIJK */ + IDENT, IDENT, IDENT, IDENT, /* LMNO */ + IDENT, IDENT, IDENT, IDENT, /* PQRS */ + IDENT, IDENT, IDENT, IDENT, /* TUVW */ + IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */ + OTHERSYM, RBRACKET, OTHERSYM, IDENT, /* \]^_ */ + + OTHERSYM, IDENT, IDENT, IDENT, /* `abc */ + IDENT, IDENT, IDENT, IDENT, /* defg */ + IDENT, IDENT, IDENT, IDENT, /* hijk */ + IDENT, IDENT, IDENT, IDENT, /* lmno */ + IDENT, IDENT, IDENT, IDENT, /* pqrs */ + IDENT, IDENT, IDENT, IDENT, /* tuvw */ + IDENT, IDENT, IDENT, OTHERSYM, /* xyz{ */ + OROP, OTHERSYM, NOTOP, OTHERSYM, /* |}~ */ + + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE +}; + +FORWARD void intconst P((void)); + +PUBLIC void context_hexconst() +{ + numbase = 16; + intconst(); +} + +PUBLIC void getsym() +{ + register char *reglineptr; + + reglineptr = lineptr; +advance: + symname = reglineptr; + switch (sym = symofchar[(unsigned char) *reglineptr++]) + { + case WHITESPACE: + goto advance; + case ADDOP: + if (*reglineptr == '+') + { + sym = POSTINCOP; + ++reglineptr; + } + break; + case BINCONST: + numbase = 2; + lineptr = reglineptr; + intconst(); + return; + case CHARCONST: + if ((number = *reglineptr) < ' ') + number = ' '; + if (*reglineptr != EOL) + ++reglineptr; + sym = INTCONST; + break; + case GREATERTHAN: /* context-sensitive */ + if (*reglineptr == '>') + { + sym = SROP; + ++reglineptr; + } + break; + case HEXCONST: + numbase = 16; + lineptr = reglineptr; + intconst(); + return; + case IDENT: + /* walk to end of identifier - magic INTCONST is max of INT, IDENT */ + while (symofchar[(unsigned char) *reglineptr] <= INTCONST) + ++reglineptr; + lineptr = reglineptr; + gsymptr = lookup(); + return; + case INTCONST: + if (*(reglineptr - 1) == '0') + { + if (*reglineptr != 'x' && *reglineptr != 'X') + numbase = 8; + else + { + numbase = 16; + ++reglineptr; + } + } + else + { + --reglineptr; + numbase = 10; + } + lineptr = reglineptr; + intconst(); + return; + case LESSTHAN: /* context-sensitive */ + if (*reglineptr == '<') + { + sym = SLOP; + ++reglineptr; + } + break; + case SUBOP: + if (*reglineptr == '-') + { + sym = PREDECOP; + ++reglineptr; + } + break; + } + lineptr = reglineptr; + return; +} + +PUBLIC void getsym_nolookup() +{ + bool_t old_ifflag; + + old_ifflag = ifflag; + ifflag = FALSE; + getsym(); + ifflag = old_ifflag; +} + +PRIVATE void intconst() +{ + register char *reglineptr; + + number = 0; + reglineptr = lineptr; + for (; *reglineptr >= '0'; ++reglineptr) + { + if (*reglineptr > '9') + { + if (numbase != 16) + break; + if (*reglineptr >= 'a' && *reglineptr <= 'f') + { + if (number != 0) + number = numbase * number + (*reglineptr - 'a' + 10); + else + number = *reglineptr - 'a' + 10; + } + else if (*reglineptr >= 'A' && *reglineptr <= 'F') + { + if (number != 0) + number = numbase * number + (*reglineptr - 'A' + 10); + else + number = *reglineptr - 'A' + 10; + } + else + break; + } + else if (number != 0) + number = numbase * number + (*reglineptr - '0'); + else + number = *reglineptr - '0'; + } + if (*reglineptr == 'L' || *reglineptr == 'l') + ++reglineptr; + sym = INTCONST; + lineptr = reglineptr; +} + +PUBLIC void initscan() +{ + if (asld_compatible) + { + lindirect = LPAREN; + rindexp = RPEXP; + rindirect = RPAREN; + } + else + { + lindirect = LBRACKET; + rindexp = RBEXP; + rindirect = RBRACKET; + } +} diff --git a/as/scan.h b/as/scan.h new file mode 100644 index 0000000..22def98 --- /dev/null +++ b/as/scan.h @@ -0,0 +1,12 @@ +/* scan.h - global variables for scanner for assembler */ + +#define EOLCHAR '\n' + +EXTERN struct sym_s *gsymptr; /* global symbol ptr */ +EXTERN char lindirect; /* left symbol for indirect addressing */ +EXTERN char *lineptr; /* current line position */ +EXTERN offset_t number; /* constant number */ +EXTERN int rindexp; /* error code for missing rindirect */ +EXTERN char rindirect; /* right symbol for indirect addressing */ +EXTERN char sym; /* current symbol */ +EXTERN char *symname; /* current symbol name */ diff --git a/as/source.h b/as/source.h new file mode 100644 index 0000000..0181e54 --- /dev/null +++ b/as/source.h @@ -0,0 +1,4 @@ +/* source.h - global variables for source handlers for assembler */ + +EXTERN unsigned linum; /* line # */ +EXTERN bool_t listpre; /* flag to show line has already been listed */ diff --git a/as/table.c b/as/table.c new file mode 100644 index 0000000..66d9332 --- /dev/null +++ b/as/table.c @@ -0,0 +1,945 @@ +/* table.c - keyword tables and symbol table lookup for assembler */ + +#include "const.h" +#include "type.h" +#include "globvar.h" +#include "opcode.h" +#include "scan.h" + +#ifdef STDC_HEADERS_MISSING +int memcmp P((const void *s1, const void *s2, unsigned n)); +#else +#undef NULL +#include <string.h> +#endif + +#define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */ + +#ifdef DEBUG +unsigned nhash; +unsigned nlookup; +unsigned nsym; +unsigned nx[30]; +FORWARD void printchain P((void)); +#endif + +/* --- start of keywords --- */ + +/* registers */ +/* the register code (internal to assembler) is given in 1 byte */ +/* the "opcode" field is not used */ + +PUBLIC char regs[] = +{ +#ifdef I80386 + 2, 'B', 'P', BPREG, 0, + 2, 'B', 'X', BXREG, 0, + 2, 'D', 'I', DIREG, 0, + 2, 'S', 'I', SIREG, 0, + + 3, 'E', 'A', 'X', EAXREG, 0, + 3, 'E', 'B', 'P', EBPREG, 0, + 3, 'E', 'B', 'X', EBXREG, 0, + 3, 'E', 'C', 'X', ECXREG, 0, + 3, 'E', 'D', 'I', EDIREG, 0, + 3, 'E', 'D', 'X', EDXREG, 0, + 3, 'E', 'S', 'I', ESIREG, 0, + 3, 'E', 'S', 'P', ESPREG, 0, + + 2, 'A', 'X', AXREG, 0, + 2, 'C', 'X', CXREG, 0, + 2, 'D', 'X', DXREG, 0, + 2, 'S', 'P', SPREG, 0, + + 2, 'A', 'H', AHREG, 0, + 2, 'A', 'L', ALREG, 0, + 2, 'B', 'H', BHREG, 0, + 2, 'B', 'L', BLREG, 0, + 2, 'C', 'H', CHREG, 0, + 2, 'C', 'L', CLREG, 0, + 2, 'D', 'H', DHREG, 0, + 2, 'D', 'L', DLREG, 0, + + 2, 'C', 'S', CSREG, 0, + 2, 'D', 'S', DSREG, 0, + 2, 'E', 'S', ESREG, 0, + 2, 'F', 'S', FSREG, 0, + 2, 'G', 'S', GSREG, 0, + 2, 'S', 'S', SSREG, 0, + + 3, 'C', 'R', '0', CR0REG, 0, + 3, 'C', 'R', '2', CR2REG, 0, + 3, 'C', 'R', '3', CR3REG, 0, + 3, 'D', 'R', '0', DR0REG, 0, + 3, 'D', 'R', '1', DR1REG, 0, + 3, 'D', 'R', '2', DR2REG, 0, + 3, 'D', 'R', '3', DR3REG, 0, + 3, 'D', 'R', '6', DR6REG, 0, + 3, 'D', 'R', '7', DR7REG, 0, + 3, 'T', 'R', '3', TR3REG, 0, + 3, 'T', 'R', '4', TR4REG, 0, + 3, 'T', 'R', '5', TR5REG, 0, + 3, 'T', 'R', '6', TR6REG, 0, + 3, 'T', 'R', '7', TR7REG, 0, + + 2, 'S', 'T', ST0REG, 0, +#endif /* I80386 */ + +#ifdef MC6809 + 1, 'A', AREG, 0, + 1, 'B', BREG, 0, + 2, 'C', 'C', CCREG, 0, + 1, 'D', DREG, 0, + 2, 'D', 'P', DPREG, 0, + 2, 'P', 'C', PCREG, 0, + 3, 'P', 'C', 'R', PCREG, 0, + 1, 'S', SREG, 0, + 1, 'U', UREG, 0, + 1, 'X', XREG, 0, + 1, 'Y', YREG, 0, +#endif + 0 /* end of register list */ +}; + +#ifdef I80386 + +/* type sizes */ +/* the "opcode" field gives the type size */ + +PUBLIC char typesizes[] = +{ + 4, 'B', 'Y', 'T', 'E', BYTEOP, 1, + 5, 'D', 'W', 'O', 'R', 'D', DWORDOP, 4, + 5, 'F', 'W', 'O', 'R', 'D', FWORDOP, 6, + 3, 'F', 'A', 'R', FAROP, 0, + 3, 'P', 'T', 'R', PTROP, 0, + 5, 'P', 'W', 'O', 'R', 'D', PWORDOP, 6, + 5, 'Q', 'W', 'O', 'R', 'D', QWORDOP, 8, + 5, 'T', 'B', 'Y', 'T', 'E', TBYTEOP, 10, + 4, 'W', 'O', 'R', 'D', WORDOP, 2, + 0 /* end of typesize list */ +}; + +#endif + +/* ops */ +/* the routine number is given in 1 byte */ +/* the opcode is given in 1 byte (it is not used for pseudo-ops) */ + +PUBLIC char ops[] = +{ + /* pseudo-ops. The "opcode" field is unused and padded with a null byte */ + /* conditionals - must be first */ + 4, 'E', 'L', 'S', 'E', ELSEOP, 0, + 6, 'E', 'L', 'S', 'E', 'I', 'F', ELSEIFOP, 0, + 7, 'E', 'L', 'S', 'E', 'I', 'F', 'C', ELSEIFCOP, 0, + 5, 'E', 'N', 'D', 'I', 'F', ENDIFOP, 0, + 2, 'I', 'F', IFOP, 0, + 3, 'I', 'F', 'C', IFCOP, 0, + + /* unconditionals */ + 6, '.', 'A', 'L', 'I', 'G', 'N', ALIGNOP, 0, + 6, '.', 'A', 'S', 'C', 'I', 'I', FCCOP, 0, + 6, '.', 'A', 'S', 'C', 'I', 'Z', ASCIZOP, 0, + 5, '.', 'B', 'L', 'K', 'B', RMBOP, 0, + 5, '.', 'B', 'L', 'K', 'W', BLKWOP, 0, + 5, 'B', 'L', 'O', 'C', 'K', BLOCKOP, 0, + 4, '.', 'B', 'S', 'S', BSSOP, 0, + 5, '.', 'B', 'Y', 'T', 'E', FCBOP, 0, + 4, 'C', 'O', 'M', 'M', COMMOP, 0, + 5, '.', 'C', 'O', 'M', 'M', COMMOP1, 0, + 5, '.', 'D', 'A', 'T', 'A', DATAOP, 0, + 6, '.', 'D', 'A', 'T', 'A', '1', FCBOP, 0, + 6, '.', 'D', 'A', 'T', 'A', '2', FDBOP, 0, + 6, '.', 'D', 'A', 'T', 'A', '4', FQBOP, 0, + 2, 'D', 'B', FCBOP, 0, + 2, 'D', 'D', FQBOP, 0, + 7, '.', 'D', 'E', 'F', 'I', 'N', 'E', EXPORTOP, 0, + 2, 'D', 'W', FDBOP, 0, + 3, 'E', 'N', 'D', PROCEOFOP, 0, + 4, 'E', 'N', 'D', 'B', ENDBOP, 0, + 5, 'E', 'N', 'T', 'E', 'R', ENTEROP, 0, + 5, 'E', 'N', 'T', 'R', 'Y', ENTRYOP, 0, + 3, 'E', 'Q', 'U', EQUOP, 0, + 5, '.', 'E', 'V', 'E', 'N', EVENOP, 0, + 6, 'E', 'X', 'P', 'O', 'R', 'T', EXPORTOP, 0, + 6, 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0, + 7, '.', 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0, + 5, 'E', 'X', 'T', 'R', 'N', IMPORTOP, 0, + 4, 'F', 'A', 'I', 'L', FAILOP, 0, + 5, '.', 'F', 'A', 'I', 'L', FAILOP, 0, + 3, 'F', 'C', 'B', FCBOP, 0, + 3, 'F', 'C', 'C', FCCOP, 0, + 3, 'F', 'D', 'B', FDBOP, 0, + 3, 'G', 'E', 'T', GETOP, 0, + 6, '.', 'G', 'L', 'O', 'B', 'L', GLOBLOP, 0, + 5, 'I', 'D', 'E', 'N', 'T', IDENTOP, 0, + 6, 'I', 'M', 'P', 'O', 'R', 'T', IMPORTOP, 0, + 7, 'I', 'N', 'C', 'L', 'U', 'D', 'E', GETOP, 0, + 5, 'L', 'C', 'O', 'M', 'M', LCOMMOP, 0, + 6, '.', 'L', 'C', 'O', 'M', 'M', LCOMMOP1, 0, + 5, '.', 'L', 'I', 'S', 'T', LISTOP, 0, + 3, 'L', 'O', 'C', LOCOP, 0, + 5, '.', 'L', 'O', 'N', 'G', FQBOP, 0, + 8, '.', 'M', 'A', 'C', 'L', 'I', 'S', 'T', MACLISTOP, 0, + 5, 'M', 'A', 'C', 'R', 'O', MACROOP, 0, + 4, '.', 'M', 'A', 'P', MAPOP, 0, + 3, 'O', 'R', 'G', ORGOP, 0, + 4, '.', 'O', 'R', 'G', ORGOP, 0, + 6, 'P', 'U', 'B', 'L', 'I', 'C', EXPORTOP, 0, + 3, 'R', 'M', 'B', RMBOP, 0, + 4, '.', 'R', 'O', 'M', DATAOP, 0, + 5, '.', 'S', 'E', 'C', 'T', SECTOP, 0, + 3, 'S', 'E', 'T', SETOP, 0, + 5, 'S', 'E', 'T', 'D', 'P', SETDPOP, 0, + 6, '.', 'S', 'H', 'O', 'R', 'T', FDBOP, 0, + 6, '.', 'S', 'P', 'A', 'C', 'E', RMBOP, 0, + 5, '.', 'T', 'E', 'X', 'T', TEXTOP, 0, + 5, 'U', 'S', 'E', '1', '6', USE16OP, 0, + 5, 'U', 'S', 'E', '3', '2', USE32OP, 0, + 5, '.', 'W', 'A', 'R', 'N', WARNOP, 0, + 5, '.', 'W', 'O', 'R', 'D', FDBOP, 0, + 6, '.', 'Z', 'E', 'R', 'O', 'W', BLKWOP, 0, + + /* hardware ops. The opcode field is now used */ +#ifdef I80386 + 3, 'A', 'A', 'A', INHER, 0x37, + 3, 'A', 'A', 'D', INHER_A, 0xD5, + 3, 'A', 'A', 'M', INHER_A, 0xD4, + 3, 'A', 'A', 'S', INHER, 0x3F, + 3, 'A', 'D', 'C', GROUP1, 0x10, + 3, 'A', 'D', 'D', GROUP1, 0x00, + 3, 'A', 'N', 'D', GROUP1, 0x20, + 4, 'A', 'R', 'P', 'L', EwGw, 0x63, + 3, 'B', 'C', 'C', BCC, 0x73, + 3, 'B', 'C', 'S', BCC, 0x72, + 3, 'B', 'E', 'Q', BCC, 0x74, + 3, 'B', 'G', 'E', BCC, 0x7D, + 3, 'B', 'G', 'T', BCC, 0x7F, + 3, 'B', 'H', 'I', BCC, 0x77, + 4, 'B', 'H', 'I', 'S', BCC, 0x73, + 3, 'B', 'L', 'E', BCC, 0x7E, + 3, 'B', 'L', 'O', BCC, 0x72, + 4, 'B', 'L', 'O', 'S', BCC, 0x76, + 3, 'B', 'L', 'T', BCC, 0x7C, + 3, 'B', 'M', 'I', BCC, 0x78, + 3, 'B', 'N', 'E', BCC, 0x75, + 5, 'B', 'O', 'U', 'N', 'D', GvMa, 0x62, + 3, 'B', 'P', 'C', BCC, 0x7B, + 3, 'B', 'P', 'L', BCC, 0x79, + 3, 'B', 'P', 'S', BCC, 0x7A, + 2, 'B', 'R', CALL, JMP_OPCODE, + 3, 'B', 'V', 'C', BCC, 0x71, + 3, 'B', 'V', 'S', BCC, 0x70, + 4, 'C', 'A', 'L', 'L', CALL, JSR_OPCODE, + 5, 'C', 'A', 'L', 'L', 'F', CALLI, 0x9A, + 5, 'C', 'A', 'L', 'L', 'I', CALLI, 0x9A, + 3, 'C', 'B', 'W', INHER16, 0x98, + 3, 'C', 'L', 'C', INHER, 0xF8, + 3, 'C', 'L', 'D', INHER, 0xFC, + 3, 'C', 'L', 'I', INHER, 0xFA, + 3, 'C', 'M', 'C', INHER, 0xF5, + 3, 'C', 'M', 'P', GROUP1, CMP_OPCODE_BASE, + 4, 'C', 'M', 'P', 'S', INHER, CMPSW_OPCODE, + 5, 'C', 'M', 'P', 'S', 'B', INHER, CMPSB_OPCODE, + 5, 'C', 'M', 'P', 'S', 'D', INHER32, CMPSW_OPCODE, + 5, 'C', 'M', 'P', 'S', 'W', INHER16, CMPSW_OPCODE, + 4, 'C', 'M', 'P', 'W', INHER16, CMPSW_OPCODE, + 4, 'C', 'S', 'E', 'G', INHER, 0x2E, + 3, 'C', 'W', 'D', INHER16, 0x99, + 4, 'C', 'W', 'D', 'E', INHER32, 0x98, + 3, 'C', 'D', 'Q', INHER32, 0x99, + 3, 'D', 'A', 'A', INHER, 0x27, + 3, 'D', 'A', 'S', INHER, 0x2F, + 4, 'D', 'S', 'E', 'G', INHER, 0x3E, + 3, 'D', 'E', 'C', INCDEC, 0x08, + 3, 'D', 'I', 'V', DIVMUL, 0x30, + 5, 'E', 'N', 'T', 'E', 'R', ENTER, 0xC8, + 4, 'E', 'S', 'E', 'G', INHER, 0x26, + 4, 'F', 'S', 'E', 'G', INHER, 0x64, + 4, 'G', 'S', 'E', 'G', INHER, 0x65, + 3, 'H', 'L', 'T', INHER, 0xF4, + 4, 'I', 'D', 'I', 'V', DIVMUL, 0x38, + 4, 'I', 'M', 'U', 'L', IMUL, 0x28, + 2, 'I', 'N', IN, 0xEC, + 3, 'I', 'N', 'C', INCDEC, 0x00, + 3, 'I', 'N', 'S', INHER, 0x6D, + 4, 'I', 'N', 'S', 'B', INHER, 0x6C, + 4, 'I', 'N', 'S', 'D', INHER32, 0x6D, + 4, 'I', 'N', 'S', 'W', INHER16, 0x6D, + 3, 'I', 'N', 'T', INT, 0xCD, + 4, 'I', 'N', 'T', 'O', INHER, 0xCE, + 3, 'I', 'N', 'W', IN, 0xED, + 4, 'I', 'R', 'E', 'T', INHER16, 0xCF, + 5, 'I', 'R', 'E', 'T', 'D', INHER32, 0xCF, + 1, 'J', CALL, JMP_SHORT_OPCODE, + 2, 'J', 'A', JCC, 0x77, + 3, 'J', 'A', 'E', JCC, 0x73, + 2, 'J', 'B', JCC, 0x72, + 3, 'J', 'B', 'E', JCC, 0x76, + 2, 'J', 'C', JCC, 0x72, + 4, 'J', 'C', 'X', 'E', JCXZ, 0x2, + 4, 'J', 'C', 'X', 'Z', JCXZ, 0x2, + 5, 'J', 'E', 'C', 'X', 'E', JCXZ, 0x4, + 5, 'J', 'E', 'C', 'X', 'Z', JCXZ, 0x4, + 2, 'J', 'E', JCC, 0x74, + 2, 'J', 'G', JCC, 0x7F, + 3, 'J', 'G', 'E', JCC, 0x7D, + 2, 'J', 'L', JCC, 0x7C, + 3, 'J', 'L', 'E', JCC, 0x7E, + 3, 'J', 'M', 'P', CALL, JMP_SHORT_OPCODE, + 4, 'J', 'M', 'P', 'F', CALLI, 0xEA, + 4, 'J', 'M', 'P', 'I', CALLI, 0xEA, + 3, 'J', 'N', 'A', JCC, 0x76, + 4, 'J', 'N', 'A', 'E', JCC, 0x72, + 3, 'J', 'N', 'B', JCC, 0x73, + 4, 'J', 'N', 'B', 'E', JCC, 0x77, + 3, 'J', 'N', 'C', JCC, 0x73, + 3, 'J', 'N', 'E', JCC, 0x75, + 3, 'J', 'N', 'G', JCC, 0x7E, + 4, 'J', 'N', 'G', 'E', JCC, 0x7C, + 3, 'J', 'N', 'L', JCC, 0x7D, + 4, 'J', 'N', 'L', 'E', JCC, 0x7F, + 3, 'J', 'N', 'O', JCC, 0x71, + 3, 'J', 'N', 'P', JCC, 0x7B, + 3, 'J', 'N', 'S', JCC, 0x79, + 3, 'J', 'N', 'Z', JCC, 0x75, + 2, 'J', 'O', JCC, 0x70, + 2, 'J', 'P', JCC, 0x7A, + 3, 'J', 'P', 'E', JCC, 0x7A, + 3, 'J', 'P', 'O', JCC, 0x7B, + 2, 'J', 'S', JCC, 0x78, + 2, 'J', 'Z', JCC, 0x74, + 4, 'L', 'A', 'H', 'F', INHER, 0x9F, + 3, 'L', 'D', 'S', GvMp, 0xC5, + 3, 'L', 'E', 'A', LEA, 0x8D, + 5, 'L', 'E', 'A', 'V', 'E', INHER, 0xC9, + 3, 'L', 'E', 'S', GvMp, 0xC4, + 4, 'L', 'O', 'C', 'K', INHER, 0xF0, + 4, 'L', 'O', 'D', 'B', INHER, 0xAC, + 4, 'L', 'O', 'D', 'S', INHER, 0xAD, + 5, 'L', 'O', 'D', 'S', 'B', INHER, 0xAC, + 5, 'L', 'O', 'D', 'S', 'D', INHER32, 0xAD, + 5, 'L', 'O', 'D', 'S', 'W', INHER16, 0xAD, + 4, 'L', 'O', 'D', 'W', INHER16, 0xAD, + 4, 'L', 'O', 'O', 'P', JCC, 0xE2, + 5, 'L', 'O', 'O', 'P', 'E', JCC, 0xE1, + 6, 'L', 'O', 'O', 'P', 'N', 'E', JCC, 0xE0, + 6, 'L', 'O', 'O', 'P', 'N', 'Z', JCC, 0xE0, + 5, 'L', 'O', 'O', 'P', 'Z', JCC, 0xE1, + 3, 'M', 'O', 'V', MOV, 0x88, + 4, 'M', 'O', 'V', 'S', INHER, MOVSW_OPCODE, + 5, 'M', 'O', 'V', 'S', 'B', INHER, MOVSB_OPCODE, + 5, 'M', 'O', 'V', 'S', 'D', INHER32, MOVSW_OPCODE, + 5, 'M', 'O', 'V', 'S', 'W', INHER16, MOVSW_OPCODE, + 4, 'M', 'O', 'V', 'W', INHER16, MOVSW_OPCODE, + 3, 'M', 'U', 'L', DIVMUL, 0x20, + 3, 'N', 'E', 'G', NEGNOT, 0x18, + 3, 'N', 'O', 'P', INHER, 0x90, + 3, 'N', 'O', 'T', NEGNOT, 0x10, + 2, 'O', 'R', GROUP1, 0x08, + 3, 'O', 'U', 'T', OUT, 0xEE, + 4, 'O', 'U', 'T', 'S', INHER, 0x6F, + 5, 'O', 'U', 'T', 'S', 'B', INHER, 0x6E, + 5, 'O', 'U', 'T', 'S', 'D', INHER32, 0x6F, + 5, 'O', 'U', 'T', 'S', 'W', INHER16, 0x6F, + 4, 'O', 'U', 'T', 'W', OUT, 0xEF, + 3, 'P', 'O', 'P', PUSHPOP, POP_OPCODE, + 4, 'P', 'O', 'P', 'A', INHER16, 0x61, + 5, 'P', 'O', 'P', 'A', 'D', INHER32, 0x61, + 4, 'P', 'O', 'P', 'F', INHER16, 0x9D, + 5, 'P', 'O', 'P', 'F', 'D', INHER32, 0x9D, + 4, 'P', 'U', 'S', 'H', PUSHPOP, PUSH_OPCODE, + 5, 'P', 'U', 'S', 'H', 'A', INHER16, 0x60, + 6, 'P', 'U', 'S', 'H', 'A', 'D', INHER32, 0x60, + 5, 'P', 'U', 'S', 'H', 'F', INHER16, 0x9C, + 6, 'P', 'U', 'S', 'H', 'F', 'D', INHER32, 0x9C, + 3, 'R', 'C', 'L', GROUP2, 0x10, + 3, 'R', 'C', 'R', GROUP2, 0x18, + 3, 'R', 'O', 'L', GROUP2, 0x00, + 3, 'R', 'O', 'R', GROUP2, 0x08, + 3, 'R', 'E', 'P', INHER, 0xF3, + 4, 'R', 'E', 'P', 'E', INHER, 0xF3, + 5, 'R', 'E', 'P', 'N', 'E', INHER, 0xF2, + 5, 'R', 'E', 'P', 'N', 'Z', INHER, 0xF2, + 4, 'R', 'E', 'P', 'Z', INHER, 0xF3, + 3, 'R', 'E', 'T', RET, 0xC3, + 4, 'R', 'E', 'T', 'F', RET, 0xCB, + 4, 'R', 'E', 'T', 'I', RET, 0xCB, + 4, 'S', 'A', 'H', 'F', INHER, 0x9E, + 3, 'S', 'A', 'L', GROUP2, 0x20, + 3, 'S', 'A', 'R', GROUP2, 0x38, + 3, 'S', 'B', 'B', GROUP1, 0x18, + 4, 'S', 'C', 'A', 'B', INHER, 0xAE, + 4, 'S', 'C', 'A', 'S', INHER, 0xAF, + 5, 'S', 'C', 'A', 'S', 'B', INHER, 0xAE, + 5, 'S', 'C', 'A', 'S', 'D', INHER32, 0xAF, + 5, 'S', 'C', 'A', 'S', 'W', INHER16, 0xAF, + 4, 'S', 'C', 'A', 'W', INHER16, 0xAF, + 3, 'S', 'E', 'G', SEG, 0x06, + 3, 'S', 'H', 'L', GROUP2, 0x20, + 3, 'S', 'H', 'R', GROUP2, 0x28, + 4, 'S', 'S', 'E', 'G', INHER, 0x36, + 3, 'S', 'T', 'C', INHER, 0xF9, + 3, 'S', 'T', 'D', INHER, 0xFD, + 3, 'S', 'T', 'I', INHER, 0xFB, + 4, 'S', 'T', 'O', 'B', INHER, 0xAA, + 4, 'S', 'T', 'O', 'S', INHER, 0xAB, + 5, 'S', 'T', 'O', 'S', 'B', INHER, 0xAA, + 5, 'S', 'T', 'O', 'S', 'D', INHER32, 0xAB, + 5, 'S', 'T', 'O', 'S', 'W', INHER16, 0xAB, + 4, 'S', 'T', 'O', 'W', INHER16, 0xAB, + 3, 'S', 'U', 'B', GROUP1, 0x28, + 4, 'T', 'E', 'S', 'T', TEST, 0x84, + 4, 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE, + 4, 'X', 'C', 'H', 'G', XCHG, 0x86, + 4, 'X', 'L', 'A', 'T', INHER, 0xD7, + 5, 'X', 'L', 'A', 'T', 'B', INHER, 0xD7, + 3, 'X', 'O', 'R', GROUP1, 0x30, + + /* floating point */ + 5, 'F', '2', 'X', 'M', '1', F_INHER, 0x70, + 4, 'F', 'A', 'B', 'S', F_INHER, 0x61, + 4, 'F', 'A', 'D', 'D', F_M4_M8_STST, 0x00, + 5, 'F', 'A', 'D', 'D', 'P', F_STST, 0x60, + 4, 'F', 'B', 'L', 'D', F_M10, 0x74, + 5, 'F', 'B', 'S', 'T', 'P', F_M10, 0x76, + 4, 'F', 'C', 'H', 'S', F_INHER, 0x60, + 5, 'F', 'C', 'L', 'E', 'X', F_W_INHER, 0xE2, + 4, 'F', 'C', 'O', 'M', F_M4_M8_OPTST, 0x02, + 5, 'F', 'C', 'O', 'M', 'P', F_M4_M8_OPTST, 0x03, + 6, 'F', 'C', 'O', 'M', 'P', 'P', F_INHER, 0x19, + 4, 'F', 'C', 'O', 'S', F_INHER, 0x7F, + 7, 'F', 'D', 'E', 'C', 'S', 'T', 'P', F_INHER, 0x76, + 5, 'F', 'D', 'I', 'S', 'I', F_W_INHER, 0xE1, + 4, 'F', 'D', 'I', 'V', F_M4_M8_STST, 0x06, + 5, 'F', 'D', 'I', 'V', 'P', F_STST, 0x67, + 5, 'F', 'D', 'I', 'V', 'R', F_M4_M8_STST, 0x07, + 6, 'F', 'D', 'I', 'V', 'R', 'P', F_STST, 0x66, + 4, 'F', 'E', 'N', 'I', F_W_INHER, 0xE0, + 5, 'F', 'F', 'R', 'E', 'E', F_ST, 0x50, + 5, 'F', 'I', 'A', 'D', 'D', F_M2_M4, 0x20, + 5, 'F', 'I', 'C', 'O', 'M', F_M2_M4, 0x22, + 6, 'F', 'I', 'C', 'O', 'M', 'P', F_M2_M4, 0x23, + 5, 'F', 'I', 'D', 'I', 'V', F_M2_M4, 0x26, + 6, 'F', 'I', 'D', 'I', 'V', 'R', F_M2_M4, 0x27, + 4, 'F', 'I', 'L', 'D', F_M2_M4_M8, 0x30, + 5, 'F', 'I', 'M', 'U', 'L', F_M2_M4, 0x21, + 7, 'F', 'I', 'N', 'C', 'S', 'T', 'P', F_INHER, 0x77, + 5, 'F', 'I', 'N', 'I', 'T', F_W_INHER, 0xE3, + 4, 'F', 'I', 'S', 'T', F_M2_M4, 0x32, + 5, 'F', 'I', 'S', 'T', 'P', F_M2_M4_M8, 0x33, + 5, 'F', 'I', 'S', 'U', 'B', F_M2_M4, 0x24, + 6, 'F', 'I', 'S', 'U', 'B', 'R', F_M2_M4, 0x25, + 3, 'F', 'L', 'D', F_M4_M8_M10_ST, 0x10, + 4, 'F', 'L', 'D', '1', F_INHER, 0x68, + 6, 'F', 'L', 'D', 'L', '2', 'E', F_INHER, 0x6A, + 6, 'F', 'L', 'D', 'L', '2', 'T', F_INHER, 0x69, + 5, 'F', 'L', 'D', 'C', 'W', F_M2, 0x15, + 6, 'F', 'L', 'D', 'E', 'N', 'V', F_M, 0x14, + 6, 'F', 'L', 'D', 'L', 'G', '2', F_INHER, 0x6C, + 6, 'F', 'L', 'D', 'L', 'N', '2', F_INHER, 0x6D, + 5, 'F', 'L', 'D', 'P', 'I', F_INHER, 0x6B, + 4, 'F', 'L', 'D', 'Z', F_INHER, 0x6E, + 4, 'F', 'M', 'U', 'L', F_M4_M8_STST, 0x01, + 5, 'F', 'M', 'U', 'L', 'P', F_STST, 0x61, + 6, 'F', 'N', 'C', 'L', 'E', 'X', F_INHER, 0xE2, + 6, 'F', 'N', 'D', 'I', 'S', 'I', F_INHER, 0xE1, + 5, 'F', 'N', 'E', 'N', 'I', F_INHER, 0xE0, + 6, 'F', 'N', 'I', 'N', 'I', 'T', F_INHER, 0xE3, + 4, 'F', 'N', 'O', 'P', F_INHER, 0x50, + 6, 'F', 'N', 'S', 'A', 'V', 'E', F_M, 0x56, + 6, 'F', 'N', 'S', 'T', 'C', 'W', F_M2, 0x17, + 7, 'F', 'N', 'S', 'T', 'E', 'N', 'V', F_M, 0x16, + 6, 'F', 'N', 'S', 'T', 'S', 'W', F_M2_AX, 0x57, + 6, 'F', 'P', 'A', 'T', 'A', 'N', F_INHER, 0x73, + 5, 'F', 'P', 'R', 'E', 'M', F_INHER, 0x78, + 6, 'F', 'P', 'R', 'E', 'M', '1', F_INHER, 0x75, + 5, 'F', 'P', 'T', 'A', 'N', F_INHER, 0x72, + 7, 'F', 'R', 'N', 'D', 'I', 'N', 'T', F_INHER, 0x7C, + 6, 'F', 'R', 'S', 'T', 'O', 'R', F_M, 0x54, + 5, 'F', 'S', 'A', 'V', 'E', F_W_M, 0x56, + 6, 'F', 'S', 'C', 'A', 'L', 'E', F_INHER, 0x7D, + 6, 'F', 'S', 'E', 'T', 'P', 'M', F_INHER, 0xE4, + 4, 'F', 'S', 'I', 'N', F_INHER, 0x7E, + 7, 'F', 'S', 'I', 'N', 'C', 'O', 'S', F_INHER, 0x7B, + 5, 'F', 'S', 'Q', 'R', 'T', F_INHER, 0x7A, + 3, 'F', 'S', 'T', F_M4_M8_ST, FST_ENCODED, + 5, 'F', 'S', 'T', 'C', 'W', F_W_M2, 0x17, + 6, 'F', 'S', 'T', 'E', 'N', 'V', F_W_M, 0x16, + 4, 'F', 'S', 'T', 'P', F_M4_M8_M10_ST, FSTP_ENCODED, + 5, 'F', 'S', 'T', 'S', 'W', F_W_M2_AX, 0x57, + 4, 'F', 'S', 'U', 'B', F_M4_M8_STST, 0x04, + 5, 'F', 'S', 'U', 'B', 'P', F_STST, 0x65, + 5, 'F', 'S', 'U', 'B', 'R', F_M4_M8_STST, 0x05, + 6, 'F', 'S', 'U', 'B', 'R', 'P', F_STST, 0x64, + 4, 'F', 'T', 'S', 'T', F_INHER, 0x64, + 5, 'F', 'U', 'C', 'O', 'M', F_OPTST, 0x54, + 6, 'F', 'U', 'C', 'O', 'M', 'P', F_OPTST, 0x55, + 7, 'F', 'U', 'C', 'O', 'M', 'P', 'P', F_INHER, 0xA9, + 5, 'F', 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE, + 4, 'F', 'X', 'A', 'M', F_INHER, 0x65, + 4, 'F', 'X', 'C', 'H', F_OPTST, 0x11, + 7, 'F', 'X', 'T', 'R', 'A', 'C', 'T', F_INHER, 0x74, + 5, 'F', 'Y', 'L', '2', 'X', F_INHER, 0x71, + 7, 'F', 'Y', 'L', '2', 'X', 'P', '1', F_INHER, 0x79, +#endif /* I80386 */ + +#ifdef MC6809 + 3, 'A', 'B', 'X', INHER, 0x3A, + 4, 'A', 'D', 'C', 'A', ALL, 0x89, + 4, 'A', 'D', 'C', 'B', ALL, 0xC9, + 4, 'A', 'D', 'D', 'A', ALL, 0x8B, + 4, 'A', 'D', 'D', 'B', ALL, 0xCB, + 4, 'A', 'D', 'D', 'D', ALL, 0xC3, + 4, 'A', 'N', 'D', 'A', ALL, 0x84, + 4, 'A', 'N', 'D', 'B', ALL, 0xC4, + 5, 'A', 'N', 'D', 'C', 'C', IMMED, 0x1C, + 3, 'A', 'S', 'L', ALTER, 0x08, + 4, 'A', 'S', 'L', 'A', INHER, 0x48, + 4, 'A', 'S', 'L', 'B', INHER, 0x58, + 3, 'A', 'S', 'R', ALTER, 0x07, + 4, 'A', 'S', 'R', 'A', INHER, 0x47, + 4, 'A', 'S', 'R', 'B', INHER, 0x57, + 3, 'B', 'C', 'C', SHORT, 0x24, + 3, 'B', 'C', 'S', SHORT, 0x25, + 3, 'B', 'E', 'Q', SHORT, 0x27, + 3, 'B', 'G', 'E', SHORT, 0x2C, + 3, 'B', 'G', 'T', SHORT, 0x2E, + 3, 'B', 'H', 'I', SHORT, 0x22, + 3, 'B', 'H', 'S', SHORT, 0x24, + 4, 'B', 'I', 'T', 'A', ALL, 0X85, + 4, 'B', 'I', 'T', 'B', ALL, 0XC5, + 3, 'B', 'L', 'E', SHORT, 0x2F, + 3, 'B', 'L', 'O', SHORT, 0x25, + 3, 'B', 'L', 'S', SHORT, 0x23, + 3, 'B', 'L', 'T', SHORT, 0x2D, + 3, 'B', 'M', 'I', SHORT, 0x2B, + 3, 'B', 'N', 'E', SHORT, 0x26, + 3, 'B', 'P', 'L', SHORT, 0x2A, + 3, 'B', 'R', 'A', SHORT, 0x20, + 4, 'L', 'B', 'R', 'A', LONG, 0x16, + 3, 'B', 'R', 'N', SHORT, 0x21, + 3, 'B', 'S', 'R', SHORT, 0x8D, + 4, 'L', 'B', 'S', 'R', LONG, 0x17, + 3, 'B', 'V', 'C', SHORT, 0x28, + 3, 'B', 'V', 'S', SHORT, 0x29, + 3, 'C', 'L', 'R', ALTER, 0x0F, + 4, 'C', 'L', 'R', 'A', INHER, 0x4F, + 4, 'C', 'L', 'R', 'B', INHER, 0x5F, + 4, 'C', 'M', 'P', 'A', ALL, 0x81, + 4, 'C', 'M', 'P', 'B', ALL, 0xC1, + 4, 'C', 'M', 'P', 'X', ALL, 0x8C, + 3, 'C', 'O', 'M', ALTER, 0x03, + 4, 'C', 'O', 'M', 'A', INHER, 0x43, + 4, 'C', 'O', 'M', 'B', INHER, 0x53, + 4, 'C', 'W', 'A', 'I', IMMED, 0x3C, + 3, 'D', 'A', 'A', INHER, 0x19, + 3, 'D', 'E', 'C', ALTER, 0x0A, + 4, 'D', 'E', 'C', 'A', INHER, 0x4A, + 4, 'D', 'E', 'C', 'B', INHER, 0x5A, + 4, 'E', 'O', 'R', 'A', ALL, 0x88, + 4, 'E', 'O', 'R', 'B', ALL, 0xC8, + 3, 'E', 'X', 'G', SWAP, 0x1E, + 3, 'I', 'N', 'C', ALTER, 0x0C, + 4, 'I', 'N', 'C', 'A', INHER, 0x4C, + 4, 'I', 'N', 'C', 'B', INHER, 0x5C, + 3, 'J', 'M', 'P', ALTER, 0x0E, + 3, 'J', 'S', 'R', ALTER, 0x8D, + 3, 'L', 'D', 'A', ALL, 0x86, + 3, 'L', 'D', 'B', ALL, 0xC6, + 3, 'L', 'D', 'D', ALL, 0xCC, + 3, 'L', 'D', 'U', ALL, 0xCE, + 3, 'L', 'D', 'X', ALL, 0x8E, + 4, 'L', 'E', 'A', 'S', INDEXD, 0x32, + 4, 'L', 'E', 'A', 'U', INDEXD, 0x33, + 4, 'L', 'E', 'A', 'X', INDEXD, 0x30, + 4, 'L', 'E', 'A', 'Y', INDEXD, 0x31, + 3, 'L', 'S', 'L', ALTER, 0x08, + 4, 'L', 'S', 'L', 'A', INHER, 0x48, + 4, 'L', 'S', 'L', 'B', INHER, 0x58, + 3, 'L', 'S', 'R', ALTER, 0x04, + 4, 'L', 'S', 'R', 'A', INHER, 0x44, + 4, 'L', 'S', 'R', 'B', INHER, 0x54, + 3, 'M', 'U', 'L', INHER, 0x3D, + 3, 'N', 'E', 'G', ALTER, 0x00, + 4, 'N', 'E', 'G', 'A', INHER, 0x40, + 4, 'N', 'E', 'G', 'B', INHER, 0x50, + 3, 'N', 'O', 'P', INHER, 0x12, + 3, 'O', 'R', 'A', ALL, 0x8A, + 3, 'O', 'R', 'B', ALL, 0xCA, + 4, 'O', 'R', 'C', 'C', IMMED, 0x1A, + 4, 'P', 'S', 'H', 'S', SSTAK, 0x34, + 4, 'P', 'S', 'H', 'U', USTAK, 0x36, + 4, 'P', 'U', 'L', 'S', SSTAK, 0x35, + 4, 'P', 'U', 'L', 'U', USTAK, 0x37, + 3, 'R', 'O', 'L', ALTER, 0x09, + 4, 'R', 'O', 'L', 'A', INHER, 0x49, + 4, 'R', 'O', 'L', 'B', INHER, 0x59, + 3, 'R', 'O', 'R', ALTER, 0x06, + 4, 'R', 'O', 'R', 'A', INHER, 0x46, + 4, 'R', 'O', 'R', 'B', INHER, 0x56, + 3, 'R', 'T', 'I', INHER, 0x3B, + 3, 'R', 'T', 'S', INHER, 0x39, + 4, 'S', 'B', 'C', 'A', ALL, 0x82, + 4, 'S', 'B', 'C', 'B', ALL, 0xC2, + 3, 'S', 'E', 'X', INHER, 0x1D, + 3, 'S', 'T', 'A', ALTER, 0x87, + 3, 'S', 'T', 'B', ALTER, 0xC7, + 3, 'S', 'T', 'D', ALTER, 0xCD, + 3, 'S', 'T', 'U', ALTER, 0xCF, + 3, 'S', 'T', 'X', ALTER, 0x8F, + 4, 'S', 'U', 'B', 'A', ALL, 0x80, + 4, 'S', 'U', 'B', 'B', ALL, 0xC0, + 4, 'S', 'U', 'B', 'D', ALL, 0x83, + 3, 'S', 'W', 'I', INHER, 0x3F, + 4, 'S', 'Y', 'N', 'C', INHER, 0x13, + 3, 'T', 'F', 'R', SWAP, 0x1F, + 3, 'T', 'S', 'T', ALTER, 0x0D, + 4, 'T', 'S', 'T', 'A', INHER, 0x4D, + 4, 'T', 'S', 'T', 'B', INHER, 0x5D, +#endif /* MC6809 */ + 0 /* end of ops */ +}; + +PUBLIC char page1ops[] = +{ +#ifdef I80386 + 3, 'B', 'S', 'F', GvEv, 0xBC, + 3, 'B', 'S', 'R', GvEv, 0xBD, + 5, 'B', 'S', 'W', 'A', 'P', BSWAP, 0xC8, + 2, 'B', 'T', GROUP8, 0x20, + 3, 'B', 'T', 'C', GROUP8, 0x38, + 3, 'B', 'T', 'R', GROUP8, 0x30, + 3, 'B', 'T', 'S', GROUP8, 0x28, + 4, 'C', 'L', 'T', 'S', INHER, 0x06, + 7, 'C', 'M', 'P', 'X', 'C', 'H', 'G', ExGx, 0xA6, + 4, 'I', 'N', 'V', 'D', INHER, 0x08, + 6, 'I', 'N', 'V', 'L', 'P', 'G', GROUP7, 0x38, + 3, 'L', 'A', 'R', GvEv, 0x02, + 3, 'L', 'F', 'S', GvMp, 0xB4, + 4, 'L', 'G', 'D', 'T', GROUP7, 0x10, + 3, 'L', 'G', 'S', GvMp, 0xB5, + 4, 'L', 'I', 'D', 'T', GROUP7, 0x18, + 4, 'L', 'L', 'D', 'T', GROUP6, 0x10, + 4, 'L', 'M', 'S', 'W', GROUP7, 0x30, + 3, 'L', 'S', 'L', GvEv, 0x03, + 3, 'L', 'S', 'S', GvMp, 0xB2, + 3, 'L', 'T', 'R', GROUP6, 0x18, + 5, 'M', 'O', 'V', 'S', 'X', MOVX, 0xBE, + 5, 'M', 'O', 'V', 'Z', 'X', MOVX, 0xB6, + 4, 'S', 'E', 'T', 'A', SETCC, 0x97, + 5, 'S', 'E', 'T', 'A', 'E', SETCC, 0x93, + 4, 'S', 'E', 'T', 'B', SETCC, 0x92, + 5, 'S', 'E', 'T', 'B', 'E', SETCC, 0x96, + 4, 'S', 'E', 'T', 'C', SETCC, 0x92, + 4, 'S', 'E', 'T', 'E', SETCC, 0x94, + 4, 'S', 'E', 'T', 'G', SETCC, 0x9F, + 5, 'S', 'E', 'T', 'G', 'E', SETCC, 0x9D, + 4, 'S', 'E', 'T', 'L', SETCC, 0x9C, + 5, 'S', 'E', 'T', 'L', 'E', SETCC, 0x9E, + 5, 'S', 'E', 'T', 'N', 'A', SETCC, 0x96, + 6, 'S', 'E', 'T', 'N', 'A', 'E', SETCC, 0x92, + 5, 'S', 'E', 'T', 'N', 'B', SETCC, 0x93, + 6, 'S', 'E', 'T', 'N', 'B', 'E', SETCC, 0x97, + 5, 'S', 'E', 'T', 'N', 'C', SETCC, 0x93, + 5, 'S', 'E', 'T', 'N', 'E', SETCC, 0x95, + 5, 'S', 'E', 'T', 'N', 'G', SETCC, 0x9E, + 6, 'S', 'E', 'T', 'N', 'G', 'E', SETCC, 0x9C, + 5, 'S', 'E', 'T', 'N', 'L', SETCC, 0x9D, + 6, 'S', 'E', 'T', 'N', 'L', 'E', SETCC, 0x9F, + 5, 'S', 'E', 'T', 'N', 'O', SETCC, 0x91, + 5, 'S', 'E', 'T', 'N', 'P', SETCC, 0x9B, + 5, 'S', 'E', 'T', 'N', 'S', SETCC, 0x99, + 5, 'S', 'E', 'T', 'N', 'Z', SETCC, 0x95, + 4, 'S', 'E', 'T', 'O', SETCC, 0x90, + 4, 'S', 'E', 'T', 'P', SETCC, 0x9A, + 5, 'S', 'E', 'T', 'P', 'E', SETCC, 0x9A, + 5, 'S', 'E', 'T', 'P', 'O', SETCC, 0x9B, + 4, 'S', 'E', 'T', 'S', SETCC, 0x98, + 4, 'S', 'E', 'T', 'Z', SETCC, 0x94, + 4, 'S', 'G', 'D', 'T', GROUP7, 0x00, + 4, 'S', 'I', 'D', 'T', GROUP7, 0x08, + 4, 'S', 'H', 'L', 'D', SH_DOUBLE, 0xA4, + 4, 'S', 'H', 'R', 'D', SH_DOUBLE, 0xAC, + 4, 'S', 'L', 'D', 'T', GROUP6, 0x00, + 4, 'S', 'M', 'S', 'W', GROUP7, 0x20, + 3, 'S', 'T', 'R', GROUP6, 0x08, + 4, 'V', 'E', 'R', 'R', GROUP6, 0x20, + 4, 'V', 'E', 'R', 'W', GROUP6, 0x28, + 6, 'W', 'B', 'I', 'N', 'V', 'D', INHER, 0x09, + 4, 'X', 'A', 'D', 'D', ExGx, 0xC0, +#endif /* I80386 */ + +#ifdef MC6809 + 4, 'L', 'B', 'C', 'C', LONG, 0x24, + 4, 'L', 'B', 'C', 'S', LONG, 0x25, + 4, 'L', 'B', 'E', 'Q', LONG, 0x27, + 4, 'L', 'B', 'G', 'E', LONG, 0x2C, + 4, 'L', 'B', 'G', 'T', LONG, 0x2E, + 4, 'L', 'B', 'H', 'I', LONG, 0x22, + 4, 'L', 'B', 'H', 'S', LONG, 0x24, + 4, 'L', 'B', 'L', 'E', LONG, 0x2F, + 4, 'L', 'B', 'L', 'O', LONG, 0x25, + 4, 'L', 'B', 'L', 'S', LONG, 0x23, + 4, 'L', 'B', 'L', 'T', LONG, 0x2D, + 4, 'L', 'B', 'M', 'I', LONG, 0x2B, + 4, 'L', 'B', 'N', 'E', LONG, 0x26, + 4, 'L', 'B', 'P', 'L', LONG, 0x2A, + 4, 'L', 'B', 'R', 'N', LONG, 0x21, + 4, 'L', 'B', 'V', 'C', LONG, 0x28, + 4, 'L', 'B', 'V', 'S', LONG, 0x29, + 4, 'C', 'M', 'P', 'D', ALL, 0x83, + 4, 'C', 'M', 'P', 'Y', ALL, 0x8C, + 3, 'L', 'D', 'S', ALL, 0xCE, + 3, 'L', 'D', 'Y', ALL, 0x8E, + 3, 'S', 'T', 'S', ALTER, 0xCF, + 3, 'S', 'T', 'Y', ALTER, 0x8F, + 4, 'S', 'W', 'I', '2', INHER, 0x3F, +#endif /* MC6809 */ + 0 /* end of page 1 ops */ +}; + +PUBLIC char page2ops[] = +{ +#ifdef MC6809 + 4, 'C', 'M', 'P', 'S', ALL, 0x8C, + 4, 'C', 'M', 'P', 'U', ALL, 0x83, + 4, 'S', 'W', 'I', '3', INHER, 0x3F, +#endif + 0 /* end of page 2 ops */ +}; + +#ifdef I80386 +# ifdef MNSIZE +PUBLIC char bytesizeops[] = +{ + 4, 'A', 'D', 'C', 'B', GROUP1, 0x10, + 4, 'A', 'D', 'D', 'B', GROUP1, 0x00, + 4, 'A', 'N', 'D', 'B', GROUP1, 0x20, + 4, 'C', 'M', 'P', 'B', GROUP1, CMP_OPCODE_BASE, + 4, 'D', 'E', 'C', 'b', INCDEC, 0x08, + 4, 'D', 'I', 'V', 'B', DIVMUL, 0x30, + 5, 'I', 'D', 'I', 'V', 'B', DIVMUL, 0x38, + 5, 'I', 'M', 'U', 'L', 'B', IMUL, 0x28, + 3, 'I', 'N', 'B', IN, 0xEC, + 4, 'I', 'N', 'C', 'B', INCDEC, 0x00, + 4, 'M', 'O', 'V', 'B', MOV, 0x88, + 4, 'M', 'U', 'L', 'B', DIVMUL, 0x20, + 4, 'N', 'E', 'G', 'B', NEGNOT, 0x18, + 4, 'N', 'O', 'T', 'B', NEGNOT, 0x10, + 3, 'O', 'R', 'B', GROUP1, 0x08, + 4, 'O', 'U', 'T', 'B', OUT, 0xEE, + 4, 'R', 'C', 'L', 'B', GROUP2, 0x10, + 4, 'R', 'C', 'R', 'B', GROUP2, 0x18, + 4, 'R', 'O', 'L', 'B', GROUP2, 0x00, + 4, 'R', 'O', 'R', 'B', GROUP2, 0x08, + 4, 'S', 'A', 'L', 'B', GROUP2, 0x20, + 4, 'S', 'A', 'R', 'B', GROUP2, 0x38, + 4, 'S', 'H', 'L', 'B', GROUP2, 0x20, + 4, 'S', 'H', 'R', 'B', GROUP2, 0x28, + 4, 'S', 'B', 'B', 'B', GROUP1, 0x18, + 4, 'S', 'U', 'B', 'B', GROUP1, 0x28, + 5, 'T', 'E', 'S', 'T', 'B', TEST, 0x84, + 5, 'X', 'C', 'H', 'G', 'B', XCHG, 0x86, + 4, 'X', 'O', 'R', 'B', GROUP1, 0x30, + 0 /* end of byte size ops */ +}; +# endif /* MNSIZE */ +#endif /* I80386 */ + +/* --- end of keywords --- */ + +FORWARD void install P((register char *keyptr, int data)); + +PUBLIC void inst_keywords() +{ + install(regs, REGBIT); +#ifdef I80386 + install(typesizes, SIZEBIT); +#endif + install(ops, 0); + install(page1ops, PAGE1); + install(page2ops, PAGE2); +#ifdef I80386 +# ifdef MNSIZE + install(bytesizeops, PAGE1 | PAGE2); +# endif +#endif +} + +PRIVATE void install(keyptr, data) +register char *keyptr; +unsigned char data; +{ + char lowcasebuf[20]; + unsigned namelength; + char *nameptr; + char *namend; + register struct sym_s *symptr; + + while (*keyptr != 0) + { + namelength = *keyptr++; + lineptr = (symname = keyptr) + namelength; + for (nameptr = lowcasebuf, namend = lowcasebuf + namelength; + nameptr < namend;) + { + if (*keyptr < 'A' || *keyptr > 'Z') + *nameptr++ = *keyptr++; + else + *nameptr++ = *keyptr++ + ('a' - 'A'); + } + symptr = lookup(); + symptr->type = MNREGBIT; + symptr->data = data; + symptr->value_reg_or_op.op.routine = *keyptr; + symptr->value_reg_or_op.op.opcode = keyptr[1]; + lineptr = (symname = lowcasebuf) + namelength; + symptr = lookup(); + symptr->type = MNREGBIT; + symptr->data = data; + symptr->value_reg_or_op.op.routine = *keyptr; + symptr->value_reg_or_op.op.opcode = keyptr[1]; + keyptr += 2; + } +} + +/* Lookup() searches symbol table for the string from symname to lineptr - 1. + * If string is not found and ifflag is TRUE, string is added to table, with + * type = 0 + * data = inidata (RELBIT | UNDBIT, possibly with IMPBIT | SEGM) + * Returns pointer to symbol entry (NULL if not found and not installed) + * unless symbol table overflows, when routine aborts. + */ + +PUBLIC struct sym_s *lookup() +{ + struct sym_s **hashptr; + register char *nameptr; + register struct sym_s *symptr; + register unsigned hashval; + register unsigned length; +#ifdef DEBUG + int tries; + + ++nlookup; + tries = 0; +#endif + + /* Hash function is a weighted xor of 1 to 4 chars in the string. + * This works seems to work better than looking at all the chars. + * It is important that the function be fast. + * The string comparision function should also be fast and it helps + * if it is optimized for mostly identical comparisions. + * The multiplication by MULTIPLIER should compile as a shift. + */ + +#define MULTIPLIER (SPTSIZ / (1 << USEFUL_BITS_IN_ASCII)) +#define USEFUL_BITS_IN_ASCII 6 + + nameptr = lineptr; + length = nameptr - symname; + if (length <= 3) + { + if (length <= 2) + hashval = hconv(nameptr[-1]) * MULTIPLIER; + else + hashval = hconv(nameptr[-2]) * MULTIPLIER, + hashval ^= hconv(nameptr[-1]); + } + else + hashval = hconv(nameptr[-(length / 2)]) * MULTIPLIER, + hashval ^= hconv(nameptr[-2]) << 2, + hashval ^= hconv(nameptr[-1]); + nameptr = symname; + if ((symptr = *(hashptr = spt + + (hashval ^ (hconv(nameptr[0]) << 1)) % SPTSIZ)) + != NULL) + { + do + { +#ifdef DEBUG + if (tries != 0) + --nx[tries]; + ++tries; + if (tries < sizeof nx / sizeof nx[0]) + ++nx[tries]; + if (tries >= 5) + printchain(hashptr - spt) +#endif + if ((unsigned char) length != symptr->length) + continue; + if (memcmp(symptr->name, nameptr, length) == 0) + return symptr; + } + while ((symptr = symptr->next) != NULL); + + /* Calculate last non-NULL hash ptr. + * This is faster than keeping hashptr up to date in previous loop + * since most lookups are successful and hash ptr is not needed. + */ + do + { + symptr = *hashptr; + hashptr = &symptr->next; + } + while (symptr->next != NULL); + } + if (!ifflag) + return NULL; + align(heapptr); + if (heapptr >= heapend) + fatalerror(SYMOV); +#ifdef DEBUG + ++nsym; + if (hashptr >= spt && hashptr < spt + SPTSIZ) + ++nhash; +#endif + *hashptr = symptr = (struct sym_s *) heapptr; + symptr->type = 0; + symptr->data = inidata; + symptr->length = length; + symptr->value_reg_or_op.value = (unsigned) (symptr->next = NULL); + heapptr = symptr->name; + do + *heapptr++ = *nameptr++; + while (--length != 0); + *heapptr++ = 0; + return symptr; +} + +#ifdef DEBUG + +static void printchain(hashval) +unsigned hashval; +{ + register struct sym_s *symptr; + + printf("%04x ", hashval); + for (symptr = spt[hashval]; symptr != NULL; symptr = symptr->next) + printf("%s ", symptr->name); + printf("\n"); +} + +#endif + +PUBLIC void statistics() +{ +#ifdef DEBUG + int i; + int weight; + + for (i = 0; i < SPTSIZ; ++i) + printchain(i); + printf("nhash = %d, nsym = %d, nlookup = %d nx =\n", nhash, nsym, nlookup); + weight = 0; + for (i = 0; i < 30; ++i) + { + printf("%5d", nx[i]); + weight += nx[i] * i; + } + printf("\n"); + printf("weight = %d%d\n", w; +#endif +} @@ -0,0 +1,14 @@ +Check why `chk' fails. + +Update 6809/const.h. + +Produce bsd symbol tables. + +Accept gas format. + +Decide how to choose between 8-bit and 32-bit branches. 16-bit branches in +32-bit mode are unusable because top 16 bits of PC are messed up. + +Limit insns to specified processor (warn for 386 insns on 8086). + +Buffer for printing of listing. diff --git a/as/type.h b/as/type.h new file mode 100644 index 0000000..978c7d8 --- /dev/null +++ b/as/type.h @@ -0,0 +1,167 @@ +/* type.h - types for assembler */ + +/* redefine foo_t's because their use has become non-portable */ + +#define bool_t bool_T +#define count_t count_T +#define fd_t fd_T +#define indcount_t indcount_T +#define offset_t offset_T +#define opcode_t opcode_T +#define opsize_t opsize_T +#define scale_t scale_T +#define sem_t sem_T +#define smallcount_t smallcount_T +#define soffset_t soffset_T + +typedef unsigned char bool_t; +typedef int bool_pt; +typedef unsigned count_t; +typedef int error_pt; +typedef int fd_t; +typedef unsigned char indcount_t; +#ifdef I80386 +typedef unsigned long offset_t; +typedef long soffset_t; +# define SIZEOF_OFFSET_T 4 /* non-portable */ +#endif +#ifdef MC6809 +typedef unsigned offset_t; +typedef int soffset_t; +# define SIZEOF_OFFSET_T 2 /* but sizeof (offset_t) often breaks cpp */ +#endif +typedef int opcode_pt; +typedef unsigned char opcode_t; +typedef int opsize_pt; +typedef unsigned char opsize_t; +typedef unsigned reg_pt; +typedef unsigned char scale_t; +typedef unsigned char smallcount_t; +typedef /* signed */ char sem_t; +typedef unsigned u16_pt; +typedef unsigned short u16_T; +typedef unsigned long u32_T; + +/* symbol table entry */ + +struct sym_s +{ + struct sym_s *next; /* next symbol in hash chain (NULL if none) */ + /* zero offset because it is accessed most */ + unsigned char type; + unsigned char data; /* flags valid for expressions as well as syms*/ + union + { + offset_t value; /* value, if sym is a label */ + unsigned char reg; /* register code, if sym is a register */ + struct + { + unsigned char routine; /* routine number */ + opcode_t opcode; /* opcode, if sym is a hardware op */ + } + op; /* if sym is pseudo-op or hardware op */ + } + value_reg_or_op; + unsigned char length; /* length of symbol string */ + char name[1]; /* string of variable length */ +}; + +/* address */ + +struct address_s +{ + offset_t offset; + unsigned char data; + struct sym_s *sym; +}; + +#ifdef I80386 + +/* effective address */ + +struct ea_s +{ + indcount_t indcount; + opsize_t size; + reg_pt base; + reg_pt index; + scale_t scale; + struct address_s displ; +}; + +#endif + +/* flags */ + +struct flags_s +{ + bool_t global; + bool_t current; + int semaphore; +}; + +/* location counter */ + +struct lc_s +{ + unsigned char data; + offset_t lc; +}; + +/* string chain */ + +struct schain_s +{ + struct schain_s *next; + char string[2]; /* variable length */ +}; + +/* block stack */ + +struct block_s +{ + unsigned char data; + unsigned char dp; + offset_t lc; +}; + +/* if stack */ + +struct if_s +{ + bool_t ifflag; + bool_t elseflag; +}; + +/* macro stack */ + +struct macro_s +{ + char *text; + struct schain_s *parameters; +}; + +/* symbol listing format */ + +struct sym_listing_s +{ + char name[SYMLIS_NAMELEN]; + char zname[2]; + char segm[1]; + char pad1[1]; + char value[4]; + char pad2[1]; + char ar[1]; + char pad3[1]; + char cein[1]; + char pad4[1]; + char nullterm; +}; + +#if __STDC__ +typedef void (*pfv)(void); +#else +typedef void (*pfv)(); +#endif + +#include "proto.h" diff --git a/bcc-bruce/6809/const.h b/bcc-bruce/6809/const.h new file mode 100644 index 0000000..559680c --- /dev/null +++ b/bcc-bruce/6809/const.h @@ -0,0 +1,52 @@ +/* const.h - constants for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* switches for code generation */ + +#define DEBUG /* generate compiler-debugging code */ +/*#define I8088*/ /* target processor is Intel 8088 thru 80386 */ +#define MC6809 /* target processor is Motorola 6809 */ +#define SELFTYPECHECK /* check calculated type = runtime type */ + +#ifdef I8088 +# define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */ +# define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */ +# define HOLDSTRINGS /* hold strings for dumping at end + * since assembler has only 1 data seg */ +#endif + +#ifdef MC6809 +# define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */ +# define OP1 /* logical operators only use 1 byte */ +# define POSINDEPENDENT /* position indep code can (also) be gen */ +#endif + +/* switches for source and target operating system dependencies */ + +/*#define SOS_EDOS*/ /* source O/S is EDOS */ +/*#define SOS_MSDOS*/ /* source O/S is MSDOS */ +#define TOS_EDOS /* target O/S is EDOS */ + +/* switches for source machine dependencies */ + +#ifndef SOS_EDOS +# define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */ +#endif + +#ifndef SOS_MSDOS /* need portable alignment for large model */ +# define UNPORTABLE_ALIGNMENT +#endif + +/* local style */ + +#define FALSE 0 +#ifndef NULL +#define NULL 0 +#endif +#define TRUE 1 + +#define EXTERN extern +#define FORWARD static +#define PRIVATE static +#define PUBLIC diff --git a/bcc-bruce/Makefile b/bcc-bruce/Makefile new file mode 100644 index 0000000..6a507fe --- /dev/null +++ b/bcc-bruce/Makefile @@ -0,0 +1,27 @@ +# +# Build bcc +# + +all: bcc bcc-cc1 + +CFLAGS = -DLOCALPREFIX="\"/usr/local\"" -O2 + +SRCS =assign.c declare.c gencode.c label.c preserve.c type.c \ + bcc-cc1.c express.c genloads.c loadexp.c scan.c \ + exptree.c glogcode.c longop.c softop.c codefrag.c \ + floatop.c hardop.c output.c state.c debug.c function.c \ + input.c preproc.c table.c + +OBJS =assign.o declare.o gencode.o label.o preserve.o type.o \ + bcc-cc1.o express.o genloads.o loadexp.o scan.o \ + exptree.o glogcode.o longop.o softop.o codefrag.o \ + floatop.o hardop.o output.o state.o debug.o function.o \ + input.o preproc.o table.o + + +bcc: bcc.c + $(CC) $(CFLAGS) -o bcc bcc.c + +bcc-cc1: $(OBJS) + $(CC) $(CFLAGS) -o bcc-cc1 $(OBJS) + diff --git a/bcc-bruce/align.h b/bcc-bruce/align.h new file mode 100644 index 0000000..3c8971b --- /dev/null +++ b/bcc-bruce/align.h @@ -0,0 +1,16 @@ +/* align.h - memory alignment requirements for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#ifndef S_ALIGNMENT +# define align(x) (x) +#else +# ifdef UNPORTABLE_ALIGNMENT +typedef unsigned pointerint_t; +# define align(x) (((pointerint_t) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1)) +# else +# define align(x) ((char *) (x) + (- (int) (x) & (S_ALIGNMENT-1))) +# endif +#endif + +extern uoffset_t alignmask; /* general alignment mask */ diff --git a/bcc-bruce/assign.c b/bcc-bruce/assign.c new file mode 100644 index 0000000..6814f64 --- /dev/null +++ b/bcc-bruce/assign.c @@ -0,0 +1,387 @@ +/* assign.c - assignment and casting operations for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "byteord.h" +#include "gencode.h" +#include "reg.h" +#include "sc.h" +#include "sizes.h" +#include "type.h" + +FORWARD void blockmove P((struct symstruct *source, struct symstruct *target)); +FORWARD void call3 P((char *funcname, struct symstruct *target, + struct symstruct *source, uoffset_t size)); +FORWARD void fconvert P((struct symstruct *source, struct typestruct *type)); + +PUBLIC void assign(source, target) +struct symstruct *source; +struct symstruct *target; +{ + store_pt regpushed; + store_pt sourcereg; + scalar_t tscalar; + + if (target->type->constructor & (ARRAY | FUNCTION) || + target->flags == TEMP || target->flags == (LABELLED | STRING) || + target->indcount == 0 && target->flags != REGVAR) + { + bugerror("botched lvalue"); + return; + } + if (source->storage != target->storage + || source->indcount != target->indcount + || source->level != target->level + || source->offset.offi != target->offset.offi /* kludge union cmp */ + || source->type != target->type + || (source->storage & (LOCAL | GLOBAL) + || source->level == OFFKLUDGELEVEL) + && ((source->flags ^ target->flags) & LABELLED + || source->flags & LABELLED + && source->name.label != target->name.label + || !(source->flags & LABELLED) + && strcmp(source->name.namep, target->name.namep) != 0)) + { + tscalar = target->type->scalar; + if (tscalar & CHAR && source->storage == CONSTANT) + { + source->offset.offv &= CHMASKTO; + source->type = target->type; + } + regpushed = preslval(source, target); + if (!(tscalar & CHAR) || source->flags != TEMP || + source->offset.offi != sp || source->type->typesize > itypesize) + cast(target->type, source); + if (tscalar & RSCALAR) + { + if (source->storage == CONSTANT && (!reguse & doubleregs)) + load(source, doubleregs & ~DREG); + if (source->storage != CONSTANT && source->indcount == 0) + { + /* XXX - 386 only */ + storereg(DREG, target); + if (tscalar & DOUBLE) + { + target->indcount = 1; /* XXX - outnnadr clobbers this */ + target->offset.offi += accregsize; + storereg(doubleregs & ~DREG, target); + } + target->storage = source->storage; + target->offset.offi = 0; + } + else if (f_indirect(source) && tscalar & DOUBLE + && (!(reguse & OPREG) || target->storage == OPREG)) + { + struct symstruct temptarg; + + temptarg = *target; + pointat(&temptarg); + call("Fpull"); + outntypechar(temptarg.type); + sp += dtypesize; + } + else + blockmove(source, target); + } + else if (target->type->constructor & STRUCTU) + blockmove(source, target); + else + { + if (tscalar & CHAR) + load(source, DREG); + else if (target->indcount == 0 && target->storage & regregs) + load(source, target->storage); + else + loadany(source); + if (tscalar & DLONG) + { + storereg(DREG, target); + target->indcount = 1; + target->offset.offi += accregsize; + } + if ((store_t) (sourcereg = source->storage) == DREG && + target->type->scalar & CHAR) + sourcereg = BREG; + storereg(sourcereg, target); + if ((store_t) regpushed != 0) + { + /* DLONG */ + target->indcount = 1; + target->offset.offi -= accregsize; + recovlist(regpushed); + } + else + { + target->storage = sourcereg; + target->offset.offi = 0; + if (target->level == OFFKLUDGELEVEL) + target->level = EXPRLEVEL; + } + } + } +} + +/* block move assumes itypesize == accregsize && BREG size == 1 */ + +PRIVATE void blockmove(source, target) +struct symstruct *source; +struct symstruct *target; +{ + struct symstruct oldtarget; + uoffset_t typesize; + struct symstruct worksource; + + oldtarget = *target; + if ((typesize = target->type->typesize) >= 16 * itypesize || + source->indcount + target->indcount != 2) + { + address(source); + address(target); + call3("_memcpy", target, source, typesize); + } + else + { + if (source->level == OFFKLUDGELEVEL) + addoffset(source); /* else kludge is lost and offsets big */ + if (target->level == OFFKLUDGELEVEL) + addoffset(target); + worksource = *source; + for (; typesize >= itypesize; typesize -= itypesize) + { + loadreg(source, DREG); + worksource.offset.offi += itypesize; + *source = worksource; + storereg(DREG, target); + target->indcount = 1; + target->offset.offi += accregsize; + } + while (typesize-- != 0) + { + outload(); + outregname(BREG); + outopsep(); + outadr(source); + worksource.offset.offi += 1; + *source = worksource; + storereg(BREG, target); + target->indcount = 1; + target->offset.offi += 1; + } + } + *target = oldtarget; +} + +PRIVATE void call3(funcname, target, source, size) +char *funcname; +struct symstruct *target; +struct symstruct *source; +uoffset_t size; +{ + store_pt regpushed; + offset_t spmark; + struct symstruct *length; + + pushlist(regpushed = reguse & ~calleemask); + spmark = sp; + length = constsym((value_t) size); + length->type = uitype; + push(length); + push(source); + push(target); + call(funcname); + outnl(); + if (regpushed) + { + modstk(spmark); + recovlist(regpushed); + } +} + +PUBLIC void cast(type, target) +struct typestruct *type; +struct symstruct *target; +{ + scalar_t newscalar; + uoffset_t newsize; + scalar_t oldscalar; + uoffset_t oldsize; + store_pt targreg; + + if (type->constructor & (ARRAY | FUNCTION) + || type->constructor & STRUCTU && target->type != type) + { + bugerror("botched implicit cast"); + return; + } + if (target->type == type) + return; + if (target->type->constructor == ARRAY) + oldsize = ptypesize; + else + oldsize = target->type->typesize; + newscalar = type->scalar; + oldscalar = target->type->scalar; + if ((newsize = type->typesize) == oldsize && + !((newscalar | oldscalar) & RSCALAR)) + ; + else if (newsize == ctypesize) /* char only */ + { + if (oldscalar & RSCALAR) + fconvert(target, type); + else if (target->indcount == 1) + { +#if DYNAMIC_LONG_ORDER + if (long_big_endian) +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN +# if BIG_ENDIAN + target->offset.offi += oldsize - ctypesize; +# else + { + if (oldscalar & DLONG) + target->offset.offi += itypesize; /* discard msword */ + } +# endif +#endif +#if DYNAMIC_LONG_ORDER + else +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 +# if BIG_ENDIAN + target->offset.offi += ctypesize; +# else + ; +# endif +#endif + } + else if (target->storage != CONSTANT) + { + load(target, DREG); + target->storage = BREG; + } + } + else if (newscalar & (SHORT | INT | LONG) && !(newscalar & DLONG) + || type->constructor & POINTER) + { + if (oldscalar & RSCALAR) + fconvert(target, type); + else if (oldsize < newsize) + extend(target); + else if (target->indcount == 1) + { +#if DYNAMIC_LONG_ORDER + if (long_big_endian) +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN + { + if (oldscalar & DLONG) + target->offset.offi += itypesize; /* discard msword */ + } +#endif + } + else + load(target, DREG); + } + else if (newscalar & DLONG) + { + if (oldscalar & RSCALAR) + fconvert(target, type); + else if (target->storage != CONSTANT) + { + extend(target); + load(target, DREG); + target->storage = targreg = getindexreg(); + if (oldscalar & (UNSIGNED | CHAR) || + target->type->constructor & (ARRAY | FUNCTION | POINTER)) + uitol(targreg); + else + itol(targreg); + } + } + else if (newscalar & RSCALAR) + { + saveopreg(); /* XXX */ + if (oldscalar & (ISCALAR | FLOAT)) + fpush(target); + if (newscalar & FLOAT) + { + pointat(target); + call("dto"); + outntypechar(type); + justpushed(target); /* XXX - sets dtype wrong (harmless) and + * wastes (dtypesize - ftypesize) stack */ + } + restoreopreg(); + } + target->type = type; +} + +/* extend char or short to int (unsigned if from unsigned) */ + +PUBLIC void extend(target) +struct symstruct *target; +{ + scalar_t tscalar; + + if ((tscalar = target->type->scalar) & (CHAR | SHORT)) + { + if (target->storage != CONSTANT && + target->type->typesize < itypesize) + { + load(target, DREG); + if (target->type == sctype) + sctoi(); +#ifdef I8088 + else if (tscalar & SHORT) + { + if (tscalar & UNSIGNED) + ustoi(); + else + stoi(); + } +#endif + else + ctoi(); + target->storage = DREG; + } + if (tscalar & UNSIGNED) + target->type = uitype; + else + target->type = itype; + } +} + +PRIVATE void fconvert(source, type) +struct symstruct *source; +struct typestruct *type; +{ + offset_t spmark; + + pushlist(reguse & OPREG); + spmark = sp; + pointat(source); + if (source->type->scalar & DOUBLE) + call("dto"); + else + call("fto"); + if (type->scalar & UNSIGNED) + outbyte('u'); + outntypechar(type); + if (type->scalar & DLONG) + { + if (reguse & OPREG) + bugerror("loading long into used reg"); + source->storage = OPREG; + } + else if (type->scalar & CHAR) + source->storage = BREG; + else + source->storage = DREG; + source->offset.offi = + source->flags = + source->indcount = 0; + modstk(spmark); /* could adjust later (load instead of pop) */ + poplist(reguse & OPREG); +} diff --git a/bcc-bruce/bcc-cc1.c b/bcc-bruce/bcc-cc1.c new file mode 100644 index 0000000..d6fece3 --- /dev/null +++ b/bcc-bruce/bcc-cc1.c @@ -0,0 +1,25 @@ +/* bcc-cc1.c - "pass 1" for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" + +PUBLIC int main(argc, argv) +int argc; +char **argv; +{ + growheap(0); /* init order is important */ + syminit(); + etreeinit(); + ifinit(); + predefine(); + openio(argc, argv); + codeinit(); + typeinit(); + program(); + finishup(); + + /* NOTREACHED */ + return 0; +} diff --git a/bcc-bruce/bcc.bugs b/bcc-bruce/bcc.bugs new file mode 100644 index 0000000..52f6958 --- /dev/null +++ b/bcc-bruce/bcc.bugs @@ -0,0 +1,169 @@ +compiler limitations +-------------------- + +These are not implemented: + +a. bit fields + kludgily implemented (everything padded to char, int or long; can store + values wider than the specified field width) + +g. signed char type, other ANSI extensions + +compiler bugs +------------- + +6. weird but doable casts are not always done for initializers + +15. calls to a (casted) absolute address produce an immediate prefix. as386 + doesn't mind this but complains about the absolute address. as09 complains + about the prefix but can handle the absolute address + +23. char *f(); &f() is accepted as f() but produces botched nodetype + (calc char **). + +31. null byte in string initialiser should be ignored if it doesn't fit + Non-null bytes which don't fit should be ignored with a warning + +32. static char c = "xyz"; is allowed, and bad FCB is generated + +37. init of union will store multiple comma-separated entries + +38. arrays sizes larger than the amount of memory are accepted + +40. structure and union definitions are confused with each other. So + struct foo may be used in a declaration like "union foo bar;" + +42. pointer arithmetic is performed on pointers to undefined structures + (of unknown size). Size is taken as 0 although alignmask is set early + +59. preprocessor stuff (# lines or macro names) between the identifier for + a label and the colon for the label messes up the label + +60. some things involving switches are now broken for 6809 due to lack of + frame pointer + +61. assembler may get lost on lines of length exactly (?) 256 + +65. expressions in emum lists or not properly checked for overflow. They + should fit in ints. The ordinal number is allowed to overflow + +66. sizeof has type int instead of size_t + +68. "return expr;" in a function returning a void is reported as a compiler + bug not as a semantic error + +69. an argument declared as float is (correctly) promoted to double, but + not demoted to float when it is used + +71. identifiers longer than 64 are botched (scanning of the identifier is + stopped but the remaining characters in the identifier are left to + mess up the input stream + +72. check for too many macro parameters is not working + +74. union { char a, b; } foo; gives the wrong offset for b. Unions work OK + if the declaration lists have length 1 + +75. stack gets cleaned up too early in bee = foo ? bar : baz() where baz() + returns a struct although there is kludge to make plain bee = baz() work + +76. have reintroduced reduced-type bugs, so sizeof(1 ? 1 : 2) is 1 + +78. fix to require comma in arg list may be half-baked + +79. compiler starts trying to load the void expression (i ? (void)0 : (void)0) + +80. (unsigned char *) - (char *) causes error and message is obscure + +81. 'defined' is a reserved word + +82. conditionals with voids don't work + +83. float = 1e100 gets overflow exception + +84. #endif seems to be seen in +#if 1 +foo #endif bar + +85. line numbers from cpp are not quite right. + +bugs that may be fixed +---------------------- + +41. typedef's are not scoped properly + +nonstandard things that are not done quite right +------------------------------------------------ + +3. arguments declared as register are not being dumped by #asm, register + vars anyway not being passed to #asm + +26. should clear label ptrs when starting #asm + +things that have to be be done better +------------------------------------- + +11. push order reversed in genloads.c (temp) - might try to get DP order right + +12. need to clean up handling of sc specs (maybe rename flags to sc) + And local statics and externs + +24. gvarsc is not returned properly for struct/union since the members + affect gvarsc (incorrectly). There should be a flag set when + inside a struct/union definition to disable sc specs. This could + replace the tests in abdeclarator and declselt + Best may be to carry the sc along with the type a bit more (in a + global symbol structure). Also, the symbol should record sc in a better + way than now + +25. need to check stack sometimes. Xenix cc does it when allocating >= 100 + bytes locals and this is essential in Xenix as the stack is grown + dynamically + +68. overflow checking for constants + +things that could be done better +-------------------------------- + +4. install new 6809 code for branch patching (after redundancy checks) + +5. can improve code for compare with global adr in non-posindependent case + +6. char *s; long *pl; + code for *s += *pl is poor, for *s += (int) *pl is good + +7. most mov's from to ax would be faster and smaller done by xchg's + +7a. check ptr add/sub operations earlier + +8. tests for against 1 and -1 can sometimes be done with dec's and inc's + +9. __opreg is used unnec when the ptr is already in it + +9a. double indirect ptrs should maybe be made direct rather than singly + indirect by makelessindirect + +10. in cmpsmallconst(), the comparison constant should be incorporated in + the offset if the indcount is 0 and lea() called. It is harmless to + use the lea() trick for non-small constants + +20. when saved registers are popped in assign() they may overwrite the + expression value, anywhere else? May be fixed now + +27. better if loadexpression returned the register used + +28. better if source.c did not #include storage.h - it only references + DEFINITION, in some blank-skipping code which could be moved to + scan.c or preproc.c. preproc.c, scan.c and type.c also #include + storage.h, just to get at the DEFINITION and KEYWORD definitions + +29. need nodetype() to know about all optimisations in advance, including + int % small power of 2 (including 0, 1). Need to delete all type + assignments in final code gen, specially the one that convert short + to int + +30. overflow checking at runtime + +31. Use more than the first char from multiple character constants + +56. --i++ is not detected as an error in the parser diff --git a/bcc-bruce/bcc.c b/bcc-bruce/bcc.c new file mode 100644 index 0000000..bb89bf7 --- /dev/null +++ b/bcc-bruce/bcc.c @@ -0,0 +1,875 @@ +/* bcc.c - driver for Bruce's C compiler (bcc) and for CvW's C compiler */ + +/* Copyright (C) 1992 Bruce Evans */ + +#define _POSIX_SOURCE 1 + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <unistd.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> + +#define FALSE 0 +#define FORWARD static +#ifndef NULL +#define NULL 0 +#endif +#define PRIVATE static +#define PUBLIC +#define TRUE 1 + +#if __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + +#define AS "as86" +#define BAS86 +#define BCC86 +#define CC1 "bcc-cc1" +#define CC1_MINUS_O_BROKEN FALSE +#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */ +#define CPPFLAGS "-E" +#define CRT0 "crt0.o" +#define GCC "gcc" +#define LD "ld86" +#define STANDARD_CRT0_0_PREFIX LOCALPREFIX "/lib/bcc/i86/" +#define STANDARD_CRT0_3_PREFIX LOCALPREFIX "/lib/bcc/i386/" +#define STANDARD_EXEC_PREFIX LOCALPREFIX "/lib/bcc/" +#define STANDARD_EXEC_PREFIX_2 LOCALPREFIX "/bin/" + +#ifdef CCC +#undef BCC86 +#undef CC1 +#define CC1 "c386" +#undef CC1_MINUS_O_BROKEN +#define CC1_MINUS_O_BROKEN TRUE +#undef STANDARD_CRT0_0_PREFIX +#undef STANDARD_CRT0_3_PREFIX +#define STANDARD_CRT0_PREFIX "/usr/local/lib/i386/" +#endif /* CCC */ + +#ifdef MC6809 +#undef BAS86 +#undef BCC86 +#undef CRT0 +#undef GCC +#undef STANDARD_CRT0_0_PREFIX +#undef STANDARD_CRT0_3_PREFIX +#undef STANDARD_EXEC_PREFIX +#define STANDARD_EXEC_PREFIX "/usr/local/libexec/m09/bcc/" +#endif /* MC6809 */ + +#define ALLOC_UNIT 16 /* allocation unit for arg arrays */ +#define DIRCHAR '/' +#define START_ARGS 4 /* number of reserved args */ + +typedef unsigned char bool_T; /* boolean: TRUE if nonzero */ + +struct arg_s +{ + char *prog; + bool_T minus_O_broken; + int argc; + char **argv; + unsigned nr_allocated; +}; + +struct prefix_s +{ + char *name; + struct prefix_s *next; +}; + +PRIVATE struct arg_s asargs = { AS, }; +PRIVATE struct arg_s ccargs = { CC1, CC1_MINUS_O_BROKEN, }; +PRIVATE struct arg_s cppargs = { CPP, }; +#ifdef STANDARD_CRT0_PREFIX +PRIVATE struct prefix_s crt0_prefix = { STANDARD_CRT0_PREFIX, }; +#endif +#ifdef STANDARD_CRT0_0_PREFIX +PRIVATE struct prefix_s crt0_0_prefix = { STANDARD_CRT0_0_PREFIX, }; +#endif +#ifdef STANDARD_CRT0_3_PREFIX +PRIVATE struct prefix_s crt0_3_prefix = { STANDARD_CRT0_3_PREFIX, }; +#endif +PRIVATE struct prefix_s exec_prefix; +PRIVATE struct arg_s ldargs = { LD, }; +#ifdef BAS86 +PRIVATE struct arg_s ldrargs = { LD, }; +#endif +PRIVATE char *progname; +PRIVATE bool_T runerror; /* = FALSE */ +PRIVATE struct arg_s tmpargs; /* = empty */ +PRIVATE char *tmpdir; +PRIVATE unsigned verbosity; /* = 0 */ + +#ifndef DONT_REDECLARE_STDC_FUNCTIONS +void exit P((int status)); +char *getenv P((const char *name)); +void *malloc P((size_t size)); +void *realloc P((void *ptr, size_t size)); +void (*signal P((int sig, void (*func) P((int sig))))) P((int sig)); +char *strcpy P((char *dest, const char *src)); +size_t strlen P((const char *s)); +char *strrchr P((const char *s, int c)); +#endif + +#ifndef DONT_REDECLARE_POSIX_FUNCTIONS +int access P((const char *path, int amode)); +int execv P((const char *path, char * const *argv)); +pid_t fork P((void)); +pid_t getpid P((void)); +int unlink P((const char *path)); +pid_t wait P((int *status)); +ssize_t write P((int fd, const void *buf, size_t nbytes)); +#endif + +int main P((int argc, char **argv)); + +FORWARD void addarg P((struct arg_s *argp, char *arg)); +FORWARD void addprefix P((struct prefix_s *prefix, char *name)); +FORWARD void fatal P((char *message)); +FORWARD char *fixpath P((char *path, struct prefix_s *prefix, int mode)); +FORWARD void killtemps P((void)); +FORWARD void *my_malloc P((unsigned size, char *where)); +FORWARD char *my_mktemp P((void)); +FORWARD void my_unlink P((char *name)); +FORWARD void outofmemory P((char *where)); +FORWARD int run P((char *in_name, char *out_name, struct arg_s *argp)); +FORWARD void set_trap P((void)); +FORWARD void show_who P((char *message)); +FORWARD void startarg P((struct arg_s *argp)); +FORWARD char *stralloc P((char *s)); +FORWARD char *stralloc2 P((char *s1, char *s2)); +FORWARD void trap P((int signum)); +FORWARD void unsupported P((char *option, char *message)); +FORWARD void writen P((void)); +FORWARD void writes P((char *s)); +FORWARD void writesn P((char *s)); + +PUBLIC int main(argc, argv) +int argc; +char **argv; +{ + char *arg; + int argcount = argc; + bool_T *argdone = my_malloc((unsigned) argc * sizeof *argdone, "argdone"); + bool_T as_only = FALSE; + char *basename; +#ifdef BCC86 + bool_T bits32 = sizeof (char *) >= 4; + char *bits_arg; +#endif + bool_T cc_only = FALSE; +#ifdef CCC + bool_T cpp_pass = TRUE; +#else + bool_T cpp_pass = FALSE; +#endif +#ifdef BCC86 + char *crt0; +#endif + bool_T debug = FALSE; + bool_T echo = FALSE; + unsigned errcount = 0; + char ext; + char *f_out = NULL; + bool_T float_emulation = FALSE; +#ifdef BAS86 + bool_T gnu_objects = FALSE; +#endif + char *in_name; + int length; + unsigned ncisfiles = 0; + unsigned nifiles = 0; + unsigned npass_specs; + bool_T optimize = FALSE; + char *out_name; + bool_T profile = FALSE; + bool_T prep_only = FALSE; + bool_T prep_line_numbers = FALSE; + int status; + char *temp; + + progname = argv[0]; + addarg(&cppargs, CPPFLAGS); +#ifdef CCC + addarg(&asargs, "-j"); +#endif + addarg(&asargs, "-u"); + addarg(&asargs, "-w"); +#ifdef BCC86 + addarg(&ldargs, "-i"); +#endif +#ifdef BAS86 + addarg(&ldrargs, "-r"); +#endif + + /* Pass 1 over argv to gather compile options. */ + for (; --argc != 0;) + { + arg = *++argv; + *++argdone = TRUE; + if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0) + switch (arg[1]) + { +#ifdef BCC86 + case '0': + bits32 = FALSE; + break; + case '3': + bits32 = TRUE; + break; +#endif + case 'E': + prep_only = prep_line_numbers = cpp_pass = TRUE; + break; +#ifdef BAS86 + case 'G': + gnu_objects = TRUE; + break; +#endif + case 'P': + prep_only = cpp_pass = TRUE; + prep_line_numbers = FALSE; + break; + case 'O': + optimize = TRUE; /* unsupported( arg, "optimize" ); */ + break; + case 'S': + cc_only = TRUE; + break; + case 'V': + echo = TRUE; + break; + case 'c': + as_only = TRUE; + break; + case 'e': + cpp_pass = TRUE; + break; + case 'f': + float_emulation = TRUE; + ++errcount; + unsupported(arg, "float emulation"); + break; + case 'g': + debug = TRUE; /* unsupported( arg, "debug" ); */ + break; + case 'o': + if (--argc < 1) + { + ++errcount; + show_who("output file missing after -o\n"); + } + else + { + if (f_out != NULL) + show_who("more than one output file\n"); + f_out = *++argv; + *++argdone = TRUE; + } + break; + case 'p': + profile = TRUE; + ++errcount; + unsupported(arg, "profile"); + break; + case 'v': + ++verbosity; + break; + default: + *argdone = FALSE; + break; + } + else if (arg[0] == '-') + switch (arg[1]) + { + case 'A': + addarg(&asargs, arg + 2); + break; + case 'B': + addprefix(&exec_prefix, arg + 2); + break; + case 'C': + addarg(&ccargs, arg + 2); + break; + case 'D': + case 'I': + case 'U': +#ifndef CCC + addarg(&ccargs, arg); +#endif + addarg(&cppargs, arg); + break; + case 'L': + addarg(&ldargs, arg + 2); + break; + case 'P': + addarg(&cppargs, arg + 2); + break; +#ifdef CCC + case 'Q': + addarg(&ccargs, arg); + break; +#endif + case 'T': + tmpdir = arg + 2; + break; + case 't': + ++errcount; + unsupported(arg, "pass number"); + break; + default: + *argdone = FALSE; + break; + } + else + { + ++nifiles; + *argdone = FALSE; + length = strlen(arg); + if (length >= 2 && arg[length - 2] == '.' + && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S' + || ext == 's')) + ++ncisfiles; + } + } + npass_specs = prep_only + cc_only + as_only; + if (npass_specs != 0) + { + if (npass_specs > 1) + { + ++errcount; + show_who("more than 1 option from -E -P -S -c\n"); + } + if (f_out != NULL && ncisfiles > 1) + { + ++errcount; + show_who("cannot have more than 1 input with non-linked output\n"); + } + } + if (nifiles == 0) + { + ++errcount; + show_who("no input files\n"); + } + if (errcount != 0) + exit(1); + + if ((temp = getenv("BCC_EXEC_PREFIX")) != NULL) + addprefix(&exec_prefix, temp); + addprefix(&exec_prefix, STANDARD_EXEC_PREFIX); + addprefix(&exec_prefix, STANDARD_EXEC_PREFIX_2); + cppargs.prog = fixpath(cppargs.prog, &exec_prefix, X_OK); + ccargs.prog = fixpath(ccargs.prog, &exec_prefix, X_OK); + asargs.prog = fixpath(asargs.prog, &exec_prefix, X_OK); + ldargs.prog = fixpath(ldargs.prog, &exec_prefix, X_OK); + ldrargs.prog = fixpath(ldrargs.prog, &exec_prefix, X_OK); + if (tmpdir == NULL && (tmpdir = getenv("TMPDIR")) == NULL) + tmpdir = "/tmp"; + + if (prep_only && !prep_line_numbers) + addarg(&cppargs, "-P"); +#ifdef BCC86 + if (bits32) + { + bits_arg = "-3"; + crt0 = fixpath(CRT0, &crt0_3_prefix, R_OK); + } + else + { + bits_arg = "-0"; + crt0 = fixpath(CRT0, &crt0_0_prefix, R_OK); + } + addarg(&ccargs, bits_arg); + addarg(&cppargs, bits_arg); + addarg(&asargs, bits_arg); +#ifdef BAS86 + if (!gnu_objects) + { + addarg(&ldargs, bits_arg); + addarg(&ldrargs, bits_arg); + addarg(&ldargs, crt0); + } +#endif /* BAS86 */ +#endif /* BCC86 */ +#if defined(BAS86) && !defined(BCC86) + if (!gnu_objects) + addarg(&ldargs, fixpath(CRT0, &crt0_prefix, R_OK)); +#endif + set_trap(); + + /* Pass 2 over argv to compile and assemble .c, .i, .S and .s files and + * gather arguments for linker. + */ + for (argv -= (argc = argcount) - 1, argdone -= argcount - 1; --argc != 0;) + { + arg = *++argv; + if (!*++argdone) + { + length = strlen(arg); + if (length >= 2 && arg[length - 2] == '.' + && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S' + || ext == 's')) + { + if (echo || verbosity != 0) + { + writes(arg); + writesn(":"); + } + if ((basename = strrchr(arg, DIRCHAR)) == NULL) + basename = arg; + else + ++basename; + in_name = arg; + if (ext == 'c') + { + if (cpp_pass) + { + if (prep_only) + out_name = f_out; + else + out_name = my_mktemp(); + if (run(in_name, out_name, &cppargs) != 0) + continue; + in_name = out_name; + } + ext = 'i'; + } + if (ext == 'i') + { + if (prep_only) + continue; + if (cc_only) + { + if (f_out != NULL) + out_name = f_out; + else + { + out_name = stralloc(basename); + out_name[strlen(out_name) - 1] = 's'; + } + } + else + out_name = my_mktemp(); + if (run(in_name, out_name, &ccargs) != 0) + continue; + in_name = out_name; + ext = 's'; + } + if (ext == 'S') + { + if (prep_only) + out_name = f_out; + else if (cc_only) + { + if (f_out != NULL) + out_name = f_out; + else + { + out_name = stralloc(basename); + out_name[strlen(out_name) - 1] = 's'; + } + } + else + out_name = my_mktemp(); + if (run(in_name, out_name, &cppargs) != 0) + continue; + in_name = out_name; + ext = 's'; + } + if (ext == 's') + { + if (prep_only || cc_only) + continue; + out_name = stralloc(basename); + out_name[strlen(out_name) - 1] = 'o'; + if (as_only) + { + if (f_out != NULL) + out_name = f_out; + else + { + out_name = stralloc(basename); + out_name[strlen(out_name) - 1] = 'o'; + } + } + else + out_name = my_mktemp(); + addarg(&asargs, "-n"); + arg[length - 1] = 's'; + addarg(&asargs, arg); +#ifdef BAS86 + if (gnu_objects) + { + char *tmp_out_name; + + tmp_out_name = my_mktemp(); + status = run(in_name, tmp_out_name, &asargs); + asargs.argc -= 2; + if (status != 0) + continue; + if (run(tmp_out_name, out_name, &ldrargs) != 0) + continue; + } + else +#endif + { + status = run(in_name, out_name, &asargs); + asargs.argc -= 2; + if (status != 0) + continue; + } + ext = 'o'; + in_name = out_name; + } + if (ext == 'o') + { + if (prep_only || cc_only || as_only) + continue; + addarg(&ldargs, in_name); + } + } + else + addarg(&ldargs, arg); + } + } + + if (!prep_only && !cc_only && !as_only && !runerror) + { + if (f_out == NULL) + f_out = "a.out"; +#ifdef BAS86 + if (gnu_objects) + { + /* Remove -i and -i-. */ + for (argc = ldargs.argc - 1; argc >= START_ARGS; --argc) + { + arg = ldargs.argv[argc]; + if (arg[0] == '-' && arg[1] == 'i' + && (arg[2] == 0 || arg[2] == '-' && arg[3] == 0)) + { + --ldargs.argc; + memmove(ldargs.argv + argc, ldargs.argv + argc + 1, + (ldargs.argc - argc) * sizeof ldargs.argv[0]); + ldargs.argv[ldargs.argc] = NULL; + } + } + + ldargs.prog = fixpath(GCC, &exec_prefix, X_OK); + run((char *) NULL, f_out, &ldargs); + } + else +#endif + { + addarg(&ldargs, "-lc"); + run((char *) NULL, f_out, &ldargs); + } + } + killtemps(); + return runerror ? 1 : 0; +} + +PRIVATE void addarg(argp, arg) +register struct arg_s *argp; +char *arg; +{ + int new_argc; + char **new_argv; + + if (argp->nr_allocated == 0) + startarg(argp); + new_argc = argp->argc + 1; + if (new_argc >= argp->nr_allocated) + { + argp->nr_allocated += ALLOC_UNIT; + new_argv = realloc(argp->argv, argp->nr_allocated * sizeof *argp->argv); + if (new_argv == NULL) + outofmemory("addarg"); + argp->argv = new_argv; + } + argp->argv[argp->argc] = arg; + argp->argv[argp->argc = new_argc] = NULL; +} + +PRIVATE void addprefix(prefix, name) +struct prefix_s *prefix; +char *name; +{ + struct prefix_s *new_prefix; + + if (prefix->name == NULL) + prefix->name = name; + else + { + new_prefix = my_malloc(sizeof *new_prefix, "addprefix"); + new_prefix->name = name; + new_prefix->next = NULL; + while (prefix->next != NULL) + prefix = prefix->next; + prefix->next = new_prefix; + } +} + +PRIVATE void fatal(message) +char *message; +{ + writesn(message); + killtemps(); + exit(1); +} + +PRIVATE char *fixpath(path, prefix, mode) +char *path; +struct prefix_s *prefix; +int mode; +{ + char *ppath; + + for (; prefix != NULL; prefix = prefix->next) + { + if (verbosity > 2) + { + show_who("searching for "); + if (mode == R_OK) + writes("readable file "); + else + writes("executable file "); + writes(path); + writes(" in "); + writesn(prefix->name); + } + ppath = stralloc2(prefix->name, path); + if (access(ppath, mode) == 0) + return ppath; + free(ppath); + } + return path; +} + +PRIVATE void killtemps() +{ + while (tmpargs.argc > START_ARGS) + my_unlink(tmpargs.argv[--tmpargs.argc]); +} + +PRIVATE void *my_malloc(size, where) +unsigned size; +char *where; +{ + void *block; + + if ((block = malloc(size)) == NULL) + outofmemory(where); + return block; +} + +PRIVATE char *my_mktemp() +{ + char *p; + unsigned digit; + unsigned digits; + char *template; + static unsigned tmpnum; + + p = template = stralloc2(tmpdir, "/bccYYYYXXXX"); + p += strlen(p); + digits = getpid(); + while (*--p == 'X') + { + if ((digit = digits % 16) > 9) + digit += 'A' - ('9' + 1); + *p = digit + '0'; + digits /= 16; + } + digits = tmpnum; + while (*p == 'Y') + { + if ((digit = digits % 16) > 9) + digit += 'A' - ('9' + 1); + *p-- = digit + '0'; + digits /= 16; + } + ++tmpnum; + addarg(&tmpargs, template); + return template; +} + +PRIVATE void my_unlink(name) +char *name; +{ + if (verbosity > 1) + { + show_who("unlinking "); + writesn(name); + } + if (unlink(name) < 0) + { + show_who("error unlinking "); + writesn(name); + } +} + +PRIVATE void outofmemory(where) +char *where; +{ + show_who("out of memory in "); + fatal(where); +} + +PRIVATE int run(in_name, out_name, argp) +char *in_name; +char *out_name; +struct arg_s *argp; +{ + int arg0; + int i; + int status; + + arg0 = 0; + if (in_name == NULL) + ++arg0; + if (out_name == NULL) + arg0 += 2; + else if (argp->minus_O_broken) + ++arg0; + if (argp->nr_allocated == 0) + startarg(argp); + argp->argv[arg0] = argp->prog; + i = arg0 + 1; + if (in_name != NULL) + argp->argv[i++] = in_name; + if (out_name != NULL) + { + if (!argp->minus_O_broken) + argp->argv[i++] = "-o"; + argp->argv[i++] = out_name; + } + if (verbosity != 0) + { + for (i = arg0; i < argp->argc; ++i) + { + writes(argp->argv[i]); + writes(" "); + } + writen(); + } + switch (fork()) + { + case -1: + show_who("fork failed"); + fatal(""); + case 0: + execv(argp->prog, argp->argv + arg0); + show_who("exec of "); + writes(argp->prog); + fatal(" failed"); + default: + wait(&status); + for (i = tmpargs.argc - 1; i >= START_ARGS; --i) + if (in_name == tmpargs.argv[i]) + { + my_unlink(in_name); + --tmpargs.argc; + memmove(tmpargs.argv + i, tmpargs.argv + i + 1, + (tmpargs.argc - i) * sizeof tmpargs.argv[0]); + tmpargs.argv[tmpargs.argc] = NULL; + break; + } + if (status != 0) + { + killtemps(); + runerror = TRUE; + } + return status; + } +} + +PRIVATE void set_trap() +{ + int signum; + +#ifndef _NSIG +#define _NSIG NSIG +#endif + for (signum = 0; signum <= _NSIG; ++signum) +#ifdef SIGCHLD + if (signum != SIGCHLD) +#endif + if (signal(signum, SIG_IGN) != SIG_IGN) + signal(signum, trap); +} + +PRIVATE void show_who(message) +char *message; +{ + writes(progname); + writes(": "); + writes(message); +} + +PRIVATE void startarg(argp) +struct arg_s *argp; +{ + argp->argv = my_malloc((argp->nr_allocated = ALLOC_UNIT) + * sizeof *argp->argv, "startarg"); + argp->argc = START_ARGS; + argp->argv[START_ARGS] = NULL; +} + +PRIVATE char *stralloc(s) +char *s; +{ + return strcpy(my_malloc(strlen(s) + 1, "stralloc"), s); +} + +PRIVATE char *stralloc2(s1, s2) +char *s1; +char *s2; +{ + return strcat(strcpy(my_malloc( + strlen(s1) + strlen(s2) + 1, "stralloc2"), s1), s2); +} + +PRIVATE void trap(signum) +int signum; +{ + signal(signum, SIG_IGN); + show_who("caught signal"); + fatal(""); +} + +PRIVATE void unsupported(option, message) +char *option; +char *message; +{ + show_who("compiler option "); + writes(option); + writes(" ("); + writes(message); + writesn(") not supported yet"); +} + +PRIVATE void writen() +{ + writes("\n"); +} + +PRIVATE void writes(s) +char *s; +{ + write(2, s, strlen(s)); +} + +PRIVATE void writesn(s) +char *s; +{ + writes(s); + writen(); +} diff --git a/bcc-bruce/bcc.doc b/bcc-bruce/bcc.doc new file mode 100644 index 0000000..61ccd04 --- /dev/null +++ b/bcc-bruce/bcc.doc @@ -0,0 +1,173 @@ +bcc options +----------- + +bcc [-03EGOPSVcegv] [-Aas_option] [-Bexecutable_prefix] [-Ccc1_option] + [-Ddefine] [-Iinclude_dir] [-Lld_option] [-Qc386_option] [-Ttmpdir] + [-Uundef] [-o outfile] [-fpt error] [ld_options] [infiles] + +The 6809 version does not support -0, -3 or -G. +Only the c386 version supports -Q. + +defaults (off or none except for these): +-03 native +outfile stdout for preprocessor output + somewhere/file.[ci] -> file.s for compiler output + somewhere/file.[cis] -> file.o for assembler output + a.out for ld output + +-0 8086 target (works even on 80386 host) +-3 80386 target (works even on 8086 host) +-A pass remainder of option to assembler (e.g. -A-l -Alistfile for a listing) +-B prefix for executable search path (as usual; the search order is all paths + specified using -B, in order, then the path given in the environment + variable BCC_EXEC_PREFIX if that is set, then the compiled-in defaults + (something like /usr/libexec/i386/bcc/ followed by /usr/bin/)) +-C pass remainder of option to cc1 (e.g. -C-c for caller-saves) +-D define (as usual) +-E produce preprocessor output (as usual) +-G produce gnu-Minix objects (link with gnu ld) +-I include search path (as usual) +-L pass remainder of option to linker +-O optimize (does nothing) +-P produce preprocessor output with no line numbers (as usual) +-Q pass full option to c386 +-S produce assembler file (as usual) +-T temporary directory (overrides previous value and default; default is + from the environment variable TMPDIR if that is set, otherwise /tmp) +-U undefine (as usual) +-V print names of files being compiled +-c produce object file (as usual) +-e run the preprocess pass separately. This takes less memory, and may help + or harm by giving more traditional semantics like token pasting with /**/. +-f error (float emulation not supported) +-g produce debugging info (does nothing) +-o output file name follows (assembler, object or executable) (as usual) +-p error (profiling not supported) +-t error (substitution of some cc passes not supported) +-v print names and args of subprocesses being run. Two or more -v's: + print names of files being unlinked. Three or more -v's: + print names of paths being searched. + +Other options are passed to the linker, in particular -i-, -lx, -M, -m, -s. +The -i option is always passed to the linker but can be cancelled using -i-. + +This is supposed to match the V7 manual except for -0, -3, -A, -C, -G, -L, +-T, -V, -e, -v and where not supported. + +cc1 options +---------- + +cc1 [-03EPcdfltw[-]] [-Ddefine] [-Iinclude_dir] [-Uundef] [-o outfile] [infile] + +The 6809 version does not support -0 or -3 but it supports -p. + +defaults (off or none except for these): +-03 native +-c on for 6809 +-f on for 6809 +outfile stdout +infile stdin + +-0 8086 target (works even on 80386 host) +-3 80386 target (works even on 8086 host) +-D define (as usual) +-E produce preprocessor output (as usual) +-I include search path (as usual) +-P produce preprocessor output with no line numbers (as usual) +-c produce code with caller saving regs before function calls +-d print debugging information in assembly output +-f produce code with 1st argument passed in a register +-l produce code for 2 3 1 0 long byte order (only works in 16-bit versions) +-o assembler output file name follows +-p produce (almost) position-independent code +-t print source code in assemby output +-w print what cc1 thinks is the location counter in assembly output + +All the options except -D, -I and -o may be turned off by following the +option letter by a '-'. Options are processed left to right so the last +setting has precedence. + +The following is defined before option processing: + +__BCC__ 1 + +The following may be defined after option processing: + +__AS09__ 1 if 6809 version +__AS386_16__ 1 if -0 option on 80*86 +__AS386_32__ 1 if -3 option on 80*86 +__CALLER_SAVES__ 1 if -c option +__FIRST_ARG_IN_AX__ 1 if -f option on 80*86 +__FIRST_ARG_IN_X__ 1 if -f option on 6809 +__LONG_BIG_ENDIAN__ 1 if -l option +__POS_INDEPENDENT__ 1 if -p option on 6809 + +The following are standard builtins: + +__FILE__ stringized name of current input file +__LINE__ current line number + +as options +---------- + +as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src + +The 6809 version does not support -0, -3, -a or -j. + +defaults (off or none except for these; no output is produced without a flag): +-03 native +list stdout (beware of clobbering next arg) +name basename of the source name + +-0 start with 16-bit code segment +-3 start with 32-bit code segment +-a enable partial compatibility with asld +-b produce binary file, filename may follow (obsolete) +-g only put global symbols in object file +-j force all jumps to be long +-l produce list file, filename may follow +-m print macro expansions in listing +-n name of module follows (goes in object instead of source name) +-o produce object file, filename follows +-s produce symbol file, filename follows (obsolete) +-u take undefined symbols as imported-with-unspecified segment +-w don't print warnings + +The -u and -w options are perhaps back to front because they are needed for +cc1 output and Minix's make does the wrong thing with .s files left around. +However, all assembler code not written by compilers should assemble with +them turned off. + +ld options +---------- + +ld [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile] + [-Llibdir] [-Olibfile] [-T textaddr] infile... + +The version that produces old Minix a.out format does not support -r. + +The 6809 version does not support -i or -r. + +defaults (off or none except for these): +-03 native +-L/usr/local/lib/m/ (m is machine-dependent) +outfile a.out + +-0 produce header with 16-bit magic and use library subdir i86 for -lx +-3 produce header with 32-bit magic and use library subdir i386 for -lx +-Cx add file libdir-from-search/crtx.o to list of files linked +-Lx add dir name x to the head of the list of library dirs searched +-M print symbols linked on stdout +-Ox add library libdir-from-search/x to list of files linked +-T text base address follows (in format suitable for strtoul) +-i separate I&D output +-lx add library libdir-from-search/libx.a to list of files linked +-m print modules linked on stdout +-o output file name follows +-r produce output suitable for further relocation +-s strip symbols +-t trace modules being looked at on stdout +-z produce "unmapped zero page" executables + +All the options not taking an argument may be turned off by following the +option letter by a '-', as for cc1. diff --git a/bcc-bruce/byteord.h b/bcc-bruce/byteord.h new file mode 100644 index 0000000..e7b19e0 --- /dev/null +++ b/bcc-bruce/byteord.h @@ -0,0 +1,13 @@ +/* byteord.h - byte order dependencies for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#ifdef I8088 +# define BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 1 /* longs are back to front for Xenix */ +#endif + +#ifdef MC6809 +# define BIG_ENDIAN 1 /* byte order in words is high-low */ +# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ +#endif diff --git a/bcc-bruce/codefrag.c b/bcc-bruce/codefrag.c new file mode 100644 index 0000000..e98dac4 --- /dev/null +++ b/bcc-bruce/codefrag.c @@ -0,0 +1,1843 @@ +/* codefrag.c - code fragments for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "byteord.h" +#include "condcode.h" +#include "gencode.h" +#include "label.h" +#include "output.h" +#include "reg.h" +#include "scan.h" +#include "sizes.h" + +#define DEFSTR_BYTEMAX 10 +#define DEFSTR_DELIMITER '"' +#define DEFSTR_STRINGMAX 40 +#define EOS_TEXT '0' +#define MAXPRINTCHAR '~' +#define MINPRINTCHAR ' ' + +/* segment numbers */ + +#ifdef I8088 +# define CSEG 0 +# define outcseg() outop0str(".text\n") +# define DSEG 1 +# define outdseg() outop0str(".data\n") +# define BSSSEG 2 +# define outbssseg() outop0str(".bss\n") +#endif + +#ifdef MC6809 +# define CSEG 0 +# define outcseg() outop0str("LOC\t0\n") +# define DPSEG 2 +# define outdpseg() outop0str("LOC\t2\n") +# define DSEG 3 +# define outdseg() outop0str("LOC\t3\n") +# define STRSEG 1 +# define outstrseg() outop0str("LOC\t1\n") +#endif + +#ifdef I8088 +FORWARD void adjcarry P((void)); +#endif +FORWARD void clr P((store_pt reg)); +FORWARD bool_pt lowregisDreg P((void)); +#ifdef I8088 +FORWARD void outand P((void)); +FORWARD void outequate P((void)); +# ifdef XENIX_AS +FORWARD void outexport P((void)); +# endif +FORWARD void outmovsx P((void)); +FORWARD void outmovzx P((void)); +FORWARD void tfrhilo P((void)); +FORWARD void tfrlohi P((void)); +#endif +#ifdef MC6809 +FORWARD void negBsbcA P((void)); +#endif +FORWARD void outaccum P((void)); +FORWARD void outstackreg P((void)); +FORWARD void opregadr P((void)); + +/* operator and miscellaneous strings */ + +#ifdef I8088 + +# define ACCHISTR "ah" +# define ANDSTRING "and\t" +# define DEFSTR_QUOTER '\\' +# define EORSTRING "xor\t" +# define MAX_INLINE_SHIFT 2 /* better 3 for 88, 1 for 186 and above */ +# define ORSTRING "or\t" +# define TARGET_FIRST +# define addfactor(reg) (outadd(), outregname(reg), outncregname(DXREG)) +# define defstorage() outop0str(".blkb\t") +# define extBnegD() (ctoi(), negDreg()) +# define finishfactor() /* save/add/subfactor() ended already */ +# define outadc() outop3str("adc\t") +# define outandac() (outand(), outaccum(), bumplc()) +# define outandlo() (outand(), outstr(acclostr)) +# define outbimmed() outbyte('*') +# define outcommon() outop0str(".comm\t") +# define outcwd() outnop1str("cwd") +# define outdefstr() outop0str(".ascii\t\"") +# define outexchange() outop1str("xchg\t") +# define outglobl() outop0str(".globl\t") +# ifdef XENIX_AS +# define outimport() outexport() +# else +# define outexport() outop0str("export\t") +# define outimport() outop0str("import\t") +# endif +# ifdef XENIX_AS +# define outj1switch() outop3str("seg\tcs\nbr\t@"); +# else +# define outj1switch() outop3str("seg\tcs\nbr\t"); +# endif +# define outj2switch() \ + (outindleft(), outstr(ireg0str), outindright(), bumplc2(), outnl()) +# define outlcommon() outop0str("\tlcomm\t") +# define outlswitch() (outload(), outstr(ireg0str), outncregname(DREG)) +# define outnc1() outnstr(",*1") +# define outsbc() outop3str("sbb\t") +# define outset() outstr ("\tset\t") +# define outsl() outop2str("shl\t") +# define outsr() outop2str("sar\t") +# define outtransfer() outload() +# define outusr() outop2str("shr\t") +# define outxor() outop2str(EORSTRING) +# define reclaimfactor() /* factor in DXREG, DXREG now junk */ +# define savefactor(reg) regtransfer((reg), DXREG) +# define smiDreg() (outcwd(), regexchange(DREG, DXREG)) +# define sr1() (outsr(), outaccum(), outnc1()) +# define subfactor(reg) (outsub(), outregname(reg), outncregname(DXREG)) +# define usr1() (outusr(), outaccum(), outnc1()) +PRIVATE void adjcarry() +{ + outop3str("rcl\t"); + outregname(DXREG); + outncimmadr((offset_t) 9); + outand(); + bumplc2(); + bumplc2(); + outregname(DXREG); + outncimmadr((offset_t) 0x100); +} +PUBLIC void clrBreg() +{ + outxor(); + outstr(acclostr); + outncregname(BREG); +} +PUBLIC void comment() +{ + outstr("! "); +} +PUBLIC void ctoi() +{ + if (i386_32) + { + outmovzx(); + outaccum(); + outncregname(BREG); + } + else + { + outxor(); + outhiaccum(); + outcomma(); + outhiaccum(); + outnl(); + } +} +PUBLIC void defbyte() +{ + outop0str(".byte\t"); +} +#ifdef XENIX_AS +PUBLIC void defword() +{ +} /* don't have to print ".word\t" */ +#else +PUBLIC void defword() +{ + outop0str(".word\t"); +} +#endif +PUBLIC void defdword() +{ + outop0str("dd\t"); +} +PUBLIC void even() +{ + outop0str(".even\n"); +} +PUBLIC void negDreg() +{ + outop2str("neg\t"); + outnregname(DREG); +} +PUBLIC void comDreg() +{ + outop2str("not\t"); + outnregname(DREG); +} +PUBLIC void outadd() +{ + outop2str("add\t"); +} +PUBLIC void outaddsp() +{ + outadd(); + outstackreg(); + outcomma(); + outimmed(); + bumplc2(); +} +PRIVATE void outand() +{ + outop2str(ANDSTRING); +} +#ifdef XENIX_AS +PUBLIC void outcalladr() +{ + outop2str("call\t@"); +} +#else +PUBLIC void outcalladr() +{ + outop2str("call\t"); +} +#endif +PUBLIC void outcmp() +{ + outop2str("cmp\t"); +} +PUBLIC void outdec() +{ + outop1str("dec\t"); +} +PUBLIC void outdword() +{ + outstr("dword "); +} +PRIVATE void outequate() +{ + outop0str("\t=\t"); +} +#ifdef XENIX_AS +PRIVATE void outexport() +{ + outop0str(".globl\t"); +} +#endif +PUBLIC void outfail() +{ + outop0str(".fail\t"); +} +PUBLIC void outinc() +{ + outop1str("inc\t"); +} +#ifdef XENIX_AS +PUBLIC void outindleft() +{ + outbyte('('); +} +PUBLIC void outindright() +{ + outbyte(')'); +} +#else +PUBLIC void outindleft() +{ + outbyte('['); +} +PUBLIC void outindright() +{ + outbyte(']'); +} +#endif +#ifndef FRAMEPOINTER +PUBLIC void outindstackreg() +{ + outindleft(); + outregname(STACKREG); + outindright(); +} +#endif +PUBLIC void outldaccum() +{ + outload(); + outaccum(); + outcomma(); +} +PUBLIC void outldmulreg() +{ + outload(); + outregname(MULREG); + outcomma(); +} +PUBLIC void outlea() +{ + outop2str("lea\t"); +} +PUBLIC void outleasp() +{ + outlea(); + outstackreg(); + outcomma(); +} +PUBLIC void outload() +{ + outop2str("mov\t"); +} +PRIVATE void outmovsx() +{ + outop3str("movsx\t"); +} +PRIVATE void outmovzx() +{ + outop3str("movzx\t"); +} +PUBLIC void outmulmulreg() +{ + outop2str("mul\t"); + outnregname(MULREG); +} +PUBLIC void outopsep() +{ + outcomma(); +} +PUBLIC void outpshs() +{ + outop1str("push"); +} +PUBLIC void outpuls() +{ + outop1str("pop"); +} +PUBLIC void outreturn() +{ + outnop1str("ret"); +} +PUBLIC void outstore() +{ + outload(); +} +PUBLIC void outsub() +{ + outop2str("sub\t"); +} +PUBLIC void outtest() +{ + outop2str("test\t"); +} +PUBLIC void outword() +{ + outstr("word "); +} +PUBLIC void sctoi() +{ + if (i386_32) + { + outmovsx(); + outncregname(BREG); + } + else + outnop1str("cbw"); +} +PUBLIC void stoi() +{ + outnop1str("cwde"); +} +PRIVATE void tfrhilo() +{ + outload(); + outstr(acclostr); + outcomma(); + outhiaccum(); + outnl(); +} +PRIVATE void tfrlohi() +{ + outload(); + outhiaccum(); + outncregname(BREG); +} +PUBLIC void ustoi() +{ + outmovzx(); + outaccum(); + outcomma(); + outshortregname(DREG); + outnl(); +} +#endif /* I8088 */ + +#ifdef MC6809 + +# define ACCHISTR "A" +# define ANDSTRING "AND" +# define DEFSTR_QUOTER '"' +# define EORSTRING "EOR" +# define MAX_INLINE_SHIFT 16 +# define ORSTRING "OR" +# define addfactor(reg) outop2str("ADDD\t,S") +# define defstorage() outop0str("RMB\t") +# define extBnegD() (ctoi(), negBsbcA()) +# define finishfactor() outnl() +# define outadc() outop2str("ADC") +# define outandhi() outop2str("ANDA") +# define outandlo() outop2str("ANDB") +# define outcommon() outop0str("\tCOMM\t") +# define outdefstr() outop0str("FCC\t\"") +# define outequate() outop0str("\tEQU\t") +# define outexchange() outop2str("EXG\t") +# define outexport() outop0str("EXPORT\t") +# define outglobl() outop0str("GLOBL\t") +# define outimport() outop0str("IMPORT\t") +# define outjswitch() outnop2str("JMP\t[D,X]") +# define outlcommon() outop0str("\tLCOMM\t") +# define outlswitch() outop3str("LDX\t#") +# define outpijswitch() outnop2str("JMP\tD,X") +# define outpil1switch() outop3str("LEAX\t<") +# define outpil2switch() outnop2str("LDD\tD,X") +# define outrolhi() outnop1str("ROLA"); +# define outsbc() outop2str("SBC") +# define outset() outstr ("\tSET\t") +# define outsl() outop1str("LSL") +# define outtransfer() outop2str("TFR\t") +# define reclaimfactor() outnstr ("++") /* discard factor from stack */ +# define savefactor(reg) outop2str("PSHS\tD") +# define smiDreg() (clrBreg(), outnop1str("ROLA"), \ + outnop2str("SBCB\t#0"), sctoi()) + /* this tricky sequence is twice as fast as TFR A,B; SEX; TFR A,B */ + /* it gets the sign bit of A in the carry */ + /* then subtracts it from 0 in D (effectively) */ +# define sr1() (outnop1str("ASRA"), outnop1str("RORB")) +# define stackregstr "S" +# define subfactor(reg) outop2str("SUBD\t,S") +# define testhi() outnop1str("TSTA") +# define tfrhilo() outnop2str("TFR\tA,B") +# define tfrlohi() outnop2str("TFR\tB,A") +# define usr1() (outnop1str("LSRA"), outnop1str("RORB")) +PUBLIC void clrBreg() +{ + outnop1str("CLRB"); +} +PUBLIC void comment() +{ + outstr("| "); +} +PUBLIC void defbyte() +{ + outop0str("FCB\t"); +} +PUBLIC void defword() +{ + outop0str("FDB\t"); +} +PUBLIC void negDreg() +{ + outnop1str("NEGA"); + negBsbcA(); +} +PRIVATE void negBsbcA() +{ + outnop1str("NEGB"); + sbc0(); +} +PUBLIC void comDreg() +{ + outnop1str("COMA"); + outnop1str("COMB"); +} +PUBLIC void outABX() +{ + outnop1str("ABX"); +} +PUBLIC void outadd() +{ + outop2str("ADD"); +} +PUBLIC void outaddsp() +{ + outleasp(); + bumplc2(); +} +PUBLIC void outcalladr() +{ + outop2str("JSR"); +} +PUBLIC void outcmp() +{ + outop2str("CMP"); +} +PUBLIC void outdec() +{ + outop1str("DEC"); +} +PUBLIC void outdirectpage() +{ + outbyte('<'); +} +PUBLIC void outextended() +{ + outbyte('>'); +} +PUBLIC void outfail() +{ + outop0str("FAIL\t"); +} +PUBLIC void outinc() +{ + outop1str("INC"); +} +PUBLIC void outindleft() +{ + outbyte('['); +} +PUBLIC void outindright() +{ + outbyte(']'); +} +PUBLIC void outldaccum() +{ + outload(); + outaccum(); +} +PUBLIC void outldmulreg() +{ + outop2str("LDA"); +} +PUBLIC void outlea() +{ + outop2str("LEA"); +} +PUBLIC void outleasp() +{ + outop2str("LEAS\t"); +} +PUBLIC void outload() +{ + outop2str("LD"); +} +PUBLIC void outmulmulreg() +{ + outnop1str("MUL"); +} +PUBLIC void outncspregname() +{ + outcomma(); + outstackreg(); + outnl(); +} +PUBLIC void outopsep() +{ +} /* is tab, but already done by outadr() */ +PUBLIC void outpshs() +{ + outop2str("PSHS"); +} +PUBLIC void outpuls() +{ + outop2str("PULS"); +} +PUBLIC void outreturn() +{ + outnop1str("RTS"); +} +PUBLIC void outstore() +{ + outop2str("ST"); +} +PUBLIC void outsub() +{ + outop2str("SUB"); +} +PUBLIC void outtest() +{ + outop1str("TST"); +} +PUBLIC void sctoi() +{ + outnop1str("SEX"); +} +PUBLIC void ctoi() +{ + outnop1str("CLRA"); +} +#endif /* MC6809 */ +#ifdef FRAMEREG +PUBLIC void outindframereg() +{ + outindleft(); + outregname(FRAMEREG); + outindright(); +} +#endif + +typedef fastin_t seg_t; /* range 0..3 */ + +PRIVATE seg_t segment; /* current seg, depends on init to CSEG = 0 */ + +/* add carry resulting from char addition */ + +PUBLIC void adc0() +{ +#ifdef I8088 + if (i386_32) + { + adjcarry(); + outadd(); + outaccum(); + outncregname(DXREG); + } + else +#endif + { + outadc(); + outhiaccum(); + outncimmadr((offset_t) 0); + } +} + +/* add constant to register */ + +PUBLIC void addconst(offset, reg) +offset_t offset; +store_pt reg; +{ +#ifdef I8088 + if (i386_32 && (uoffset_t) offset + 1 <= 2 /* do -1 to 1 by dec/inc */ + || !i386_32 && (uoffset_t) offset + 2 <= 4) /* do -2 to 2 */ + { + if (reg == ALREG) + reg = AXREG; /* shorter and faster */ + do + { + if (offset < 0) + { + outdec(); + ++offset; + } + else /* if offset == 0, do inc + dec */ + { + outinc(); + --offset; /* shouldn't happen and harmless */ + } + outnregname(reg); + } + while (offset); + } + else +#endif +#ifdef MC6809 + if (!(reg & ALLDATREGS)) + lea(offset, reg, reg); + else if (reg == BREG && (offset == 1 || offset == -1)) + { + if (offset < 0) + outdec(); + else + outinc(); + outnregname(reg); + } + else +#endif + { + outadd(); + outimadj(offset, reg); + } +} + +/* adjust lc for signed offset */ + +PUBLIC void adjlc(offset, reg) +offset_t offset; +store_pt reg; +{ + if (!(reg & CHARREGS)) + { + bumplc(); + if (!isbyteoffset(offset)) + { +#ifdef I8088 + if ((store_t) reg != AXREG) +#endif + bumplc(); +#ifdef I8088 + if (i386_32) + bumplc2(); +#endif + } + } +} + +/* adjust stack ptr by adding a labelled constant less current sp */ + +PUBLIC void adjsp(label) +label_t label; +{ + outaddsp(); + outbyte(LOCALSTARTCHAR); + outlabel(label); + if (switchnow != NULL) + { + outminus(); + outswstacklab(); + } + else + { + outplus(); + outhex((uoffset_t) - sp); + } +#ifdef MC6809 + outcregname(LOCAL); +#endif +#ifdef I8088 + if (i386_32) + bumplc2(); +#endif + outnl(); +} + +/* and accumulator with constant */ + +PUBLIC void andconst(offset) +offset_t offset; +{ + char_t botbits; + uoffset_t topbits; + + if ((topbits = offset & ~(uoffset_t) CHMASKTO & intmaskto) != 0 && + topbits != (~(uoffset_t) CHMASKTO & intmaskto)) + /* if topbits == 0, callers reduce the type */ + { +#ifdef OP1 + outandhi(); + outncimmadr((offset_t) (topbits >> (INT16BITSTO - CHBITSTO))); +#else + outandac(); + if (i386_32) + bumplc2(); + outncimmadr(offset); + return; +#endif + } + if ((botbits = (char_t) offset & CHMASKTO) == 0) + clrBreg(); + else if (botbits != CHMASKTO) + { + outandlo(); + outncimmadr((offset_t) botbits); + } +} + +#ifdef I8088 + +/* set bss segment */ + +PUBLIC void bssseg() +{ + if (segment != BSSSEG) + { + segment = BSSSEG; + outbssseg(); + } +} + +#endif + +/* jump to case of switch */ + +PUBLIC label_t casejump() +{ + label_t jtablelab; + +#ifdef I8088 + outlswitch(); + outj1switch(); + outlabel(jtablelab = getlabel()); + outj2switch(); + if (i386_32) + bumplc2(); +#endif +#ifdef MC6809 + if (posindependent) + { + outpil1switch(); + outlabel(jtablelab = getlabel()); + outncregname(GLOBAL); + outpil2switch(); + outpijswitch(); + } + else + { + outlswitch(); + outnlabel(jtablelab = getlabel()); + outjswitch(); + } +#endif + return jtablelab; +} + +/* clear register to 0 */ + +PRIVATE void clr(reg) +store_pt reg; +{ + loadconst((offset_t) 0, reg); +} + +/* define common storage */ + +PUBLIC void common(name) +char *name; +{ +#ifdef I8088 + outcommon(); + outccname(name); + outcomma(); +#endif +#ifdef MC6809 + outccname(name); + outcommon(); +#endif +} + +/* set code segment */ + +PUBLIC void cseg() +{ + if (segment != CSEG) + { + segment = CSEG; + outcseg(); + } +} + +/* define long */ + +PUBLIC void deflong(value) +uoffset_t value; +{ + uoffset_t longhigh; + uoffset_t longlow; + + longlow = value & (uoffset_t) intmaskto; +#ifdef I8088 + if (i386_32) + defdword(); + else +#endif + { + longhigh = (value >> INT16BITSTO) & (uoffset_t) intmaskto; + defword(); +#if DYNAMIC_LONG_ORDER + if (long_big_endian) +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN + outnhex(longhigh); +#endif +#if DYNAMIC_LONG_ORDER + else +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 + { + outnhex(longlow); + longlow = longhigh; + } +#endif + defword(); + } + outnhex(longlow); +} + +/* define null storage */ + +PUBLIC void defnulls(nullcount) +uoffset_t nullcount; +{ + if (nullcount != 0) + { + defstorage(); + outnhex(nullcount); + } +} + +/* define string */ + +PUBLIC label_t defstr(sptr, stop, dataflag) +char *sptr; +char *stop; +bool_pt dataflag; +{ + int byte; /* promoted char for output */ + label_t strlab; + seg_t oldsegment; + fastin_t count; /* range 0..max(DEFSTR_BYTEMAX,DEFSTR_STRMAX) */ + +#ifdef HOLDSTRINGS + if (!(bool_t) dataflag) + return holdstr(sptr, stop); +#endif + oldsegment = segment; +#ifdef I8088 + dseg(); +#endif +#ifdef MC6809 + if (dataflag) + dseg(); + else + { + segment = STRSEG; /* could use dseg() */ + outstrseg(); /* this brings strings together */ + } +#endif + outnlabel(strlab = getlabel()); + byte = (unsigned char) *sptr++; + while (sptr <= stop) + { + if ((unsigned char) byte >= MINPRINTCHAR + && (unsigned char) byte <= MAXPRINTCHAR) + { + outdefstr(); + count = DEFSTR_STRINGMAX; + while (count-- > 0 && (unsigned char) byte >= MINPRINTCHAR + && (unsigned char) byte <= MAXPRINTCHAR && sptr <= stop) + { +#if DEFSTR_DELIMITER - DEFSTR_QUOTER + if ((unsigned char) byte == DEFSTR_DELIMITER + || (unsigned char) byte == DEFSTR_QUOTER) +#else + if ((unsigned char) byte == DEFSTR_DELIMITER) +#endif + outbyte(DEFSTR_QUOTER); + outbyte(byte); + byte = (unsigned char) *sptr++; + } + outnbyte(DEFSTR_DELIMITER); + } + else + { + defbyte(); + count = DEFSTR_BYTEMAX; + while (count-- > 0 && ((unsigned char) byte < MINPRINTCHAR + || (unsigned char) byte > MAXPRINTCHAR) && sptr <= stop) + { + if (count < DEFSTR_BYTEMAX - 1) + outcomma(); /* byte separator */ + outhex((uoffset_t) byte); + byte = (unsigned char) *sptr++; + } + outnl(); + } + } + defbyte(); + outnbyte(EOS_TEXT); + switch (oldsegment) + { + case CSEG: + cseg(); + break; + case DSEG: + dseg(); + break; +#ifdef I8088 + case BSSSEG: + bssseg(); + break; +#endif +#ifdef MC6809 + case DPSEG: + dpseg(); + break; +#endif + } + return strlab; +} + +/* divide D register by a constant if it is easy to do with shifts */ + +PUBLIC bool_pt diveasy(divisor, uflag) +value_t divisor; +bool_pt uflag; +{ + bool_t sign; + + sign = FALSE; + if (divisor < 0 && !(bool_t) uflag) + { + sign = TRUE; + divisor = -divisor; + } + if (bitcount((uvalue_t) divisor) > 1) + return FALSE; + if (divisor == 0) + clr(DREG); + else + { + if (sign) + negDreg(); + srconst((value_t) highbit((uvalue_t) divisor), uflag); + } + return TRUE; +} + +#ifdef MC6809 + +/* set direct page segment */ + +PUBLIC void dpseg() +{ + if (segment != DPSEG) + { + segment = DPSEG; + outdpseg(); + } +} + +#endif + +/* set data segment */ + +PUBLIC void dseg() +{ + if (segment != DSEG) + { + segment = DSEG; + outdseg(); + } +} + +/* equate a name to an EOL-terminated string */ + +PUBLIC void equ(name, string) +char *name; +char *string; +{ + outstr(name); + outequate(); + outline(string); +} + +/* equate a local label to a value */ + +PUBLIC void equlab(label, offset) +label_t label; +offset_t offset; +{ + outbyte(LOCALSTARTCHAR); + outlabel(label); + outequate(); + outshex(offset); + outnl(); +} + +/* import or export a variable */ + +PUBLIC void globl(name) +char *name; +{ + outglobl(); + outnccname(name); +} + +/* import a variable */ + +PUBLIC void import(name) +char *name; +{ + outimport(); + outnccname(name); +} + +/* extend an int to a long */ + +PUBLIC void itol(reg) +store_pt reg; +{ +#define TEMP_LABEL_FOR_REGRESSION_TESTS +#ifdef TEMP_LABEL_FOR_REGRESSION_TESTS + getlabel(); +#endif + + if (lowregisDreg()) + { +#ifdef I8088 + outcwd(); + regtransfer(DXREG, reg); +#else + label_t exitlab; + + clr(reg); + testhi(); + sbranch(GE, exitlab = getlabel()); + loadconst((offset_t) - 1, reg); + outnlabel(exitlab); +#endif + } + else + { + regtransfer(DREG, reg); + smiDreg(); + } +} + +/* define local common storage */ + +PUBLIC void lcommlab(label) +label_t label; +{ + outlabel(label); + outlcommon(); +} + +PUBLIC void lcommon(name) +char *name; +{ + outccname(name); + outlcommon(); +} + +#ifdef MC6809 + +/* load effective address */ + +PUBLIC void lea(offset, sourcereg, targreg) +offset_t offset; +store_pt sourcereg; +store_pt targreg; +{ + outlea(); + outregname(targreg); + outtab(); + outshex(offset); + outncregname(sourcereg); +} + +#endif + +/* load constant into given register */ + +PUBLIC void loadconst(offset, reg) +offset_t offset; +store_pt reg; +{ +#ifdef I8088 + if (offset == 0) + { + outxor(); + outregname(reg); + outncregname(reg); + } + else +#endif +#ifdef MC6809 + if (offset == 0 && reg == BREG) + clrBreg(); + else +#endif + { + outload(); + outregname(reg); +#ifdef MC6809 + if (reg == YREG) + bumplc2(); + else +#endif + if (reg != BREG) + { + bumplc(); +#ifdef I8088 + if (i386_32) + bumplc2(); +#endif + } + outncimmadr(offset); + } +} + +/* convert index half of long reg pair into low half of pair */ + +PRIVATE bool_pt lowregisDreg() +{ +#if DYNAMIC_LONG_ORDER + if (long_big_endian) +#endif +# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN + return FALSE; +#endif +#if DYNAMIC_LONG_ORDER + else +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 + return TRUE; +#endif +} + +/* partially long shift left register by a constant (negative = infinity) */ + +PUBLIC int lslconst(shift, reg) +value_t shift; +store_pt reg; +{ + if ((uvalue_t) shift >= INT16BITSTO) + { + slconst(shift - INT16BITSTO, lowregisDreg() ? DREG : reg); + regexchange(reg, DREG); + clr(lowregisDreg() ? DREG : reg); + return 0; + } +#ifdef I8088 + if (shift >= CHBITSTO) + { + if (long_big_endian) + { + tfrlohi(); + outnop2str("mov\tal,bh"); + outnop2str("mov\tbh,bl"); + outnop2str("sub\tbl,bl"); + } + else + { + outnop2str("mov\tbh,bl"); + outnop2str("mov\tbl,ah"); + tfrlohi(); + clrBreg(); + } + return (int) shift - CHBITSTO; + } +#endif + return (int) shift; +} + +/* partially long shift right register by a constant (negative = infinity) */ + +PUBLIC int lsrconst(shift, reg, uflag) +value_t shift; +store_pt reg; +bool_pt uflag; +{ + if ((uvalue_t) shift >= INT16BITSTO) + { + if (lowregisDreg()) + regexchange(reg, DREG); + srconst(shift - INT16BITSTO, uflag); + if ((bool_t) uflag) + uitol(reg); + else + itol(reg); + return 0; + } +#ifdef I8088 + if (shift >= CHBITSTO) + { + if (long_big_endian) + { + outnop2str("mov\tbl,bh"); + outnop2str("mov\tbh,al"); + tfrhilo(); + if ((bool_t) uflag) + ctoi(); + else + sctoi(); + } + else + { + tfrhilo(); + outnop2str("mov\tah,bl"); + outnop2str("mov\tbl,bh"); + if ((bool_t) uflag) + outnop2str("sub\tbh,bh"); + else + { + regexchange(reg, DREG); + sctoi(); + regexchange(reg, DREG); + } + } + return (int) shift - CHBITSTO; + } +#endif + return (int) shift; +} + +/* take D register modulo a constant if it is easy to do with a mask */ + +PUBLIC bool_pt modeasy(divisor, uflag) +value_t divisor; +bool_pt uflag; +{ + bool_t sign; + + sign = FALSE; + if (divisor < 0 && !(bool_t) uflag) + { + sign = TRUE; + divisor = -divisor; + } + if (bitcount((uvalue_t) divisor) > 1) + return FALSE; + if (--divisor == 0) + clrBreg(); /* original divisor 1 or -1 yields 0 */ + else + { + if (sign) + negDreg(); + andconst((offset_t) divisor); /* if original divisor 0, this is + null */ + if (sign) + negDreg(); + } + return TRUE; +} + +/* multiply register by a constant if it is easy to do with shifts */ + +PUBLIC bool_pt muleasy(factor, reg) +uvalue_t factor; +store_pt reg; +{ + int mulstack[MAXINTBITSTO / 2 + 1]; /* must be signed, not a fastin_t */ + fastin_pt count; + fastin_t single1skip; + fastin_t lastcount; + fastin_t mulsp; + int stackentry; /* signed */ + + if (factor == 0) + { + clr(reg); + return TRUE; + } + single1skip = 0; + mulsp = -1; /* may be unsigned, but bumps to 0 */ + while (factor != 0) + { + for (lastcount = single1skip; (factor & 1) == 0; factor >>= 1) + ++lastcount; + mulstack[++mulsp] = lastcount; + /* first time bumps mulsp to 0 even if an unsigned char */ + for (count = 0; (factor & 1) != 0; factor >>= 1) + ++count; + single1skip = 1; + if (count == 2 && factor == 0) + /* 3 = 2 + 1 better than 3 = 4 - 1 */ + /* but rest of algorithm messed up unless factor now 0 */ + mulstack[++mulsp] = 1; + else if (count > 1) + { + single1skip = 0; + if (lastcount == 1 && mulsp != 0) + mulstack[mulsp] = -1 - count; + else + mulstack[++mulsp] = -count; + } + } + if (mulsp > 3) + return FALSE; + if (mulsp != 0) + { + savefactor(reg); /* on stack or in reg as nec */ + do + { + finishfactor(); /* finish save/add/subfactor() if nec */ + stackentry = mulstack[mulsp--]; + if (stackentry < 0) + { +#ifdef I8088 + if (stackentry == -INT32BITSTO) + clr(reg); /* shifting would do nothing */ + else +#endif + slconst((value_t) - stackentry, reg); + subfactor(reg); /* from wherever put by savefactor() */ + } + else + { + slconst((value_t) stackentry, reg); + addfactor(reg); /* from wherever put by savefactor() */ + } + } + while (mulsp != 0); + reclaimfactor(); /* reclaim storage if nec */ + } + slconst((value_t) mulstack[0], reg); + return TRUE; +} + +/* negate a register */ + +PUBLIC void negreg(reg) +store_pt reg; +{ + if ((store_t) reg == BREG) + extBnegD(); + else + negDreg(); +} + +/* return string of operator */ + +PUBLIC char *opstring(op) +op_pt op; +{ + switch (op) + { + case ANDOP: + return ANDSTRING; + case EOROP: + return EORSTRING; + case OROP: + return ORSTRING; + } + return "badop"; +} + +/* print DREG (accumulator) */ + +PRIVATE void outaccum() +{ + outstr(accumstr); +} + +/* print a c compiler name with leading CCNAMEPREXFIX */ + +PUBLIC void outccname(name) +char *name; +{ + outbyte(CCNAMEPREFIX); + outstr(name); +} + +/* print high byte of word accumulator */ + +PUBLIC void outhiaccum() +{ + outstr(ACCHISTR); +} + +/* print immediate address */ + +PUBLIC void outimmadr(offset) +offset_t offset; +{ +#ifdef I8088 + if (!isbyteoffset(offset)) + outimmed(); + else + outbimmed(); +#else + outimmed(); +#endif + outshex(offset); +} + +/* print register, comma, immediate address and adjust lc */ + +PUBLIC void outimadj(offset, targreg) +offset_t offset; +store_pt targreg; +{ + outregname(targreg); + adjlc(offset, targreg); + outncimmadr(offset); +} + +/* print immediate address designator */ + +PUBLIC void outimmed() +{ + outbyte('#'); +} + +PUBLIC void outjumpstring() +{ + outop3str(jumpstring); +#ifdef I8088 + if (i386_32) + bumplc2(); +#endif +} + +/* print cc name, then newline */ + +PUBLIC void outnccname(name) +char *name; +{ + outccname(name); + outnl(); +} + +/* print separator, immediate address, newline */ + +PUBLIC void outncimmadr(offset) +offset_t offset; +{ +#ifdef I8088 + outcomma(); +#endif +#ifdef MC6809 + outtab(); +#endif + outimmadr(offset); + outnl(); +} + +/* print signed offset and adjust lc */ + +PUBLIC void outoffset(offset) +offset_t offset; +{ +#ifdef MC6809 + if (!is5bitoffset(offset)) +#endif + adjlc(offset, INDREG0); + outshex(offset); +} + +/* print stack register */ + +PRIVATE void outstackreg() +{ + outstr(stackregstr); +} + +PUBLIC void public(name) +char *name; +{ +#ifndef AS09 + outexport(); + outnccname(name); +#endif + outccname(name); + outnbyte(PUBLICENDCHAR); +} + +/* print cc name as a private label */ + +PUBLIC void private(name) +char *name; +{ +#ifdef LABELENDCHAR + outccname(name); + outnbyte(LABELENDCHAR); +#else + outnccname(name); +#endif +} + +/* exchange registers */ + +PUBLIC void regexchange(sourcereg, targreg) +store_pt sourcereg; +store_pt targreg; +{ + outexchange(); + outregname(sourcereg); + outncregname(targreg); +#ifdef I8088 + if (!((sourcereg | targreg) & AXREG)) + bumplc(); +#endif +} + +/* transfer a register */ + +PUBLIC void regtransfer(sourcereg, targreg) +store_pt sourcereg; +store_pt targreg; +{ + outtransfer(); +#ifdef TARGET_FIRST + outregname(targreg); + outncregname(sourcereg); +#else + outregname(sourcereg); + outncregname(targreg); +#endif +} + +/* subtract carry resulting from char addition */ + +PUBLIC void sbc0() +{ +#ifdef I8088 + if (i386_32) + { + adjcarry(); + outsub(); + outaccum(); + outncregname(DXREG); + } + else +#endif + { + outsbc(); + outhiaccum(); + outncimmadr((offset_t) 0); + } +} + +/* set a name to a value */ + +PUBLIC void set(name, value) +char *name; +offset_t value; +{ + outccname(funcname); + outbyte(LOCALSTARTCHAR); + outstr(name); + outset(); + outshex(value); + outnl(); +} + +/* shift left register by 1 */ + +PUBLIC void sl1(reg) +store_pt reg; +{ + outsl(); +#ifdef I8088 + outregname(reg); + outnc1(); +#endif +#ifdef MC6809 + outnregname(BREG); + outrolhi(); +#endif +} + +/* shift left register by a constant (negative = infinity) */ + +PUBLIC void slconst(shift, reg) +value_t shift; +store_pt reg; +{ +#ifdef I8088 + if (i386_32) + { + if ((shift = (uvalue_t) shift % INT32BITSTO) != 0) + { + outsl(); + if (shift != 1) + bumplc(); + outregname(reg); + outncimmadr((offset_t) shift); + } + return; + } +#endif + if ((uvalue_t) shift >= INT16BITSTO) + clr(reg); + else + { + if (shift >= CHBITSTO && reg == DREG) + { + tfrlohi(); + clrBreg(); + shift -= CHBITSTO; + } +#ifdef I8088 +# if MAX_INLINE_SHIFT < INT16BITSTO + if (shift > MAX_INLINE_SHIFT) + { + outload(); + outregname(SHIFTREG); + outcomma(); + outimmadr((offset_t) shift); + outnl(); + outsl(); + outregname(reg); + outncregname(SHIFTREG); + } + else +# endif +#endif + while (shift--) + sl1(reg); + } +} + +/* shift right D register by a constant (negative = infinity) */ + +PUBLIC void srconst(shift, uflag) +value_t shift; +bool_pt uflag; +{ +#ifdef I8088 + if (i386_32) + { + if ((shift = (uvalue_t) shift % INT32BITSTO) != 0) + { + if (uflag) + outusr(); + else + outsr(); + if (shift != 1) + bumplc(); + outaccum(); + outncimmadr((offset_t) shift); + } + return; + } +#endif + if ((uvalue_t) shift >= INT16BITSTO) /* covers negatives too */ + { + if ((bool_t) uflag) + clr(DREG); + else /* make D == 0 if D >= 0, else D == -1 */ + smiDreg(); /* special case of 68020 Scc instruction */ + } + else + { + if (shift >= CHBITSTO) + { + tfrhilo(); + if ((bool_t) uflag) + ctoi(); + else + sctoi(); + shift -= CHBITSTO; + } +#ifdef I8088 +# if MAX_INLINE_SHIFT < INT16BITSTO + if (shift > MAX_INLINE_SHIFT) + { + outload(); + outregname(SHIFTREG); + outcomma(); + outimmadr((offset_t) shift); + outnl(); + if ((bool_t) uflag) + outusr(); + else + outsr(); + outaccum(); + outncregname(SHIFTREG); + } + else +# endif +#endif + while (shift--) + { + if ((bool_t) uflag) + usr1(); + else + sr1(); + } + } +} + +/* extend an unsigned in DREG to a long */ + +PUBLIC void uitol(reg) +store_pt reg; +{ + if (lowregisDreg()) + clr(reg); + else + { + regexchange(DREG, reg); + clr(DREG); + } +} + +PRIVATE char opregstr[] = "_opreg"; + +/*----------------------------------------------------------------------------- + opregadr() + outputs address of variable opreg where OPREG is saved +-----------------------------------------------------------------------------*/ + +PRIVATE void opregadr() +{ +#ifdef I8088 + outindleft(); + outccname(opregstr); + outindright(); + bumplc2(); + if (i386_32) + bumplc2(); +#endif +#ifdef MC6809 + outregname(OPREG); + outtab(); + if (posindependent) + { + outccname(opregstr); + outncregname(GLOBAL); + bumplc(); + } + else + { + outextended(); + outnccname(opregstr); + } + bumplc(); +#endif +} + +/*----------------------------------------------------------------------------- + restoreopreg() + restores register OPREG from static location >opreg if it is was use +-----------------------------------------------------------------------------*/ + +PUBLIC void restoreopreg() +{ + if (reguse & OPREG) + { +#ifdef I8088 + outload(); + outregname(OPREG); + outopsep(); + opregadr(); + outnl(); +#endif +#ifdef MC6809 + outload(); + opregadr(); +#endif + } +} + +/*----------------------------------------------------------------------------- + saveopreg() + saves register OPREG to static location >opreg if it is in use + this makes the flop routines non-reentrant. It is too messy to + push it because the flop routines leave results on the stack +-----------------------------------------------------------------------------*/ + +PUBLIC void saveopreg() +{ + if (reguse & OPREG) + { +#ifdef I8088 + bssseg(); + common(opregstr); + outnhex(opregsize); + cseg(); + outstore(); + opregadr(); + outncregname(OPREG); +#endif +#ifdef MC6809 + dseg(); + common(opregstr); + outnhex(opregsize); + cseg(); + outstore(); + opregadr(); +#endif + } +} diff --git a/bcc-bruce/condcode.h b/bcc-bruce/condcode.h new file mode 100644 index 0000000..9b047df --- /dev/null +++ b/bcc-bruce/condcode.h @@ -0,0 +1,16 @@ +/* condcode.h - condition codes for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#define EQ 0 +#define NE 1 +#define RA 2 +#define RN 3 +#define LT 4 +#define GE 5 +#define LE 6 +#define GT 7 +#define LO 8 +#define HS 9 +#define LS 10 +#define HI 11 diff --git a/bcc-bruce/const.h b/bcc-bruce/const.h new file mode 100644 index 0000000..8df8bcb --- /dev/null +++ b/bcc-bruce/const.h @@ -0,0 +1,52 @@ +/* const.h - constants for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* switches for code generation */ + +#define DEBUG /* generate compiler-debugging code */ +#define I8088 /* target processor is Intel 8088 thru 80386 */ +/*#define MC6809*/ /* target processor is Motorola 6809 */ +#define SELFTYPECHECK /* check calculated type = runtime type */ + +#ifdef I8088 +# define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */ +# define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */ +# define HOLDSTRINGS /* hold strings for dumping at end + * since assembler has only 1 data seg */ +#endif + +#ifdef MC6809 +# define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */ +# define OP1 /* logical operators only use 1 byte */ +# define POSINDEPENDENT /* position indep code can (also) be gen */ +#endif + +/* switches for source and target operating system dependencies */ + +/*#define SOS_EDOS*/ /* source O/S is EDOS */ +/*#define SOS_MSDOS*/ /* source O/S is MSDOS */ +/*#define TOS_EDOS*/ /* target O/S is EDOS */ + +/* switches for source machine dependencies */ + +#ifndef SOS_EDOS +# define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */ +#endif + +#ifndef SOS_MSDOS /* need portable alignment for large model */ +# define UNPORTABLE_ALIGNMENT +#endif + +/* local style */ + +#define FALSE 0 +#ifndef NULL +#define NULL 0 +#endif +#define TRUE 1 + +#define EXTERN extern +#define FORWARD static +#define PRIVATE static +#define PUBLIC diff --git a/bcc-bruce/debug.c b/bcc-bruce/debug.c new file mode 100644 index 0000000..26f7bf8 --- /dev/null +++ b/bcc-bruce/debug.c @@ -0,0 +1,202 @@ +/* debug.c - print debug messages for operators for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" + +#ifdef DEBUG + +#include "types.h" +#include "gencode.h" +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "type.h" + +PRIVATE char *opname[LASTOP - FIRSTOP + 1] = /* operator names */ +{ /* order must agree with op.h */ + "cond?", + "or", + "eor", + "and", + "gt", "lt", + "add", + "div", "mod", + "lognot", "not", + "strucelt", "strucptr", + "eq", + "addab", "andab", "divab", "eorab", "modab", "mulab", "orab", + "slab", "srab", "subab", + "comma", + "cond:", + "logor", + "logand", + "logeq", + "ne", + "ge", "le", + "sl", "sr", + "sub", + "mul", + "address", "cast", "indirect", "neg", + "predec", "preinc", "postdec", "postinc", + "func", "list", "rootlist", + "leaf", + "ptraddab", "ptradd", "ptrsub", +}; + +FORWARD void outindchars P((int byte, indn_pt count)); + +PUBLIC void dbitem(item) +struct symstruct *item; +{ + dbtype(item->type); + if (item->storage == NOSTORAGE) + { + outbyte(' '); + outstr(item->name.namep + 2); + outstr(" (offset "); + outshex(item->offset.offi); + outbyte(')'); + return; + } + if (item->storage == LOCAL) + { + outbyte(' '); + if (item->flags == TEMP) + outstr("(temp)"); + else + outstr(item->name.namep); + } + outstr(" = "); + outindchars('[', item->indcount); + switch (item->storage) + { + case CONSTANT: + outstr("const "); + if (item->type->scalar & RSCALAR) + outstr("(whatever)"); + else if (item->type->scalar & UNSIGNED) + outuvalue((uvalue_t) item->offset.offv); + else + outvalue(item->offset.offv); + break; + case BREG: + case DREG: + case INDREG0: + case INDREG1: + case INDREG2: +#ifdef DATREG1 + case DATREG1: +#endif +#ifdef DATREG2 + case DATREG2: +#endif + outregname(item->storage); + if (item->level == OFFKLUDGELEVEL) + { + outplus(); + if (item->flags & LABELLED) + outlabel(item->name.label); + else + outccname(item->name.namep); + } + break; + case LOCAL: + outbyte('S'); + if (sp <= 0) + outplus(); + outshex(-sp); + break; + case GLOBAL: + if (item->flags & LABELLED) + outlabel(item->name.label); + else + outstr(item->name.namep); + break; + default: + outstr("bad storage ("); + outhex((uoffset_t) item->storage); + outbyte(')'); + outstr(" offset "); + } + if (item->storage != CONSTANT) + { + if (item->offset.offi >= 0) + outplus(); + outshex(item->offset.offi); + } + outindchars(']', item->indcount); +} + +PUBLIC void dbtype(type) +struct typestruct *type; +{ + for ( ; type != NULL; type = type->nexttype) + { + outbyte(' '); + switch (type->constructor) + { + case ARRAY: + outbyte('['); + outhex(type->typesize / type->nexttype->typesize); + outbyte(']'); + break; + case FUNCTION: + outstr("()"); + break; + case POINTER: + outbyte('*'); + break; + case STRUCTU: + outstr("struct "); + default: + if (type->scalar & UNSIGNED) + outstr("unsigned "); + outstr(type->tname); + break; + } + } +} + +PUBLIC void debug(exp) /* sub-nodes must be leaves */ +struct nodestruct *exp; +{ + if (!debugon) + return; + comment(); + if (exp->tag < FIRSTOP && exp->tag > LASTOP) + outstr("unknown op"); + else + outstr(opname[exp->tag - FIRSTOP]); + if (exp->right != NULL && exp->tag != FUNCOP && + exp->tag != LISTOP && exp->tag != ROOTLISTOP) + { + dbitem(exp->right->left.symptr); + outstr(" to"); + } + dbitem(exp->left.nodeptr->left.symptr); + outstr(" (used reg = "); + if (reguse & INDREG0) + outregname(INDREG0); + if (reguse & INDREG1) + outregname(INDREG1); + if (reguse & INDREG2) + outregname(INDREG2); + outnstr(")"); +} + +PUBLIC void debugswap() +{ + if (debugon) + outnstr("* swapping"); +} + +PRIVATE void outindchars(byte, count) +int byte; +indn_pt count; +{ + while (count--) + outbyte(byte); +} + +#endif /* DEBUG */ diff --git a/bcc-bruce/declare.c b/bcc-bruce/declare.c new file mode 100644 index 0000000..e6b464c --- /dev/null +++ b/bcc-bruce/declare.c @@ -0,0 +1,1124 @@ +/* declare.c - declaration routines for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "align.h" +#include "byteord.h" +#include "gencode.h" +#include "input.h" /* just for orig_cppmode */ +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "sizes.h" +#include "table.h" +#include "type.h" + +#undef EXTERN +#define EXTERN +#include "parse.h" + +PRIVATE bool_t argsallowed; /* nonzero to allow args in declarator */ +PRIVATE sym_t gvarsc; /* sc flags of last identifier declared */ +PRIVATE char gvar2name[2 + NAMESIZE]; /* space for structure keys and .. */ + +#define gvarname (gvar2name + 2) /* last identifier declared */ +PRIVATE struct typestruct *gvartype; /* type of last identifier declared */ +PRIVATE bool_t initlistflag; /* remembers whether initializer is a list */ + +FORWARD struct typestruct *chainprefix P((struct typestruct *pretype, + struct typestruct *sufftype)); +FORWARD void declaf P((void)); +FORWARD void declarator P((void)); +FORWARD void declarg P((void)); +FORWARD struct typestruct *declenum P((void)); +FORWARD void declfunc P((void)); +FORWARD void declselt P((struct typestruct *structype, offset_t *psoffset, + struct typelist ** ptypelist)); +FORWARD bool_pt declspec P((void)); +FORWARD struct typestruct *declsu P((void)); +FORWARD void idecllist P((void)); +FORWARD void initarray P((struct typestruct *type)); +FORWARD void inititem P((struct typestruct *type)); +FORWARD void initstruct P((struct typestruct *type)); +FORWARD void lbrace P((void)); +FORWARD void multidecl P((char *sname)); +FORWARD void need P((int charneeded)); +FORWARD void rdeclarator P((void)); +FORWARD bool_pt regdecl P((void)); + +PRIVATE struct typestruct *chainprefix(pretype, sufftype) +struct typestruct *pretype; +struct typestruct *sufftype; +{ + if (pretype->nexttype != NULL) + { + sufftype = chainprefix(pretype->nexttype, sufftype); + if (pretype->constructor != ARRAY) + return prefix(pretype->constructor, pretype->typesize, sufftype); + else + return prefix(ARRAY, + pretype->typesize / pretype->nexttype->typesize + * sufftype->typesize, sufftype); + } + return sufftype; +} + +PUBLIC void colon() +{ + if (sym != COLON) + need(':'); + else + nextsym(); +} + +/* decllist() - list of local declarations */ +/* this does the non-terminal symbols declaration-list, type-declaration */ +/* list and declaration */ +/* the different cases are and ";" at the end are decided by idecllist() */ + +PUBLIC void decllist() +{ + while (declspec()) + { + if (gvarsc == NULLDECL) + gvarsc = AUTODECL; + idecllist(); + } +} + +PRIVATE void declaf() +{ + uoffset_t asize; + bool_t levelnew; +#ifdef TESTING_PROTOTYPES + char ogvarname[NAMESIZE]; + sym_t ogvarsc; + struct symstruct *ogvarsymptr; + struct typestruct *ogvartype; +#endif + + if (sym == LPAREN) /* function */ + { + nextsym(); + if (argsallowed && level == GLBLEVEL) + { + newlevel(); + levelnew = TRUE; + } + else + levelnew = FALSE; +#ifdef TESTING_PROTOTYPES + strcpy(ogvarname, gvarname); + ogvarsc = gvarsc; + ogvarsymptr = gvarsymptr; + ogvartype = gvartype; + if (declspec()) + { + if (level == ARGLEVEL) + outstr(gvarname); + outbyte('('); + do + { + declarator(); + dbtype(gvartype); + outbyte(' '); +#if 0 + if (gvarname[0] != 0 && gsymptr != NULL + && gsymptr->level == level) + error("repeated argument"); +#endif + outstr(gvarname); + if (levelnew) + addloc(gsname, gvartype); /* adjust offsets later */ + if (sym != COMMA) + break; + outcomma(); + nextsym(); + } + while (declspec()); + if (sym == STRUCELTOP) + { + /* ... should be lexed. */ + nextsym(); + if (sym == STRUCELTOP) + { + nextsym(); + if (sym == STRUCELTOP) + { + nextsym(); + outstr(" ..."); + } + } + } + outbyte(')'); + if (level == ARGLEVEL) + outnl(); + } + else + { +#endif /* TESTING_PROTOTYPES */ + while (sym == IDENT) + { + if (gsymptr != NULL && gsymptr->level == level) + error("repeated argument"); + if (levelnew) + addloc(gsname, itype); /* adjust types and offsets later */ + nextsym(); + if (sym != COMMA) + break; + nextsym(); + } +#ifdef TESTING_PROTOTYPES + } + strcpy(gvarname, ogvarname); + gvarsc = ogvarsc; + gvarsymptr = ogvarsymptr; + gvartype = ogvartype; +#endif /* TESTING_PROTOTYPES */ + rparen(); + declaf(); + switch (gvartype->constructor) + { + case ARRAY: + error("function returning array is illegal"); + break; + case FUNCTION: + error("function returning function is illegal"); + break; + } + gvartype = prefix(FUNCTION, ftypesize, gvartype); + } + else if (sym == LBRACKET) + { + nextsym(); + if (sym == RBRACKET) + asize = 0; + else + asize = constexpression() & intmaskto; /* FIXME: warn overflow */ + rbracket(); + declaf(); + if (gvartype->typesize == 0) + switch (gvartype->constructor) + { + case FUNCTION: + error("array of functions is illegal"); + break; + case STRUCTU: + error("undefined structure"); + break; + default: /* array */ + error("null dimension"); + gvartype->typesize = 1; + } + gvartype = prefix(ARRAY, asize * gvartype->typesize, gvartype); + } +} + +PRIVATE void declarator() +{ + rdeclarator(); + if (gvartype->constructor == STRUCTU && gvartype->typesize == 0 && + gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL) + error("undefined structure"); +} + +PRIVATE void declarg() +{ + if (gvarsymptr->level != ARGLEVEL) + error2error(gvarname, " not in argument list"); + else if (gvarsymptr->flags & INITIALIZED && gvarsymptr->type != gvartype) + multidecl(gvarname); + else + { + gvarsymptr->flags = INITIALIZED; /* flag otherwise unused for locals */ + if (gvartype->constructor & (ARRAY | POINTER)) + gvartype = pointype(gvartype->nexttype); + gvarsymptr->type = gvartype; + if (gvarsc == REGDECL && regdecl()) + regarg = TRUE; + } +} + +/* +enum-specifier = + "enum" [identifier] "{" enumerator {, enumerator} "}" + | "enum" identifier. +enumerator = + identifier + | identifier = constant-expression. +*/ + +PRIVATE struct typestruct *declenum() +{ + register struct symstruct *esymptr; + register struct typestruct *enumtype; + offset_t ordinal; + + nextsym(); + if (sym != IDENT && sym != TYPEDEFNAME) + enumtype = addstruct(""); + else if ((esymptr = findstruct(gsname)) == NULL) + { + enumtype = addstruct(gsname); + nextsym(); + } + else + { + nextsym(); + enumtype = esymptr->type; + if (sym != LBRACE) + return enumtype; + if (esymptr->level != level) + enumtype = addstruct(esymptr->name.namea); + } + lbrace(); + if (enumtype->typesize != 0) + multidecl(enumtype->tname); + else + { + enumtype->typesize = itypesize; + enumtype->alignmask = itype->alignmask; + } + if (sym != IDENT) + error("empty enumerator list"); + ordinal = 0; + while (sym == IDENT) + { + if ((esymptr = gsymptr) != NULL && esymptr->level == level) + multidecl(gsname); + else + { + (esymptr = addlorg(gsname, itype))->storage = CONSTANT; + esymptr->indcount = 0; + } + nextsym(); + if (sym == ASSIGNOP) + { + nextsym(); + ordinal = constexpression() & intmaskto; /* FIXME: warn ovflo */ + if (ordinal > maxintto) + ordinal -= (maxuintto + 1); + } + if (esymptr->storage == CONSTANT) + esymptr->offset.offv = ordinal++; + if (sym != COMMA) + break; + nextsym(); + } + rbrace(); + return enumtype; +} + +/* declselt - get list of declarations for a structure/union member */ + +PRIVATE void declselt(structype, psoffset, ptypelist) +struct typestruct *structype; +offset_t *psoffset; +struct typelist **ptypelist; +{ + struct typestruct *basetype; + value_t fieldwidth; + value_t fwidth; + offset_t offset; + scalar_t scalar; + + offset = *psoffset; + declspec(); + if (gvarsc != NULLDECL) + error("illegal type name"); + basetype = gvartype; + while (sym != SEMICOLON && sym != EOFSYM) + { + gvartype = basetype; + declarator(); + fieldwidth = -1; + if (sym == COLON) + { + scalar = gvartype->scalar; + if (!(scalar & ISCALAR)) + error("bitfield has non-integral type"); + nextsym(); + fwidth = constexpression(); + if (fwidth < 0) + error("bitfield has negative width"); + else if (fwidth > INT32BITSTO) /* XXX */ + error("bitfield is too wide"); + else + fieldwidth = fwidth; + } + if (gvarname[0] == 0) + { + if (fieldwidth == 0) + offset = (offset + ~gvartype->alignmask) & gvartype->alignmask; + else + /* XXX - should really align to fieldwidth'th bit. */ + offset = (offset + ~gvartype->alignmask) & gvartype->alignmask; + } + else + { + if (fieldwidth == 0) + error("bitfield has zero width"); + else if (fieldwidth > 0 && scalar & ISCALAR) + { + if (fieldwidth <= CHBITSTO) /* XXX! */ + gvartype = ctype; + else if (fieldwidth <= INT32BITSTO) /* XXX */ + gvartype = itype; + else + gvartype = ltype; + if (scalar & UNSIGNED) + gvartype = tounsigned(gvartype); + } + gvar2name[0] = structype->structkey[0]; + gvar2name[1] = structype->structkey[1]; + /* key provides unique name space */ + if (findlorg(gvar2name) != NULL) + multidecl(gvarname); + else + { + (gvarsymptr = addlorg(gvar2name, gvartype))->storage + = NOSTORAGE; + structype->alignmask &= gvartype->alignmask; + offset = (gvarsymptr->offset.offi = + (offset+ ~gvartype->alignmask) & gvartype->alignmask) + + gvartype->typesize; + { + register struct typelist *newtypelist; + + newtypelist = qmalloc(sizeof *newtypelist); +#ifdef TS +++ts_n_newtypelist; +ts_s_newtypelist += sizeof *newtypelist; +#endif + newtypelist->tlnext = NULL; + newtypelist->tltype = gvartype; + if (*ptypelist == NULL) + structype->listtype = newtypelist; + else + (*ptypelist)->tlnext = newtypelist; + *ptypelist = newtypelist; + } + } + } + if (sym != COMMA) + break; + nextsym(); + } + semicolon(); + *psoffset = offset; +} + +PRIVATE bool_pt declspec() +{ + unsigned nsc; + unsigned ntype; + unsigned nunsigned; + + gvarsc = NULLDECL; + gvartype = itype; + nunsigned = ntype = nsc = 0; + while (TRUE) + { + switch (sym) + { + case AUTODECL: + ++nsc; + gvarsc = sym; + nextsym(); + break; + case ENUMDECL: + ++ntype; + declenum(); + gvartype = itype; /* kludge - ignore type of enum */ + break; + case EXTERNDECL: + ++nsc; + gvarsc = sym; + nextsym(); + break; + case REGDECL: + ++nsc; + gvarsc = sym; + nextsym(); + break; + case STATICDECL: + ++nsc; + gvarsc = sym; + nextsym(); + break; + case STRUCTDECL: + case UNIONDECL: + ++ntype; + gvartype = declsu(); + break; + case TYPEDECL: + if (ntype == 1) + { + /* allow short int and long int */ + if (gvartype == itype + && (gsymptr->type == stype || gsymptr->type == ltype)) + ntype = 0; + + /* allow int short and int long, blech */ + if (gsymptr->type == itype + && (gvartype == stype || gvartype == ltype)) + { + nextsym(); + break; + } + } + ++ntype; + gvartype = gsymptr->type; + nextsym(); + break; + case TYPEDEFDECL: + ++nsc; + gvarsc = sym; + nextsym(); + break; + case TYPEDEFNAME: + if (ntype != 0) + goto break2; + ++ntype; + gvartype = gsymptr->type; + nextsym(); + break; + case UNSIGNDECL: + ++nunsigned; + nextsym(); + break; + default: + goto break2; + } + } +break2: + if (nunsigned > 0) + { + if (ntype == 0) + { + gvartype = uitype; + ntype = 1; + } + gvartype = tounsigned(gvartype); + if (nunsigned > 1) + ntype = 2; + } + if (nsc > 0) + { + if (ntype == 0) + ntype = 1; + if (nsc > 1) + error("multiple storage classes in declaration"); + } + if (ntype > 1) + error("multiple types in declaration"); + return nsc > 0 || ntype > 0; +} + +/* declsu - get structure or union name and/or declaration, return type */ + +PRIVATE struct typestruct *declsu() +{ + sym_t ogvarsc; + offset_t soffset; + offset_t struclength; + sym_t susym; + struct typelist *typelist; + struct typestruct *structype; + + susym = sym; + nextsym(); + if (sym != IDENT && sym != TYPEDEFNAME) + structype = addstruct(""); + else if ((gvarsymptr = findstruct(gsname)) == NULL) + { + structype = addstruct(gsname); + nextsym(); + } + else + { + nextsym(); + if (sym == LBRACE && gvarsymptr->level != level) + structype = addstruct(gvarsymptr->name.namea); + else + structype = gvarsymptr->type; + } + if (sym != LBRACE) + return structype; + if (structype->typesize != 0) + multidecl(structype->tname); + nextsym(); + ogvarsc = gvarsc; + struclength = soffset = 0; + typelist = NULL; + while (sym != RBRACE && sym != EOFSYM) + { + declselt(structype, &soffset, &typelist); + if (susym == STRUCTDECL) + struclength = soffset; + else + { + if (struclength < soffset) + struclength = soffset; + soffset = 0; + } + } + structype->typesize = (struclength + ~structype->alignmask) & + structype->alignmask; + rbrace(); + gvarsc = ogvarsc; + return structype; +} + +/* declfunc() - function name and parameter list */ + +PRIVATE void declfunc() +{ + offset_t argsp; + uoffset_t argsize; + struct symstruct *symptr; + + strcpy(funcname, gvarname); + if (gvarsymptr == NULL) + gvarsymptr = addglb(gvarname, gvartype); + else if (gvarsymptr->type != gvartype || + (gvarsymptr->flags & INITIALIZED)) + multidecl(gvarname); /* different type or full declare */ + gvarsymptr->flags = INITIALIZED; /* show full declare */ + cseg(); + if (gvarsc == STATICDECL) + private(gvarname); /* don't need to put STATIC in flags */ + else + public(gvarname); + callee1mask = calleemask; +#ifdef FRAMEPOINTER + frame1list = framelist; +#endif + func1saveregsize = funcsaveregsize; +#if 0 + if ((returntype = gvartype->nexttype)->scalar & RSCALAR) +#else + if ((returntype = gvartype->nexttype)->scalar & DOUBLE) +#endif + { + callee1mask &= ~doublreturnregs; +#ifdef FRAMEPOINTER + frame1list &= ~doublreturnregs; +#endif + func1saveregsize = funcdsaveregsize; + } + + arg1size = /* would already be 0 unless last function empty */ +#ifdef FRAMEPOINTER + framep = + stackarg = +#endif + reguse = 0; /* would already be 0 unless last f had reg vars */ + decllist(); + argsp = returnadrsize; + if (returntype->constructor & STRUCTU) + argsp += ptypesize; + softsp = -func1saveregsize; + for (symptr = &locsyms[0]; + symptr < locptr && symptr->flags != STRUCTNAME && + *symptr->name.namea >= 'A'; + symptr = (struct symstruct *) + align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) + { + /* convert arg sizes to offsets */ + if (symptr->type == fltype) + symptr->type = dtype; + argsize = symptr->type->typesize; +#ifdef FRAMEPOINTER + if (!arg1inreg || symptr != &locsyms[0] || symptr->flags != REGVAR) + stackarg = TRUE; +#endif + if (arg1inreg && symptr == &locsyms[0] && symptr->flags != REGVAR) + { + if ((arg1size = argsize) < itypesize) + arg1size = itypesize; + argsp = softsp -= arg1size; + } +#if BIG_ENDIAN + if (argsize < itypesize) + argsp += itypesize - argsize; + symptr->offset.offi = argsp; + argsp += argsize; +#else + symptr->offset.offi = argsp; + if (argsize > itypesize) + argsp += argsize; + else + argsp += itypesize; +#endif + if (arg1inreg && symptr == &locsyms[0]) + argsp = returnadrsize; /* skip return adr after 1st arg */ + } + lbrace(); + compound(); + clearfunclabels(); +} + +/* idecllist() - list of init-declarations with a given base type */ +/* this does the non-terminal symbols list( init-declarator ) ";" */ +/* and list( type-declaration ) ";" */ +/* and complete declarations of functions */ + +PRIVATE void idecllist() +{ + struct typestruct *basetype; + struct typestruct *inittype; + scopelev_t levelmark; + uoffset_t newoffset; + + argsallowed = level == GLBLEVEL; + levelmark = level; + basetype = gvartype; + while (sym != SEMICOLON) + { + gvartype = basetype; + declarator(); + if (gvarname[0] == 0) + needvarname(); + if (gvartype->constructor == FUNCTION) + { + if (sym != COMMA && sym != SEMICOLON) + { + if (level == ARGLEVEL && gvarsc != TYPEDEFDECL) + declfunc(); + else + error("illegal non-external function"); + if (level != levelmark) + { + oldlevel(); + locptr = &locsyms[0]; + } + argsallowed = FALSE; + return; + } + } + if (level != levelmark) + { + oldlevel(); + locptr = &locsyms[0]; + } + argsallowed = FALSE; + if (level == ARGLEVEL) + { + if (gvarsymptr == NULL) + gvarsymptr = addglb(gvarname, gvartype); /* error soon */ + declarg(); + } + else if (gvarsymptr != NULL && (gvarsymptr->level == level || + gvartype->constructor == FUNCTION || + gvarsc == EXTERNDECL && + gvarsymptr->level == GLBLEVEL)) + { + if (gvarsymptr->level != GLBLEVEL || gvarsymptr->flags == KEYWORD) + multidecl(gvarname); + else if (gvarsymptr->type != gvartype) + { + if (gvartype->constructor != ARRAY || + gvarsymptr->type->constructor != ARRAY || + gvartype->nexttype != gvarsymptr->type->nexttype || + gvartype->typesize != 0 && + gvarsymptr->type->typesize != 0) + multidecl(gvarname); + else if (gvartype->typesize != 0) + gvarsymptr->type = gvartype; + } + if (gvarsc == NULLDECL) + gvarsymptr->flags &= ~EXTERNAL; + } + else if (level == GLBLEVEL || gvartype->constructor == FUNCTION || + gvarsc == EXTERNDECL) + { + gvarsymptr = addglb(gvarname, gvartype); +#ifdef DIRECTPAGE /* make all global scalar and pointer variables DIRECTPAGE */ + if (!(gvartype->constructor & ~POINTER)) + gvarsymptr->flags = DIRECTPAGE; +#endif + if (gvarsc == EXTERNDECL) + gvarsymptr->flags |= EXTERNAL; + } + else + { + gvarsymptr = addloc(gvarname, gvartype); + if ((gvarsc != REGDECL || !regdecl()) && + gvartype->constructor != FUNCTION && gvarsc != STATICDECL && + gvarsc != TYPEDEFDECL) + gvarsymptr->offset.offi = softsp = + (softsp & gvartype->alignmask) - gvartype->typesize; + } + if (gvarsc == STATICDECL) + { + gvarsymptr->flags &= ~EXTERNAL; + gvarsymptr->flags |= STATIC; + if (gvarsymptr->level != GLBLEVEL) + { + gvarsymptr->storage = GLOBAL; + gvarsymptr->offset.offlabel = getlabel(); + /* must leave gvarsymptr->name.label alone */ + /* since name is required for findlorg() */ + /* label is activated by expression() */ + } + } + if (gvarsc == TYPEDEFDECL) + { + gvarsymptr->flags = KEYWORD; + gvarsymptr->offset.offsym = TYPEDEFNAME; + } + if (sym == ASSIGNOP) + { + if (gvarsymptr->flags & INITIALIZED) + multidecl(gvarname); + nextsym(); + if (level == GLBLEVEL || gvarsc == STATICDECL) + { +#ifndef DIRECTPAGE + dseg(); +#else + if (gvarsymptr->flags & DIRECTPAGE) + dpseg(); + else + dseg(); +#endif + if ((inittype = gvartype)->constructor == ARRAY) + inittype = inittype->nexttype; + newoffset = (dataoffset + ~inittype->alignmask) + & inittype->alignmask; + defnulls(newoffset - dataoffset); + dataoffset = newoffset; + if (gvarsc == STATICDECL) + { + if (level == GLBLEVEL) + private(gvarname); + else + outnlabel(gvarsymptr->offset.offlabel); + } + else + public(gvarname); + initlistflag = TRUE; + if (sym != LBRACE) + initlistflag = FALSE; + inititem(gvartype); + dataoffset += (gvarsymptr->type = gvartype)->typesize; + if (gvarsymptr->level == GLBLEVEL) + gvarsymptr->flags |= INITIALIZED; + if (level != GLBLEVEL) + cseg(); + } + else + { + if (gvarsc == EXTERNDECL) + error("initialization of externs is illegal"); + switch (gvartype->constructor) + { + case ARRAY: + error("initialization of auto arrays is illegal"); + break; + case FUNCTION: + error("initialization of functions is illegal"); + break; + default: + initexpression(gvartype); + break; + } + } + } + else if (level != GLBLEVEL && gvarsc == STATICDECL && + gvartype->constructor != FUNCTION) + { +#ifndef DIRECTPAGE + bssseg(); +#else + if (gvarsymptr->flags & DIRECTPAGE) + dpseg(); + else + dseg(); +#endif + lcommlab(gvarsymptr->offset.offlabel); + outnhex(gvartype->typesize); + cseg(); + } + if (sym != COMMA) + break; + nextsym(); + } + semicolon(); + argsallowed = FALSE; +} + +PRIVATE void initarray(type) +struct typestruct *type; +{ + uoffset_t basesize; + struct typestruct *basetype; + uoffset_t dimension; + char *stringend; + uoffset_t stringlength; + uoffset_t remaining; + + if ((basesize = (basetype = type->nexttype)->typesize) == 0) + dimension = remaining = 0; + else + dimension = remaining = type->typesize / basesize; + if (sym == STRINGCONST && (basetype->scalar & CHAR)) + { + stringlength = (stringend = charptr) - constant.value.s; + if (remaining != 0 && stringlength >= remaining) + /* same dim should be allowed but defstr always nullterms */ + { + error("string longer than dimension"); + stringend = constant.value.s + (/* size_t */ unsigned) + (stringlength = remaining - 1); + } + defstr(constant.value.s, stringend, TRUE); + remaining -= (stringlength + 1); + nextsym(); + } + else + do + inititem(basetype); + while (--remaining != 0 && sym == COMMA && initlistflag && + (nextsym(), sym != RBRACE)); + if (dimension == 0) + { + if (type == gvartype) + gvartype = prefix(ARRAY, -remaining * basesize, basetype); + } + else + defnulls(remaining * basesize); +} + +PRIVATE void inititem(type) +struct typestruct *type; +{ + sym_t startsym; + + if ((startsym = sym) == LBRACE) + nextsym(); + switch (type->constructor) + { + case ARRAY: + initarray(type); + break; + case STRUCTU: + initstruct(type); + break; + case FUNCTION: + error("initialization of functions is illegal"); + break; + default: + initexpression(type); + } + if (startsym == LBRACE) + { + if (sym == COMMA) + { + nextsym(); + if (sym != RBRACE) + error("too many initializers"); + } + rbrace(); + } +} + +PRIVATE void initstruct(type) +struct typestruct *type; +{ + struct typestruct *memtype; + uoffset_t newoffset; + uoffset_t offset; + struct typelist *typelist; + + offset = 0; + if ((typelist = type->listtype) != NULL) + do + { + memtype = typelist->tltype; + newoffset = (offset + ~memtype->alignmask) & memtype->alignmask; + defnulls(newoffset - offset); + offset = newoffset + memtype->typesize; + inititem(memtype); + } + while ((typelist = typelist->tlnext) != NULL && sym == COMMA && + initlistflag && (nextsym(), sym != RBRACE)); + /* eof here will break next time */ + defnulls(type->typesize - offset); +} + +PRIVATE void lbrace() +{ + if (sym != LBRACE) + need('{'); + else + nextsym(); +} + +PUBLIC void lparen() +{ + if (sym != LPAREN) + need('('); + else + nextsym(); +} + +PRIVATE void multidecl(sname) +char *sname; +{ + error2error(sname, " already declared"); +} + +PRIVATE void need(charneeded) +int charneeded; +{ + static char message[] = "need 'x'"; + + message[6] = charneeded; + error(message); +} + +PUBLIC void needvarname() +{ + error("need variable name"); + nextsym(); +} + +PUBLIC void program() +{ + if (orig_cppmode) + cppscan(); + else + { + nextsym(); + while (sym != EOFSYM) + { + declspec(); + idecllist(); + } + } +} + +PUBLIC void rbrace() +{ + if (sym != RBRACE) + need('}'); + else + nextsym(); +} + +PUBLIC void rbracket() +{ + if (sym != RBRACKET) + need(']'); + else + nextsym(); +} + +PRIVATE void rdeclarator() +{ + while (sym == STAR) + { + nextsym(); + gvartype = pointype(gvartype); + } + if (sym == LPAREN) + { + struct typestruct *pretype; + struct typestruct *sufftype; + + nextsym(); + sufftype = gvartype; + gvartype = ctype; + rdeclarator(); + rparen(); + pretype = gvartype; + gvartype = sufftype; + declaf(); + gvartype = chainprefix(pretype, gvartype); + } + else if (sym == IDENT || sym == TYPEDEFNAME) + { + strcpy(gvarname, gsname); + gvarsymptr = gsymptr; + nextsym(); + } + else + { + gvarname[0] = 0; + gvarsymptr = NULL; + } + declaf(); +} + +PRIVATE bool_pt regdecl() +{ + store_t regavail; + +#if !NOTFINISHED + if (gvarsymptr->type->constructor != POINTER) + return FALSE; +#endif +#ifdef MC6809 + if (gvarsymptr->type->constructor != POINTER) + return FALSE; +#endif + if (!(regavail = regregs & ~reguse)) + return FALSE; + gvarsymptr->flags = REGVAR; + gvarsymptr->indcount = 0; +#define LOWBITMASK(bits) (bits - (bits & (bits - 1))) /* & chops low bit */ + reguse |= gvarsymptr->storage = LOWBITMASK(regavail); + return TRUE; +} + +PUBLIC void rparen() +{ + if (sym != RPAREN) + need(')'); + else + nextsym(); +} + +PUBLIC void semicolon() +{ + if (sym != SEMICOLON) + need(';'); + else + nextsym(); +} + +PUBLIC struct typestruct *typename() +{ + char ogvarname[NAMESIZE]; + sym_t ogvarsc; + struct symstruct *ogvarsymptr; + struct typestruct *ogvartype; + struct typestruct *type; + + /* the global variable data must be preserved */ + /* although this is only called for casts and sizeof, */ + /* the casts can be in initialisers */ + /* and the sizeof in an array size expression */ + strcpy(ogvarname, gvarname); + ogvarsc = gvarsc; + ogvarsymptr = gvarsymptr; + ogvartype = gvartype; + if (declspec()) + { + declarator(); + if (gvarsc != NULLDECL || gvarname[0] != 0) + error("illegal type name"); + type = gvartype; + } + else + type = NULL; + strcpy(gvarname, ogvarname); + gvarsc = ogvarsc; + gvarsymptr = ogvarsymptr; + gvartype = ogvartype; + return type; +} diff --git a/bcc-bruce/express.c b/bcc-bruce/express.c new file mode 100644 index 0000000..e6ee64c --- /dev/null +++ b/bcc-bruce/express.c @@ -0,0 +1,466 @@ +/* express.c - expression parsing routines for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "gencode.h" +#include "parse.h" +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "table.h" /* just for charptr for string constant */ +#include "type.h" + +PRIVATE unsigned insizeof; /* nest level for getsizeof */ + /* used to avoid aborting undefined idents */ + /* to 0 when they appear in a cpp expression */ + /* under sizeof */ + +/* names of expression functions are related to the 15 precedence levels */ +/* on p49 of K & R */ + +FORWARD struct nodestruct *cast_exp P((void)); +FORWARD struct nodestruct *exp2 P((void)); +FORWARD struct nodestruct *exp3to12 P((fastin_pt lprecedence)); +FORWARD struct nodestruct *listargs P((void)); +FORWARD struct nodestruct *postfix_exp P((bool_pt seenlp)); +FORWARD struct nodestruct *primary_exp P((void)); +FORWARD struct nodestruct *unary_exp P((void)); + +PRIVATE struct nodestruct *cast_exp() +{ + struct nodestruct *nodeptr; + scalar_t scalar; + struct typestruct *vartype; + + if (sym != LPAREN) + return unary_exp(); + nextsym(); + if ((vartype = typename()) == NULL) + return postfix_exp(TRUE); + rparen(); + scalar = (nodeptr = cast_exp())->nodetype->scalar; + if (vartype->scalar & INT && scalar & (CHAR | SHORT | INT) + && !((vartype->scalar ^ scalar) & UNSIGNED)) + { + nodeptr->flags &= ~LVALUE; + return nodeptr; /* skip casts that are default promotions */ + } + return castnode(vartype, nodeptr); +} + +PUBLIC struct nodestruct *assignment_exp() +{ + struct nodestruct *lhs; + op_pt op; + + lhs = exp2(); + if (sym >= ASSIGNOP && sym <= SUBABOP) /* assign-op syms in order! */ + { + op = sym; + nextsym(); + lhs = node(op, lhs, assignment_exp()); + } + return lhs; +} + +PUBLIC struct nodestruct *expression() +{ + struct nodestruct *lhs; + + lhs = assignment_exp(); + while (sym == COMMA) + { + nextsym(); + lhs = node(COMMAOP, lhs, assignment_exp()); + } + return lhs; +} + +PRIVATE struct nodestruct *exp2() +{ + struct nodestruct *lhs; + struct nodestruct *rhs; + + lhs = exp3to12(0); + if (sym == CONDOP) + { + nextsym(); + rhs = expression(); + colon(); + lhs = node(CONDOP, lhs, node(COLONOP, rhs, exp2())); + } + return lhs; +} + +PRIVATE struct nodestruct *exp3to12(lprecedence) +fastin_pt lprecedence; +{ + struct nodestruct *lhs; + op_pt op; + fastin_t rprecedence; + + lhs = cast_exp(); + while (TRUE) + { + rprecedence = 0; + switch (sym) + { + case LOGOROP: + if ((fastin_t) lprecedence <= 1) + rprecedence = 2; + break; + case LOGANDOP: + if ((fastin_t) lprecedence <= 3) + rprecedence = 4; + break; + case OROP: + if ((fastin_t) lprecedence <= 5) + rprecedence = 6; + break; + case EOROP: + if ((fastin_t) lprecedence <= 7) + rprecedence = 8; + break; + case AMPERSAND: + if ((fastin_t) lprecedence <= 9) + { + sym = ANDOP; + rprecedence = 10; + } + break; + case EQOP: + case NEOP: + if ((fastin_t) lprecedence <= 11) + rprecedence = 12; + break; + case GEOP: + case GTOP: + case LEOP: + case LTOP: + if ((fastin_t) lprecedence <= 13) + rprecedence = 14; + break; + case SLOP: + case SROP: + if ((fastin_t) lprecedence <= 15) + rprecedence = 16; + break; + case HYPHEN: + if ((fastin_t) lprecedence <= 17) + { + sym = SUBOP; + rprecedence = 18; + } + break; + case ADDOP: + if ((fastin_t) lprecedence <= 17) + rprecedence = 18; + break; + case STAR: + if ((fastin_t) lprecedence <= 19) + { + sym = MULOP; + rprecedence = 20; + } + break; + case DIVOP: + case MODOP: + if ((fastin_t) lprecedence <= 19) + rprecedence = 20; + break; + } + if (rprecedence == 0) + break; + op = sym; + nextsym(); + lhs = node(op, lhs, exp3to12(rprecedence)); + } + return lhs; +} + +PRIVATE struct nodestruct *listargs() +{ + struct nodestruct *parent; + struct nodestruct *nextright; + + if (sym == RPAREN) + { + nextsym(); + return NULLNODE; + } + parent = node(arg1op, assignment_exp(), NULLNODE); + nextright = parent; + while (sym == COMMA) + { + nextsym(); + nextright = nextright->right + = node(LISTOP, assignment_exp(), NULLNODE); + } + rparen(); + return parent; +} + +PRIVATE struct nodestruct *postfix_exp(seenlp) +bool_pt seenlp; +{ + struct nodestruct *nodeptr; + struct symstruct *symptr; + + if (seenlp) + { + nodeptr = expression(); + rparen(); + } + else + nodeptr = primary_exp(); + while (TRUE) + { + switch (sym) + { + case DECSYM: + nextsym(); + nodeptr = node(POSTDECOP, nodeptr, NULLNODE); + continue; + case INCSYM: + nextsym(); + nodeptr = node(POSTINCOP, nodeptr, NULLNODE); + continue; + case LBRACKET: + nextsym(); + nodeptr = node(INDIRECTOP, node(ADDOP, nodeptr, expression()), + NULLNODE); + rbracket(); + continue; + case LPAREN: + nextsym(); + nodeptr = node(FUNCOP, nodeptr, listargs()); + { + register struct nodestruct *np; + + for (np = nodeptr->right; np != NULL; np = np->right) + { + if (np->nodetype->scalar & RSCALAR) + { + np = nodeptr->left.nodeptr; + if (np->tag != LEAF) + printf_fp = TRUE; + else + { + unsigned len; + register char *name; + + name = np->left.symptr->name.namep; + if ((len = strlen(name)) >= 6 + && strcmp(name + len - 6, "printf") == 0) + printf_fp = TRUE; + } + break; + } + } + for (np = nodeptr->right; np != NULL; np = np->right) + { + if (np->nodetype->constructor & POINTER + && np->nodetype->nexttype->scalar & RSCALAR) + { + np = nodeptr->left.nodeptr; + if (np->tag != LEAF) + scanf_fp = TRUE; + else + { + unsigned len; + register char *name; + + name = np->left.symptr->name.namep; + if ((len = strlen(name)) >= 5 + && strcmp(name + len - 5, "scanf") == 0) + scanf_fp = TRUE; + } + break; + } + } + } + continue; + case STRUCPTROP: + nodeptr = node(INDIRECTOP, nodeptr, NULLNODE); + case STRUCELTOP: + nextsym(); + gs2name[0] = nodeptr->nodetype->structkey[0]; + gs2name[1] = nodeptr->nodetype->structkey[1]; + if ((gsymptr = findlorg(gs2name)) == NULL) + { + error("undefined structure element"); + gsymptr = addglb(gs2name, itype); + } + symptr = exprsym(gsymptr); + nextsym(); + nodeptr = node(STRUCELTOP, nodeptr, leafnode(symptr)); + continue; + default: + return nodeptr; + } + } +} + +PRIVATE struct nodestruct *primary_exp() +{ + bool_t isdefined; + struct nodestruct *nodeptr; + uoffset_t stringlen; + struct symstruct *symptr; + struct symstruct *symptr1; + bool_t waslparen; + + switch (sym) + { + case IDENT: + if (incppexpr && !insizeof) + { +cpp_ident: + nextsym(); + return leafnode(constsym((value_t) 0)); + } + if ((symptr = gsymptr) != NULL) + nextsym(); + else + { + symptr = addglb(gsname, fitype); + nextsym(); + if (sym != LPAREN) + { + error2error(symptr->name.namea, " undeclared"); + symptr->indcount = 1; + symptr->type = itype; + } + } + symptr1 = exprsym(symptr); + if (symptr->flags & STATIC && symptr->level != GLBLEVEL) + { + symptr1->flags |= LABELLED; + symptr1->offset.offi = 0; + symptr1->name.label = symptr->offset.offlabel; + } + nodeptr = leafnode(symptr1); + if (!(nodeptr->nodetype->constructor & (ARRAY | FUNCTION | VOID))) + nodeptr->flags = LVALUE; + return nodeptr; + case TYPEDEFNAME: + if (incppexpr && !insizeof) + goto cpp_ident; /* else fall through */ + default: + error("bad expression"); + constant.value.v = 0; + constant.type = itype; + case CHARCONST: + case INTCONST: /* this includes enumeration-constants */ + symptr = constsym(constant.value.v); + symptr->type = constant.type; + if (!(ltype->scalar & LONG)) + { + if (symptr->type == ltype) + symptr->type = itype; + else if (symptr->type == ultype) + symptr->type = uitype; + } + nextsym(); + return leafnode(symptr); + case DEFINEDSYM: + waslparen = isdefined = FALSE; + if (!blanksident()) + { + nextsym(); + if (sym != LPAREN) + lparen(); + else + waslparen = TRUE; + } + if (waslparen && !blanksident()) + needvarname(); + else + { + if ((symptr = findlorg(gsname)) != NULL && + symptr->flags == DEFINITION) + isdefined = TRUE; + nextsym(); + } + if (waslparen) + rparen(); + return leafnode(constsym((value_t) isdefined)); + case FLOATCONST: + symptr = constsym((value_t) 0); + symptr->type = constant.type; + symptr->offset.offd = qmalloc(sizeof *symptr->offset.offd); + *symptr->offset.offd = constant.value.d; + nextsym(); + return leafnode(symptr); + case LPAREN: + nextsym(); + nodeptr = expression(); + rparen(); + return nodeptr; + case STRINGCONST: + symptr = constsym((value_t) 0); + symptr->storage = GLOBAL; + symptr->flags = LABELLED | STRING; + /* string length before defstr() or prefix() updates charptr */ + stringlen = charptr - constant.value.s + 1; + symptr->name.label = defstr(constant.value.s, charptr, FALSE); + symptr->type = prefix(ARRAY, stringlen, ctype); + nextsym(); + return leafnode(symptr); + } +} + +PRIVATE struct nodestruct *unary_exp() +{ + value_t size; + struct typestruct *vartype; + + switch (sym) + { + case ADDOP: + nextsym(); + return cast_exp(); + case AMPERSAND: + nextsym(); + return node(ADDRESSOP, cast_exp(), NULLNODE); /* maybe unary_exp */ + case DECSYM: + nextsym(); + return node(PREDECOP, unary_exp(), NULLNODE); + case HYPHEN: + nextsym(); + return node(NEGOP, cast_exp(), NULLNODE); + case INCSYM: + nextsym(); + return node(PREINCOP, unary_exp(), NULLNODE); + case LOGNOTOP: + nextsym(); + return node(LOGNOTOP, cast_exp(), NULLNODE); + case NOTOP: + nextsym(); + return node(NOTOP, cast_exp(), NULLNODE); + case SIZEOFSYM: + nextsym(); + ++insizeof; + if (sym != LPAREN) + size = unary_exp()->nodetype->typesize; + else + { + nextsym(); + if ((vartype = typename()) != NULL) + { + rparen(); + size = vartype->typesize; + } + else + size = postfix_exp(TRUE)->nodetype->typesize; + } + --insizeof; + return leafnode(constsym(size)); + case STAR: + nextsym(); + return node(INDIRECTOP, cast_exp(), NULLNODE); /* maybe unary_exp */ + } + return postfix_exp(FALSE); +} diff --git a/bcc-bruce/exptree.c b/bcc-bruce/exptree.c new file mode 100644 index 0000000..32d9386 --- /dev/null +++ b/bcc-bruce/exptree.c @@ -0,0 +1,1086 @@ +/* exptree.c - expression tree routines for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "byteord.h" +#include "gencode.h" +#include "parse.h" +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "sizes.h" +#include "type.h" + +#define ETREESIZE 1200 +#define errtype itype +#define redtype ctype +#define uredtype uctype + +PRIVATE struct nodestruct etree[ETREESIZE]; /* expression tree */ +PRIVATE struct nodestruct *ettop; + +FORWARD void badlvalue P((struct nodestruct *nodeptr)); +FORWARD void binconvert P((struct nodestruct *nodeptr)); +FORWARD void castiright P((struct nodestruct *nodeptr)); +FORWARD void etreefull P((void)); +FORWARD void fixnode P((struct nodestruct *nodeptr)); +FORWARD bool_pt isconst0 P((struct nodestruct *nodeptr)); +FORWARD bool_pt isnodecharconst P((struct nodestruct *nodeptr)); +FORWARD void needint P((struct nodestruct *nodeptr)); +FORWARD void neednonstruct P((struct nodestruct *nodeptr)); +FORWARD void needscalar P((struct nodestruct *nodeptr)); +FORWARD void needspv P((struct nodestruct *nodeptr)); +FORWARD struct typestruct *nodetype P((struct nodestruct *nodeptr)); +FORWARD int redscalar P((struct nodestruct *nodeptr)); +FORWARD struct nodestruct *unconvert P((struct nodestruct *nodeptr)); + +PRIVATE void badlvalue(nodeptr) +struct nodestruct *nodeptr; +{ + error("invalid lvalue"); + fixnode(nodeptr); +} + +PRIVATE void binconvert(nodeptr) +register struct nodestruct *nodeptr; +{ + bool_t bothscalar; + value_t divisor; + scalar_t lscalar; + register struct nodestruct *right; + scalar_t rscalar; + + rscalar = (right = nodeptr->right)->nodetype->scalar; + lscalar = nodeptr->left.nodeptr->nodetype->scalar; + if ((bothscalar = lscalar | rscalar) & RSCALAR) + { + nodeptr->nodetype = dtype; + if (!(lscalar & DOUBLE)) + nodeptr->left.nodeptr = castnode(dtype, nodeptr->left.nodeptr); + if (!(rscalar & DOUBLE)) + nodeptr->right = castnode(dtype, right); + } + else if (!(bothscalar & DLONG) && (nodeptr->tag == ANDOP && + (redscalar(nodeptr->left.nodeptr) | redscalar(right)) & CHAR || + (nodeptr->tag == EOROP || nodeptr->tag == OROP) && + redscalar(nodeptr->left.nodeptr) & redscalar(right) & CHAR || + nodeptr->tag == MODOP && right->tag == LEAF && + right->left.symptr->storage == CONSTANT && + (divisor = right->left.symptr->offset.offv, + (uvalue_t) divisor <= MAXUCHTO + 1) && + bitcount((uvalue_t) divisor) <= 1)) + { + /* result fits in char and extends correctly */ + if (bothscalar & UNSIGNED) + nodeptr->nodetype = uredtype; + else + nodeptr->nodetype = redtype; + } + else if (bothscalar & LONG) + { + nodeptr->nodetype = ltype; + if (bothscalar & UNSIGNED) + nodeptr->nodetype = ultype; + if (bothscalar & (DLONG | SHORT | INT)) + { + /* XXX - otherwise both are long, or one is long with the same + * size as int and the other is char, and we want the lower level + * routines to handle the char. + */ + if (!(lscalar & LONG)) + nodeptr->left.nodeptr = castnode(nodeptr->nodetype, + nodeptr->left.nodeptr); + if (!(rscalar & LONG)) + nodeptr->right = castnode(nodeptr->nodetype, right); + } + } +#ifdef I8088 + else if (i386_32 && bothscalar & SHORT) + { + nodeptr->nodetype = itype; + if (bothscalar & UNSIGNED) + nodeptr->nodetype = uitype; + if (lscalar & SHORT) + nodeptr->left.nodeptr = castnode(nodeptr->nodetype, + nodeptr->left.nodeptr); + if (rscalar & SHORT) + nodeptr->right = castnode(nodeptr->nodetype, right); + } +#endif + else if (bothscalar & UNSIGNED) + nodeptr->nodetype = uitype; + else + nodeptr->nodetype = itype; +} + +PRIVATE void castiright(nodeptr) +struct nodestruct *nodeptr; +{ + nodeptr->right = castnode(itype, nodeptr->right); +} + +PUBLIC struct nodestruct *castnode(type, nodeptr) +struct typestruct *type; +struct nodestruct *nodeptr; +{ + struct symstruct *symptr; + + (symptr = constsym((value_t) 0))->type = type; + return node(CASTOP, nodeptr, leafnode(symptr)); +} + +PRIVATE void etreefull() +{ + limiterror("expression too complex (1201 nodes)"); +} + +PUBLIC void etreeinit() +{ + ettop = (etptr = etree) + ETREESIZE; +} + +PRIVATE void fixnode(nodeptr) +register struct nodestruct *nodeptr; +{ + nodeptr->tag = LEAF; + nodeptr->flags = nodeptr->weight = 0; + nodeptr->left.symptr = constsym((value_t) 0); /* this has type errtype */ + nodeptr->nodetype = errtype; +} + +PRIVATE bool_pt isconst0(nodeptr) +register struct nodestruct *nodeptr; +{ + register struct symstruct *symptr; + + return nodeptr->tag == LEAF && + (symptr = nodeptr->left.symptr)->storage == CONSTANT && + symptr->offset.offv == 0 && + symptr->type->scalar & ISCALAR; +} + +PRIVATE bool_pt isnodecharconst(nodeptr) +register struct nodestruct *nodeptr; +{ + register struct symstruct *symptr; + + if (nodeptr->tag == LEAF && + (symptr = nodeptr->left.symptr)->storage == CONSTANT && + ischarconst(symptr->offset.offv) && + symptr->type->scalar & ISCALAR) + return TRUE; + return FALSE; +} + +PUBLIC struct nodestruct *leafnode(source) +struct symstruct *source; +{ + register struct nodestruct *leafptr; + + if ((leafptr = etptr++) >= ettop) + etreefull(); + leafptr->tag = LEAF; + leafptr->flags = leafptr->weight = 0; + leafptr->nodetype = source->type; + leafptr->left.symptr = source; + leafptr->right = NULL; + return leafptr; +} + +PRIVATE void needint(nodeptr) +struct nodestruct *nodeptr; +{ + if (!(nodeptr->nodetype->scalar & ISCALAR)) + { + error("need integral type"); + fixnode(nodeptr); + } +} + +PRIVATE void neednonstruct(nodeptr) +struct nodestruct *nodeptr; +{ + if (nodeptr->nodetype->constructor & STRUCTU) + { + error("need non-structure type"); + fixnode(nodeptr); + } +} + +PRIVATE void needscalar(nodeptr) +struct nodestruct *nodeptr; +{ + if (!nodeptr->nodetype->scalar) + { + error("need scalar"); + fixnode(nodeptr); + } +} + +PRIVATE void needspv(nodeptr) +struct nodestruct *nodeptr; +{ + if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION | STRUCTU)) + { + error("need scalar or pointer or void"); + fixnode(nodeptr); + } +} + +PUBLIC struct nodestruct *node(t, p1, p2) +op_pt t; +struct nodestruct *p1; +struct nodestruct *p2; +{ +#if MAXREGS != 1 + weight_t rightweight; +#endif + double dsourceval; + double dtargval; + bool_t lflag; + scalar_t lscalar; + struct nodestruct *pswap; + struct symstruct *source; + value_t sourceval; + struct symstruct *target; + offset_t targszdelta; + value_t targval; + scalar_t rscalar; + bool_t uflag; + + switch ((op_t) t) + { + case ADDABOP: + if (p1->nodetype->constructor & (ARRAY | POINTER)) + t = PTRADDABOP; + break; + case ADDOP: + if (p2->nodetype->constructor & (ARRAY | POINTER)) + { + pswap = p1; + p1 = p2; + p2 = pswap; + } + if (p1->nodetype->constructor & (ARRAY | POINTER)) + t = PTRADDOP; + break; + case CONDOP: + /* Change structs to struct pointers so condop() doesn't have to know + * about structs. + */ + if (p2->nodetype->constructor & STRUCTU) + { + p2 = node(COLONOP, node(ADDRESSOP, p2->left.nodeptr, NULLNODE), + node(ADDRESSOP, p2->right, NULLNODE)); + return node(INDIRECTOP, node(CONDOP, p1, p2), NULLNODE); + } + break; + case FUNCOP: + if (p1->nodetype->constructor & (ARRAY | POINTER)) + p1 = node(INDIRECTOP, p1, NULLNODE); + break; + case SUBABOP: + if (p1->nodetype->constructor & (ARRAY | POINTER)) + { + t = PTRADDABOP; + p2 = node(NEGOP, p2, NULLNODE); + break; + } + case SUBOP: +#if 0 + /* This works but sometimes pessimizes the code by converting small + * constants into large negative constants. It makes the most + * difference for longs by avoiding stack tangles. longop could be + * more careful. Only the case (regpair) - constant is naturally + * tangled. + */ + if (p2->tag == LEAF && p2->nodetype->scalar + && (source = p2->left.symptr)->storage == CONSTANT) + { + if (source->type->scalar & RSCALAR) + *source->offset.offd = -*source->offset.offd; + else + source->offset.offv = -source->offset.offv; + return node((op_t) t == SUBOP ? ADDOP : ADDABOP, p1, p2); + } +#endif + if (p1->nodetype->constructor & (ARRAY | POINTER)) + { + if (p2->nodetype->nexttype == p1->nodetype->nexttype) + t = PTRSUBOP; + else + { + t = PTRADDOP; + p2 = node(NEGOP, p2, NULLNODE); + } + } + break; + } + if (((op_t) t == PTRADDABOP || (op_t) t == PTRADDOP) && + p1->nodetype->nexttype->constructor & (FUNCTION | VOID)) + error("arithmetic on pointer to function or void"); + if (p1->tag != LEAF) + goto node1; + target = p1->left.symptr; + switch ((op_t) t) + { + case ADDRESSOP: + if (target->indcount == 0 && target->flags == REGVAR) + error("register variable addressed"); + else if (target->type->constructor & ARRAY) + { + if (target->indcount != 0) + bugerror("botched array indirection count"); + target->type = pointype(target->type); + } + else if (!(p1->flags & LVALUE)) + badlvalue(p1); + else + { + address(target); /* change p1, no code generated */ + if (target->indcount == 2) /* XXX - MAXINDIRECT? */ + /* just became direct enough */ + p1->weight = 1; + } + p1->flags &= ~LVALUE; + p1->nodetype = target->type; + return p1; + case CASTOP: + needspv(p2); + if (p1->nodetype == p2->nodetype) + { + p1->flags &= ~LVALUE; + return p1; + } + if ((rscalar = p2->nodetype->scalar) & ISCALAR) + neednonstruct(p1); + else if (rscalar & RSCALAR) + needscalar(p1); + else /* POINTER */ + neednonstruct(p1); /* H & S say functions & arrays must match */ + if (((lscalar = p1->nodetype->scalar) | rscalar) & RSCALAR) + { + if (target->storage != CONSTANT) + goto node1; + if (lscalar & RSCALAR && !(rscalar & RSCALAR)) + { + double val; + + val = *target->offset.offd; + if (val > maxlongto) + val -= (double) (unsigned long) 0xFFFFFFFF + 1; /* XXX */ + target->offset.offv = (value_t) val; + } + if (!(lscalar & RSCALAR) && rscalar & RSCALAR) + { + value_t val; + + val = target->offset.offv; + target->offset.offd = qmalloc(sizeof *target->offset.offd); + if (lscalar & UNSIGNED) + *target->offset.offd = (uvalue_t) val; + else + *target->offset.offd = val; + } + } + if (target->storage == CONSTANT) + { + if (rscalar & CHAR) + target->offset.offv &= CHMASKTO; + else if (rscalar & SHORT) + { + target->offset.offv &= shortmaskto; + if (!(rscalar & UNSIGNED) && target->offset.offv > maxshortto) + target->offset.offv -= (maxushortto + 1); + } + else if (rscalar & INT) + { + target->offset.offv &= intmaskto; + if (!(rscalar & UNSIGNED) && target->offset.offv > maxintto) + target->offset.offv -= (maxuintto + 1); + } + else if (rscalar & FLOAT) + *target->offset.offd = (float) *target->offset.offd; + } + else if ((targszdelta = + ((p1->nodetype->constructor & (ARRAY | POINTER)) ? + ptypesize : p1->nodetype->typesize) - + p2->nodetype->typesize) == 0) + ; + else if (target->indcount == 1 && targszdelta > 0 && + target->flags != REGVAR) + { +#if DYNAMIC_LONG_ORDER + if (long_big_endian) +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN +# if BIG_ENDIAN + target->offset.offi += targszdelta; +# else + { + if (lscalar & DLONG) + target->offset.offi += itypesize; /* discard msword */ + } +# endif +#endif +#if DYNAMIC_LONG_ORDER + else +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 +# if BIG_ENDIAN + { + if (rscalar & CHAR) + target->offset.offi += ctypesize; + } +# else + ; +# endif +#endif + } + else + goto node1; + p1->flags &= ~LVALUE; + p1->nodetype = target->type = p2->nodetype; + return p1; + case INDIRECTOP: + if (!(target->type->constructor & (ARRAY | POINTER))) + error("illegal indirection"); + else + { + indirec(target); + if (target->indcount == 3) /* XXX - MAXINDIRECT + 1? */ + /* just became too indirect */ + p1->weight = 1; + p1->flags |= LVALUE; + p1->nodetype = target->type; + } + return p1; + case STRUCELTOP: /* p2 known leaf */ + if (target->indcount != 1) + break; /* struc() would generate code */ + struc(p2->left.symptr, target); + p1->flags |= LVALUE; + p1->nodetype = target->type; + return p1; + } + if (target->indcount != 0) + goto node1; + lscalar = target->type->scalar; + if (target->storage == CONSTANT) + { + if (lscalar & RSCALAR) + dtargval = *target->offset.offd; + else + targval = target->offset.offv; + switch ((op_t) t) + { + case COMMAOP: + return p2; + case CONDOP: + if (lscalar & RSCALAR && dtargval != FALSE + || !(lscalar & RSCALAR) && targval != FALSE) + { + p2->left.nodeptr->nodetype = p2->nodetype; + return p2->left.nodeptr; + } + p2->right->nodetype = p2->nodetype; + return p2->right; + case LOGANDOP: + if (lscalar & RSCALAR && dtargval != FALSE + || !(lscalar & RSCALAR) && targval != FALSE) + break; + p1->nodetype = target->type = itype; + return p1; + case LOGOROP: + if (lscalar & RSCALAR && dtargval == FALSE + || !(lscalar & RSCALAR) && targval == FALSE) + break; + target->offset.offv = TRUE; + p1->nodetype = target->type = itype; + return p1; + } + } + switch ((op_t) t) + { + case COLONOP: + case FUNCOP: + case LISTOP: + case ROOTLISTOP: + goto node1; + case PTRADDOP: + if (p2->tag == LEAF && + (source = p2->left.symptr)->storage == CONSTANT && + source->type->scalar & ISCALAR) + { + indexadr(source, target); + p1->flags &= ~LVALUE; + p1->nodetype = target->type; + return p1; + } + } + if (target->storage != CONSTANT || + !(lscalar & (ISCALAR | RSCALAR)) && (op_t) t != PTRSUBOP || + p2 != NULL && + (p2->tag != LEAF || (source = p2->left.symptr)->storage != CONSTANT || + !((rscalar = source->type->scalar) & (ISCALAR | RSCALAR)) + && (op_t) t != PTRSUBOP)) + goto node1; + lflag = lscalar & LONG; + uflag = lscalar & UNSIGNED; + if (p2 != NULL) + { + if (rscalar & RSCALAR) + dsourceval = *source->offset.offd; + else + { + sourceval = source->offset.offv; + lflag |= rscalar & LONG; + uflag |= rscalar & UNSIGNED; + } + } + if (lscalar & RSCALAR || p2 != NULL && rscalar & RSCALAR) + { + if (!(lscalar & RSCALAR)) + { + if (uflag) + dtargval = (uvalue_t) targval; + else + dtargval = targval; + } + if (p2 != NULL && !(rscalar & RSCALAR)) + { + if (rscalar & UNSIGNED) + dsourceval = (uvalue_t) sourceval; + else + dsourceval = sourceval; + } + switch ((op_t) t) + { + case ADDOP: + dtargval += dsourceval; + break; + case DIVOP: + if (dsourceval == 0) + { + error("divison by 0"); + dsourceval = 1; + } + dtargval /= dsourceval; + break; + case EQOP: + targval = dtargval == dsourceval; + goto intconst; + case GEOP: + targval = dtargval >= dsourceval; + goto intconst; + case GTOP: + targval = dtargval > dsourceval; + goto intconst; + case LEOP: + targval = dtargval <= dsourceval; + goto intconst; + case LOGANDOP: + targval = dtargval && dsourceval; + goto intconst; + case LOGNOTOP: + targval = !dtargval; + goto intconst; + case LOGOROP: + targval = dtargval || dsourceval; + goto intconst; + case LTOP: + targval = dtargval < dsourceval; + goto intconst; + case MULOP: + dtargval *= dsourceval; + break; + case NEGOP: + dtargval = -dtargval; + break; + case NEOP: + targval = dtargval != dsourceval; + goto intconst; + case SUBOP: + dtargval -= dsourceval; + break; + } + /* XXX - leaks memory */ + target->offset.offd = qmalloc(sizeof *target->offset.offd); + *target->offset.offd = dtargval; + p1->nodetype = target->type = dtype; + return p1; + } + switch ((op_t) t) + { + case ADDOP: + targval += sourceval; + break; + case ANDOP: + targval &= sourceval; + break; + case DIVOP: + if (sourceval == 0) + { + error("divison by 0"); + sourceval = 1; + } + if (uflag) + targval = (uvalue_t) targval / sourceval; + else + targval /= sourceval; + break; + case EOROP: + targval ^= sourceval; + break; + case EQOP: + targval = targval == sourceval; + break; + case GEOP: + if (uflag) + targval = (uvalue_t) targval >= sourceval; + else + targval = targval >= sourceval; + goto intconst; + case GTOP: + if (uflag) + targval = (uvalue_t) targval > sourceval; + else + targval = targval > sourceval; + goto intconst; + case LEOP: + if (uflag) + targval = (uvalue_t) targval <= sourceval; + else + targval = targval <= sourceval; + goto intconst; + case LOGANDOP: + targval = targval && sourceval; + goto intconst; + case LOGNOTOP: + targval = !targval; + goto intconst; + case LOGOROP: + targval = targval || sourceval; + goto intconst; + case LTOP: + if (uflag) + targval = (uvalue_t) targval < sourceval; + else + targval = targval < sourceval; + goto intconst; + break; + case MODOP: + if (sourceval == 0) + { + error("modulo by 0"); + sourceval = 1; + } + if (uflag) + targval = (uvalue_t) targval % sourceval; + else + targval %= sourceval; + break; + case MULOP: + targval *= sourceval; + break; + case NEGOP: + targval = -targval; + break; + case NEOP: + targval = targval != sourceval; + goto intconst; + case NOTOP: + targval = ~targval; + break; + case OROP: + targval |= sourceval; + break; + case PTRSUBOP: + if (targval < sourceval) + targval = -((uvalue_t) (sourceval - targval) / + target->type->nexttype->typesize); + else + targval = (uvalue_t) (targval - sourceval) / + target->type->nexttype->typesize; + uflag = FALSE; + break; + case SLOP: + targval <<= sourceval; /* assume shiftcount treated as unsigned */ + lflag = lscalar & LONG; + uflag = lscalar & UNSIGNED; + break; + case SROP: + if (uflag) + targval = (uvalue_t) targval >> sourceval; + else + targval >>= sourceval; + lflag = lscalar & LONG; + uflag = lscalar & UNSIGNED; + break; + case SUBOP: + targval -= sourceval; + break; + } + if (lflag) + { + target->type = ltype; + if (uflag) + target->type = ultype; + } + else + { + targval &= intmaskto; + if (uflag) + target->type = uitype; + else + { + target->type = itype; + if (targval > maxintto) + targval -= (maxuintto + 1); + } + } + target->offset.offv = targval; + p1->nodetype = target->type; + return p1; + +intconst: + target->offset.offv = targval; + p1->nodetype = target->type = itype; + return p1; + +node1: + { + register struct nodestruct *nodeptr; + register struct nodestruct *regp2; + + if ((nodeptr = etptr++) >= ettop) + etreefull(); + regp2 = p2; + nodeptr->tag = t; + nodeptr->left.nodeptr = p1; + nodeptr->right = regp2; + if ((op_t) t == FUNCOP) + nodeptr->weight = MAXREGS + 1; + else + { +#if MAXREGS == 1 + if ((nodeptr->weight = p1->weight) <= MAXREGS && + (regp2 == NULL || + (nodeptr->weight = regp2->weight) < MAXREGS)) + nodeptr->weight = MAXREGS; +#else + nodeptr->weight = p1->weight; + if (regp2 == NULL) + rightweight = 1; /* could do POST-ops with 0 */ + else /* 0 more approp for LIST-ops but 1 OK */ + rightweight = regp2->weight; + if (nodeptr->weight < rightweight) + nodeptr->weight = rightweight; + else if (nodeptr->weight == rightweight && + nodeptr->weight < MAXREGS) + ++nodeptr->weight; +#endif + } + nodeptr->nodetype = nodetype(nodeptr); + return nodeptr; + } +} + +PRIVATE struct typestruct *nodetype(nodeptr) +struct nodestruct *nodeptr; +{ + scalar_t bothscalar; + scalar_t lscalar; + scalar_t rscalar; + struct nodestruct *left; + struct nodestruct *right; + struct typestruct *targtype; + + if (nodeptr->tag == LEAF) + return nodeptr->left.symptr->type; + targtype = (left = nodeptr->left.nodeptr)->nodetype; + right = nodeptr->right; + switch (nodeptr->tag) + { + case FUNCOP: + if (!(targtype->constructor & FUNCTION)) + { + error("call of non-function"); + fixnode(nodeptr); + return errtype; + } + return targtype->nexttype; + case INDIRECTOP: + if (!(targtype->constructor & (ARRAY | POINTER))) + { + error("illegal indirection"); + fixnode(nodeptr); + return errtype; + } + nodeptr->flags |= LVALUE; + return targtype->nexttype; + case LISTOP: + case ROOTLISTOP: + nodeptr->left.nodeptr = unconvert(left); + return promote(targtype); + case CASTOP: + needspv(right); + case COMMAOP: + case CONDOP: + return right->nodetype; + + case STRUCELTOP: + nodeptr->flags |= LVALUE; + return right->nodetype; + + case ADDRESSOP: + if (!(left->flags & LVALUE)) + { + badlvalue(nodeptr); + return errtype; + } + return pointype(targtype); + case LOGNOTOP: + neednonstruct(left); + return redtype; + case NEGOP: + needscalar(left); + return promote(left->nodetype); + case NOTOP: + needint(left); + return promote(left->nodetype); + case PREDECOP: + case PREINCOP: + case POSTDECOP: + case POSTINCOP: + neednonstruct(left); + if (!(left->flags & LVALUE)) + { + badlvalue(nodeptr); + return errtype; + } + break; + + case ANDOP: + case EOROP: + case MODOP: + case OROP: + needint(left); + needint(right); + /* fall through to redundant check and code to cast to same types */ + case ADDOP: + case DIVOP: + case MULOP: + case SUBOP: + needscalar(left); + needscalar(right); + binconvert(nodeptr); + return nodeptr->nodetype; + + case PTRADDABOP: + if (!(left->flags & LVALUE)) + { + badlvalue(nodeptr); + return errtype; + } + case PTRADDOP: /* right type conversion to same size as ptr */ + needint(right); + if (right->nodetype->scalar & LONG) + castiright(nodeptr); + break; + case PTRSUBOP: /* already checked */ + return itype; + case SLOP: /* right type conversion always to int */ + case SROP: /* ulong strictly to unsigned but no matter */ + needint(left); + needint(right); + if (right->nodetype->scalar & LONG) + castiright(nodeptr); + return promote(left->nodetype); + + case LTOP: + case LEOP: + case GTOP: + case GEOP: + case EQOP: + case LOGOROP: + case LOGANDOP: + case NEOP: + neednonstruct(left); + neednonstruct(right); + nodeptr->left.nodeptr = left = unconvert(left); + nodeptr->right = right = unconvert(right); +#ifdef MAYBE_DO_LATER /* OK if pointers fit in uitype */ + if (left->nodetype->constructor & POINTER) + nodeptr->left.nodeptr = left = castnode(uitype, left); + if (right->nodetype->constructor & POINTER) + nodeptr->right = right = castnode(uitype, right); +#endif + binconvert(nodeptr); + return redtype; + + case COLONOP: + if (isnodecharconst(left) && isnodecharconst(right)) + { + targtype = (targtype->scalar | right->nodetype->scalar) & UNSIGNED + ? uctype : ctype; + left = castnode(targtype, left); + right = castnode(targtype, right); + } + nodeptr->left.nodeptr = left = unconvert(left); + nodeptr->right = right = unconvert(right); + if ((targtype = left->nodetype) == right->nodetype) + return targtype; /* XXX - reduced from promote(targtype) */ + if ((lscalar = targtype->scalar) != 0 && + (rscalar = right->nodetype->scalar) != 0) + { + /* promote minimally without using binconvert for char/short */ + if ((bothscalar = lscalar | rscalar) & (LONG | RSCALAR)) + { + binconvert(nodeptr); + return nodeptr->nodetype; + } + if (bothscalar & INT || (lscalar ^ rscalar) & UNSIGNED) + targtype = itype; + else if (bothscalar & SHORT) + targtype = stype; + else + targtype = ctype; + if (bothscalar & UNSIGNED) + targtype = tounsigned(targtype); + if (!(bothscalar & INT) || left->tag == LEAF && lscalar & INT || + right->tag == LEAF && rscalar & INT) + { + /* this is correct even when the if fails (the casts have to */ + /* be considered at a lower level) but gives worse code */ + if (left->nodetype != targtype) + nodeptr->left.nodeptr = castnode(targtype, left); + if (right->nodetype != targtype) + nodeptr->right = castnode(targtype, right); + } + return targtype; /* XXX - reduced from promote(targtype) */ + } + if (targtype->constructor & POINTER && + (isconst0(right) || right->nodetype->constructor & POINTER && + right->nodetype->nexttype->constructor & VOID)) + return targtype; + if (right->nodetype->constructor & POINTER && + (isconst0(left) || targtype->constructor & POINTER && + targtype->nexttype->constructor & VOID)) + return right->nodetype; + error("mismatched types"); + fixnode(left); /* XXX - better to fix the CONDOP */ + fixnode(right); + return errtype; + + case ASSIGNOP: + if (right->nodetype->constructor & VOID) + { + error("assignment of void"); + fixnode(right); + } + if (targtype->constructor & (ARRAY | FUNCTION | VOID)) + { + error("assignment to array, function or void"); + fixnode(nodeptr); + return errtype; + } + if ((targtype->constructor | right->nodetype->constructor) + & STRUCTU && targtype != right->nodetype) + { + error("assignment to/from struct/union of a different type"); + fixnode(nodeptr); + return errtype; + } + if (!(left->flags & LVALUE)) + { + badlvalue(nodeptr); + return errtype; + } +#if 0 + /* XXX - this is done at the lowest levels, with too many chances for + * errors. + */ + if (targtype != right->nodetype) + nodeptr->right = castnode(left->nodetype, right); +#endif + break; + case ANDABOP: + case EORABOP: + case MODABOP: + case ORABOP: + needint(right); + needint(left); + if (!(left->flags & LVALUE)) + { + badlvalue(nodeptr); + return errtype; + } + /* fall through to redundant check and code to cast to same types */ + case ADDABOP: + case SUBABOP: + case DIVABOP: + case MULABOP: + needscalar(right); + needscalar(left); + if (!(left->flags & LVALUE)) + { + badlvalue(nodeptr); + return errtype; + } + rscalar = right->nodetype->scalar; + if ((lscalar = (targtype = left->nodetype)->scalar) & RSCALAR) + { + if (!(rscalar & DOUBLE)) + nodeptr->right = castnode(dtype, right); + } + else if (lscalar & LONG) + { + if (!(rscalar & LONG)) + nodeptr->right = castnode(rscalar & UNSIGNED + ? ultype : targtype, right); + } +#ifdef I8088 + else if (i386_32 && lscalar & INT) + { + if (rscalar & SHORT) + nodeptr->right = castnode(rscalar & UNSIGNED + ? uitype : targtype, right); + } +#endif + break; + case SLABOP: + case SRABOP: + needint(right); + needint(left); + if (!(left->flags & LVALUE)) + { + badlvalue(nodeptr); + return errtype; + } + if (!(right->nodetype->scalar & INT)) + castiright(nodeptr); + break; + } + return left->nodetype; +} + +PRIVATE int redscalar(nodeptr) +register struct nodestruct *nodeptr; +{ + if (isnodecharconst(nodeptr)) + return CHAR; + return nodeptr->nodetype->scalar; +} + +PRIVATE struct nodestruct *unconvert(nodeptr) +struct nodestruct *nodeptr; +{ + if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION)) + return castnode(pointype(nodeptr->nodetype->constructor & ARRAY ? + nodeptr->nodetype->nexttype : + nodeptr->nodetype), nodeptr); + return nodeptr; +} diff --git a/bcc-bruce/floatop.c b/bcc-bruce/floatop.c new file mode 100644 index 0000000..fb9c54d --- /dev/null +++ b/bcc-bruce/floatop.c @@ -0,0 +1,173 @@ +/* floatop.c - software operations on floats and doubles for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "gencode.h" +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "type.h" + +/*----------------------------------------------------------------------------- + f_indirect(target leaf) + make the float or double target indirect if it is not already + return nonzero iff the result is a temp double on the base of the stack +-----------------------------------------------------------------------------*/ + +PUBLIC bool_pt f_indirect(target) +struct symstruct *target; +{ + if (target->indcount == 0) + { + if (target->storage == CONSTANT) + { + /* XXX - more for non-386 */ + if (target->type->scalar & FLOAT) + { + float val; + + val = *target->offset.offd; + push(constsym(((value_t *) &val)[0])); + } + else + { + push(constsym(((value_t *) target->offset.offd)[1])); + push(constsym(((value_t *) target->offset.offd)[0])); + } + } + else if (target->type->scalar & FLOAT) + pushlist(target->storage); /* XXX - floatregs */ + else + pushlist(doubleregs); + onstack(target); + } + return target->flags == TEMP && target->type->scalar & DOUBLE + && target->offset.offi == sp; +} + +/*----------------------------------------------------------------------------- + float1op(operation code, source leaf) + handles all flop unary operations except inc/dec + result is double on stack (or in condition codes for EQOP) +-----------------------------------------------------------------------------*/ + +PUBLIC void float1op(op, source) +op_pt op; +struct symstruct *source; +{ + saveopreg(); + pointat(source); + if ((op_t) op == NEGOP) + call("Fneg"); + else /* op == EQOP */ + call("Ftst"); + outntypechar(source->type); + if ((op_t) op != EQOP) + justpushed(source); + restoreopreg(); +} + +/*----------------------------------------------------------------------------- + floatop(operation code, source leaf, target leaf) + handles all flop binary operations + result is double on stack (or in condition codes for EQOP) +----------------------------------------------------------------------------*/ + +PUBLIC void floatop(op, source, target) +op_pt op; +struct symstruct *source; +struct symstruct *target; +{ + store_t regmark; + bool_t sflag; + + regmark = reguse; + saveopreg(); + (void) f_indirect(source); + if (!(reguse & OPREG) && (source->storage == OPREG)) + { + reguse |= source->storage; + saveopreg(); + } + fpush(target); + sflag = TRUE; + if (source->flags != TEMP || source->offset.offi != sp + dtypesize) + { + sflag = FALSE; + if (source->storage == OPREG) + restoreopreg(); + pointat(source); + } + switch ((op_t) op) + { + case ADDOP: + call("Fadd"); + break; + case DIVOP: + call("Fdiv"); + break; + case EQOP: + call("Fcomp"); + sp += dtypesize; /* target is popped */ + break; /* target symbol now invalid but is not used */ + case MULOP: + call("Fmul"); + break; + case SUBOP: + call("Fsub"); + break; + } + if (sflag) + { + outnl(); + sp += dtypesize; /* source is popped */ + } + else + outntypechar(source->type); + onstack(target); + reguse = regmark; /* early so opreg is not reloaded if source */ + restoreopreg(); +} + +/*----------------------------------------------------------------------------- + fpush(source leaf of scalar type) + converts source to double and pushes it to stack + OPREG must be free +-----------------------------------------------------------------------------*/ + +PUBLIC void fpush(source) +struct symstruct *source; +{ + scalar_t scalar; + + if ((scalar = source->type->scalar) & RSCALAR) + { + if (f_indirect(source)) + return; + pointat(source); + } + else if (scalar & DLONG) + load(source, OPREG); + else + load(source, DREG); + call("Fpush"); + if (scalar & UNSIGNED) + outbyte('u'); + outntypechar(source->type); + justpushed(source); +} + +/*----------------------------------------------------------------------------- + justpushed(target leaf) + records that target has just been pushed to a double on the stack +-----------------------------------------------------------------------------*/ + +PUBLIC void justpushed(target) +struct symstruct *target; +{ + sp -= dtypesize; + onstack(target); + target->type = dtype; +} diff --git a/bcc-bruce/function.c b/bcc-bruce/function.c new file mode 100644 index 0000000..1d48a19 --- /dev/null +++ b/bcc-bruce/function.c @@ -0,0 +1,413 @@ +/* function.c - function call protocol for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "align.h" +#include "byteord.h" +#include "gencode.h" +#include "parse.h" +#include "reg.h" +#include "sc.h" +#include "table.h" +#include "type.h" + +#ifdef I8088 +# define ADJUSTLONGRETURN +# define CANHANDLENOFRAME +# undef CANHANDLENOFRAME +# define STUPIDFRAME +#endif + +FORWARD void out_callstring P((void)); + +/* call a named (assembly interface) procedure, don't print newline after */ + +PUBLIC void call(name) +char *name; +{ + out_callstring(); + outstr(name); +} + +PUBLIC void function(source) +struct symstruct *source; +{ + if (source->indcount == 0 && source->storage == GLOBAL && + !(source->flags & LABELLED) && *source->name.namep != 0) + { + out_callstring(); + outnccname(source->name.namep); + } + else + { +#ifdef XENIX_AS + if (source->indcount == 0) /* fix call fixed address */ + out_callstring(); + else +#endif + outcalladr(); +#ifdef MC6809 + if (source->indcount == 1) + ++source->indcount; /* fake for outadr */ +#endif + outadr(source); + } + source->type = source->type->nexttype; +#ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */ + if (source->type->scalar & DLONG) + { +# ifdef ADJUSTLONGRETURN +# if DYNAMIC_LONG_ORDER + if (long_big_endian) +# endif +# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN + { + regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2); + regexchange(LONGREG2, DXREG); + } +# endif +# if DYNAMIC_LONG_ORDER + else +# endif +# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 + regtransfer(DXREG, LONGRETURNREGS & ~LONGREG2); +# endif +# endif + source->storage = LONGRETURNREGS & ~LONGREG2; + } + else +#endif + if (source->type->scalar & CHAR) + { +#if RETURNREG != DREG + transfer(source, DREG); +#endif + source->storage = BREG; + } + else if (source->type->scalar & DOUBLE) + source->storage = doublreturnregs & ~DREG; +#if 0 + else if (source->type->scalar & FLOAT) + source->storage = floatreturnregs /* XXX? & ~DREG */; +#endif + else + source->storage = RETURNREG; + source->offset.offi = source->indcount = 0; + if (source->level == OFFKLUDGELEVEL) + source->level = EXPRLEVEL; + if (source->type->constructor & STRUCTU) + { + transfer(source, getindexreg()); /* so it can be indirected + * and/or preserved in blockmove() */ + source->indcount = 1; + source->flags = TEMP; /* kludge so blockpush can be avoided */ + } +} + +PUBLIC void ldregargs() +{ + register struct symstruct *symptr; + store_pt targreg; + struct symstruct temptarg; + + for (symptr = &locsyms[0]; symptr < locptr && symptr->level == ARGLEVEL; + symptr = (struct symstruct *) + align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) + { + if ((store_t) (targreg = symptr->storage) & allregs) + { + + /* load() is designed to work on expression symbols, so don't + * trust it on reg variables although it almost works. + */ + temptarg = *symptr; + if (arg1inreg && symptr == &locsyms[0]) + { + temptarg.storage = ARGREG; + temptarg.offset.offi = 0; + } + else + { + temptarg.storage = LOCAL; + temptarg.indcount = 1; + } + load(&temptarg, targreg); + symptr->offset.offi = 0; + } + } + regarg = FALSE; +} + +PUBLIC void loadretexpression() +{ + if (returntype->constructor & STRUCTU) + { + struct nodestruct *etmark; + struct nodestruct *exp; + struct symstruct *exprmark; + struct symstruct *structarg; + + etmark = etptr; + exprmark = exprptr; + exp = expression(); + makeleaf(exp); + structarg = constsym((value_t) 0); + structarg->type = pointype(returntype); + onstack(structarg); + indirec(structarg); + structarg->flags = 0; /* assign() doesn't like TEMP even for indir */ + structarg->offset.offi = returnadrsize; + assign(exp->left.symptr, structarg); + etptr = etmark; + exprptr = exprmark; + } +#ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */ + else if (returntype->scalar & DLONG) + { + loadexpression(LONGRETURNREGS & ~LONGREG2, returntype); +# ifdef ADJUSTLONGRETURN +# if DYNAMIC_LONG_ORDER + if (long_big_endian) +# endif +# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN + { + regexchange(LONGREG2, DXREG); + regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2); + } +# endif +# if DYNAMIC_LONG_ORDER + else +# endif +# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 + regtransfer(LONGRETURNREGS & ~LONGREG2, DXREG); +# endif +# endif + } + else +#endif + if (returntype->scalar & DOUBLE) + loadexpression(doublreturnregs & ~DREG, returntype); +#if 0 + else if (returntype->scalar & FLOAT) + loadexpression(floatreturnregs /* XXX? & ~DREG */, returntype); +#endif + else + loadexpression(RETURNREG, returntype); +} + +PUBLIC void listo(target, lastargsp) +struct symstruct *target; +offset_t lastargsp; +{ + extend(target); + push(target); + if (lastargsp != 0 && sp != lastargsp - target->type->typesize) + { + loadany(target); + modstk(lastargsp); + push(target); + if (sp != lastargsp - target->type->typesize) + { + bugerror("botched push of arg"); +#ifdef DEBUG + outstr("arg type is "); + dbtype(target->type); + outnl(); +#endif + } + } +} + +PUBLIC void listroot(target) +struct symstruct *target; +{ + extend(target); + /* necessary regs are free since they were saved for function */ + if (target->type->scalar & DLONG) + load(target, LONGARGREGS & ~LONGREG2); + else + load(target, ARGREG); +} + +PRIVATE void out_callstring() +{ + outop3str(callstring); +#ifdef I8088 + if (i386_32) + bumplc2(); +#endif +} + +#ifdef FRAMEPOINTER + +PUBLIC void popframe() +{ + poplist(frame1list); +} + +#endif + +/* reserve storage for locals if necessary */ +/* also push 1st function arg and load register args if necessary */ + +PUBLIC void reslocals() +{ +#ifdef FRAMEPOINTER +# ifndef STUPIDFRAME + bool_t loadframe = FALSE; + +# endif +#endif + + if (switchnow != NULL) + { +#ifdef FRAMEPOINTER + if (framep == 0 && softsp != sp) + bugerror("local variables in switch statement messed up, sorry"); +#else + if (sp != softsp) + bugerror("local variables in switch statement don't work, sorry"); +#endif + if (lowsp > softsp) + lowsp = softsp; + sp = softsp; + return; + } +#ifdef FRAMEPOINTER + if (framep == 0) + { +# ifdef STUPIDFRAME + pushreg(FRAMEREG); + regtransfer(STACKREG, FRAMEREG); + framep = sp; + pushlist(callee1mask); +# else /* not STUPIDFRAME */ +# ifdef CANHANDLENOFRAME + if (stackarg || softsp != -frameregsize) /* args or locals */ +# endif + { + pushlist(frame1list); + loadframe = TRUE; + } +# endif /* not STUPIDFRAME */ + } +#else + if (sp == 0) + pushlist(callee1mask); +#endif /* FRAMEPOINTER */ + if (arg1size) + { + switch ((fastin_t) arg1size) + { + case 8: + pushlist(doubleargregs); + break; + case 4: +# ifdef I8088 + if (!i386_32) +# endif + { + pushlist(LONGARGREGS); + break; + } + case 2: +# ifdef I8088 + pushlist(ARGREG); +# endif +# ifdef MC6809 + switch (sp - softsp) + { + case 3: + pushlist(LOC1REGS | ARGREG); + break; + case 4: + pushlist(LOC2REGS | ARGREG); + break; + case 5: + pushlist(LOC3REGS | ARGREG); + break; + case 6: + pushlist(LOC4REGS | ARGREG); + break; + default: + pushlist(ARGREG); + break; + } +# endif /* MC6809 */ + } + arg1size = 0; /* show 1st arg allocated */ + } +#ifdef FRAMEPOINTER +# ifndef STUPIDFRAME /* else this moved above for compat with Xenix cc frame */ + if (loadframe || softsp != -frameregsize) + modstk(softsp); + /* else avoid modstk() because softsp holds space for frame pointer only) */ + /* but pointer has not been pushed (must keep softsp for later levels) */ + if (loadframe) + { + regtransfer(STACKREG, FRAMEREG); + framep = sp; + } +# else /* STUPIDFRAME */ + modstk(softsp); +# endif /* STUPIDFRAME */ +#else /* no FRAMEPOINTER */ + modstk(softsp); +#endif /* FRAMEPOINTER */ + if (regarg) + ldregargs(); +} + +/* clean up stack and return from a function */ + +PUBLIC void ret() +{ +#ifdef FRAMEPOINTER + offset_t newsp; + + if (framep != 0) + { + newsp = -(offset_t) func1saveregsize; + if (switchnow != NULL || newsp - sp >= 0x80) + changesp(newsp, TRUE); + else + modstk(newsp); + popframe(); + } + outreturn(); +#else /* no FRAMEPOINTER */ +# ifdef MC6809 + store_pt reglist; + + switch (sp) + { + case -1: + reglist = JUNK1REGS | PCREG; + break; + case -2: + reglist = JUNK2REGS | PCREG; + break; + case -3: + reglist = JUNK3REGS | PCREG; + break; + case -4: + reglist = JUNK4REGS | PCREG; + break; + default: + modstk(0); + outreturn(); + return; + } + poplist(reglist); +#else + if (sp != 0) + { + modstk(-(offset_t) func1saveregsize); + poplist(callee1mask); + } + outreturn(); +# endif /* no MC6809 */ +#endif /* no FRAMEPOINTER */ +} diff --git a/bcc-bruce/gencode.c b/bcc-bruce/gencode.c new file mode 100644 index 0000000..55f36df --- /dev/null +++ b/bcc-bruce/gencode.c @@ -0,0 +1,736 @@ +/* gencode.c - generate code for an expression tree for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#define islvalop(op) \ + ((op) >= ASSIGNOP && (op) <= SUBABOP || (op) == PTRADDABOP) + +#include "const.h" +#include "types.h" +#include "align.h" +#include "condcode.h" +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "type.h" + +#undef EXTERN +#define EXTERN +#include "gencode.h" +#include "sizes.h" + +#define FIRSTOPDATA GTOP + +#if MAXINDIRECT <= 1 +# define istooindirect(t) ((t)->indcount > MAXINDIRECT) +#else +# define istooindirect(t) ((t)->indcount >= MAXINDIRECT && \ + ((t)->indcount > MAXINDIRECT || \ + (t)->type->typesize > maxregsize || \ + (t)->type->constructor & FUNCTION)) +#endif + +#ifdef I8088 +#if NOTFINISHED +PUBLIC store_pt allregs = BREG | DREG | DATREG1 | DATREG2 + | INDREG0 | INDREG1 | INDREG2; +#else +PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2; +#endif +PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2; +PUBLIC uoffset_t alignmask = ~(uoffset_t) 0x0001; +PUBLIC bool_t arg1inreg = FALSE; +PUBLIC store_pt calleemask = INDREG1 | INDREG2; +PUBLIC bool_t callersaves = FALSE; +PUBLIC char *callstring = "call\t"; +PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2; +PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2; +PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2; +PUBLIC offset_t jcclonger = 3; +PUBLIC offset_t jmplonger = 1; +PUBLIC char *jumpstring = "br \t"; +PUBLIC char *regpulllist = "f2ax2ax2bx2si2di2bp2qx2qx2cx2dx2"; +PUBLIC char *regpushlist = "dx2cx2qx2qx2bp2di2si2bx2ax2ax2f2"; +#if NOTFINISHED +PUBLIC store_pt regregs = INDREG1 | INDREG2 | DATREG1 | DATREG2; +#else +PUBLIC store_pt regregs = INDREG1 | INDREG2; +#endif + +PUBLIC char *acclostr = "al"; +PUBLIC char *accumstr = "ax"; +PUBLIC char *badregstr = "qx"; +PUBLIC char *dreg1str = "cx"; +PUBLIC char *dreg1bstr = "cl"; +PUBLIC char *dreg2str = "dx"; +PUBLIC char *ireg0str = "bx"; +PUBLIC char *ireg1str = "si"; +PUBLIC char *ireg2str = "di"; +#ifdef FRAMEPOINTER +PUBLIC char *localregstr = "bp"; +#else +PUBLIC char *localregstr = "sp"; +#endif +PUBLIC char *stackregstr = "sp"; +#endif + +#ifdef MC6809 +PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2; +PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2; +PUBLIC uoffset_t alignmask = ~(uoffset_t) 0x0000; +PUBLIC bool_t arg1inreg = TRUE; +PUBLIC store_pt calleemask = INDREG1 | INDREG2; +PUBLIC bool_t callersaves = TRUE; +PUBLIC char *callstring = "JSR\t>"; +PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2; +PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2; +PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2; +PUBLIC offset_t jcclonger = 2; +PUBLIC offset_t jmplonger = 1; +PUBLIC char *jumpstring = "JMP\t>"; +PUBLIC char *regpulllist = "CC1B1D2X2U2Y2DP1PC2"; +PUBLIC char *regpushlist = "PC2DP1Y2U2X2D2B1CC1"; +PUBLIC store_pt regregs = INDREG1 | INDREG2; + +PUBLIC char *acclostr = "B"; +PUBLIC char *accumstr = "D"; +PUBLIC char *badregstr = "Q"; +PUBLIC char *ireg0str = "X"; +PUBLIC char *ireg1str = "U"; +PUBLIC char *ireg2str = "Y"; +PUBLIC char *localregstr = "S"; +#endif + +PUBLIC uoffset_t accregsize = 2; +#ifdef FRAMEPOINTER +PUBLIC uoffset_t frameregsize = 2; +#endif +PUBLIC uoffset_t maxregsize = 2; +PUBLIC uoffset_t opregsize = 2; +PUBLIC uoffset_t pshregsize = 2; +PUBLIC uoffset_t returnadrsize = 2; + +#ifndef MC6809 +PUBLIC uvalue_t intmaskto = 0xFFFFL; +PUBLIC uvalue_t maxintto = 0x7FFFL; +PUBLIC uvalue_t maxlongto = 0x7FFFFFFFL; +PUBLIC uvalue_t maxoffsetto = 0x7FFFL; +PUBLIC uvalue_t maxshortto = 0x7FFFL; +PUBLIC uvalue_t maxuintto = 0xFFFFL; +PUBLIC uvalue_t maxushortto = 0xFFFFL; +PUBLIC uvalue_t shortmaskto = 0xFFFFL; +#endif + +PRIVATE store_pt callermask; +PRIVATE offset_t lastargsp; + +PRIVATE smalin_t opdata[] = +{ +/* GTOP, LTOP, ADDOP, DIVOP, */ + GT, LT, 0, 0, +/* MODOP, LOGNOTOP, NOTOP, STRUCELTOP, */ + 0, 0, 0, 0, +/* STRUCPTROP, ASSIGNOP, ADDABOP, ANDABOP, */ + 0, 0, 0, ANDOP, +/* DIVABOP, EORABOP, MODABOP, MULABOP, */ + DIVOP, EOROP, MODOP, MULOP, +/* ORABOP, SLABOP, SRABOP, SUBABOP, */ + OROP, SLOP, SROP, 0, +/* COMMAOP, COLONOP, LOGOROP, LOGANDOP, */ + 0, 0, 0, 0, +/* EQOP, NEOP, GEOP, LEOP, */ + EQ, NE, GE, LE, +}; + +FORWARD void abop P((op_pt op, struct symstruct *source, + struct symstruct *target)); +FORWARD void smakeleaf P((struct nodestruct *exp)); +FORWARD void tcheck P((struct nodestruct *exp)); + +PRIVATE void abop(op, source, target) +op_pt op; +struct symstruct *source; +struct symstruct *target; +{ + store_pt regmark; + store_pt regpushed; + store_pt regtemp; + struct symstruct temptarg; + + regpushed = preslval(source, target); + temptarg = *target; + if ((source->type->scalar ^ target->type->scalar) & (DLONG | RSCALAR) + && op != SLABOP && op != SRABOP) /* XXX - perhaps not float */ + { + pres2(target, source); + cast(source->type, &temptarg); + } + switch (op) + { + case ADDABOP: + add(source, &temptarg); + break; + case ANDABOP: + case EORABOP: + case ORABOP: + op1((opdata - FIRSTOPDATA)[op], source, &temptarg); + break; + case DIVABOP: + case MODABOP: + case MULABOP: + case SLABOP: + case SRABOP: + softop((opdata - FIRSTOPDATA)[op], source, &temptarg); + break; + case PTRADDABOP: + regtemp = 0; + if ((reguse & allindregs) == allindregs) + { + /* free a temporary index not used for source or target */ + + regmark = reguse; + reguse = source->storage | temptarg.storage; + pushreg(regtemp = getindexreg()); + reguse = regmark & ~regtemp; + } + indexadr(source, &temptarg); + if (regtemp) + { + load(&temptarg, DREG); + recovlist(regtemp); + } + break; + case SUBABOP: + sub(source, &temptarg); + break; + } + assign(&temptarg, target); + recovlist(regpushed); +} + +PUBLIC void bileaf(exp) +struct nodestruct *exp; +{ + bool_t commutop; + bool_t tookaddress; + store_t regmark; + struct nodestruct *indchase; + struct nodestruct *left; + struct nodestruct *right; + struct symstruct *source; + struct symstruct *target; + + left = exp->left.nodeptr; + if ((right = exp->right) == NULL) + { + makeleaf(left); +#ifdef DEBUG + debug(exp); +#endif + return; + } + switch (exp->tag) + { + case ADDOP: + case ANDOP: + case EOROP: + case OROP: + case EQOP: + case NEOP: + case MULOP: + commutop = TRUE; + break; + case FUNCOP: + makeleaf(left); + if ((target = left->left.symptr)->storage & allregs + && right->tag != LEAF && target->flags != REGVAR) + { + if (target->indcount == 0) + push(target); + else + { + --target->indcount; + push(target); + ++target->indcount; + } + } + default: + commutop = FALSE; + break; + } + regmark = reguse; + if (right->tag != LEAF) + { + if (left->tag != LEAF && commutop && left->weight > right->weight) + { + exp->left.nodeptr = right; + right = exp->right = left; + left = exp->left.nodeptr; +#ifdef DEBUG + debugswap(); +#endif + } + makeleaf(right); + } + else if (left->tag != LEAF) + makeleaf(left); + source = right->left.symptr; + if (left->tag != LEAF) + { + for (indchase = left; + indchase->tag == INDIRECTOP || indchase->tag == STRUCELTOP; + indchase = indchase->left.nodeptr) + ; + tookaddress = FALSE; + if (source->storage & allindregs || indchase->tag != LEAF) + { + if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP) + { + address(source); + tookaddress = TRUE; + } + if (source->storage & allindregs && source->indcount == 0 && + (source->type->scalar & (DLONG | RSCALAR) || + left->tag == FUNCOP && source->flags != REGVAR)) + push(source); /* XXX - perhaps not float */ + else + preserve(source); + } + makeleaf(left); + if (tookaddress) + indirec(source); + } + target = left->left.symptr; + if (istooindirect(source)) + { + /* want to makelessindirect(source) */ + /* this uses source->storage if that is a free index */ + /* otherwise, must preserve target if that is an index */ + + tookaddress = FALSE; + if (!(source->storage & ~reguse & allindregs) && + target->storage & allindregs) + { + /* want to pres2(source, target) */ + /* this requires target to be < MAXINDIRECT indirect */ + /* it is safe to makelessindirect(target) */ + /* since source is not a free index */ + + if (islvalop(exp->tag) && target->indcount != 0) + { + address(target); + tookaddress = TRUE; + } + if (istooindirect(target)) + makelessindirect(target); + pres2(source, target); + } + makelessindirect(source); + if (tookaddress) + indirec(target); + } + if (istooindirect(target)) + { + tookaddress = FALSE; + if (!(target->storage & ~reguse & allindregs) && + source->storage & allindregs) + { + if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP) + { + address(source); + tookaddress = TRUE; + } + pres2(target, source); + } + makelessindirect(target); + if (tookaddress) + indirec(source); + } + reguse = regmark; +#ifdef DEBUG + debug(exp); +#endif + if (commutop + && (target->storage == CONSTANT + && !(target->type->scalar & (DLONG | RSCALAR)) + || source->storage & ALLDATREGS + || source->type->scalar & (DLONG | RSCALAR) + && source->indcount == 0 && target->indcount != 0)) + { + exp->left.nodeptr = right; + exp->right = left; +#ifdef DEBUG + debugswap(); +#endif + } +} + +PUBLIC fastin_pt bitcount(number) +register uvalue_t number; +{ + register fastin_pt count; + + for (count = 0; number != 0; number >>= 1) + if (number & 1) + ++count; + return count; +} + +PUBLIC void codeinit() +{ +#ifdef I8088 + if (i386_32) + { + /* Need DATREG2 for doubles although handling of extra data regs is + * not finished. + * XXX - might need more regs for 16-bit mode doubles or floats. + */ + allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2 + | DATREG1 | DATREG1B | DATREG2; +#if NOTFINISHED + allindregs = INDREG0 | INDREG1 | INDREG2 | DATREG1 | DATREG2; +#else + allindregs = INDREG0 | INDREG1 | INDREG2; +#endif + alignmask = ~(uoffset_t) 0x00000003; + calleemask = INDREG0 | INDREG1 | INDREG2; + doubleargregs = DREG | DATREG2; + doubleregs = DREG | DATREG2; + doublreturnregs = DREG | DATREG2; + jcclonger = 4; + jmplonger = 3; + regpulllist = "fd4eax4eax4ebx4esi4edi4ebp4qx4qx4ecx4edx4"; + regpushlist = "edx4ecx4qx4qx4ebp4edi4esi4ebx4eax4eax4fd4"; + + accumstr = "eax"; + dreg1str = "ecx"; + dreg2str = "edx"; + ireg0str = "ebx"; + ireg1str = "esi"; + ireg2str = "edi"; +#ifdef FRAMEPOINTER + localregstr = "ebp"; +#else + localregstr = "esp"; +#endif + stackregstr = "esp"; + + opregsize = + returnadrsize = + pshregsize = + maxregsize = +#ifdef FRAMEPOINTER + frameregsize = +#endif + accregsize = 4; + + intmaskto = (unsigned long) 0xFFFFFFFFL; + maxintto = 0x7FFFFFFFL; + maxoffsetto = 0x7FFFFFFFL; + maxuintto = (unsigned long) 0xFFFFFFFFL; + } +#endif +#ifdef POSINDEPENDENT + if (posindependent) + { +# ifdef MC6809 + callstring = "LBSR\t"; + jumpstring = "LBRA\t"; +# endif + } +#endif + if (callersaves) + calleemask = 0; + callermask = ~calleemask; +#ifdef FRAMEPOINTER + funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize + + frameregsize; + funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs) + * maxregsize + frameregsize; + framelist = FRAMEREG | calleemask; +#else + funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize; + funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs) + * maxregsize; +#endif +} + +PUBLIC fastin_pt highbit(number) +register uvalue_t number; +{ + register fastin_pt bit; + + for (bit = -1; number != 0; number >>= 1) + ++bit; + return bit; +} + +PUBLIC void makeleaf(exp) +struct nodestruct *exp; +{ + ccode_t condtrue; + op_pt op; + store_t regmark; + offset_t saveargsp; + store_t savelist; + offset_t saveoffset; + struct symstruct *source; + offset_t spmark; + struct symstruct *structarg; + struct symstruct *target; + + if ((op_t) (op = exp->tag) == LEAF) + { + target = exp->left.symptr; + if (istooindirect(target)) + makelessindirect(target); +#ifdef SELFTYPECHECK + tcheck(exp); +#endif + return; + } + if ((op_t) op == INDIRECTOP || (op_t) op == STRUCELTOP) + { + smakeleaf(exp); + target = exp->left.symptr; + if (istooindirect(target)) + makelessindirect(target); +#ifdef SELFTYPECHECK + tcheck(exp); +#endif + return; + } + if ((op_t) op == COMMAOP) + { + spmark = sp; + makeleaf(exp->left.nodeptr); + modstk(spmark); + makeleaf(exp->right); + exp->tag = LEAF; + exp->left.symptr = exp->right->left.symptr; +#ifdef SELFTYPECHECK + tcheck(exp); +#endif + return; + } + if ((op_t) op == CONDOP) + { + condop(exp); +#ifdef SELFTYPECHECK + tcheck(exp); +#endif + return; + } + if ((op_t) op == LOGANDOP || (op_t) op == LOGNOTOP + || (op_t) op == LOGOROP) + { + logop(exp); +#ifdef SELFTYPECHECK + tcheck(exp); +#endif + return; + } + regmark = reguse; + if ((op_t) op == FUNCOP) + { + saveargsp = lastargsp; + lastargsp = savelist = 0; + if (exp->nodetype->constructor & STRUCTU) + { + modstk(sp - (offset_t) exp->nodetype->typesize); + onstack(structarg = constsym((value_t) 0)); + } + else + { + if (exp->nodetype->scalar & DOUBLE) + { + if (regmark & doublreturnregs) + savelist = doublreturnregs; + } + else if (regmark & RETURNREG) + savelist = exp->nodetype->scalar & DLONG + ? LONGRETURNREGS : RETURNREG; + if (savelist != 0) + modstk(saveoffset = sp - exp->nodetype->typesize); + } + pushlist(regmark & callermask); + } + spmark = sp; + bileaf(exp); + if (exp->right != NULL) + source = exp->right->left.symptr; + else + source = NULL; + target = exp->left.nodeptr->left.symptr; + switch ((op_t) op) + { + case ADDABOP: + case ANDABOP: + case DIVABOP: + case EORABOP: + case SUBABOP: + case MODABOP: + case MULABOP: + case ORABOP: + case PTRADDABOP: + case SLABOP: + case SRABOP: + abop(op, source, target); + break; + case ADDOP: + add(source, target); + break; + case ADDRESSOP: + address(target); + break; + case ANDOP: + case EOROP: + case OROP: + op1(op, source, target); + break; + case ASSIGNOP: + assign(source, target); + break; + case CASTOP: + cast(source->type, target); + break; + case DIVOP: + case MODOP: + case MULOP: + case SLOP: + case SROP: + softop(op, source, target); + break; + case EQOP: + case GEOP: + case GTOP: + case LEOP: + case LTOP: + case NEOP: + condtrue = (opdata - FIRSTOPDATA)[op]; + cmp(source, target, &condtrue); + break; + case FUNCOP: + /* kludge update pushed regs */ + /* may only work for si, di */ + /* -2 skips for ax and bx */ + /* need dirtymask to mostly avoid this */ + savereturn(regmark & callermask & regregs, + spmark - 2 * (offset_t) pshregsize); + if (exp->nodetype->constructor & STRUCTU) + { + address(structarg); + push(structarg); + } + function(target); + break; + case INDIRECTOP: + indirec(target); + break; + case LISTOP: + listo(target, lastargsp); + lastargsp = sp; + break; + case NEGOP: + neg(target); + break; + case NOTOP: + not(target); + break; + case POSTDECOP: + case POSTINCOP: + case PREDECOP: + case PREINCOP: + incdec(op, target); + break; + case PTRADDOP: + indexadr(source, target); + break; + case PTRSUBOP: + ptrsub(source, target); + break; + case ROOTLISTOP: + listroot(target); + lastargsp = sp; + break; + case STRUCELTOP: + struc(source, target); + break; + case SUBOP: + sub(source, target); + break; + } + if (target->storage == LOCAL && target->offset.offi < spmark && + target->flags == TEMP) + spmark = target->offset.offi; +#if 1 /* XXX - why does sp get changed without this? */ + if ((op_t) op != ROOTLISTOP) +#endif + modstk(spmark); + if ((op_t) op == FUNCOP) + { + lastargsp = saveargsp; + if (savelist != 0) + { + savereturn(savelist, saveoffset); + onstack(target); + target->offset.offi = saveoffset; + } + recovlist(regmark & callermask); + } + reguse = regmark; + exp->tag = LEAF; + exp->left.symptr = target; + if (istooindirect(target)) + makelessindirect(target); +#ifdef SELFTYPECHECK + tcheck(exp); +#endif +} + +PRIVATE void smakeleaf(exp) +struct nodestruct *exp; +{ + struct nodestruct *left; + + left = exp->left.nodeptr; + if (left->tag == INDIRECTOP || left->tag == STRUCELTOP) + smakeleaf(left); + else if (left->tag != LEAF) + makeleaf(left); + if (exp->tag == INDIRECTOP) + indirec(left->left.symptr); + else + { + if (left->left.symptr->indcount > MAXINDIRECT + 1) + makelessindirect(left->left.symptr); + struc(exp->right->left.symptr, left->left.symptr); + } + exp->tag = LEAF; + exp->left.symptr = left->left.symptr; +} + +#ifdef SELFTYPECHECK + +PRIVATE void tcheck(exp) +register struct nodestruct *exp; +{ + register struct symstruct *target; + + if (exp->nodetype != (target = exp->left.symptr)->type) + { + { + bugerror("botched nodetype calculation"); +#ifdef DEBUG + comment(); + outstr("runtime type is "); + dbtype(target->type); + outstr(", calculated type is "); + dbtype(exp->nodetype); + outnl(); +#endif + } + } +} + +#endif /* SELFTYPECHECK */ diff --git a/bcc-bruce/gencode.h b/bcc-bruce/gencode.h new file mode 100644 index 0000000..370817a --- /dev/null +++ b/bcc-bruce/gencode.h @@ -0,0 +1,101 @@ +/* gencode.h - code generation for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#ifdef MC6809 +# define CANABXCUTOFF 7 /* favour ABX over MUL before this */ +#endif +#define EXPRLEVEL 126 /* level for symbols in exptree, > real levs */ +#define OFFKLUDGELEVEL 127 /* level for expr sym with offset from name */ +#define OPERANDSEPARATOR ',' /* char separating operands */ +#define OPSEPARATOR '\t' /* char separating op string and operand */ + +EXTERN uoffset_t arg1size; /* size of 1st arg to function */ + /* zero after allocation of 1st arg */ +EXTERN store_pt callee1mask; /* calleemask with doubleregs masked if nec */ +EXTERN uoffset_t dataoffset; /* amount of initialized data so far */ +#ifdef DEBUG +EXTERN bool_t debugon; /* nonzero to print debugging messages */ + /* depends on zero init */ +#endif +#ifdef FRAMEPOINTER +EXTERN store_pt framelist; /* bit pattern for frame and saved regs */ +EXTERN store_pt frame1list; /* framelist with doubleregs masked if nec */ +EXTERN offset_t framep; /* hardware relative frame ptr */ +#endif +EXTERN uoffset_t func1saveregsize; /* choice of next two values */ +EXTERN uoffset_t funcdsaveregsize; /* funcsaveregsize adjusted for doubles */ +EXTERN uoffset_t funcsaveregsize; /* tot size of framelist/calleemask regs */ +#ifdef I8088 +EXTERN bool_t i386_32; /* nonzero to generate 386 32 bit code */ + /* depends on zero init */ +#endif +#ifdef DYNAMIC_LONG_ORDER +EXTERN bool_t long_big_endian; /* nonzero if high long word is first */ + /* depends on zero init */ +#endif +EXTERN offset_t lowsp; /* low water sp (collects locals in switch) */ +#ifdef POSINDEPENDENT +EXTERN bool_t posindependent; /* nonzero to generate pos-independent code */ + /* depends on zero init */ +#endif +EXTERN bool_t printf_fp; /* nonzero if *printf called with FP arg */ +EXTERN bool_t regarg; /* nonzero to show unloaded register arg */ + /* depends on zero init */ +EXTERN store_t reguse; /* registers in use */ +EXTERN bool_t scanf_fp; /* nonzero if *scanf called with ptr-to-FP */ +EXTERN offset_t softsp; /* software sp (leads sp during declares) */ +EXTERN offset_t sp; /* hardware relative stack ptr */ + /* depends on zero init */ +#ifdef FRAMEPOINTER +EXTERN bool_t stackarg; /* nonzero to show function has arg on stack */ +#endif +EXTERN struct switchstruct *switchnow; /* currently active switch */ + /* depends on NULL init */ + +/* variables to be initialised to nonzero */ + +extern store_pt allindregs; /* mask (in) for index registers */ +extern store_pt allregs; /* mask (in) for registers */ +extern bool_t arg1inreg; /* nonzero to pass 1st arg in reg */ +extern store_pt calleemask; /* mask (in) for regs to be saved by callee */ +extern bool_t callersaves; /* nonzero to make caller save regs */ +extern char *callstring; /* opcode string for call */ +extern store_pt doubleargregs; /* mask (in) for regs for 1st arg if double */ +extern store_pt doubleregs; /* mask (in) for regs to temp contain double */ +extern store_pt doublreturnregs; /* mask (in) for regs for returning double */ +extern offset_t jcclonger; /* amount jcc long jumps are longer */ +extern offset_t jmplonger; /* amount long jumps is longer */ +extern char *jumpstring; /* opcode string for jump */ +extern char *regpulllist; /* reg names and sizes (0 store_t bit first) */ +extern char *regpushlist; /* reg names and sizes (0 store_t bit last) */ +extern store_pt regregs; /* mask (in) for regs which can be reg vars */ + +/* register names */ + +extern char *acclostr; +extern char *accumstr; +extern char *badregstr; +#ifdef I8088 +extern char *dreg1str; +extern char *dreg1bstr; +extern char *dreg2str; +#endif +extern char *ireg0str; +extern char *ireg1str; +extern char *ireg2str; +extern char *localregstr; +#ifdef I8088 +extern char *stackregstr; +#endif + +/* register sizes */ + +extern uoffset_t accregsize; +#ifdef FRAMEPOINTER +extern uoffset_t frameregsize; +#endif +extern uoffset_t maxregsize; +extern uoffset_t opregsize; +extern uoffset_t pshregsize; +extern uoffset_t returnadrsize; diff --git a/bcc-bruce/genloads.c b/bcc-bruce/genloads.c new file mode 100644 index 0000000..9e4f6be --- /dev/null +++ b/bcc-bruce/genloads.c @@ -0,0 +1,1254 @@ +/* genloads.c - generate loads of registers and memory for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "byteord.h" +#include "condcode.h" +#include "gencode.h" +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "sizes.h" +#include "type.h" + +FORWARD void badaddress P((void)); +FORWARD void blockpush P((struct symstruct *source)); +FORWARD void loadadr P((struct symstruct *source, store_pt targreg)); +FORWARD void loadlongindirect P((struct symstruct *source, store_pt targreg)); +FORWARD void outnamoffset P((struct symstruct *adr)); +FORWARD void outnnadr P((struct symstruct *adr)); +FORWARD fastin_pt pushpull P((store_pt reglist, bool_pt pushflag)); + +PUBLIC void addoffset(source) +struct symstruct *source; +{ +#ifdef I8088 + if (source->level == OFFKLUDGELEVEL) + { + outadd(); + outregname(source->storage); + outcomma(); + outnamoffset(source); + outnl(); + if (source->storage & (AXREG | ALREG)) + unbumplc(); + if (source->level == OFFKLUDGELEVEL) + source->level = EXPRLEVEL; + source->offset.offi = 0; + } + else +#endif + if (source->offset.offi != 0) + { + addconst(source->offset.offi, source->storage); + source->offset.offi = 0; + } +} + +PUBLIC void address(source) +struct symstruct *source; +{ + if (source->indcount == 0) + bugerror("taking address of non-lvalue"); + else + { + if (source->type->constructor & (ARRAY | FUNCTION)) + bugerror("botched indirect array or function"); + else if (--source->indcount == 0 && source->storage == GLOBAL && + !(source->flags & LABELLED) && *source->name.namep == 0) + source->storage = CONSTANT; + source->type = pointype(source->type); + } +} + +PRIVATE void badaddress() +{ + bugerror("bad address"); +} + +PRIVATE void blockpush(source) +struct symstruct *source; +{ + struct symstruct *length; + offset_t spmark; + uoffset_t typesize; + + typesize = source->type->typesize; + length = constsym((value_t) typesize); + length->type = uitype; + address(source); + modstk(spmark = sp - (offset_t) typesize); +#ifdef STACKREG + regtransfer(STACKREG, DREG); +#else +#ifdef MC6809 /* XXX ? */ + regtransfer(LOCAL, DREG); +#else +#include "need STACKREG and stackregstr" +#endif +#endif + push(length); + push(source); + pushreg(DREG); + call("_memcpy"); + outnl(); + modstk(spmark); + indirec(source); +} + +PUBLIC void exchange(source, target) +struct symstruct *source; +struct symstruct *target; +{ + store_t tempreg; + + regexchange(source->storage, target->storage); + tempreg = target->storage; + target->storage = source->storage; + source->storage = tempreg; +} + +/*----------------------------------------------------------------------------- + getindexreg() + returns the "best" available index register +-----------------------------------------------------------------------------*/ + +PUBLIC store_pt getindexreg() +{ + if (!(reguse & INDREG0)) + return INDREG0; + if (!(reguse & INDREG1)) + return INDREG1; + if (!(reguse & INDREG2)) + return INDREG2; +#if NOTFINISHED +#ifdef I8088 + if (i386_32) + { + if (!(reguse & DATREG1)) + return DATREG1; + if (!(reguse & DATREG2)) + return DATREG2; + } +#endif +#endif + bugerror("out of index regs"); + return 0; +} + +/*----------------------------------------------------------------------------- + indexadr(index leaf, pointer leaf) + is used by the index and add and subtract (pointer) routines + it handles expressions like + pointer + index + &array[index] + the target becomes register direct with offset + (except for index = 0, when nothing is changed) + constant indexes are optimised by leaving them as offsets + register direct pointers are optimised by leaving the offset alone + (except for PC register direct, since there is no LEAX D,PC) +-----------------------------------------------------------------------------*/ + +PUBLIC void indexadr(source, target) +struct symstruct *source; +struct symstruct *target; +{ +#ifdef MC6809 + bool_t canABX; +#endif + uoffset_t size; + store_pt sourcereg; + struct typestruct *targtype; + store_pt targreg; + + if (!(target->type->constructor & (ARRAY | POINTER))) + { + bugerror("cannot index"); + return; + } + size = target->type->nexttype->typesize; + if (source->storage == CONSTANT) + { + if (source->offset.offv != 0) + { + if (target->indcount != 0) + loadany(target); + target->offset.offi += source->offset.offv * size; + } + return; + } + if (target->storage & ALLDATREGS) + push(target); + if ((store_t) (sourcereg = target->storage) & ~reguse & allindregs) + targreg = sourcereg; + else + targreg = getindexreg(); +#ifdef I8088 + if ((store_t) sourcereg == GLOBAL && target->indcount == 0 && + !(source->type->scalar & CHAR) && source->storage != DREG) + load(source, targreg); + else +#endif + load(source, DREG); + +#ifdef I8088 + softop(MULOP, constsym((value_t) size), source); +#endif +#ifdef MC6809 + +/*----------------------------------------------------------------------------- + do some calculations in advance to decide if index can be done with ABX +-----------------------------------------------------------------------------*/ + + if ((store_t) targreg == XREG && source->type->scalar & CHAR && + size < CANABXCUTOFF) + canABX = TRUE; + else + { + canABX = FALSE; + softop(MULOP, constsym((value_t) size), source); + } + +#endif + +/*----------------------------------------------------------------------------- + deal with constant target - constant becomes offset, result in DREG +-----------------------------------------------------------------------------*/ + + if (target->storage == CONSTANT) + { + target->storage = DREG; + return; + } + +/*----------------------------------------------------------------------------- + load target if it is indirect or GLOBAL or canABX so D or B can be added + otherwise, it is register direct (maybe S register, maybe with offset) + and the offset can be left after adding DREG +-----------------------------------------------------------------------------*/ + +#ifdef I8088 + if (target->indcount != 0) + { + targtype = target->type; + target->type = itype; + add(source, target); + target->type = targtype; + return; + } + if ((store_t) sourcereg == GLOBAL) + { + target->storage = source->storage; + target->level = OFFKLUDGELEVEL; + return; + } +#endif +#ifdef MC6809 + if (canABX || (store_t) sourcereg == GLOBAL) + { + load(target, targreg); + sourcereg = targreg; + } + else if (target->indcount != 0) + { + targtype = target->type; + target->type = itype; + add(source, target); + target->type = targtype; + return; + } + if (canABX) + while (size--) + outABX(); + else +#endif + { +#ifdef I8088 + if ((store_t) targreg != (store_t) sourcereg) + regtransfer(sourcereg, targreg); + outadd(); + outregname(targreg); + outncregname(DREG); +#endif +#ifdef MC6809 + outlea(); + outregname(targreg); + outtab(); + outregname(DREG); + outncregname(sourcereg); +#endif + } + if ((store_t) sourcereg == LOCAL) +#ifdef FRAMEPOINTER + target->offset.offi -= framep; +#else + target->offset.offi -= sp; +#endif + target->storage = targreg; +} + +PUBLIC void indirec(source) +struct symstruct *source; +{ + if (!(source->type->constructor & (ARRAY | POINTER))) + bugerror("illegal indirection"); + else if (source->indcount == (indn_t) - 1) + limiterror("too many indirections (256)"); + else + { + if (source->storage & ALLDATREGS) + transfer(source, getindexreg()); + if (!((source->type = source->type->nexttype)->constructor & + (ARRAY | FUNCTION))) + ++source->indcount; + if (source->storage == CONSTANT) + source->storage = GLOBAL; + } +} + +/*----------------------------------------------------------------------------- + load(source leaf, target register) + loads the specified register without changing any others (except CC) + if the type is long or float, DREG is paired with the target register + the result has no offset +-----------------------------------------------------------------------------*/ + +PUBLIC void load(source, targreg) +struct symstruct *source; +store_pt targreg; +{ + if (source->type->scalar & DLONG) + { + if (source->storage == CONSTANT) + loadreg(source, targreg); + else if (source->indcount == 0) + { +#if DYNAMIC_LONG_ORDER + if (!long_big_endian) +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 + { + if ((store_t) targreg == DREG) + source->storage = DREG; + } +#endif + if (source->storage != (store_t) targreg) + transfer(source, targreg); + if (source->offset.offi != 0) + bugerror("loading direct long with offset not implemented"); + } + else + loadlongindirect(source, targreg); + } + else if (source->type->scalar & DOUBLE) + { + if (source->storage == targreg && source->indcount == 0) + return; + if (source->storage == CONSTANT) + { + /* XXX - more for non-386 */ + loadconst(((offset_t *) source->offset.offd)[0], DREG); + loadconst(((offset_t *) source->offset.offd)[1], targreg); + } + else + { + push(source); + poplist(targreg | DREG); /* actually it's the full reg list */ + } + source->storage = targreg; /* XXX - multi for non-386 */ + source->indcount = 0; + source->flags = 0; + if (source->level == OFFKLUDGELEVEL) + source->level = EXPRLEVEL; + source->offset.offi = 0; + } + else if (source->type->scalar & FLOAT && source->storage == CONSTANT) + { + float val; + + val = *source->offset.offd; + loadconst(((offset_t *) &val)[0], targreg); + } + else if (source->indcount == 0 && source->storage != CONSTANT) + loadadr(source, targreg); + else if (source->type->scalar || + source->type->constructor & (ARRAY | POINTER)) + loadreg(source, targreg); + else + bugerror("attempting to load non-scalar non-pointer"); +} + +PRIVATE void loadadr(source, targreg) +struct symstruct *source; +store_pt targreg; +{ + if ((store_t) targreg & ALLDATREGS) + { + if (source->storage == GLOBAL) + { +#ifdef MC6809 + if (posindependent) + { + pushreg(INDREG0); + loadreg(source, INDREG0); + transfer(source, DREG); + recovlist(INDREG0); + } + else +#endif + loadreg(source, targreg); + } + if (source->storage == LOCAL) +#ifdef FRAMEPOINTER + source->offset.offi -= framep; +#else + source->offset.offi -= sp; +#endif + if (source->type->scalar & CHAR) + targreg = BREG; +#ifdef I8088 + if (source->storage == DREG) + addoffset(source); +#endif + if (source->storage != (store_t) targreg) + transfer(source, targreg); + addoffset(source); + } + else if (source->storage & ALLDATREGS) + { + addoffset(source); + transfer(source, targreg); + } + else if (source->storage != (store_t) targreg || + source->offset.offi != 0 || source->level == OFFKLUDGELEVEL) + loadreg(source, targreg); +} + +PUBLIC void loadany(source) +struct symstruct *source; +{ + if (source->indcount != 0 || source->offset.offi != 0 || /* kludge u cmp */ + source->level == OFFKLUDGELEVEL || !(source->storage & allregs)) + { + if (source->type->scalar & RSCALAR) + load(source, doubleregs & ~DREG); + else if (source->storage == CONSTANT && !(source->type->scalar & DLONG) + || source->type->scalar & CHAR) + load(source, DREG); + else if (source->storage & ~reguse & allregs) + load(source, source->storage); + else if (((reguse & allindregs) == allindregs || + !(source->type->constructor & (ARRAY | POINTER)) && + source->indcount != 0) && + !(source->type->scalar & DLONG)) + load(source, DREG); + else + load(source, getindexreg()); + } +} + +PRIVATE void loadlongindirect(source, targreg) +struct symstruct *source; +store_pt targreg; +{ + sc_t flags; + offset_t offset; + store_t reg; + struct typestruct *type; + + if (source->level == OFFKLUDGELEVEL) + addoffset(source); /* else kludge is lost and offsets big */ + flags = source->flags; + offset = source->offset.offi; + reg = source->storage; + type = source->type; + source->type = itype; + loadreg(source, DREG); + source->flags = flags; + source->storage = reg; + source->indcount = 1; + source->offset.offi = offset + accregsize; + loadreg(source, targreg); + source->type = type; +} + +PUBLIC void loadreg(source, targreg) +struct symstruct *source; +store_pt targreg; +{ + offset_t longhigh; + offset_t longlow; + + if (source->storage == CONSTANT) + { + if (source->type->scalar & CHAR && (store_t) targreg & ALLDATREGS) + targreg = BREG; + longlow = (offset_t) source->offset.offv; + if (source->type->scalar & DLONG) + { + longlow &= (offset_t) intmaskto; + longhigh = (offset_t) (source->offset.offv >> INT16BITSTO) + & (offset_t) intmaskto; + if ((store_t) targreg != LONGREG2) /* loading the whole long */ + { +#if DYNAMIC_LONG_ORDER + if (long_big_endian) +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN + loadconst(longhigh, DREG); +#endif +#if DYNAMIC_LONG_ORDER + else +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 + { + loadconst(longlow, DREG); + longlow = longhigh; + } +#endif + } + } + loadconst(longlow, targreg); + source->storage = targreg; + source->offset.offi = 0; + } + else + { +#ifdef I8088 + if (source->indcount == 0 && source->storage != GLOBAL && + (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL)) + { + if ((store_t) targreg == source->storage) + { + addoffset(source); + return; + } + source->indcount = 1; /* fake for outadr() to produce "()" */ + outlea(); + } + else + { + outload(); + if (source->storage == GLOBAL && source->indcount != 0 && + (store_t) targreg & (AXREG | ALREG)) + unbumplc(); + } +#endif +#ifdef MC6809 + if (source->indcount == 0 && + (source->storage != GLOBAL || posindependent)) + outlea(); + else + { + outload(); + if ((store_t) targreg == YREG) + bumplc(); + } +#endif + movereg(source, targreg); + } +} + +PUBLIC void makelessindirect(source) +struct symstruct *source; +{ + store_pt lreg; + + if (!((store_t) (lreg = source->storage) & ~reguse & allindregs)) + lreg = getindexreg(); + while (source->indcount > MAXINDIRECT) + loadreg(source, lreg); +#if MAXINDIRECT > 1 + if (source->indcount == MAXINDIRECT && + (source->type->typesize > maxregsize || + source->type->constructor & FUNCTION)) + { + source->indcount = 1; + loadreg(source, lreg); + source->indcount = 1; + } +#endif +} + +PUBLIC void movereg(source, targreg) +struct symstruct *source; +store_pt targreg; +{ + if ((store_t) targreg & ALLDATREGS && source->type->scalar & CHAR) + targreg = BREG; +#ifdef I8088 + if (i386_32 && source->type->scalar & SHORT && + source->indcount <= 1) + { + outshortregname(targreg); + bumplc(); + } + else +#endif + outregname(targreg); + if (source->storage == CONSTANT) + adjlc((offset_t) source->offset.offv, targreg); +#ifdef I8088 + outcomma(); +#endif + outadr(source); + source->storage = targreg; /* in register for further use */ + source->flags = 0; + if (source->level == OFFKLUDGELEVEL) + source->level = EXPRLEVEL; + source->offset.offi = 0; /* indcount was adjusted by outadr */ +} + +PUBLIC void onstack(target) +register struct symstruct *target; +{ + target->storage = LOCAL; + target->flags = TEMP; + if (target->level == OFFKLUDGELEVEL) + target->level = EXPRLEVEL; + target->indcount = 1; + target->offset.offi = sp; +} + +PUBLIC void outadr(adr) +struct symstruct *adr; +{ + outnnadr(adr); + outnl(); +} + +PUBLIC void outcregname(reg) +store_pt reg; +{ + outcomma(); + outregname(reg); +} + +PRIVATE void outnamoffset(adr) +struct symstruct *adr; +{ + outimmed(); + if (adr->flags & LABELLED) + outlabel(adr->name.label); + else + outccname(adr->name.namep); + if (adr->offset.offi != 0) + { + if (adr->offset.offi > 0) + outplus(); + outshex(adr->offset.offi); + } + bumplc2(); +#ifdef I8088 + if (i386_32) + bumplc2(); +#endif +} + +/* print comma, then register name, then newline */ + +PUBLIC void outncregname(reg) +store_pt reg; +{ + outcomma(); + outnregname(reg); +} + +PRIVATE void outnnadr(adr) +struct symstruct *adr; +{ + bool_t indflag; + + indflag = FALSE; +#ifdef I8088 + if (adr->indcount >= MAXINDIRECT) + indflag = TRUE; +#endif +#ifdef MC6809 + outtab(); + if (adr->indcount >= MAXINDIRECT && (adr->indcount & 1) == 0) + { + indflag = TRUE; /* indirection means double indirect */ + outindleft(); + } +#endif + switch (adr->storage) + { + case CONSTANT: + outimmadr((offset_t) adr->offset.offv); + break; +#ifdef I8088 + case DREG: + if (indflag || adr->offset.offi != 0 || adr->level == OFFKLUDGELEVEL) + badaddress(); + else + outregname(DREG); + break; +#endif +#ifdef I8088 + case DATREG1: + case DATREG2: + if (indflag && !i386_32) + { + outnl(); + badaddress(); + break; + } +#endif + case INDREG0: + case INDREG1: + case INDREG2: + if (adr->level == OFFKLUDGELEVEL) + outnamoffset(adr); +#ifndef MC6809 + else if (adr->offset.offi != 0) +#endif + outoffset(adr->offset.offi); +#ifdef I8088 + if (indflag) + outindleft(); + outregname(adr->storage); +# ifdef XENIX_AS + if (indflag) + outindright(); +# endif +#endif +#ifdef MC6809 + if (indflag && adr->offset.offi != 0 && is5bitoffset(adr->offset.offi)) + bumplc(); + outcregname(adr->storage); +#endif + break; + case LOCAL: +#ifdef I8088 +# ifdef FRAMEPOINTER + if (framep == 0) + bugerror("no frame pointer"); + if (indflag) + { + if (adr->offset.offi == framep) + bumplc(); + else + { + if (switchnow != NULL && adr->flags == TEMP) + outswoffset(adr->offset.offi); + else + outoffset(adr->offset.offi - framep); + } + outindleft(); + } + else if (adr->offset.offi != framep) + badaddress(); + outregname(LOCAL); +# else + if (indflag) + { + bumplc(); + if (adr->offset.offi != sp) + outoffset(adr->offset.offi - sp); + outindleft(); + } + else if (adr->offset.offi != sp) + badaddress(); + outregname(LOCAL); +# endif /* FRAMEPOINTER */ +# ifdef XENIX_AS + if (indflag) + outindright(); +# endif +#endif /* I8088 */ +#ifdef MC6809 + if (adr->flags == TEMP && adr->offset.offi == sp && + adr->indcount == 1) + { + outcregname(LOCAL); + outplus(); + ++sp; + if (adr->type->typesize != 1) + { + outplus(); + ++sp; + } + break; + } + outoffset(adr->offset.offi - sp); + if (indflag && adr->offset.offi != sp && + is5bitoffset(adr->offset.offi - sp)) + bumplc(); + outcregname(LOCAL); +#endif /* MC6809 */ + break; + case GLOBAL: +#ifdef I8088 + bumplc(); + if (i386_32) + bumplc2(); + if (!indflag) + outimmed(); + else + { +# ifndef XENIX_AS + outindleft(); +# endif + bumplc(); + } +#endif +#ifdef MC6809 + if (!posindependent) + { + if (adr->indcount == 0) + { + outimmed(); + bumplc(); + } + else if (indflag) + { + outextended(); + bumplc2(); + } + else if (adr->flags & DIRECTPAGE) + outdirectpage(); + else + { + outextended(); + bumplc(); + } + } +#endif + if (adr->flags & LABELLED) + outlabel(adr->name.label); + else if (*adr->name.namep == 0) /* constant address */ + { + outhex((uoffset_t) adr->offset.offi); + break; + } + else + outccname(adr->name.namep); + if (adr->offset.offi != 0) + { + if (adr->offset.offi > 0) + outplus(); + outshex(adr->offset.offi); + } +#ifdef MC6809 + if (posindependent) + { + outcregname(GLOBAL); + bumplc2(); + } +#endif + break; + default: + outnl(); + badaddress(); + break; + } +#ifdef I8088 + if (indflag) + { + --adr->indcount; +# ifndef XENIX_AS + outindright(); +# endif + } +#endif +#ifdef MC6809 + if (indflag) + { + outindright(); + adr->indcount -= MAXINDIRECT; + } + else if (adr->indcount != 0) + --adr->indcount; +#endif +} + +/* print register name, then newline */ + +PUBLIC void outnregname(reg) +store_pt reg; +{ + outregname(reg); + outnl(); +} + +/* print register name */ + +PUBLIC void outregname(reg) +store_pt reg; +{ + switch ((store_t) reg) + { + case BREG: + outstr(acclostr); + break; + case DREG: + outstr(accumstr); + break; +#ifdef MC6809 + case GLOBAL: + outstr("PC"); + break; +#endif + case INDREG0: + outstr(ireg0str); + break; + case INDREG1: + outstr(ireg1str); + break; + case INDREG2: + outstr(ireg2str); + break; + case LOCAL: + outstr(localregstr); + break; +#ifdef STACKREG + case STACKREG: + outstr(stackregstr); + break; +#endif +#ifdef DATREG1 + case DATREG1: + outstr(dreg1str); + break; +#endif +#ifdef DATREG1B + case DATREG1B: + outstr(dreg1bstr); + break; +#endif +#ifdef DATREG2 + case DATREG2: + outstr(dreg2str); + break; +#endif + default: + outstr(badregstr); + break; + } +} + +#ifdef I8088 +/* print register name for short type */ + +PUBLIC void outshortregname(reg) +store_pt reg; +{ + switch ((store_t) reg) + { + case DREG: + outstr(accumstr + 1); + break; + case INDREG0: + outstr(ireg0str + 1); + break; + case INDREG1: + outstr(ireg1str + 1); + break; + case INDREG2: + outstr(ireg2str + 1); + break; + case DATREG1: + outstr(dreg1str + 1); + break; + case DATREG2: + outstr(dreg2str + 1); + break; + default: + outstr(badregstr); + break; + } +} + +#endif + +/*----------------------------------------------------------------------------- + pointat(target leaf) + point OPREG at target + target must be singly indirect or float or double +-----------------------------------------------------------------------------*/ + +PUBLIC void pointat(target) +struct symstruct *target; +{ + if (target->type->scalar & RSCALAR) + (void) f_indirect(target); + address(target); + load(target, OPREG); + target->type = target->type->nexttype; +} + +PUBLIC void poplist(reglist) +store_pt reglist; +{ + if (reglist) + sp += pushpull(reglist, FALSE); +} + +PUBLIC void push(source) +struct symstruct *source; +{ + store_t reg; +#ifdef I8088 + uoffset_t size; +#endif + scalar_t sscalar; + + if (source->type->constructor & STRUCTU) + { + if (source->flags != TEMP) /* TEMP must be from last function */ + blockpush(source); + } + else if ((sscalar = source->type->scalar) & RSCALAR) + { + if (!f_indirect(source)) + { + saveopreg(); + fpush(source); + restoreopreg(); + } + } +#ifdef I8088 + else if (source->indcount == 1 && + (sscalar & (SHORT | INT | LONG | FLOAT) || + source->type->constructor & POINTER) || + source->storage == CONSTANT && i386_32) + { + size = source->type->typesize; + if (size == 1) + size = 2; + if (sscalar & DLONG) + { + source->offset.offi += itypesize; + outpshs(); + bumplc(); + outtab(); + outadr(source); + source->indcount = 1; + source->offset.offi -= itypesize; + } + outpshs(); + bumplc(); + outtab(); + if (i386_32) + { + if (source->storage == CONSTANT) + { + unbumplc(); + adjlc((offset_t) source->offset.offv, INDREG0); + } + if (size == 2) + { + outword(); + bumplc(); + } + else + outdword(); + } + outadr(source); + sp -= size; + } +#endif + else + { + reg = source->storage; + loadany(source); + if (sscalar & DLONG) + pushlist(DREG | source->storage); + else if (sscalar & CHAR) + pushchar(); + else + pushreg(source->storage); + if (source->flags != REGVAR) + reguse &= ~(reg | source->storage); + } + onstack(source); +} + +PUBLIC void pushlist(reglist) +store_pt reglist; +{ + if ((store_t) reglist) + sp -= pushpull(reglist, TRUE); +} + +PRIVATE fastin_pt pushpull(reglist, pushflag) +store_pt reglist; +bool_pt pushflag; +{ + store_pt lastregbit; + void (*ppfunc) P((void)); + char *regptr; + +#ifdef MC6809 + int separator; /* promoted char for output */ + +#endif + fastin_t bytespushed; + store_pt regbit; + + if ((bool_t) pushflag) + { + ppfunc = outpshs; +#ifdef I8088 + regbit = 1 << 10; +#else + regbit = 1 << 7; +#endif + regptr = regpushlist; + lastregbit = 1; + } + else + { + ppfunc = outpuls; + regbit = 1; + regptr = regpulllist; +#ifdef I8088 + lastregbit = 1 << 10; +#else + lastregbit = 1 << 7; +#endif + } +#ifdef MC6809 /* temp use pull strings to keep old order */ + regbit = 1; + regptr = regpulllist; + lastregbit = 1 << 7; +#endif +#ifdef MC6809 + separator = OPSEPARATOR; + (*ppfunc) (); +#endif + bytespushed = 0; + while (TRUE) + { + if (regbit & reglist) + { +#ifdef I8088 + (*ppfunc)(); + if (*regptr != FLAGSREGCHAR) + outtab(); +#endif +#ifdef MC6809 + outbyte(separator); +#endif + do + outbyte(*regptr++); + while (*regptr >= MINREGCHAR); + bytespushed += *regptr++ - '0'; +#ifdef I8088 + outnl(); +#endif +#ifdef MC6809 + separator = OPERANDSEPARATOR; +#endif + } + else + do + ; + while (*regptr++ >= MINREGCHAR); + if (regbit == lastregbit) + break; +#ifdef MC6809 /* temp use pull strings to keep old order */ + regbit <<= 1; +#else /* this should normally be unconditional */ + if ((bool_t) pushflag) + regbit >>= 1; + else + regbit <<= 1; +#endif + } +#ifdef MC6809 + outnl(); +#endif + return bytespushed; +} + +PUBLIC void pushreg(reg) +store_pt reg; +{ + outpshs(); + outtab(); + outnregname(reg); + sp -= pshregsize; +} + +PUBLIC void storereg(sourcereg, target) +store_pt sourcereg; +struct symstruct *target; +{ + store_pt targreg; + + if (target->indcount == 0) + { + if (target->offset.offi != 0 || target->level == OFFKLUDGELEVEL || + !(target->storage & allregs) || target->storage & CHARREGS) + bugerror("bad register store"); + else if ((store_t) (targreg = target->storage) != (store_t) sourcereg) + { + target->storage = sourcereg; + loadadr(target, targreg); /* do LEA or TFR */ + } + } + else + { + outstore(); +#ifdef I8088 + if (target->storage == GLOBAL && (store_t) sourcereg & (AXREG | ALREG)) + unbumplc(); + outnnadr(target); + outcomma(); +#ifdef I8088 + if (i386_32 && target->type->scalar & SHORT) + { + outshortregname(sourcereg); + bumplc(); + outnl(); + } + else +#endif + outnregname(sourcereg); +#endif +#ifdef MC6809 + if ((store_t) sourcereg == YREG) + bumplc(); + outregname(sourcereg); + outadr(target); +#endif + } +} + +/*----------------------------------------------------------------------------- + struc(element leaf, structure leaf) + evaluates the expression + structure.element +-----------------------------------------------------------------------------*/ + +PUBLIC void struc(source, target) +struct symstruct *source; +struct symstruct *target; +{ + address(target); + if (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL) + { + if (target->indcount != 0 || target->level == OFFKLUDGELEVEL) + load(target, getindexreg()); + target->offset.offi += source->offset.offi; + } + if (source->indcount == 0) + target->type = source->type; + else + { + target->type = pointype(source->type); /* lost by = */ + indirec(target); + } +} + +PUBLIC void transfer(source, targreg) +struct symstruct *source; +store_pt targreg; +{ + regtransfer(source->storage, targreg); + source->storage = targreg; +} diff --git a/bcc-bruce/glogcode.c b/bcc-bruce/glogcode.c new file mode 100644 index 0000000..edbedcd --- /dev/null +++ b/bcc-bruce/glogcode.c @@ -0,0 +1,560 @@ +/* glogcode.c - generate code for logical expressions for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "condcode.h" +#include "gencode.h" +#include "reg.h" +#include "scan.h" +#include "sizes.h" +#include "type.h" + +#define cc_signed(cc) ((cc) >= 4 && (cc) < 8) + +PRIVATE char oppcc[] = /* opposite condition codes LT --> GE etc */ +/* EQ, NE, RA, RN, LT, GE, LE, GT, LO, HS, LS, HI, indices */ +{ + NE, EQ, RN, RA, GE, LT, GT, LE, HS, LO, HI, LS, +}; + +PRIVATE char reverscc[] = /* reverse condition codes LT --> GT etc */ +{ + EQ, NE, RN, RA, GT, LE, GE, LT, HI, LS, HS, LO, +}; + +PRIVATE char testcc[] = /* test condition codes LS --> EQ etc */ +{ + EQ, NE, RA, RN, LT, GE, LE, GT, RN, RA, EQ, NE, +}; + +PRIVATE char unsigncc[] = /* unsigned condition codes LT --> LO etc */ +{ + EQ, NE, RA, RN, LO, HS, LS, HI, LO, HS, LS, HI, +}; + +FORWARD void cmplocal P((struct symstruct *source, struct symstruct *target, + ccode_t *pcondtrue)); +#ifdef MC6809 +FORWARD void cmporsub P((struct symstruct *target)); +FORWARD bool_pt cmpsmallconst P((value_t intconst, struct symstruct *target, + ccode_t *pcondtrue)); +#endif +FORWARD void comparecond P((struct nodestruct *exp, label_t truelab, + label_t falselab, bool_pt nojump)); +FORWARD void jumpcond P((struct nodestruct *exp, label_t truelab, + label_t falselab, bool_pt nojump)); +FORWARD void loadlogical P((struct symstruct *source, label_t falselab)); +FORWARD void logandcond P((struct nodestruct *exp, label_t truelab, + label_t falselab, bool_pt nojump)); +FORWARD void logorcond P((struct nodestruct *exp, label_t truelab, + label_t falselab, bool_pt nojump)); +FORWARD void reduceconst P((struct symstruct *source)); +FORWARD void test P((struct symstruct *target, ccode_t *pcondtrue)); +FORWARD void testcond P((struct nodestruct *exp, label_t truelab, + label_t falselab, bool_pt nojump)); + +PUBLIC void cmp(source, target, pcondtrue) +struct symstruct *source; +struct symstruct *target; +ccode_t *pcondtrue; +{ + label_t falselab; + + cmplocal(source, target, pcondtrue); +#if 0 +#ifdef I8088 + if (i386_32) + { + if (*pcondtrue == LO) + { + getlabel(); + getlabel(); + outnop2str("sbb\teax,eax"); + outnop1str("inc eax"); + target->storage = BREG; + target->type = ctype; + return; + } + if (*pcondtrue == HS) + { + getlabel(); + getlabel(); + outnop2str("sbb\teax,eax"); + outnop2str("neg eax"); + target->storage = BREG; + target->type = ctype; + return; + } + } +#endif +#endif + sbranch(oppcc[*pcondtrue], falselab = getlabel()); + loadlogical(target, falselab); +} + +PRIVATE void cmplocal(source, target, pcondtrue) +struct symstruct *source; +struct symstruct *target; +ccode_t *pcondtrue; +{ + scalar_t sscalar; + scalar_t tempscalar; + scalar_t tscalar; + + reduceconst(source); + reduceconst(target); + sscalar = source->type->scalar; + tscalar = target->type->scalar; + if (source->storage != CONSTANT && + (target->storage == CONSTANT || + sscalar & CHAR && !(tscalar & CHAR) || + (sscalar & CHAR || !(tscalar & CHAR)) && + source->indcount == 0 && target->indcount != 0) || + tscalar & DLONG && target->indcount != 0) + { + swapsym(target, source); + *pcondtrue = reverscc[*pcondtrue]; + tempscalar = sscalar; + sscalar = tscalar; + tscalar = tempscalar; + } + if (sscalar & CHAR && tscalar & CHAR && + (source->type != sctype || target->type != sctype) || + (sscalar | tscalar) & UNSIGNED || + (source->type->constructor | target->type->constructor) & + (ARRAY | POINTER)) + *pcondtrue = unsigncc[*pcondtrue]; + if (source->type->scalar & DLONG) + { + longop(EQOP, source, target); + return; + } + if (source->type->scalar & RSCALAR) + { + floatop(EQOP, source, target); + return; + } + if (source->storage == CONSTANT) + { + if (sscalar & CHAR) + { + if (tscalar & CHAR) + *pcondtrue = unsigncc[*pcondtrue]; + else + { + source->type = iscalartotype(sscalar); + sscalar = source->type->scalar; + } + } + if (source->offset.offv == 0) + { + test(target, pcondtrue); + return; + } +#ifdef MC6809 + if (cmpsmallconst(source->offset.offv, target, pcondtrue)) + return; +#endif + } + if (!(sscalar & CHAR) && tscalar & CHAR) + { + loadpres(target, source); + extend(target); + } +#ifndef MC6809 +# define posindependent 0 +#endif + if (source->indcount == 0 && source->storage != CONSTANT && + (posindependent || source->storage != GLOBAL)) + { + loadpres(source, target); +#ifdef MC6809 + push(source); +#endif + } + loadpres(target, source); +#ifdef MC6809 + cmporsub(target); +#else + outcmp(); +#endif +#ifdef I8088 + if (source->storage == GLOBAL && source->indcount == 0 && + !(target->storage & (AXREG | ALREG))) + bumplc(); +#endif + movereg(source, target->storage); +} + +#ifdef MC6809 + +PRIVATE void cmporsub(target) +struct symstruct *target; +{ + if (target->storage & ALLDATREGS) + outsub(); + else + { + outcmp(); + if (target->storage != XREG) + bumplc(); + } +} + +PRIVATE bool_pt cmpsmallconst(intconst, target, pcondtrue) +value_t intconst; +struct symstruct *target; +ccode_t *pcondtrue; +{ + store_pt targreg; + + if ((*pcondtrue == EQ || *pcondtrue == NE) && + !(target->storage & ALLDATREGS) && !(target->type->scalar & CHAR) && + isnegbyteoffset(intconst) && + (reguse & (XREG | YREG)) != (XREG | YREG)) + { + targreg = XREG; + if (reguse & XREG) + targreg = YREG; + if (target->indcount != 0) + load(target, targreg); + target->offset.offi -= (offset_t) intconst; + loadreg(target, targreg); + return TRUE; + } + return FALSE; +} + +#endif + +PRIVATE void comparecond(exp, truelab, falselab, nojump) +struct nodestruct *exp; +label_t truelab; +label_t falselab; +bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ +{ + ccode_t condtrue; + store_t regmark; + struct symstruct *source; + offset_t spmark; + struct symstruct *target; + + regmark = reguse; + spmark = sp; + bileaf(exp); + target = exp->left.nodeptr->left.symptr; + source = exp->right->left.symptr; /* exp->right != NULL since cond */ + switch (exp->tag) + { + case GEOP: + condtrue = GE; + break; + case GTOP: + condtrue = GT; + break; + case LEOP: + condtrue = LE; + break; + case EQOP: + condtrue = EQ; + break; + case LTOP: + condtrue = LT; + break; + case NEOP: + condtrue = NE; + break; + } + cmplocal(source, target, &condtrue); + changesp(spmark, FALSE); + reguse = regmark; + if ((bool_t) nojump) + lbranch(oppcc[condtrue], falselab); + else + lbranch(condtrue, truelab); +} + +PUBLIC void condop(exp) +struct nodestruct *exp; +{ + label_t exitlab; + label_t falselab; + struct nodestruct *falsenode; + struct symstruct *falsesym; + label_t truelab; + struct nodestruct *truenode; + struct symstruct *truesym; + + jumpcond(exp->left.nodeptr, truelab = getlabel(), + falselab = getlabel(), ~0); + deflabel(truelab); + makeleaf(truenode = exp->right->left.nodeptr); + loadany(truesym = truenode->left.symptr); + if (truesym->storage & reguse) + { + /* This can happen if truesym was a reg variable. */ + if (truesym->type->scalar & RSCALAR) + /* XXX - always happens for non-386 with 2 regs vars assigned. */ + bugerror("loaded float or double into used reg"); + load(truesym, DREG); + } + falsenode = exp->right->right; + if (/* falsenode->tag != LEAF || XXX */ + truesym->type != falsenode->left.symptr->type) + cast(truenode->nodetype == falsenode->nodetype ? + truenode->nodetype : exp->nodetype, truesym); + jump(exitlab = getlabel()); + deflabel(falselab); + makeleaf(falsenode); + falsesym = falsenode->left.symptr; + if (falsesym->type != truesym->type) + cast(truesym->type, falsesym); + load(falsesym, truesym->storage); + deflabel(exitlab); + exp->tag = LEAF; + exp->left.symptr = truesym; +} + +PRIVATE void jumpcond(exp, truelab, falselab, nojump) +struct nodestruct *exp; +label_t truelab; +label_t falselab; +bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ +{ + switch (exp->tag) + { + case GEOP: + case GTOP: + case LEOP: + case EQOP: + case LTOP: + case NEOP: + comparecond(exp, truelab, falselab, nojump); + break; + case LOGANDOP: + logandcond(exp, truelab, falselab, nojump); + break; + case LOGNOTOP: + jumpcond(exp->left.nodeptr, falselab, truelab, ~nojump); + break; + case LOGOROP: + logorcond(exp, truelab, falselab, nojump); + break; + default: + testcond(exp, truelab, falselab, nojump); + break; + } +} + +PUBLIC void jumpfalse(exp, label) +struct nodestruct *exp; +label_t label; +{ + label_t truelab; + + jumpcond(exp, truelab = getlabel(), label, ~0); + deflabel(truelab); +} + +PUBLIC void jumptrue(exp, label) +struct nodestruct *exp; +label_t label; +{ + label_t falselab; + + jumpcond(exp, label, falselab = getlabel(), 0); + deflabel(falselab); +} + +PRIVATE void loadlogical(source, falselab) +struct symstruct *source; +label_t falselab; +{ + label_t exitlab; + struct symstruct *target; + + target = constsym((value_t) TRUE); + target->type = ctype; + loadreg(target, DREG); + sbranch(RA, exitlab = getlabel()); + deflabel(falselab); + target = constsym((value_t) FALSE); + target->type = ctype; + *source = *target; + loadreg(source, DREG); + outnlabel(exitlab); +} + +PRIVATE void logandcond(exp, truelab, falselab, nojump) +struct nodestruct *exp; +label_t truelab; +label_t falselab; +bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ +{ + label_t andlab; + + andlab = getlabel(); + jumpcond(exp->left.nodeptr, andlab, falselab, ~0); + deflabel(andlab); + jumpcond(exp->right, truelab, falselab, nojump); +} + +PUBLIC void logop(exp) +struct nodestruct *exp; +{ + label_t falselab; + struct symstruct *target; + label_t truelab; + + jumpcond(exp, truelab = getlabel(), falselab = getlabel(), ~0); + deflabel(truelab); + target = constsym((value_t) 0); /* anything, loadlogical makes B reg */ + target->type = ctype; + loadlogical(target, falselab); + exp->tag = LEAF; + exp->left.symptr = target; +} + +PRIVATE void logorcond(exp, truelab, falselab, nojump) +struct nodestruct *exp; +label_t truelab; +label_t falselab; +bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ +{ + label_t orlab; + + orlab = getlabel(); + jumpcond(exp->left.nodeptr, truelab, orlab, 0); + deflabel(orlab); + jumpcond(exp->right, truelab, falselab, nojump); +} + +PRIVATE void reduceconst(source) +struct symstruct *source; +{ + if (source->storage == CONSTANT && ischarconst(source->offset.offv) && + (source->type->scalar & (CHAR | SHORT | INT | DLONG)) != DLONG) + { + if (source->type->scalar & UNSIGNED) + source->type = uctype; + else + source->type = ctype; + } +} + +PRIVATE void test(target, pcondtrue) +struct symstruct *target; +ccode_t *pcondtrue; +{ +#ifdef I8088 + store_t targreg; +#endif + + *pcondtrue = testcc[*pcondtrue]; + if (target->type->scalar & DLONG) + { + long1op(EQOP, target); + return; + } + if (target->type->scalar & RSCALAR) + { + float1op(EQOP, target); + return; + } +#ifdef I8088 + if (target->indcount != 0 || + target->storage == LOCAL && target->offset.offi != sp) + load(target, DREG); + if (target->storage == GLOBAL) + load(target, getindexreg()); + if (target->type->scalar & CHAR) + load(target, DREG); + targreg = target->storage; + if (target->offset.offi != 0 && cc_signed(*pcondtrue)) + load(target, targreg); + + /* Extension was not done in exptree for the == 0 case, to allow + * optimization here - which we don't do for shorts. (foo--) is + * newfoo == -1 here and used to be missed. + */ + if (i386_32 && target->type->scalar & SHORT) + extend(target); + + if (target->offset.offi == 0) + { + outtest(); + outregname(targreg); + outcomma(); + outnregname(targreg); + return; + } + outcmp(); + outimadj(-target->offset.offi, targreg); +#endif +#ifdef MC6809 + if (target->indcount != 0 || + target->storage == LOCAL && target->offset.offi != sp) + { + load(target, DREG); + return; + } + if (cmpsmallconst(0, target, pcondtrue)) + return; + if (target->storage == GLOBAL) + load(target, getindexreg()); + if (target->type->scalar & CHAR) + load(target, DREG); + if (target->offset.offi != 0 && cc_signed(*pcondtrue)) + load(target, target->storage); + if (target->type->scalar & CHAR) + { + if (target->offset.offi == 0) + { + outtest(); + outnregname(BREG); + return; + } + outcmp(); + outimadj(-target->offset.offi, BREG); + } + else + { + cmporsub(target); + outimadj(-target->offset.offi, target->storage); + } +#endif +} + +/* test expression and jump depending on NE/EQ */ + +PRIVATE void testcond(exp, truelab, falselab, nojump) +struct nodestruct *exp; +label_t truelab; +label_t falselab; +bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ +{ + ccode_t condtrue; + struct symstruct *source; + + makeleaf(exp); + source = exp->left.symptr; + reduceconst(source); + if (source->storage != CONSTANT) + { + condtrue = NE; + test(source, &condtrue); + if ((bool_t) nojump) + lbranch(oppcc[condtrue], falselab); + else + lbranch(condtrue, truelab); + } + else if (source->offset.offi == 0) + { + if ((bool_t) nojump) + jump(falselab); + } + else if (!(bool_t) nojump) + jump(truelab); +} diff --git a/bcc-bruce/hardop.c b/bcc-bruce/hardop.c new file mode 100644 index 0000000..8121484 --- /dev/null +++ b/bcc-bruce/hardop.c @@ -0,0 +1,510 @@ +/* hardop.c - hardware operations for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "byteord.h" +#include "condcode.h" +#include "gencode.h" +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "sizes.h" +#include "type.h" + +FORWARD void sub1 P((struct symstruct *source, struct symstruct *target)); + +PUBLIC void add(source, target) +struct symstruct *source; +struct symstruct *target; +{ + scalar_t sscalar; + + if (source->indcount == 0 && source->storage != CONSTANT && + (target->indcount != 0 || target->storage & ALLDATREGS)) + swapsym(target, source); + if ((sscalar = source->type->scalar) & DLONG) + { + longop(ADDOP, source, target); + return; + } + if (sscalar & RSCALAR) + { + floatop(ADDOP, source, target); + return; + } + if (source->storage == CONSTANT) + { + extend(target); + if (target->indcount != 0 || target->storage & reguse) + loadany(target); + target->offset.offi += (offset_t) source->offset.offv; + } + else if (source->indcount == 0) + { + /* target is also direct */ + sscalar |= target->type->scalar; /* remember if unsigned/long */ + target->type = pctype; /* fake to use indexadr() */ + indexadr(source, target); + } + else + { + /* source is indirect and not DREG */ + extend(target); + load(target, DREG); + outadd(); + movereg(source, DREG); + if (source->type->scalar & CHAR) + adc0(); + } + target->type = iscalartotype(target->type->scalar | sscalar); +} + +PUBLIC void incdec(op, source) +op_pt op; +struct symstruct *source; +{ + offset_t bump; + bool_t postflag; + store_t regmark; + struct symstruct *target; + struct symstruct targ; +#ifdef MC6809 + store_pt targreg; +#endif + + *(target = &targ) = *source; + bump = 1; + if (targ.type->constructor & POINTER) + bump = targ.type->nexttype->typesize; + if (op == PREDECOP || op == POSTDECOP) + bump = -bump; + postflag = FALSE; + if (op == POSTDECOP || op == POSTINCOP) + postflag = TRUE; + reguse |= targ.storage; + if (targ.type->scalar & DLONG) /* cannot be direct */ + { + if (postflag) + { + regmark = reguse; + if (((reguse |= OPREG) & allindregs) == allindregs) + { + saveopreg(); + load(source, OPREG); + pushreg(source->storage); + restoreopreg(); + } + else + { + loadany(source); + reguse = regmark | source->storage; + saveopreg(); + } + } + else + saveopreg(); + pointat(target); + switch (op) + { + case PREDECOP: + case POSTDECOP: + call("ldec"); + break; + case PREINCOP: + case POSTINCOP: + call("linc"); + break; + } + outlongendian(); + restoreopreg(); + if (postflag && source->storage == OPREG) + poplist(OPREG); + return; + } + if (targ.type->scalar & RSCALAR) + { + saveopreg(); + pointat(target); + switch (op) + { + case PREDECOP: + call("Fpredec"); + break; + case PREINCOP: + call("Fpreinc"); + break; + case POSTDECOP: + call("Fpostdec"); + break; + case POSTINCOP: + call("Fpostinc"); + break; + } + outntypechar(targ.type); + restoreopreg(); + if (postflag) + { + justpushed(source); + source->type = targ.type; + } + return; + } + loadany(source); +#ifdef MC6809 + if (postflag && targ.flags != REGVAR && + !(source->storage & ALLDATREGS) && + ((reguse |= source->storage) & allindregs) != allindregs) + { + targreg = getindexreg(); + outlea(); + outregname(targreg); + outtab(); + outshex(bump); + outncregname(source->storage); + } + else + { + addconst(bump, targreg = source->storage); + if (postflag) + source->offset.offi = -bump; + } + storereg(targreg, target); + target->storage = targreg; + target->offset.offi = 0; +#else + addconst(bump, source->storage); + if (postflag) + source->offset.offi = -bump; + storereg(source->storage, target); + target->storage = source->storage; + target->offset.offi = 0; +#endif +} + +PUBLIC void neg(target) +struct symstruct *target; +{ + scalar_t scalar; + struct symstruct *source; + + if ((scalar = target->type->scalar) & DLONG) + long1op(NEGOP, target); + else if (scalar & RSCALAR) + float1op(NEGOP, target); + else + { + if (scalar & SHORT) + extend(target); + if (!(target->storage & ALLDATREGS)) + { + /* load 0, subtract is shorter than load, negate */ + /* if no hardware integer negate; about the same if there is */ + sub1(target, source = constsym((value_t) 0)); + *target = *source; + } + else + { + load(target, DREG); + negreg(target->storage); + target->storage = DREG; + } + target->type = iscalartotype(scalar); + } +} + +PUBLIC void not(target) +struct symstruct *target; +{ + if (target->type->scalar & DLONG) + long1op(NOTOP, target); + else + { + extend(target); + load(target, DREG); + comDreg(); + } +} + +/* 1-byte ops like AND acting on integers (not both constant) */ + +PUBLIC void op1(op, source, target) +op_pt op; +struct symstruct *source; +struct symstruct *target; +{ + char *opstr; +#ifdef OP1 +# if MAXINDIRECT > 1 + indn_t indcount; +# endif +#endif + bool_t resultchar; + scalar_t resultscalar; + scalar_t sscalar; + scalar_t tscalar; + + if ((sscalar = source->type->scalar) & DLONG) + { + longop(op, source, target); + return; + } + /* Emergency fix. The types of constants should be reduced here and in + * other low-level routines anyway, and not in exptree.c and table.c, + * and for the 80386 and maybe the 8086 they would be better not + * reduced. + */ + if (source->storage == CONSTANT && ischarconst(source->offset.offv)) + { + if (sscalar & UNSIGNED) + source->type = uctype; + else + source->type = ctype; + sscalar = source->type->scalar; + } + tscalar = target->type->scalar; + if (target->storage == CONSTANT && ischarconst(target->offset.offv)) + { + if (sscalar & UNSIGNED) + target->type = uctype; + else + target->type = ctype; + tscalar = target->type->scalar; + } + resultscalar = sscalar | tscalar; + if (op != ANDOP) + resultchar = sscalar & tscalar & CHAR; + else if ((resultchar = (sscalar | tscalar) & CHAR) != 0 && + source->storage == CONSTANT) + { + source->offset.offv &= CHMASKTO; + if (sscalar & UNSIGNED) + source->type = uctype; + else + source->type = ctype; + sscalar = source->type->scalar; + } + if (target->indcount != 0 && + (tscalar & CHAR && !(sscalar & CHAR) && + op != ANDOP || source->indcount == 0 && source->storage != CONSTANT)) + { + swapsym(target, source); + sscalar = tscalar; + tscalar = target->type->scalar; + } + if (source->indcount == 0 && source->storage != CONSTANT) + { + loadpres(source, target); + push(source); + } +#if MAXINDIRECT > 1 + else if (source->indcount >= MAXINDIRECT && !(sscalar & CHAR)) + { + address(source); + if (!(target->storage & ALLDATREGS)) + preserve(target); + load(source, getindexreg()); + indirec(source); + } +#endif + if (!(tscalar & CHAR) && + op == ANDOP && sscalar & CHAR && target->indcount == 1) + cast(ctype, target); + if (!(target->storage & ALLDATREGS) || target->indcount != 0) + pres2(target, source); + load(target, DREG); + opstr = opstring(op); + if (source->storage == CONSTANT && op == ANDOP) + andconst((offset_t) source->offset.offv); +#ifdef OP1 + else if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP) + outload(); + else + outop2str(opstr); +#else /* OP1 */ + else + { + if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP) + extend(target); + outop2str(opstr); + } +#endif /* OP1 */ + if (source->storage == CONSTANT) + { + if (op != ANDOP) + { +#ifdef OP1 + if (!(sscalar & CHAR)) + { + outhiaccum(); + outncimmadr((offset_t) ((uoffset_t) source->offset.offv + >> (INT16BITSTO - CHBITSTO))); + outop2str(opstr); + } + outregname(BREG); + outncimmadr((offset_t) source->offset.offv & CHMASKTO); +#else /* OP1 */ + if (!(sscalar & CHAR)) + { + outregname(DREG); + bumplc(); + } + else + outregname(BREG); +# ifdef I8088 + if (i386_32 && !(sscalar & CHAR)) + bumplc2(); +# endif + outncimmadr((offset_t) source->offset.offv); + +#endif /* OP1 */ + } + } + else if (sscalar & CHAR) + { + outregname(BREG); + outopsep(); + outadr(source); + } + else + { +#ifdef MC6809 + source->type = ctype; /* fool outadr to avoid ,S++ */ +#endif +#ifdef OP1 + if (!(tscalar & CHAR) || op != ANDOP) + { + outhiaccum(); +# if MAXINDIRECT > 1 + indcount = source->indcount; +# endif + outopsep(); +# if BIG_ENDIAN == 0 + ++source->offset.offi; +# endif + outadr(source); +# if BIG_ENDIAN == 0 + --source->offset.offi; +# endif +# if MAXINDIRECT > 1 + source->indcount = indcount; +# else + source->indcount = 1; +# endif + outop2str(opstr); + } + outregname(BREG); + outopsep(); +# if BIG_ENDIAN + ++source->offset.offi; +# endif + outadr(source); + } +#else /* OP1 */ + if (!(tscalar & CHAR) || op != ANDOP) + outregname(DREG); + else + outregname(BREG); + outopsep(); + outadr(source); + } +#endif /* OP1 */ + if (resultchar) + { + target->storage = BREG; + if (resultscalar & UNSIGNED) + target->type = uctype; + else + target->type = ctype; + } + else + { + target->storage = DREG; + target->type = iscalartotype(resultscalar); + } +} + +PUBLIC void ptrsub(source, target) +struct symstruct *source; +struct symstruct *target; +{ + label_t exitlab; + uoffset_t factor; + label_t usignlab; + + if (source->indcount == 0 && source->storage != CONSTANT) + { + loadpres(source, target); + push(source); + } + if (target->indcount == 0) + { + pres2(target, source); + load(target, DREG); + } + factor = target->type->nexttype->typesize; + source->type = target->type = itype; + sub1(source, target); + if (factor != 1) + { + pushlist(CCREG); + sbranch(HS, usignlab = getlabel()); /* HS == no carry */ + negDreg(); + outnlabel(usignlab); + target->type = uitype; + softop(DIVOP, constsym((value_t) factor), target); + target->type = itype; + poplist(CCREG); + sbranch(HS, exitlab = getlabel()); + negDreg(); + outnlabel(exitlab); + } +} + +PUBLIC void sub(source, target) +struct symstruct *source; +struct symstruct *target; +{ + scalar_t sscalar; + + if ((sscalar = source->type->scalar) & DLONG) + { + longop(SUBOP, source, target); + return; + } + if (sscalar & RSCALAR) + { + floatop(SUBOP, source, target); + return; + } + if (source->storage == CONSTANT) + { + extend(target); + if (target->indcount != 0 || target->storage & reguse) + loadany(target); + target->offset.offi -= (offset_t) source->offset.offv; + } + else + sub1(source, target); + target->type = iscalartotype(target->type->scalar | sscalar); +} + +PRIVATE void sub1(source, target) +struct symstruct *source; +struct symstruct *target; +{ + if (source->storage == CONSTANT) + source->type = itype; + else if (source->indcount == 0) + { + loadpres(source, target); + push(source); + } + extend(target); + load(target, DREG); + outsub(); + movereg(source, DREG); + if (source->type->scalar & CHAR) + sbc0(); +} diff --git a/bcc-bruce/input.c b/bcc-bruce/input.c new file mode 100644 index 0000000..f321a9d --- /dev/null +++ b/bcc-bruce/input.c @@ -0,0 +1,729 @@ +/* input.c - input for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#define ARBITRARY_BACKSLASH_NEWLINES_NOT +#define INSERT_BACKSLASH_NEWLINES_NOT + +#include "const.h" +#include "types.h" +#include "gencode.h" +#include "output.h" +#include "os.h" +#include "sc.h" +#include "scan.h" +#include "table.h" + +#undef EXTERN +#define EXTERN +#include "input.h" + +#define INBUFSIZE 2048 + +struct fbufstruct /* file buffer structure */ +{ + struct fcbstruct fcb; /* status after opening an include sub-file */ + char *fname; /* file name */ + bool_t fname_malloced; /* nonzero if fname was malloced */ + char pushback[3]; /* allows pushback to 2 before start of fbuf + * XXX 3 chars before? + * XXX should do everything in fbuf */ + char fbuf[INBUFSIZE + 1]; /* buffer to read into */ +}; + +struct inclist /* list of include file directories */ +{ + char *incdirname; + struct inclist *incnext; +}; + +PRIVATE char filemacro[] = "__FILE__"; +PRIVATE struct inclist incabsolute; /* dummy list for absolute names */ + /* depends on zero (NULL) init */ +PRIVATE struct inclist incfirst; + /* begin include searches here for "" */ + /* at next in list for <> */ + /* -I directories are put in list */ + /* between first and last */ +PRIVATE struct inclist inclast = +{ + DEFAULT_INCLUDE_DIR, + NULL, +}; +PRIVATE fastin_t inclevel; /* nest level of include files */ + /* depends on zero init */ +PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */ + /* its fcb only to date in includes */ + /* depends on zero (NULL) init */ +PRIVATE bool_t suppress_line_numbers; + +#ifdef ARBITRARY_BACKSLASH_NEWLINES +FORWARD void backslash P((void)); +#endif +FORWARD void definefile P((char *fname)); +FORWARD void inputinit P((char *fname, fd_t fd)); +FORWARD void leaveinclude P((void)); +FORWARD void usage P((void)); + +#ifdef ARBITRARY_BACKSLASH_NEWLINES +PRIVATE void backslash() +{ + static unsigned nbackslash; + + if (nbackslash != 0) + --nbackslash; +more: + ++nbackslash; + while (*(lineptr + 1) == '\\') + { + ++nbackslash; + ++lineptr; + } + if (*(lineptr + 1) != EOL) + { + if (--nbackslash != 0) + *--lineptr = '\\'; /* force look at current backslash again */ + return; + } + ch = *++lineptr; +more1: + if (!eof && lineptr >= input.limit) + skipeol(); + if (ch == EOL) + { + --nbackslash; + if (eof) + eofin("backslash-newline"); + else + { + skipeol(); + if (ch == EOL && !eof && lineptr >= input.limit) + skipeol(); +#ifdef COEOL /* XXX - this should go through specialchar() */ + if (ch == COEOL) + { + ch = *++lineptr; + if (ch == EOL && !eof && lineptr >= input.limit) + skipeol(); + } +#endif + } + if (ch == '\\') + goto more; + if (nbackslash != 0 && ch == EOL && !eof) + goto more1; + if (nbackslash != 0) + { + ch = *--lineptr = '\\'; + if (--nbackslash != 0) + ch = *--lineptr = '\\'; + } + return; + } + if (ch == '\\') + goto more; + if (ch == EOL && !eof) + goto more1; + ch = *--lineptr = '\\'; /* pushback */ + if (--nbackslash != 0) + ch = *--lineptr = '\\'; +} +#endif + +PUBLIC void closein() +{ +#ifdef FAKE_INBUFSIZE_1 + fclose(input.fp); +#else + close(input.fd); +#endif + while (inclevel != 0) + leaveinclude(); +} + +PRIVATE void definefile(fname) +char *fname; +{ + char *def; + + def = ourmalloc(sizeof filemacro - 1 + 2 + strlen(fname) + 1 + 1); + strcpy(def, filemacro); + strcat(def, "=\""); + strcat(def, fname); + strcat(def, "\""); + definestring(def); + ourfree(def); +} + +PUBLIC void errorloc() +{ + register struct fbufstruct *infbuf; + + if ((infbuf = inputbuf) == NULL) + return; + outstr(infbuf->fname); + outbyte(':'); + if (eof) + outstr("eof"); + else + { + outudec(input.linenumber); + outbyte('.'); + if (maclevel == 0) + outudec((unsigned) (lineptr - inputbuf->fbuf) - input.lineoffset); + else + { + outudec((unsigned) (savedlineptr() - inputbuf->fbuf) + - input.lineoffset); + outstr(" (macro level "); + outudec((unsigned) maclevel); + outbyte(')'); + } + } + infbuf->fcb.includer = input.includer; + while ((infbuf = infbuf->fcb.includer) != NULL) + { + outstr(" (from "); + outstr(infbuf->fname); + outbyte(':'); + outudec(infbuf->fcb.linenumber); + outbyte(')'); + } + outstr(": "); +} + +/* gch1() - get next char, advance ptr (only works on current line) */ + +PUBLIC void gch1() +{ + if (SYMOFCHAR(ch = *++lineptr) != SPECIALCHAR) + return; + specialchar(); +} + +/* process #include */ + +PUBLIC void include() +{ + char *dirnameptr; + char *dirnamend; + unsigned dirnamelen; + fd_t fd; + char *fnameptr; + char *fullnameptr; + struct inclist *incptr; + char terminator; + + while (blanksident()) + { + if ((gsymptr = findlorg(gsname)) == NULL || + gsymptr->flags != DEFINITION) + break; + entermac(); + } + if ((terminator = ch) == '<') + terminator = '>'; + else if (terminator != '"') + { + error("bad file name"); + return; + } + gch1(); + fnameptr = charptr; + while (TRUE) + { + if (ch == EOL) /* no escapes in file names */ + break; + if (ch == terminator) + { + gch1(); + break; + } + if (charptr >= chartop) + fnameptr = growobject(fnameptr, 1); +#ifdef TS +++ts_n_filename; +++ts_s_filename; +++ts_s_filename_tot; +#endif + *charptr++ = ch; + gch1(); + } + if (charptr >= chartop) + fnameptr = growobject(fnameptr, 1); +#ifdef TS +++ts_n_filename_term; +++ts_s_filename_term; +++ts_s_filename_tot; +#endif + *charptr++ = 0; + dirnamend = NULL; + if (isabspath(fnameptr, &ch)) + incptr = &incabsolute; + else + { + incptr = &incfirst; + if (terminator == '>') + incptr = incptr->incnext; + else + { + dirnameptr = inputbuf->fname; + if ((dirnamend = strrchr(dirnameptr, DIRCHAR)) == NULL) + incptr->incdirname = NULL; + else + { + *dirnamend = 0; + incptr->incdirname = dirnameptr; + } + } + } + do + { + if (incptr->incdirname == NULL) + { + fullnameptr = ourmalloc(strlen(fnameptr) + 1); +#ifdef TS +++ts_n_pathname; +ts_s_pathname += strlen(fnameptr) + 1; +ts_s_pathname_tot += strlen(fnameptr) + 1; +#endif + strcpy(fullnameptr, fnameptr); + } + else + { + dirnamelen = strlen(incptr->incdirname); + fullnameptr = ourmalloc(dirnamelen + (int) (charptr - fnameptr) + + 2); + /* 2 extra for null and maybe DIRCHAR */ +#ifdef TS +++ts_n_pathname; +ts_s_pathname += dirnamelen + (charptr - fnameptr) + 2; +ts_s_pathname_tot += dirnamelen + (charptr - fnameptr) + 2; +#endif + dirnameptr = fullnameptr + dirnamelen; + strcpy(fullnameptr, incptr->incdirname); + if (*fullnameptr != 0 && *(dirnameptr - 1) != DIRCHAR) + strcat(fullnameptr, DIRSTRING); + strcat(fullnameptr, fnameptr); + if (dirnamend != NULL) + { + *dirnamend = DIRCHAR; + dirnamend = NULL; + } + } + fd = open(fullnameptr, 0); + if (fd >= 0) + { +#ifdef TS +ts_s_filename_tot -= charptr - fnameptr; +#endif + charptr = fnameptr; + input.lineptr = lineptr; + inputbuf->fcb = input; + ++inclevel; /* XXX - will run out of memory before overflow */ + inputinit(fullnameptr, fd); + inputbuf->fname_malloced = TRUE; + return; + } +#ifdef TS +ts_s_pathname_tot -= strlen(fullnameptr) + 1; +#endif + ourfree(fullnameptr); + } + while ((incptr = incptr->incnext) != NULL); + error("cannot find include file"); +#ifdef TS +ts_s_filename_tot -= charptr - fnameptr; +#endif + charptr = fnameptr; +} + +/* initialise current input file */ + +PRIVATE void inputinit(fname, fd) +char *fname; +fd_t fd; +{ + register struct fbufstruct *newinputbuf; + + /* don't allocate after saying input.includer = inputbuf (to save a reg) + * or an error in the alloc would cycle trying to print the include list + */ + newinputbuf = (struct fbufstruct *) ourmalloc(sizeof *inputbuf); +#ifdef TS +++ts_n_inputbuf; +ts_s_inputbuf += sizeof *inputbuf; +ts_s_inputbuf_tot += sizeof *inputbuf; +#endif + input.fd = fd; +#ifdef FAKE_INBUFSIZE_1 + input.fp = fdopen(fd, "r"); +#endif + input.linenumber = 0; + input.lineoffset = 0; + input.includer = inputbuf; + inputbuf = newinputbuf; + newinputbuf->fname = fname; + newinputbuf->fname_malloced = FALSE; + undefinestring(filemacro); + definefile(fname); + if (orig_cppmode && !suppress_line_numbers) + outcpplinenumber(1, fname, input.includer == NULL ? "" : " 1"); + *(input.limit = newinputbuf->fbuf) = EOL; + + /* dummy line so #include processing can start with skipline() */ + ch = *(lineptr = newinputbuf->fbuf - 1) = EOL; +} + +/* switch from include file to file which included it */ + +PRIVATE void leaveinclude() +{ + --inclevel; + if (inputbuf->fname_malloced) +{ +#ifdef TS +ts_s_pathname_tot -= strlen(inputbuf->fname) + 1; +#endif + ourfree(inputbuf->fname); +} +#ifdef TS +ts_s_inputbuf_tot -= sizeof *inputbuf; +#endif + ourfree((char *) inputbuf); + close(input.fd); +#ifdef FAKE_INBUFSIZE_1 + fclose(input.fp); +#endif + inputbuf = input.includer; + input = inputbuf->fcb; + undefinestring(filemacro); + definefile(inputbuf->fname); + ch = *(lineptr = input.lineptr); + skipline(); + if (orig_cppmode && !suppress_line_numbers) + outcpplinenumber(input.linenumber, inputbuf->fname, " 2"); +} + +/* open input and output files and get options */ + +PUBLIC void openio(argc, argv) +int argc; +char *argv[]; +{ + register char *arg; + int argn; + fd_t fd; + char *fname; + struct inclist *incnew; + struct inclist *incptr; + bool_t flag[128]; + +#if 0 + lineptr = "\n"; /* empty line in case error message */ +#endif + fd = 0; /* standard input */ + memset(flag, 0, sizeof flag); + flag['3'] = sizeof (int) >= 4; + fname = "stdin"; + (incptr = &incfirst)->incnext = &inclast; + initout(); + for (argn = 1; argn < argc; ++argn) + { + arg = argv[argn]; + if (*arg != '-') + { + if (fd != 0) + fatalerror("more than one input file"); + fname = arg; + if ((fd = open(arg, 0)) < 0) + fatalerror("cannot open input"); + } + else + switch (arg[1]) + { +#ifdef I8088 + case '0': /* generate 16-bit code */ + case '3': /* generate 32-bit code */ +#endif + case 'c': /* caller saves */ +#ifdef DEBUG + case 'd': /* print debugging information in asm output */ +#endif + case 'E': /* acting as cpp */ + case 'f': /* pass first argument in register */ +#ifdef DYNAMIC_LONG_ORDER + case 'l': /* long big-endian */ +#endif + case 'P': /* if acting as cpp, suppress line numbers */ +#ifdef POSINDEPENDENT + case 'p': /* generate almost-position-independent code */ +#endif + case 't': /* print source code in asm output */ + case 'w': /* watch location counter */ + if (arg[2] == 0) + flag[arg[1]] = TRUE; + else if (arg[2] == '-' && arg[3] == 0) + flag[arg[1]] = FALSE; + else + usage(); + if (arg[1] == '0') /* flag 0 is negative logic flag 3 */ + flag['3'] = TRUE + FALSE - flag['0']; + break; + case 'D': + definestring(arg + 2); + break; + case 'I': + (incnew = (struct inclist *) ourmalloc(sizeof *incnew)) + ->incdirname = arg + 2; +#ifdef TS +++ts_n_includelist; +ts_s_includelist += sizeof *incnew; +#endif + incnew->incnext = incptr->incnext; + incptr = incptr->incnext = incnew; + break; + case 'U': + undefinestring(arg + 2); + break; + case 'o': + if (arg[2] != 0 || ++argn >= argc) + usage(); + openout(argv[argn]); + break; + default: + usage(); + break; + } + } +#ifdef I8088 + if (flag['3']) + { + i386_32 = TRUE; + definestring("__AS386_32__"); + } + else + definestring("__AS386_16__"); +#endif +#ifdef MC6809 + definestring("__AS09__"); +#endif + if (flag['c']) + { + callersaves = TRUE; + definestring("__CALLER_SAVES__"); + } +#ifdef DEBUG + debugon = flag['d']; +#endif + orig_cppmode = cppmode = flag['E']; + if (flag['f']) + { + arg1inreg = TRUE; +#ifdef I8088 + definestring("__FIRST_ARG_IN_AX__"); +#endif +#ifdef MC6808 + definestring("__FIRST_ARG_IN_X__"); +#endif + } + arg1op = arg1inreg ? ROOTLISTOP : LISTOP; +#ifdef DYNAMIC_LONG_ORDER + if (flag['l']) + { + long_big_endian = TRUE; + definestring("__LONG_BIG_ENDIAN__"); + } +#endif + suppress_line_numbers = flag['P']; +#ifdef POSINDEPENDENT + if (flag['p']) + { + posindependent = TRUE; + definestring("__POS_INDEPENDENT__"); + } +#endif + ctext = flag['t']; + watchlc = flag['w']; + setoutbufs(); + inputinit(fname, fd); +} + +/* advance over EOL sentinel to new line */ + +PUBLIC void skipeol() +{ +#ifdef FAKE_INBUFSIZE_1 + static int ich; +#endif +#ifdef INSERT_BACKSLASH_NEWLINES + static int bs_state; + static bool_t skip_printing_nl; +#endif + int nread; + + if (eof) + return; + if (lineptr < input.limit) + { + ++input.linenumber; + ch = *++lineptr; + if (ctext && !asmmode) + { + comment(); + outudec(input.linenumber); + outbyte(' '); + outline(lineptr); + } + if (orig_cppmode && !asmmode) +#ifdef INSERT_BACKSLASH_NEWLINES + if (!skip_printing_nl) +#endif + + outbyte('\n'); +#ifdef INSERT_BACKSLASH_NEWLINES + if (bs_state == 1 && *(lineptr - 1) == EOL) +#endif + input.lineoffset = (int) (lineptr - inputbuf->fbuf); + return; + } + input.lineoffset -= (int) (lineptr - inputbuf->fbuf); +#ifdef FAKE_INBUFSIZE_1 + lineptr = inputbuf->fbuf; +#ifdef INSERT_BACKSLASH_NEWLINES + switch (bs_state) + { +case0: + case 0: + bs_state = nread = (ich = getc(input.fp)) == EOF ? 0 : 1; + skip_printing_nl = FALSE; + break; + case 1: + if (ich == '\\') + goto case0; /* avoid chance of splitting \EOL */ + ich = '\\'; + nread = 1; + bs_state = 2; + ++input.lineoffset; + break; + case 2: + ich = EOL; + nread = 1; + bs_state = 0; + skip_printing_nl = TRUE; + ++input.lineoffset; + --input.linenumber; + break; + } +#else + nread = (ich = getc(input.fp)) == EOF ? 0 : 1; +#endif + *lineptr = ich; +#else + nread = read(input.fd, lineptr = inputbuf->fbuf, INBUFSIZE); +#endif + if (nread < 0) + fatalerror("input error"); + *(input.limit = lineptr + nread) = EOL; + ch = *lineptr; + if (nread == 0) + { + if (inclevel == 0) + { + eof = TRUE; + checknotinif(); + } + else + { + leaveinclude(); + skipeol(); + } + return; + } + if (ctext && !asmmode) + { + comment(); + outudec(input.linenumber); + outbyte(' '); + outline(lineptr); + } +} + +PUBLIC void specialchar() +{ + if (maclevel != 0) + { + if (ch == EOL) /* it might also be backslash or COEOL */ + leavemac(); + if (ch != EOL) + return; + } +more: +#ifdef ARBITRARY_BACKSLASH_NEWLINES + if (ch == '\\') + backslash(); +#endif + if (!eof && lineptr >= input.limit) + { + skipeol(); +#ifdef ARBITRARY_BACKSLASH_NEWLINES + if (ch == '\\') + backslash(); +#endif + } +#ifndef ARBITRARY_BACKSLASH_NEWLINES + if (ch == '\\') + { + if (*(lineptr + 1) == EOL) + { + if (lineptr + 1 >= input.limit) + { + ++lineptr; + skipeol(); + ch = *--lineptr = '\\'; /* pushback */ + } + if (*(lineptr + 1) == EOL) + { + if (eof) + eofin("backslash-newline"); + else + { + ++lineptr; + skipeol(); + if (SYMOFCHAR(ch) == SPECIALCHAR) + { +#ifdef COEOL + if (ch != COEOL + || SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) +#endif + goto more; + } + } + } + } +#endif + } +#ifdef COEOL + if (ch == EOL && !eof) + { + if (*(lineptr + 1) == EOL && lineptr + 1 >= input.limit) + { + ++lineptr; + skipeol(); /* refill buffer */ + ch = *--lineptr = EOL; /* pushback */ + } + if (*(lineptr + 1) == COEOL) + *++lineptr = EOL; /* discard COEOL */ + } +#endif +} + +PRIVATE void usage() +{ + fatalerror( +#ifdef MC6809 +"usage: cc1 [-cdfptw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]"); +#else +"usage: cc1 [-03cdfltw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]"); +#endif +} diff --git a/bcc-bruce/input.h b/bcc-bruce/input.h new file mode 100644 index 0000000..0563059 --- /dev/null +++ b/bcc-bruce/input.h @@ -0,0 +1,37 @@ +/* input.h - input for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#define FAKE_INBUFSIZE_1_NOT + +#ifdef FAKE_INBUFSIZE_1 +#include <stdio.h> +FILE *fdopen(); +#endif + +struct fcbstruct /* file control block structure */ +{ + fd_t fd; /* file descriptor */ +#ifdef FAKE_INBUFSIZE_1 + FILE *fp; +#endif + unsigned linenumber; /* current line in file */ + int lineoffset; /* offset to start of current line in buf */ + char *lineptr; /* current spot in line */ + char *limit; /* end of used part of input buffer */ + struct fbufstruct *includer; + /* buffer of file which included current one */ +}; + +EXTERN bool_t asmmode; /* nonzero when processing assembler code */ + /* depends on zero init */ +EXTERN char ch; /* current char */ +EXTERN bool_t cppmode; /* nonzero if acting as cpp not as compiler */ +EXTERN bool_t eof; /* nonzero after end of main file reached */ + /* depends on zero init */ +EXTERN struct fcbstruct input; /* current input file control block */ + /* input.lineptr is not kept up to date */ +EXTERN char *lineptr; /* ptr to current char */ +EXTERN maclev_t maclevel; /* nest level of #defined identifiers */ + /* depends on zero init */ +EXTERN bool_t orig_cppmode; /* same as cppmode ex. not varied while in # */ diff --git a/bcc-bruce/label.c b/bcc-bruce/label.c new file mode 100644 index 0000000..8489230 --- /dev/null +++ b/bcc-bruce/label.c @@ -0,0 +1,429 @@ +/* label.c - label handling routines for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "condcode.h" +#include "gencode.h" +#include "label.h" +#include "output.h" +#include "sc.h" +#include "scan.h" +#include "sizes.h" +#include "type.h" + +#ifdef I8088 +# define outlbranch() outop3str( "b") +# define outsbranch() outop2str( "j") +#endif +#ifdef MC6809 +# define outlbranch() outop3str( "LB") +# define outsbranch() outop2str( "B") +#endif + +#define MAXVISLAB 32 + +struct labdatstruct +{ + label_t labnum; /* 0 if not active */ + offset_t lablc; /* location counter for branch or label */ + char *labpatch; /* buffer ptr for branch, NULL for label */ + ccode_t labcond; /* condition code for branch */ +}; + +#ifdef I8088 +PRIVATE char lcondnames[][2] = /* names of long condition codes */ +{ + { 'e', 'q', }, { 'n', 'e', }, { 'r', ' ', }, { 'r', 'n', }, + { 'l', 't', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', 't', }, + { 'l', 'o', }, { 'h', 'i', }, { 'l', 'o', }, { 'h', 'i' }, +}; +PRIVATE char scondnames[][2] = /* names of short condition codes */ +{ + { 'e', ' ', }, { 'n', 'e', }, { 'm', 'p', }, { 'n', 0, }, + { 'l', ' ', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', ' ', }, + { 'b', ' ', }, { 'a', 'e', }, { 'b', 'e', }, { 'a', ' ', }, +}; +#endif + +#ifdef MC6809 +PRIVATE char condnames[][2] = /* names of condition codes */ +{ + { 'E', 'Q', }, { 'N', 'E', }, { 'R', 'A', }, { 'R', 'N', }, + { 'L', 'T', }, { 'G', 'E', }, { 'L', 'E', }, { 'G', 'T', }, + { 'L', 'O', }, { 'H', 'S', }, { 'L', 'S', }, { 'H', 'I', }, +}; +#endif + +PRIVATE label_t lasthighlab = 0xFFFF+1; /* temp & temp init so labels fixed */ + /* lint */ +PRIVATE label_t lastlab; /* bss init to 0 */ +PRIVATE offset_t lc; /* bss init to 0 */ + +PRIVATE struct labdatstruct vislab[MAXVISLAB]; /* bss, all labnum's init 0 */ +PRIVATE smalin_t nextvislab; /* bss init to NULL */ +PRIVATE struct symstruct *namedfirst; /* bss init to NULL */ +PRIVATE struct symstruct *namedlast; /* bss init to NULL */ + +FORWARD void addlabel P((ccode_pt cond, label_t label, char *patch)); +FORWARD struct labdatstruct *findlabel P((label_t label)); + +/* add label to circular list */ + +PRIVATE void addlabel(cond, label, patch) +ccode_pt cond; +label_t label; +char *patch; +{ + register struct labdatstruct *labptr; + + labptr = &vislab[nextvislab]; + labptr->labcond = cond; + labptr->labnum = label; + labptr->lablc = lc; + labptr->labpatch = patch; + if (++nextvislab == MAXVISLAB) + nextvislab = 0; +} + +/* bump location counter */ + +PUBLIC void bumplc() +{ + ++lc; +} + +/* bump location counter by 2 */ + +PUBLIC void bumplc2() +{ + lc += 2; +} + +/* bump location counter by 3 */ + +PUBLIC void bumplc3() +{ + lc += 3; +} + +/* clear out labels in function */ + +PUBLIC void clearfunclabels() +{ + register struct symstruct *symptr; + register struct symstruct *tmp; + + for (symptr = namedfirst; symptr != NULL;) + { + if (symptr->indcount == 2) + error("undefined label"); + symptr->indcount = 0; + tmp = symptr; + symptr = (struct symstruct *) symptr->type; + tmp->type = NULL; + } + namedlast = namedfirst = NULL; +} + +/* clear out labels no longer in buffer */ + +PUBLIC void clearlabels(patchbuf, patchtop) +char *patchbuf; +char *patchtop; +{ + register struct labdatstruct *labptr; + struct labdatstruct *labtop; + register char *labpatch; + + for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB]; + labptr < labtop; ++labptr) + if ((labpatch = labptr->labpatch) >= patchbuf && labpatch < patchtop) + labptr->labnum = 0; +} + +/* clear out labels in switch statement */ + +PUBLIC void clearswitchlabels() +{ + register struct symstruct *symptr; + + for (symptr = namedfirst; symptr != NULL; + symptr = (struct symstruct *) symptr->type) + if (symptr->indcount == 3) + { + equlab(symptr->offset.offlabel, lowsp); + symptr->indcount = 4; + } +} + +/* return location counter */ + +PUBLIC uoffset_t getlc() +{ + return (uoffset_t) lc; +} + +/* define location of label and backpatch references to it */ + +PUBLIC void deflabel(label) +label_t label; +{ + char *cnameptr; + struct labdatstruct *labmin; + struct labdatstruct *labmax; + struct labdatstruct *labmid; + struct labdatstruct *labptrsave; + offset_t nlonger; + + outnlabel(label); + { + register struct labdatstruct *labptr; + register char *labpatch; + + labmin = &vislab[0]; + labmax = &vislab[MAXVISLAB]; + labptr = labmid = &vislab[nextvislab]; + if (!watchlc) + do + { + if (labptr == labmin) + labptr = &vislab[MAXVISLAB]; + --labptr; + if (labptr->labnum == label) + { + if ((labpatch = labptr->labpatch) != NULL && + isshortbranch(lc - labptr->lablc)) + { +#ifdef I8088 /* patch "bcc(c) to j(c)(c)( ) */ + *labpatch = 'j'; + *(labpatch + 1) = + *(cnameptr = scondnames[labptr->labcond]); +#endif +#ifdef MC6809 +# ifdef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */ + *labpatch = 'B'; + *(labpatch + 4) = '\t'; /* redundant unless JMP */ + *(labpatch + 1) = + *(cnameptr = condnames[labptr->labcond]); +# else + if (labptr->labcond == RA) + strncpy(labpatch, "BRA\t\t", 5); + else + *labpatch = '\t'; + goto over; +# endif +#endif + *(labpatch + 2) = *(cnameptr + 1); + *(labpatch + 3) = ' '; +#ifdef MC6809 +# ifndef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */ + over: ; /* temp regression test kludge */ +# endif +#endif + nlonger = jcclonger; + if (labptr->labcond == RA) + nlonger = jmplonger; + lc -= nlonger; + labptrsave = labptr; + while (++labptr != labmid) + if (labptr == labmax) + labptr = &vislab[-1]; + else + labptr->lablc -= nlonger; + labptr = labptrsave; + } + } + } + while (labptr != labmid); + } + addlabel((ccode_pt) 0, label, (char *) NULL); +} + +PRIVATE struct labdatstruct *findlabel(label) +label_t label; +{ + register struct labdatstruct *labptr; + struct labdatstruct *labtop; + + for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB]; + labptr < labtop; ++labptr) + if (labptr->labnum == label) + { + if (labptr->labpatch != 0) + break; + return labptr; + } + return (struct labdatstruct *) NULL; +} + +/* reserve a new label, from top down to temp avoid renumbering low labels */ + +PUBLIC label_t gethighlabel() +{ + return --lasthighlab; +} + +/* reserve a new label */ + +PUBLIC label_t getlabel() +{ + return ++lastlab; +} + +/* jump to label */ + +PUBLIC void jump(label) +label_t label; +{ + lbranch(RA, label); +} + +/* long branch on condition to label */ + +PUBLIC void lbranch(cond, label) +ccode_pt cond; +label_t label; +{ +#ifdef I8088 + char *cnameptr; + +#endif + struct labdatstruct *labptr; + char *oldoutptr; + + if ((ccode_t) cond == RN) + return; + if ((labptr = findlabel(label)) != NULL && + isshortbranch(lc - labptr->lablc + 2)) + { + sbranch(cond, label); + return; + } + oldoutptr = outbufptr; + if (cond == RA) + outjumpstring(); + else + { + outlbranch(); +#ifdef I8088 + outbyte(*(cnameptr = lcondnames[(ccode_t) cond])); + outbyte(*(cnameptr + 1)); + if ((ccode_t) cond == LS || (ccode_t) cond == HS) + outbyte('s'); /* "blos" or "bhis" */ + else + outbyte(' '); + outtab(); + bumplc2(); + if (i386_32) + bumplc(); +#endif +#ifdef MC6809 + outcond(cond); + bumplc(); +#endif + } + outlabel(label); + outnl(); + if (labptr == NULL && oldoutptr < outbufptr) /* no wrap-around */ + addlabel(cond, label, oldoutptr); +} + +/* look up the name gsname in label space, install it if new */ + +PUBLIC struct symstruct *namedlabel() +{ + struct symstruct *symptr; + + gs2name[1] = 0xFF; + if ((symptr = findlorg(gs2name + 1)) == NULL) + { + symptr = addglb(gs2name + 1, vtype); + symptr->flags = LABELLED; + } + if (symptr->indcount < 2) + { + symptr->indcount = 2; + symptr->offset.offlabel = gethighlabel(); + if (namedfirst == NULL) + namedfirst = symptr; + else + namedlast->type = (struct typestruct *) symptr; + namedlast = symptr; + symptr->type = NULL; + } + return symptr; +} + +#ifdef MC6809 + +/* print condition code name */ + +PUBLIC void outcond(cond) +ccode_pt cond; +{ + char *cnameptr; + + outbyte(*(cnameptr = condnames[(ccode_t) cond])); + outbyte(*(cnameptr + 1)); + outtab(); +} + +#endif + +/* print label */ + +PUBLIC void outlabel(label) +label_t label; +{ + outbyte(LABELSTARTCHAR); + outhexdigs((uoffset_t) label); +} + +/* print label and newline */ + +PUBLIC void outnlabel(label) +label_t label; +{ + outlabel(label); +#ifdef LABELENDCHAR + outnbyte(LABELENDCHAR); +#else + outnl(); +#endif +} + +/* short branch on condition to label */ + +PUBLIC void sbranch(cond, label) +ccode_pt cond; +label_t label; +{ +#ifdef I8088 + char *cnameptr; + + if ((ccode_t) cond != RN) + { + outsbranch(); + outbyte(*(cnameptr = scondnames[(ccode_t) cond])); + outbyte(*(cnameptr + 1)); + outtab(); + outlabel(label); + outnl(); + } +#endif +#ifdef MC6809 + outsbranch(); + outcond(cond); + outlabel(label); + outnl(); +#endif +} + +/* reverse bump location counter */ + +PUBLIC void unbumplc() +{ + --lc; +} diff --git a/bcc-bruce/label.h b/bcc-bruce/label.h new file mode 100644 index 0000000..89c83d7 --- /dev/null +++ b/bcc-bruce/label.h @@ -0,0 +1,24 @@ +/* label.h - assembler-specific label characters for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* defaults */ + +#define CCNAMEPREFIX '_' +# define LABELENDCHAR ':' /* last char of ALL labels */ +#define LABELSTARTCHAR '.' /* first char of names of generated labels */ +#define LOCALSTARTCHAR '.' /* first char of local names */ +#define PUBLICENDCHAR ':' + +/* adjustments for other assemblers */ + +#ifdef AS09 +# undef LABELENDCHAR +#endif + +#ifdef XENIX_AS +# undef LABELSTARTCHAR +# define LABELSTARTCHAR 'L' +# undef LOCALSTARTCHAR +# define LOCALSTARTCHAR 'L' +#endif diff --git a/bcc-bruce/loadexp.c b/bcc-bruce/loadexp.c new file mode 100644 index 0000000..781dca0 --- /dev/null +++ b/bcc-bruce/loadexp.c @@ -0,0 +1,180 @@ +/* loadexp.c - load expressions for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "byteord.h" +#include "gencode.h" +#include "parse.h" +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "sizes.h" +#include "table.h" +#include "type.h" + +PUBLIC value_t constexpression() +{ + struct nodestruct *etmark; + struct nodestruct *exp; + struct symstruct *exprmark; + struct symstruct *symptr; + + etmark = etptr; + exprmark = exprptr; + exp = assignment_exp(); + etptr = etmark; + exprptr = exprmark; + if (exp->tag == LEAF && (symptr = exp->left.symptr)->storage == CONSTANT + && symptr->type->scalar & ISCALAR) + return symptr->offset.offv; + error("constant expression required"); + return 1; +} + +PUBLIC void initexpression(type) +struct typestruct *type; +{ + struct nodestruct *etmark; + struct nodestruct *exp; + struct symstruct *exprmark; + struct nodestruct *lhs; + struct symstruct *symptr; + uoffset_t value; + + if (gvarsymptr->storage != GLOBAL) + reslocals(); + exprmark = exprptr; + etmark = etptr; + exp = assignment_exp(); + if (gvarsymptr->storage != GLOBAL) + { + lhs = leafnode(exprsym(gvarsymptr)); + if (!(lhs->nodetype->constructor & (ARRAY | FUNCTION | VOID))) + lhs->flags = LVALUE; + makeleaf(node(ASSIGNOP, lhs, exp)); + } + else if (exp->tag != LEAF || + (symptr = exp->left.symptr)->storage != CONSTANT && + (symptr->storage != GLOBAL || symptr->indcount != 0 || + type->scalar & DLONG) || + (type->constructor | (symptr->type->constructor & ~FUNCTION)) & + ~(ARRAY | POINTER)) + error("initializer too complicated"); + else + { + if ((symptr->type->scalar | type->scalar) & RSCALAR) + { + /* Can only afford castnode if result known constant. */ + exp = castnode(type, exp); + symptr = exp->left.symptr; + } + if (type->scalar & RSCALAR) + { + if (type->scalar & FLOAT) + { + float val; + + val = *symptr->offset.offd; + deflong(((uoffset_t *) &val)[0]); + } + else + { + deflong(((uoffset_t *) symptr->offset.offd)[0]); + deflong(((uoffset_t *) symptr->offset.offd)[1]); + } + etptr = etmark; /* XXX - stuff from end of function */ + exprptr = exprmark; + return; + } + if (type->typesize == 1) + defbyte(); + else if (type->typesize == 2) + defword(); +#ifdef I8088 + else if (!(type->scalar & DLONG)) + defdword(); +#endif + switch (symptr->storage) + { + case CONSTANT: + value = (uoffset_t) symptr->offset.offv; + if (type->scalar & DLONG) + { + deflong(value); + break; + } + /* XXX - put sizes in type struct to avoid tests */ + if (type->scalar & CHAR) + value &= CHMASKTO; + else if (type->scalar & SHORT) + value &= shortmaskto; + else if (type->scalar & INT) + value &= intmaskto; + /* XXX - no longmaskto */ + outnhex(value); + break; + case GLOBAL: + if (symptr->flags & LABELLED) + { + outlabel(symptr->name.label); + outplus(); + outnhex((uoffset_t) symptr->offset.offi); + break; + } + if (*symptr->name.namep == 0) /* constant address */ + { + outnhex((uoffset_t) symptr->offset.offi); + break; + } + outccname(symptr->name.namep); + if (symptr->offset.offi != 0) + { + if (symptr->offset.offi > 0) + outplus(); + outshex(symptr->offset.offi); + } + outnl(); + break; + } + } + etptr = etmark; + exprptr = exprmark; +} + +PUBLIC struct typestruct *loadexpression(targreg, targtype) +store_pt targreg; +struct typestruct *targtype; +{ + struct nodestruct *etmark; + struct nodestruct *exp; + struct symstruct *exprmark; + + etmark = etptr; + exprmark = exprptr; + exp = expression(); + if (targtype != NULL) + exp = castnode(targtype, exp); + makeleaf(exp); + if (targtype == NULL) /* this is for a switch */ + { + targtype = exp->left.symptr->type; + if (!(targtype->scalar & (CHAR | INT)) + && (targtype->scalar & (LONG | DLONG)) != LONG) + { + if (targtype->scalar & SHORT) + targtype = promote(targtype); + else + { + error("non-integral selector in switch"); + targtype = itype; + } + makeleaf(exp = castnode(targtype, exp)); + } + } + load(exp->left.symptr, targreg); /* resets stack if value was there */ + etptr = etmark; + exprptr = exprmark; + return exp->left.symptr->type; +} diff --git a/bcc-bruce/longop.c b/bcc-bruce/longop.c new file mode 100644 index 0000000..8396392 --- /dev/null +++ b/bcc-bruce/longop.c @@ -0,0 +1,169 @@ +/* longop.c - software operations on longs for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "byteord.h" +#include "gencode.h" +#include "reg.h" +#include "scan.h" +#include "type.h" + +/*----------------------------------------------------------------------------- + longop(operation code, source leaf, target leaf) + handles all binary operations on longs + source and target must already have been converted to long, + (except source is int for shifts) and not more than singly indirect + hence they must be direct (in an index reg paired with DREG), + or singly indirect (local, global, or from an index reg) +-----------------------------------------------------------------------------*/ + +PUBLIC void longop(op, source, target) +op_pt op; +struct symstruct *source; +struct symstruct *target; +{ + store_pt reglist; + store_t regmark; + bool_t shiftflag; + scalar_t scalar; + offset_t spmark; + + pushlist(reglist = (regmark = reguse) & (OPREG | OPWORKREG)); + reguse &= ~reglist; + spmark = sp; + shiftflag = FALSE; + scalar = target->type->scalar; + if ((op_t) op == SLOP || (op_t) op == SROP) + shiftflag = TRUE; + else + scalar |= source->type->scalar; + if (source->indcount == 0 && !shiftflag || + source->storage & (DREG | OPREG | OPWORKREG)) + { + pres2(source, target); + push(source); + } + if (!shiftflag) + address(source); + load(target, OPREG); + if (source->storage == CONSTANT && shiftflag) + { + if (scalar & UNSIGNED) + target->type = ultype; + if ((op_t) op == SLOP) + source->offset.offv = lslconst(source->offset.offv, + target->storage); + else + source->offset.offv = lsrconst(source->offset.offv, + target->storage, scalar & UNSIGNED); + if (source->offset.offv == 0) + goto shiftdone; + } + load(source, OPWORKREG); + switch ((op_t) op) + { + case ADDOP: + call("ladd"); + break; + case ANDOP: + call("land"); + break; + case DIVOP: + call("ldiv"); + break; + case EOROP: + call("leor"); + break; + case EQOP: + call("lcmp"); + break; + case MODOP: + call("lmod"); + break; + case MULOP: + call("lmul"); + break; + case OROP: + call("lor"); + break; + case SLOP: + call("lsl"); + break; + case SROP: + call("lsr"); + break; + case SUBOP: + call("lsub"); + break; + } + if (scalar & UNSIGNED) + { + outbyte('u'); + target->type = ultype; + } + outlongendian(); + +shiftdone: + if ((reguse = regmark) & OPREG && op != EQOP) + load(target, getindexreg()); + if (reglist) + { +#ifdef I8088 + if (op == EQOP) + changesp(spmark, FALSE); + else +#endif + modstk(spmark); + poplist(reglist); + } +} + +/*----------------------------------------------------------------------------- + long1op(operation code, target leaf) + handles all unary operations on longs except inc/dec + target must be not more than singly indirect + hence it must be direct (in an index reg paired with DREG), + or singly indirect (local, global, or from an index reg) +-----------------------------------------------------------------------------*/ + +PUBLIC void long1op(op, target) +op_pt op; +struct symstruct *target; +{ + pushlist(reguse & OPREG); + load(target, OPREG); + if (op == NOTOP) + call("lcom"); + else if (op == NEGOP) + call("lneg"); + else + call("ltst"); + outlongendian(); + if (reguse & OPREG) + { + if (op != EQOP) + load(target, getindexreg()); + poplist(reguse & OPREG); + } +} + +PUBLIC void outlongendian() +{ +#ifdef MC6809 + outbyte('_'); +#endif +#if DYNAMIC_LONG_ORDER + if (long_big_endian) +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN + outnbyte('b'); +#endif +#if DYNAMIC_LONG_ORDER + else +#endif +#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 + outnbyte('l'); +#endif +} diff --git a/bcc-bruce/misc/sformat b/bcc-bruce/misc/sformat new file mode 100644 index 0000000..3dcb0c4 --- /dev/null +++ b/bcc-bruce/misc/sformat @@ -0,0 +1,56 @@ +int x; +.comm _x,2 + +int x = 1; +.global _x +.data +_x: +1 + +static int x; +.bss +_x: +.=.+2 + +static int x = 1; +.bss | implicit +.data +_x: +1 + +char x[10]; +.comm _x,12 + +char x[10] = "1"; +.globl _x +.data +_x: +.byte 61,0 +.=.+10 + +static char x[10]; +.bss; +_cc: +.=.+12 + +static char x[10] = "1"; +.data +_x: +.byte 61,0 +.=.+10 + +test() +.globl _test +.text +_test: + +{ +static int x; +.bss +L3: +.=.+2 + +static int x = 1; +.bss +.data +L5:1 diff --git a/bcc-bruce/misc/test/8queens.pas b/bcc-bruce/misc/test/8queens.pas new file mode 100644 index 0000000..f4f1b47 --- /dev/null +++ b/bcc-bruce/misc/test/8queens.pas @@ -0,0 +1,33 @@ +program eightqueens; + +var i: integer; + a: array[ 1..8 ] of boolean; + b: array[ 2..16] of boolean; + c: array[-7..7 ] of boolean; + x: array[ 1..8 ] of integer; + +procedure print; +var k: integer; +begin + for k:= 1 to 8 do write(x[k]:4); + writeln; +end; + +procedure try(i: integer); +var j: integer; +begin + for j:= 1 to 8 do if a[j] and b[i+j] and c[i-j] then + begin + x[i]:= j; + a[j]:= false; b[i+j]:= false; c[i-j]:= false; + if i < 8 then try(i+1) else print; + a[j]:= true; b[i+j]:= true; c[i-j]:= true; + end; +end; + +begin + for i:= 1 to 8 do a[i]:= true; + for i:= 2 to 16 do b[i]:= true; + for i:= -7 to 7 do c[i]:= true; + try(1); +end. diff --git a/bcc-bruce/misc/test/8queens.t b/bcc-bruce/misc/test/8queens.t new file mode 100644 index 0000000..8d20a4d --- /dev/null +++ b/bcc-bruce/misc/test/8queens.t @@ -0,0 +1,74 @@ +/* 8queens - straightforward translation of pascal version */ + +#define TRUE 1 +#define FALSE 0 + +int i; +char a[8],b[15],c[15],x[8]; + +main() +{ + for (i=0;i<8;i++) + a[i]=TRUE; + for (i=0;i<15;i++) + b[i]=TRUE; + for (i=0;i<15;i++) + c[i]=TRUE; + try(0); +} + +print() +{ + int k; + + for (k=0;k<8;k++) + write(x[k]); + writeln(); +} + +write(i) +int i; +{ + { +#asm + LDA #$20 + JSR $E820 + LDD .i,S + JSR $C682 +#endasm + } +} + +writeln() +{ + { +#asm + LDA #13 + JSR $E820 + LDA #10 + JSR $E820 +#endasm + } +} + +try(i) +int i; +{ + int j; + + for(j=0;j<8;j++) + if (a[j] && b[i+j] && c[7+i-j]) + { + x[i]=j; + a[j]=FALSE; + b[i+j]=FALSE; + c[7+i-j]=FALSE; + if (i<7) + try(i+1); + else + print(); + a[j]=TRUE; + b[i+j]=TRUE; + c[7+i-j]=TRUE; + } +} diff --git a/bcc-bruce/misc/test/atol.t b/bcc-bruce/misc/test/atol.t new file mode 100644 index 0000000..79c78b7 --- /dev/null +++ b/bcc-bruce/misc/test/atol.t @@ -0,0 +1,29 @@ +/* atol.c - long atol( char *s ) */ + +/* atol converts s to a long */ +/* leading spaces and tabs are ignored, an optional sign is recognised, */ +/* and the digits (0 to 9) following determine the long */ + +long atol( s ) +register char *s; +{ + char signflag; + long number; + + while ( *s == ' ' || *s == '\t') + s++; + signflag = 0; + if ( *s == '+' ) + s++; + else if ( *s == '-' ) + { + signflag = 1; + s++; + } + number = 0; + while ( *s >= '0' && *s <= '9' ) + number = 10 * number + *s++ - '0'; + if ( signflag ) + return -number; + return number; +} diff --git a/bcc-bruce/misc/test/bigsievec.t b/bcc-bruce/misc/test/bigsievec.t new file mode 100644 index 0000000..f3f76b2 --- /dev/null +++ b/bcc-bruce/misc/test/bigsievec.t @@ -0,0 +1,29 @@ +#define TRUE 1 +#define FALSE 0 +#define NITER 10 +#define SIZE 100000 + +char flags[SIZE+1]; + +main() +{ + int i,prime,k,count,iter; + + for (iter=0;iter<NITER;iter++) + { + count=0; + for (i=0;i<=SIZE;i++) + flags[i]=TRUE; + for (i=0;i<=SIZE;i++) + { + if (flags[i]) + { + prime=i+i+3; + for (k=i+prime;k<=SIZE;k=k+prime) + flags[k]=FALSE; + count++; + } + } + } + printf( "%d primes\n", count ); +} diff --git a/bcc-bruce/misc/test/bt.t b/bcc-bruce/misc/test/bt.t new file mode 100644 index 0000000..b88836c --- /dev/null +++ b/bcc-bruce/misc/test/bt.t @@ -0,0 +1,373 @@ +/* bt.t - bug tests */ + +test1() +{ + char *p, *q; + + q += *p++; +} + +test2() +{ + int i,j,k,a[2],b[2],c[2]; + + i = a[i] + b[j] + c[k]; +} + +test3() +{ + int *p, *q; + int i; + + i = p - q; +} + +test4() +{ + int a[2]; + int *p; + + p = a; + test4(a); +} + +test5() +{ + char c; + + test4(c); +} + +test6(a,b) +int b,a; +{ + int i; + + i = b; + i = a; +} + +test7() +{ + int a[2]; + int *p; + + p = a + 1; +} + +int *test8(); + +int *test8() +{ + int i; + + if ( test8() == i ) + ; + i = *test8(); +} + +test9() +{ + int i,j,k,n; + + if ((i < 0 || j > 100) && (k < 0 || n > 50)) + i = 1; +} + +struct complex +{ + int re; + int im; +} + znum, *zptr, zarr[10], *zptrarr[10]; + +test10() +{ + int i; + + znum.re = i; + znum.im = 1; + zptr -> re = 1; + zptr -> im = i; + zarr[3].im = i; + zptrarr[4] -> im = 1; +} + +test11() +{ + char symtab[100]; + + char *p; + + if (p > symtab) + ; +} + +test12() +{ +char symtab[100]; + + char *p; + + p = symtab - 21; +} + +test13() +{ + char a[10]; + int i; + + i = a - 1; +} + +test14() +{ + int i, **pi; + + **pi = i; +} + +test15() +{ + int i, j; + + if ( (i = j ) == 2 ) + test(); +} + +test16() +{ + struct cx3 + { + int re3; + char im3; + } + z[10], *pz, *pz1; + int i; + + i = z[i].re3; + i = pz1 - pz; +} + +test17() +{ + int i; + char c; + + c &= ~i; +} + +test18() +{ + typedef int (*PFI)(); + PFI h(); + + (*h())( 0 ); +} + +test19() +{ + register int *p, *q; + int ***z,i,a[10]; + + test(***z + a[i]); +} + +char a[2][3][5]; + +char *p = a; +char *q = a[1]; +char *r = a[1][2]; + +char test20(); +char (*test21)(); + +test22() +{ + char i,k; + char *p; + + p = a; + p = a[1]; + p = a[1][2]; + p = a[k]; + p = a[k][k]; + i = sizeof a; + i = sizeof a[k]; + i = sizeof a[k][k]; + i = sizeof test20; + i = sizeof test21; + i = sizeof test20(); + i = sizeof (*test21)(); +} + +test23() +{ + long *pl; + int i; + char *s; + + *pl += i; + *s += *pl; +} + +test24() +{ + float f; + double *dp1(), *dp2(); + + f = *dp1()++; /* illegal */ + f = *++dp1(); /* illegal */ + f = *dp1() + *dp2(); /* bad code (pushes ptr to doubly indirect) */ +} + +test25() +{ + test25( "2"[1] ); /* added 1 to label number, not label address */ +} + +struct stat +{ + int st_dev; +}; + +test26( buf ) +struct stat buf; /* wrong declare, s.b. struct stat *buf */ +{ + buf->st_dev = 1; /* error caused null pointer to be dereferenced */ +} + +union +{ + long l; +} + test27; + +test28() +{ + test27.l = test27.l + 1; /* produced poor code */ +} + +int test29 = (char) 1; /* cast was clobbering the global symptr */ + +struct { int i; } test30; + +test31() +{ + return test30; /* a structure cannot be returned (yet) */ +} + +int *test32, test33() {} /* this is illegal */ + +test35() +{ + char a[1]; + char b[1]; + int i; + + i = i == 1 ? a : b; /* arrays were not converted to ptrs */ +} + +test36() +{ + struct fp + { + struct filp *fp_filp[1]; + }; + struct filp + { + int filp_int; + long filp_long; + }; + int i; + register char *junk; + register struct fp *cp; + + cp->fp_filp[i]->filp_int++; /* used to push lvalue */ + cp->fp_filp[i]->filp_long++; /* used to push lvalue */ + cp->fp_filp[i]->filp_int += 1; /* was OK */ + cp->fp_filp[i]->filp_long += 1; /* used to load long into DREG:DREG */ +} + +test37() +{ + unsigned u; + + u = -u; /* used to give botched nodetype */ +} + +test38() +{ + char c; + int i; + + i = -c; /* did i = (char) -c for a time */ +} + +test39() +{ + int i; + + i = (char) 1000; /* the constant wasn't being truncated */ +} + +#define test40(x) (x) + +test41() +{ + int i; + int j; + int k; + + i = test40( j + /* was confused by EOL in macro argument */ + k ); +} + +test42() +{ + register char *junk1; + register char *junk2; + long *longptr; + long longfn(); + + *longptr = longfn(); /* used to run out of index regs */ +} + +test43() +{ + register char *jnk1, *junk2; + unsigned char *bp; + struct FILE_BUF + { + char *bufp; + } *op; + + *op->bufp++ = *bp; /* used to push lvalue */ +} + +test44() +{ + register char *x, *y; + int i; + char a[2]; + char **p; + + a[**p] = **p; /* used to push lvalue */ +} + +struct test45 +{ + int i; + int j; +} test45[10]; + +test46() +{ + register char *p, *q; + int i; + int j; + + test45[i] = test45[j]; /* used to push lvalue */ +} + +int (*test100( x )() {} /* this is legal, keep last avoid swallowing */ diff --git a/bcc-bruce/misc/test/cast.t b/bcc-bruce/misc/test/cast.t new file mode 100644 index 0000000..554cb93 --- /dev/null +++ b/bcc-bruce/misc/test/cast.t @@ -0,0 +1,144 @@ +/* cast.t */ + +char c; +unsigned char uc; +short s; +unsigned short us; +int i; +unsigned int ui; +long l; +unsigned long ul; +float f; +double d; +int *p; + +cast() +{ + c = (char) c; + uc = (unsigned char) c; + s = (short) c; + us = (unsigned short) c; + i = (int) c; + ui = (unsigned int) c; + l = (long) c; + ul = (unsigned long) c; + f = (float) c; + d = (double) c; + p = (int *) c; + + c = (char) uc; + uc = (unsigned char) uc; + s = (short) uc; + us = (unsigned short) uc; + i = (int) uc; + ui = (unsigned int) uc; + l = (long) uc; + ul = (unsigned long) uc; + f = (float) uc; + d = (double) uc; + p = (int *) uc; + + c = (char) s; + uc = (unsigned char) s; + s = (short) s; + us = (unsigned short) s; + i = (int) s; + ui = (unsigned int) s; + l = (long) s; + ul = (unsigned long) s; + f = (float) s; + d = (double) s; + p = (int *) s; + + c = (char) us; + uc = (unsigned char) us; + s = (short) us; + us = (unsigned short) us; + i = (int) us; + ui = (unsigned int) us; + l = (long) us; + ul = (unsigned long) us; + f = (float) us; + d = (double) us; + p = (int *) us; + + c = (char) i; + uc = (unsigned char) i; + s = (short) i; + us = (unsigned short) i; + i = (int) i; + ui = (unsigned int) i; + l = (long) i; + ul = (unsigned long) i; + f = (float) i; + d = (double) i; + p = (int *) i; + + c = (char) ui; + uc = (unsigned char) ui; + s = (short) ui; + us = (unsigned short) ui; + i = (int) ui; + ui = (unsigned int) ui; + l = (long) ui; + ul = (unsigned long) ui; + f = (float) ui; + d = (double) ui; + p = (int *) ui; + + c = (char) l; + uc = (unsigned char) l; + s = (short) l; + us = (unsigned short) l; + i = (int) l; + ui = (unsigned int) l; + l = (long) l; + ul = (unsigned long) l; + f = (float) l; + d = (double) l; + p = (int *) l; + + c = (char) ul; + uc = (unsigned char) ul; + s = (short) ul; + us = (unsigned short) ul; + i = (int) ul; + ui = (unsigned int) ul; + l = (long) ul; + ul = (unsigned long) ul; + f = (float) ul; + d = (double) ul; + p = (int *) ul; + + c = (char) f; + uc = (unsigned char) f; + s = (short) f; + us = (unsigned short) f; + i = (int) f; + ui = (unsigned int) f; + l = (long) f; + ul = (unsigned long) f; + f = (float) f; + d = (double) f; + + c = (char) d; + uc = (unsigned char) d; + s = (short) d; + us = (unsigned short) d; + i = (int) d; + ui = (unsigned int) d; + l = (long) d; + ul = (unsigned long) d; + f = (float) d; + d = (double) d; + + c = (char) p; + uc = (unsigned char) p; + s = (short) p; + us = (unsigned short) p; + i = (int) p; + ui = (unsigned int) p; + l = (long) p; + ul = (unsigned long) p; + p = (int *) p; +} diff --git a/bcc-bruce/misc/test/cast1.t b/bcc-bruce/misc/test/cast1.t new file mode 100644 index 0000000..a4c15d5 --- /dev/null +++ b/bcc-bruce/misc/test/cast1.t @@ -0,0 +1,144 @@ +/* cast1.t */ + +char c; +unsigned char uc; +short s; +unsigned short us; +int i; +unsigned int ui; +long l; +unsigned long ul; +float f; +double d; +int *p; + +cast() +{ + c = c; + uc = c; + s = c; + us = c; + i = c; + ui = c; + l = c; + ul = c; + f = c; + d = c; + p = c; + + c = uc; + uc = uc; + s = uc; + us = uc; + i = uc; + ui = uc; + l = uc; + ul = uc; + f = uc; + d = uc; + p = uc; + + c = s; + uc = s; + s = s; + us = s; + i = s; + ui = s; + l = s; + ul = s; + f = s; + d = s; + p = s; + + c = us; + uc = us; + s = us; + us = us; + i = us; + ui = us; + l = us; + ul = us; + f = us; + d = us; + p = us; + + c = i; + uc = i; + s = i; + us = i; + i = i; + ui = i; + l = i; + ul = i; + f = i; + d = i; + p = i; + + c = ui; + uc = ui; + s = ui; + us = ui; + i = ui; + ui = ui; + l = ui; + ul = ui; + f = ui; + d = ui; + p = ui; + + c = l; + uc = l; + s = l; + us = l; + i = l; + ui = l; + l = l; + ul = l; + f = l; + d = l; + p = l; + + c = ul; + uc = ul; + s = ul; + us = ul; + i = ul; + ui = ul; + l = ul; + ul = ul; + f = ul; + d = ul; + p = ul; + + c = f; + uc = f; + s = f; + us = f; + i = f; + ui = f; + l = f; + ul = f; + f = f; + d = f; + + c = d; + uc = d; + s = d; + us = d; + i = d; + ui = d; + l = d; + ul = d; + f = d; + d = d; + + c = p; + uc = p; + s = p; + us = p; + i = p; + ui = p; + l = p; + ul = p; + p = p; +} diff --git a/bcc-bruce/misc/test/castest.t b/bcc-bruce/misc/test/castest.t new file mode 100644 index 0000000..ae27f7b --- /dev/null +++ b/bcc-bruce/misc/test/castest.t @@ -0,0 +1,74 @@ +/* castest.c */ + +/* +#define signedchar +#define bigints +*/ +#define unsigchar +#define unsigshort +#define unsiglong + +#define TEST(u,c) if ( (u) != (c) )\ + { printf( "u != c\n" ); ++bad; } ++possible + +main() +{ + int bad; + int possible; + char c; +#ifdef signedchar + signed char sc; +#endif +#ifdef unsigchar + unsigned char uc; +#endif + short s; +#ifdef unsigshort + unsigned short us; +#endif + int i; + unsigned u; + long l; +#ifdef unsiglong + unsigned long ul; +#endif + + bad = possible = 0; + u = 0x1ff; + c = (char) u; + if ( c < 0 ) + printf( "characters are signed\n" ); + TEST((char)u,c); + i = (int)(char) u; + TEST(i,(int)c); + TEST((int)(char)u,i); + +#ifdef signedchar + sc = (signed char) u; + if ( sc >= 0 ) + printf( "??? signed char not signed\n" ); + TEST((signed char)u,sc); + TEST((int)(signed char)u,(int)sc); + i = (int) sc; + TEST((int)(signed char)u,i); +#endif + +#ifdef bigints + u = 0x1ffff; + s = (short) u; + TEST((short)u,s); + TEST((int)(short)u,(int)s); + i = (int) s; + TEST((int)(short)u,i); + +#ifdef unsigshort + us = (unsigned short) u; + TEST((unsigned short)u,us); + TEST((int)(unsigned short)u,(int)us); + i = (int) us; + TEST((int)(unsigned short)u,i); +#endif +#endif + + printf( "%d bad out of a possible %d\n", bad, possible ); +} diff --git a/bcc-bruce/misc/test/ctype.t b/bcc-bruce/misc/test/ctype.t new file mode 100644 index 0000000..93b3e4f --- /dev/null +++ b/bcc-bruce/misc/test/ctype.t @@ -0,0 +1,38 @@ +/* ctype.h */ + +#define _C 1 /* control */ +#define _D 2 /* digit */ +#define _L 4 /* lower */ +#define _P 8 /* punctuation */ +#define _S 16 /* space */ +#define _U 32 /* upper */ +#define _UN 64 /* underline */ +#define _X '\200' /* hex digit, not digit */ + +extern char _ctype_[]; + +#define _ct1_ (_ctype_+1) + +#define isalnum(c) (_ct1_[c]&(_U|_L|_D)) +#define isalpha(c) (_ct1_[c]&(_U|_L)) +#define isascii(i) ((unsigned)(i)<=0x7f) +#define isalpha(c) (_ct1_[c]&(_U|_L)) +#define iscntrl(c) (_ct1_[c]&_C) +#define iscsym(c) (_ct1_[c]&(_U|_L|_D|_UN)) +#define iscsymf(c) (_ct1_[c]&(_U|_L|_UN)) +#define isdigit(c) (_ct1_[c]&_D) +#define isgraph(c) (_ct1_[c]&(_U|_L|_D|_P)) +#define islower(c) (_ct1_[c]&_L) +/* isodigit(i) is a function */ +/* isprint(i) is a function */ +#define ispunct(c) (_ct1_[c]&_P) +#define isspace(c) (_ct1_[c]&_S) +#define isupper(c) (_ct1_[c]&_U) +#define isxdigit(c) (_ct1_[c]&(_D|_X)) + +#define toascii(i) ((i)&0x7f) +/* toint(i) is a function */ +/* tolower(i) is a function */ +#define _tolower(c) ((c)+('a'-'A')) +/* toupper(i) is a function */ +#define _toupper(c) ((c)+('A'-'a')) diff --git a/bcc-bruce/misc/test/error.t b/bcc-bruce/misc/test/error.t new file mode 100644 index 0000000..24e302a --- /dev/null +++ b/bcc-bruce/misc/test/error.t @@ -0,0 +1,78 @@ +static char *errorstring[] = +{ + "# in a macro: not preprocessed", + "already declared", + "array of functions is illegal", + "bad address", + "bad case label", + "bad character constant", + "bad character", + "bad control", + "bad default label", + "bad expression", + "bad file name", + "bad indirection count", + "bad initializer address", + "bad register store", + "call of non-function", + "can't continue in switch", + "can't index", + "can't load char to index reg", + "can't open", + "can't open input", + "can't open output", + "case can't be reached with char switch", + "constant expression expected", + "else without if", + "end of file in #asm", + "end of file in #define", + "end of file in comment", + "end of file in failed #if", + "end of file in macro parameter expansion", + "end of file in string constant", + "end of line in string constant", + "endif without if", + "function returning array is illegal", + "function returning function is illegal", + "function returning structure is illegal", + "if stack overflow", + "illegal indirection", + "illegal macro name", + "illegal non-external function", + "illegal symbol name", + "illegal type conversion", + "illegal type name", + "initializer too complicated", + "input error", + "load of long constants not implemented", + "loading direct long with offset not implemented", + "local symbol table overflow", + "macro stack overflow", + "missing '('", + "missing while at end of do-while", + "need '", + "need int or char", + "need lvalue", + "need scalar or ptr type", + "need structure", + "no active fors, switches or whiles", + "not in a compound statement", + "null dimension", + "out of index registers", + "redefined macro", + "repeated argument", + "repeated default label", + "repeated parameter", + "table full", + "too few macro parameters", + "too many active whiles", + "too many cases", + "too many macro parameters", + "too many open compound statements", + "too many parameters", + "undeclared variable", + "undefined structure element", + "undefined structure", + "unsigned ints only", + "variable not in argument list" +}; diff --git a/bcc-bruce/misc/test/extern.t b/bcc-bruce/misc/test/extern.t new file mode 100644 index 0000000..dac5f5c --- /dev/null +++ b/bcc-bruce/misc/test/extern.t @@ -0,0 +1,236 @@ +/* extern.c - external declarations (K & R p218-9) */ + +#include "def.h" +#include "globvar.h" +#include "symbol.h" + +struct typestruct *declarator(); +struct typestruct *extypespec(); +int paramlist(); +struct typestruct *typespec(); + +/*============================================================================= + -- notation is 1st attempt at EBNF (see Modula-2 book) + program = { type-definition | function-or-data-definition }. + type-definition = "typedef" type-definition-list. +=============================================================================*/ + +program() +{ + nextsym(); + while ( sym != EOFSYM ) + { + if ( sym = TYPEDEFDECL ) + deftypes(); + else + functordata(); + } +} + +/*============================================================================= + type-definition-list. -- not implemented +=============================================================================*/ + +deftypes() +{} + +/*============================================================================= + function-or-data-definition = external-type-specification + ( function-definition | init-declarators ). + function-definition = "(" parameter-list ")" arg-list compound-statement. + -- this is different from K & R who omit typedefs and static functions +=============================================================================*/ + +functordata() +{ + struct typestruct *type; + int nargs; + + type = extypespec(); + if ( sym == LPAREN ) + { + nextsym(); + nargs = paramlist(); + need( RPAREN ); + arglist( nargs ); + need( LBRACE ); + compound( 1 + locptr-pstartloc );/* 1 = function flag, rest = nargs */ + oldlevel(); + } + else + initdecl( type ); +} + +/*============================================================================= + external-type-specification = extern-sc type-specifier declarator. + extern-sc = [ extern | static ]. +=============================================================================*/ + +struct typestruct *extypespec() +{ + int sc; + + switch( sym ) + { + case EXTERNDECL: + case STATICDECL: + sc = sym; nextsym(); break; + default: + sc = EXTERNDECL; break; + } + return declarator( typespec() ); +} + +/*============================================================================= + parameter-list = [identifier { "," identifier }]. +=============================================================================*/ + +int paramlist() +{ + int nargs; + + locptr = pstartloc; + newlevel(); + nargs = 0; + while ( sym == IDENT ) + { + addloc( gsname, itype, 0 ); /* fix up types and offsets later */ + nextsym(); + ++nargs; + if ( sym != COMMA ) + break; + nextsym(); + } + return nargs; +} + +/*============================================================================= + arg-list = +=============================================================================*/ + +arglist( nargs ) +int nargs; +{ + struct symstruct *symptr; + int argsize, argsp; + int lastsym; + struct typestruct *basetype; + char declflag; + + declflag = TRUE; + do + { + switch( sym ) + { + case TYPEDECL: + basetype = gsymptr->type; + nextsym(); + getarg1( basetype ); + break; + case STRUCTDECL: + case UNIONDECL: + lastsym = sym; + nextsym(); + getarg( declsu( lastsym ) ); + break; + case AUTODECL: + case EXTERNDECL: + case REGDECL: + case STATICDECL: + case SEMICOLON: + nextsym(); + break; + default: + declflag = FALSE; + break; + } + } + while ( declflag ); + argsp = -2; + symptr = pstartloc; + while ( nargs && symptr < locptr ) /* convert arg sizes to offsets */ + { + argsize = symptr->offset; + if ( symptr->type == ctype ) + { + ++argsp; + --argsize; + } + symptr->offset = argsp; + argsp += argsize; + if ( symptr == pstartloc ) + argsp += 2; + --nargs; + ++symptr; + } + if ( nargs ) + error( "arguments not all declared" ); +} + +/* getarg( basetype ) - fill in argument types and sizes */ + +getarg1( basetype ) +struct typestruct *basetype; +{ + char sname[NAMESIZE]; + struct typestruct *type; + int size; + struct symstruct *symptr; + + if ( sym != SEMICOLON ) + while ( TRUE ) + { + type = basetype; + size = getvar( sname, &type ); + if ( (symptr = findlorg( sname )) == NULL || symptr->level != ARGLEVEL ) + error( "variable not in argument list" ); + else if ( symptr->offset != 0 ) /* already in arg list */ + multidecl( sname, type, symptr ); + else + { + if ( size < 2 || type->typeop == ATYPEOP ) + size = 2; + symptr->offset = size; + symptr->type = type; + } + if ( sym == COMMA ) + nextsym(); + else + break; + } + ns(); +} + +struct typestruct *declarator( basetype ) +struct typestruct *basetype; +{ + char sname[NAMESIZE]; + int size; + struct symstruct *multi; + + size = getvar( sname, &type ); + if ( multi = findlorg( sname ) ) + multidecl( sname, type, multi ); + else + addglb( sname, type, size ); + nextsym(); +} + +struct typestruct *typespec() +{ + int lastsym; + + switch( sym ) + { + case TYPEDECL: + nextsym(); + return gsymptr->type; + case STRUCTDECL: + case UNIONDECL: + lastsym = sym; + nextsym(); + return declsu( lastsym ); + default: + return itype; + } +} diff --git a/bcc-bruce/misc/test/hilbert.t b/bcc-bruce/misc/test/hilbert.t new file mode 100644 index 0000000..e18dc63 --- /dev/null +++ b/bcc-bruce/misc/test/hilbert.t @@ -0,0 +1,169 @@ +/* hilbert.c */ + +/* S1 stuff + +#define PIFBUF ( *(struct IFBUF **) 0xf010 ) +#define PSET 2 + +struct IFBUF +{ + char ERR; + char COMMAND; + char COLOR; + char PLOTOPTION; + int LINESTYLE; + int X1; + int Y1; + int X2; + int Y2; + char BFFLAG; +}; +end of S1 stuff */ + +/* L3 stuff */ + +#define PIFBUF ( (struct IFBUF *) 0xa1 ) +#define PSET 1 + +struct IFBUF +{ + char PLOTOPTION; + char junk1[0xa8-0xa2]; + int X1; + int Y1; + int X2; + int Y2; + char junk2[0xf0-0xb0]; + char ERR; /* this to BFFLAG are dummies to keep S1 code */ + char COMMAND; + int LINESTYLE; + char BFFLAG; + char junk3[0x3ea-0xf5]; + char COLOR; +}; + +#define H0 512 /* square size */ +#define XOFFS 80 /* offset to centre square */ +#define XNUM 15 /* scale 512 * 15/16 = 480 */ +#define XDENOM 16 +#define YNUM 25 /* scale 512 * 25/64 = 200 */ +#define YDENOM 64 /* to give max height, dot ratio 480/200 = 2.4 */ + +int h, x, y; + +main() +{ + int i, x0, y0; + char color; + + PIFBUF->PLOTOPTION = PSET; + PIFBUF->LINESTYLE = /* normal */ + PIFBUF->COMMAND = /* ?? */ + PIFBUF->BFFLAG = 0; /* not a box */ + color = i = 0; + x0 = y0 = (h = H0)/2; + while ( h > 1 ) + { + ++i; + h = h/2; + if ( ++color > 7 ) + color = 1; + gcolor( color ); + x = x0 += h/2; + y = y0 += h/2; + glocate(); + a( i ); + } +} + +a( i ) +int i; +{ + if ( --i >= 0 ) + { + d( i ); x -= h; plot(); + a( i ); y -= h; plot(); + a( i ); x += h; plot(); + b( i ); + } +} + +b( i ) +int i; +{ + if ( --i >= 0 ) + { + c( i ); y += h; plot(); + b( i ); x += h; plot(); + b( i ); y -= h; plot(); + a( i ); + } +} + +c( i ) +int i; +{ + if ( --i >= 0 ) + { + b( i ); x += h; plot(); + c( i ); y += h; plot(); + c( i ); x -= h; plot(); + d( i ); + } +} + +d( i ) +int i; +{ + if ( --i >= 0 ) + { + a( i ); y -= h; plot(); + d( i ); x -= h; plot(); + d( i ); y += h; plot(); + c( i ); + } +} + +glocate() +{ + PIFBUF->X2 = x - x * (XDENOM - XNUM) / XDENOM + XOFFS; + PIFBUF->Y2 = (y * YNUM) / YDENOM; +} + +/* S1 gcolor and plot + +gcolor( color ) +int color; +{ + PIFBUF->COLOR = color; +} + +plot() +{ + PIFBUF->X1 = PIFBUF->X2; + PIFBUF->Y1 = PIFBUF->Y2; + glocate(); +#asm + SWI2 + FDB $4201 call LINEMA +#endasm +} + +end S1 plot */ + +gcolor( color ) +int color; +{ + PIFBUF->COLOR = color | 0x10; +} + +plot() +{ + PIFBUF->X1 = PIFBUF->X2; + PIFBUF->Y1 = PIFBUF->Y2; + glocate(); +#asm + JSR $D709 + JSR $D79A +#endasm +} diff --git a/bcc-bruce/misc/test/longtest.c b/bcc-bruce/misc/test/longtest.c new file mode 100644 index 0000000..0c0bfe0 --- /dev/null +++ b/bcc-bruce/misc/test/longtest.c @@ -0,0 +1,24 @@ +int i,j; +long m,n; + +main() +{ + while ( 1 ) + { + if ( scanf( "%ld %ld", &m, &n ) <= 0 ) + exit( 0 ); + printf( "m = %ld n = %ld m + n = %ld m - n = %ld m * n = %ld\n", + m, n, m + n, m - n, m * n ); + printf( "m = %ld n = %ld m / n = %ld m %% n = %ld\n", + m, n, m / n, m % n ); + printf( "m = %ld n = %ld m&n = %ld m | n = %ld m^n = %ld\n", + m, n, m & n, m | n, m ^ n ); + printf( "m = %ld n = %ld m << n = %ld m >> n = %ld\n", + m, n, m << (int) n, m >> (int) n ); + printf( + "m = %ld n = %ld m < n is %d m == n is %d m > n is %d m == 0 is %d\n", + m, n, m < n, m == n, m > n, m == 0 ); + printf( "m = %ld n = %ld -m = %ld ~m = %ld ++m = %ld --n = %ld\n", + m, n, -m, ~m, ++m, --n ); + } +} diff --git a/bcc-bruce/misc/test/longtest.dat b/bcc-bruce/misc/test/longtest.dat new file mode 100644 index 0000000..a1c7998 --- /dev/null +++ b/bcc-bruce/misc/test/longtest.dat @@ -0,0 +1,15 @@ +1 1 +-1 1 +1 -1 +-1 -1 +2 3 +4 5 +234234 34554 +4534534 34535 +345324523 3245325 +345435345 319755 +34534 345 +-352351235 23535 +533512351 -3535345 +-351351313 -12235 +123456789 987654321 diff --git a/bcc-bruce/misc/test/longtest.mak b/bcc-bruce/misc/test/longtest.mak new file mode 100755 index 0000000..454a4e8 --- /dev/null +++ b/bcc-bruce/misc/test/longtest.mak @@ -0,0 +1,3 @@ +cc -o cclongtest longtest.c +sc longtest.c sclongtest.s +cc -o sclongtest sclongtest.s $HOME/lib/libcb.a $HOME/lib/liblb.a diff --git a/bcc-bruce/misc/test/longtest.sh b/bcc-bruce/misc/test/longtest.sh new file mode 100755 index 0000000..e76f98a --- /dev/null +++ b/bcc-bruce/misc/test/longtest.sh @@ -0,0 +1,4 @@ +./sclongtest < longtest.dat >scl.out +./cclongtest < longtest.dat >ccl.out +diff scl.out ccl.out >longtest.diff +cat longtest.diff diff --git a/bcc-bruce/misc/test/miniltest.t b/bcc-bruce/misc/test/miniltest.t new file mode 100644 index 0000000..78097d4 --- /dev/null +++ b/bcc-bruce/misc/test/miniltest.t @@ -0,0 +1,72 @@ +long x; +int i; +unsigned u; + +long test1(x) +long x; +{ + return x; +} + +long test2(x) +int x; +{ + return x; +} + +main() +{ + printlong( "x=1 is ", x = 1 ); + printlong( "test1(x) is ", test1(x) ); + printlong( "test1(1L) is ", test1(1L) ); + printlong( "x = test1(1L) is ", x = test1(1L) ); + printlong( "x = test1(x=1) is ", x = test1(x=1) ); + printlong( "i=1 is ", (long) (i = 1) ); + printlong( "test2(i) is ", test2(i) ); + printlong( "test2(1) is ", test2(1) ); + printlong( "i = test2(1) is ", (long) (i = test2(1)) ); + printlong( "i = test2(i=1) is ", (long) (i = test2(i=1)) ); + printlong( "(long) (i = -1) is ", (long) (i=-1) ); + printlong( "(long) (u = -1) is ", (long) (u=-1) ); + printlong( "x = -1 is ", x = -1 ); +} + +printlong( s, x ) +char *s; +long x; +{ + printf( "%s", s ); + if ( x & 0x80000000 ) + { + putchar( '-' ); + x = -x; + } + printf( "%08lx", (x >> 16) + (x << 16) ); + putchar( '\n' ); +} + +outulhex( pnum ) +char *pnum; +{ + int i; + + for ( i = 3; i >=0; --i ) + p2( pnum[i] ); +} + +p2(i) +int i; +{ + p1(i>>4); + p1(i); +} + +p1(num) +int num; +{ + int digit; + + if ( (digit = num & 0xf) >= 10 ) + digit += 'A' - ('9' + 1); + putchar( digit + '0' ); +} diff --git a/bcc-bruce/misc/test/op1.t b/bcc-bruce/misc/test/op1.t new file mode 100644 index 0000000..614e093 --- /dev/null +++ b/bcc-bruce/misc/test/op1.t @@ -0,0 +1,120 @@ +/* op1.t - test and, or (eor same as or ) */ + +char cfn(); +int ifn(); + +char *op1() +{ + char c, *pc, **ppc; + int i, *pi, **ppi; + + i = c & 1; + i = 1 & c; + i = i & 1; + i = 1 & i; + + i = c & 500; + i = 500 & c; + i = i & 500; + i = 500 & i; + + i = c | 1; + i = 1 | c; + i = i | 1; + i = 1 | i; + + i = c | 500; + i = 500 | c; + i = i | 500; + i = 500 | i; + + i = c & c; + i = c & i; + i = i & c; + i = i & i; + + i = c | c; + i = c | i; + i = i | c; + i = i | i; + + i = c & c++; + i = c & i++; + i = i & c++; + i = i & i++; + + i = c++ & c; + i = i++ & c; + i = c++ & i; + i = i++ & i; + + i = c | c++; + i = c | i++; + i = i | c++; + i = i | i++; + + i = c++ | c; + i = i++ | c; + i = c++ | i; + i = i++ | i; + + i = c & cfn(); + i = c & ifn(); + i = i & cfn(); + i = i & ifn(); + + i = cfn() & c; + i = ifn() & c; + i = cfn() & i; + i = ifn() & i; + + i = c | cfn(); + i = c | ifn(); + i = i | cfn(); + i = i | ifn(); + + i = cfn() | c; + i = ifn() | c; + i = cfn() | i; + i = ifn() | i; + + i = *pc & c++; + i = *pc & i++; + i = *pi & c++; + i = *pi & i++; + + i = c++ & *pc; + i = i++ & *pc; + i = c++ & *pi; + i = i++ & *pi; + + i = *pc | c++; + i = *pc | i++; + i = *pi | c++; + i = *pi | i++; + + i = c++ | *pc; + i = i++ | *pc; + i = c++ | *pi; + i = i++ | *pi; + + i = **ppc & c++; + i = **ppc & i++; + i = **ppi & c++; + i = **ppi & i++; + + i = c++ & **ppc; + i = i++ & **ppc; + i = c++ & **ppi; + i = i++ & **ppi; + + i = **ppc | c++; + i = **ppc | i++; + i = **ppi | c++; + i = **ppi | i++; + + i = c++ | **ppc; + i = i++ | **ppc; + i = c++ | **ppi; + i = i++ | **ppi; +} diff --git a/bcc-bruce/misc/test/opcmp.t b/bcc-bruce/misc/test/opcmp.t new file mode 100644 index 0000000..28bd1a2 --- /dev/null +++ b/bcc-bruce/misc/test/opcmp.t @@ -0,0 +1,106 @@ +/* opcmp.t - test logical compare operations */ + +/* only doing chars, shorts, ints and unsigneds */ +/* not doing longs, floats or doubles */ + +/* short = int, so only a few examples */ +/* unsigned like int, so only a few examples */ +/* all examples < */ + +op1() +{ + char c, *pc, **ppc, cfn(); + short s, *ps, **pps, sfn(); + int i, *pi, **ppi, ifn(); + unsigned u, *pu, **ppu, ufn(); + + c < 0; + 0 < c; + i < 0; + 0 < i; + + s < 0; + 0 < s; + + 0 < u; + u < 0; + 1 < u; + u < 1; + + c < 1; + 1 < c; + c < 500; + 500 < c; + + c < c; + c < i; + i < c; + i < i; + + s < c; + i < u; + + c < c++; + c < i++; + i < c++; + i < i++; + + s < i++; + c < u++; + + c++ < c; + i++ < c; + c++ < i; + i++ < i; + + s++ < c; + i++ < u; + + c < cfn(); + c < ifn(); + i < cfn(); + i < ifn(); + + s < cfn(); + c < ufn(); + + cfn() < c; + ifn() < c; + cfn() < i; + ifn() < i; + + sfn() < c; + ifn() < u; + + *pc < c++; + *pc < i++; + *pi < c++; + *pi < i++; + + *ps < c++; + *pi < u++; + + c++ < *pc; + i++ < *pc; + c++ < *pi; + i++ < *pi; + + s++ < *pc; + i++ < *pu; + + **ppc < c++; + **ppc < i++; + **ppi < c++; + **ppi < i++; + + **pps < c++; + **ppi < u++; + + c++ < **ppc; + i++ < **ppc; + c++ < **ppi; + i++ < **ppi; + + s++ < **ppc; + i++ < **ppu; +} diff --git a/bcc-bruce/misc/test/oplong.t b/bcc-bruce/misc/test/oplong.t new file mode 100644 index 0000000..b452243 --- /dev/null +++ b/bcc-bruce/misc/test/oplong.t @@ -0,0 +1,264 @@ +/* oplong.t - test long operations */ + +/* this is just opsoft.t with int defined as long */ + +#define int long +#define UNSIGNED unsigned long + +/* only doing chars, shorts, ints and unsigneds */ +/* not doing longs, floats or doubles */ + +/* short = int, so only a few examples */ +/* unsigned like int, so only a few examples */ +/* most examples for DIVOP */ +/* only (all) special cases of MULOP, MODOP, SLOP and SROP are tried */ + +op1() +{ + char c, *pc, **ppc, cfn(); + short s, *ps, **pps, sfn(); + int i, *pi, **ppi, ifn(); + UNSIGNED u, *pu, **ppu, ufn(); + + i = c / 0; + i = 0 / c; + i = i / 0; + i = 0 / i; + + i = s / 0; + i = 0 / u; + + i = c / 1; + i = 1 / c; + i = i / 1; + i = 1 / i; + + i = s / 1; + i = 1 / u; + + i = c / 2; + i = 2 / c; + i = i / 2; + i = 2 / i; + + i = s / 2; + i = 2 / u; + + i = c / 500; + i = 500 / c; + i = i / 500; + i = 500 / i; + + i = s / 500; + i = 500 / u; + + i = c / c; + i = c / i; + i = i / c; + i = i / i; + + i = s / c; + i = i / u; + + i = c / c++; + i = c / i++; + i = i / c++; + i = i / i++; + + i = s / i++; + i = c / u++; + + i = c++ / c; + i = i++ / c; + i = c++ / i; + i = i++ / i; + + i = s++ / c; + i = i++ / u; + + i = c / cfn(); + i = c / ifn(); + i = i / cfn(); + i = i / ifn(); + + i = s / cfn(); + i = c / ufn(); + + i = cfn() / c; + i = ifn() / c; + i = cfn() / i; + i = ifn() / i; + + i = sfn() / c; + i = ifn() / u; + + i = *pc / c++; + i = *pc / i++; + i = *pi / c++; + i = *pi / i++; + + i = *ps / c++; + i = *pi / u++; + + i = c++ / *pc; + i = i++ / *pc; + i = c++ / *pi; + i = i++ / *pi; + + i = s++ / *pc; + i = i++ / *pu; + + i = **ppc / c++; + i = **ppc / i++; + i = **ppi / c++; + i = **ppi / i++; + + i = **pps / c++; + i = **ppi / u++; + + i = c++ / **ppc; + i = i++ / **ppc; + i = c++ / **ppi; + i = i++ / **ppi; + + i = s++ / **ppc; + i = i++ / **ppu; + + i = c * 0; + i = 0 * c; + i = i * 0; + i = 0 * i; + + i = s * 0; + i = 0 * u; + + i = c * 1; + i = 1 * c; + i = i * 1; + i = 1 * i; + + i = s * 1; + i = 1 * u; + + i = c * 2; + i = 2 * c; + i = i * 2; + i = 2 * i; + + i = s * 2; + i = 2 * u; + + i = c * 500; + i = 500 * c; + i = i * 500; + i = 500 * i; + + i = s * 500; + i = 500 * u; + + i = c * c; + i = c * c++; + i = c++ * c; + i = c * cfn(); + i = cfn() * c; + i = *pc * c++; + i = c++ * *pc; + i = **ppc * c++; + i = c++ * **ppc; + + i = c % 0; + i = 0 % c; + i = i % 0; + i = 0 % i; + + i = s % 0; + i = 0 % u; + + i = c % 1; + i = 1 % c; + i = i % 1; + i = 1 % i; + + i = s % 1; + i = 1 % u; + + i = c % 2; + i = 2 % c; + i = i % 2; + i = 2 % i; + + i = s % 2; + i = 2 % u; + + i = c % 500; + i = 500 % c; + i = i % 500; + i = 500 % i; + + i = s % 500; + i = 500 % u; + + i = c << 0; + i = 0 << c; + i = i << 0; + i = 0 << i; + + i = s << 0; + i = 0 << u; + + i = c << 1; + i = 1 << c; + i = i << 1; + i = 1 << i; + + i = s << 1; + i = 1 << u; + + i = c << 8; + i = 8 << c; + i = i << 8; + i = 8 << i; + + i = s << 8; + i = 8 << u; + + i = c << 9; + i = 9 << c; + i = i << 9; + i = 9 << i; + + i = s << 9; + i = 9 << u; + + i = c >> 0; + i = 0 >> c; + i = i >> 0; + i = 0 >> i; + + i = s >> 0; + i = 0 >> u; + + i = c >> 1; + i = 1 >> c; + i = i >> 1; + i = 1 >> i; + + i = s >> 1; + i = 1 >> u; + + i = c >> 8; + i = 8 >> c; + i = i >> 8; + i = 8 >> i; + + i = s >> 8; + i = 8 >> u; + + i = c >> 9; + i = 9 >> c; + i = i >> 9; + i = 9 >> i; + + i = s >> 9; + i = 9 >> u; +} diff --git a/bcc-bruce/misc/test/opplus.t b/bcc-bruce/misc/test/opplus.t new file mode 100644 index 0000000..88e31e9 --- /dev/null +++ b/bcc-bruce/misc/test/opplus.t @@ -0,0 +1,122 @@ +/* op+-.t - test plus, minus operators */ + +/* only doing chars and ints, not shorts, longs, floats, doubles */ +/* not doing pointer arithmetic */ + +op1() +{ + char cfn(); + int ifn(); + char c, *pc, **ppc; + int i, *pi, **ppi; + + i = c + 1; + i = 1 + c; + i = i + 1; + i = 1 + i; + + i = c + 500; + i = 500 + c; + i = i + 500; + i = 500 + i; + + i = c - 1; + i = 1 - c; + i = i - 1; + i = 1 - i; + + i = c - 500; + i = 500 - c; + i = i - 500; + i = 500 - i; + + i = c + c; + i = c + i; + i = i + c; /* -2 cycles, +1 byte different from c + i, lhs loaded 1st */ + i = i + i; + + i = c - c; + i = c - i; + i = i - c; + i = i - i; + + i = c + c++; + i = c + i++; + i = i + c++; + i = i + i++; + + i = c++ + c; + i = i++ + c; + i = c++ + i; + i = i++ + i; + + i = c - c++; + i = c - i++; + i = i - c++; + i = i - i++; + + i = c++ - c; + i = i++ - c; + i = c++ - i; + i = i++ - i; + + i = c + cfn(); + i = c + ifn(); + i = i + cfn(); + i = i + ifn(); + + i = cfn() + c; + i = ifn() + c; + i = cfn() + i; + i = ifn() + i; + + i = c - cfn(); + i = c - ifn(); + i = i - cfn(); + i = i - ifn(); + + i = cfn() - c; + i = ifn() - c; + i = cfn() - i; + i = ifn() - i; + + i = *pc + c++; + i = *pc + i++; + i = *pi + c++; + i = *pi + i++; + + i = c++ + *pc; + i = i++ + *pc; + i = c++ + *pi; + i = i++ + *pi; + + i = *pc - c++; + i = *pc - i++; + i = *pi - c++; + i = *pi - i++; + + i = c++ - *pc; + i = i++ - *pc; + i = c++ - *pi; + i = i++ - *pi; + + i = **ppc + c++; + i = **ppc + i++; + i = **ppi + c++; + i = **ppi + i++; + + i = c++ + **ppc; + i = i++ + **ppc; + i = c++ + **ppi; + i = i++ + **ppi; + + i = **ppc - c++; + i = **ppc - i++; + i = **ppi - c++; + i = **ppi - i++; + + i = c++ - **ppc; + i = i++ - **ppc; + i = c++ - **ppi; + i = i++ - **ppi; +} diff --git a/bcc-bruce/misc/test/opsoft.t b/bcc-bruce/misc/test/opsoft.t new file mode 100644 index 0000000..346df4d --- /dev/null +++ b/bcc-bruce/misc/test/opsoft.t @@ -0,0 +1,259 @@ +/* opsoft.t - test software operations */ + +/* only doing chars, shorts, ints and unsigneds */ +/* not doing longs, floats or doubles */ + +/* short = int, so only a few examples */ +/* unsigned like int, so only a few examples */ +/* most examples for DIVOP */ +/* only (all) special cases of MULOP, MODOP, SLOP and SROP are tried */ + +op1() +{ + char c, *pc, **ppc, cfn(); + short s, *ps, **pps, sfn(); + int i, *pi, **ppi, ifn(); + unsigned u, *pu, **ppu, ufn(); + + i = c / 0; + i = 0 / c; + i = i / 0; + i = 0 / i; + + i = s / 0; + i = 0 / u; + + i = c / 1; + i = 1 / c; + i = i / 1; + i = 1 / i; + + i = s / 1; + i = 1 / u; + + i = c / 2; + i = 2 / c; + i = i / 2; + i = 2 / i; + + i = s / 2; + i = 2 / u; + + i = c / 500; + i = 500 / c; + i = i / 500; + i = 500 / i; + + i = s / 500; + i = 500 / u; + + i = c / c; + i = c / i; + i = i / c; + i = i / i; + + i = s / c; + i = i / u; + + i = c / c++; + i = c / i++; + i = i / c++; + i = i / i++; + + i = s / i++; + i = c / u++; + + i = c++ / c; + i = i++ / c; + i = c++ / i; + i = i++ / i; + + i = s++ / c; + i = i++ / u; + + i = c / cfn(); + i = c / ifn(); + i = i / cfn(); + i = i / ifn(); + + i = s / cfn(); + i = c / ufn(); + + i = cfn() / c; + i = ifn() / c; + i = cfn() / i; + i = ifn() / i; + + i = sfn() / c; + i = ifn() / u; + + i = *pc / c++; + i = *pc / i++; + i = *pi / c++; + i = *pi / i++; + + i = *ps / c++; + i = *pi / u++; + + i = c++ / *pc; + i = i++ / *pc; + i = c++ / *pi; + i = i++ / *pi; + + i = s++ / *pc; + i = i++ / *pu; + + i = **ppc / c++; + i = **ppc / i++; + i = **ppi / c++; + i = **ppi / i++; + + i = **pps / c++; + i = **ppi / u++; + + i = c++ / **ppc; + i = i++ / **ppc; + i = c++ / **ppi; + i = i++ / **ppi; + + i = s++ / **ppc; + i = i++ / **ppu; + + i = c * 0; + i = 0 * c; + i = i * 0; + i = 0 * i; + + i = s * 0; + i = 0 * u; + + i = c * 1; + i = 1 * c; + i = i * 1; + i = 1 * i; + + i = s * 1; + i = 1 * u; + + i = c * 2; + i = 2 * c; + i = i * 2; + i = 2 * i; + + i = s * 2; + i = 2 * u; + + i = c * 500; + i = 500 * c; + i = i * 500; + i = 500 * i; + + i = s * 500; + i = 500 * u; + + i = c * c; + i = c * c++; + i = c++ * c; + i = c * cfn(); + i = cfn() * c; + i = *pc * c++; + i = c++ * *pc; + i = **ppc * c++; + i = c++ * **ppc; + + i = c % 0; + i = 0 % c; + i = i % 0; + i = 0 % i; + + i = s % 0; + i = 0 % u; + + i = c % 1; + i = 1 % c; + i = i % 1; + i = 1 % i; + + i = s % 1; + i = 1 % u; + + i = c % 2; + i = 2 % c; + i = i % 2; + i = 2 % i; + + i = s % 2; + i = 2 % u; + + i = c % 500; + i = 500 % c; + i = i % 500; + i = 500 % i; + + i = s % 500; + i = 500 % u; + + i = c << 0; + i = 0 << c; + i = i << 0; + i = 0 << i; + + i = s << 0; + i = 0 << u; + + i = c << 1; + i = 1 << c; + i = i << 1; + i = 1 << i; + + i = s << 1; + i = 1 << u; + + i = c << 8; + i = 8 << c; + i = i << 8; + i = 8 << i; + + i = s << 8; + i = 8 << u; + + i = c << 9; + i = 9 << c; + i = i << 9; + i = 9 << i; + + i = s << 9; + i = 9 << u; + + i = c >> 0; + i = 0 >> c; + i = i >> 0; + i = 0 >> i; + + i = s >> 0; + i = 0 >> u; + + i = c >> 1; + i = 1 >> c; + i = i >> 1; + i = 1 >> i; + + i = s >> 1; + i = 1 >> u; + + i = c >> 8; + i = 8 >> c; + i = i >> 8; + i = 8 >> i; + + i = s >> 8; + i = 8 >> u; + + i = c >> 9; + i = 9 >> c; + i = i >> 9; + i = 9 >> i; + + i = s >> 9; + i = 9 >> u; +} diff --git a/bcc-bruce/misc/test/puzzle.t b/bcc-bruce/misc/test/puzzle.t new file mode 100644 index 0000000..9d2c4ab --- /dev/null +++ b/bcc-bruce/misc/test/puzzle.t @@ -0,0 +1,178 @@ +/* puzzle.t - from C puzzle book */ + +#define puzzle(which) ( puts( "-----which-----\n" ), which() ) + +main() +{ + puzzle( op1 ); + puzzle( op2 ); + puzzle( op3 ); + puzzle( op4 ); + puzzle( op5 ); + puzzle( op6 ); + puzzle( prep1 ); + puzzle( prep2 ); +} + +op1() +{ + int x; + + x = - 3 + 4 * 5 - 6; printf("%d\n",x); + x = 3 + 4 % 5 - 6; printf("%d\n",x); + x = - 3 * 4 % - 6 / 5; printf("%d\n",x); + x = ( 7 + 6 ) % 5 /2; printf("%d\n",x); +} + +#define PRINTX printf( "%d\n", x ) + +op2() +{ + int x, y, z; + + x = 2; + x *= 3 + 2; PRINTX; + x *= y = z = 4; PRINTX; + x = y == z; PRINTX; + x == (y == z); PRINTX; +} + +#define PRINT(int) printf( "int = %d\n", int ) + +op3() +{ + int x, y, z; + + x = 2; y = 1; z = 0; + x = x && y || z; PRINT(x); + PRINT( x || ! y && z ); + + x = y = 1; + z = x ++ - 1; PRINT(x); PRINT(z); + z += - x ++ + ++ y;PRINT(x);PRINT(z); + z = x / ++ x; PRINT(z); +} + +op4() +{ + int x, y, z; + + x = 03; y = 02; z = 01; + PRINT( x | y & z ); + PRINT( x | y & ~ z ); + PRINT( x ^ y & ~ z ); + PRINT( x & y && z ); + + x = 1; y = -1; + PRINT( ! x | x ); + PRINT( ~ x | x ); + PRINT( x ^ x ); + x <<= 3; PRINT(x); + y <<= 3; PRINT(y); + y >>= 3; PRINT(y); +} + +op5() +{ + int x, y, z; + + x = 1; y = 1; z = 1; + + x += y += z; + PRINT( x < y ? y : x ); + + PRINT( x < y ? x ++ : y ++ ); + PRINT(x); PRINT(y); + + PRINT( z += x < y ? x ++ : y ++ ); + PRINT(y); PRINT(z); + + x = 3; y=z=4; + PRINT( (z >= y >= x) ? 1 : 0 ); + PRINT( z >= y && y >= x ); +} + +#define PRINT3(x,y,z) printf("x=%d\ty=%d\tz=%d\n",x,y,z) + +op6() +{ + int x, y, z; + + x = y = z = 1; + ++x || ++y && ++z; PRINT3(x,y,z); + + x = y = z = 1; + ++x && ++y || ++z; PRINT3(x,y,z); + + x = y = z = 1; + ++x && ++y && ++z; PRINT3(x,y,z); + + x = y = z = -1; + ++x && ++y || ++z; PRINT3(x,y,z); + + x = y = z = -1; + ++x || ++y && ++z; PRINT3(x,y,z); + + x = y = z = -1; + ++x && ++y && ++z; PRINT3(x,y,z); +} + +#define FUDGE(k) k+3 +#define PR(a) printf("a= %d\t",(int)(a)) +#define PRINTNEW(a) PR(a); putchar( '\n' ); +#define PRINT2(a,b) PR(a); PRINT(b) +#define PRINT3NEW(a,b,c) PR(a); PRINT2(b,c) +#define MAX(a,b) (a<b ? b : a ) + +prep1() +{ + { + int x; + x = 2; + PRINTNEW( x*FUDGE(2) ); + } + { + int cel; + for( cel=0; cel<=100; cel+=50 ) + PRINT2( cel, 9/5*cel+32 ); + } + { + int x, y; + x=1; y=2; + PRINT3NEW( MAX(x++,y),x,y ); + PRINT3NEW( MAX(x++,y),x,y ); + } +} + +#define NEG(a)-a +#define weeks(mins) (days(mins)/7) +#define days(mins) (hours(mins)/24) +#define hours(mins) (mins/60) +#define mins(secs) (secs/60) +#define TAB(c,i,oi,tx) if(c=='\t')\ + for(tx=8-(i-oi-1)%8,oi=i; tx; tx--)\ + putchar(' ') + +static char *input = "\twhich\tif?"; + +prep2() +{ + { + int x; + x=1; + PRINT( -NEG(x) ); + } + { + PRINT( weeks(10080) ); + PRINT( days(mins(86400)) ); + } + { + char c; + int i, oldi, temp; + + for( oldi= -1,i=0; (c=input[i])!='\0'; i++ ) + if( c<' ' ) TAB(c,i,oldi,temp); + else putchar(c); + putchar('\n'); + } +} diff --git a/bcc-bruce/misc/test/sierpin.t b/bcc-bruce/misc/test/sierpin.t new file mode 100644 index 0000000..79016f7 --- /dev/null +++ b/bcc-bruce/misc/test/sierpin.t @@ -0,0 +1,123 @@ +/* sierpin.t */ + +#define PPIFBUF 0xf010 /* address of ptr to IFBUF */ +#define PSET 2 /* use this plot option */ + +struct IFBUF +{ + char ERR; + char COMMAND; + char COLOR; + char PLOTOPTION; + int LINESTYLE; + int X1; + int Y1; + int X2; + int Y2; + char BFFLAG; +}; + +#define H0 512 /* square size */ +#define XOFFS 80 /* offset to centre square */ +#define XNUM 15 /* scale 512 * 15/16 = 480 */ +#define XDENOM 16 +#define YNUM 25 /* scale 512 * 25/64 = 200 */ +#define YDENOM 64 /* to give max height, dot ratio 480/200 = 2.4 */ + +struct IFBUF *pifbuf; +int h, x, y; + +main() +{ + struct IFBUF **ppifbuf; /* required since no casts */ + int i, x0, y0; + char color; + + pifbuf = *(ppifbuf = PPIFBUF); /* pifbuf = *(struct IFBUF **)PPIFBUF; */ + pifbuf->PLOTOPTION = PSET; + pifbuf->LINESTYLE = /* normal */ + pifbuf->COMMAND = /* ?? */ + pifbuf->BFFLAG = 0; /* not a box */ + color = i = 0; + x0 = 2 * (h = H0/4); + y0 = 3 * (H0/4); + while ( h > 1 ) + { + ++i; + if ( ++color > 7 ) + color = 1; + pifbuf->COLOR = color; + x = x0 -= h; + y = y0 += h /= 2; + glocate(); + a( i ); x += h; y -= h; plot(); + b( i ); x -= h; y -= h; plot(); + c( i ); x -= h; y += h; plot(); + d( i ); x += h; y += h; plot(); + } +} + +a( i ) +int i; +{ + if ( --i >= 0 ) + { + a( i ); x += h; y -=h; plot(); + b( i ); x += 2*h; plot(); + d( i ); x += h; y += h; plot(); + a( i ); + } +} + +b( i ) +int i; +{ + if ( --i >= 0 ) + { + b( i ); x -= h; y -=h; plot(); + c( i ); y -= 2*h; plot(); + a( i ); x += h; y -= h; plot(); + b( i ); + } +} + +c( i ) +int i; +{ + if ( --i >= 0 ) + { + c( i ); x -= h; y +=h; plot(); + d( i ); x -= 2*h; plot(); + b( i ); x -= h; y -= h; plot(); + c( i ); + } +} + +d( i ) +int i; +{ + if ( --i >= 0 ) + { + d( i ); x += h; y +=h; plot(); + a( i ); y += 2*h; plot(); + c( i ); x -= h; y += h; plot(); + d( i ); + } +} + +glocate() +{ + pifbuf->X2 = x - x * (XDENOM - XNUM) / XDENOM + XOFFS; + pifbuf->Y2 = (y * YNUM) / YDENOM; +} + +plot() +{ + pifbuf->X1 = pifbuf->X2; + pifbuf->Y1 = pifbuf->Y2; + glocate(); +#asm + SWI2 + FDB $4201 call LINEMA +#endasm +} diff --git a/bcc-bruce/misc/test/sievec.t b/bcc-bruce/misc/test/sievec.t new file mode 100644 index 0000000..1b51fdb --- /dev/null +++ b/bcc-bruce/misc/test/sievec.t @@ -0,0 +1,28 @@ +#define TRUE 1 +#define FALSE 0 +#define SIZE 8190 + +char flags[SIZE+1]; + +main() +{ + int i,prime,k,count,iter; + + for (iter=0;iter<10;iter++) + { + count=0; + for (i=0;i<=SIZE;i++) + flags[i]=TRUE; + for (i=0;i<=SIZE;i++) + { + if (flags[i]) + { + prime=i+i+3; + for (k=i+prime;k<=SIZE;k=k+prime) + flags[k]=FALSE; + count++; + } + } + } + printf( "%d primes\n", count ); +} diff --git a/bcc-bruce/misc/test/sievecp.t b/bcc-bruce/misc/test/sievecp.t new file mode 100644 index 0000000..185b031 --- /dev/null +++ b/bcc-bruce/misc/test/sievecp.t @@ -0,0 +1,45 @@ +/* sieve using pointers */ + +#define TRUE 1 +#define FALSE 0 +#define NITER 100 +#define SIZE 8191 /* last prime <= 2*this+3 */ +#define SQRSIZE 63 /* last divisor tested = 2*this+3 */ + +char flags[SIZE+2*SQRSIZE+3]; /* avoid ptr+=prime overflowing */ + +main() +{ + int i,count,iter; + register char *ptr; + char *endptr; + int prime; + + for (iter=0;iter<NITER;iter++) + { + count=0; + ptr=flags; + endptr=flags+SIZE; + while (ptr<endptr) + *ptr++=TRUE; + for (i=0;i<SQRSIZE;i++) + { + if (flags[i]) + { + prime=i+i+3; + ptr=flags+i+prime; /* ptr<endptr since i<SQRSIZE */ + while (ptr<endptr) + { + *ptr=FALSE; + ptr+=prime; /* does not overflow since in flags */ + } + count++; + } + } + ptr=flags+SQRSIZE; + while (ptr<endptr) + if (*ptr++) + count++; + } + printf( "%d primes\n", count ); +} diff --git a/bcc-bruce/misc/test/sievei.t b/bcc-bruce/misc/test/sievei.t new file mode 100644 index 0000000..d4910dc --- /dev/null +++ b/bcc-bruce/misc/test/sievei.t @@ -0,0 +1,28 @@ +#define TRUE 1 +#define FALSE 0 +#define SIZE 8190 + +int flags[SIZE+1]; + +main() +{ + int i,prime,k,count,iter; + + for (iter=0;iter<10;iter++) + { + count=0; + for (i=0;i<=SIZE;i++) + flags[i]=TRUE; + for (i=0;i<=SIZE;i++) + { + if (flags[i]) + { + prime=i+i+3; + for (k=i+prime;k<=SIZE;k=k+prime) + flags[k]=FALSE; + count++; + } + } + } + printf( "%d primes\n", count ); +} diff --git a/bcc-bruce/misc/test/sort.t b/bcc-bruce/misc/test/sort.t new file mode 100644 index 0000000..34bcb9e --- /dev/null +++ b/bcc-bruce/misc/test/sort.t @@ -0,0 +1,104 @@ +unsigned t[10000]; +unsigned s[10000]; +unsigned size,repet; +unsigned comp=0,swap=0; /* s.b. long */ + +main(argc) +{ + int i,zz; + +/* + printf("size?"); + scanf("%d",&size); + printf("repet?"); + scanf("%d",&repet); +*/ + if ( argc > 20 ) + { + printf( "usage: sort [args], where 500*argc is the array size\n" ); + exit( 1 ); + } + size = 500 * argc; + repet = 1; + for (i = 0; i < size; i++) + s[i] = size-i; + printf("\npress key to begin shell sorting\n"); + getchar(); + for (zz=0;zz<repet;zz++) + { + comp=swap=0; + for (i=0;i<size;i++) + t[i]=s[i]; + sort(); + } + printf("\nsorted\n"); + printf("\ncompares = %d, swaps = %d\n",comp,swap); + printf("\npress key to begin quick sorting\n"); + getchar(); + for (zz=0;zz<repet;zz++) + { + comp=swap=0; + for (i=0;i<size;i++) + t[i]=s[i]; + qqsort(); + } + printf("\nsorted\n"); + printf("\ncompares = %d, swaps = %d\n",comp,swap); +} + +sort() +{ + int i,j,h,temp; + + h=1; + while (9*h+4<size) + h=3*h+1; + while (h>0) + { + for (j=h; j<size; j++) + for (i=j-h; i>=0; i-=h) + { + ++comp; + if (t[i]<=t[i+h]) + break; + ++swap; + temp=t[i]; + t[i]=t[i+h]; + t[i+h]=temp; + } + h=(h-1)/3; + } +} + +qqsort() +{ + qsort(0,size-1); +} + +qsort(l,r) +int l,r; +{ + int i,j; + unsigned x,w; + + i=l;j=r; + x=t[(l+r)>>1]; + do + { + while (t[i] < x) + { + ++comp; + i++; + } + while (x < t[j]) {--j;} + if (i<=j) + { + ++swap; + w=t[i];t[i]=t[j];t[j]=w; + i++;j--; + } + } + while (i<=j); + if (l<j) qsort(l,j); + if (i<r) qsort(i,r); +} diff --git a/bcc-bruce/misc/test/stdio.t b/bcc-bruce/misc/test/stdio.t new file mode 100644 index 0000000..e7e174d --- /dev/null +++ b/bcc-bruce/misc/test/stdio.t @@ -0,0 +1,87 @@ +/* stdio.h */ + +#asm + +#define BUFSIZ 512 +#define _NFILE 20 + +#define _IOREAD 1 +#define _IOWRITE 2 +#define _IODIRTY 4 +#define _IOEOF 8 +#define _IOERR 16 +#define _IOMYBUF 32 /* says if stream routines allocated buffer */ +#define _IOUNBUF 64 + +#define EOF (-1) +#define NULL 0 + +#endasm + +#define stdin (&_iob[0]) +#define stdout (&_iob[1]) +#define stderr (&_iob[2]) + +#define FILE struct _iobuf + +struct _iobuf +{ + char *_ptr; + char *_base; + char *_rtop; + char *_wtop; + char _flags; + char _fd; +} + _iob[_NFILE]; + +#define clearerr(fp) ((fp)->flags&=~_IOERR) +#define getchar() getc(stdin) +#define feof(fp) ((fp)->_flags&_IOEOF) +#define ferror(fp) ((fp)->_flags&_IOERR) +#define fileno(fp) ((fp)->_fd) +#define putchar(c) putc((c),stdout) + +#define void int + +FILE *fdopen(); +char *fgets(); +FILE *fopen(); +FILE *freopen(); +long ftell(); + +long lseek(); +unsigned read(); +unsigned write(); + +char *malloc(); +char *realloc(); +char *sbrk(); + +char *index(); +char *rindex(); +char *strcat(); +char *strcpy(); +char *strncat(); +char *strncpy(); + +#asm + +BLANK EQU 32 +COEOL EQU 10 +EOL EQU 13 +MAXCONTROL EQU 31 + +* struct _iobuf translated into offsets + + BLOCK 0 +PTR RMB 2 +BASE RMB 2 +RTOP RMB 2 +WTOP RMB 2 +FLAGS RMB 1 +FD RMB 1 +IOB.SIZE + ENDB + +#endasm diff --git a/bcc-bruce/os.h b/bcc-bruce/os.h new file mode 100644 index 0000000..672ddd8 --- /dev/null +++ b/bcc-bruce/os.h @@ -0,0 +1,79 @@ +/* os.h - source/target operating system dependencies for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* + must have unix-near-compatible creat, open, read, write and close + + source O/S's supported: + default: + *IX + special: + EDOS (#define SOS_EDOS if required) + MSDOS (#define SOS_MSDOS) + target O/S's supported: + default: + *IX + MSDOS + special: + EDOS (#define TOS_EDOS) +*/ + +/* defaults */ + +#define CREATPERMS 0666 /* permissions for creat */ +#define EOL 10 /* source newline */ +#define EOLTO 10 /* target newline */ +#define DIRCHAR '/' +#define DIRSTRING "/" +#define DEFAULT_INCLUDE_DIR "/usr/include" +#define isabspath(fnameptr, tempcptr) \ + ((*(tempcptr) = *(fnameptr)) == DIRCHAR) + +/* special */ + +#ifdef SOS_EDOS +# undef DEFAULT_INCLUDE_DIR +# define DEFAULT_INCLUDE_DIR "3" +# undef DIRCHAR +# define DIRCHAR ':' +# undef DIRSTRING +# define DIRSTRING ":" +# define AS09 +# undef EOL +# define EOL 13 +# undef isabspath +# define isabspath(fnameptr, tempcptr) \ + ((*(tempcptr) = *(fnameptr)) >= '0' && *(tempcptr) <= '9' && \ + (fnameptr)[1] == DIRCHAR) +#endif + +#ifdef SOS_MSDOS +# define COEOL 10 +# undef DEFAULT_INCLUDE_DIR +# define DEFAULT_INCLUDE_DIR "\\usr\\include" +# undef DIRCHAR +# define DIRCHAR '\\' +# undef DIRSTRING +# define DIRSTRING "\\" +# undef EOL +# define EOL 13 +/* + Problems with newline on MSDOS (as usual). + Defining EOL as 10 (LF) handles LF-terminated lines as well as + CRLF-terminated lines, but escaped CRLF's do not work. The compiler + should handle the escapes better. (Perhaps it does now.) + Defining EOL as 13 (CR) handles CRLF-terminated lines but fails on + LF-terminated lines. +*/ +#endif + +#ifdef TOS_EDOS +# undef EOLTO +# define EOLTO 13 +#endif + +/* don't let names dealt with here affect anything outside this file */ + +#undef SOS_EDOS +#undef SOS_MSDOS diff --git a/bcc-bruce/output.c b/bcc-bruce/output.c new file mode 100644 index 0000000..09e45a2 --- /dev/null +++ b/bcc-bruce/output.c @@ -0,0 +1,813 @@ +/* output.c - output and error handling for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "input.h" +#include "os.h" +#include "sizes.h" +#include "table.h" + +#undef EXTERN +#define EXTERN +#include "output.h" + +#ifdef XENIX_AS +# define HEXSTARTCHAR '/' +#else +# define HEXSTARTCHAR '$' +#endif +#define OUTBUFSIZE 2048 +#define opcodeleadin() /* outtab() for fussy assemblers */ + +PRIVATE unsigned errcount; /* # errors in compilation */ + /* depends on zero init */ +PRIVATE char hexdigits[] = "0123456789ABCDEF"; +PRIVATE char *outbuf; +EXTERN char *outbufend; /* end of pair of output buffers */ +PRIVATE char *outbufmid; +PRIVATE fd_t output; +PRIVATE fastin_t outstage; /* depends on zero init */ + +FORWARD void errorsummary P((void)); +FORWARD void errsum1 P((void)); +#ifdef MC6809 +#ifdef DEBUG +FORWARD void outvaldigs P((uvalue_t num)); +#endif +#endif + +PUBLIC void bugerror(message) +char *message; +{ + error2error("compiler bug - ", message); +} + +PUBLIC void closeout() +{ + char *saveoutptr; + + if (outstage == 3) + { + saveoutptr = outbufptr; + flushout(); /* buffer from last stage */ + outbufptr = saveoutptr; + } + outstage = 0; /* flush from top to current ptr */ + flushout(); + close(output); +} + +/* error handler */ + +PUBLIC void error(message) +char *message; +{ + error2error(message, ""); +} + +/* error handler - concatenate 2 messages */ + +PUBLIC void error2error(message1, message2) +char *message1; +char *message2; +{ + char *warning; + + if (message1[0] == '%' && message1[1] == 'w') + { + message1 += 2; + warning = "warning: "; + } + else + { + ++errcount; + warning = "error: "; + } + if (output != 1) + { + char *old_outbuf; + char *old_outbufptr; + char *old_outbuftop; + fd_t old_output; + fastin_t old_outstage; + char smallbuf[81]; /* don't use heap - might be full or busy */ + + old_outbuf = outbuf; + old_outbufptr = outbufptr; + old_outbuftop = outbuftop; + old_output = output; + old_outstage = outstage; + + outbufptr = outbuf = &smallbuf[0]; + outbuftop = &smallbuf[sizeof smallbuf]; + output = 1; + outstage = 0; + errorloc(); + outstr(warning); + outstr(message1); + outstr(message2); + outnl(); + flushout(); + + outbuf = old_outbuf; + outbufptr = old_outbufptr; + outbuftop = old_outbuftop; + output = old_output; + outstage = old_outstage; + } + comment(); + errorloc(); + outstr(warning); + outstr(message1); + outstr(message2); + outnl(); +} + +/* summarise errors */ + +PRIVATE void errorsummary() +{ + if (errcount != 0) + { + outfail(); + errsum1(); + } + outnl(); + comment(); + errsum1(); +} + +PRIVATE void errsum1() +{ + outudec(errcount); + outnstr(" errors detected"); +} + +/* fatal error, exit early */ + +PUBLIC void fatalerror(message) +char *message; +{ + error(message); + finishup(); +} + +/* finish up compile */ + +PUBLIC void finishup() +{ + if (!cppmode) + { + if (watchlc) + { + cseg(); + outop0str("if *-.program.start-"); + outnhex(getlc()); + outfail(); + outnstr("phase error"); + outop0str("endif\n"); + } +#ifdef HOLDSTRINGS + dumpstrings(); +#endif + dumpglbs(); + errorsummary(); + } + closein(); + closeout(); + exit(errcount == 0 ? 0 : 1); +} + +/* flush output file */ + +PUBLIC void flushout() +{ + unsigned nbytes; + + switch (outstage) + { + case 0: + nbytes = (unsigned) (outbufptr - outbuf); + outbufptr = outbuf; + break; + case 2: + nbytes = OUTBUFSIZE; + outbufptr = outbuf; + outbuftop = outbufmid; + outstage = 3; + break; + default: + nbytes = OUTBUFSIZE; + if (outstage == 1) + nbytes = 0; + outbufptr = outbufmid; + outbuftop = outbufend; + outstage = 2; + break; + } + if (nbytes != 0) + { + if (!orig_cppmode) + clearlabels(outbufptr, outbufptr + nbytes); + if (write(output, outbufptr, nbytes) != nbytes) + { + write(2, "output file error\n", 18); + closein(); + close(output); + exit(1); + } + } +} + +PUBLIC void initout() +{ + static char smallbuf[1]; + + outbufend = outbuftop = (outbuf = outbufptr = smallbuf) + sizeof smallbuf; + output = 1; /* standard output */ +} + +PUBLIC void limiterror(message) +char *message; +{ + error2error("compiler limit exceeded - ", message); + finishup(); +} + +PUBLIC void openout(oname) +char *oname; +{ + if (output != 1) + fatalerror("more than one output file"); + if ((output = creat(oname, CREATPERMS)) < 0) + { + output = 1; + fatalerror("cannot open output"); + } +} + +/* print character */ + +PUBLIC void outbyte(c) +int c; +{ +#if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1 + register char *outp; + + outp = outbufptr; + *outp++ = c; + outbufptr = outp; + if (outp >= outbuftop) + flushout(); +#else /* !C_CODE etc */ + +#if __AS09__ +# asm + TFR X,D + LDX _outbufptr,PC + STB ,X+ + STX _outbufptr,PC + CMPX _outbuftop,PC + LBHS CALL.FLUSHOUT +# endasm +#endif /* __AS09__ */ + +#if __AS386_16__ +# asm +# if !__FIRST_ARG_IN_AX__ + pop dx + pop ax + dec sp + dec sp +# else +# if ARGREG != DREG + xchg ax,bx +# endif +# endif + mov bx,[_outbufptr] + mov [bx],al + inc bx + mov [_outbufptr],bx + cmp bx,[_outbuftop] + jae OUTBYTE.FLUSH +# if !__FIRST_ARG_IN_AX__ + jmp dx +# else + ret +# endif + +OUTBYTE.FLUSH: +# if !__FIRST_ARG_IN_AX__ + push dx +# endif + br _flushout +# endasm +#endif /* __AS386_16__ */ + +#if __AS386_32__ +# asm +# if !__FIRST_ARG_IN_AX__ + mov eax,_outbyte.c[esp] +# else +# if ARGREG != DREG + xchg eax,ebx +# endif +# endif + mov ecx,[_outbufptr] + mov [ecx],al + inc ecx + mov [_outbufptr],ecx + cmp ecx,[_outbuftop] + jae OUTBYTE.FLUSH + ret + +OUTBYTE.FLUSH: + br _flushout +# endasm +#endif /* __AS386_32__ */ +#endif /* C_CODE etc */ +} + +/* print comma */ + +PUBLIC void outcomma() +{ + outbyte(','); +} + +/* print line number in format ("# %u \"%s\"%s", nr, fname, str) */ + +PUBLIC void outcpplinenumber(nr, fname, str) +unsigned nr; +char *fname; +char *str; +{ + outstr("# "); + outudec(nr); + outstr(" \""); + outstr(fname); + outstr("\""); + outnstr(str); +} + +/* print unsigned offset, hex format */ + +PUBLIC void outhex(num) +uoffset_t num; +{ +#ifdef HEXSTARTCHAR + if (num >= 10) + outbyte(HEXSTARTCHAR); +#endif + outhexdigs(num); +#ifdef HEXENDCHAR + if (num >= 10) + outbyte(HEXENDCHAR); +#endif +} + +/* print unsigned offset, hex format with digits only (no hex designator) */ + +PUBLIC void outhexdigs(num) +register uoffset_t num; +{ + if (num >= 0x10) + { + outhexdigs(num / 0x10); + num %= 0x10; + } + outbyte(hexdigits[(fastin_t) num]); +} + +/* print string terminated by EOL */ + +PUBLIC void outline(s) +char *s; +{ + register char *outp; + register char *rs; + + outp = outbufptr; + rs = s; +#ifdef COEOL + if (*rs == COEOL) + ++rs; +#endif + do + { + *outp++ = *rs; + if (outp >= outbuftop) + { + outbufptr = outp; + flushout(); + outp = outbufptr; + } + } + while (*rs++ != EOL); + outbufptr = outp; +#ifdef COEOL + if (*rs == COEOL) + outbyte(COEOL); +#endif +} + +/* print minus sign */ + +PUBLIC void outminus() +{ + outbyte('-'); +} + +/* print character, then newline */ + +PUBLIC void outnbyte(byte) +int byte; +{ + outbyte(byte); + outnl(); +} + +/* print unsigned offset, hex format, then newline */ + +PUBLIC void outnhex(num) +uoffset_t num; +{ + outhex(num); + outnl(); +} + +/* print newline */ + +PUBLIC void outnl() +{ + if (watchlc) + { + outtab(); + comment(); + outhex(getlc()); + } + outbyte('\n'); +} + +/* print opcode and newline, bump lc by 1 */ + +PUBLIC void outnop1str(s) +char *s; +{ + opcodeleadin(); + outstr(s); + bumplc(); + outnl(); +} + +/* print opcode and newline, bump lc by 2 */ + +PUBLIC void outnop2str(s) +char *s; +{ + opcodeleadin(); + outstr(s); + bumplc2(); + outnl(); +} + +/* print string, then newline */ + +PUBLIC void outnstr(s) +char *s; +{ + outstr(s); + outnl(); +} + +/* print opcode */ + +PUBLIC void outop0str(s) +char *s; +{ + opcodeleadin(); + outstr(s); +} + +/* print opcode, bump lc by 1 */ + +PUBLIC void outop1str(s) +char *s; +{ + opcodeleadin(); + outstr(s); + bumplc(); +} + +/* print opcode, bump lc by 2 */ + +PUBLIC void outop2str(s) +char *s; +{ + opcodeleadin(); + outstr(s); + bumplc2(); +} + +/* print opcode, bump lc by 3 */ + +PUBLIC void outop3str(s) +char *s; +{ + opcodeleadin(); + outstr(s); + bumplc3(); +} + +/* print plus sign */ + +PUBLIC void outplus() +{ + outbyte('+'); +} + +/* print signed offset, hex format */ + +PUBLIC void outshex(num) +offset_t num; +{ + if (num >= -(maxoffsetto + 1)) + { + outminus(); + num = -num; + } + outhex((uoffset_t) num); +} + +/* print string */ + +PUBLIC void outstr(s) +char *s; +{ +#if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1 + register char *outp; + register char *rs; + + outp = outbufptr; + rs = s; + while (*rs) + { + *outp++ = *rs++; + if (outp >= outbuftop) + { + outbufptr = outp; + flushout(); + outp = outbufptr; + } + } + outbufptr = outp; +#else /* !C_CODE etc */ + +#if __AS09__ +# asm + LEAU ,X + LDX _outbuftop,PC + PSHS X + LDX _outbufptr,PC + BRA OUTSTR.NEXT + +CALL.FLUSHOUT + PSHS U,B + STX _outbufptr,PC + LBSR _flushout + LDX _outbufptr,PC + LDY _outbuftop,PC + PULS B,U,PC + +OUTSTR.LOOP + STB ,X+ + CMPX ,S + BLO OUTSTR.NEXT + BSR CALL.FLUSHOUT + STY ,S +OUTSTR.NEXT + LDB ,U+ + BNE OUTSTR.LOOP + STX _outbufptr,PC + LEAS 2,S +# endasm +#endif /* __AS09__ */ + +#if __AS386_16__ +# asm +# if !__CALLER_SAVES__ + mov dx,di + mov cx,si +# endif +# if !__FIRST_ARG_IN_AX__ + pop ax + pop si + dec sp + dec sp + push ax +# else +# if ARGREG == DREG + xchg si,ax +# else + mov si,bx +# endif +# endif + mov di,[_outbufptr] + mov bx,[_outbuftop] + br OUTSTR.NEXT + +CALL.FLUSHOUT: + push si +# if !__CALLER_SAVES__ + push dx + push cx +# endif + push ax + mov [_outbufptr],di + call _flushout + mov di,[_outbufptr] + mov bx,[_outbuftop] + pop ax +# if !__CALLER_SAVES__ + pop cx + pop dx +#endif + pop si + ret + +OUTSTR.LOOP: + stosb + cmp di,bx + jb OUTSTR.NEXT + call CALL.FLUSHOUT +OUTSTR.NEXT: + lodsb + test al,al + jne OUTSTR.LOOP + mov [_outbufptr],di +# if !__CALLER_SAVES__ + mov si,cx + mov di,dx +# endif +# endasm +#endif /* __AS386_16__ */ + +#if __AS386_32__ +# asm +# if !__CALLER_SAVES__ + mov edx,edi + push esi +# define TEMPS 4 +# else +# define TEMPS 0 +# endif +# if !__FIRST_ARG_IN_AX__ + mov esi,TEMPS+_outstr.s[esp] +# else +# if ARGREG == DREG + xchg esi,eax +# else + mov esi,ebx +# endif +# endif + mov edi,[_outbufptr] + mov ecx,[_outbuftop] + br OUTSTR.NEXT + +CALL.FLUSHOUT: + push esi +# if !__CALLER_SAVES__ + push edx +# endif + push eax + mov [_outbufptr],edi + call _flushout + mov edi,[_outbufptr] + mov ecx,[_outbuftop] + pop eax +# if !__CALLER_SAVES__ + pop edx +# endif + pop esi + ret + +OUTSTR.LOOP: + stosb + cmp edi,ecx + jb OUTSTR.NEXT + call CALL.FLUSHOUT +OUTSTR.NEXT: + lodsb + test al,al + jne OUTSTR.LOOP + mov [_outbufptr],edi +# if !__CALLER_SAVES__ + pop esi + mov edi,edx +# endif +# endasm +#endif /* __AS386_32__ */ +#endif /* C_CODE etc */ +} + +/* print tab */ + +PUBLIC void outtab() +{ + outbyte('\t'); +} + +/* print unsigned, decimal format */ + +PUBLIC void outudec(num) +unsigned num; +{ + char str[10 + 1]; + + str[sizeof str - 1] = 0; + outstr(pushudec(str + sizeof str - 1, num)); +} + +#ifdef MC6809 +#ifdef DEBUG + +/* print unsigned value, hex format (like outhex except value_t is larger) */ + +PUBLIC void outuvalue(num) +uvalue_t num; +{ +#ifdef HEXSTARTCHAR + if (num >= 10) + outbyte(HEXSTARTCHAR); +#endif + outvaldigs(num); +#ifdef HEXENDCHAR + if (num >= 10) + outbyte(HEXENDCHAR); +#endif +} + +/* print unsigned value, hex format with digits only (no hex designator) */ + +PRIVATE void outvaldigs(num) +register uvalue_t num; +{ + if (num >= 0x10) + { + outvaldigs(num / 0x10); + num %= 0x10; + } + outbyte(hexdigits[(fastin_t) num]); +} + +/* print signed value, hex format (like outshex except value_t is larger) */ + +PUBLIC void outvalue(num) +register value_t num; +{ + if (num < 0) + { + outminus(); + num = -num; + } + outuvalue((uoffset_t) num); +} + +#endif /* DEBUG */ +#endif /* MC6809 */ + +/* push decimal digits of an unsigned onto a stack of chars */ + +PUBLIC char *pushudec(s, num) +register char *s; +register unsigned num; +{ + register unsigned reduction; + + while (num >= 10) + { + reduction = num / 10; + *--s = num - 10 * reduction + '0'; + num = reduction; + } + *--s = num + '0'; + return s; +} + +PUBLIC void setoutbufs() +{ + if (!isatty(output)) + { + outbufptr = outbuf = ourmalloc(2 * OUTBUFSIZE); +#ifdef TS +ts_s_outputbuf += 2 * OUTBUFSIZE; +#endif + outbufmid = outbuftop = outbufptr + OUTBUFSIZE; + outbufend = outbufmid + OUTBUFSIZE; + outstage = 1; + } + if (watchlc) + outnstr(".program.start:\n"); /* kludge temp label */ +} diff --git a/bcc-bruce/output.h b/bcc-bruce/output.h new file mode 100644 index 0000000..6dc9cf1 --- /dev/null +++ b/bcc-bruce/output.h @@ -0,0 +1,14 @@ +/* output.h - output for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#define OUTBYTE(ch) \ + do {register char *outp = outbufptr; *outp++ = (ch); \ + outbufptr = outp; if (outp >= outbuftop) flushout(); } while (0) + +EXTERN bool_t ctext; /* nonzero to intermix C source */ + /* depends on zero init */ +EXTERN char *outbufptr; /* current spot in output buffer */ +EXTERN char *outbuftop; /* top of current output buffer */ +EXTERN bool_t watchlc; /* nonzero to print lc after every line */ + /* depends on zero init */ diff --git a/bcc-bruce/parse.h b/bcc-bruce/parse.h new file mode 100644 index 0000000..ab67f6c --- /dev/null +++ b/bcc-bruce/parse.h @@ -0,0 +1,19 @@ +/* parse.h - parser for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* possible scope levels */ + +#define ARGLEVEL 1 +#define GLBLEVEL 0 +#define MAXLEVEL 125 +#define MINLOCLEVEL 1 + +/* possible node flags */ + +#define LVALUE (1 << 0) + +EXTERN struct nodestruct *etptr; /* ptr to next entry in expression tree */ +EXTERN struct symstruct *gvarsymptr; /* gsymptr for last identifier declared */ +EXTERN scopelev_t level; /* scope level */ + /* depends on zero init */ diff --git a/bcc-bruce/preproc.c b/bcc-bruce/preproc.c new file mode 100644 index 0000000..59ed9dc --- /dev/null +++ b/bcc-bruce/preproc.c @@ -0,0 +1,944 @@ +/* preprocessor routines for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "input.h" +#include "os.h" +#include "output.h" +#include "parse.h" +#include "sc.h" +#include "scan.h" +#include "table.h" +#include "type.h" + +#define MAX_IF 32 +#define MAX__LINE__ 10 /* enough for 32-bit source unsigneds */ +#define MAX_MACRO 32 +#define MAX_PARAM 127 /* max char with no sign on all machines */ + +/* Definition types. These are kept in the 'storage' member of struct + * symstruct and must be distinct from 'LOCAL' because dumplocs() doesn't + * check. + */ +enum +{ + DEF_LINE, /* __LINE__ keyword */ + DEF_NONE /* nothing special */ +}; + +struct ifstruct +{ + bool_t elseflag; + bool_t ifflag; +}; + +struct macroposition +{ + char *maclineptr; + char **paramlist; + char *paramspot; + bool_t inparam; + indn_t nparam; +}; + +PRIVATE char dummyparam[] = { EOL, 0 }; +PRIVATE fastin_t iflevel; /* depends on zero init */ +PRIVATE struct ifstruct ifstate; + /* elseflag depends on zero init */ +PRIVATE struct ifstruct ifstack[MAX_IF]; + +PRIVATE struct macroposition macrostack[MAX_MACRO]; + +FORWARD void asmcontrol P((void)); +FORWARD void control P((void)); +FORWARD void defineorundefinestring P((char *str, bool_pt defineflag)); +FORWARD void elsecontrol P((void)); +FORWARD void endif P((void)); +FORWARD fastin_pt getparnames P((void)); +FORWARD void ifcontrol P((sym_pt ifcase)); +FORWARD void undef P((void)); + +/* asmcontrol() - process #asm */ + +PRIVATE void asmcontrol() +{ + char treasure; /* to save at least one leading blank */ + + asmmode = TRUE; + if (orig_cppmode) + outstr("#asm\n"); + else + dumplocs(); + while (TRUE) + { + skipline(); + skipeol(); + if (eof) + { + eofin("#asm"); + break; + } + if (SYMOFCHAR(ch) == SPECIALCHAR) + specialchar(); + treasure = 0; + if (SYMOFCHAR(ch) == WHITESPACE) + treasure = ch; + blanks(); + if (ch == '#') + { + if (ctext) + { + register char *lptr; + + comment(); + if (treasure != 0) + outbyte(treasure); + lptr = lineptr; + while (*lptr++ != EOL) /* XXX - handle COEOL too */ + outbyte(ch); + outnl(); + } + gch1(); + docontrol(); + if (!asmmode) + break; + } + else + { + if (treasure != 0) + outbyte(treasure); + while (ch != EOL) /* XXX - handle COEOL too */ + { + outbyte(ch); + gch1(); + } + outnl(); + } + } + if (orig_cppmode) + outstr("#endasm"); /* nl is done by skipeol */ +} + +/* blanksident() - return nonzero if at blanks followed by an identifier */ + +PUBLIC bool_pt blanksident() +{ + blanks(); + return isident(); +} + +PUBLIC void checknotinif() +{ + while (iflevel != 0) + { + if (ifstate.ifflag) + eofin("true #conditional"); + else + eofin("false #conditional"); + endif(); + } +} + +/* control() - select and switch to control statement */ + +PRIVATE void control() +{ + char sname[NAMESIZE + 1]; + sym_t ctlcase; + struct symstruct *symptr; + + sname[0] = '#'; /* prepare for bad control */ + sname[1] = 0; + while (blanksident()) + { + if ((gsymptr = findlorg(gsname)) == NULL || + gsymptr->flags != DEFINITION) + { + strcat(sname, gsname); + break; + } + entermac(); + } + if (sname[1] == 0 && ch == EOL) + return; + if (SYMOFCHAR(ch) == INTCONST) + return; /* XXX - # linenumber not implemented */ + if ((symptr = findlorg(sname)) == NULL) + { + if (ifstate.ifflag) + error(" bad control"); + return; + } + ctlcase = symptr->offset.offsym; + if (ifstate.ifflag == FALSE && + (ctlcase < ELSECNTL || ctlcase > IFNDEFCNTL)) + return; + switch (ctlcase) + { + case ASMCNTL: + asmcontrol(); + break; + case DEFINECNTL: + define(); + break; + case ELSECNTL: + elsecontrol(); + break; + case ENDASMCNTL: + asmmode = FALSE; + break; + case ENDIFCNTL: + endif(); + break; + case IFCNTL: + case IFDEFCNTL: + case IFNDEFCNTL: + ifcontrol(symptr->offset.offsym); + break; + case INCLUDECNTL: + include(); + break; + case LINECNTL: + break; /* XXX - #line not implemented */ + case UNDEFCNTL: + undef(); + break; + } +} + +/* define() - process #define */ + +/* + MACRO storage. + A symbol recording the macro name is added to the symbol table. + This overrides all current scopes of the name (put at head of hash chain). + The flags are set to DEFINITION. + The indcount is 0 if no parameters, else 1 + number of parameters. + The offset field points to the macro string. + The macro string is null-terminated but EOL-sentineled. + It consists of EOL-terminated substrings followed by parameter numbers, + e.g., junk(x,y)=-x+y is stored as '-', EOL, 1, '+', EOL, 2, EOL, 0. + Here 1 is for the 1st parameter (start at 1 so 0 can terminate). + EOL acts as a sentinel for the scanner. + This choice works well because EOL cannot occur in a macro string. +*/ + +PUBLIC void define() +{ + char sname[NAMESIZE]; + char quote; + struct symstruct **hashptr; + struct symstruct *locmark; + char *macstring; + fastin_t nparnames; + char *oldstring; + struct symstruct *symptr; + + if (!blanksident()) + { + error("illegal macro name"); + return; + } + strcpy(sname, gsname); /* will overwrite gsname if parameters */ + if (ch == '(') + { + locmark = locptr; + newlevel(); /* temp storage for parameter names */ + nparnames = getparnames() + 1; + } + else + nparnames = 0; + blanks(); + macstring = charptr; + quote = 0; + while (ch != EOL) + { + if (charptr >= char1top) /* check room for char and end of string */ + macstring = growobject(macstring, 2); + if (nparnames && isident()) + { + if ((symptr = findlorg(gsname)) != NULL && + symptr->level == level) + { +#ifdef TS +++ts_n_macstring_param; +ts_s_macstring += 2; +#endif + *charptr++ = EOL; /* end current string */ + *charptr++ = symptr->indcount; /* param to insert */ + } + else + { + if (charptr + strlen(gsname) >= chartop) /* null too */ + macstring = growobject(macstring, strlen(gsname) + 1); +#ifdef TS +++ts_n_macstring_ident; +ts_s_macstring += strlen(gsname);; +#endif + strcpy(charptr, gsname); + charptr += strlen(gsname); /* discard null */ + } + continue; + } + if (ch == '\\') + { + gch1(); + *charptr = '\\'; + *(charptr + 1) = ch; +#ifdef TS +++ts_n_macstring_quoted; +ts_s_macstring += 2; +#endif + charptr += 2; + gch1(); + continue; + } + if (quote) + { + if (ch == quote) + quote = 0; + } + else if (ch == '"' || ch == '\'') + quote = ch; + else if (ch == '/') + { + if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR) + { + gch1(); + ch = *--lineptr = '/'; /* pushback */ + } + if (*(lineptr + 1) == '*') + { + gch1(); + skipcomment(); + ch = *--lineptr = ' '; /* comment is space in modern cpp's */ + } + } +#ifdef TS +++ts_n_macstring_ordinary; +++ts_s_macstring; +#endif + *charptr++ = ch; + gch1(); + } + { + register char *rcp; + + /* strip trailing blanks, but watch out for parameters */ + for (rcp = charptr; + rcp > macstring && SYMOFCHAR(*(rcp - 1)) == WHITESPACE + && (--rcp == macstring || *(rcp - 1) != EOL); ) + charptr = rcp; + } + if (charptr >= char1top) + macstring = growobject(macstring, 2); +#ifdef TS +++ts_n_macstring_term; +ts_s_macstring += 2; +#endif + *charptr++ = EOL; + *charptr++ = 0; + if (nparnames) + { + oldlevel(); + locptr = locmark; + } + if (asmmode) + equ(sname, macstring); + + if ((symptr = findlorg(sname)) != NULL && symptr->flags == DEFINITION) + { + if (strcmp(macstring, oldstring = symptr->offset.offp) != 0) + error("%wredefined macro"); + if (strlen(macstring) > strlen(oldstring = symptr->offset.offp)) + symptr->offset.offp = macstring; + else + { + strcpy(oldstring, macstring); /* copy if == to avoid test */ + charptr = macstring; + } + return; + } + symptr = qmalloc(sizeof (struct symstruct) + strlen(sname)); +#ifdef TS +++ts_n_defines; +ts_s_defines += sizeof (struct symstruct) + strlen(sname); +#endif + addsym(sname, vtype, symptr); + symptr->storage = DEF_NONE; + symptr->indcount = nparnames; + symptr->flags = DEFINITION; + symptr->level = GLBLEVEL; + symptr->offset.offp = macstring; + if (*(hashptr = gethashptr(sname)) != NULL) + { + symptr->next = *hashptr; + symptr->next->prev = &symptr->next; + } + *hashptr = symptr; + symptr->prev = hashptr; +} + +PRIVATE void defineorundefinestring(str, defineflag) +char *str; /* "name[=def]" or "name def" */ +bool_pt defineflag; +{ + char *fakeline; + unsigned len; + bool_t old_eof; + + len = strlen(str); + strcpy(fakeline = (char *) ourmalloc(3 + len + 2 + 2) + 3, str); + /* 3 pushback, 2 + 2 guards */ +#ifdef TS +ts_s_fakeline += 3 + len + 2 + 2; +ts_s_fakeline_tot += 3 + len + 2 + 2; +#endif + { + register char *endfakeline; + + endfakeline = fakeline + len; + endfakeline[0] = EOL; /* guards any trailing backslash */ + endfakeline[1] = EOL; /* line ends here or before */ + } + old_eof = eof; + eof = TRUE; /* valid after first EOL */ + ch = *(lineptr = fakeline); + if (defineflag) + { + if (blanksident()) /* if not, let define() produce error */ + { + blanks(); + if (ch == '=') + *lineptr = ' '; + else if (ch == EOL) + { + register char *lptr; + + lptr = lineptr; + lptr[0] = ' '; + lptr[1] = '1'; /* 2 extra were allocated for this & EOL */ + lptr[2] = EOL; + } + } + ch = *(lineptr = fakeline); + define(); + } + else + undef(); + eof = old_eof; +#ifdef TS +ts_s_fakeline_tot -= len + 2 + 2; +#endif + ourfree(fakeline - 3); +} + +PUBLIC void definestring(str) +char *str; /* "name[=def]" or "name def" */ +{ + defineorundefinestring(str, TRUE); +} + +/* docontrol() - process control statement, loop till "#if" is true */ + +PUBLIC void docontrol() +{ + while (TRUE) + { + control(); + skipline(); + if (ifstate.ifflag) + return; + while (TRUE) + { + skipeol(); + if (eof) + return; + blanks(); + if (ch == '#') + { + gch1(); + break; + } + skipline(); + } + } +} + +/* elsecontrol() - process #else */ + +PRIVATE void elsecontrol() +{ + if (iflevel == 0) + { + error("else without if"); + return; + } + ifstate.ifflag = ifstate.elseflag; + ifstate.elseflag = FALSE; +} + +/* endif() - process #endif */ + +PRIVATE void endif() +{ + if (iflevel == 0) + { + error("endif without if"); + return; + } + { + register struct ifstruct *ifptr; + + ifptr = &ifstack[--iflevel]; + ifstate.elseflag = ifptr->elseflag; + ifstate.ifflag = ifptr->ifflag; + } +} + +/* entermac() - switch line ptr to macro string */ + +PUBLIC void entermac() +{ + char quote; + struct symstruct *symptr; + char **paramhead; + char **paramlist; + int ngoodparams; + int nparleft; + int lpcount; + + if (maclevel >= MAX_MACRO) + { + limiterror("macros nested too deeply (33 levels)"); + return; + } + symptr = gsymptr; + ngoodparams = 0; + paramhead = NULL; + if (symptr->indcount != 0) + { + nparleft = symptr->indcount - 1; + if (nparleft == 0) + paramhead = NULL; + else + paramhead = ourmalloc(sizeof *paramlist * nparleft); + paramlist = paramhead; +#ifdef TS +++ts_n_macparam; +ts_s_macparam += sizeof *paramlist * nparleft; +ts_s_macparam_tot += sizeof *paramlist * nparleft; +#endif + blanks(); + while (ch == EOL && !eof) + { + skipeol(); + blanks(); + } + if (ch != '(') + error("missing '('"); + else + { + gch1(); + while (nparleft) + { + --nparleft; + ++ngoodparams; + *(paramlist++) = charptr; + quote = 0; + lpcount = 1; + while (TRUE) + { + if (ch == '\\') + { + gch1(); + if (charptr >= char1top) + *(paramlist - 1) = growobject(*(paramlist - 1), 2); +#ifdef TS +++ts_n_macparam_string_quoted; +++ts_s_macparam_string; +++ts_s_macparam_string_tot; +#endif + *charptr++ = '\\'; + } + else if (quote) + { + if (ch == quote) + quote = 0; + } + else if (ch == '"' || ch == '\'') + quote = ch; + else if (ch == '/') + { + if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR) + { + gch1(); + ch = *--lineptr = '/'; /* pushback */ + } + if (*(lineptr + 1) == '*') + { + gch1(); + skipcomment(); + ch = *--lineptr = ' '; /* pushback */ + } + } + else if (ch == '(') + ++lpcount; + else if (ch == ')' && --lpcount == 0 || + ch == ',' && lpcount == 1) + break; + if (ch == EOL) + ch = ' '; + if (charptr >= char1top) + *(paramlist - 1) = growobject(*(paramlist - 1), 2); +#ifdef TS +++ts_n_macparam_string_ordinary; +++ts_s_macparam_string; +++ts_s_macparam_string_tot; +#endif + *charptr++ = ch; + if (*lineptr == EOL) + { + skipeol(); /* macro case disposed of already */ + if (SYMOFCHAR(ch) == SPECIALCHAR) + specialchar(); + if (eof) + break; + } + else + gch1(); + } +#ifdef TS +++ts_n_macparam_string_term; +++ts_s_macparam_string; +++ts_s_macparam_string_tot; +#endif + *charptr++ = EOL; + { + register char *newparam; + register char *oldparam; + unsigned size; + + oldparam = *(paramlist - 1); + size = (/* size_t */ unsigned) (charptr - oldparam); + newparam = ourmalloc(size); +#ifdef TS +ts_s_macparam_string_alloced += size; +ts_s_macparam_string_alloced_tot += size; +#endif + memcpy(newparam, oldparam, size); + *(paramlist - 1) = newparam; +#ifdef TS +ts_s_macparam_string_tot -= charptr - oldparam; +#endif + charptr = oldparam; + } + if (ch == ',') + gch1(); + else + break; + } + } + blanks(); + while (ch == EOL && !eof) + { + skipeol(); + blanks(); + } + if (eof) + eofin("macro parameter expansion"); + if (nparleft) + { + error("too few macro parameters"); + do + *(paramlist++) = dummyparam; + while (--nparleft); + } + if (ch == ')') + gch1(); + else if (ch == ',') + { + error("too many macro parameters"); + + /* XXX - should read and discard extra parameters. Also check + * for eof at end. + */ + while (ch != ')') + { + if (ch == EOL) + { + skipeol(); + if (eof) + break; + continue; + } + gch1(); + } + } + else + error("missing ')'"); + } + + if (symptr->storage == DEF_LINE) + { + char *str; + + str = pushudec(symptr->offset.offp + MAX__LINE__, input.linenumber); + memcpy(symptr->offset.offp, str, /* size_t */ + (unsigned) (symptr->offset.offp + MAX__LINE__ + 1 + 1 - str)); + } + + { + register struct macroposition *mpptr; + + mpptr = ¯ostack[maclevel]; + mpptr->paramlist = paramhead; + mpptr->maclineptr = lineptr; + ch = *(lineptr = symptr->offset.offp); + mpptr->inparam = FALSE; + mpptr->nparam = ngoodparams; + ++maclevel; + } +/* + comment(); + outstr("MACRO (level "); + outudec((unsigned) maclevel); + outstr(") "); + outline(lineptr); +*/ +} + +/* getparnames() - get parameter names during macro definition, return count */ + +PRIVATE fastin_pt getparnames() +{ + fastin_t nparnames; + struct symstruct *symptr; + + nparnames = 0; + gch1(); + while (blanksident()) + { + if ((symptr = findlorg(gsname)) != NULL && + symptr->level == level) + error("repeated parameter"); + symptr = addloc(gsname, itype); + if (nparnames >= MAX_PARAM) + limiterror("too many macro parameters (128)"); + else + ++nparnames; /* number params from 1 */ + symptr->indcount = nparnames; /* param number */ + blanks(); + if (ch == ',') + gch1(); + } + if (ch != ')') + error("missing ')'"); + else + gch1(); + return nparnames; +} + +/* ifcontrol - process #if, #ifdef, #ifndef */ + +PRIVATE void ifcontrol(ifcase) +sym_pt ifcase; +{ + bool_t iftrue; + struct symstruct *symptr; + + if (iflevel >= MAX_IF) + { + limiterror("#if's nested too deeply (33 levels)"); + return; + } + { + register struct ifstruct *ifptr; + + ifptr = &ifstack[iflevel++]; + ifptr->elseflag = ifstate.elseflag; + ifptr->ifflag = ifstate.ifflag; + ifstate.elseflag = FALSE; /* prepare for !(if now)||(if future)*/ + } + if (ifstate.ifflag) + { + if ((sym_t) ifcase != IFCNTL) + { + iftrue = FALSE; + if (blanksident() && (symptr = findlorg(gsname)) != NULL && + symptr->flags == DEFINITION) + iftrue = TRUE; + } + else + { + incppexpr = TRUE; + nextsym(); + iftrue = constexpression() != 0; + incppexpr = FALSE; + } + if (!iftrue && (sym_t) ifcase != IFNDEFCNTL || + iftrue && (sym_t) ifcase == IFNDEFCNTL) + { + ifstate.elseflag = TRUE; + ifstate.ifflag = FALSE; + } + } +} + +/* ifinit() - initialise if state */ + +PUBLIC void ifinit() +{ + ifstate.ifflag = TRUE; +} + +/* leavemac() - leave current and further macro substrings till not at end */ + +PUBLIC void leavemac() +{ + register struct macroposition *mpptr; + + do + { + mpptr = ¯ostack[maclevel - 1]; + if (mpptr->inparam) + { + lineptr = ++mpptr->paramspot; + mpptr->inparam = FALSE; + } + else + { + ch = *++lineptr; /* gch1() would mess up next param == EOL-1 */ + if (ch != 0) + { + mpptr->paramspot = lineptr; + lineptr = mpptr->paramlist[ch - 1]; + mpptr->inparam = TRUE; + } + else + { + lineptr = mpptr->maclineptr; + if (mpptr->nparam != 0) + { + register char **paramlist; + +#ifdef TS +ts_s_macparam_tot -= sizeof *paramlist * mpptr->nparam; +#endif + paramlist = mpptr->paramlist; + do +{ +#ifdef TS +ts_s_macparam_string_alloced_tot -= strchr(*paramlist, EOL) - *paramlist + 1; +#endif + ourfree(*paramlist++); +} + while (--mpptr->nparam != 0); + ourfree(mpptr->paramlist); + } + --maclevel; + } + } + } + while ((ch = *lineptr) == EOL && maclevel != 0); +} + +PUBLIC void predefine() +{ + definestring("__BCC__ 1"); + definestring("__LINE__ 0123456789"); /* MAX__LINE__ digits */ + findlorg("__LINE__")->storage = DEF_LINE; +} + +PUBLIC char *savedlineptr() +{ + return macrostack[0].maclineptr; +} + +PUBLIC void skipcomment() +{ +/* Skip current char, then everything up to '*' '/' or eof. */ + + gch1(); + do + { + while (TRUE) + { + { + register char *reglineptr; + + reglineptr = lineptr; + symofchar['*'] = SPECIALCHAR; + while (SYMOFCHAR(*reglineptr) != SPECIALCHAR) + ++reglineptr; + symofchar['*'] = STAR; + lineptr = reglineptr; + if (*reglineptr == '*') + break; + ch = *reglineptr; + } + specialchar(); + if (ch == EOL) + { + skipeol(); + if (eof) + break; + } + else if (ch != '*') + gch1(); + } + gch1(); + if (eof) + { + eofin("comment"); + return; + } + } + while (ch != '/'); + gch1(); +} + +/* skipline() - skip rest of line */ + +PUBLIC void skipline() +{ + while (TRUE) + { + blanks(); + if (ch == EOL) + return; + if (ch == '\\') + { + gch1(); + if (ch == EOL) /* XXX - I think blanks() eats \EOL */ + return; + gch1(); /* XXX - escape() better? */ + } + else if (ch == '"' || ch == '\'') + { + stringorcharconst(); + charptr = constant.value.s; + } + else + gch1(); + } +} + +/* undef() - process #undef */ + +PRIVATE void undef() +{ + struct symstruct *symptr; + + if (blanksident() && (symptr = findlorg(gsname)) != NULL && + symptr->flags == DEFINITION) + delsym(symptr); +} + +PUBLIC void undefinestring(str) +char *str; +{ + defineorundefinestring(str, FALSE); +} diff --git a/bcc-bruce/preserve.c b/bcc-bruce/preserve.c new file mode 100644 index 0000000..0103a43 --- /dev/null +++ b/bcc-bruce/preserve.c @@ -0,0 +1,215 @@ +/* preserve.c - preserve opererands or registers in use for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "gencode.h" +#include "reg.h" +#include "type.h" + +/* change stack ptr without changing condition codes */ + +PUBLIC void changesp(newsp, absflag) +offset_t newsp; +bool_pt absflag; +{ + if (newsp != sp || (bool_t) absflag && switchnow != NULL) + { +#ifdef FRAMEPOINTER + if (newsp != framep || !(bool_t) absflag && switchnow != NULL) + { + outleasp(); + if (!(bool_t) absflag && switchnow != NULL) + outswoffset(newsp); + else + outoffset(newsp - framep); + outindframereg(); + outnl(); + } + else + regtransfer(FRAMEREG, STACKREG); + sp = newsp; + if (framep == 0) + bugerror("no frame pointer"); +#else +# ifdef I8088 + outleasp(); + outoffset(newsp - sp); + outindstackreg(); + outnl(); +# else + modstk(newsp); /* this should preserve CC */ +# endif +#endif /* FRAMEPOINTER */ + } +} + +/* load source to any while preserving target */ + +PUBLIC void loadpres(source, target) +struct symstruct *source; +struct symstruct *target; +{ + store_t regmark; + + if (target->storage & ALLDATREGS) + { + if (source->type->scalar & CHAR) + { + push(target); + load(source, DREG); + } + else + load(source, getindexreg()); + } + else + { + regmark = reguse; + reguse |= target->storage; + loadany(source); + reguse = regmark; + } +} + +/* change stack ptr */ + +PUBLIC void modstk(newsp) +offset_t newsp; +{ + if (newsp != sp) + { +#ifdef FRAMEPOINTER + if (newsp != framep || framep == 0 || switchnow != NULL) + addconst(newsp - sp, STACKREG); + else + regtransfer(FRAMEREG, STACKREG); +#else +# ifdef I8088 + addconst(newsp - sp, STACKREG); +# else + outleasp(); + outoffset(newsp - sp); + outncspregname(); +# endif +#endif + sp = newsp; + } +} + +/* preserve target without changing source */ + +PUBLIC void pres2(source, target) +struct symstruct *source; +struct symstruct *target; +{ + if (target->storage & allregs) + { + if (target->storage & (allregs - allindregs) /* XXX */ || + target->indcount == 0 && target->type->scalar & (DLONG | RSCALAR)) + push(target); /* XXX - perhaps not float */ + else if (((target->storage | reguse) & allindregs) == allindregs) + { + loadpres(target, source); + push(target); + } + else + reguse |= target->storage; + } +} + +/* preserve source */ + +PUBLIC void preserve(source) +struct symstruct *source; +{ + if (source->storage & allregs) + { + if (source->storage & (allregs - allindregs) /* XXX */ || + ((source->storage | reguse) & allindregs) == allindregs) + push(source); + else + reguse |= source->storage; + } +} + +/* preserve lvalue target without changing source or target */ + +PUBLIC store_pt preslval(source, target) +struct symstruct *source; +struct symstruct *target; +{ + store_pt regpushed; + + if (target->indcount == 0) + reguse &= ~target->storage; + else + reguse = (target->storage | reguse) & allindregs; + if (!((source->type->scalar | target->type->scalar) & (DLONG | RSCALAR)) + || reguse != allindregs) + return 0; /* XXX - perhaps not float */ + reguse = source->storage | target->storage; /* free one other than s/t */ + pushreg(regpushed = getindexreg()); + reguse = ~(store_t) regpushed & allindregs; + return regpushed; +} + +PUBLIC void recovlist(reglist) +store_pt reglist; +{ + poplist(reglist); + reguse |= (store_t) reglist; +} + +#ifdef I8088 +PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5}; + /* CONSTANT, BREG, ax = DREG, bx = INDREG0, si = INDREG1, di = INDREG2 */ + /* LOCAL, GLOBAL, STACKREG, cx = DATREG1, dx = DATREG2 */ +#endif +#ifdef MC6809 +PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 3, 2}; + /* CONSTANT, BREG, DREG, XREG = INDREG0, UREG = INDREG1, YREG = INDREG2 */ +#endif + +PUBLIC void savereturn(savelist, saveoffset) +store_pt savelist; +offset_t saveoffset; +{ + store_t reg; + smalin_t *regoffptr; + offset_t spoffset; + + if (savelist == 0) + return; +#ifdef MC6809 /* must check this */ + if (savelist == XREG || savelist == INDREG1) + saveoffset -= accregsize; /* patch for DREG/YREG not saved */ +#endif + for (reg = 1, regoffptr = regoffset; reg != 0; ++regoffptr, reg <<= 1) + if (reg & savelist) + { + outstore(); + spoffset = saveoffset + *regoffptr * maxregsize; +#ifdef I8088 +# ifdef FRAMEPOINTER + if (switchnow != NULL) + outswoffset(spoffset); + else + outoffset(spoffset - framep); + outindframereg(); +# else + outoffset(spoffset - sp); + outindstackreg(); +# endif + outncregname(reg); +#endif +#ifdef MC6809 + if (reg == YREG) + bumplc(); + outregname(reg); + outtab(); + outoffset(spoffset - sp); + outncspregname(); +#endif + } +} diff --git a/bcc-bruce/proto.h b/bcc-bruce/proto.h new file mode 100644 index 0000000..00dc116 --- /dev/null +++ b/bcc-bruce/proto.h @@ -0,0 +1,399 @@ +/* proto.h - extern functions for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#if __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + +/* assign.c */ +void assign P((struct symstruct *source, struct symstruct *target)); +void cast P((struct typestruct *type, struct symstruct *target)); +void extend P((struct symstruct *target)); + +/* codefrag.c */ +void adjsp P((label_t label)); +void clrBreg P((void)); +void comment P((void)); +void ctoi P((void)); +void defbyte P((void)); +void deflong P((uoffset_t value)); +void defword P((void)); +void defdword P((void)); +void even P((void)); +void negDreg P((void)); +void comDreg P((void)); +void outadd P((void)); +void outaddsp P((void)); +void outcalladr P((void)); +void outcmp P((void)); +void outdec P((void)); +void outdword P((void)); +void outfail P((void)); +void outinc P((void)); +void outindleft P((void)); +void outindright P((void)); +void outindstackreg P((void)); +void outldaccum P((void)); +void outldmulreg P((void)); +void outlea P((void)); +void outleasp P((void)); +void outload P((void)); +void outmulmulreg P((void)); +void outopsep P((void)); +void outpshs P((void)); +void outpuls P((void)); +void outreturn P((void)); +void outstore P((void)); +void outsub P((void)); +void outtest P((void)); +void outword P((void)); +void sctoi P((void)); +void stoi P((void)); +void ustoi P((void)); +void outABX P((void)); +void outdirectpage P((void)); +void outextended P((void)); +void outncspregname P((void)); +void outindframereg P((void)); +void adc0 P((void)); +void addconst P((offset_t offset, store_pt reg)); +void adjlc P((offset_t offset, store_pt reg)); +void andconst P((offset_t offset)); +void bssseg P((void)); +label_t casejump P((void)); +void common P((char *name)); +void cseg P((void)); +void defnulls P((uoffset_t nullcount)); +label_t defstr P((char *sptr, char *stop, bool_pt dataflag)); +bool_pt diveasy P((value_t divisor, bool_pt uflag)); +void dpseg P((void)); +void dseg P((void)); +void equ P((char *name, char *string)); +void equlab P((label_t label, offset_t offset)); +void globl P((char *name)); +void import P((char *name)); +void itol P((store_pt reg)); +void lcommlab P((label_t label)); +void lcommon P((char *name)); +void lea P((offset_t offset, store_pt sourcereg, store_pt targreg)); +void loadconst P((offset_t offset, store_pt reg)); +int lslconst P((value_t shift, store_pt reg)); +int lsrconst P((value_t shift, store_pt reg, bool_pt uflag)); +bool_pt modeasy P((value_t divisor, bool_pt uflag)); +bool_pt muleasy P((uvalue_t factor, store_pt reg)); +void negreg P((store_pt reg)); +char *opstring P((op_pt op)); +void outccname P((char *name)); +void outhiaccum P((void)); +void outimmadr P((offset_t offset)); +void outimadj P((offset_t offset, store_pt targreg)); +void outimmed P((void)); +void outjumpstring P((void)); +void outnccname P((char *name)); +void outncimmadr P((offset_t offset)); +void outoffset P((offset_t offset)); +void public P((char *name)); +void private P((char *name)); +void regexchange P((store_pt sourcereg, store_pt targreg)); +void regtransfer P((store_pt sourcereg, store_pt targreg)); +void sbc0 P((void)); +void set P((char *name, offset_t value)); +void sl1 P((store_pt reg)); +void slconst P((value_t shift, store_pt reg)); +void srconst P((value_t shift, bool_pt uflag)); +void uitol P((store_pt reg)); +void restoreopreg P((void)); +void saveopreg P((void)); + +/* debug.c */ +void dbitem P((struct symstruct *item)); +void dbtype P((struct typestruct *type)); +void debug P((struct nodestruct *exp)); +void debugswap P((void)); + +/* declare.c */ +void colon P((void)); +void decllist P((void)); +void lparen P((void)); +void needvarname P((void)); +void program P((void)); +void rbrace P((void)); +void rbracket P((void)); +void rparen P((void)); +void semicolon P((void)); +struct typestruct *typename P((void)); + +/* express.c */ +struct nodestruct *assignment_exp P((void)); +struct nodestruct *expression P((void)); + +/* exptree.c */ +struct nodestruct *castnode P((struct typestruct *type, + struct nodestruct *nodeptr)); +void etreeinit P((void)); +struct nodestruct *leafnode P((struct symstruct *source)); +struct nodestruct *node P((op_pt t, struct nodestruct *p1, + struct nodestruct *p2)); + +/* floatop.c */ +bool_pt f_indirect P((struct symstruct *target)); +void float1op P((op_pt op, struct symstruct *source)); +void floatop P((op_pt op, struct symstruct *source, struct symstruct *target)); +void fpush P((struct symstruct *source)); +void justpushed P((struct symstruct *target)); + +/* function.c */ +void call P((char *name)); +void function P((struct symstruct *source)); +void ldregargs P((void)); +void loadretexpression P((void)); +void listo P((struct symstruct *target, offset_t lastargsp)); +void listroot P((struct symstruct *target)); +void popframe P((void)); +void reslocals P((void)); +void ret P((void)); + +/* gencode.c */ +void bileaf P((struct nodestruct *exp)); +fastin_pt bitcount P((uvalue_t number)); +void codeinit P((void)); +fastin_pt highbit P((uvalue_t number)); +void makeleaf P((struct nodestruct *exp)); + +/* genloads.c */ +void addoffset P((struct symstruct *source)); +void address P((struct symstruct *source)); +void exchange P((struct symstruct *source, struct symstruct *target)); +store_pt getindexreg P((void)); +void indexadr P((struct symstruct *source, struct symstruct *target)); +void indirec P((struct symstruct *source)); +void load P((struct symstruct *source, store_pt targreg)); +void loadany P((struct symstruct *source)); +void loadreg P((struct symstruct *source, store_pt targreg)); +void makelessindirect P((struct symstruct *source)); +void movereg P((struct symstruct *source, store_pt targreg)); +void onstack P((struct symstruct *target)); +void outadr P((struct symstruct *adr)); +void outcregname P((store_pt reg)); +void outncregname P((store_pt reg)); +void outnregname P((store_pt reg)); +void outregname P((store_pt reg)); +void outshortregname P((store_pt reg)); +void pointat P((struct symstruct *target)); +void poplist P((store_pt reglist)); +void push P((struct symstruct *source)); +void pushlist P((store_pt reglist)); +void pushreg P((store_pt reg)); +void storereg P((store_pt sourcereg, struct symstruct *target)); +void struc P((struct symstruct *source, struct symstruct *target)); +void transfer P((struct symstruct *source, store_pt targreg)); + +/* glogcode.c */ +void cmp P((struct symstruct *source, struct symstruct *target, + ccode_t *pcondtrue)); +void condop P((struct nodestruct *exp)); +void jumpfalse P((struct nodestruct *exp, label_t label)); +void jumptrue P((struct nodestruct *exp, label_t label)); +void logop P((struct nodestruct *exp)); + +/* hardop.c */ +void add P((struct symstruct *source, struct symstruct *target)); +void incdec P((op_pt op, struct symstruct *source)); +void neg P((struct symstruct *target)); +void not P((struct symstruct *target)); +void op1 P((op_pt op, struct symstruct *source, struct symstruct *target)); +void ptrsub P((struct symstruct *source, struct symstruct *target)); +void sub P((struct symstruct *source, struct symstruct *target)); + +/* input.c */ +void closein P((void)); +void errorloc P((void)); +void gch1 P((void)); +void include P((void)); +void openio P((int argc, char **argv)); +void skipeol P((void)); +void specialchar P((void)); + +/* label.c */ +void bumplc P((void)); +void bumplc2 P((void)); +void bumplc3 P((void)); +void clearfunclabels P((void)); +void clearlabels P((char *patchbuf, char *patchtop)); +void clearswitchlabels P((void)); +uoffset_t getlc P((void)); +void deflabel P((label_t label)); +label_t gethighlabel P((void)); +label_t getlabel P((void)); +void jump P((label_t label)); +void lbranch P((ccode_pt cond, label_t label)); +struct symstruct *namedlabel P((void)); +void outcond P((ccode_pt cond)); +void outlabel P((label_t label)); +void outnlabel P((label_t label)); +void sbranch P((ccode_pt cond, label_t label)); +void unbumplc P((void)); + +/* loadexp.c */ +value_t constexpression P((void)); +void initexpression P((struct typestruct *type)); +struct typestruct *loadexpression P((store_pt targreg, + struct typestruct *targtype)); + +/* longop.c */ +void longop P((op_pt op, struct symstruct *source, struct symstruct *target)); +void long1op P((op_pt op, struct symstruct *target)); +void outlongendian P((void)); + +/* output.c */ +void bugerror P((char *message)); +void closeout P((void)); +void error P((char *message)); +void error2error P((char *message1, char *message2)); +void fatalerror P((char *message)); +void finishup P((void)); +void flushout P((void)); +void limiterror P((char *message)); +void initout P((void)); +void openout P((char *oname)); +void outbyte P((int ch)); +void outcomma P((void)); +void outcpplinenumber P((unsigned nr, char *fname, char *str)); +void outhex P((uoffset_t num)); +void outhexdigs P((uoffset_t num)); +void outline P((char *s)); +void outminus P((void)); +void outnl P((void)); +void outnbyte P((int byte)); +void outnhex P((uoffset_t num)); +void outnop1str P((char *s)); +void outnop2str P((char *s)); +void outnstr P((char *s)); +void outop0str P((char *s)); +void outop1str P((char *s)); +void outop2str P((char *s)); +void outop3str P((char *s)); +void outplus P((void)); +void outshex P((offset_t num)); +void outstr P((char *s)); +void outtab P((void)); +void outudec P((unsigned num)); +void outuvalue P((uvalue_t num)); +void outvalue P((value_t num)); +char *pushudec P((char *s, unsigned num)); +void setoutbufs P((void)); + +/* preproc.c */ +void blanks P((void)); +bool_pt blanksident P((void)); +void checknotinif P((void)); +void define P((void)); +void definestring P((char *str)); +void docontrol P((void)); +void entermac P((void)); +void ifinit P((void)); +void leavemac P((void)); +void predefine P((void)); +char *savedlineptr P((void)); +void skipcomment P((void)); +void skipline P((void)); +void undefinestring P((char *str)); + +/* preserve.c */ +void changesp P((offset_t newsp, bool_pt absflag)); +void loadpres P((struct symstruct *source, struct symstruct *target)); +void modstk P((offset_t newsp)); +void pres2 P((struct symstruct *source, struct symstruct *target)); +void preserve P((struct symstruct *source)); +store_pt preslval P((struct symstruct *source, struct symstruct *target)); +void recovlist P((store_pt reglist)); +void savereturn P((store_pt savelist, offset_t saveoffset)); + +/* sc.c */ +int main P((int argc, char **argv)); + +/* scan.c */ +void cppscan P((void)); +void eofin P((char *message)); +bool_pt isident P((void)); +void nextsym P((void)); +void stringorcharconst P((void)); + +/* softop.c */ +void softop P((op_pt op, struct symstruct *source, struct symstruct *target)); + +/* state.c */ +void compound P((void)); +void outswoffset P((offset_t offset)); +void outswstacklab P((void)); + +/* table.c */ +struct symstruct *addglb P((char *name, struct typestruct *type)); +struct symstruct *addloc P((char *name, struct typestruct *type)); +struct symstruct *addlorg P((char *name, struct typestruct *type)); +void addsym P((char *name, struct typestruct *type, + struct symstruct *symptr)); +struct symstruct *constsym P((value_t intconst)); +void delsym P((struct symstruct *symptr)); +void dumpglbs P((void)); +void dumplocs P((void)); +void dumpstrings P((void)); +struct symstruct *exprsym P((struct symstruct *symptr)); +struct symstruct *findlorg P((char *name)); +struct symstruct *findstruct P((char *name)); +struct symstruct **gethashptr P((char *sname)); +void growheap P((unsigned size)); +void *growobject P((void *object, unsigned extra)); +label_t holdstr P((char *sptr, char *stop)); +void newlevel P((void)); +void oldlevel P((void)); +void ourfree P((void *ptr)); +void *ourmalloc P((unsigned nbytes)); +void outofmemoryerror P((char *message)); +void *qmalloc P((unsigned size)); +void swapsym P((struct symstruct *sym1, struct symstruct *sym2)); +void syminit P((void)); + +/* type.c */ +struct typestruct *addstruct P((char *structname)); +struct typestruct *iscalartotype P((scalar_pt scalar)); +struct typestruct *newtype P((void)); +void outntypechar P((struct typestruct *type)); +struct typestruct *pointype P((struct typestruct *type)); +struct typestruct *prefix P((constr_pt constructor, uoffset_t size, + struct typestruct *type)); +struct typestruct *promote P((struct typestruct *type)); +struct typestruct *tounsigned P((struct typestruct *type)); +void typeinit P((void)); + +/* library - fcntl.h */ +int creat P((const char *_path, int _mode)); +int open P((const char *_path, int _oflag, ...)); + +/* library - stdlib.h */ +double atof P((const char *_str)); +void exit P((int _status)); +void free P((void *_ptr)); +void *malloc P((unsigned _nbytes)); +void *realloc P((void *_ptr, unsigned _nbytes)); + +/* library - string.h */ +void *memcpy P((void *_t, const void *_s, unsigned _length)); +void *memset P((void *_s, int _c, unsigned _nbytes)); +char *strcat P((char *_target, const char *_source)); +char *strchr P((const char *_s, int _ch)); +int strcmp P((const char *_s1, const char *_s2)); +char *strcpy P((char *_target, const char *_source)); +unsigned strlen P((const char *_s)); +char *strncpy P((char *_target, const char *_source, unsigned _maxlength)); +char *strrchr P((const char *_s, int _ch)); + +/* library - unistd.h */ +int close P((int _fd)); +int isatty P((int _fd)); +long lseek P((int _fd, long _offset, int _whence)); +int read P((int _fd, char *_buf, unsigned _nbytes)); +int write P((int _fd, char *_buf, unsigned _nbytes)); diff --git a/bcc-bruce/reg.h b/bcc-bruce/reg.h new file mode 100644 index 0000000..822bda7 --- /dev/null +++ b/bcc-bruce/reg.h @@ -0,0 +1,139 @@ +/* reg.h - registers for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* + The compiler generates "addresses" of the form + indirect(indcount) (rx + offset) + where + rx is a machine register (possibly null) + n is the indirection count (possibly 0) + offset is a constant. + It does not support more complicated formats like + indirect(indcount) (rx + index * scale + offset). + + The register is coded as bit flag in the storage component of + the symbol structure. This allows groups of registers to be tested + using bitwise "&". Throughout the compiler, the group of these bit + flags has the type reg_t. If there are only a few registers, reg_t + can be an unsigned char. It must be unsigned if the high bit is + used, to avoid sign extension problems. For bootstrapping the compiler + from a compiler with no unsigned char, the unsigned type should be + used instead (with a signifigant waste of storage). + + The bit flags should really be defined as ((reg_t) whatever) but + then they would not (necessarily) be constant expressions and couldn't + be used in switch selectors or (worse) preprocessor expressions. + + The CONSTANT and GLOBAL (non-) register bits are almost + equivalent. A constant with nonzero indirection is marked as a + GLOBAL and not a CONSTANT. This makes it easier to test for a constant + CONSTANT. Globals which are formed in this way are converted to + constants if their indirection count is reset to 0 (by & operator). +*/ + +/* register bit flags */ + +#define NOSTORAGE 0x000 /* structure/union member offsets */ +#define CONSTANT 0x001 /* offsets are values */ +#define BREG 0x002 +#define DREG 0x004 +#define INDREG0 0x008 +#define INDREG1 0x010 +#define INDREG2 0x020 +#define LOCAL 0x040 +#define GLOBAL 0x080 /* offsets from storage name or 0 */ +#define CCREG CONSTANT /* arg to PSHS/PULS functions only */ +#ifdef I8088 +# ifdef FRAMEPOINTER +# define FRAMEREG LOCAL +# endif +# define STACKREG 0x100 +# define DATREG1 0x200 +# define DATREG2 0x400 +# define DATREG1B 0x800 +#endif +#ifdef MC6809 +# define DPREG LOCAL /* arg to PSHS/PULS functions only */ +# define PCREG GLOBAL /* arg to PSHS/PULS functions only */ +#endif + +/* data for pushing and pulling registers */ + +#define MINREGCHAR 'A' +#ifdef I8088 +# define FLAGSREGCHAR 'f' +# define pushchar() pushlist(AXREG) +#endif +#ifdef MC6809 +# define pushchar() pushlist(BREG) +#endif + +/* special registers */ + +#ifdef I8088 +# define ALREG BREG +# define AXREG DREG +# define DXREG DATREG2 +# define MULREG DATREG1B +# define SHIFTREG DATREG1B +#endif +#ifdef MC6809 +# define XREG INDREG0 /* XREG is special for ABX in index & switch */ +# define YREG INDREG2 /* XREG and YREG allow LEA (Z test) in cmp() */ +#endif + +/* groups of registers */ + +#define ALLDATREGS (BREG|DREG) +#define CHARREGS BREG +#define MAXREGS 1 /* number of data registers */ +#define WORKDATREGS (BREG|DREG) + +/* function call and return registers */ + +#define ARGREG RETURNREG /* for (1st) argument */ +#define LONGARGREGS LONGRETURNREGS /* for long or float arg */ +#define LONGRETURNREGS (INDREG0|LONGREG2) +#define LONGREG2 DREG +#ifdef I8088 +# define LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */ +# define RETURNREG DREG +#endif +#ifdef MC6809 +# define RETURNREG INDREG0 +#endif + +/* registers which can be pulled as a group with the program counter */ +/* to perform an efficient function return */ + +#ifdef MC6809 +#define JUNK1REGS BREG /* 1 bytes locals to discard */ +#define JUNK2REGS INDREG2 +#define JUNK3REGS (BREG|INDREG2) +#define JUNK4REGS (INDREG1|INDREG2) +#endif + +/* registers which can be pushed as a group with the first argument */ +/* to perform an efficient function startup */ + +#ifdef MC6809 +# define LOC1REGS CCREG /* 1 bytes local to allocate */ +# define LOC2REGS DREG +# define LOC3REGS (CCREG|DREG) +# define LOC4REGS (CCREG|DREG|DPREG) +# endif + +/* registers to be used by software operations */ + +#define OPREG INDREG0 /* 2nd reg for software ops (1st is DREG) */ +#define OPWORKREG INDREG2 /* 3rd register for software ops */ + +/* maximum indirection count for 1 instruction */ + +#ifdef I8088 +# define MAXINDIRECT 1 +#endif +#ifdef MC6809 +# define MAXINDIRECT 2 +#endif diff --git a/bcc-bruce/sc.h b/bcc-bruce/sc.h new file mode 100644 index 0000000..c17536a --- /dev/null +++ b/bcc-bruce/sc.h @@ -0,0 +1,27 @@ +/* sc.h - storage classes for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#ifdef MC6809 +#define DIRECTPAGE 0x01 /* modifier on global to show in dpseg */ +#endif +#define EXTERNAL 0x02 /* external */ +#define STATIC 0x04 + +/* symbols with flags above the 1st initialised value are not to be dumped */ + +#define MAXDUMPFLAG 0x07 +#define INITIALIZED 0x08 /* modifier on global to show initialized */ +#define LABELLED 0x10 /* modifier on static to show labelled */ + /* and on STRING to show labelled */ + +/* remaining "flags" are numbers, not flags */ +/* they are disjoint from all combinations of flags above */ +/* except STRING => LABELLED (and no other flags) */ + +#define DEFINITION 0x20 /* #defined name */ +#define KEYWORD 0x40 /* reserved word for C */ +#define STRUCTNAME 0x60 /* struct/union name or member name */ +#define REGVAR 0x80 /* register variable */ +#define TEMP 0xa0 /* temporary on stack expression eval */ +#define STRING 0xc0 /* string constant (=> LABELLED) */ diff --git a/bcc-bruce/scan.c b/bcc-bruce/scan.c new file mode 100644 index 0000000..0baecf8 --- /dev/null +++ b/bcc-bruce/scan.c @@ -0,0 +1,806 @@ +/* scan.c - lexical analyser for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#define GCH1() do { if (SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) specialchar(); } while (0) + +#include "const.h" +#include "types.h" +#include "input.h" +#include "os.h" +#include "output.h" +#include "sc.h" +#include "sizes.h" +#include "table.h" +#include "type.h" + +#undef EXTERN +#define EXTERN +#include "scan.h" + +PUBLIC sym_t symofchar[256] = +{ + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, WHITESPACE, SPECIALCHAR, BADCHAR, + WHITESPACE, SPECIALCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + + WHITESPACE, LOGNOTOP, STRINGCONST, CONTROL, /* !"# */ + BADCHAR, MODOP, AMPERSAND, CHARCONST, /* $%&' */ + LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */ + COMMA, HYPHEN, FLOATCONST, SLASH, /* ,-./ */ + + INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */ + INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */ + INTCONST, INTCONST, COLON, SEMICOLON, /* 89:; */ + LTOP, ASSIGNOP, GTOP, CONDOP, /* <=>? */ + + BADCHAR, IDENT, IDENT, IDENT, /* @ABC */ + IDENT, IDENT, IDENT, IDENT, /* DEFG */ + IDENT, IDENT, IDENT, IDENT, /* HIJK */ + IDENT, IDENT, IDENT, IDENT, /* LMNO */ + IDENT, IDENT, IDENT, IDENT, /* PQRS */ + IDENT, IDENT, IDENT, IDENT, /* TUVW */ + IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */ + SPECIALCHAR, RBRACKET, EOROP, IDENT, /* \]^_ */ + + BADCHAR, IDENT, IDENT, IDENT, /* `abc */ + IDENT, IDENT, IDENT, IDENT, /* defg */ + IDENT, IDENT, IDENT, IDENT, /* hijk */ + IDENT, IDENT, IDENT, IDENT, /* lmno */ + IDENT, IDENT, IDENT, IDENT, /* pqrs */ + IDENT, IDENT, IDENT, IDENT, /* tuvw */ + IDENT, IDENT, IDENT, LBRACE, /* xyz{ */ + OROP, RBRACE, NOTOP, BADCHAR, /* |}~ */ + + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR, + BADCHAR, BADCHAR, BADCHAR, BADCHAR +}; + +FORWARD void getident P((void)); +FORWARD void intconst P((void)); +FORWARD void ppnumber P((void)); +PRIVATE void newstringorcharconst P((void)); + +/* skip white space up to end of line (skip EOL's if in comments) */ + +PUBLIC void blanks() +{ + register char *reglineptr; + + while (TRUE) + { + reglineptr = lineptr; + while (SYMOFCHAR(*reglineptr) == WHITESPACE) + ++reglineptr; + lineptr = reglineptr; + if (SYMOFCHAR(ch = *reglineptr) == SPECIALCHAR) + { + specialchar(); + if (ch == EOL) + return; + if (SYMOFCHAR(ch) == WHITESPACE) + continue; + reglineptr = lineptr; + } + if (*reglineptr != '/') + return; + if (SYMOFCHAR(*(reglineptr + 1)) == SPECIALCHAR) + { + ch = *(lineptr = reglineptr + 1); + specialchar(); + ch = *(reglineptr = --lineptr) = '/'; /* pushback */ + } + if (*(reglineptr + 1) != '*') + return; + gch1(); + skipcomment(); + } +} + +PUBLIC void cppscan() +{ + while (TRUE) + { + switch (SYMOFCHAR(ch)) + { + case CHARCONST: + case STRINGCONST: + stringorcharconst(); + *charptr = 0; /* room reserved */ + outstr(constant.value.s); /* XXX - embedded null would kill it */ + charptr = constant.value.s; + break; + case CONTROL: + gch1(); + if (maclevel != 0) + { + error("# in a macro: not preprocessed"); /* XXX? */ + break; + } + else + { + cppmode = FALSE; + docontrol(); + cppmode = TRUE; + break; + } + case SLASH: + gch1(); + if (ch == '*') + { + skipcomment(); + break; + } + outbyte('/'); + break; + case FLOATCONST: + gch1(); + if (SYMOFCHAR(ch) == INTCONST) + { + --lineptr; + ch = '.'; /* pushback */ + ppnumber(); + outstr(constant.value.s); + charptr = constant.value.s; + } + else + outbyte('.'); + break; + case IDENT: + getident(); + if ((gsymptr = findlorg(gsname)) != NULL) + { + if (gsymptr->flags == DEFINITION) + { + entermac(); + break; + } + } + outstr(gsname); + break; + case INTCONST: + ppnumber(); + outstr(constant.value.s); + charptr = constant.value.s; + break; + case SPECIALCHAR: + specialchar(); /* XXX - this is necessary because entermac + * and skipeol can leave lineptr at a special + * char although GCH1 cannot. entermac would + * be easy to fix, but too many places already + * have to handle the extra work after skipeol + * for other reasons. + */ + if (ch == EOL) + { + skipeol(); + if (eof) + return; + break; + } +#ifdef COEOL + if (ch == COEOL) + { + gch1(); + break; + } +#endif + if (SYMOFCHAR(ch) != SPECIALCHAR) + break; /* specialchar advanced the input */ + /* must be '\\' */ + default: + OUTBYTE(ch); + GCH1(); + break; + } + } +} + +PUBLIC void eofin(message) +char *message; +{ + error2error("end of file in ", message); +} + +/* get identifier in gsname == gs2name + 2 */ + +PRIVATE void getident() +{ + register int c; + register char *idptr; + register int length; + register char *reglineptr; + + idptr = gsname; + length = NAMESIZE; + reglineptr = lineptr; + c = ch; +more: + do + { + *idptr++ = c; + c = (unsigned char) *++reglineptr; + } + while (symofchar[c] <= MAXIDSYM && --length != 0); + ch = c; + *idptr = 0; + lineptr = reglineptr; + if (symofchar[c] == SPECIALCHAR) + { + specialchar(); + if (SYMOFCHAR(ch) <= MAXIDSYM && length != 0) + { + reglineptr = lineptr; + c = ch; + goto more; + } + } +} + +/* return nonzero if at an identifier */ + +PUBLIC bool_pt isident() +{ + if (SYMOFCHAR(ch) != IDENT) + return FALSE; + getident(); + return TRUE; +} + +PRIVATE void intconst() +{ + fastin_t base; + fastin_t digit; + register char *digptr; + fastin_t lcount; + fastin_t ucount; + bool_t dflag; + + ppnumber(); + digptr = charptr = constant.value.s; + if (*digptr == '0') + { + if (digptr[1] != 'x' && digptr[1] != 'X') + base = 8; + else + { + base = 16; + digptr += 2; + } + } + else + base = 10; + dflag = FALSE; + if (*digptr == 0) + error("constant has no digits"); + if (base != 16) + { + while (SYMOFCHAR(*digptr) == INTCONST) + ++digptr; + if (*digptr == '.') + { + dflag = TRUE; + ++digptr; + while (SYMOFCHAR(*digptr) == INTCONST) + ++digptr; + } + if (*digptr == 'E' || *digptr == 'e') + { + dflag = TRUE; + ++digptr; + if (*digptr == '+' || *digptr == '-') + ++digptr; + if (SYMOFCHAR(*digptr) != INTCONST) + error("exponent has no digits"); + while (SYMOFCHAR(*digptr) == INTCONST) + ++digptr; + } + } + if (dflag) + { + constant.type = dtype; + digit = *digptr; + *digptr = 0; + constant.value.d = atof(constant.value.s); + *digptr = digit; + if (digit == 'F' || digit == 'f') + { + ++digptr; + constant.type = fltype; + constant.value.d = (float) constant.value.d; + } + sym = FLOATCONST; + if (*digptr != 0) + error("junk at end of floating point constant"); + return; + } + if (base != 16) + digptr = constant.value.s; + constant.value.v = 0; + while (*digptr >= '0') + { + digit = *digptr; + if (digit > '9') + { + if (base != 16) + break; + if (digit >= 'a' && digit <= 'f') + digit = digit + (-'a' + '0' + 10); + else if (digit >= 'A' && digit <= 'F') + digit = digit + (-'A' + '0' + 10); + else + break; + } + constant.value.v = base * constant.value.v + (digit - '0'); + ++digptr; + } + ucount = lcount = 0; + while (TRUE) + { + if (*digptr == 'L' || *digptr == 'l') + ++lcount; + else if (*digptr == 'U' || *digptr == 'u') + ++ucount; + else + break; + ++digptr; + } + if (lcount > 1) + error("more than one 'L' in integer constant"); + if (ucount > 1) + error("more than one 'U' in integer constant"); + if (constant.value.v <= maxintto && lcount == 0 && ucount == 0) + constant.type = itype; + else if (constant.value.v <= maxuintto && lcount == 0 + && (base != 10 || ucount != 0)) + constant.type = uitype; + else if (constant.value.v <= maxlongto && ucount == 0) + constant.type = ltype; + else + constant.type = ultype; + if (*digptr != 0) + error("junk at end of integer constant"); +} + +PUBLIC void nextsym() +{ + static char lastch; + register char *reglineptr; + + while (TRUE) /* exit with short, fast returns */ + { + reglineptr = lineptr; + while ((sym = SYMOFCHAR(*reglineptr)) == WHITESPACE) + ++reglineptr; + lastch = *reglineptr; + if (SYMOFCHAR(ch = *(lineptr = reglineptr + 1)) == SPECIALCHAR + && sym != SPECIALCHAR) + specialchar(); + switch (sym) + { + case CHARCONST: + --lineptr; + ch = lastch; /* pushback */ + stringorcharconst(); + newstringorcharconst(); + if (charptr == constant.value.s) + { + charptr = constant.value.s; + error("empty character constant"); + constant.value.v = 0; + } + else + { + if (charptr != constant.value.s + 1) + error("character constant too long"); + charptr = constant.value.s; + constant.value.v = *constant.value.s & CHMASKTO; + } + constant.type = itype; + return; + case CONTROL: + if (maclevel != 0) + { + error("# in a macro: not preprocessed"); /* XXX? */ + return; + } + else + { + docontrol(); + break; + } + case FLOATCONST: + if (SYMOFCHAR(ch) == INTCONST) + { + --lineptr; + ch = lastch; + intconst(); + } + else + sym = STRUCELTOP; + return; + case IDENT: + --lineptr; + ch = lastch; + getident(); + if ((gsymptr = findlorg(gsname)) != NULL) + { + if (gsymptr->flags == DEFINITION) + { + entermac(); + break; + } + if (gsymptr->flags == KEYWORD) + sym = gsymptr->offset.offsym; + } + return; + case INTCONST: + --lineptr; + ch = lastch; + intconst(); + return; + case SPECIALCHAR: + ch = *(lineptr = reglineptr); + specialchar(); + if (ch == EOL) + { + if (incppexpr) + { + sym = SEMICOLON; + return; + } + skipeol(); + if (eof) + { + sym = EOFSYM; + return; + } + break; + } + if (SYMOFCHAR(ch) != SPECIALCHAR) + break; + gch1(); + /* fall through to BADCHAR case */ + case BADCHAR: + error("illegal character"); + break; + case STRINGCONST: + --lineptr; + ch = lastch; /* pushback */ + stringorcharconst(); + newstringorcharconst(); +#ifdef TS + ts_n_string += charptr - constant.value.s; +#endif + return; + case COLON: /* could be COLONOP or in label */ + case COMMA: /* could be COMMAOP or in list */ + case CONDOP: + case LBRACE: + case LBRACKET: + case LPAREN: + case NOTOP: + case RBRACE: + case RBRACKET: + case RPAREN: + case SEMICOLON: + return; + case ASSIGNOP: + if (ch == '=') + { + sym = EQOP; + gch1(); + } + return; + case ADDOP: + if (ch == '+') + { + sym = INCSYM; /* PREINCOP or POSINCOP */ + gch1(); + } + else if (ch == '=') + { + sym = ADDABOP; + gch1(); + } + return; + case HYPHEN: /* NEGOP or SUBOP or decoded below */ + if (ch == '-') + { + sym = DECSYM; /* PREDECOP or POSTDECOP */ + gch1(); + } + else if (ch == '=') + { + sym = SUBABOP; + gch1(); + } + else if (ch == '>') + { + sym = STRUCPTROP; + gch1(); + } + return; + case STAR: /* INDIRECTOP or MULOP or as below */ + if (ch == '=') + { + sym = MULABOP; + gch1(); + } + return; + case SLASH: + if (ch == '*') + { + skipcomment(); + break; + } + if (ch == '=') + { + sym = DIVABOP; + gch1(); + } + else + sym = DIVOP; + return; + case MODOP: + if (ch == '=') + { + sym = MODABOP; + gch1(); + } + return; + case LTOP: + if (ch == '=') + { + sym = LEOP; + gch1(); + } + else if (ch == '<') + { + gch1(); + if (ch == '=') + { + sym = SLABOP; + gch1(); + } + else + { + sym = SLOP; + } + } + return; + case GTOP: + if (ch == '=') + { + sym = GEOP; + gch1(); + } + else if (ch == '>') + { + gch1(); + if (ch == '=') + { + sym = SRABOP; + gch1(); + } + else + { + sym = SROP; + } + } + return; + case AMPERSAND: /* ADDRESSOP or ANDOP or as below */ + if (ch == '&') + { + sym = LOGANDOP; + gch1(); + } + else if (ch == '=') + { + sym = ANDABOP; + gch1(); + } + return; + case EOROP: + if (ch == '=') + { + sym = EORABOP; + gch1(); + } + return; + case OROP: + if (ch == '|') + { + sym = LOGOROP; + gch1(); + } + else if (ch == '=') + { + sym = ORABOP; + gch1(); + } + return; + case LOGNOTOP: + if (ch == '=') + { + sym = NEOP; + gch1(); + } + return; + } + } +} + +PRIVATE void ppnumber() +{ + constant.value.s = charptr; + while (TRUE) + { + if (charptr >= char1top) + constant.value.s = growobject(constant.value.s, 2); + *charptr++ = ch; + if (ch == 'E' || ch == 'e') + { + gch1(); + if (ch == '+' || ch == '-') + continue; + } + else + GCH1(); + if (SYMOFCHAR(ch) > MAXPPNUMSYM) + break; + } + *charptr = 0; +} + +PUBLIC void stringorcharconst() +{ + char terminator; + + constant.value.s = charptr; + terminator = ch; + while (TRUE) + { + if (charptr >= char3top) + constant.value.s = growobject(constant.value.s, 4); + *charptr++ = ch; + if (ch == '\\') + { + gch1(); + if (ch == EOL) + { + if (!orig_cppmode) + eofin("escape sequence"); + break; + } + *charptr++ = ch; + } + GCH1(); + if (ch == EOL) + { + if (!orig_cppmode) + error(terminator == '"' ? "end of line in string constant" + : "end of line in character constant"); + break; + } + if (ch == terminator) + { + *charptr++ = terminator; + gch1(); + break; + } + } +} + +PRIVATE void newstringorcharconst() +{ + char *endinptr; + int escvalue; + fastin_t maxdigits; + register char *inptr; + register char *outptr; + + outptr = constant.value.s; + inptr = charptr - 1; + if (inptr == outptr || *inptr != *outptr) + endinptr = charptr; /* not properly terminated */ + else + endinptr = inptr; + inptr = outptr + 1; + while (inptr != endinptr) + { + if (*inptr == '\\') + { + if (++inptr == endinptr) + break; /* error reported already */ + if (*inptr >= '0' && *inptr < '8') + { + escvalue = 0; + maxdigits = 3; + do + { + escvalue = 8 * escvalue + *inptr - '0'; + ++inptr; + } + while (--maxdigits != 0 && *inptr >= '0' && *inptr < '8'); + --inptr; + *outptr++ = escvalue; + } + else switch (*inptr) + { + case '"': + case '\'': + case '\\': + *outptr++ = *inptr; + break; + case 'a': + *outptr++ = 7; + break; + case 'b': + *outptr++ = 8; + break; + case 'f': + *outptr++ = 12; + break; + case 'n': + *outptr++ = EOLTO; + break; + case 'r': + *outptr++ = 13; + break; + case 't': + *outptr++ = 9; + break; + case 'v': + *outptr++ = 11; + break; + default: + error("%wnonstandard escape sequence"); + *outptr++ = *inptr; + break; + } + } + else + *outptr++ = *inptr; + ++inptr; + } + charptr = outptr; +} diff --git a/bcc-bruce/scan.h b/bcc-bruce/scan.h new file mode 100644 index 0000000..5333e96 --- /dev/null +++ b/bcc-bruce/scan.h @@ -0,0 +1,201 @@ +/* scan.h - scanner for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#define NAMESIZE 64 /* limit on identifier lengths */ +#define SYMOFCHAR(ch) (symofchar[(unsigned char) (ch)]) + +/* scanner codes */ + +enum +{ +/* The first group of entries consists of all the values that occur in the + switch for cppscan(). +*/ + IDENT, + INTCONST, +#define MAXIDSYM INTCONST /* IDENT and INTCONST must be the only + * symofchar[] entries below this */ + FLOATCONST, +#define MAXPPNUMSYM FLOATCONST /* IDENT, INTCONST and FLOATCONST must be the + * only symofchar[] entries below this */ + CHARCONST, + CONTROL, + SLASH, + SPECIALCHAR, + STRINGCONST, + +/* The next group of entries are all the rest of the values that occur in + symofchar[] and so in the switch for nextsym(). +*/ + AMPERSAND, /* ADDRESSOP or ANDOP */ + BADCHAR, + COLON, /* also COLONOP */ + COMMA, /* also COMMAOP */ + DECSYM, /* PREDECOP or POSTDECOP */ + EOFSYM, + HYPHEN, /* NEGOP or SUBOP */ + INCSYM, /* PREINCOP or POSTINCOP */ + LBRACE, + LBRACKET, + LPAREN, + RBRACE, + RBRACKET, + RPAREN, + SEMICOLON, + STAR, /* INDIRECTOP or MULOP */ + WHITESPACE, + +/* The next group of entries consists of all operator codes. These codes must + be contiguous so they can be used as (offsetted) array indexes. The group + is ordered by operator-precedence (this is not necessary). The first part + of it overlaps the previous group. +*/ + +/* Assign-abops (level 1) belong here but are at end to improve switch. */ + +#define FIRSTOP CONDOP + CONDOP, /* level 2 */ + + OROP, /* level 5 */ + + EOROP, /* level 6 */ + + ANDOP, /* level 7 */ + + GTOP, /* level 9 */ + LTOP, + + ADDOP, /* level 11 */ + + DIVOP, /* level 12 */ + MODOP, + + LOGNOTOP, /* level 13 */ + NOTOP, + + STRUCELTOP, /* level 14 */ + STRUCPTROP, + +/* End of symbols that appear in symofchar[]. */ + + ASSIGNOP, /* level 1 - assign ops must be contiguous */ + ADDABOP, + ANDABOP, + DIVABOP, + EORABOP, + MODABOP, + MULABOP, + ORABOP, + SLABOP, + SRABOP, + SUBABOP, + + COMMAOP, /* level 0 */ + + COLONOP, /* level 2 */ + + LOGOROP, /* level 3 */ + + LOGANDOP, /* level 4 */ + + EQOP, /* level 8 */ + NEOP, + + GEOP, /* level 9 */ + LEOP, + + SLOP, /* level 10 */ + SROP, + + SUBOP, /* level 11 */ + + MULOP, /* level 12 */ + + ADDRESSOP, /* level 13 */ + CASTOP, + INDIRECTOP, + NEGOP, + PREDECOP, + PREINCOP, + POSTDECOP, + POSTINCOP, + + FUNCOP, /* level 14 */ + LISTOP, + ROOTLISTOP, + + LEAF, /* special */ + PTRADDABOP, + PTRADDOP, + PTRSUBOP, + +/* end of operator codes (they must stay contiguous) */ + +#define LASTOP PTRSUBOP + + ENUMDECL, + NULLDECL, + STRUCTDECL, + TYPEDECL, + TYPEDEFNAME, + UNIONDECL, + UNSIGNDECL, + + AUTODECL, + EXTERNDECL, + REGDECL, + STATICDECL, + TYPEDEFDECL, + + BREAKSYM, + CASESYM, + CONTSYM, + DEFAULTSYM, + DEFINEDSYM, + DOSYM, + ELSESYM, + FORSYM, + GOTOSYM, + IFSYM, + RETURNSYM, + SIZEOFSYM, + SWITCHSYM, + WHILESYM, + + ASMCNTL, + DEFINECNTL, + ENDASMCNTL, + INCLUDECNTL, + LINECNTL, + UNDEFCNTL, + + ELIFCNTL, /* "IF" controls must be contiguous */ + ELSECNTL, + ENDIFCNTL, + IFCNTL, + IFDEFCNTL, + IFNDEFCNTL +}; + +EXTERN op_pt arg1op; /* LISTOP, or ROOTLISTOP if arg1inreg */ +EXTERN struct +{ + union + { + char *s; + value_t v; + double d; + } + value; + struct typestruct *type; +} + constant; /* value of last constant scanned */ + /* sym tells type */ +EXTERN char funcname[NAMESIZE]; /* name of current function for unique labels */ +EXTERN char gs2name[2 + NAMESIZE]; /* 2 reserved for namespace keys */ +#define gsname (gs2name + 2) /* before last identifier */ +EXTERN struct symstruct *gsymptr; /* symbol ptr for last identifier */ +EXTERN bool_t incppexpr; /* nonzero while scanning cpp expression */ +EXTERN sym_t sym; /* current symbol */ +extern sym_t symofchar[]; /* table to convert chars to their symbols */ diff --git a/bcc-bruce/sizes.h b/bcc-bruce/sizes.h new file mode 100644 index 0000000..df0d141 --- /dev/null +++ b/bcc-bruce/sizes.h @@ -0,0 +1,50 @@ +/* sizes.h - target scalar type sizes for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* + the compiler is not very portable in this area + it only directly supports I8088-I80386 and MC6809 + it assumes + sizeof(source long) >= sizeof(target long) + usual register size = int + long = 2 int sizes +*/ + +#define CHBITSTO 8 /* bits in a character */ +#define CHMASKTO 0xFF /* mask to reduce SOURCE int to TARGET uchar */ +#define INT16BITSTO 16 /* not accessed in non-16 bit case */ +#define INT32BITSTO 32 /* not accessed in non-32 bit case */ +#define MAXINTBITSTO 32 /* max bits in an integer (var processors) */ +#define MAXSCHTO 127 /* maximum signed character */ +#define MAXUCHTO 255 /* maximum unsigned character */ +#define MINSCHTO (-128) /* minimum signed character */ + +#ifdef MC6809 +# define is5bitoffset(n) ((uoffset_t) (n) + 0x10 < 0x20) +#endif +#define isbyteoffset(n) ((uoffset_t) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO) +#define ischarconst(n) ((uvalue_t) (n) <= MAXUCHTO) +#define isnegbyteoffset(n) ((uvalue_t) (n) + MAXSCHTO <= MAXSCHTO - MINSCHTO) +#define isshortbranch(n) ((uoffset_t) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO) + +#ifdef MC6809 +/* Hack to reduce number of direct page variables. */ +#define intmaskto ((uvalue_t) 0xFFFFL) +#define maxintto ((uvalue_t) 0x7FFFL) +#define maxlongto ((uvalue_t) 0x7FFFFFFFL) +#define maxoffsetto ((uvalue_t) 0x7FFFL) +#define maxshortto ((uvalue_t) 0x7FFFL) +#define maxuintto ((uvalue_t) 0xFFFFL) +#define maxushortto ((uvalue_t) 0xFFFFL) +#define shortmaskto ((uvalue_t) 0xFFFFL) +#else +extern uvalue_t intmaskto; /* mask for ints */ +extern uvalue_t maxintto; /* maximum int */ +extern uvalue_t maxlongto; /* maximum long */ +extern uvalue_t maxoffsetto; /* maximum offset */ +extern uvalue_t maxshortto; /* maximum short */ +extern uvalue_t maxuintto; /* maximum unsigned */ +extern uvalue_t maxushortto; /* maximum unsigned short */ +extern uvalue_t shortmaskto; /* mask for shorts */ +#endif diff --git a/bcc-bruce/softop.c b/bcc-bruce/softop.c new file mode 100644 index 0000000..d676e18 --- /dev/null +++ b/bcc-bruce/softop.c @@ -0,0 +1,222 @@ +/* softop.c - software operations for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "gencode.h" +#include "reg.h" +#include "scan.h" +#include "sizes.h" +#include "type.h" + +/*----------------------------------------------------------------------------- + softop(operation code, source leaf, target leaf) + handles binary operations which are not done in hardware + if the result type is (unsigned) long, float or double, all the work + is immediately passed on to routines in other files. Otherwise: + source and target may be either char, int or unsigned int + they are not cast to ints or unsigneds before they get here + considerable effort goes into avoiding unnecessary pushes +-----------------------------------------------------------------------------*/ + +PUBLIC void softop(op, source, target) +op_pt op; +struct symstruct *source; +struct symstruct *target; +{ + store_t regpushed; + store_t regmark; + scalar_t resultscalar; + scalar_t sscalar; + scalar_t tscalar; + value_t sourceval; + bool_t uflag; + store_t workreg; + + if ((tscalar = target->type->scalar) & DLONG) + { + longop(op, source, target); + return; + } + if (tscalar & RSCALAR) + { + floatop(op, source, target); + return; + } + sscalar = source->type->scalar; + resultscalar = tscalar; + uflag = tscalar & UNSIGNED; + if (op != SLOP && op != SROP) + { + resultscalar |= sscalar; + uflag |= sscalar & UNSIGNED; + } +#ifdef MC6809 + if ((op_t) op == MULOP && sscalar & CHAR && tscalar & CHAR && + (source->storage != CONSTANT || (uvalue_t) source->offset.offv > 2)) + { + if (source->storage & WORKDATREGS) + push(source); + load(target, DREG); + outldmulreg(); + outadr(source); + outmulmulreg(); + target->storage = DREG; + target->type = iscalartotype(resultscalar); + return; + } +#endif + if (source->storage == CONSTANT) + { + extend(target); +#ifdef I8088 + if (op == MULOP || op == SLOP) + loadany(target); + else +#endif + load(target, DREG); + target->type = iscalartotype(resultscalar); + sourceval = source->offset.offv; + switch ((op_t) op) + { + case DIVOP: + if (diveasy(sourceval, uflag)) + return; + break; + case MODOP: + if (modeasy(sourceval, uflag)) + { + if ((uvalue_t) sourceval <= MAXUCHTO + 1) + { + target->storage = BREG; + target->type = ctype; + if (uflag) + target->type = uctype; + } + return; + } + break; + case MULOP: + if (muleasy((uvalue_t) sourceval, target->storage)) + return; + load(target, DREG); + break; + case SLOP: + slconst(sourceval, target->storage); + return; + case SROP: + srconst(sourceval, uflag); + return; + } + sscalar = (source->type = iscalartotype(resultscalar))->scalar; + } + +/* to load source first if it is CHAR: */ +/* need work register if target is in WORKDATREGS */ +/* use OPREG unless it will become overloaded later */ + +/* to preserve source while target is loaded: */ +/* if source is in WORKDATREGS, put it in OPREG, */ +/* unless target is OPREG-indirect */ +/* otherwise, if source is in WORKDATREGS, put it in work reg not OPREG */ +/* also assign a work reg if source is already in OPREG and target needs one */ + + regpushed = (regmark = reguse) & OPREG; + workreg = OPREG; + if (sscalar & CHAR && target->storage & WORKDATREGS && + source->storage == OPREG && source->indcount != 0 || + (sscalar & CHAR || source->storage & WORKDATREGS) && + target->storage == OPREG && target->indcount != 0 || + source->storage == OPREG && + target->storage == GLOBAL && target->indcount == 0 +#ifdef MC6809 + && posindependent +#endif + ) + { + if ((regmark | OPREG) == allindregs) + regpushed |= (workreg = OPWORKREG); + else + { + reguse |= OPREG; + workreg = getindexreg(); + } + } + pushlist(regpushed); /* no more pushes */ + reguse = allindregs; /* error if another reg unexpectedly needed */ + + if (sscalar & CHAR) + { + if (target->storage & WORKDATREGS) + { + extend(target); + if (source->storage == workreg) + exchange(source, target); + else + transfer(target, workreg); + } + extend(source); + if (target->storage != OPREG && + (target->storage != GLOBAL || target->indcount != 0 +#ifdef MC6809 + || !posindependent +#endif + )) + workreg = OPREG; + } + if (source->storage & WORKDATREGS) + { + if (target->storage == OPREG && target->indcount == 0) + exchange(source, target); + else + { + transfer(source, workreg); + workreg = OPREG; + } + } + if (target->storage == GLOBAL && target->indcount == 0 +#ifdef MC6809 + && posindependent +#endif + ) + load(target, workreg); + +/* source and target now in position to be loaded without any more registers */ + + extend(target); + load(target, DREG); + load(source, OPREG); + switch ((op_t) op) + { + case DIVOP: +#ifdef I8088 + call("idiv_"); +#else + call("idiv"); +#endif + break; + case MODOP: + call("imod"); + break; + case MULOP: +#ifdef I8088 + call("imul_"); +#else + call("imul"); +#endif + break; + case SLOP: + call("isl"); + break; + case SROP: + call("isr"); + break; + } + if (uflag) + outbyte('u'); + outnl(); + target->type = iscalartotype(resultscalar); + poplist(regpushed); + reguse = regmark; +} diff --git a/bcc-bruce/state.c b/bcc-bruce/state.c new file mode 100644 index 0000000..526d1f9 --- /dev/null +++ b/bcc-bruce/state.c @@ -0,0 +1,793 @@ +/* state.c - statement routines for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "align.h" +#include "condcode.h" +#include "gencode.h" +#include "input.h" /* just for ch and eof for label check */ +#include "label.h" +#include "os.h" /* just for EOL */ +#include "parse.h" +#include "reg.h" +#include "scan.h" +#include "sizes.h" +#include "table.h" +#include "type.h" + +#define COLONCHAR ':' /* for label */ +#define GROWCASES 64 /* extra cases for growth of switch struct */ +#define INITIALCASES 16 /* initial cases in switch structure */ + +struct loopstruct +{ + label_t breaklab; /* destination for break */ + label_t contlab; /* destination for continue */ + struct nodestruct *etmark; /* expression tree built during loop */ + struct symstruct *exprmark; /* expression symbols built during loop */ + struct symstruct *locmark; /* local variables built during loop */ + struct loopstruct *prevloop; /* previous active for, switch or while */ + offset_t spmark; /* stack value for continue and break */ +}; + +struct switchstruct +{ + struct casestruct *caseptr; /* current spot in caselist */ + struct casestruct *casetop; /* last in caselist + 1 */ + bool_t charselector; /* tells if case selector is char */ + label_t dfaultlab; /* destination for default case (0 if none) */ + struct switchstruct *prevswitch; /* previous active switch */ + struct casestruct + { + value_t casevalue; /* value giving this case */ + label_t caselabel; /* corresponding label */ + } + caselist[INITIALCASES]; /* perhaps larger */ +}; + +PRIVATE struct loopstruct *loopnow; /* currently active for/switch/while */ + /* depends on NULL init */ +PRIVATE bool_t returnflag; /* set if last effective statement */ + /* was a return */ +PRIVATE label_t swstacklab; /* label giving stack for switch statement */ + +FORWARD void addloop P((struct loopstruct *newloop)); +FORWARD void badloop P((void)); +FORWARD void deleteloop P((void)); +FORWARD void evalexpression P((struct nodestruct *exp)); +FORWARD void exprstatement P((void)); +FORWARD bool_pt isforever P((struct nodestruct *exp)); +FORWARD void sort P((struct casestruct *caselist, int count)); +FORWARD void dobreak P((void)); +FORWARD void docase P((void)); +FORWARD void docont P((void)); +FORWARD void dodefault P((void)); +FORWARD void dodowhile P((void)); +FORWARD void dofor P((void)); +FORWARD void dogoto P((void)); +FORWARD void doif P((void)); +FORWARD void doreturn P((void)); +FORWARD void doswitch P((void)); +FORWARD void dowhile P((void)); +FORWARD void jumptocases P((void)); +FORWARD void statement P((void)); + +/* --- utility routines --- */ + +PRIVATE void addloop(newloop) +struct loopstruct *newloop; +{ + newloop->breaklab = getlabel(); + newloop->contlab = getlabel(); + newloop->etmark = etptr; + newloop->exprmark = exprptr; + newloop->locmark = locptr; + newloop->prevloop = loopnow; + newloop->spmark = sp; + loopnow = newloop; +} + +PRIVATE void badloop() +{ + error(" no active fors, switches or whiles"); +} + +PRIVATE void deleteloop() +{ + etptr = loopnow->etmark; + exprptr = loopnow->exprmark; + locptr = loopnow->locmark; + loopnow = loopnow->prevloop; +} + +PRIVATE void evalexpression(exp) +struct nodestruct *exp; +{ + offset_t spmark; + + spmark = sp; + makeleaf(exp); + modstk(spmark); +} + +PRIVATE void exprstatement() +{ + struct nodestruct *etmark; + struct symstruct *exprmark; + + etmark = etptr; + exprmark = exprptr; + evalexpression(expression()); + etptr = etmark; + exprptr = exprmark; +} + +PRIVATE bool_pt isforever(exp) +register struct nodestruct *exp; +{ + return exp == NULL || + exp->tag == LEAF && exp->left.symptr->storage == CONSTANT && + exp->left.symptr->offset.offv != 0; +} + +PRIVATE void sort(caselist, count) /* shell sort */ +struct casestruct *caselist; +int count; +{ + register int gap; + register int i; + int j; + struct casestruct swaptemp; + + gap = 1; + do + gap = 3 * gap + 1; + while (gap <= count); + while (gap != 1) + { + gap /= 3; + for (j = gap; j < count; ++j) + for (i = j - gap; + i >= 0 && caselist[i].casevalue > caselist[i + gap].casevalue; + i -= gap) + { + swaptemp = caselist[i]; + caselist[i] = caselist[i + gap]; + caselist[i + gap] = swaptemp; + } + } +} + +/* --- syntax routines --- */ + +/* ---------------------------------------------------------------------------- + compound-statement: + "{" <declaration-list> <statement-list> "}" +---------------------------------------------------------------------------- */ + +PUBLIC void compound() /* have just seen "{" */ +{ + struct symstruct *locmark; + store_t regmark; +#ifdef FRAMEPOINTER + offset_t framepmark; + offset_t softspmark; +#else + /* softsp == sp here unless level == ARGLEVEL so mark is unnec */ + /* this is also true if funcsaveregsize != 0 but the tests are too messy */ +#endif + offset_t spmark; + + locmark = locptr; + regmark = reguse; +#ifdef FRAMEPOINTER + softspmark = softsp; + framepmark = framep; +#endif + spmark = sp; + newlevel(); + decllist(); + softsp &= alignmask; + if (sym != RBRACE) /* no need for locals if empty compound */ + reslocals(); + returnflag = FALSE; + while (sym != RBRACE && sym != EOFSYM) + statement(); + oldlevel(); + if (!returnflag) + { + if (level != ARGLEVEL) + { + if (switchnow == NULL) + { +#ifdef FRAMEPOINTER + if (framep != 0) + { + /* some args or locals, maybe at lower levels */ + modstk(softspmark); + if (framep != framepmark) + /* frame was just set up */ + popframe(); + } +#else + modstk(spmark); +#endif + } + } + else + ret(); + } +#ifdef FRAMEPOINTER + framep = framepmark; + sp = spmark; + softsp = softspmark; +#else + softsp = sp = spmark; +#endif + reguse = regmark; + locptr = locmark; + rbrace(); +} + +PRIVATE void dobreak() +{ + offset_t spmark; + + if (loopnow == NULL) + badloop(); + else + { + if (switchnow == NULL) + { + spmark = sp; + modstk(loopnow->spmark); + sp = spmark; + } + jump(loopnow->breaklab); + } +} + +PRIVATE void docase() +{ + value_t caseval; + + caseval = constexpression() & intmaskto; /* FIXME: warn overflow */ + if (caseval > maxintto) + caseval -= (maxuintto + 1); + colon(); + if (switchnow == NULL) + error("case not in switch"); + else + { + if (switchnow->charselector && (caseval < 0 || caseval > 255)) + error("%wcase cannot be reached with char switch"); + else + { + if (switchnow->caseptr >= switchnow->casetop) + { + int ncases; + + ncases = (/* ptrdiff_t */ int) + (switchnow->caseptr - &switchnow->caselist[0]); + switchnow = realloc(switchnow, + (/* size_t */ unsigned) + ((char *) switchnow->caseptr + - (char *) switchnow) + + GROWCASES * sizeof (struct casestruct)); +#ifdef TS +++ts_n_case_realloc; +ts_s_case += GROWCASES * sizeof (struct casestruct); +ts_s_case_tot += GROWCASES * sizeof (struct casestruct); +#endif + if (switchnow == NULL) + outofmemoryerror(""); + switchnow->caseptr = &switchnow->caselist[ncases]; + switchnow->casetop = switchnow->caseptr + GROWCASES; + } + switchnow->caseptr->casevalue = caseval; + deflabel(switchnow->caseptr->caselabel = getlabel()); + ++switchnow->caseptr; + } + } +} + +PRIVATE void docont() +{ + struct loopstruct *contloop; + offset_t spmark; + struct switchstruct *switchthen; + + for (contloop = loopnow, switchthen = switchnow; ; + contloop = contloop->prevloop, switchthen = switchthen->prevswitch) + { + if (contloop == NULL) + { + badloop(); + return; + } + if (contloop->contlab != 0) + break; + } + if (switchnow == NULL) + { + spmark = sp; + modstk(contloop->spmark); + sp = spmark; + } + else if (switchthen == NULL) + { + outaddsp(); + outshex(contloop->spmark); + outminus(); + outswstacklab(); +#ifdef MC6809 + outcregname(LOCAL); +#endif +#ifdef I8088 + if (i386_32) + bumplc2(); +#endif + outnl(); + } + jump(contloop->contlab); +} + +PRIVATE void dodefault() +{ + colon(); + if (switchnow == NULL) + error("default not in switch"); + else if (switchnow->dfaultlab != 0) + error("multiple defaults"); + else + deflabel(switchnow->dfaultlab = getlabel()); +} + +PRIVATE void dodowhile() +{ + struct loopstruct dwhileloop; + label_t dolab; + + addloop(&dwhileloop); + deflabel(dolab = getlabel()); + statement(); + if (sym == WHILESYM) + nextsym(); + else + error("missing while at end of do-while"); + deflabel(dwhileloop.contlab); + lparen(); + jumptrue(expression(), dolab); + rparen(); + semicolon(); + deflabel(dwhileloop.breaklab); + deleteloop(); +} + +PRIVATE void dofor() +{ + struct loopstruct forloop; + label_t forstatlab; + label_t fortestlab; + struct nodestruct *testexp; + struct nodestruct *loopexp; + + lparen(); + if (sym != SEMICOLON) + exprstatement(); + semicolon(); + addloop(&forloop); + if (sym == SEMICOLON) + testexp = NULL; + else + testexp = expression(); /* remember test expression */ + semicolon(); + if (sym == RPAREN) + loopexp = NULL; + else + loopexp = expression(); /* remember loop expression */ + rparen(); + if (!isforever(testexp)) + jump(fortestlab = getlabel()); /* test at bottom */ + deflabel(forstatlab = getlabel()); /* back here if test succeeds */ + statement(); + deflabel(forloop.contlab); + if (loopexp != NULL) + evalexpression(loopexp); + if (isforever(testexp)) + jump(forstatlab); + else + { + deflabel(fortestlab); /* test label */ + jumptrue(testexp, forstatlab); + } + deflabel(forloop.breaklab); + deleteloop(); +} + +PRIVATE void dogoto() +{ + struct symstruct *symptr; + + if (sym == IDENT || sym == TYPEDEFNAME) + { + symptr = namedlabel(); +/* + if (symptr->indcount == 4) + modstk( + else +*/ + adjsp(symptr->offset.offlabel); + jump(symptr->offset.offlabel); + nextsym(); + } + else + error("need identifier"); +} + +PRIVATE void doif() +{ + struct nodestruct *etmark; + label_t elselab; + label_t exitlab; + struct symstruct *exprmark; + + lparen(); + etmark = etptr; + exprmark = exprptr; + jumpfalse(expression(), elselab = getlabel()); + etptr = etmark; + exprptr = exprmark; + rparen(); + statement(); /* true, do a statement */ + if (sym == ELSESYM) /* "if .. else" statement */ + { + nextsym(); + jump(exitlab = getlabel()); /* over "else" label and code */ + deflabel(elselab); + statement(); + deflabel(exitlab); + } + else + deflabel(elselab); +} + +PRIVATE void doreturn() +{ + offset_t spmark; + + spmark = sp; + if (sym != SEMICOLON) /* returning expression */ + loadretexpression(); + ret(); /* clean up stack and return */ + sp = spmark; /* restore stack for rest of function */ +} + +PRIVATE void doswitch() +{ + struct switchstruct *sw; + struct loopstruct switchloop; + offset_t spmark; + label_t sdecidelab; + + sw = (struct switchstruct *) ourmalloc(sizeof *sw); +#ifdef TS +++ts_n_case; +ts_s_case += sizeof *sw; +ts_s_case_tot += sizeof *sw; +#endif + lparen(); + sw->charselector = loadexpression(DREG, NULLTYPE)->scalar & CHAR; + rparen(); + if (switchnow == NULL) + spmark = lowsp = sp; + addloop(&switchloop); + sw->dfaultlab = switchloop.contlab = 0; /* kill to show this is a switch */ + sw->casetop = (sw->caseptr = sw->caselist) + INITIALCASES; + sw->prevswitch = switchnow; + jump(sdecidelab = getlabel()); /* to case decision label */ + if (switchnow == NULL) + swstacklab = gethighlabel(); + switchnow = sw; + statement(); /* cases */ + sw = switchnow; + jump(switchloop.breaklab); /* over case decision to break label */ + deflabel(sdecidelab); + if (sw->prevswitch == NULL) + modstk(lowsp); + jumptocases(); + deflabel(switchloop.breaklab); + if ((switchnow = sw->prevswitch) == NULL) + { + equlab(swstacklab, lowsp); + clearswitchlabels(); + modstk(spmark); + } + deleteloop(); +#ifdef TS +ts_s_case_tot -= (char *) sw->casetop - (char *) sw; +#endif + ourfree(sw); +} + +PRIVATE void dowhile() +{ + struct loopstruct whileloop; + struct nodestruct *testexp; + label_t wstatlab; + + lparen(); + addloop(&whileloop); + testexp = expression(); + rparen(); + if (!isforever(testexp)) + jump(whileloop.contlab); /* test at bottom */ + deflabel(wstatlab = getlabel()); /* back here if test succeeds */ + statement(); + deflabel(whileloop.contlab); + jumptrue(testexp, wstatlab); + deflabel(whileloop.breaklab); + deleteloop(); +} + +PRIVATE void jumptocases() +{ + value_t basevalue; + struct casestruct *case1ptr; + struct casestruct *caseptr; + struct casestruct *casetop; + value_t caseval; + bool_t charselector; + bool_t dfaultflag; + label_t dfaultlab; + label_t jtablelab; + ccode_t lowcondition; + store_pt targreg; + label_t zjtablelab; + + caseptr = switchnow->caselist; + casetop = switchnow->caseptr; + sort(caseptr, (/* ptrdiff_t */ int) (casetop - caseptr)); + basevalue = 0; + if ((charselector = switchnow->charselector) != 0) + { + targreg = BREG; + lowcondition = LO; + } + else + { + targreg = DREG; + lowcondition = LT; + } + dfaultflag = TRUE; + if ((dfaultlab = switchnow->dfaultlab) == 0) + { + dfaultflag = FALSE; + dfaultlab = loopnow->breaklab; + } + --casetop; + for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr) + if (case1ptr->casevalue == (case1ptr + 1)->casevalue) + error("duplicate case in switch"); + while (caseptr <= casetop) + { + outsub(); + outimadj((offset_t) (caseptr->casevalue - basevalue), targreg); + basevalue = caseptr->casevalue; + for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr) + if (case1ptr->casevalue < (case1ptr + 1)->casevalue - 10) + break; + if (case1ptr < caseptr + 5) + { + lbranch(EQ, caseptr->caselabel); + ++caseptr; + } + else + { + lbranch(lowcondition, dfaultlab); + outcmp(); + outimadj((offset_t) (case1ptr->casevalue - basevalue), targreg); + lbranch(HI, zjtablelab = getlabel()); + if (charselector) + ctoi(); +#ifdef MC6809 + else + bumplc(); /* extra for CMPD */ +#endif + slconst((value_t) (ptypesize / 2), DREG); + /* really log ptypesize */ + deflabel(jtablelab = casejump()); +#ifdef I8088 + jtablelab = jtablelab; /* not used, allocated for regress */ +#endif + for (caseval = caseptr->casevalue; caseval <= case1ptr->casevalue; + ++caseval) + { +#ifdef I8088 + if (ptypesize > 2) + defdword(); + else +#endif + defword(); + if (caseval != caseptr->casevalue) + outlabel(dfaultlab); + else + { + outlabel(caseptr->caselabel); + ++caseptr; + } +#ifdef MC6809 + if (posindependent) + { + outminus(); + outlabel(jtablelab); + } +#endif + bumplc2(); +#ifdef I8088 + if (ptypesize > 2) + bumplc2(); +#endif + outnl(); + } + deflabel(zjtablelab); + } + lowcondition = LO; /* 1st subtraction makes rest unsigned */ + } + if (dfaultflag) + jump(dfaultlab); +} + +PUBLIC void outswoffset (offset) +offset_t offset; +{ +#ifdef FRAMEPOINTER + outoffset(offset - softsp - framep); +#else + outoffset(offset - softsp - sp); +#endif + outplus(); + outswstacklab(); +#ifdef I8088 + bumplc(); + if (i386_32) + bumplc2(); +#endif +} + +PUBLIC void outswstacklab() +{ + outbyte(LOCALSTARTCHAR); + outlabel(swstacklab); +} + +/* ---------------------------------------------------------------------------- + statement: + <compound-statement> + <if-statement> + <while-statement> + <do-statement> + <for-statement> + <switch-statement> + <case-statement> + <default-statement> + <break-statement> + <continue-statement> + <return-statement> + <goto-statement> + <labelled-statement> + <null-statement> + <expression> ; +---------------------------------------------------------------------------- */ + +PRIVATE void statement() +{ +#if 1 + struct symstruct *symptr; +#endif + +more: + switch (sym) + { + case LBRACE: + nextsym(); + compound(); + return; + case IFSYM: + nextsym(); + doif(); + break; + case WHILESYM: + nextsym(); + dowhile(); + break; + case FORSYM: + nextsym(); + dofor(); + break; + case RETURNSYM: + nextsym(); + doreturn(); + semicolon(); + returnflag = TRUE; + return; + case SWITCHSYM: + nextsym(); + doswitch(); + break; + case BREAKSYM: + nextsym(); + dobreak(); + semicolon(); + break; + case CASESYM: + nextsym(); + docase(); + goto more; + case DEFAULTSYM: + nextsym(); + dodefault(); + goto more; + case DOSYM: + nextsym(); + dodowhile(); + break; + case CONTSYM: + nextsym(); + docont(); + semicolon(); + break; + case GOTOSYM: + nextsym(); + dogoto(); + semicolon(); + break; + case SEMICOLON: + nextsym(); + return; + case IDENT: + case TYPEDEFNAME: + blanks(); /* cannot afford nextsym() */ + while (ch == EOL && !eof) + { + /* this now fails only on #controls and macros giving ':' */ + skipeol(); + blanks(); + } + if (ch == COLONCHAR) + { +#if 0 + struct symstruct *symptr; +#endif + symptr = namedlabel(); + if (symptr->indcount != 2) + error("redefined label"); + else + { + deflabel(symptr->offset.offlabel); + if (switchnow != NULL) + symptr->indcount = 3; + else + { + symptr->indcount = 4; + outbyte(LOCALSTARTCHAR); + outlabel(symptr->offset.offlabel); + outop0str("\t=\t"); + outshex(sp); + outnl(); + } + } + nextsym(); + nextsym(); + goto more; + } + /* else fall into default */ + default: + exprstatement(); + semicolon(); + break; + } + returnflag = FALSE; +} diff --git a/bcc-bruce/table.c b/bcc-bruce/table.c new file mode 100644 index 0000000..028950f --- /dev/null +++ b/bcc-bruce/table.c @@ -0,0 +1,668 @@ +/* table.c - table handler for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* Can I now get rid of EXPRLEVEL? Yes, except expression symbols must + * usually be set to some level different from OFFKLUDGELEVEL. + */ + +#include "const.h" +#include "types.h" +#include "align.h" +#include "gencode.h" +#include "os.h" +#include "parse.h" +#include "reg.h" +#include "sc.h" +#include "scan.h" +#include "sizes.h" +#include "type.h" + +#undef EXTERN +#define EXTERN +#include "table.h" + +#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */ +#define HASHTABSIZE 256 +#define MARKER ((unsigned) 0x18C396A5L) /* lint everywhere it is used */ +#define MAXEXPR 500 +#define MAXLOCAL 100 +#define NKEYWORDS 34 +#define NSCALTYPES 12 +#define STACKSPACE 256 /* punt for normal recursions - switch extra */ + +struct keywordstruct +{ + char *kwname; + sym_t kwcode; +}; + +#ifdef HOLDSTRINGS +struct string +{ + struct string *snext; + char *sptr; + char *stop; + label_t slabel; +}; +#endif + +struct typedatastruct +{ + char *tdname; + bool_t tdkeyscalar; + scalar_t tdscalar; + smalin_t tdsize; + struct typestruct **tdtypeptr; +}; + +PRIVATE struct symstruct exprsyms[MAXEXPR]; +PRIVATE struct symstruct *hashtab[HASHTABSIZE]; + /* depends on zero init */ +#ifdef HOLDSTRINGS +PRIVATE struct string *laststring; /* last in list of strings */ + /* depends on NULL init */ +#endif +PUBLIC struct symstruct locsyms[MAXLOCAL]; + +PRIVATE struct symstruct constemplate = +{ + CONSTANT, /* storage */ + 0, /* indcount */ + 0, /* flags */ + EXPRLEVEL, /* level */ + NULL, /* next */ + NULL, /* prev */ + NULL, /* type, init later to itype */ + /* offset is a union, set every time constemplate is used */ + /* name is a union, namea member is constant "\0" */ +}; + +PRIVATE struct keywordstruct keywords[NKEYWORDS] = +{ + { "enum", ENUMDECL, }, + { "struct", STRUCTDECL, }, + { "union", UNIONDECL, }, + { "unsigned", UNSIGNDECL, }, + + { "auto", AUTODECL, }, + { "extern", EXTERNDECL, }, + { "register", REGDECL, }, + { "static", STATICDECL, }, + + { "typedef", TYPEDEFDECL, }, + + { "break", BREAKSYM, }, + { "case", CASESYM, }, + { "continue", CONTSYM, }, + { "default", DEFAULTSYM, }, + { "do", DOSYM, }, + { "else", ELSESYM, }, + { "for", FORSYM, }, + { "goto", GOTOSYM, }, + { "if", IFSYM, }, + { "return", RETURNSYM, }, + { "sizeof", SIZEOFSYM, }, + { "switch", SWITCHSYM, }, + { "while", WHILESYM, }, + + { "#asm", ASMCNTL, }, + { "#define", DEFINECNTL, }, + { "#else", ELSECNTL, }, + { "#endasm", ENDASMCNTL, }, + { "#endif", ENDIFCNTL, }, + { "#if", IFCNTL, }, + { "#ifdef", IFDEFCNTL, }, + { "#include", INCLUDECNTL, }, + { "#ifndef", IFNDEFCNTL, }, + { "#line", LINECNTL, }, + { "#undef", UNDEFCNTL, }, + + { "defined", DEFINEDSYM, }, /* should be deactivated except in #if's */ +}; + +PRIVATE struct typedatastruct scaltypes[NSCALTYPES] = +{ + { "void", TRUE, 0, 0, &vtype, }, /* first - addkeyword uses vtype */ + { "char", TRUE, CHAR, 1, &ctype, }, + { "char", FALSE, UNSIGNED | CHAR, 1, &uctype, }, + { "char", FALSE, CHAR, 1, &sctype, }, + { "short", TRUE, SHORT, 2, &stype, }, + { "short", FALSE, UNSIGNED | SHORT, 2, &ustype, }, + { "int", TRUE, INT, 2, &itype, }, + { "int", FALSE, UNSIGNED | INT, 2, &uitype, }, + { "long", TRUE, LONG | DLONG, 4, <ype, }, + { "long", FALSE, UNSIGNED | LONG | DLONG, 4, &ultype, }, + { "float", TRUE, FLOAT, 4, &fltype, }, + { "double", TRUE, DOUBLE, 8, &dtype, }, +}; + +FORWARD struct symstruct *addkeyword P((char *name, sym_pt code)); +FORWARD void heapcorrupterror P((void)); + +PUBLIC struct symstruct *addglb(name, type) +char *name; +struct typestruct *type; +{ + struct symstruct **hashptr; + struct symstruct *oldsymptr; + register struct symstruct *symptr; + + hashptr = gethashptr(name); + symptr = *hashptr; + while (symptr != NULL) + { + oldsymptr = symptr; + symptr = symptr->next; + } + symptr = qmalloc(sizeof (struct symstruct) + strlen(name)); +#ifdef TS +++ts_n_global; +ts_size_global += sizeof (struct symstruct) + strlen(name); +#endif + addsym(name, type, symptr); + symptr->storage = GLOBAL; + symptr->level = GLBLEVEL; + if (*hashptr == NULL) + { + *hashptr = symptr; + symptr->prev = hashptr; + } + else + { + oldsymptr->next = symptr; + symptr->prev = &oldsymptr->next; + } + return symptr; +} + +PRIVATE struct symstruct *addkeyword(name, code) +char *name; +sym_pt code; +{ + struct symstruct *symptr; + + (symptr = addglb(name, vtype))->flags = KEYWORD; + symptr->offset.offsym = code; + return symptr; +} + +PUBLIC struct symstruct *addloc(name, type) +char *name; +struct typestruct *type; +{ + struct symstruct **hashptr; + register struct symstruct *symptr; + + hashptr = gethashptr(name); + symptr = *hashptr; + while (symptr != NULL) + symptr = symptr->next; + symptr = locptr; + locptr = (struct symstruct *) align(&symptr->name.namea[strlen(name) + 1]); + if (locptr >= &locsyms[MAXLOCAL]) + limiterror("too many local symbols (101)"); + addsym(name, type, symptr); + if (type->constructor == FUNCTION) + symptr->storage = GLOBAL; + else + symptr->storage = LOCAL; + symptr->level = level; + if (*hashptr != NULL) + { + symptr->next = *hashptr; + symptr->next->prev = &symptr->next; + } + *hashptr = symptr; + symptr->prev = hashptr; + return symptr; +} + +PUBLIC struct symstruct *addlorg(name, type) +char *name; +struct typestruct *type; +{ + if (level != GLBLEVEL) + return addloc(name, type); + return addglb(name, type); +} + +PUBLIC void addsym(name, type, symptr) +char *name; +struct typestruct *type; +register struct symstruct *symptr; +{ + if (type->constructor & (ARRAY | FUNCTION)) + symptr->indcount = 0; + else + symptr->indcount = 1; + symptr->flags = 0; + symptr->next = NULL; + symptr->type = type; + symptr->offset.offi = 0; + strcpy(symptr->name.namea, name); +} + +PUBLIC struct symstruct *constsym(longconst) +value_t longconst; +{ + register struct symstruct *symptr; + + symptr = exprsym(&constemplate); + symptr->offset.offv = longconst; + return symptr; +} + +PUBLIC void delsym(symptr) +register struct symstruct *symptr; +{ + if ((*(symptr->prev) = symptr->next) != NULL) + symptr->next->prev = symptr->prev; +} + +/* dumpglbs() - define locations of globals and reserve space for them */ + +PUBLIC void dumpglbs() +{ + int i; + register struct symstruct *symptr; + register struct typestruct *type; + +#ifdef TS +extern char *brksize; +struct ts +{ + char *what; + uvalue_t *where; +}; +static struct ts ts[] = +{ + "ts_n_newtypelist ", &ts_n_newtypelist, + "ts_s_newtypelist ", &ts_s_newtypelist, + "ts_n_filename_term ", &ts_n_filename_term, + "ts_s_filename_term ", &ts_s_filename_term, + "ts_n_filename ", &ts_n_filename, + "ts_s_filename ", &ts_s_filename, + "ts_s_filename_tot ", &ts_s_filename_tot, + "ts_n_pathname ", &ts_n_pathname, + "ts_s_pathname ", &ts_s_pathname, + "ts_s_pathname_tot ", &ts_s_pathname_tot, + "ts_n_inputbuf ", &ts_n_inputbuf, + "ts_s_inputbuf ", &ts_s_inputbuf, + "ts_s_inputbuf_tot ", &ts_s_inputbuf_tot, + "ts_n_includelist ", &ts_n_includelist, + "ts_s_includelist ", &ts_s_includelist, + "ts_s_outputbuf ", &ts_s_outputbuf, + "ts_n_macstring_ident ", &ts_n_macstring_ident, + "ts_n_macstring_ordinary ", &ts_n_macstring_ordinary, + "ts_n_macstring_param ", &ts_n_macstring_param, + "ts_n_macstring_quoted ", &ts_n_macstring_quoted, + "ts_n_macstring_term ", &ts_n_macstring_term, + "ts_s_macstring ", &ts_s_macstring, + "ts_n_defines ", &ts_n_defines, + "ts_s_defines ", &ts_s_defines, + "ts_n_macparam ", &ts_n_macparam, + "ts_s_macparam ", &ts_s_macparam, + "ts_s_macparam_tot ", &ts_s_macparam_tot, + "ts_n_macparam_string_ordinary ", &ts_n_macparam_string_ordinary, + "ts_n_macparam_string_quoted ", &ts_n_macparam_string_quoted, + "ts_n_macparam_string_term ", &ts_n_macparam_string_term, + "ts_s_macparam_string ", &ts_s_macparam_string, + "ts_s_macparam_string_tot ", &ts_s_macparam_string_tot, + "ts_s_macparam_string_alloced ", &ts_s_macparam_string_alloced, + "ts_s_macparam_string_alloced_tot ", &ts_s_macparam_string_alloced_tot, + "ts_s_fakeline ", &ts_s_fakeline, + "ts_s_fakeline_tot ", &ts_s_fakeline_tot, + "ts_n_string ", &ts_n_string, + "ts_n_case ", &ts_n_case, + "ts_n_case_realloc ", &ts_n_case_realloc, + "ts_s_case ", &ts_s_case, + "ts_s_case_tot ", &ts_s_case_tot, + "ts_n_structname ", &ts_n_structname, + "ts_s_structname ", &ts_s_structname, + "ts_n_type ", &ts_n_type, + "ts_s_type ", &ts_s_type, + "ts_n_global ", &ts_n_global, + "ts_size_global ", &ts_size_global, + "ts_n_holdstr ", &ts_n_holdstr, + "ts_size_holdstr ", &ts_size_holdstr, + "ts_n_growobj ", &ts_n_growobj, + "ts_size_growobj_wasted ", &ts_size_growobj_wasted, + "ts_n_growheap ", &ts_n_growheap, + "ts_s_growheap ", &ts_s_growheap, +}; +struct ts *tp; + +for (tp = &ts[0]; tp < &ts[sizeof ts / sizeof ts[0]]; ++tp) +{ + comment(); + outstr(tp->what); + outstr(""); + outuvalue(*tp->where); + outnl(); +} +comment(); +outstr("brksize "); +outhex((uvalue_t) brksize); +outnl(); +#endif + +#ifndef DIRECTPAGE + bssseg(); +#endif + for (i = 0; i < HASHTABSIZE; ++i) + for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next) + if (symptr->storage == GLOBAL && !(symptr->flags & EXTERNAL) + && *symptr->name.namea >= 'A' && symptr->flags <= MAXDUMPFLAG + /* Don't access type unless flags <= MAXDUMPFLAG, because + * type is punned to a symbol pointer for the label chain + * and might be null. + */ + && symptr->type->constructor != FUNCTION) + { +#ifdef DIRECTPAGE + if (symptr->flags & DIRECTPAGE) + dpseg(); + else + dseg(); +#endif + type = symptr->type; + if (symptr->flags & STATIC) + lcommon(symptr->name.namea); + else + common(symptr->name.namea); + outnhex(type->typesize); + } + if (printf_fp) + globl("__xfpcvt"); + if (scanf_fp) + globl("__xfptvc"); +} + +/* dumplocs() - define offsets of current locals */ + +PUBLIC void dumplocs() +{ + register struct symstruct *symptr; + int i; + + for (i = 0; i < HASHTABSIZE; ++i) + for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next) + if (symptr->storage == LOCAL) + set(symptr->name.namea, symptr->offset.offi - sp); +} + +#ifdef HOLDSTRINGS + +/* dumpstrings() - dump held-up strings */ + +PUBLIC void dumpstrings() +{ + struct string *stringp; + + dseg(); + for (stringp = laststring; stringp != NULL; stringp = stringp->snext) + { + outnlabel(stringp->slabel); + defstr(stringp->sptr, stringp->stop, TRUE); + dataoffset += stringp->stop - stringp->sptr + 1; + } +} + +#endif + +PUBLIC struct symstruct *exprsym(symptr) +struct symstruct *symptr; +{ + register struct symstruct *newsymptr; + + newsymptr = exprptr++; + if (exprptr >= &exprsyms[MAXEXPR]) + limiterror("expression too complex (501 symbols)"); + *newsymptr = *symptr; + newsymptr->level = EXPRLEVEL; + newsymptr->name.namep = symptr->name.namea; + return newsymptr; +} + +PUBLIC struct symstruct *findlorg(name) +char *name; +{ + struct symstruct *symptr; + + symptr = *gethashptr(name); + while (symptr != NULL && (strcmp(symptr->name.namea, name) != 0 || + symptr->flags == STRUCTNAME)) + symptr = symptr->next; + return symptr; +} + +PUBLIC struct symstruct *findstruct(name) +char *name; +{ + struct symstruct *symptr; + + symptr = *gethashptr(name); + while (symptr != NULL && (symptr->flags != STRUCTNAME || + strcmp(symptr->name.namea, name) != 0)) + symptr = symptr->next; + return symptr; +} + +/* convert name to a hash table ptr */ + +PUBLIC struct symstruct **gethashptr(sname) +char *sname; +{ + register int hashval; + register char *rsname; + + hashval = 0; + rsname = sname; +#if 1 + while (*rsname) + hashval = hashval * 2 + *rsname++; +#else + hashval = rsname[0]; + if (rsname[1] != 0) + hashval = (rsname[2] << 2) ^ rsname[1] ^ (rsname[0] << 1); + else + hashval = rsname[0]; +#endif + return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1)); +} + +PRIVATE void heapcorrupterror() +{ + outofmemoryerror(" (heap corrupt - stack overflow?)"); +} + +#ifdef HOLDSTRINGS + +/* hold string for dumping at end, to avoid mixing it with other data */ + +PUBLIC label_t holdstr(sptr, stop) +char *sptr; +char *stop; +{ + register struct string *stringp; + + stringp = qmalloc(sizeof *stringp); +#ifdef TS +++ts_n_holdstr; +ts_size_holdstr += sizeof *stringp; +#endif + stringp->snext = laststring; + stringp->sptr = sptr; + stringp->stop = stop; + laststring = stringp; + return stringp->slabel = getlabel(); +} + +#endif /* HOLDSTRINGS */ + +PUBLIC void newlevel() +{ + if (*(unsigned *) chartop != MARKER) + heapcorrupterror(); + if (level >= MAXLEVEL) + limiterror("compound statements nested too deeply (126 levels)"); + else + ++level; +} + +PUBLIC void oldlevel() +{ + register struct symstruct *symptr; + + if (*(unsigned *) chartop != MARKER) + heapcorrupterror(); + if (level == 0) + bugerror("not in a compound statement"); + else + --level; + for (symptr = &locsyms[0]; symptr < locptr; + symptr = (struct symstruct *) + align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) + if (symptr->level > level) + delsym(symptr); +} + +PUBLIC void ourfree(ptr) +void *ptr; +{ + free(ptr); +} + +PUBLIC void *ourmalloc(nbytes) +unsigned nbytes; +{ + void *ptr; + + if ((ptr = malloc(nbytes)) == NULL) + outofmemoryerror(""); + return ptr; +} + +PUBLIC void outofmemoryerror(message) +char *message; +{ + error2error("compiler out of memory", message); + +#if defined(DEBUG) && 0 + { + unsigned size; + char *ptr; + + for (size = 0x1000; size != 0; --size) + if ((ptr = malloc(size)) != NULL) + { + outstr("found free memory at "); + outuvalue((uvalue_t) ptr); + outstr(" size "); + outuvalue((uvalue_t) size); + outnl(); + } + } +#endif + + finishup(); +} + +PUBLIC void *growobject(object, extra) +void *object; +unsigned extra; +{ + /* size_t */ unsigned oblength; + + /* It would be nice to realloc the previous memory if it can be left in + * the same place. Since a realloc that moves the memory can almost be + * relied on to mess up pointers before *obptr, and since malloc(extra) + * would be unlikely to produce memory adjoining chartop, it is not + * clear how to do this. + */ +#ifdef TS +ts_size_growobj_wasted += chartop - (char *) object; +#endif + oblength = (/* size_t */ unsigned) (charptr - (char *) object); + growheap(oblength + extra); +#ifdef TS +++ts_n_growobj; +#endif + memcpy(charptr, object, oblength); + object = charptr; + charptr += oblength; + return object; +} + +#define ALLOC_UNIT ((unsigned) 0x400) +#ifdef S_ALIGNMENT +#define ALLOC_OVERHEAD (S_ALIGNMENT - 1 + sizeof (unsigned)) +#else +#define ALLOC_OVERHEAD (sizeof (unsigned)) +#endif + +PUBLIC void growheap(size) +unsigned size; +{ + register char *newptr; + + if ((newptr = malloc(size += ALLOC_UNIT + ALLOC_OVERHEAD)) == NULL + && (newptr = malloc(size -= ALLOC_UNIT)) == NULL) + outofmemoryerror(""); +#ifdef TS +++ts_n_growheap; +ts_s_growheap += size; +#endif + charptr = newptr; + newptr = (char *) align(newptr + size - ALLOC_OVERHEAD); + chartop = newptr; + char1top = newptr - 1; + char3top = newptr - 3; + *(unsigned *) newptr = MARKER; +} + +PUBLIC void *qmalloc(size) +unsigned size; +{ + register char *ptr; + + if ((charptr = (char *) align(charptr)) + size > chartop) + growheap(size); + ptr = charptr; + charptr += size; + return ptr; +} + +PUBLIC void swapsym(sym1, sym2) +struct symstruct *sym1; +struct symstruct *sym2; +{ + struct symstruct swaptemp; + + swaptemp = *sym1; + *sym1 = *sym2; + *sym2 = swaptemp; +} + +PUBLIC void syminit() +{ + struct keywordstruct *kwptr; + struct typedatastruct *tdptr; + struct typestruct *type; + + exprptr = exprsyms; + locptr = locsyms; + for (tdptr = scaltypes; tdptr < scaltypes + NSCALTYPES; ++tdptr) + { + (*tdptr->tdtypeptr = type = newtype())->scalar = tdptr->tdscalar; + type->alignmask = ~((type->typesize = tdptr->tdsize) - 1) | + alignmask; + type->tname = tdptr->tdname; + if (tdptr->tdkeyscalar) + addkeyword(tdptr->tdname, TYPEDECL)->type = type; + } + for (kwptr = keywords; kwptr < keywords + NKEYWORDS; ++kwptr) + addkeyword(kwptr->kwname, kwptr->kwcode); + constemplate.type = itype; +} diff --git a/bcc-bruce/table.h b/bcc-bruce/table.h new file mode 100644 index 0000000..f9b2f38 --- /dev/null +++ b/bcc-bruce/table.h @@ -0,0 +1,71 @@ +/* table.h - table handler for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +EXTERN char *charptr; /* next free spot in catchall table */ +EXTERN char *chartop; /* spot after last in table */ +EXTERN char *char1top; /* last character spot in table */ +EXTERN char *char3top; /* third last character spot in table */ +EXTERN struct symstruct *exprptr; + /* next entry in expression symbol table */ +EXTERN struct symstruct *locptr; + /* next entry in local symbol table */ +extern struct symstruct locsyms[]; + /* local symbol table */ + +#define TS1 +#ifdef TS +uvalue_t ts_n_newtypelist; +uvalue_t ts_s_newtypelist; +uvalue_t ts_n_filename_term; +uvalue_t ts_s_filename_term; +uvalue_t ts_n_filename; +uvalue_t ts_s_filename; +uvalue_t ts_s_filename_tot; +uvalue_t ts_n_pathname; +uvalue_t ts_s_pathname; +uvalue_t ts_s_pathname_tot; +uvalue_t ts_n_inputbuf; +uvalue_t ts_s_inputbuf; +uvalue_t ts_s_inputbuf_tot; +uvalue_t ts_n_includelist; +uvalue_t ts_s_includelist; +uvalue_t ts_s_outputbuf; +uvalue_t ts_n_macstring_ident; +uvalue_t ts_n_macstring_ordinary; +uvalue_t ts_n_macstring_param; +uvalue_t ts_n_macstring_quoted; +uvalue_t ts_n_macstring_term; +uvalue_t ts_s_macstring; +uvalue_t ts_n_defines; +uvalue_t ts_s_defines; +uvalue_t ts_n_macparam; +uvalue_t ts_s_macparam; +uvalue_t ts_s_macparam_tot; +uvalue_t ts_n_macparam_string_ordinary; +uvalue_t ts_n_macparam_string_quoted; +uvalue_t ts_n_macparam_string_term; +uvalue_t ts_s_macparam_string; +uvalue_t ts_s_macparam_string_tot; +uvalue_t ts_s_macparam_string_alloced; +uvalue_t ts_s_macparam_string_alloced_tot; +uvalue_t ts_s_fakeline; +uvalue_t ts_s_fakeline_tot; +uvalue_t ts_n_string; +uvalue_t ts_n_case; +uvalue_t ts_n_case_realloc; +uvalue_t ts_s_case; +uvalue_t ts_s_case_tot; +uvalue_t ts_n_structname; +uvalue_t ts_s_structname; +uvalue_t ts_n_type; +uvalue_t ts_s_type; +uvalue_t ts_n_global; +uvalue_t ts_size_global; +uvalue_t ts_n_holdstr; +uvalue_t ts_size_holdstr; +uvalue_t ts_n_growobj; +uvalue_t ts_size_growobj_wasted; +uvalue_t ts_n_growheap; +uvalue_t ts_s_growheap; +#endif diff --git a/bcc-bruce/type.c b/bcc-bruce/type.c new file mode 100644 index 0000000..4852c9d --- /dev/null +++ b/bcc-bruce/type.c @@ -0,0 +1,203 @@ +/* type.c - type and storage-class routines for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "align.h" +#include "gencode.h" /* s.b. switches.h */ +#include "sc.h" +#include "scan.h" +#include "table.h" + +#undef EXTERN +#define EXTERN +#include "type.h" + +PUBLIC uoffset_t ctypesize = 1; +PUBLIC uoffset_t dtypesize = 8; +PUBLIC uoffset_t ftypesize = 0; +PUBLIC uoffset_t itypesize = 2; +PUBLIC uoffset_t ptypesize = 2; +PUBLIC uoffset_t stypesize = 2; + +PRIVATE char skey0; +PRIVATE char skey1; + +PUBLIC struct typestruct *addstruct(structname) +char *structname; +{ + unsigned namelength; + struct symstruct *symptr; + struct typestruct *structype; + + (structype = newtype())->constructor = STRUCTU; + structype->alignmask = ctype->alignmask; + if (++skey1 == 0) + { + ++skey1; /* must be nonzero or key string would end */ + ++skey0; /* will never reach 'A' to be an identifier */ + } + structype->structkey[0] = skey0; + structype->structkey[1] = skey1; + if (*structname != 0) + { + symptr = addlorg(structname, structype); + symptr->storage = 0; + symptr->flags = STRUCTNAME; + if (charptr + (namelength = strlen(structname)) >= chartop) + growheap(namelength + 1); +#ifdef TS +++ts_n_structname; +ts_s_structname += namelength + 1; +#endif + structype->tname = strcpy(charptr, structname); + charptr += namelength + 1; + } + return structype; +} + +PUBLIC struct typestruct *iscalartotype(scalar) +scalar_pt scalar; +{ + if (scalar & LONG) + { + if (scalar & UNSIGNED) + return ultype; + return ltype; + } + if (scalar & UNSIGNED) + return uitype; + return itype; +} + +PUBLIC struct typestruct *newtype() +{ + register struct typestruct *type; + + type = qmalloc(sizeof *type); +#ifdef TS +++ts_n_type; +ts_s_type += sizeof *type; +#endif + type->typesize = /* (uoffset_t) */ + type->scalar = /* (scalar_t) */ + type->constructor = /* (constr_t) */ + type->structkey[0] = 0; + type->nexttype = + type->prevtype = + type->sidetype = NULL; + type->listtype = NULL; + type->tname = ""; + return type; +} + +PUBLIC void outntypechar(type) +struct typestruct *type; +{ + outnbyte(*type->tname); +} + +PUBLIC struct typestruct *pointype(type) +struct typestruct *type; +{ + return prefix(POINTER, ptypesize, type); +} + +PUBLIC struct typestruct *prefix(constructor, size, type) +constr_pt constructor; +uoffset_t size; +struct typestruct *type; +{ + register struct typestruct *searchtype; + + for (searchtype = type->prevtype; searchtype != NULL; + searchtype = searchtype->sidetype) + if (searchtype->constructor == (constr_t) constructor && + searchtype->typesize == size) + return searchtype; + switch ((searchtype = newtype())->constructor = constructor) + { + case ARRAY: + searchtype->alignmask = type->alignmask; + break; + case FUNCTION: + searchtype->alignmask = ~(uoffset_t) 0; + break; + case POINTER: + searchtype->alignmask = ~(ptypesize - 1) | alignmask; + break; + case STRUCTU: + bugerror("prefixing structure/union"); + searchtype->alignmask = alignmask; + break; + } + searchtype->typesize = size; + searchtype->nexttype = type; + searchtype->sidetype = type->prevtype; + return type->prevtype = searchtype; +} + +PUBLIC struct typestruct *promote(type) +struct typestruct *type; +{ + scalar_t scalar; + + if ((scalar = type->scalar) & (CHAR | SHORT)) + { + if (scalar & UNSIGNED) + return uitype; + return itype; + } + if (scalar & FLOAT) + return dtype; + if (type->constructor & ARRAY) + return pointype(type->nexttype); + if (type->constructor & FUNCTION) + return pointype(type); + return type; +} + +PUBLIC struct typestruct *tounsigned(type) +struct typestruct *type; +{ + switch (type->scalar & ~(UNSIGNED | DLONG)) + { + case CHAR: + return uctype; + case SHORT: + return ustype; + case INT: + return uitype; + case LONG: + return ultype; + default: + error("unsigned only applies to integral types"); + return type; + } +} + +PUBLIC void typeinit() +{ +#ifdef I8088 + if (i386_32) + { + uitype->typesize = + itype->typesize = + ptypesize = + itypesize = 4; + dtype->alignmask = + fltype->alignmask = + uitype->alignmask = + ltype->alignmask = + ultype->alignmask = + itype->alignmask = ~(uoffset_t) (4 - 1); + ltype->scalar = LONG; /* not DLONG */ + ultype->scalar = UNSIGNED | LONG; + } +#endif + fitype = prefix(FUNCTION, ftypesize, itype); + pctype = pointype(ctype); + skey0 = 1; + vtype->constructor = VOID; +} diff --git a/bcc-bruce/type.h b/bcc-bruce/type.h new file mode 100644 index 0000000..c451283 --- /dev/null +++ b/bcc-bruce/type.h @@ -0,0 +1,98 @@ +/* type.h - types for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* + A type is essentially a "constructor", a size, and a list of pointers + leading to a scalar type. + The type constructors are codes for the scalar types and (), [], *, + struct and union. + The scalar types are char, short, int, long, float and double. + The type lists are triply linked. + + Part of the type structure might look like + + int (int) + = + func <-------> int (int ()) + | = + --> ptr <--> int (int *) + + (the exact structure depends on the order of declarations). + This layout results from the pre-declared (int) and (int ()) followed by + a declaration using (int *). + The sideways link (from func to ptr here) allows all types leading to a + given type to be found. + This allows different declarations of (int *) to be recognised as the same. + Type equivalence is equality of type pointers. +*/ + +/* + flags for scalar types + up to 3 of the flags may be set (none for constructed types) + the 2nd and third flags can only be UNSIGNED or DLONG + UNSIGNED only applies to integral types + DLONG only applies to long and unsigned long types and says that these + are actually longer than an int +*/ + +#define CHAR 0x01 +#define SHORT 0x02 +#define INT 0x04 +#define LONG 0x08 +#define FLOAT 0x10 +#define DOUBLE 0x20 +#define UNSIGNED 0x40 +#define DLONG 0x80 + +#define ISCALAR (CHAR | SHORT | INT | LONG) +#define RSCALAR (FLOAT | DOUBLE) + +/* + flags for type constructor + at most 1 of the flags may be set (none for scalar types) + flags are used for fast testing for array/pointer +*/ + +#define ARRAY 1 +#define FUNCTION 2 +#define POINTER 4 +#define STRUCTU 8 +#define VOID 0x10 + +/* type sizes */ +/* default sizes and long and float sizes are hard-coded into type data */ + +extern uoffset_t ctypesize; +extern uoffset_t dtypesize; +extern uoffset_t ftypesize; +extern uoffset_t itypesize; +extern uoffset_t ptypesize; +extern uoffset_t stypesize; + +/* basic scalar types */ + +EXTERN struct typestruct *dtype; +EXTERN struct typestruct *fltype; +EXTERN struct typestruct *itype; +EXTERN struct typestruct *ltype; +EXTERN struct typestruct *sctype; +EXTERN struct typestruct *stype; +EXTERN struct typestruct *uctype; +EXTERN struct typestruct *uitype; +EXTERN struct typestruct *ultype; +EXTERN struct typestruct *ustype; +EXTERN struct typestruct *vtype; + +/* working type */ + +EXTERN struct typestruct *ctype; + +/* constructed types */ + +EXTERN struct typestruct *fitype; +EXTERN struct typestruct *pctype; + +/* return type of current function */ + +EXTERN struct typestruct *returntype; diff --git a/bcc-bruce/types.h b/bcc-bruce/types.h new file mode 100644 index 0000000..547637c --- /dev/null +++ b/bcc-bruce/types.h @@ -0,0 +1,206 @@ +/* types.h - type definitions for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +/* + source types big enough to handle target quantities + these have to be match the source compiler and target machine + this is impossible if the source long type is too small +*/ + +typedef unsigned char char_t; /* target char */ +typedef long value_t; /* target ints, longs and offsets */ +typedef unsigned long uvalue_t; /* target unsigned ints, longs and offsets */ + +#ifdef I8088 +typedef long offset_t; /* target machine offset */ +typedef unsigned long uoffset_t; /* target unsigned machine offset */ +#define outuvalue outhex +#define outvalue outshex +#endif +#ifdef MC6809 +typedef int offset_t; +typedef unsigned uoffset_t; +#endif + + +/* + storage class type must hold all the flags defined elsewhere + it must have a few more bits than the target has registers +*/ + +#ifdef I8088 +typedef unsigned store_pt; /* promoted store_t */ +typedef unsigned store_t; /* storage class flags */ +#endif +#ifdef MC6809 +# if __STDC__ +typedef int store_pt; +# else +typedef unsigned store_pt; +# endif +typedef unsigned char store_t; +#endif + + +/* + types for library routines +*/ + +typedef int fd_t; /* file descriptor */ + + +/* + basic scalar types - may be tuned to suit machine +*/ + +typedef int fastin_pt; /* promoted fastin_t */ + /* always an int - use to show that the */ + /* value may be accessed as a fastin_t */ +typedef char fastin_t; /* fast int - a small integer value */ + /* on some machines, chars can be accessed */ + /* more efficiently than ints for arithmetic */ + /* such as comparing and masking which */ + /* does not requiring promotion */ + /* change to int if chars are inefficient */ + /* or if char has < 8 bits */ +typedef int smalin_pt; /* promoted smalin_t */ +typedef char smalin_t; /* small int - a small integer value */ + /* on most machines, chars are stored in */ + /* less space than any other type */ + /* change to fastin_t if this is not true */ + /* or if char has < 8 bits */ + /* or if space is not a limiting factor */ +#if __STDC__ +typedef int smalu_pt; +#else +typedef unsigned smalu_pt; +#endif +typedef unsigned char smalu_t; + + +/* + derived scalar types + the types containing bit flags fit in an 8 bit smalin_t +*/ + +typedef fastin_pt bool_pt; /* promoted bool_t */ +typedef fastin_t bool_t; /* boolean: TRUE if nonzero */ +typedef fastin_pt ccode_pt; /* promoted ccode_t */ +typedef fastin_t ccode_t; /* condition code code */ +typedef smalu_pt constr_pt; /* promoted constr_t */ +typedef smalu_t constr_t; /* type constructor flags */ +typedef smalu_pt indn_pt; /* promoted indn_t */ +typedef smalu_t indn_t; /* storage indirection count */ +typedef unsigned label_t; /* label number */ +typedef smalu_t maclev_t; /* macro expansion level */ +typedef smalin_pt op_pt; /* promoted op_t */ +typedef smalin_t op_t; /* operator code */ +typedef smalu_t sc_t; /* storage class flags */ +typedef smalu_pt scalar_pt; /* promoted scalar_t */ +typedef smalu_t scalar_t; /* type scalar flags */ +typedef smalu_t scopelev_t; /* scope level */ +typedef fastin_pt sym_pt; /* promoted sym_t */ +typedef fastin_t sym_t; /* symbol code from scanner */ +typedef smalu_t weight_t; /* expression tree node weight */ + + +/* + derived structure types + the fields are ordered in a way that is most space-efficient + when smalin_t is char and smalu_t is unsigned char + the first element of the structures is the one most frequently accessed +*/ + +/* + expression table entry format +*/ + +struct nodestruct +{ + op_t tag; + weight_t weight; + smalu_t flags; + struct typestruct *nodetype; + union nodeunion + { + struct nodestruct *nodeptr; + struct symstruct *symptr; + } left; + struct nodestruct *right; +}; + +/* + symbol table entry format +*/ + +struct symstruct +{ + store_t storage; + indn_t indcount; + sc_t flags; + scopelev_t level; + struct symstruct *next; + struct symstruct **prev; + struct typestruct *type; + union + { + double *offd; /* value for double constants */ + offset_t offi; /* offset for register or global storage */ + label_t offlabel; /* label number for strings */ + char *offp; /* to string for macro definitions */ + sym_pt offsym; /* symbol code for keywords */ + value_t offv; /* value for integral constants */ + } + offset; + union + { + label_t label; /* label number for strings */ + char namea[1]; /* variable length array for declarations */ + char *namep; /* to constant storage for exprs */ + } + name; +}; + +/* + type table entry format +*/ + +struct typestruct +{ + scalar_t scalar; /* scalar type flags u d f l i s c */ + constr_t constructor; /* constructed type flags a f p s/u */ + char structkey[2]; /* unique prefix for member names */ + /* ranges from "\001\001" to "@\377" */ + /* avoiding nulls */ + uoffset_t alignmask; /* alignment mask, typesize - 1 for scalars */ + uoffset_t typesize; /* size of this type */ + char *tname; /* name of scalar type or constructor */ + struct typelist *listtype; /* list of member types */ + struct typestruct *nexttype; + /* next in list */ + struct typestruct *prevtype; + /* previous in list */ + struct typestruct *sidetype; + /* next in sideways list */ +}; + +/* + list of type structures +*/ + +struct typelist +{ + struct typelist *tlnext; + struct typestruct *tltype; +}; + + +/* + definitions to avoid passing raw NULLs to functions +*/ + +#define NULLNODE ((struct nodestruct *) NULL) +#define NULLTYPE ((struct typestruct *) NULL) + +#include "proto.h" diff --git a/bcc-linux16.patch b/bcc-linux16.patch new file mode 100644 index 0000000..6fe0ad2 --- /dev/null +++ b/bcc-linux16.patch @@ -0,0 +1,444 @@ +diff -Nurd bcc-bruce/COPYING bcc-linux16/COPYING +--- bcc-bruce/COPYING Thu Jan 1 01:00:00 1970 ++++ bcc-linux16/COPYING Sun Mar 26 10:39:11 1995 +@@ -0,0 +1,339 @@ ++ GNU GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1989, 1991 Free Software Foundation, Inc. ++ 675 Mass Ave, Cambridge, MA 02139, USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++License is intended to guarantee your freedom to share and change free ++software--to make sure the software is free for all its users. This ++General Public License applies to most of the Free Software ++Foundation's software and to any other program whose authors commit to ++using it. (Some other Free Software Foundation software is covered by ++the GNU Library General Public License instead.) You can apply it to ++your programs, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++this service if you wish), that you receive source code or can get it ++if you want it, that you can change the software or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if you ++distribute copies of the software, or if you modify it. ++ ++ For example, if you distribute copies of such a program, whether ++gratis or for a fee, you must give the recipients all the rights that ++you have. You must make sure that they, too, receive or can get the ++source code. And you must show them these terms so they know their ++rights. ++ ++ We protect your rights with two steps: (1) copyright the software, and ++(2) offer you this license which gives you legal permission to copy, ++distribute and/or modify the software. ++ ++ Also, for each author's protection and ours, we want to make certain ++that everyone understands that there is no warranty for this free ++software. If the software is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original, so ++that any problems introduced by others will not reflect on the original ++authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that redistributors of a free ++program will individually obtain patent licenses, in effect making the ++program proprietary. To prevent this, we have made it clear that any ++patent must be licensed for everyone's free use or not licensed at all. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. ++ ++ GNU GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License applies to any program or other work which contains ++a notice placed by the copyright holder saying it may be distributed ++under the terms of this General Public License. The "Program", below, ++refers to any such program or work, and a "work based on the Program" ++means either the Program or any derivative work under copyright law: ++that is to say, a work containing the Program or a portion of it, ++either verbatim or with modifications and/or translated into another ++language. (Hereinafter, translation is included without limitation in ++the term "modification".) Each licensee is addressed as "you". ++ ++Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running the Program is not restricted, and the output from the Program ++is covered only if its contents constitute a work based on the ++Program (independent of having been made by running the Program). ++Whether that is true depends on what the Program does. ++ ++ 1. You may copy and distribute verbatim copies of the Program's ++source code as you receive it, in any medium, provided that you ++conspicuously and appropriately publish on each copy an appropriate ++copyright notice and disclaimer of warranty; keep intact all the ++notices that refer to this License and to the absence of any warranty; ++and give any other recipients of the Program a copy of this License ++along with the Program. ++ ++You may charge a fee for the physical act of transferring a copy, and ++you may at your option offer warranty protection in exchange for a fee. ++ ++ 2. You may modify your copy or copies of the Program or any portion ++of it, thus forming a work based on the Program, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) You must cause the modified files to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ b) You must cause any work that you distribute or publish, that in ++ whole or in part contains or is derived from the Program or any ++ part thereof, to be licensed as a whole at no charge to all third ++ parties under the terms of this License. ++ ++ c) If the modified program normally reads commands interactively ++ when run, you must cause it, when started running for such ++ interactive use in the most ordinary way, to print or display an ++ announcement including an appropriate copyright notice and a ++ notice that there is no warranty (or else, saying that you provide ++ a warranty) and that users may redistribute the program under ++ these conditions, and telling the user how to view a copy of this ++ License. (Exception: if the Program itself is interactive but ++ does not normally print such an announcement, your work based on ++ the Program is not required to print an announcement.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Program, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Program, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Program. ++ ++In addition, mere aggregation of another work not based on the Program ++with the Program (or with a work based on the Program) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may copy and distribute the Program (or a work based on it, ++under Section 2) in object code or executable form under the terms of ++Sections 1 and 2 above provided that you also do one of the following: ++ ++ a) Accompany it with the complete corresponding machine-readable ++ source code, which must be distributed under the terms of Sections ++ 1 and 2 above on a medium customarily used for software interchange; or, ++ ++ b) Accompany it with a written offer, valid for at least three ++ years, to give any third party, for a charge no more than your ++ cost of physically performing source distribution, a complete ++ machine-readable copy of the corresponding source code, to be ++ distributed under the terms of Sections 1 and 2 above on a medium ++ customarily used for software interchange; or, ++ ++ c) Accompany it with the information you received as to the offer ++ to distribute corresponding source code. (This alternative is ++ allowed only for noncommercial distribution and only if you ++ received the program in object code or executable form with such ++ an offer, in accord with Subsection b above.) ++ ++The source code for a work means the preferred form of the work for ++making modifications to it. For an executable work, complete source ++code means all the source code for all modules it contains, plus any ++associated interface definition files, plus the scripts used to ++control compilation and installation of the executable. However, as a ++special exception, the source code distributed need not include ++anything that is normally distributed (in either source or binary ++form) with the major components (compiler, kernel, and so on) of the ++operating system on which the executable runs, unless that component ++itself accompanies the executable. ++ ++If distribution of executable or object code is made by offering ++access to copy from a designated place, then offering equivalent ++access to copy the source code from the same place counts as ++distribution of the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 4. You may not copy, modify, sublicense, or distribute the Program ++except as expressly provided under this License. Any attempt ++otherwise to copy, modify, sublicense or distribute the Program is ++void, and will automatically terminate your rights under this License. ++However, parties who have received copies, or rights, from you under ++this License will not have their licenses terminated so long as such ++parties remain in full compliance. ++ ++ 5. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Program or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Program (or any work based on the ++Program), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Program or works based on it. ++ ++ 6. Each time you redistribute the Program (or any work based on the ++Program), the recipient automatically receives a license from the ++original licensor to copy, distribute or modify the Program subject to ++these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties to ++this License. ++ ++ 7. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Program at all. For example, if a patent ++license would not permit royalty-free redistribution of the Program by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Program. ++ ++If any portion of this section is held invalid or unenforceable under ++any particular circumstance, the balance of the section is intended to ++apply and the section as a whole is intended to apply in other ++circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system, which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 8. If the distribution and/or use of the Program is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Program under this License ++may add an explicit geographical distribution limitation excluding ++those countries, so that distribution is permitted only in or among ++countries not thus excluded. In such case, this License incorporates ++the limitation as if written in the body of this License. ++ ++ 9. The Free Software Foundation may publish revised and/or new versions ++of the General Public License from time to time. Such new versions will ++be similar in spirit to the present version, but may differ in detail to ++address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Program ++specifies a version number of this License which applies to it and "any ++later version", you have the option of following the terms and conditions ++either of that version or of any later version published by the Free ++Software Foundation. If the Program does not specify a version number of ++this License, you may choose any version ever published by the Free Software ++Foundation. ++ ++ 10. If you wish to incorporate parts of the Program into other free ++programs whose distribution conditions are different, write to the author ++to ask for permission. For software which is copyrighted by the Free ++Software Foundation, write to the Free Software Foundation; we sometimes ++make exceptions for this. Our decision will be guided by the two goals ++of preserving the free status of all derivatives of our free software and ++of promoting the sharing and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED ++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS ++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE ++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ++REPAIR OR CORRECTION. ++ ++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING ++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR ++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, ++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING ++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED ++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY ++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER ++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ Appendix: How to Apply These Terms to Your New Programs ++ ++ If you develop a new program, and you want it to be of the greatest ++possible use to the public, the best way to achieve this is to make it ++free software which everyone can redistribute and change under these terms. ++ ++ To do so, attach the following notices to the program. It is safest ++to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least ++the "copyright" line and a pointer to where the full notice is found. ++ ++ <one line to give the program's name and a brief idea of what it does.> ++ Copyright (C) 19yy <name of author> ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++If the program is interactive, make it output a short notice like this ++when it starts in an interactive mode: ++ ++ Gnomovision version 69, Copyright (C) 19yy name of author ++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. ++ This is free software, and you are welcome to redistribute it ++ under certain conditions; type `show c' for details. ++ ++The hypothetical commands `show w' and `show c' should show the appropriate ++parts of the General Public License. Of course, the commands you use may ++be called something other than `show w' and `show c'; they could even be ++mouse-clicks or menu items--whatever suits your program. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the program, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program ++ `Gnomovision' (which makes passes at compilers) written by James Hacker. ++ ++ <signature of Ty Coon>, 1 April 1989 ++ Ty Coon, President of Vice ++ ++This General Public License does not permit incorporating your program into ++proprietary programs. If your program is a subroutine library, you may ++consider it more useful to permit linking proprietary applications with the ++library. If this is what you want to do, use the GNU Library General ++Public License instead of this License. +diff -Nurd bcc-bruce/Makefile bcc-linux16/Makefile +--- bcc-bruce/Makefile Tue Jul 25 19:27:02 1995 ++++ bcc-linux16/Makefile Mon Nov 6 23:06:11 1995 +@@ -1,27 +1,23 @@ +-# +-# Build bcc +-# +- +-all: bcc bcc-cc1 +- +-CFLAGS = -DLOCALPREFIX="\"/usr/local\"" -O2 ++CFLAGS =-O2 ++LDFLAGS = ++CC = gcc + +-SRCS =assign.c declare.c gencode.c label.c preserve.c type.c \ +- bcc-cc1.c express.c genloads.c loadexp.c scan.c \ +- exptree.c glogcode.c longop.c softop.c codefrag.c \ +- floatop.c hardop.c output.c state.c debug.c function.c \ +- input.c preproc.c table.c ++bcc: bcc.c ++ $(CC) $(CFLAGS) $(LDFLAGS) $@.c -o $@ + +-OBJS =assign.o declare.o gencode.o label.o preserve.o type.o \ +- bcc-cc1.o express.o genloads.o loadexp.o scan.o \ +- exptree.o glogcode.o longop.o softop.o codefrag.o \ +- floatop.o hardop.o output.o state.o debug.o function.o \ +- input.o preproc.o table.o ++bcc09: bcc.c ++ $(CC) -DMC6809 $(CFLAGS) $(LDFLAGS) bcc.c -o $@ + ++ccc: bcc.c ++ $(CC) -DCCC $(CFLAGS) $(LDFLAGS) bcc.c -o $@ + +-bcc: bcc.c +- $(CC) $(CFLAGS) -o bcc bcc.c ++SOURCES = bcc-cc1.c codefrag.c debug.c declare.c express.c exptree.c floatop.c \ ++ function.c gencode.c genloads.c glogcode.c hardop.c input.c label.c \ ++ loadexp.c longop.c output.c preproc.c preserve.c scan.c softop.c \ ++ state.c table.c type.c assign.c + +-bcc-cc1: $(OBJS) +- $(CC) $(CFLAGS) -o bcc-cc1 $(OBJS) ++bcc-cc1: $(SOURCES) ++ $(CC) $(CFLAGS) $(LDFLAGS) $(SOURCES) -o bcc-cc1 + ++clean: ++ rm -f bcc bcc09 ccc +diff -Nurd bcc-bruce/README bcc-linux16/README +--- bcc-bruce/README Thu Jan 1 01:00:00 1970 ++++ bcc-linux16/README Mon Nov 6 23:07:46 1995 +@@ -0,0 +1,8 @@ ++ This is a source distribution of bcc designed for use with as86 and ++ld86 (part of the bin86 package). I have altered the Makefile so that bcc-cc1 ++can be made from the Makefile (it does not check for dependancies, so it can ++be slow. bcc and bcc-cc1 are both needed to build Linux/16. ++ ++ - Chad Page ++ page0588@sundance.sjsu.edu ++ +diff -Nurd bcc-bruce/VERSION bcc-linux16/VERSION +--- bcc-bruce/VERSION Thu Jan 1 01:00:00 1970 ++++ bcc-linux16/VERSION Sun Mar 26 10:48:18 1995 +@@ -0,0 +1 @@ ++1995 Mar 12 10:29 UTC +Binary files bcc-bruce/bcc and bcc-linux16/bcc differ +Binary files bcc-bruce/bcc-cc1 and bcc-linux16/bcc-cc1 differ +diff -Nurd bcc-bruce/bcc.c bcc-linux16/bcc.c +--- bcc-bruce/bcc.c Tue Jul 25 19:18:16 1995 ++++ bcc-linux16/bcc.c Mon Nov 6 23:05:59 1995 +@@ -32,15 +32,15 @@ + #define BCC86 + #define CC1 "bcc-cc1" + #define CC1_MINUS_O_BROKEN FALSE +-#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */ ++#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */ + #define CPPFLAGS "-E" +-#define CRT0 "crt0.o" ++#define CRT0 "ncrtso.o" + #define GCC "gcc" + #define LD "ld86" +-#define STANDARD_CRT0_0_PREFIX LOCALPREFIX "/lib/bcc/i86/" +-#define STANDARD_CRT0_3_PREFIX LOCALPREFIX "/lib/bcc/i386/" +-#define STANDARD_EXEC_PREFIX LOCALPREFIX "/lib/bcc/" +-#define STANDARD_EXEC_PREFIX_2 LOCALPREFIX "/bin/" ++#define STANDARD_CRT0_0_PREFIX "/usr/home/minix/lib/" ++#define STANDARD_CRT0_3_PREFIX "/usr/home/minix/lib/" ++#define STANDARD_EXEC_PREFIX "/usr/bin/" ++#define STANDARD_EXEC_PREFIX_2 "/usr/bin/" + + #ifdef CCC + #undef BCC86 +@@ -207,7 +207,7 @@ + addarg(&ldargs, "-i"); + #endif + #ifdef BAS86 +- addarg(&ldrargs, "-r"); ++ addarg(&ldrargs, "-r -0"); + #endif + + /* Pass 1 over argv to gather compile options. */ diff --git a/bin86-0.3/ChangeLog b/bin86-0.3/ChangeLog new file mode 100644 index 0000000..1e6d936 --- /dev/null +++ b/bin86-0.3/ChangeLog @@ -0,0 +1,67 @@ +Tue May 16 22:01:05 1995 H.J. Lu (hjl@nynexst.com) + + * version 0.3 is released. + + * Makefile: fix a few typos. + + * as/const.h: include "endian.h". + (LOW_BYTE): check the byte order. + + * Makefile (endian.h): new target. + (const.h): depend on endian.h. + + * as/det_endian.c: new from glibc. + +Sat Mar 18 16:39:19 1995 Francois-Rene Rideau (rideau@clipper.ens.fr) + + * as/pops.c (doif): support nested conditionals. + +Mon Nov 21 22:48:26 1994 H.J. Lu (hlu@nighthawk) + + * version 0.2 is released. + + * Makefile (MFLAGS): new. add BINDIR and CC. + +Fri Nov 18 22:25:24 1994 Package Maintainer (opt@calum.csclub.uwaterloo.ca) + + * ./as/Makefile: + * ./as/const.h: + * ./as/proto.h: + * ./as/readsrc.c: + * ./as/type.h: + * ./ld/Makefile: + * ./ld/align.h: + * ./ld/config.h: + * ./ld/type.h: + * ./ld/typeconv.c: remove endian dependency. + +Thu Mar 3 15:12:23 1994 H.J. Lu (hlu@nighthawk) + + * version 0.1 is released. + + * Makefile: new. + + * a.out.h/bsd-a.out.h (struct exec): use short form if + __linux__ is defined. + + * as/Makefile: minor changes. + (CLFAGS): add -I../a.out.h. + + * ld/Makefile: minor changes. + (CLFAGS): add -I../a.out.h. + + * ld/io.c (MY_STAT_H): don't define it if __linux__ is + defined. + + * ld/ld.c (flag['z']): initialized to 0 if __linux__ is + defined. + + * ld/obj.h (roundup): + * ld/writebin.c (roundup): + ld/readobj.c (roundup): change that to ld_roundup to avoid the + conflict with the system's roundup. + + * ld/writebin.c: cleanup for the latest Linux C library. + (FILEHEADERLENGTH): change to sizeof (struct exec). + don't write a_trsize and its friends. + diff --git a/bin86-0.3/Makefile b/bin86-0.3/Makefile new file mode 100644 index 0000000..62a0730 --- /dev/null +++ b/bin86-0.3/Makefile @@ -0,0 +1,36 @@ +CC=gcc +CFLAGS=-O6 -fomit-frame-pointer +LDFLAGS= +# Where to get strtoul ()? +#LIBS=-liberty +DIRS=ld as + +BINDIR=/usr/gnu/i486-linux/bin +AS86=i486-linux-ld86 +LD86=i486-linux-ld86 + +BINDIR=/usr/bin +AS86=as86 +LD86=ld86 + +STRIP=strip + +MFLAGS= "LIBS=$(LIBS)" \ + "CFLAGS=$(CFLAGS)" \ + "LDFLAGS=$(LDFLAGS)" \ + "CC=$(CC)" + +all: + for d in $(DIRS); do \ + (cd $$d; $(MAKE) $(MFLAGS) $@;); \ + done + +install: all + cp as/as86 $(BINDIR)/$(AS86) + cp ld/ld86 $(BINDIR)/$(LD86) + $(STRIP) $(BINDIR)/$(AS86) $(BINDIR)/$(LD86) + +depend clean clobber: + for d in $(DIRS); do \ + (cd $$d; $(MAKE) $(MFLAGS) $@;); \ + done diff --git a/bin86-0.3/README b/bin86-0.3/README new file mode 100644 index 0000000..f91a9dc --- /dev/null +++ b/bin86-0.3/README @@ -0,0 +1,79 @@ +To build this real mode as/ld for x86, just edit Makefile and then +do + +make install + +It is only tested under SunOS 4.1.3 and Linux. + +H.J. Lu +hjl@nynexst.com +11/21/94 +------ +We seem to have cross bin86 for Solaris working. The most important +changes involve alignment (it needs to be on) and byte ordering. +Some of the patches just eliminate compiler warnings (conversion of +pointer to integer without a cast, etc.) and some (in the Makefiles) +reflect the local setup, and can probably be ignored (the change to $BINDIR, +for example). + + - Ian (iagoldbe@csclub.uwaterloo.ca) + +---- +I modified it for the latest Linux C library 4.5.21 and released it as +bin86 0.1. It is only tested for building the Linux kernel and is not +intended for any other purposes. To build it under Linux, just type + +make all +make install + +It is not tested for cross-compiling. If you have any patches for +cross-compiling, please send them to me. + +Thanks. + + +H.J. Lu +hjl@nynexst.com +03/03/94 +------------- +This is the as86 and ld86 distribution written by Bruce Evans. It's +copyright Bruce Evans, all rights reserved although you may use and copy +it for your personal use. It's a complete 8086 assembler and loader +which can make 32-bit code for the 386+ processors (under linux it's +used only to create the 16-bit bootsector and setup binaries). The +syntax is not compatible with the GNU assembler, but closer to intel +syntax ("wrong" order of operands etc). + +Hints for compiling: + + - you'll need the a.out.h-files from the a.out.h directory for the +linker. These aren't really part of the distribution, but I included +them for ease of setup (in case you need to crosscompile etc). Do a + cp a.out.h/* ld/ +or similar before compiling the linker. + + - the assembler needs the typeconv.o file produced by the linker +compilation. So compile the linker first, and then do a + cp ld/typeconv.o as/ +before making the assembler. + +This distribution also contains some test-files etc that aren't actually +needed, but as they also give some idea of the assembler syntax, I left +them in. The directories are as follows: + + as - the assembler sources (minus typeconv.c) + ld - linker sources + bcc - bruce evans' cc frontend sources (the actual compiler isn't + included). + bccfp - assembly floating point routines written by bruce evans. Note + that these use integer register returns, and won't work with the + linux libraries. They can be used as examples of as86 code. + a.out.h - header files for crosscompilation. + +Note that I am NOT the author of this package, but I'll forward any +comments to bruce evans and I'll try to answer any questions about the +assembler/linker I can. I just made it available as bde doesn't have +ftp capability right now. Bruce Evans does have mail as +<bde@runx.oz.au>. + + Linus Torvalds diff --git a/bin86-0.3/a.out.h/a.out.gnu.h b/bin86-0.3/a.out.h/a.out.gnu.h new file mode 100644 index 0000000..bf6d4d9 --- /dev/null +++ b/bin86-0.3/a.out.h/a.out.gnu.h @@ -0,0 +1,276 @@ +#ifndef __A_OUT_GNU_H__ +#define __A_OUT_GNU_H__ + +#if defined(sequent) && defined(i386) +#define a_magic a_info +#include <a.out.h> +#undef a_magic +#define __STRUCT_EXEC_OVERRIDE__ +#define N_NLIST_DECLARED +#define N_RELOCATION_INFO_DECLARED +#endif + +#define __GNU_EXEC_MACROS__ + +#ifndef __STRUCT_EXEC_OVERRIDE__ + +struct exec +{ + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned long a_text; /* length of text, in bytes */ + unsigned long a_data; /* length of data, in bytes */ + unsigned long a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned long a_syms; /* length of symbol table data in file, in bytes */ + unsigned long a_entry; /* start address */ + unsigned long a_trsize; /* length of relocation info for text, in bytes */ + unsigned long a_drsize; /* length of relocation info for data, in bytes */ +}; + +#endif /* __STRUCT_EXEC_OVERRIDE__ */ + +/* these go in the N_MACHTYPE field */ +enum machine_type { +#if defined (M_OLDSUN2) + M__OLDSUN2 = M_OLDSUN2, +#else + M_OLDSUN2 = 0, +#endif +#if defined (M_68010) + M__68010 = M_68010, +#else + M_68010 = 1, +#endif +#if defined (M_68020) + M__68020 = M_68020, +#else + M_68020 = 2, +#endif +#if defined (M_SPARC) + M__SPARC = M_SPARC, +#else + M_SPARC = 3, +#endif + /* skip a bunch so we don't run into any of sun's numbers */ + M_386 = 100, +}; + +#if !defined (N_MAGIC) +#define N_MAGIC(exec) ((exec).a_info & 0xffff) +#endif +#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) +#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff) +#define N_SET_INFO(exec, magic, type, flags) \ + ((exec).a_info = ((magic) & 0xffff) \ + | (((int)(type) & 0xff) << 16) \ + | (((flags) & 0xff) << 24)) +#define N_SET_MAGIC(exec, magic) \ + ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) + +#define N_SET_MACHTYPE(exec, machtype) \ + ((exec).a_info = \ + ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16)) + +#define N_SET_FLAGS(exec, flags) \ + ((exec).a_info = \ + ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24)) + +#ifndef OMAGIC +/* Code indicating object file or impure executable. */ +#define OMAGIC 0407 +/* Code indicating pure executable. */ +#define NMAGIC 0410 +/* Code indicating demand-paged executable. */ +#define ZMAGIC 0413 +#endif /* not OMAGIC */ + +#if !defined (N_BADMAG) +#define N_BADMAG(x) \ + (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ + && N_MAGIC(x) != ZMAGIC) +#endif + +#define _N_BADMAG(x) \ + (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ + && N_MAGIC(x) != ZMAGIC) + +#define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec)) + +#if !defined (N_TXTOFF) +#define N_TXTOFF(x) \ + (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec)) +#endif + +#if !defined (N_DATOFF) +#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text) +#endif + +#if !defined (N_TRELOFF) +#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data) +#endif + +#if !defined (N_DRELOFF) +#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize) +#endif + +#if !defined (N_SYMOFF) +#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize) +#endif + +#if !defined (N_STROFF) +#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms) +#endif + +/* Address of text segment in memory after it is loaded. */ +#if !defined (N_TXTADDR) +#define N_TXTADDR(x) 0 +#endif + +/* Address of data segment in memory after it is loaded. + Note that it is up to you to define SEGMENT_SIZE + on machines not listed here. */ +#if defined(vax) || defined(hp300) || defined(pyr) +#define SEGMENT_SIZE PAGE_SIZE +#endif +#ifdef hp300 +#define PAGE_SIZE 4096 +#endif +#ifdef sony +#define SEGMENT_SIZE 0x2000 +#endif /* Sony. */ +#ifdef is68k +#define SEGMENT_SIZE 0x20000 +#endif +#if defined(m68k) && defined(PORTAR) +#define PAGE_SIZE 0x400 +#define SEGMENT_SIZE PAGE_SIZE +#endif + +#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1)) + +#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text) + +#ifndef N_DATADDR +#define N_DATADDR(x) \ + (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \ + : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) +#endif + +/* Address of bss segment in memory after it is loaded. */ +#if !defined (N_BSSADDR) +#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) +#endif + +#if !defined (N_NLIST_DECLARED) +struct nlist { + union { + char *n_name; + struct nlist *n_next; + long n_strx; + } n_un; + unsigned char n_type; + char n_other; + short n_desc; + unsigned long n_value; +}; +#endif /* no N_NLIST_DECLARED. */ + +#if !defined (N_UNDF) +#define N_UNDF 0 +#endif +#if !defined (N_ABS) +#define N_ABS 2 +#endif +#if !defined (N_TEXT) +#define N_TEXT 4 +#endif +#if !defined (N_DATA) +#define N_DATA 6 +#endif +#if !defined (N_BSS) +#define N_BSS 8 +#endif +#if !defined (N_COMM) +#define N_COMM 18 +#endif +#if !defined (N_FN) +#define N_FN 15 +#endif + +#if !defined (N_EXT) +#define N_EXT 1 +#endif +#if !defined (N_TYPE) +#define N_TYPE 036 +#endif +#if !defined (N_STAB) +#define N_STAB 0340 +#endif + +/* The following type indicates the definition of a symbol as being + an indirect reference to another symbol. The other symbol + appears as an undefined reference, immediately following this symbol. + + Indirection is asymmetrical. The other symbol's value will be used + to satisfy requests for the indirect symbol, but not vice versa. + If the other symbol does not have a definition, libraries will + be searched to find a definition. */ +#define N_INDR 0xa + +/* The following symbols refer to set elements. + All the N_SET[ATDB] symbols with the same name form one set. + Space is allocated for the set in the text section, and each set + element's value is stored into one word of the space. + The first word of the space is the length of the set (number of elements). + + The address of the set is made into an N_SETV symbol + whose name is the same as the name of the set. + This symbol acts like a N_DATA global symbol + in that it can satisfy undefined external references. */ + +/* These appear as input to LD, in a .o file. */ +#define N_SETA 0x14 /* Absolute set element symbol */ +#define N_SETT 0x16 /* Text set element symbol */ +#define N_SETD 0x18 /* Data set element symbol */ +#define N_SETB 0x1A /* Bss set element symbol */ + +/* This is output from LD. */ +#define N_SETV 0x1C /* Pointer to set vector in data area. */ + +#if !defined (N_RELOCATION_INFO_DECLARED) +/* This structure describes a single relocation to be performed. + The text-relocation section of the file is a vector of these structures, + all of which apply to the text section. + Likewise, the data-relocation section applies to the data section. */ + +struct relocation_info +{ + /* Address (within segment) to be relocated. */ + unsigned long r_address; +#if 0 + /* The meaning of r_symbolnum depends on r_extern. */ + unsigned int r_symbolnum:24; + /* Nonzero means value is a pc-relative offset + and it should be relocated for changes in its own address + as well as for changes in the symbol or section specified. */ + unsigned int r_pcrel:1; + /* Length (as exponent of 2) of the field to be relocated. + Thus, a value of 2 indicates 1<<2 bytes. */ + unsigned int r_length:2; + /* 1 => relocate with value of symbol. + r_symbolnum is the index of the symbol + in file's the symbol table. + 0 => relocate with the address of a segment. + r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS + (the N_EXT bit may be set also, but signifies nothing). */ + unsigned int r_extern:1; + /* Four bits that aren't used, but when writing an object file + it is desirable to clear them. */ + unsigned int r_pad:4; +#else + unsigned long foo; +#endif +}; +#endif /* no N_RELOCATION_INFO_DECLARED. */ + + +#endif /* __A_OUT_GNU_H__ */ diff --git a/bin86-0.3/a.out.h/bsd-a.out.h b/bin86-0.3/a.out.h/bsd-a.out.h new file mode 100644 index 0000000..b59435b --- /dev/null +++ b/bin86-0.3/a.out.h/bsd-a.out.h @@ -0,0 +1,108 @@ +#ifndef _BSD_A_OUT_H +#define _BSD_A_OUT_H + +struct exec { /* a.out header */ + unsigned char a_magic[2]; /* magic number */ + unsigned char a_flags; /* flags, see below */ + unsigned char a_cpu; /* cpu id */ + unsigned char a_hdrlen; /* length of header */ + unsigned char a_unused; /* reserved for future use */ + unsigned short a_version; /* version stamp (not used at present) */ + long a_text; /* size of text segement in bytes */ + long a_data; /* size of data segment in bytes */ + long a_bss; /* size of bss segment in bytes */ + long a_entry; /* entry point */ + long a_total; /* total memory allocated */ + long a_syms; /* size of symbol table */ + /* SHORT FORM ENDS HERE */ +#ifndef __linux__ + long a_trsize; /* text relocation size */ + long a_drsize; /* data relocation size */ + long a_tbase; /* text relocation base */ + long a_dbase; /* data relocation base */ +#endif +}; + +#define A_MAGIC0 ((unsigned char) 0x01) +#define A_MAGIC1 ((unsigned char) 0x03) +#define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 || (X).a_magic[1] != A_MAGIC1) + +/* CPU Id of TARGET machine (byte order coded in low order two bits) */ +#define A_NONE 0x00 /* unknown */ +#define A_I8086 0x04 /* intel i8086/8088 */ +#define A_M68K 0x0B /* motorola m68000 */ +#define A_NS16K 0x0C /* national semiconductor 16032 */ +#define A_I80386 0x10 /* intel i80386 */ +#define A_SPARC 0x17 /* Sun SPARC */ + +#define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */ +#define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */ + +/* Flags. */ +#define A_UZP 0x01 /* unmapped zero page (pages) */ +#define A_EXEC 0x10 /* executable */ +#define A_SEP 0x20 /* separate I/D */ +#define A_PURE 0x40 /* pure text */ /* not used */ +#define A_TOVLY 0x80 /* text overlay */ /* not used */ + +/* Tell a.out.gnu.h not to define `struct exec'. */ +#define __STRUCT_EXEC_OVERRIDE__ + +/* Hide M_386 from enum declaration in a.out.h. */ +#define M_386 HIDE_M_386 + +#include "a.out.gnu.h" + +#undef M_386 +#define M_386 A_I80386 + +#undef N_MAGIC +#define N_MAGIC3(magic0, magic1, type) \ + ((magic0) | ((magic1) << 8) | ((type) << 16)) +#define N_MAGIC(exec) \ + N_MAGIC3((exec).a_magic[0], (exec).a_magic[1], (exec).a_flags) + +#undef N_MACHTYPE +#define N_MACHTYPE(exec) ((enum machine_type)((exec).a_cpu)) + +#undef N_FLAGS +#define N_FLAGS(exec) 0 + +#undef N_SET_INFO +#define N_SET_INFO(exec, magic, type, flags) \ + ((exec).a_magic[0] = (magic) & 0xff, \ + (exec).a_magic[1] = ((magic) >> 8) & 0xff, \ + (exec).a_flags = ((magic) >> 16) & 0xff, \ + (exec).a_cpu = (type) & 0xff) + +#undef N_SET_MAGIC +#define N_SET_MAGIC(exec, magic) \ + ((exec).a_magic[0] = (magic) & 0xff, \ + (exec).a_magic[1] = ((magic) >> 8) & 0xff, \ + (exec).a_flags = ((magic) >> 16) & 0xff) + +#undef N_SET_MACHTYPE +#define N_SET_MACHTYPE(exec, machtype) \ + ((exec).a_cpu = (machtype) & 0xff, \ + (exec).a_hdrlen = sizeof (exec)) + +#undef N_SET_FLAGS +#define N_SET_FLAGS(exec, flags) /* nothing */ + +#undef OMAGIC +#define OMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, 0) + +#undef NMAGIC +#define NMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, A_EXEC) + +#undef ZMAGIC +#define ZMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, A_EXEC) + +#undef _N_HDROFF +#define _N_HDROFF(x) 0 + +#define PAGE_SIZE 16 +#define SEGMENT_SIZE PAGE_SIZE +#define getpagesize() PAGE_SIZE + +#endif /* _BSD_A_OUT_H */ diff --git a/bin86-0.3/as/6809/const.h b/bin86-0.3/as/6809/const.h new file mode 100644 index 0000000..512c348 --- /dev/null +++ b/bin86-0.3/as/6809/const.h @@ -0,0 +1,507 @@ +/* + * bin86/as/6809/const.h + * + * Copyright (C) 1992 Bruce Evans + */ + +#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */ +#define LOW_BYTE 0 /* must be changed for big-endian */ + +/* const.h - constants for assembler */ + +/* major switches */ + +#undef I80386 /* generate 80386 code */ +#define MC6809 /* generate 6809 code */ +#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */ +#undef SOS_EDOS /* source OS is EDOS */ + +/* defaults */ + +#define DIRCHAR '/' /* character separating filename from dir */ +#define INBUFSIZE 8192 +#define SOS_EOLSTR "\012" + +/* defaults modified by switches */ + +#ifdef SOS_EDOS +# undef INBUFSIZE +# define INBUFSIZE 512 +# undef SOS_EOLSTR +# define SOS_EOLSTR "\015\012" +# define STAKSIZ 256 /* table grows up to stack less this */ +#endif + +/* booleans */ + +#define FALSE 0 +#define TRUE 1 + +/* ASCII constants */ + +#define ETB 23 + +/* C tricks */ + +#define EXTERN extern +#define FORWARD static +#define PRIVATE static +#define PUBLIC +#define NULL 0 + +/* O/S constants */ + +#define CREAT_PERMS 0666 +#define EOF (-1) +#define STDIN 0 +#define STDOUT 1 + +/* register codes (internal to assembler) */ + +#ifdef I80386 + +/* index regs must be first */ + +#define BPREG 0 +#define BXREG 1 +#define DIREG 2 +#define SIREG 3 +#define MAX16BITINDREG 3 + +#define EAXREG 4 +#define EBPREG 5 +#define EBXREG 6 +#define ECXREG 7 +#define EDIREG 8 +#define EDXREG 9 +#define ESIREG 10 +#define ESPREG 11 +#define MAXINDREG 11 + +#define AXREG 12 +#define CXREG 13 +#define DXREG 14 +#define SPREG 15 + +#define AHREG 16 +#define ALREG 17 +#define BHREG 18 +#define BLREG 19 +#define CHREG 20 +#define CLREG 21 +#define DHREG 22 +#define DLREG 23 + +#define CSREG 24 +#define DSREG 25 +#define ESREG 26 +#define FSREG 27 +#define GSREG 28 +#define SSREG 29 + +#define CR0REG 30 +#define CR2REG 31 +#define CR3REG 32 +#define DR0REG 33 +#define DR1REG 34 +#define DR2REG 35 +#define DR3REG 36 +#define DR6REG 37 +#define DR7REG 38 +#define TR6REG 39 +#define TR7REG 40 + +#define NOREG 41 + +#endif /* I80386 */ + +#ifdef MC6809 + +/* index regs must be first, then PC, then other regs */ + +#define AREG 5 +#define BREG 6 +#define CCREG 7 +#define DPREG 8 +#define DREG 9 +#define MAXINDREG 3 +#define NOREG 10 +#define PCREG 4 +#define SREG 0 +#define UREG 1 +#define XREG 2 +#define YREG 3 + +#endif + +#ifdef I80386 + +/* type and size keywords */ + +#define BYTEOP 0 +#define DWORDOP 1 +#define FWORDOP 2 +#define FAROP 3 +#define PTROP 4 +#define PWORDOP 5 +#define QWORDOP 6 +#define TBYTEOP 7 +#define WORDOP 8 +#endif + +/* special chars */ + +#define EOL 0 +#define MACROCHAR '?' + +/* symbol codes */ + +/* the first 2 must be from chars in identifiers */ +#define IDENT 0 +#define INTCONST 1 + +/* the next few are best for other possibly-multi-char tokens */ +#define ADDOP 2 /* also ++ */ +#define BINCONST 3 +#define CHARCONST 4 +#define GREATERTHAN 5 /* also >> and context-sensitive */ +#define HEXCONST 6 +#define LESSTHAN 7 /* also << and context-sensitive */ +#define SUBOP 8 /* also -- */ +#define WHITESPACE 9 + +#define ANDOP 10 +#define COMMA 11 +#define EOLSYM 12 +#define EQOP 13 +#define IMMEDIATE 14 +#define INDIRECT 15 +#define LBRACKET 16 +#define LPAREN 17 +#define MACROARG 18 +#define NOTOP 19 +#define OROP 20 +#define OTHERSYM 21 +#define POSTINCOP 22 +#define PREDECOP 23 +#define RBRACKET 24 +#define RPAREN 25 +#define SLASH 26 /* context-sensitive */ +#define SLOP 27 +#define SROP 28 +#define STAR 29 /* context-sensitive */ +#define STRINGCONST 30 +#define COLON 31 + +/* these are from assembler errors module */ + +/* syntax errors */ + +#define COMEXP 0 +#define DELEXP 1 +#define FACEXP 2 +#define IREGEXP 3 +#define LABEXP 4 +#define LPEXP 5 +#define OPEXP 6 +#define RBEXP 7 +#define REGEXP 8 +#define RPEXP 9 +#define SPEXP 10 + +/* expression errors */ + +#define ABSREQ 11 +#define NONIMPREQ 12 +#define RELBAD 13 + +/* label errors */ + +#define ILLAB 14 +#define MACUID 15 +#define MISLAB 16 +#define MNUID 17 +#define REGUID 18 +#define RELAB 19 +#define UNBLAB 20 +#define UNLAB 21 +#define VARLAB 22 + +/* addressing errors */ + +#define ABOUNDS 23 +#define DBOUNDS 24 +#define ILLMOD 25 +#define ILLREG 26 + +/* control structure errors */ + +#define ELSEBAD 27 +#define ELSEIFBAD 27 +#define ENDBBAD 28 +#define ENDIFBAD 27 +#define EOFBLOCK 29 +#define EOFIF 30 + +#define EOFLC 31 +#define EOFMAC 32 +#define FAILERR 33 + +/* overflow errors */ + +#define BLOCKOV 34 +#define BWRAP 35 +#define COUNTOV 36 +#define COUNTUN 37 +#define GETOV 38 +#define IFOV 39 + +#define LINLONG 40 +#define MACOV 41 +#define OBJSYMOV 42 +#define OWRITE 43 +#define PAROV 44 +#define SYMOV 45 +#define SYMOUTOV 46 + +/* i/o errors */ + +#define OBJOUT 47 + +/* miscellaneous errors */ + +#define CTLINS 48 +#define FURTHER 49 +#define NOIMPORT 50 +#define NOTIMPLEMENTED 51 +#define REENTER 52 +#define SEGREL 53 + +/* warnings */ + +#define MINWARN 54 +#define ALREADY 54 +#define SHORTB 55 + +/* symbol table entry */ + + /* type entry contains following flags */ +#define ENTBIT (1<<0) /* entry point (=OBJ_N_MASK) */ +#define COMMBIT (1<<1) /* common */ +#define LABIT (1<<2) /* label (a PC location or defined by EQU) */ +#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */ +#define MACBIT (1<<4) /* macro */ +#define REDBIT (1<<5) /* redefined */ +#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */ +#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */ + + /* data entry contains following flags, valid */ + /* for expressions as well as syms */ +#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT \ PAGE1 */ +#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT \ PAGE2 */ +#define REGBIT (1<<2) /* register = MNREGBIT \ REGBIT */ +#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT \ SIZEBIT */ +#define SEGM 15 /* 1st 4 bits reused for segment if !MNREGBIT */ +#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */ +#define FORBIT (1<<5) /* forward referenced */ +#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */ +#define UNDBIT (1<<7) /* undefined */ + +/* pseudo-op routine numbers */ +/* conditionals are first, this is used to test if op is a conditional */ + +#define ELSEOP 0 +#define ELSEIFOP 1 +#define ELSEIFCOP 2 +#define ENDIFOP 3 +#define IFOP 4 +#define IFCOP 5 +#define MAXCOND 6 /* limit of conditionals */ + +#define BLOCKOP 6 +#define COMMOP 7 +#define ENDOP 8 +#define ENDBOP 9 +#define ENTEROP 10 +#define ENTRYOP 11 +#define EQUOP 12 +#define EXPORTOP 13 +#define FAILOP 14 +#define FCBOP 15 +#define FCCOP 16 +#define FDBOP 17 +#define GETOP 18 +#define IDENTOP 19 +#define IMPORTOP 20 +#define _LISTOP 21 +#define LOCOP 22 +#define _MACLISTOP 23 +#define MACROOP 24 +#define _MAPOP 25 +#define ORGOP 26 +#define RMBOP 27 +#define SETOP 28 +#define SETDPOP 29 +#define _WARNOP 30 + +#ifdef I80386 + +/* further pseudo-ops */ + +#define BSSOP 31 +#define COMMOP1 32 +#define DATAOP 33 +#define TEXTOP 34 +#define USE16OP 35 +#define USE32OP 36 + +/* machine-op routine numbers */ + +#define ARPL 37 +#define BCC 38 +#define BOUND 39 +#define CALL 40 +#define DIVMUL 41 +#define ENTER 42 +#define GROUP1 43 +#define GROUP2 44 +#define GROUP6 45 +#define GROUP7 46 +#define GROUP8 47 +#define GvEv 48 +#define IMUL 49 +#define IN 50 +#define INCDEC 51 +#define INHER 52 +#define INHER16 53 +#define INHER32 54 +#define INHER_A 55 +#define INT 56 +#define JCC 57 +#define JCXZ 58 +#define LEA 59 +#define LOAD_FULL_POINTER 60 +#define MOV 61 +#define MOVX 62 +#define NEGNOT 63 +#define OUT 64 +#define PUSHPOP 65 +#define RET 66 +#define RETF 67 +#define SEG 68 +#define SETCC 69 +#define SH_DOUBLE 70 +#define TEST 71 +#define XCHG 72 + +/* further pseudo-ops */ + +#define BLKWOP 73 +#define EVENOP 74 +#define FQBOP 75 +#define ALIGNOP 76 + +/* further machine-ops */ + +#define CALLI 77 + +/* yet further pseudo-ops */ + +#define LCOMMOP 78 +#define LCOMMOP1 79 + +#endif /* I80386 */ + +#ifdef MC6809 + +/* machine-op routine numbers */ + +#define ALL 31 /* all address modes allowed, like LDA */ +#define ALTER 32 /* all but immediate, like STA */ +#define IMMED 33 /* immediate only (ANDCC, ORCC) */ +#define INDEXD 34 /* indexed (LEA's) */ +#define INHER 35 /* inherent, like CLC or CLRA */ +#define LONG 36 /* long branches */ +#define SHORT 37 /* short branches */ +#define SSTAK 38 /* S-stack (PSHS, PULS) */ +#define SWAP 39 /* TFR, EXG */ +#define USTAK 40 /* U-stack (PSHU,PULU) */ + +/* yet further pseudo-ops */ + +#define LCOMMOP 41 + +#endif + +/* object code format (Introl) */ + +#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */ + +#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */ + +#define OBJ_ABS 0x40 /* absolute code command */ +#define OBJ_OFFSET_REL 0x80 /* offset relocation command */ +#define OBJ_SET_SEG 0x20 /* set segment command */ +#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */ +#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */ +#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */ +#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */ + +#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */ +#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */ +oops - RELBIT misplaced +#endif +#define OBJ_E_MASK 0x80 /* exported bit (symbols) */ +#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */ +oops - EXPBIT misplaced +#endif +#define OBJ_I_MASK 0x40 /* imported bit (symbols) */ +#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */ +oops - IMPBIT misplaced +#endif +#define OBJ_N_MASK 0x01 /* entry bit (symbols) */ +#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */ +oops - ENTBIT misplaced +#endif +#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */ +#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */ +#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */ +#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */ + +#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */ +#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */ + +#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */ +#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */ + +#define SYMLIS_NAMELEN 26 +#define SYMLIS_LEN (sizeof (struct sym_listing_s)) + +#define FILNAMLEN 64 /* max length of a file name */ +#define LINLEN 256 /* max length of input line */ +#define LINUM_LEN 5 /* length of formatted line number */ + +#define SPTSIZ 1024 /* number of symbol ptrs */ + /* pseudo-op flags */ +#define POPHI 1 /* set to print hi byte of adr */ +#define POPLO 2 /* to print lo byte of ADR */ +#define POPLC 4 /* to print LC */ +#define POPLONG 8 /* to print high word of ADR */ +#define MAXBLOCK 8 /* max nesting level of BLOCK stack */ +#define MAXGET 8 /* max nesting level of GET stack */ +#define MAXIF 8 /* max nesting level of IF stack */ +#define MACPSIZ (128/sizeof (struct schain_s)) + /* size of macro param buffer */ +#define MAXMAC 8 /* max nesting level of macro stack */ +#define NLOC 16 /* number of location counters */ +#ifdef I80386 +#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */ +#endif + +/* special segments */ + +#define BSSLOC 3 +#define DATALOC 3 +#define DPLOC 2 +#define STRLOC 1 +#define TEXTLOC 0 diff --git a/bin86-0.3/as/Makefile b/bin86-0.3/as/Makefile new file mode 100644 index 0000000..70104e8 --- /dev/null +++ b/bin86-0.3/as/Makefile @@ -0,0 +1,57 @@ +CC =gcc +CFLAGS =-O1 -fomit-frame-pointer -Dwarn=as_warn +INC_CFLAGS =-I../a.out.h +LDFLAGS =-s + +OBJS =as.o assemble.o error.o express.o \ + genbin.o genlist.o genobj.o gensym.o \ + keywords.o macro.o mops.o pops.o \ + readsrc.o scan.o table.o ../ld/typeconv.o + +.SUFFIXES: +.SUFFIXES: .c .o + +.c.o: + $(CC) $(CFLAGS) $(INC_CFLAGS) -c $< + +all: as86 + +as86: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) + +clean: + $(RM) *.o as86 core endian.h + +as.o: const.h type.h byteord.h macro.h file.h flag.h globvar.h +assemble.o: const.h type.h address.h globvar.h opcode.h scan.h +error.o: const.h type.h +express.o: const.h type.h address.h globvar.h scan.h source.h +genbin.o: const.h type.h address.h file.h globvar.h +genlist.o: const.h type.h address.h flag.h file.h globvar.h macro.h scan.h \ + source.h +genobj.o: const.h type.h address.h file.h globvar.h +gensym.o: const.h type.h flag.h file.h globvar.h +keywords.o: const.h type.h opcode.h +macro.o: const.h type.h globvar.h scan.h macro.h +mops.o: const.h type.h globvar.h opcode.h scan.h address.h +pops.o: const.h type.h address.h flag.h globvar.h opcode.h scan.h +readsrc.o: const.h type.h flag.h file.h globvar.h macro.h scan.h source.h +scan.o: const.h type.h scan.h +table.o: const.h type.h globvar.h scan.h + +const.h: endian.h + +endian.h: det_endian.c + $(CC) -o det_endian det_endian.c + -@if [ $$? = 0 ]; then \ + det_endian > $@; \ + if [ $$? = 0 ]; then \ + rm -f det_endian; \ + else \ + echo Failed to create $@; \ + exit 1; \ + fi; \ + else \ + echo Failed to compile det_endian.c; \ + exit 1; \ + fi diff --git a/bin86-0.3/as/address.h b/bin86-0.3/as/address.h new file mode 100644 index 0000000..e310535 --- /dev/null +++ b/bin86-0.3/as/address.h @@ -0,0 +1,36 @@ +/* + * bin86/as/address.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* address.h - global variables involving addresses for assembler */ + +EXTERN struct address_s lastexp;/* last expression parsed */ + +EXTERN union +{ + char fcbuf[LINLEN - 6]; /* buffer for fcb and fcc data */ + /* data is absolute in 1 char pieces */ + /* limited by FCC\t"" etc on line */ + struct address_s fdbuf[(LINLEN - 4) / 2]; + /* buffer for fdb data */ + /* data can be of any 2-byte adr type */ + /* limited by FDB\t and commas on line */ +#if SIZEOF_OFFSET_T > 2 + struct address_s fqbuf[(LINLEN - 4) / 4]; + /* buffer for fqb data */ + /* data can be of any 4-byte adr type */ + /* limited by FQB\t and commas on line */ +#endif +} + databuf; + +EXTERN bool_t fcflag; +EXTERN bool_t fdflag; +#if SIZEOF_OFFSET_T > 2 +EXTERN bool_t fqflag; +#endif + +EXTERN struct address_s immadr; +EXTERN smallcount_t immcount; diff --git a/bin86-0.3/as/as.c b/bin86-0.3/as/as.c new file mode 100644 index 0000000..9f91639 --- /dev/null +++ b/bin86-0.3/as/as.c @@ -0,0 +1,280 @@ +/* + * bin86/as/as.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* as.c - assembler */ + +/* + usage: as source [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] [-guw] + in any order (but no repeated file options) +*/ + +#include <sys/types.h> +#include <fcntl.h> +#include "const.h" +#include "type.h" +#include "byteord.h" +#include "macro.h" +#undef EXTERN +#define EXTERN +#include "file.h" +#include "flag.h" +#include "globvar.h" + +PRIVATE struct block_s hid_blockstak[MAXBLOCK]; /* block stack */ +PRIVATE struct lc_s hid_lctab[NLOC]; /* location counter table */ +PRIVATE struct if_s hid_ifstak[MAXBLOCK]; /* if stack */ +PRIVATE struct schain_s hid_mcpar[MACPSIZ]; /* MACRO params */ +PRIVATE struct macro_s hid_macstak[MAXBLOCK]; /* macro stack */ +PRIVATE struct sym_s *hid_spt[SPTSIZ]; /* hash table */ + +FORWARD void initp1 P((void)); +FORWARD int my_creat P((char *name, char *message)); +FORWARD void process_args P((int argc, char **argv)); +FORWARD void summary P((fd_t fd)); +FORWARD void summ_number P((unsigned num)); +FORWARD void usage P((void)); + +#define USERMEM (sizeof(int) <= 2 ? (unsigned) 0xAC00 : (unsigned) 0x20000L) + +PUBLIC int main(argc, argv) +int argc; +char **argv; +{ + heapptr = malloc(USERMEM); + heapend = heapptr + USERMEM; + if (heapptr == 0) + as_abort("cannot allocate memory"); +#ifdef SOS_EDOS + heapend = stackreg() - STAKSIZ; +#endif + initp1(); + initp1p2(); + inst_keywords(); + initbin(); + initobj(); + initsource(); /* only nec to init for unsupported mem file */ + typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN); + warn.global = TRUE; /* constant */ + process_args(argc, argv); + initscan(); + + assemble(); /* doesn't return, maybe use setjmp */ + + /* NOTREACHED */ + return 0; +} + +PUBLIC void as_abort(message) +char *message; +{ + write(STDOUT, "as: ", 4); + write(STDOUT, message, strlen(message)); + write(STDOUT, "\n", 1); + exit(1); +} + +PUBLIC void finishup() +{ + bintrailer(); + objtrailer(); + if (list.global ||symgen) + gensym(); /* output to lstfil and/or symfil */ + if (list.global ||toterr != 0 || totwarn != 0) + summary(lstfil); + if (lstfil != STDOUT && (toterr != 0 || totwarn != 0)) + summary(STDOUT); + statistics(); + exit(toterr != 0 ? 1 : 0); /* should close output files and check */ +} + +/* initialise constant nonzero values */ + +PRIVATE void initp1() +{ +#ifdef I80386 + idefsize = defsize = sizeof (char *) > 2 ? 4 : 2; +#endif + lctabtop = lctab + NLOC; + lstfil = STDOUT; + mapnum = 15; /* default map number for symbol table */ + spt_top = (spt = hid_spt) + SPTSIZ; +} + +/* initialise nonzero values which start same each pass */ + +PUBLIC void initp1p2() +{ + register struct lc_s *lcp; + + ifflag = TRUE; + pedata = UNDBIT; /* program entry point not defined */ + blockstak = hid_blockstak + MAXBLOCK; + ifstak = hid_ifstak + MAXIF; + macstak = hid_macstak + MAXMAC; + macptop = (macpar = hid_mcpar) + MACPSIZ; + lctabtop = (lcptr = lctab = hid_lctab) + NLOC; + for (lcp = lctab; lcp < lctabtop; ++lcp) + /* init of lcdata/lc (many times) in loop to save space */ + { + lcp->data = lcdata = RELBIT; /* lc relocatable until 1st ORG */ + lcp->lc = lc = 0; + } +} + +PRIVATE int my_creat(name, message) +char *name; +char *message; +{ + int fd; + + if ((fd = creat(name, CREAT_PERMS)) < 0 || fd > 255) + as_abort(message); + return fd; +} + +PRIVATE void process_args(argc, argv) +int argc; +char **argv; +{ + char *arg; + bool_t isnextarg; + char *nextarg; + + if (argc <= 1) + usage(); + do + { + arg = *++argv; + if (arg[0] == '-') + { + if (arg[2] != 0) + usage(); /* no multiple options */ + isnextarg = FALSE; + if (argc > 2) + { + nextarg = argv[1]; + if (nextarg[0] != 0 && nextarg[0] != '-') + isnextarg = TRUE; + } + switch (arg[1]) + { +#ifdef I80386 + case '0': + idefsize = defsize = 0x2; + break; + case '3': + idefsize = defsize = 0x4; + break; + case 'a': + asld_compatible = TRUE; + break; +#endif + case 'b': + if (!isnextarg || binfil != 0) + usage(); + binfil = my_creat(nextarg, "error creating binary file"); + binaryg = TRUE; + --argc; + ++argv; + break; + case 'g': + globals_only_in_obj = TRUE; + break; +#ifdef I80386 + case 'j': + jumps_long = TRUE; + break; +#endif + case 'l': + list.global = TRUE; + goto get_any_list_file; + case 'm': + maclist.global = TRUE; + get_any_list_file: + if (isnextarg) + { + if (lstfil != STDOUT) + usage(); + lstfil = my_creat(nextarg, "error creating list file"); + --argc; + ++argv; + } + break; + case 'n': + if (!isnextarg) + usage(); + truefilename = nextarg; + --argc; + ++argv; + break; + case 'o': + if (!isnextarg || objfil != 0) + usage(); + objectg = TRUE; + objfil = my_creat(nextarg, "error creating object file"); + --argc; + ++argv; + break; + case 's': + if (!isnextarg || symfil != 0) + usage(); + symgen = TRUE; + symfil = my_creat(nextarg, "error creating symbol file"); + --argc; + ++argv; + break; + case 'u': + inidata = IMPBIT | SEGM; + break; + case 'w': + warn.semaphore = -1; + break; + default: + usage(); /* bad option */ + } + } + else if (infil != 0) + usage(); /* no multiple sources */ + else + { + if (strlen(arg) > FILNAMLEN) + as_abort("source file name too long"); + infil = open_input(strcpy(filnamptr, arg)); + infiln = infil0 = 1; + } + } + while (--argc != 1); + inidata = (~binaryg & inidata) | (RELBIT | UNDBIT); +} /* IMPBIT from inidata unless binaryg */ + +PRIVATE void summary(fd) +int fd; +{ + innum = fd; + writenl(); + summ_number(toterr); + writesn(" errors"); + summ_number(totwarn); + writesn(" warnings"); +} + +PRIVATE void summ_number(num) +unsigned num; +{ + /* format number like line numbers, build it at free spot heapptr */ + *build_number(num, LINUM_LEN, heapptr) = 0; + writes(heapptr); +} + +PRIVATE void usage() +{ + as_abort( +#ifdef I80386 +"usage: as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src"); +#else + "usage: as [-guw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src"); +#endif +} diff --git a/bin86-0.3/as/asm/calljmp.asm b/bin86-0.3/as/asm/calljmp.asm new file mode 100644 index 0000000..36a6ea4 --- /dev/null +++ b/bin86-0.3/as/asm/calljmp.asm @@ -0,0 +1,70 @@ + CALL 0x10:0x20 ; not implemented + CALL AL; ; illeg + CALL DS ; illeg + + CALL REL16 + + CALL AX + CALL BX + CALL CX + CALL DX + CALL SP + CALL BP + CALL SI + CALL DI + + CALL BYTE [BX] ; illeg + CALL [BX] + CALL WORD [BX] + + USE32 + CALL REL32 + + USE16 + CALL EAX + CALL EBX + CALL ECX + CALL EDX + CALL ESP + CALL EBP + CALL ESI + CALL EDI + + CALL DWORD [BX] + + JMP 0x10:0x20 ; not implemented + JMP AL; ; illeg + JMP DS ; illeg + + JMP REL16 + + JMP AX + JMP BX + JMP CX + JMP DX + JMP SP + JMP BP + JMP SI + JMP DI + + JMP BYTE [BX] ; illeg + JMP [BX] + JMP WORD [BX] + + USE32 + JMP REL32 + + USE16 + JMP EAX + JMP EBX + JMP ECX + JMP EDX + JMP ESP + JMP EBP + JMP ESI + JMP EDI + + JMP DWORD [BX] + +REL16: +REL32: diff --git a/bin86-0.3/as/asm/ea.asm b/bin86-0.3/as/asm/ea.asm new file mode 100644 index 0000000..8717a73 --- /dev/null +++ b/bin86-0.3/as/asm/ea.asm @@ -0,0 +1,109 @@ + MOV AX,[BX+SI] + MOV AX,[BX+DI] + MOV AX,[BP+SI] + MOV AX,[BP+DI] + MOV AX,[SI] + MOV AX,[DI] + MOV AX,[0x1234] + MOV AX,[BX] + + MOV AX,[BX+SI+0x12] + MOV AX,[BX+DI+0x12] + MOV AX,[BP+SI+0x12] + MOV AX,[BP+DI+0x12] + MOV AX,[SI+0x12] + MOV AX,[DI+0x12] + MOV AX,[BP+0x12] + MOV AX,[BX+0x12] + + MOV AX,[BX+SI+0x1234] + MOV AX,[BX+DI+0x1234] + MOV AX,[BP+SI+0x1234] + MOV AX,[BP+DI+0x1234] + MOV AX,[SI+0x1234] + MOV AX,[DI+0x1234] + MOV AX,[BP+0x1234] + MOV AX,[BX+0x1234] + + MOV AL,AL + MOV AL,AH + MOV AL,BL + MOV AL,BH + MOV AL,CL + MOV AL,CH + MOV AL,DL + MOV AL,DH + + MOV AX,AX + MOV AX,CX + MOV AX,DX + MOV AX,BX + MOV AX,SP + MOV AX,BP + MOV AX,SI + MOV AX,DI + + MOV AX,[EAX] + MOV AX,[ECX] + MOV AX,[EDX] + MOV AX,[EBX] + + MOV AX,[0x12345678] + MOV AX,[ESI] + MOV AX,[EDI] + + MOV AX,[EAX+0x12] + MOV AX,[ECX+0x12] + MOV AX,[EDX+0x12] + MOV AX,[EBX+0x12] + + MOV AX,[EBP+0x12] + MOV AX,[ESI+0x12] + MOV AX,[EDI+0x12] + + MOV AX,[EAX+0x12345678] + MOV AX,[ECX+0x12345678] + MOV AX,[EDX+0x12345678] + MOV AX,[EBX+0x12345678] + + MOV AX,[EBP+0x12345678] + MOV AX,[ESI+0x12345678] + MOV AX,[EDI+0x12345678] + + MOV EAX,EAX + MOV EAX,ECX + MOV EAX,EDX + MOV EAX,EBX + MOV EAX,ESP + MOV EAX,EBP + MOV EAX,ESI + MOV EAX,EDI + + MOV AX,[EAX+ESI*2] + MOV AX,[ECX+ESI*2] + MOV AX,[EDX+ESI*2] + MOV AX,[EBX+ESI*2] + MOV AX,[ESP+ESI*2] + MOV AX,[ESI*2+0x12345678] + MOV AX,[ESI+ESI*2] + MOV AX,[EDI+ESI*2] + + MOV AX,[EAX+ESI*2+0x12] + MOV AX,[ECX+ESI*2+0x12] + MOV AX,[EDX+ESI*2+0x12] + MOV AX,[EBX+ESI*2+0x12] + MOV AX,[ESP+ESI*2+0x12] + MOV AX,[ESP+0x12] + MOV AX,[EBP+ESI*2+0x12] + MOV AX,[ESI+ESI*2+0x12] + MOV AX,[EDI+ESI*2+0x12] + + MOV AX,[EAX+ESI*2+0x12345678] + MOV AX,[ECX+ESI*2+0x12345678] + MOV AX,[EDX+ESI*2+0x12345678] + MOV AX,[EBX+ESI*2+0x12345678] + MOV AX,[ESP+ESI*2+0x12345678] + MOV AX,[ESP+0x12345678] + MOV AX,[EBP+ESI*2+0x12345678] + MOV AX,[ESI+ESI*2+0x12345678] + MOV AX,[EDI+ESI*2+0x12345678] diff --git a/bin86-0.3/as/asm/each.asm b/bin86-0.3/as/asm/each.asm new file mode 100644 index 0000000..2145489 --- /dev/null +++ b/bin86-0.3/as/asm/each.asm @@ -0,0 +1,145 @@ +aaa +aad +aam +aas +adc bx,[esi*4] +add bx,[esi*4] +and bx,[esi*4] +arpl [esi*4],bx +bound bx,[esi*4] +bsf bx,[esi*4] +bsr bx,[esi*4] +bswap ebx +bt [esi*4],bx +btc [esi*4],bx +btr [esi*4],bx +bts [esi*4],bx +call [esi*4] +cbw +cwde +clc +cld +cli +clts +cmc +cmp bx,[esi*4] +cmpsb +cmpsw +cmpsd +cmpxchg [esi*4],bx +cwd +cdq +daa +das +dec [esi*4] +div [esi*4] +enter 0x200,3 +hlt +idiv [esi*4] +imul [esi*4] +in al,0x20 +inc [esi*4] +insb +insw +insd +int 0x20 +into +invd +invlpg [esi*4] +iret +iretd +jnz many +many: +jmp [esi*4] +lahf +lar bx,[esi*4] +lea bx,[esi*4] +leave +lgdt [esi*4] +lidt [esi*4] +lds bx,[esi*4] +les bx,[esi*4] +lfs bx,[esi*4] +lgs bx,[esi*4] +lss bx,[esi*4] +lldt [esi*4] +lmsw [esi*4] +lock +lodsb +lodsw +lodsd +loop alot +alot: +lsl bx,[esi*4] +ltr [esi*4] +mov ax,[esi*4] +mov bx,[esi*4] +mov cr0,eax +movsb +movsw +movsd +movsx bx,byte [esi*4] +movzx bx,byte [esi*4] +mul [esi*4] +neg [esi*4] +nop +not [esi*4] +or bx,[esi*4] +out 0x20,al +outsb +outsw +outsd +pop [esi*4] +popa +popad +popf +popfd +push [esi*4] +pusha +pushad +pushf +pushfd +rcl [esi*4],1 +rcr [esi*4],1 +rol [esi*4],1 +ror [esi*4],1 +rep +repe +repz +repne +repnz +ret +retf +sahf +sal [esi*4],1 +sar [esi*4],1 +shl [esi*4],1 +shr [esi*4],1 +sbb bx,[esi*4] +scasb +scasw +scasd +setnz byte [esi*4] +sgdt [esi*4] +sidt [esi*4] +shld [esi*4],bx,1 +shrd [esi*4],bx,1 +sldt [esi*4] +smsw [esi*4] +stc +std +sti +stosb +stosw +stosd +str [esi*4] +sub bx,[esi*4] +test bx,[esi*4] +verr [esi*4] +verw [esi*4] +wait +wbinvd +xadd [esi*4],bx +xchg bx,[esi*4] +xlat +xor bx,[esi*4] diff --git a/bin86-0.3/as/asm/easlow.as b/bin86-0.3/as/asm/easlow.as new file mode 100644 index 0000000..75d71e2 --- /dev/null +++ b/bin86-0.3/as/asm/easlow.as @@ -0,0 +1,1219 @@ + MOV AL,[0] + MOV AH,[1] + MOV BL,[-1] ; illeg + MOV BH,[127] + MOV CL,[-128] ; illeg + MOV CH,[128] + MOV DL,[-129] ; illeg + MOV DH,[32767] + MOV AL,[-32768] ; illeg + MOV AH,[32768] + MOV BL,[-32769] ; illeg + MOV BH,[$7FFFFFFF] ; illeg + MOV CL,[$80000000] ; illeg + + MOV AL,AL + MOV AL,AH + MOV AL,BL + MOV AL,BH + MOV AL,CL + MOV AL,CH + MOV AL,DL + MOV AL,DH + + MOV AL,AX ; illeg + MOV AL,BX ; illeg + MOV AL,CX ; illeg + MOV AL,DX ; illeg + MOV AL,BP ; illeg + MOV AL,DI ; illeg + MOV AL,SI ; illeg + MOV AL,SP ; illeg + + MOV AH,AL + MOV AH,AH + MOV AH,BL + MOV AH,BH + MOV AH,CL + MOV AH,CH + MOV AH,DL + MOV AH,DH + + MOV AH,AX ; illeg + MOV AH,BX ; illeg + MOV AH,CX ; illeg + MOV AH,DX ; illeg + MOV AH,BP ; illeg + MOV AH,DI ; illeg + MOV AH,SI ; illeg + MOV AH,SP ; illeg + + MOV BL,AL + MOV BL,AH + MOV BL,BL + MOV BL,BH + MOV BL,CL + MOV BL,CH + MOV BL,DL + MOV BL,DH + + MOV BL,AX ; illeg + MOV BL,BX ; illeg + MOV BL,CX ; illeg + MOV BL,DX ; illeg + MOV BL,BP ; illeg + MOV BL,DI ; illeg + MOV BL,SI ; illeg + MOV BL,SP ; illeg + + MOV BH,AL + MOV BH,AH + MOV BH,BL + MOV BH,BH + MOV BH,CL + MOV BH,CH + MOV BH,DL + MOV BH,DH + + MOV BH,AX ; illeg + MOV BH,BX ; illeg + MOV BH,CX ; illeg + MOV BH,DX ; illeg + MOV BH,BP ; illeg + MOV BH,DI ; illeg + MOV BH,SI ; illeg + MOV BH,SP ; illeg + + MOV CL,AL + MOV CL,AH + MOV CL,BL + MOV CL,BH + MOV CL,CL + MOV CL,CH + MOV CL,DL + MOV CL,DH + + MOV CL,AX ; illeg + MOV CL,BX ; illeg + MOV CL,CX ; illeg + MOV CL,DX ; illeg + MOV CL,BP ; illeg + MOV CL,DI ; illeg + MOV CL,SI ; illeg + MOV CL,SP ; illeg + + MOV CH,AL + MOV CH,AH + MOV CH,BL + MOV CH,BH + MOV CH,CL + MOV CH,CH + MOV CH,DL + MOV CH,DH + + MOV CH,AX ; illeg + MOV CH,BX ; illeg + MOV CH,CX ; illeg + MOV CH,DX ; illeg + MOV CH,BP ; illeg + MOV CH,DI ; illeg + MOV CH,SI ; illeg + MOV CH,SP ; illeg + + MOV DL,AL + MOV DL,AH + MOV DL,BL + MOV DL,BH + MOV DL,CL + MOV DL,CH + MOV DL,DL + MOV DL,DH + + MOV DL,AX ; illeg + MOV DL,BX ; illeg + MOV DL,CX ; illeg + MOV DL,DX ; illeg + MOV DL,BP ; illeg + MOV DL,DI ; illeg + MOV DL,SI ; illeg + MOV DL,SP ; illeg + + MOV DH,AL + MOV DH,AH + MOV DH,BL + MOV DH,BH + MOV DH,CL + MOV DH,CH + MOV DH,DL + MOV DH,DH + + MOV DH,AX ; illeg + MOV DH,BX ; illeg + MOV DH,CX ; illeg + MOV DH,DX ; illeg + MOV DH,BP ; illeg + MOV DH,DI ; illeg + MOV DH,SI ; illeg + MOV DH,SP ; illeg + + MOV AL,[AL] ; illeg + MOV AH,[AH] ; illeg + MOV BL,[BL] ; illeg + MOV BH,[BH] ; illeg + MOV CL,[CL] ; illeg + MOV CH,[CH] ; illeg + MOV DL,[DL] ; illeg + MOV DH,[DH] ; illeg + + MOV AL,[AX] ; illeg + MOV AH,[BX] + MOV BL,[CX] ; illeg + MOV BH,[DX] ; illeg + MOV CL,[BP] + MOV CH,[DI] + MOV DL,[SI] + MOV DH,[SP] ; illeg + + MOV AL,[AX+1] ; illeg + MOV AH,[BX+1] + MOV BL,[CX+1] ; illeg + MOV BH,[DX+1] ; illeg + MOV CL,[BP+1] + MOV CH,[DI+1] + MOV DL,[SI+1] + MOV DH,[SP+1] ; illeg + + MOV AL,[AX-1] ; illeg + MOV AH,[BX-1] + MOV BL,[CX-1] ; illeg + MOV BH,[DX-1] ; illeg + MOV CL,[BP-1] + MOV CH,[DI-1] + MOV DL,[SI-1] + MOV DH,[SP-1] ; illeg + + MOV AL,[AX+127] ; illeg + MOV AH,[BX+127] + MOV BL,[CX+127] ; illeg + MOV BH,[DX+127] ; illeg + MOV CL,[BP+127] + MOV CH,[DI+127] + MOV DL,[SI+127] + MOV DH,[SP+127] ; illeg + + MOV AL,[AX-128] ; illeg + MOV AH,[BX-128] + MOV BL,[CX-128] ; illeg + MOV BH,[DX-128] ; illeg + MOV CL,[BP-128] + MOV CH,[DI-128] + MOV DL,[SI-128] + MOV DH,[SP-128] ; illeg + + MOV AL,[AX+128] ; illeg + MOV AH,[BX+128] + MOV BL,[CX+128] ; illeg + MOV BH,[DX+128] ; illeg + MOV CL,[BP+128] + MOV CH,[DI+128] + MOV DL,[SI+128] + MOV DH,[SP+128] ; illeg + + MOV AL,[AX-129] ; illeg + MOV AH,[BX-129] + MOV BL,[CX-129] ; illeg + MOV BH,[DX-129] ; illeg + MOV CL,[BP-129] + MOV CH,[DI-129] + MOV DL,[SI-129] + MOV DH,[SP-129] ; illeg + + MOV AL,[AX+32767] ; illeg + MOV AH,[BX+32767] + MOV BL,[CX+32767] ; illeg + MOV BH,[DX+32767] ; illeg + MOV CL,[BP+32767] + MOV CH,[DI+32767] + MOV DL,[SI+32767] + MOV DH,[SP+32767] ; illeg + + MOV AL,[AX-32768] ; illeg + MOV AH,[BX-32768] + MOV BL,[CX-32768] ; illeg + MOV BH,[DX-32768] ; illeg + MOV CL,[BP-32768] + MOV CH,[DI-32768] + MOV DL,[SI-32768] + MOV DH,[SP-32768] ; illeg + + MOV AL,[AX+32768] ; illeg + MOV AH,[BX+32768] + MOV BL,[CX+32768] ; illeg + MOV BH,[DX+32768] ; illeg + MOV CL,[BP+32768] + MOV CH,[DI+32768] + MOV DL,[SI+32768] + MOV DH,[SP+32768] ; illeg + + MOV AL,[AX-32769] ; illeg + MOV AH,[BX-32769] + MOV BL,[CX-32769] ; illeg + MOV BH,[DX-32769] ; illeg + MOV CL,[BP-32769] + MOV CH,[DI-32769] + MOV DL,[SI-32769] + MOV DH,[SP-32769] ; illeg + + MOV AL,[AX+$7FFFFFFF] ; illeg + MOV AH,[BX+$7FFFFFFF] ; illeg (bounds) + MOV BL,[CX+$7FFFFFFF] ; illeg + MOV BH,[DX+$7FFFFFFF] ; illeg + MOV CL,[BP+$7FFFFFFF] ; illeg (bounds) + MOV CH,[DI+$7FFFFFFF] ; illeg (bounds) + MOV DL,[SI+$7FFFFFFF] ; illeg (bounds) + MOV DH,[SP+$7FFFFFFF] ; illeg + + MOV AL,[AX-$80000000] ; illeg + MOV AH,[BX-$80000000] ; illeg (bounds) + MOV BL,[CX-$80000000] ; illeg + MOV BH,[DX-$80000000] ; illeg + MOV CL,[BP-$80000000] ; illeg (bounds) + MOV CH,[DI-$80000000] ; illeg (bounds) + MOV DL,[SI-$80000000] ; illeg (bounds) + MOV DH,[SP-$80000000] ; illeg + + MOV AL,[AX+AX] ; illeg + MOV AH,[AX+BX] ; illeg + MOV BL,[AX+CX] ; illeg + MOV BH,[AX+DX] ; illeg + MOV CL,[AX+BP] ; illeg + MOV CH,[AX+DI] ; illeg + MOV DL,[AX+SI] ; illeg + MOV DH,[AX+SP] ; illeg + + MOV AL,[BX+AX] ; illeg + MOV AH,[BX+BX] ; illeg + MOV BL,[BX+CX] ; illeg + MOV BH,[BX+DX] ; illeg + MOV CL,[BX+BP] ; illeg + MOV CH,[BX+DI] + MOV DL,[BX+SI] + MOV DH,[BX+SP] ; illeg + + MOV AL,[CX+AX] ; illeg + MOV AH,[CX+BX] ; illeg + MOV BL,[CX+CX] ; illeg + MOV BH,[CX+DX] ; illeg + MOV CL,[CX+BP] ; illeg + MOV CH,[CX+DI] ; illeg + MOV DL,[CX+SI] ; illeg + MOV DH,[CX+SP] ; illeg + + MOV AL,[DX+AX] ; illeg + MOV AH,[DX+BX] ; illeg + MOV BL,[DX+CX] ; illeg + MOV BH,[DX+DX] ; illeg + MOV CL,[DX+BP] ; illeg + MOV CH,[DX+DI] ; illeg + MOV DL,[DX+SI] ; illeg + MOV DH,[DX+SP] ; illeg + + MOV AL,[BP+AX] ; illeg + MOV AH,[BP+BX] ; illeg + MOV BL,[BP+CX] ; illeg + MOV BH,[BP+DX] ; illeg + MOV CL,[BP+BP] ; illeg + MOV CH,[BP+DI] + MOV DL,[BP+SI] + MOV DH,[BP+SP] ; illeg + + MOV AL,[DI+AX] ; illeg + MOV AH,[DI+BX] + MOV BL,[DI+CX] ; illeg + MOV BH,[DI+DX] ; illeg + MOV CL,[DI+BP] + MOV CH,[DI+DI] ; illeg + MOV DL,[DI+SI] ; illeg + MOV DH,[DI+SP] ; illeg + + MOV AL,[SI+AX] ; illeg + MOV AH,[SI+BX] + MOV BL,[SI+CX] ; illeg + MOV BH,[SI+DX] ; illeg + MOV CL,[SI+BP] + MOV CH,[SI+DI] ; illeg + MOV DL,[SI+SI] ; illeg + MOV DH,[SI+SP] ; illeg + + MOV AL,[SP+AX] ; illeg + MOV AH,[SP+BX] ; illeg + MOV BL,[SP+CX] ; illeg + MOV BH,[SP+DX] ; illeg + MOV CL,[SP+BP] ; illeg + MOV CH,[SP+DI] ; illeg + MOV DL,[SP+SI] ; illeg + MOV DH,[SP+SP] ; illeg + + MOV AL,[AX+AX+1] ; illeg + MOV AH,[AX+BX+1] ; illeg + MOV BL,[AX+CX+1] ; illeg + MOV BH,[AX+DX+1] ; illeg + MOV CL,[AX+BP+1] ; illeg + MOV CH,[AX+DI+1] ; illeg + MOV DL,[AX+SI+1] ; illeg + MOV DH,[AX+SP+1] ; illeg + + MOV AL,[BX+AX+1] ; illeg + MOV AH,[BX+BX+1] ; illeg + MOV BL,[BX+CX+1] ; illeg + MOV BH,[BX+DX+1] ; illeg + MOV CL,[BX+BP+1] ; illeg + MOV CH,[BX+DI+1] + MOV DL,[BX+SI+1] + MOV DH,[BX+SP+1] ; illeg + + MOV AL,[CX+AX+1] ; illeg + MOV AH,[CX+BX+1] ; illeg + MOV BL,[CX+CX+1] ; illeg + MOV BH,[CX+DX+1] ; illeg + MOV CL,[CX+BP+1] ; illeg + MOV CH,[CX+DI+1] ; illeg + MOV DL,[CX+SI+1] ; illeg + MOV DH,[CX+SP+1] ; illeg + + MOV AL,[DX+AX+1] ; illeg + MOV AH,[DX+BX+1] ; illeg + MOV BL,[DX+CX+1] ; illeg + MOV BH,[DX+DX+1] ; illeg + MOV CL,[DX+BP+1] ; illeg + MOV CH,[DX+DI+1] ; illeg + MOV DL,[DX+SI+1] ; illeg + MOV DH,[DX+SP+1] ; illeg + + MOV AL,[BP+AX+1] ; illeg + MOV AH,[BP+BX+1] ; illeg + MOV BL,[BP+CX+1] ; illeg + MOV BH,[BP+DX+1] ; illeg + MOV CL,[BP+BP+1] ; illeg + MOV CH,[BP+DI+1] + MOV DL,[BP+SI+1] + MOV DH,[BP+SP+1] ; illeg + + MOV AL,[DI+AX+1] ; illeg + MOV AH,[DI+BX+1] + MOV BL,[DI+CX+1] ; illeg + MOV BH,[DI+DX+1] ; illeg + MOV CL,[DI+BP+1] + MOV CH,[DI+DI+1] ; illeg + MOV DL,[DI+SI+1] ; illeg + MOV DH,[DI+SP+1] ; illeg + + MOV AL,[SI+AX+1] ; illeg + MOV AH,[SI+BX+1] + MOV BL,[SI+CX+1] ; illeg + MOV BH,[SI+DX+1] ; illeg + MOV CL,[SI+BP+1] + MOV CH,[SI+DI+1] ; illeg + MOV DL,[SI+SI+1] ; illeg + MOV DH,[SI+SP+1] ; illeg + + MOV AL,[SP+AX+1] ; illeg + MOV AH,[SP+BX+1] ; illeg + MOV BL,[SP+CX+1] ; illeg + MOV BH,[SP+DX+1] ; illeg + MOV CL,[SP+BP+1] ; illeg + MOV CH,[SP+DI+1] ; illeg + MOV DL,[SP+SI+1] ; illeg + MOV DH,[SP+SP+1] ; illeg + + MOV AL,[AX+AX-1] ; illeg + MOV AH,[AX+BX-1] ; illeg + MOV BL,[AX+CX-1] ; illeg + MOV BH,[AX+DX-1] ; illeg + MOV CL,[AX+BP-1] ; illeg + MOV CH,[AX+DI-1] ; illeg + MOV DL,[AX+SI-1] ; illeg + MOV DH,[AX+SP-1] ; illeg + + MOV AL,[BX+AX-1] ; illeg + MOV AH,[BX+BX-1] ; illeg + MOV BL,[BX+CX-1] ; illeg + MOV BH,[BX+DX-1] ; illeg + MOV CL,[BX+BP-1] ; illeg + MOV CH,[BX+DI-1] + MOV DL,[BX+SI-1] + MOV DH,[BX+SP-1] ; illeg + + MOV AL,[CX+AX-1] ; illeg + MOV AH,[CX+BX-1] ; illeg + MOV BL,[CX+CX-1] ; illeg + MOV BH,[CX+DX-1] ; illeg + MOV CL,[CX+BP-1] ; illeg + MOV CH,[CX+DI-1] ; illeg + MOV DL,[CX+SI-1] ; illeg + MOV DH,[CX+SP-1] ; illeg + + MOV AL,[DX+AX-1] ; illeg + MOV AH,[DX+BX-1] ; illeg + MOV BL,[DX+CX-1] ; illeg + MOV BH,[DX+DX-1] ; illeg + MOV CL,[DX+BP-1] ; illeg + MOV CH,[DX+DI-1] ; illeg + MOV DL,[DX+SI-1] ; illeg + MOV DH,[DX+SP-1] ; illeg + + MOV AL,[BP+AX-1] ; illeg + MOV AH,[BP+BX-1] ; illeg + MOV BL,[BP+CX-1] ; illeg + MOV BH,[BP+DX-1] ; illeg + MOV CL,[BP+BP-1] ; illeg + MOV CH,[BP+DI-1] + MOV DL,[BP+SI-1] + MOV DH,[BP+SP-1] ; illeg + + MOV AL,[DI+AX-1] ; illeg + MOV AH,[DI+BX-1] + MOV BL,[DI+CX-1] ; illeg + MOV BH,[DI+DX-1] ; illeg + MOV CL,[DI+BP-1] + MOV CH,[DI+DI-1] ; illeg + MOV DL,[DI+SI-1] ; illeg + MOV DH,[DI+SP-1] ; illeg + + MOV AL,[SI+AX-1] ; illeg + MOV AH,[SI+BX-1] + MOV BL,[SI+CX-1] ; illeg + MOV BH,[SI+DX-1] ; illeg + MOV CL,[SI+BP-1] + MOV CH,[SI+DI-1] ; illeg + MOV DL,[SI+SI-1] ; illeg + MOV DH,[SI+SP-1] ; illeg + + MOV AL,[SP+AX-1] ; illeg + MOV AH,[SP+BX-1] ; illeg + MOV BL,[SP+CX-1] ; illeg + MOV BH,[SP+DX-1] ; illeg + MOV CL,[SP+BP-1] ; illeg + MOV CH,[SP+DI-1] ; illeg + MOV DL,[SP+SI-1] ; illeg + MOV DH,[SP+SP-1] ; illeg + + MOV AL,[AX+AX+127] ; illeg + MOV AH,[AX+BX+127] ; illeg + MOV BL,[AX+CX+127] ; illeg + MOV BH,[AX+DX+127] ; illeg + MOV CL,[AX+BP+127] ; illeg + MOV CH,[AX+DI+127] ; illeg + MOV DL,[AX+SI+127] ; illeg + MOV DH,[AX+SP+127] ; illeg + + MOV AL,[BX+AX+127] ; illeg + MOV AH,[BX+BX+127] ; illeg + MOV BL,[BX+CX+127] ; illeg + MOV BH,[BX+DX+127] ; illeg + MOV CL,[BX+BP+127] ; illeg + MOV CH,[BX+DI+127] + MOV DL,[BX+SI+127] + MOV DH,[BX+SP+127] ; illeg + + MOV AL,[CX+AX+127] ; illeg + MOV AH,[CX+BX+127] ; illeg + MOV BL,[CX+CX+127] ; illeg + MOV BH,[CX+DX+127] ; illeg + MOV CL,[CX+BP+127] ; illeg + MOV CH,[CX+DI+127] ; illeg + MOV DL,[CX+SI+127] ; illeg + MOV DH,[CX+SP+127] ; illeg + + MOV AL,[DX+AX+127] ; illeg + MOV AH,[DX+BX+127] ; illeg + MOV BL,[DX+CX+127] ; illeg + MOV BH,[DX+DX+127] ; illeg + MOV CL,[DX+BP+127] ; illeg + MOV CH,[DX+DI+127] ; illeg + MOV DL,[DX+SI+127] ; illeg + MOV DH,[DX+SP+127] ; illeg + + MOV AL,[BP+AX+127] ; illeg + MOV AH,[BP+BX+127] ; illeg + MOV BL,[BP+CX+127] ; illeg + MOV BH,[BP+DX+127] ; illeg + MOV CL,[BP+BP+127] ; illeg + MOV CH,[BP+DI+127] + MOV DL,[BP+SI+127] + MOV DH,[BP+SP+127] ; illeg + + MOV AL,[DI+AX+127] ; illeg + MOV AH,[DI+BX+127] + MOV BL,[DI+CX+127] ; illeg + MOV BH,[DI+DX+127] ; illeg + MOV CL,[DI+BP+127] + MOV CH,[DI+DI+127] ; illeg + MOV DL,[DI+SI+127] ; illeg + MOV DH,[DI+SP+127] ; illeg + + MOV AL,[SI+AX+127] ; illeg + MOV AH,[SI+BX+127] + MOV BL,[SI+CX+127] ; illeg + MOV BH,[SI+DX+127] ; illeg + MOV CL,[SI+BP+127] + MOV CH,[SI+DI+127] ; illeg + MOV DL,[SI+SI+127] ; illeg + MOV DH,[SI+SP+127] ; illeg + + MOV AL,[SP+AX+127] ; illeg + MOV AH,[SP+BX+127] ; illeg + MOV BL,[SP+CX+127] ; illeg + MOV BH,[SP+DX+127] ; illeg + MOV CL,[SP+BP+127] ; illeg + MOV CH,[SP+DI+127] ; illeg + MOV DL,[SP+SI+127] ; illeg + MOV DH,[SP+SP+127] ; illeg + + MOV AL,[AX+AX-128] ; illeg + MOV AH,[AX+BX-128] ; illeg + MOV BL,[AX+CX-128] ; illeg + MOV BH,[AX+DX-128] ; illeg + MOV CL,[AX+BP-128] ; illeg + MOV CH,[AX+DI-128] ; illeg + MOV DL,[AX+SI-128] ; illeg + MOV DH,[AX+SP-128] ; illeg + + MOV AL,[BX+AX-128] ; illeg + MOV AH,[BX+BX-128] ; illeg + MOV BL,[BX+CX-128] ; illeg + MOV BH,[BX+DX-128] ; illeg + MOV CL,[BX+BP-128] ; illeg + MOV CH,[BX+DI-128] + MOV DL,[BX+SI-128] + MOV DH,[BX+SP-128] ; illeg + + MOV AL,[CX+AX-128] ; illeg + MOV AH,[CX+BX-128] ; illeg + MOV BL,[CX+CX-128] ; illeg + MOV BH,[CX+DX-128] ; illeg + MOV CL,[CX+BP-128] ; illeg + MOV CH,[CX+DI-128] ; illeg + MOV DL,[CX+SI-128] ; illeg + MOV DH,[CX+SP-128] ; illeg + + MOV AL,[DX+AX-128] ; illeg + MOV AH,[DX+BX-128] ; illeg + MOV BL,[DX+CX-128] ; illeg + MOV BH,[DX+DX-128] ; illeg + MOV CL,[DX+BP-128] ; illeg + MOV CH,[DX+DI-128] ; illeg + MOV DL,[DX+SI-128] ; illeg + MOV DH,[DX+SP-128] ; illeg + + MOV AL,[BP+AX-128] ; illeg + MOV AH,[BP+BX-128] ; illeg + MOV BL,[BP+CX-128] ; illeg + MOV BH,[BP+DX-128] ; illeg + MOV CL,[BP+BP-128] ; illeg + MOV CH,[BP+DI-128] + MOV DL,[BP+SI-128] + MOV DH,[BP+SP-128] ; illeg + + MOV AL,[DI+AX-128] ; illeg + MOV AH,[DI+BX-128] + MOV BL,[DI+CX-128] ; illeg + MOV BH,[DI+DX-128] ; illeg + MOV CL,[DI+BP-128] + MOV CH,[DI+DI-128] ; illeg + MOV DL,[DI+SI-128] ; illeg + MOV DH,[DI+SP-128] ; illeg + + MOV AL,[SI+AX-128] ; illeg + MOV AH,[SI+BX-128] + MOV BL,[SI+CX-128] ; illeg + MOV BH,[SI+DX-128] ; illeg + MOV CL,[SI+BP-128] + MOV CH,[SI+DI-128] ; illeg + MOV DL,[SI+SI-128] ; illeg + MOV DH,[SI+SP-128] ; illeg + + MOV AL,[SP+AX-128] ; illeg + MOV AH,[SP+BX-128] ; illeg + MOV BL,[SP+CX-128] ; illeg + MOV BH,[SP+DX-128] ; illeg + MOV CL,[SP+BP-128] ; illeg + MOV CH,[SP+DI-128] ; illeg + MOV DL,[SP+SI-128] ; illeg + MOV DH,[SP+SP-128] ; illeg + + MOV AL,[AX+AX+128] ; illeg + MOV AH,[AX+BX+128] ; illeg + MOV BL,[AX+CX+128] ; illeg + MOV BH,[AX+DX+128] ; illeg + MOV CL,[AX+BP+128] ; illeg + MOV CH,[AX+DI+128] ; illeg + MOV DL,[AX+SI+128] ; illeg + MOV DH,[AX+SP+128] ; illeg + + MOV AL,[BX+AX+128] ; illeg + MOV AH,[BX+BX+128] ; illeg + MOV BL,[BX+CX+128] ; illeg + MOV BH,[BX+DX+128] ; illeg + MOV CL,[BX+BP+128] ; illeg + MOV CH,[BX+DI+128] + MOV DL,[BX+SI+128] + MOV DH,[BX+SP+128] ; illeg + + MOV AL,[CX+AX+128] ; illeg + MOV AH,[CX+BX+128] ; illeg + MOV BL,[CX+CX+128] ; illeg + MOV BH,[CX+DX+128] ; illeg + MOV CL,[CX+BP+128] ; illeg + MOV CH,[CX+DI+128] ; illeg + MOV DL,[CX+SI+128] ; illeg + MOV DH,[CX+SP+128] ; illeg + + MOV AL,[DX+AX+128] ; illeg + MOV AH,[DX+BX+128] ; illeg + MOV BL,[DX+CX+128] ; illeg + MOV BH,[DX+DX+128] ; illeg + MOV CL,[DX+BP+128] ; illeg + MOV CH,[DX+DI+128] ; illeg + MOV DL,[DX+SI+128] ; illeg + MOV DH,[DX+SP+128] ; illeg + + MOV AL,[BP+AX+128] ; illeg + MOV AH,[BP+BX+128] ; illeg + MOV BL,[BP+CX+128] ; illeg + MOV BH,[BP+DX+128] ; illeg + MOV CL,[BP+BP+128] ; illeg + MOV CH,[BP+DI+128] + MOV DL,[BP+SI+128] + MOV DH,[BP+SP+128] ; illeg + + MOV AL,[DI+AX+128] ; illeg + MOV AH,[DI+BX+128] + MOV BL,[DI+CX+128] ; illeg + MOV BH,[DI+DX+128] ; illeg + MOV CL,[DI+BP+128] + MOV CH,[DI+DI+128] ; illeg + MOV DL,[DI+SI+128] ; illeg + MOV DH,[DI+SP+128] ; illeg + + MOV AL,[SI+AX+128] ; illeg + MOV AH,[SI+BX+128] + MOV BL,[SI+CX+128] ; illeg + MOV BH,[SI+DX+128] ; illeg + MOV CL,[SI+BP+128] + MOV CH,[SI+DI+128] ; illeg + MOV DL,[SI+SI+128] ; illeg + MOV DH,[SI+SP+128] ; illeg + + MOV AL,[SP+AX+128] ; illeg + MOV AH,[SP+BX+128] ; illeg + MOV BL,[SP+CX+128] ; illeg + MOV BH,[SP+DX+128] ; illeg + MOV CL,[SP+BP+128] ; illeg + MOV CH,[SP+DI+128] ; illeg + MOV DL,[SP+SI+128] ; illeg + MOV DH,[SP+SP+128] ; illeg + + MOV AL,[AX+AX-129] ; illeg + MOV AH,[AX+BX-129] ; illeg + MOV BL,[AX+CX-129] ; illeg + MOV BH,[AX+DX-129] ; illeg + MOV CL,[AX+BP-129] ; illeg + MOV CH,[AX+DI-129] ; illeg + MOV DL,[AX+SI-129] ; illeg + MOV DH,[AX+SP-129] ; illeg + + MOV AL,[BX+AX-129] ; illeg + MOV AH,[BX+BX-129] ; illeg + MOV BL,[BX+CX-129] ; illeg + MOV BH,[BX+DX-129] ; illeg + MOV CL,[BX+BP-129] ; illeg + MOV CH,[BX+DI-129] + MOV DL,[BX+SI-129] + MOV DH,[BX+SP-129] ; illeg + + MOV AL,[CX+AX-129] ; illeg + MOV AH,[CX+BX-129] ; illeg + MOV BL,[CX+CX-129] ; illeg + MOV BH,[CX+DX-129] ; illeg + MOV CL,[CX+BP-129] ; illeg + MOV CH,[CX+DI-129] ; illeg + MOV DL,[CX+SI-129] ; illeg + MOV DH,[CX+SP-129] ; illeg + + MOV AL,[DX+AX-129] ; illeg + MOV AH,[DX+BX-129] ; illeg + MOV BL,[DX+CX-129] ; illeg + MOV BH,[DX+DX-129] ; illeg + MOV CL,[DX+BP-129] ; illeg + MOV CH,[DX+DI-129] ; illeg + MOV DL,[DX+SI-129] ; illeg + MOV DH,[DX+SP-129] ; illeg + + MOV AL,[BP+AX-129] ; illeg + MOV AH,[BP+BX-129] ; illeg + MOV BL,[BP+CX-129] ; illeg + MOV BH,[BP+DX-129] ; illeg + MOV CL,[BP+BP-129] ; illeg + MOV CH,[BP+DI-129] + MOV DL,[BP+SI-129] + MOV DH,[BP+SP-129] ; illeg + + MOV AL,[DI+AX-129] ; illeg + MOV AH,[DI+BX-129] + MOV BL,[DI+CX-129] ; illeg + MOV BH,[DI+DX-129] ; illeg + MOV CL,[DI+BP-129] + MOV CH,[DI+DI-129] ; illeg + MOV DL,[DI+SI-129] ; illeg + MOV DH,[DI+SP-129] ; illeg + + MOV AL,[SI+AX-129] ; illeg + MOV AH,[SI+BX-129] + MOV BL,[SI+CX-129] ; illeg + MOV BH,[SI+DX-129] ; illeg + MOV CL,[SI+BP-129] + MOV CH,[SI+DI-129] ; illeg + MOV DL,[SI+SI-129] ; illeg + MOV DH,[SI+SP-129] ; illeg + + MOV AL,[SP+AX-129] ; illeg + MOV AH,[SP+BX-129] ; illeg + MOV BL,[SP+CX-129] ; illeg + MOV BH,[SP+DX-129] ; illeg + MOV CL,[SP+BP-129] ; illeg + MOV CH,[SP+DI-129] ; illeg + MOV DL,[SP+SI-129] ; illeg + MOV DH,[SP+SP-129] ; illeg + + MOV AL,[AX+AX+32767] ; illeg + MOV AH,[AX+BX+32767] ; illeg + MOV BL,[AX+CX+32767] ; illeg + MOV BH,[AX+DX+32767] ; illeg + MOV CL,[AX+BP+32767] ; illeg + MOV CH,[AX+DI+32767] ; illeg + MOV DL,[AX+SI+32767] ; illeg + MOV DH,[AX+SP+32767] ; illeg + + MOV AL,[BX+AX+32767] ; illeg + MOV AH,[BX+BX+32767] ; illeg + MOV BL,[BX+CX+32767] ; illeg + MOV BH,[BX+DX+32767] ; illeg + MOV CL,[BX+BP+32767] ; illeg + MOV CH,[BX+DI+32767] + MOV DL,[BX+SI+32767] + MOV DH,[BX+SP+32767] ; illeg + + MOV AL,[CX+AX+32767] ; illeg + MOV AH,[CX+BX+32767] ; illeg + MOV BL,[CX+CX+32767] ; illeg + MOV BH,[CX+DX+32767] ; illeg + MOV CL,[CX+BP+32767] ; illeg + MOV CH,[CX+DI+32767] ; illeg + MOV DL,[CX+SI+32767] ; illeg + MOV DH,[CX+SP+32767] ; illeg + + MOV AL,[DX+AX+32767] ; illeg + MOV AH,[DX+BX+32767] ; illeg + MOV BL,[DX+CX+32767] ; illeg + MOV BH,[DX+DX+32767] ; illeg + MOV CL,[DX+BP+32767] ; illeg + MOV CH,[DX+DI+32767] ; illeg + MOV DL,[DX+SI+32767] ; illeg + MOV DH,[DX+SP+32767] ; illeg + + MOV AL,[BP+AX+32767] ; illeg + MOV AH,[BP+BX+32767] ; illeg + MOV BL,[BP+CX+32767] ; illeg + MOV BH,[BP+DX+32767] ; illeg + MOV CL,[BP+BP+32767] ; illeg + MOV CH,[BP+DI+32767] + MOV DL,[BP+SI+32767] + MOV DH,[BP+SP+32767] ; illeg + + MOV AL,[DI+AX+32767] ; illeg + MOV AH,[DI+BX+32767] + MOV BL,[DI+CX+32767] ; illeg + MOV BH,[DI+DX+32767] ; illeg + MOV CL,[DI+BP+32767] + MOV CH,[DI+DI+32767] ; illeg + MOV DL,[DI+SI+32767] ; illeg + MOV DH,[DI+SP+32767] ; illeg + + MOV AL,[SI+AX+32767] ; illeg + MOV AH,[SI+BX+32767] + MOV BL,[SI+CX+32767] ; illeg + MOV BH,[SI+DX+32767] ; illeg + MOV CL,[SI+BP+32767] + MOV CH,[SI+DI+32767] ; illeg + MOV DL,[SI+SI+32767] ; illeg + MOV DH,[SI+SP+32767] ; illeg + + MOV AL,[SP+AX+32767] ; illeg + MOV AH,[SP+BX+32767] ; illeg + MOV BL,[SP+CX+32767] ; illeg + MOV BH,[SP+DX+32767] ; illeg + MOV CL,[SP+BP+32767] ; illeg + MOV CH,[SP+DI+32767] ; illeg + MOV DL,[SP+SI+32767] ; illeg + MOV DH,[SP+SP+32767] ; illeg + + MOV AL,[AX+AX-32768] ; illeg + MOV AH,[AX+BX-32768] ; illeg + MOV BL,[AX+CX-32768] ; illeg + MOV BH,[AX+DX-32768] ; illeg + MOV CL,[AX+BP-32768] ; illeg + MOV CH,[AX+DI-32768] ; illeg + MOV DL,[AX+SI-32768] ; illeg + MOV DH,[AX+SP-32768] ; illeg + + MOV AL,[BX+AX-32768] ; illeg + MOV AH,[BX+BX-32768] ; illeg + MOV BL,[BX+CX-32768] ; illeg + MOV BH,[BX+DX-32768] ; illeg + MOV CL,[BX+BP-32768] ; illeg + MOV CH,[BX+DI-32768] + MOV DL,[BX+SI-32768] + MOV DH,[BX+SP-32768] ; illeg + + MOV AL,[CX+AX-32768] ; illeg + MOV AH,[CX+BX-32768] ; illeg + MOV BL,[CX+CX-32768] ; illeg + MOV BH,[CX+DX-32768] ; illeg + MOV CL,[CX+BP-32768] ; illeg + MOV CH,[CX+DI-32768] ; illeg + MOV DL,[CX+SI-32768] ; illeg + MOV DH,[CX+SP-32768] ; illeg + + MOV AL,[DX+AX-32768] ; illeg + MOV AH,[DX+BX-32768] ; illeg + MOV BL,[DX+CX-32768] ; illeg + MOV BH,[DX+DX-32768] ; illeg + MOV CL,[DX+BP-32768] ; illeg + MOV CH,[DX+DI-32768] ; illeg + MOV DL,[DX+SI-32768] ; illeg + MOV DH,[DX+SP-32768] ; illeg + + MOV AL,[BP+AX-32768] ; illeg + MOV AH,[BP+BX-32768] ; illeg + MOV BL,[BP+CX-32768] ; illeg + MOV BH,[BP+DX-32768] ; illeg + MOV CL,[BP+BP-32768] ; illeg + MOV CH,[BP+DI-32768] + MOV DL,[BP+SI-32768] + MOV DH,[BP+SP-32768] ; illeg + + MOV AL,[DI+AX-32768] ; illeg + MOV AH,[DI+BX-32768] + MOV BL,[DI+CX-32768] ; illeg + MOV BH,[DI+DX-32768] ; illeg + MOV CL,[DI+BP-32768] + MOV CH,[DI+DI-32768] ; illeg + MOV DL,[DI+SI-32768] ; illeg + MOV DH,[DI+SP-32768] ; illeg + + MOV AL,[SI+AX-32768] ; illeg + MOV AH,[SI+BX-32768] + MOV BL,[SI+CX-32768] ; illeg + MOV BH,[SI+DX-32768] ; illeg + MOV CL,[SI+BP-32768] + MOV CH,[SI+DI-32768] ; illeg + MOV DL,[SI+SI-32768] ; illeg + MOV DH,[SI+SP-32768] ; illeg + + MOV AL,[SP+AX-32768] ; illeg + MOV AH,[SP+BX-32768] ; illeg + MOV BL,[SP+CX-32768] ; illeg + MOV BH,[SP+DX-32768] ; illeg + MOV CL,[SP+BP-32768] ; illeg + MOV CH,[SP+DI-32768] ; illeg + MOV DL,[SP+SI-32768] ; illeg + MOV DH,[SP+SP-32768] ; illeg + + MOV AL,[AX+AX+32768] ; illeg + MOV AH,[AX+BX+32768] ; illeg + MOV BL,[AX+CX+32768] ; illeg + MOV BH,[AX+DX+32768] ; illeg + MOV CL,[AX+BP+32768] ; illeg + MOV CH,[AX+DI+32768] ; illeg + MOV DL,[AX+SI+32768] ; illeg + MOV DH,[AX+SP+32768] ; illeg + + MOV AL,[BX+AX+32768] ; illeg + MOV AH,[BX+BX+32768] ; illeg + MOV BL,[BX+CX+32768] ; illeg + MOV BH,[BX+DX+32768] ; illeg + MOV CL,[BX+BP+32768] ; illeg + MOV CH,[BX+DI+32768] + MOV DL,[BX+SI+32768] + MOV DH,[BX+SP+32768] ; illeg + + MOV AL,[CX+AX+32768] ; illeg + MOV AH,[CX+BX+32768] ; illeg + MOV BL,[CX+CX+32768] ; illeg + MOV BH,[CX+DX+32768] ; illeg + MOV CL,[CX+BP+32768] ; illeg + MOV CH,[CX+DI+32768] ; illeg + MOV DL,[CX+SI+32768] ; illeg + MOV DH,[CX+SP+32768] ; illeg + + MOV AL,[DX+AX+32768] ; illeg + MOV AH,[DX+BX+32768] ; illeg + MOV BL,[DX+CX+32768] ; illeg + MOV BH,[DX+DX+32768] ; illeg + MOV CL,[DX+BP+32768] ; illeg + MOV CH,[DX+DI+32768] ; illeg + MOV DL,[DX+SI+32768] ; illeg + MOV DH,[DX+SP+32768] ; illeg + + MOV AL,[BP+AX+32768] ; illeg + MOV AH,[BP+BX+32768] ; illeg + MOV BL,[BP+CX+32768] ; illeg + MOV BH,[BP+DX+32768] ; illeg + MOV CL,[BP+BP+32768] ; illeg + MOV CH,[BP+DI+32768] + MOV DL,[BP+SI+32768] + MOV DH,[BP+SP+32768] ; illeg + + MOV AL,[DI+AX+32768] ; illeg + MOV AH,[DI+BX+32768] + MOV BL,[DI+CX+32768] ; illeg + MOV BH,[DI+DX+32768] ; illeg + MOV CL,[DI+BP+32768] + MOV CH,[DI+DI+32768] ; illeg + MOV DL,[DI+SI+32768] ; illeg + MOV DH,[DI+SP+32768] ; illeg + + MOV AL,[SI+AX+32768] ; illeg + MOV AH,[SI+BX+32768] + MOV BL,[SI+CX+32768] ; illeg + MOV BH,[SI+DX+32768] ; illeg + MOV CL,[SI+BP+32768] + MOV CH,[SI+DI+32768] ; illeg + MOV DL,[SI+SI+32768] ; illeg + MOV DH,[SI+SP+32768] ; illeg + + MOV AL,[SP+AX+32768] ; illeg + MOV AH,[SP+BX+32768] ; illeg + MOV BL,[SP+CX+32768] ; illeg + MOV BH,[SP+DX+32768] ; illeg + MOV CL,[SP+BP+32768] ; illeg + MOV CH,[SP+DI+32768] ; illeg + MOV DL,[SP+SI+32768] ; illeg + MOV DH,[SP+SP+32768] ; illeg + + MOV AL,[AX+AX-32769] ; illeg + MOV AH,[AX+BX-32769] ; illeg + MOV BL,[AX+CX-32769] ; illeg + MOV BH,[AX+DX-32769] ; illeg + MOV CL,[AX+BP-32769] ; illeg + MOV CH,[AX+DI-32769] ; illeg + MOV DL,[AX+SI-32769] ; illeg + MOV DH,[AX+SP-32769] ; illeg + + MOV AL,[BX+AX-32769] ; illeg + MOV AH,[BX+BX-32769] ; illeg + MOV BL,[BX+CX-32769] ; illeg + MOV BH,[BX+DX-32769] ; illeg + MOV CL,[BX+BP-32769] ; illeg + MOV CH,[BX+DI-32769] + MOV DL,[BX+SI-32769] + MOV DH,[BX+SP-32769] ; illeg + + MOV AL,[CX+AX-32769] ; illeg + MOV AH,[CX+BX-32769] ; illeg + MOV BL,[CX+CX-32769] ; illeg + MOV BH,[CX+DX-32769] ; illeg + MOV CL,[CX+BP-32769] ; illeg + MOV CH,[CX+DI-32769] ; illeg + MOV DL,[CX+SI-32769] ; illeg + MOV DH,[CX+SP-32769] ; illeg + + MOV AL,[DX+AX-32769] ; illeg + MOV AH,[DX+BX-32769] ; illeg + MOV BL,[DX+CX-32769] ; illeg + MOV BH,[DX+DX-32769] ; illeg + MOV CL,[DX+BP-32769] ; illeg + MOV CH,[DX+DI-32769] ; illeg + MOV DL,[DX+SI-32769] ; illeg + MOV DH,[DX+SP-32769] ; illeg + + MOV AL,[BP+AX-32769] ; illeg + MOV AH,[BP+BX-32769] ; illeg + MOV BL,[BP+CX-32769] ; illeg + MOV BH,[BP+DX-32769] ; illeg + MOV CL,[BP+BP-32769] ; illeg + MOV CH,[BP+DI-32769] + MOV DL,[BP+SI-32769] + MOV DH,[BP+SP-32769] ; illeg + + MOV AL,[DI+AX-32769] ; illeg + MOV AH,[DI+BX-32769] + MOV BL,[DI+CX-32769] ; illeg + MOV BH,[DI+DX-32769] ; illeg + MOV CL,[DI+BP-32769] + MOV CH,[DI+DI-32769] ; illeg + MOV DL,[DI+SI-32769] ; illeg + MOV DH,[DI+SP-32769] ; illeg + + MOV AL,[SI+AX-32769] ; illeg + MOV AH,[SI+BX-32769] + MOV BL,[SI+CX-32769] ; illeg + MOV BH,[SI+DX-32769] ; illeg + MOV CL,[SI+BP-32769] + MOV CH,[SI+DI-32769] ; illeg + MOV DL,[SI+SI-32769] ; illeg + MOV DH,[SI+SP-32769] ; illeg + + MOV AL,[SP+AX-32769] ; illeg + MOV AH,[SP+BX-32769] ; illeg + MOV BL,[SP+CX-32769] ; illeg + MOV BH,[SP+DX-32769] ; illeg + MOV CL,[SP+BP-32769] ; illeg + MOV CH,[SP+DI-32769] ; illeg + MOV DL,[SP+SI-32769] ; illeg + MOV DH,[SP+SP-32769] ; illeg + + MOV AL,[AX+AX+$7FFFFFFF] ; illeg + MOV AH,[AX+BX+$7FFFFFFF] ; illeg + MOV BL,[AX+CX+$7FFFFFFF] ; illeg + MOV BH,[AX+DX+$7FFFFFFF] ; illeg + MOV CL,[AX+BP+$7FFFFFFF] ; illeg + MOV CH,[AX+DI+$7FFFFFFF] ; illeg + MOV DL,[AX+SI+$7FFFFFFF] ; illeg + MOV DH,[AX+SP+$7FFFFFFF] ; illeg + + MOV AL,[BX+AX+$7FFFFFFF] ; illeg + MOV AH,[BX+BX+$7FFFFFFF] ; illeg + MOV BL,[BX+CX+$7FFFFFFF] ; illeg + MOV BH,[BX+DX+$7FFFFFFF] ; illeg + MOV CL,[BX+BP+$7FFFFFFF] ; illeg + MOV CH,[BX+DI+$7FFFFFFF] ; illeg (bounds) + MOV DL,[BX+SI+$7FFFFFFF] ; illeg (bounds) + MOV DH,[BX+SP+$7FFFFFFF] ; illeg + + MOV AL,[CX+AX+$7FFFFFFF] ; illeg + MOV AH,[CX+BX+$7FFFFFFF] ; illeg + MOV BL,[CX+CX+$7FFFFFFF] ; illeg + MOV BH,[CX+DX+$7FFFFFFF] ; illeg + MOV CL,[CX+BP+$7FFFFFFF] ; illeg + MOV CH,[CX+DI+$7FFFFFFF] ; illeg + MOV DL,[CX+SI+$7FFFFFFF] ; illeg + MOV DH,[CX+SP+$7FFFFFFF] ; illeg + + MOV AL,[DX+AX+$7FFFFFFF] ; illeg + MOV AH,[DX+BX+$7FFFFFFF] ; illeg + MOV BL,[DX+CX+$7FFFFFFF] ; illeg + MOV BH,[DX+DX+$7FFFFFFF] ; illeg + MOV CL,[DX+BP+$7FFFFFFF] ; illeg + MOV CH,[DX+DI+$7FFFFFFF] ; illeg + MOV DL,[DX+SI+$7FFFFFFF] ; illeg + MOV DH,[DX+SP+$7FFFFFFF] ; illeg + + MOV AL,[BP+AX+$7FFFFFFF] ; illeg + MOV AH,[BP+BX+$7FFFFFFF] ; illeg + MOV BL,[BP+CX+$7FFFFFFF] ; illeg + MOV BH,[BP+DX+$7FFFFFFF] ; illeg + MOV CL,[BP+BP+$7FFFFFFF] ; illeg + MOV CH,[BP+DI+$7FFFFFFF] ; illeg (bounds) + MOV DL,[BP+SI+$7FFFFFFF] ; illeg (bounds) + MOV DH,[BP+SP+$7FFFFFFF] ; illeg + + MOV AL,[DI+AX+$7FFFFFFF] ; illeg + MOV AH,[DI+BX+$7FFFFFFF] ; illeg (bounds) + MOV BL,[DI+CX+$7FFFFFFF] ; illeg + MOV BH,[DI+DX+$7FFFFFFF] ; illeg + MOV CL,[DI+BP+$7FFFFFFF] ; illeg (bounds) + MOV CH,[DI+DI+$7FFFFFFF] ; illeg + MOV DL,[DI+SI+$7FFFFFFF] ; illeg + MOV DH,[DI+SP+$7FFFFFFF] ; illeg + + MOV AL,[SI+AX+$7FFFFFFF] ; illeg + MOV AH,[SI+BX+$7FFFFFFF] ; illeg (bounds) + MOV BL,[SI+CX+$7FFFFFFF] ; illeg + MOV BH,[SI+DX+$7FFFFFFF] ; illeg + MOV CL,[SI+BP+$7FFFFFFF] ; illeg (bounds) + MOV CH,[SI+DI+$7FFFFFFF] ; illeg + MOV DL,[SI+SI+$7FFFFFFF] ; illeg + MOV DH,[SI+SP+$7FFFFFFF] ; illeg + + MOV AL,[SP+AX+$7FFFFFFF] ; illeg + MOV AH,[SP+BX+$7FFFFFFF] ; illeg + MOV BL,[SP+CX+$7FFFFFFF] ; illeg + MOV BH,[SP+DX+$7FFFFFFF] ; illeg + MOV CL,[SP+BP+$7FFFFFFF] ; illeg + MOV CH,[SP+DI+$7FFFFFFF] ; illeg + MOV DL,[SP+SI+$7FFFFFFF] ; illeg + MOV DH,[SP+SP+$7FFFFFFF] ; illeg + + MOV AL,[AX+AX-$80000000] ; illeg + MOV AH,[AX+BX-$80000000] ; illeg + MOV BL,[AX+CX-$80000000] ; illeg + MOV BH,[AX+DX-$80000000] ; illeg + MOV CL,[AX+BP-$80000000] ; illeg + MOV CH,[AX+DI-$80000000] ; illeg + MOV DL,[AX+SI-$80000000] ; illeg + MOV DH,[AX+SP-$80000000] ; illeg + + MOV AL,[BX+AX-$80000000] ; illeg + MOV AH,[BX+BX-$80000000] ; illeg + MOV BL,[BX+CX-$80000000] ; illeg + MOV BH,[BX+DX-$80000000] ; illeg + MOV CL,[BX+BP-$80000000] ; illeg + MOV CH,[BX+DI-$80000000] ; illeg (bounds) + MOV DL,[BX+SI-$80000000] ; illeg (bounds) + MOV DH,[BX+SP-$80000000] ; illeg + + MOV AL,[CX+AX-$80000000] ; illeg + MOV AH,[CX+BX-$80000000] ; illeg + MOV BL,[CX+CX-$80000000] ; illeg + MOV BH,[CX+DX-$80000000] ; illeg + MOV CL,[CX+BP-$80000000] ; illeg + MOV CH,[CX+DI-$80000000] ; illeg + MOV DL,[CX+SI-$80000000] ; illeg + MOV DH,[CX+SP-$80000000] ; illeg + + MOV AL,[DX+AX-$80000000] ; illeg + MOV AH,[DX+BX-$80000000] ; illeg + MOV BL,[DX+CX-$80000000] ; illeg + MOV BH,[DX+DX-$80000000] ; illeg + MOV CL,[DX+BP-$80000000] ; illeg + MOV CH,[DX+DI-$80000000] ; illeg + MOV DL,[DX+SI-$80000000] ; illeg + MOV DH,[DX+SP-$80000000] ; illeg + + MOV AL,[BP+AX-$80000000] ; illeg + MOV AH,[BP+BX-$80000000] ; illeg + MOV BL,[BP+CX-$80000000] ; illeg + MOV BH,[BP+DX-$80000000] ; illeg + MOV CL,[BP+BP-$80000000] ; illeg + MOV CH,[BP+DI-$80000000] ; illeg (bounds) + MOV DL,[BP+SI-$80000000] ; illeg (bounds) + MOV DH,[BP+SP-$80000000] ; illeg + + MOV AL,[DI+AX-$80000000] ; illeg + MOV AH,[DI+BX-$80000000] ; illeg (bounds) + MOV BL,[DI+CX-$80000000] ; illeg + MOV BH,[DI+DX-$80000000] ; illeg + MOV CL,[DI+BP-$80000000] ; illeg (bounds) + MOV CH,[DI+DI-$80000000] ; illeg + MOV DL,[DI+SI-$80000000] ; illeg + MOV DH,[DI+SP-$80000000] ; illeg + + MOV AL,[SI+AX-$80000000] ; illeg + MOV AH,[SI+BX-$80000000] ; illeg (bounds) + MOV BL,[SI+CX-$80000000] ; illeg + MOV BH,[SI+DX-$80000000] ; illeg + MOV CL,[SI+BP-$80000000] ; illeg (bounds) + MOV CH,[SI+DI-$80000000] ; illeg + MOV DL,[SI+SI-$80000000] ; illeg + MOV DH,[SI+SP-$80000000] ; illeg + + MOV AL,[SP+AX-$80000000] ; illeg + MOV AH,[SP+BX-$80000000] ; illeg + MOV BL,[SP+CX-$80000000] ; illeg + MOV BH,[SP+DX-$80000000] ; illeg + MOV CL,[SP+BP-$80000000] ; illeg + MOV CH,[SP+DI-$80000000] ; illeg + MOV DL,[SP+SI-$80000000] ; illeg + MOV DH,[SP+SP-$80000000] ; illeg diff --git a/bin86-0.3/as/asm/f.asm b/bin86-0.3/as/asm/f.asm new file mode 100644 index 0000000..c067bf9 --- /dev/null +++ b/bin86-0.3/as/asm/f.asm @@ -0,0 +1,114 @@ +; [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] + fadd qword [ebx] + fadd dword [ebx] + fadd st,st(1) + fadd st(1),st + fdiv qword [ebx] + fdiv dword [ebx] + fdiv st,st(1) ; special swapping for this + +; [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st + faddp st(1),st + +; [fbld fbstp] mem10r + fbld tbyte [ebx] + fbstp tbyte [ebx] + +; [fcom fcomp] [mem4r mem8r optional-st(i)] + fcom dword [ebx] + fcom qword [ebx] + fcom + fcom st(1) + +; ffree st(i) + ffree st(1) + +; [fucom fucomp fxch] optional-st(i) + fucom + fucom st(1) + +; [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] + fiadd word [ebx] + fiadd dword [ebx] + +; [fild fistp] [mem2i mem4i mem8i] + fild word [ebx] + fild dword [ebx] + fild qword [ebx] + +; [fld fstp] [mem4r mem8r mem10r st(i)] + fld dword [ebx] + fld qword [ebx] + fld tbyte [ebx] + fld st(1) + +; [fldcw fnstcw] mem2i + fldcw word [ebx] + fnstcw word [ebx] + +; [fldenv fnsave fnstenv frstor] mem + fldenv [ebx] + fnsave [ebx] + fnstenv [ebx] + frstor [ebx] + +; fnstsw [mem2i ax] + fnstsw word [ebx] + fnstsw ax + +; fst [mem4r mem8r st(i)] + fst dword [ebx] + fst qword [ebx] + fst st(1) + +; fstcw mem2i (wait) + fstcw word [ebx] + +; fstsw [mem2i ax] (wait) + fstsw word [ebx] + fstsw ax + +; [fsave fstenv] mem (wait) + fsave [ebx] + fstenv [ebx] + +; [fxxx] (no operands) + fnop ; D9D0 + fchs ; D9E0 + fabs ; D9E1 + ftst ; D9E4 + fxam ; D9E5 + fld1 ; D9E8 + fldl2t ; D9E9 + fldl2e ; D9EA + fldpi ; D9EB + fldlg2 ; D9EC + fldln2 ; D9ED + fldz ; D9EE + f2xm1 ; D9F0 + fyl2x ; D9F1 + fptan ; D9F2 + fpatan ; D9F3 + fxtract ; D9F4 + fprem1 ; D9F5 + fdecstp ; D9F6 + fincstp ; D9F7 + fprem ; D9F8 + fyl2xp1 ; D9F9 + fsqrt ; D9FA + fsincos ; D9FB + frndint ; D9FC + fscale ; D9FD + fsin ; D9FE + fcos ; D9FF + fucompp ; DAE9 + feni ; 9BDBE0 + fneni ; DBE0 + fdisi ; 9BDBE1 + fndisi ; DBE1 + fclex ; 9BDBE2 + fnclex ; DBE2 + finit ; 9BDBE3 + fninit ; DBE3 + fsetpm ; DBE4 + fcompp ; DED9 diff --git a/bin86-0.3/as/asm/fadd.asm b/bin86-0.3/as/asm/fadd.asm new file mode 100644 index 0000000..d18f002 --- /dev/null +++ b/bin86-0.3/as/asm/fadd.asm @@ -0,0 +1,271 @@ +_fadd: + PUSH BP + MOV BP,SP + MOV EAX,DWORD PTR [BP+4] + MOV EDX,DWORD PTR [BP+8] + MOV EBX,DWORD PTR [BP+12] + MOV ECX,DWORD PTR [BP+16] + CALL faddfxfy + MOV DWORD PTR _facc,EAX + MOV DWORD PTR _facc+4,EDX + POP BP + RET + +fsubfxfy: + XOR ECX,#$80000000 ; complement sign bit, fall into add routine +faddfxfy: + PUSH EBP + PUSH EDI + PUSH ESI + MOV EDI,ECX ; free CL for shifts + MOV ESI,EDX ; this mainly for consistent naming + AND ESI,#$7FFFFFFF ; discard sign so comparison is simple + AND EDI,#$7FFFFFFF + + CMP ESI,EDI + JA XBIG + JB SWAP + CMP EAX,EBX + JAE XBIG +SWAP: + XCHG EDX,ECX + XCHG ESI,EDI + XCHG EAX,EBX +XBIG: + AND ESI,#$000FFFFF ; discard exponent + AND EDI,#$000FFFFF + OR ESI,#$00100000 ; normalize + OR EDI,#$00100000 + + SHR ECX,32-(1+11) + SHR EDX,32-(1+11) + MOV EBP,ECX ; prepare to compare signs (want high bits 0) + SUB CX,DX ; get difference of signs in CX + NEG CX ; D holds sign and exponent of both throughout + CMP CX,#(64-11)+2 + JAE TO_DONE1 ; x dominates y + XOR BP,DX + AND BP,#$0800 ; see if signs are same + JNZ TO_SUBTRACT ; else roundoff reg EBP is 0 + + CMP CL,#32 + JAE TO_ADD_BIGSHIFT + SHRD EBP,EBX,CL + SHRD EBX,EDI,CL + SHR EDI,CL + ADD EAX,EBX + ADC ESI,EDI + SUB EBX,EBX + +; result DX(1+11):SI:AX:BP:BX but needs normalization + +NORMALIZE: + MOV CX,DX + AND CX,#$07FF + TEST ESI,#$00200000 + JZ NORMALIZE2 + BR LOVERFLOW + +TO_DONE1: + JMP DONE1 + +TO_SUBTRACT: + BR SUBTRACT + +TO_ADD_BIGSHIFT: + BR ADD_BIGSHIFT + +TO_NORMLITTLE: + BR NORMLITTLE + +; result DX(1):CX(11):SI:AX:BP:BX + +NORMALIZE2: + SHRD EDI,ESI,32-11 + ; top 11 bits of ESI known 0 and BSR is slooow + BSR EDI,EDI ; index of leading 1 bit in EDI is 11..31 in DI + JZ TO_NORMLITTLE ; ESI is zero (flag wrong in Intel Manual) + SUB DI,#31 + NEG DI + PUSH CX ; gr + MOV CX,DI ; rr + SHLD ESI,EAX,CL + SHLD EAX,EBP,CL + SHLD EBP,EBX,CL + SHL EBX,CL + POP CX ; rr + SUB CX,DI + JC UNDERFLOW + +ROUND: + CMP EBP,#$80000000 ; test roundoff register + JA ROUNDUP + JB DONE ; no rounding + TEST EBX,EBX + JNZ ROUNDUP + TEST AL,#1 ; ambiguous case, round to even + JZ DONE ; even, no rounding +ROUNDUP: + ADD EAX,#1 + ADC ESI,#0 + SUB EBP,EBP + SUB EBX,EBX + TEST ESI,#$00200000 + JNZ LOVERFLOW ; rounding may cause overflow! + +DONE: + AND DX,#$0800 ; extract sign of largest and result + OR DX,CX ; include exponent with sign +DONE1: + SHL EDX,32-(1+11) + AND ESI,#$000FFFFF ; discard normalization bit + OR EDX,ESI + POP ESI + POP EDI + POP EBP + RET + +UNDERFLOW: ; should have error message here +ANSWER0: + SUB EDX,EDX + MOV EAX,EDX + POP ESI + POP EDI + POP EBP + RET + +LOVERFLOW: ; carry bit must be right-shifted back in + SHR ESI,1 + RCR EAX,1 + RCR EBP,1 + RCR EBX,1 + INC CX + CMP CX,#$0800 + JNZ ROUND + +OVERFLOW: ; should have error message here + MOV EDX,#$FFE00000 ; + infinity + SUB EAX,EAX + POP ESI + POP EDI + POP EBP + RET + +ADD_BIGSHIFT: + SUB CL,#32 + SHRD EBP,EBX,CL + SHRD EBX,EDI,CL + SHR EDI,CL + ADD EAX,EDI + ADC ESI,#0 + XCHG EBP,EBX + BR NORMALIZE + +NORMLITTLE: + SHLD ESI,EAX,32-(1+11) + SHLD EAX,EBP,32-(1+11) + SHLD EBP,EBX,32-(1+11) + SHL EBX,20 + SUB CL,#32-(1+11) + JC UNDERFLOW + BR NORMALIZE2 + +SUBTRACT: + SUB EBP,EBP ; set up roundoff register + CMP CL,#32 + JAE SUBTRACT_BIGSHIFT + SHRD EBP,EBX,CL + SHRD EBX,EDI,CL + SHR EDI,CL + NEG EBP + SBB EAX,EBX + SBB ESI,EDI + SUB EBX,EBX + MOV CX,DX + AND CX,#$07FF + BR NORMALIZE2 + +SUBTRACT_BIGSHIFT: + SUB CL,#32 + SHRD EBP,EBX,CL + SHRD EBX,EDI,CL + SHR EDI,CL + NEG EBX + NEG EBP + SBB EBX,#0 + SBB EAX,EDI + SBB ESI,#0 + XCHG EBP,EBX + MOV CX,DX + AND CX,#$07FF + BR NORMALIZE2 + +TO_ANSWER0: + BR ANSWER0 + +TO_OVERFLOW: + JMP TO_OVERFLOW + +TO_UNDERFLOW: + BR UNDERFLOW + +fmulfxfy: + PUSH EBP + PUSH EDI + PUSH ESI + MOV ESI,EDX ; free DX for multiplications + MOV EDI,ECX ; this mainly for consistent naming + SHR EDX,32-(1+11) + SHR ECX,32-(1+11) + MOV BP,DX + XOR BP,CX + AND BP,#$0800 ; extract sign + AND DX,#$07FF ; exp(x) + JZ TO_ANSWER0 + AND CX,#$07FF ; exp(y) + JZ TO_ANSWER0 + ADD CX,DX + SUB CX,#$0400 + JB TO_UNDERFLOW + CMP CX,#$07FF + JA TO_OVERFLOW ; probably not quite right + + AND ESI,#$000FFFFF ; discard sign and exponent + AND EDI,#$000FFFFF + OR ESI,#$00100000 ; normalize + OR EDI,#$00100000 + +; exponent is in CX, sign in BP, operands in ESI:EAX and EDI:EBX, DX is free +; product to go in ESI:EAX:EBP:EBX +; terminology: x * y = (x32:x0) * (y32:y0) = x32y32 + x32y0 + x0y32 +x0y0 + + PUSH CX + PUSH BP + MOV ECX,EAX + MUL EBX ; x0y0 + MOV EBP,EDX ; x0y0.high in EBP + XCHG EBX,EAX ; x0y0.low in EBX (final), y0 in EAX + MUL ESI ; x32y0 + PUSH EAX ; x32y0.low on stack + PUSH EDX ; x32y0.high on stack + MOV EAX,ESI + MUL EDI ; x32y32 + MOV ESI,EDX ; x32y32.high in ESI (final except carries) + XCHG ECX,EAX ; x32y32.low in ECX, x0 in EAX + MUL EDI ; x0y32 + + ADD EBP,EAX ; x0y0.high + x0y32.low + POP EAX ; x32y0.high + ADC EAX,EDX ; x32y0.high + x0y32.high + ADC ESI,#0 + POP EDX ; x32y0.low + ADD EBP,EDX ; (x0y0.high + x0y32.low) + x32y0.low + ADC EAX,ECX ; (x32y0.high + x0y32.high) + x32y32.low + ADC ESI,#0 + POP DX ; sign + POP CX ; exponent + ADD CX,#13 ; temp fixup + BR NORMALIZE2 + +_facc: + .word 0,0 diff --git a/bin86-0.3/as/asm/farcall.asm b/bin86-0.3/as/asm/farcall.asm new file mode 100644 index 0000000..6a779d9 --- /dev/null +++ b/bin86-0.3/as/asm/farcall.asm @@ -0,0 +1,10 @@ +call 1:2 +call far [1] +use32 +call far [1] + +use16 +jmp 1:2 +jmp far [1] +use32 +jmp far [1] diff --git a/bin86-0.3/as/asm/group1.asm b/bin86-0.3/as/asm/group1.asm new file mode 100644 index 0000000..fe2fb45 --- /dev/null +++ b/bin86-0.3/as/asm/group1.asm @@ -0,0 +1,31 @@ + ADD AL,#3 + ADD AX,#$1234 + ADD EAX,#$12345678 + ADD BL,#3 + ADD BX,#$1234 + ADD EBX,#$12345678 + ADD BYTE [BX],#3 + ADD BYTE 3[BX],#4 + ADD BYTE [BX+SI],#4 + ADD WORD [BX],#$1234 + ADD DWORD [BX],#$12345678 + ADD BYTE [BX],#3 + ADD WORD [BX],#-3 + ADD DWORD [BX],#-3 + ADD CL,BL + ADD CX,BX + ADD ECX,EBX + ADD [BX],CL + ADD [BX],CX + ADD [BX],ECX + ADD CL,[BX] + ADD CX,[BX] + ADD ECX,[BX] + + ADC CL,BL + AND CL,BL + CMP CL,BL + OR CL,BL + SUB CL,BL + SBB CL,BL + XOR CL,BL diff --git a/bin86-0.3/as/asm/group6.asm b/bin86-0.3/as/asm/group6.asm new file mode 100644 index 0000000..f742672 --- /dev/null +++ b/bin86-0.3/as/asm/group6.asm @@ -0,0 +1,24 @@ +; group6.asm +; 0F 00 /nnn + +; LLDT r/m16 nnn = 010 +; LTR r/m16 nnn = 011 +; SLDT r/m16 nnn = 000 +; STR r/m16 nnn = 001 +; VERR r/m16 nnn = 100 +; VERW r/m16 nnn = 101 + + LLDT AL ; illeg size + LLDT EAX ; illeg size + LLDT WORD $1234 ; immed not allowed + LLDT DS ; segreg not allowed + + LLDT AX + LLDT [BX] + LLDT [EAX] + + LTR BX + SLDT [BP] + STR [EBX] + VERR CX + VERW [SI] diff --git a/bin86-0.3/as/asm/group7.asm b/bin86-0.3/as/asm/group7.asm new file mode 100644 index 0000000..0df497c --- /dev/null +++ b/bin86-0.3/as/asm/group7.asm @@ -0,0 +1,34 @@ +; group7.asm +; 0F 01 /nnn + +; INVLPG m nnn = 111 +; LGDT m16&32 nnn = 010 +; LIDT m16&32 nnn = 011 +; LMSW r/m16 nnn = 110 +; SGDT m nnn = 000 +; SIDT m nnn = 001 +; SMSW r/m16 nnn = 100 + + LGDT EAX ; register not allowed + LGDT #$1234 ; immed not allowed + LGDT WORD PTR [BX] ; illegal size + + LGDT [BX] + LGDT PWORD PTR [BX] + LGDT FWORD PTR [BX] + LGDT [EAX] + + INVLPG [EDI] + SGDT [BP] + SIDT [EBX] + + LMSW AL ; illeg size + LMSW EAX ; illeg size + LMSW #$1234 ; immed not allowed + LMSW DS ; segreg not allowed + + LMSW AX + LMSW [BX] + LMSW [EAX] + + SMSW BX diff --git a/bin86-0.3/as/asm/imul.asm b/bin86-0.3/as/asm/imul.asm new file mode 100644 index 0000000..e2772c2 --- /dev/null +++ b/bin86-0.3/as/asm/imul.asm @@ -0,0 +1,33 @@ + use32 + + imul bl + imul byte ptr [esi] + imul bx + imul word ptr [esi] + imul ebx + imul dword ptr [esi] + + imul ax,bx + imul ax,[esi] + imul eax,ebx + imul eax,[esi] + + imul ax,bx,22 + imul ax,[esi],22 + imul eax,ebx,22 + imul eax,[esi],22 + + imul ax,[22] + imul eax,[22] + imul ax,#22 + imul eax,#22 + + imul ax,bx,300 + imul ax,[esi],300 + imul eax,ebx,300000 + imul eax,[esi],300000 + + imul ax,[300] + imul eax,[300000] + imul ax,#300 + imul eax,#300000 diff --git a/bin86-0.3/as/asm/incdec.asm b/bin86-0.3/as/asm/incdec.asm new file mode 100644 index 0000000..573861c --- /dev/null +++ b/bin86-0.3/as/asm/incdec.asm @@ -0,0 +1,83 @@ + INC AL + INC AH + INC BL + INC BH + INC CL + INC CH + INC DL + INC DH + INC #1 ; illeg + INC BYTE #1 ; illeg + INC [BX] ; illeg + INC BYTE [BX] + + INC AX + INC BX + INC CX + INC DX + INC SP + INC BP + INC SI + INC DI + INC CS ; illeg + INC DS ; illeg + INC ES ; illeg + INC FS ; illeg + INC GS ; illeg + INC #$1234 ; illeg + INC WORD #$1234 ; illeg + INC WORD [BX] + + INC EAX + INC EBX + INC ECX + INC EDX + INC ESP + INC EBP + INC ESI + INC EDI + INC #$12345678 ; illeg + INC DWORD #$12345678 ; illeg + INC DWORD [BX] + + DEC AL + DEC AH + DEC BL + DEC BH + DEC CL + DEC CH + DEC DL + DEC DH + DEC #1 ; illeg + DEC BYTE #1 ; illeg + DEC [BX] ; illeg + DEC BYTE [BX] + + DEC AX + DEC BX + DEC CX + DEC DX + DEC SP + DEC BP + DEC SI + DEC DI + DEC CS ; illeg + DEC DS ; illeg + DEC ES ; illeg + DEC FS ; illeg + DEC GS ; illeg + DEC #$1234 ; illeg + DEC WORD #$1234 ; illeg + DEC WORD [BX] + + DEC EAX + DEC EBX + DEC ECX + DEC EDX + DEC ESP + DEC EBP + DEC ESI + DEC EDI + DEC #$12345678 ; illeg + DEC DWORD #$12345678 ; illeg + DEC DWORD [BX] diff --git a/bin86-0.3/as/asm/inher.asm b/bin86-0.3/as/asm/inher.asm new file mode 100644 index 0000000..f1343fa --- /dev/null +++ b/bin86-0.3/as/asm/inher.asm @@ -0,0 +1,127 @@ +; INHER.ASM + +; INHER opcodes + + AAA + AAS + + CLC + CLD + CLI + CLTS + CMC + CMPSB + + DAA + DAS + + HLT + + INTO + INSB + + LAHF + LEAVE + LOCK + LODSB + + MOVSB + + NOP + + OUTSB + + REP + REPE + REPNE + + SAHF + SCASB + STC + STD + STI + STOSB + + WAIT + +; INHER16 and INHER32 opcodes + + USE16 + + CBW + CWD + CWDE + CDQ + CMPSW + CMPSD + + INSW + INSD + IRET + IRETD + + LODSW + LODSD + + MOVSW + MOVSD + + OUTSW + OUTSD + + POPA + POPAD + POPF + POPFD + PUSHA + PUSHAD + PUSHF + PUSHFD + + SCASW + SCASD + STOSW + STOSW + + XLAT + XLATB + + USE32 + + CBW + CWD + CWDE + CDQ + CMPSW + CMPSD + + INSW + INSD + IRET + IRETD + + LODSW + LODSD + + MOVSW + MOVSD + + OUTSW + OUTSD + + POPA + POPAD + POPF + POPFD + PUSHA + PUSHAD + PUSHF + PUSHFD + + SCASW + SCASD + STOSW + STOSW + + XLAT + XLATB diff --git a/bin86-0.3/as/asm/inout.asm b/bin86-0.3/as/asm/inout.asm new file mode 100644 index 0000000..3f0a3f2 --- /dev/null +++ b/bin86-0.3/as/asm/inout.asm @@ -0,0 +1,25 @@ + IN EAX,DX ; plain IN is no longer allowed + INB + IN AL,DX + INW + IN AX,DX + IN EAX,DX + IN AL,$20 + IN AL,$101 + IN AX,$20 + IN AX,$101 + IN EAX,$20 + IN EAX,$101 + + OUTB DX,EAX ; plain OUT is no longer allowed + OUTB + OUT DX,AL + OUTW + OUT DX,AX + OUT DX,EAX + OUT $20,AL + OUT $101,AL + OUT $20,AX + OUT #101,AX + OUT $20,EAX + OUT $101,EAX diff --git a/bin86-0.3/as/asm/movspec.asm b/bin86-0.3/as/asm/movspec.asm new file mode 100644 index 0000000..a4f9c15 --- /dev/null +++ b/bin86-0.3/as/asm/movspec.asm @@ -0,0 +1,246 @@ +mov eax,cr0 +mov eax,cr2 +mov eax,cr3 +mov eax,dr0 +mov eax,dr1 +mov eax,dr2 +mov eax,dr3 +mov eax,dr6 +mov eax,dr7 +mov eax,tr3 +mov eax,tr4 +mov eax,tr5 +mov eax,tr6 +mov eax,tr7 + +mov cr0,eax +mov cr2,eax +mov cr3,eax +mov dr0,eax +mov dr1,eax +mov dr2,eax +mov dr3,eax +mov dr6,eax +mov dr7,eax +mov tr3,eax +mov tr4,eax +mov tr5,eax +mov tr6,eax +mov tr7,eax + + +mov ebx,cr0 +mov ebx,cr2 +mov ebx,cr3 +mov ebx,dr0 +mov ebx,dr1 +mov ebx,dr2 +mov ebx,dr3 +mov ebx,dr6 +mov ebx,dr7 +mov ebx,tr3 +mov ebx,tr4 +mov ebx,tr5 +mov ebx,tr6 +mov ebx,tr7 + +mov cr0,ebx +mov cr2,ebx +mov cr3,ebx +mov dr0,ebx +mov dr1,ebx +mov dr2,ebx +mov dr3,ebx +mov dr6,ebx +mov dr7,ebx +mov tr3,ebx +mov tr4,ebx +mov tr5,ebx +mov tr6,ebx +mov tr7,ebx + + +mov ecx,cr0 +mov ecx,cr2 +mov ecx,cr3 +mov ecx,dr0 +mov ecx,dr1 +mov ecx,dr2 +mov ecx,dr3 +mov ecx,dr6 +mov ecx,dr7 +mov ecx,tr3 +mov ecx,tr4 +mov ecx,tr5 +mov ecx,tr6 +mov ecx,tr7 + +mov cr0,ecx +mov cr2,ecx +mov cr3,ecx +mov dr0,ecx +mov dr1,ecx +mov dr2,ecx +mov dr3,ecx +mov dr6,ecx +mov dr7,ecx +mov tr3,ecx +mov tr4,ecx +mov tr5,ecx +mov tr6,ecx +mov tr7,ecx + + +mov edx,cr0 +mov edx,cr2 +mov edx,cr3 +mov edx,dr0 +mov edx,dr1 +mov edx,dr2 +mov edx,dr3 +mov edx,dr6 +mov edx,dr7 +mov edx,tr3 +mov edx,tr4 +mov edx,tr5 +mov edx,tr6 +mov edx,tr7 + +mov cr0,edx +mov cr2,edx +mov cr3,edx +mov dr0,edx +mov dr1,edx +mov dr2,edx +mov dr3,edx +mov dr6,edx +mov dr7,edx +mov tr3,edx +mov tr4,edx +mov tr5,edx +mov tr6,edx +mov tr7,edx + + +mov esi,cr0 +mov esi,cr2 +mov esi,cr3 +mov esi,dr0 +mov esi,dr1 +mov esi,dr2 +mov esi,dr3 +mov esi,dr6 +mov esi,dr7 +mov esi,tr3 +mov esi,tr4 +mov esi,tr5 +mov esi,tr6 +mov esi,tr7 + +mov cr0,esi +mov cr2,esi +mov cr3,esi +mov dr0,esi +mov dr1,esi +mov dr2,esi +mov dr3,esi +mov dr6,esi +mov dr7,esi +mov tr3,esi +mov tr4,esi +mov tr5,esi +mov tr6,esi +mov tr7,esi + + +mov edi,cr0 +mov edi,cr2 +mov edi,cr3 +mov edi,dr0 +mov edi,dr1 +mov edi,dr2 +mov edi,dr3 +mov edi,dr6 +mov edi,dr7 +mov edi,tr3 +mov edi,tr4 +mov edi,tr5 +mov edi,tr6 +mov edi,tr7 + +mov cr0,edi +mov cr2,edi +mov cr3,edi +mov dr0,edi +mov dr1,edi +mov dr2,edi +mov dr3,edi +mov dr6,edi +mov dr7,edi +mov tr3,edi +mov tr4,edi +mov tr5,edi +mov tr6,edi +mov tr7,edi + + +mov esp,cr0 +mov esp,cr2 +mov esp,cr3 +mov esp,dr0 +mov esp,dr1 +mov esp,dr2 +mov esp,dr3 +mov esp,dr6 +mov esp,dr7 +mov esp,tr3 +mov esp,tr4 +mov esp,tr5 +mov esp,tr6 +mov esp,tr7 + +mov cr0,esp +mov cr2,esp +mov cr3,esp +mov dr0,esp +mov dr1,esp +mov dr2,esp +mov dr3,esp +mov dr6,esp +mov dr7,esp +mov tr3,esp +mov tr4,esp +mov tr5,esp +mov tr6,esp +mov tr7,esp + + +mov ebp,cr0 +mov ebp,cr2 +mov ebp,cr3 +mov ebp,dr0 +mov ebp,dr1 +mov ebp,dr2 +mov ebp,dr3 +mov ebp,dr6 +mov ebp,dr7 +mov ebp,tr3 +mov ebp,tr4 +mov ebp,tr5 +mov ebp,tr6 +mov ebp,tr7 + +mov cr0,ebp +mov cr2,ebp +mov cr3,ebp +mov dr0,ebp +mov dr1,ebp +mov dr2,ebp +mov dr3,ebp +mov dr6,ebp +mov dr7,ebp +mov tr3,ebp +mov tr4,ebp +mov tr5,ebp +mov tr6,ebp +mov tr7,ebp diff --git a/bin86-0.3/as/asm/pushpop.asm b/bin86-0.3/as/asm/pushpop.asm new file mode 100644 index 0000000..b45117a --- /dev/null +++ b/bin86-0.3/as/asm/pushpop.asm @@ -0,0 +1,86 @@ + PUSH AL ; illeg + PUSH AH ; illeg + PUSH BL ; illeg + PUSH BH ; illeg + PUSH CL ; illeg + PUSH CH ; illeg + PUSH DL ; illeg + PUSH DH ; illeg + PUSH #1 ; illeg + PUSH BYTE #1 ; illeg + PUSH [BX] ; illeg + PUSH BYTE [BX] ; illeg + PUSH WORD #-1 ; right way to push a signed byte value + + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SP + PUSH BP + PUSH SI + PUSH DI + PUSH CS + PUSH DS + PUSH ES + PUSH FS + PUSH GS + PUSH SS + PUSH #$1234 ; illeg + PUSH WORD #$1234 + PUSH WORD [BX] + + PUSH EAX + PUSH EBX + PUSH ECX + PUSH EDX + PUSH ESP + PUSH EBP + PUSH ESI + PUSH EDI + PUSH #$12345678 ; illeg + PUSH DWORD #$12345678 + PUSH DWORD [BX] + + POP AL ; illeg + POP AH ; illeg + POP BL ; illeg + POP BH ; illeg + POP CL ; illeg + POP CH ; illeg + POP DL ; illeg + POP DH ; illeg + POP #1 ; illeg + POP BYTE #1 ; illeg + POP [BX] ; illeg + POP BYTE [BX] ; illeg + + POP AX + POP BX + POP CX + POP DX + POP SP + POP BP + POP SI + POP DI + POP CS ; illeg + POP DS + POP ES + POP FS + POP GS + POP SS + POP #$1234 ; illeg + POP WORD #$1234 ; illeg + POP WORD [BX] + + POP EAX + POP EBX + POP ECX + POP EDX + POP ESP + POP EBP + POP ESI + POP EDI + POP #$12345678 ; illeg + POP DWORD #$12345678 ; illeg + POP DWORD [BX] diff --git a/bin86-0.3/as/asm/seg.asm b/bin86-0.3/as/asm/seg.asm new file mode 100644 index 0000000..0394615 --- /dev/null +++ b/bin86-0.3/as/asm/seg.asm @@ -0,0 +1,6 @@ + SEG CS + SEG DS + SEG ES + SEG FS + SEG GS + SEG SS diff --git a/bin86-0.3/as/asm/shdouble.asm b/bin86-0.3/as/asm/shdouble.asm new file mode 100644 index 0000000..1080ece --- /dev/null +++ b/bin86-0.3/as/asm/shdouble.asm @@ -0,0 +1,34 @@ +; SHDOUBLE.ASM + +ILLEGALS EQU 1 + +; 0F A4 SHLD r/m16,r16,imm8 3/7 +; 0F A4 SHLD r/m32,r32,imm8 3/7 +; 0F A5 SHLD r/m16,r16,CL 3/7 +; 0F A5 SHLD r/m32,r32,CL 3/7 + +; 0F AC SHRD r/m16,r16,imm8 3/7 +; 0F AC SHRD r/m32,r32,imm8 3/7 +; 0F AD SHRD r/m16,r16,CL 3/7 +; 0F AD SHRD r/m32,r32,CL 3/7 + +IF ILLEGALS + SHLD AL,BL,8 ; byte size + SHLD AX,8,8 ; immediate source + SHLD AX,DS,8 ; segment register + SHLD AX,[BX],8 ; non-register source + SHLD AX,BX,256 ; shift count too big + SHLD AL,BL,8 ; byte size +ENDIF + + SHLD BX,CX,3 + SHLD EDX,ESI,1 + SHLD CX,BX,CL + SHLD ESI,EDX,1 + SHLD [BX],CX,3 + SHLD [BX],ECX,1 + SHLD [SI],BX,CL + SHLD [SI],EBX,CL + + SHRD BX,CX,3 + SHRD CX,BX,CL diff --git a/bin86-0.3/as/asm/shift.asm b/bin86-0.3/as/asm/shift.asm new file mode 100644 index 0000000..35cc23f --- /dev/null +++ b/bin86-0.3/as/asm/shift.asm @@ -0,0 +1,119 @@ + RCL AL,CL + RCL AH,CL + RCL BL,CL + RCL BH,CL + RCL CL,CL + RCL CH,CL + RCL DL,CL + RCL DH,CL + RCL #1,CL ; illeg + RCL [BX],CL ; illeg + RCL BYTE [BX],CL + + RCL AX,CL + RCL BX,CL + RCL CX,CL + RCL DX,CL + RCL SP,CL + RCL BP,CL + RCL SI,CL + RCL DI,CL + RCL CS,CL ; illeg + RCL DS,CL ; illeg + RCL ES,CL ; illeg + RCL FS,CL ; illeg + RCL GS,CL ; illeg + RCL WORD [BX],CL + + RCL EAX,CL + RCL EBX,CL + RCL ECX,CL + RCL EDX,CL + RCL ESP,CL + RCL EBP,CL + RCL ESI,CL + RCL EDI,CL + RCL DWORD [BX],CL + + RCL AL,1 + RCL AH,1 + RCL BL,1 + RCL BH,1 + RCL CL,1 + RCL CH,1 + RCL DL,1 + RCL DH,1 + RCL #1,1 ; illeg + RCL [BX],1 ; illeg + RCL BYTE [BX],1 + + RCL AX,1 + RCL BX,1 + RCL CX,1 + RCL DX,1 + RCL SP,1 + RCL BP,1 + RCL SI,1 + RCL DI,1 + RCL CS,1 ; illeg + RCL DS,1 ; illeg + RCL ES,1 ; illeg + RCL FS,1 ; illeg + RCL GS,1 ; illeg + RCL WORD [BX],1 + + RCL EAX,1 + RCL EBX,1 + RCL ECX,1 + RCL EDX,1 + RCL ESP,1 + RCL EBP,1 + RCL ESI,1 + RCL EDI,1 + RCL DWORD [BX],1 + + RCL AL,15 + RCL AH,15 + RCL BL,15 + RCL BH,15 + RCL CL,15 + RCL CH,15 + RCL DL,15 + RCL DH,15 + RCL #1,15 ; illeg + RCL [BX],15 ; illeg + RCL BYTE [BX],15 + RCL AL,$1000 + + RCL AX,15 + RCL BX,15 + RCL CX,15 + RCL DX,15 + RCL SP,15 + RCL BP,15 + RCL SI,15 + RCL DI,15 + RCL CS,15 ; illeg + RCL DS,15 ; illeg + RCL ES,15 ; illeg + RCL FS,15 ; illeg + RCL GS,15 ; illeg + RCL WORD [BX],15 + + RCL EAX,15 + RCL EBX,15 + RCL ECX,15 + RCL EDX,15 + RCL ESP,15 + RCL EBP,15 + RCL ESI,15 + RCL EDI,15 + RCL DWORD [BX],15 + + RCR AX,7 + ROL AX,7 + ROR AX,7 + SAL AX,7 + SAR AX,7 + SHL AX,7 + SHR AX,7 diff --git a/bin86-0.3/as/asm/summary.as b/bin86-0.3/as/asm/summary.as new file mode 100644 index 0000000..cd62e37 --- /dev/null +++ b/bin86-0.3/as/asm/summary.as @@ -0,0 +1,385 @@ +general: + ; AL,imm8 + ; AX,imm16 + ; EAX,imm32 + ; r/m8,imm8 + ; r/m16,imm16 + ; r/m32.imm32 + ; r/m16,signed imm8 + ; r/m32,signed imm8 + ; r/m8,r8 + ; r/m16,r16 + ; r/m32,r32 + ; r8,r/m8 + ; r16,r/m16 + ; r32,r/m32 + +shiftcount: + ; 1 + ; CL + ; imm8 +unary alterable: + ; r/m8 + ; r/m16 + ; r/m32 + + AAA + AAD ; [unsupported base] + AAM ; [unsupported base] + AAS + ADC ; general + ADD ; general + AND ; general + ARPL ; r/m16,r16 + BOUND ; r16,m16&16 + BOUND ; r32,m32&32 + BSF ; r16,r/m16 + BSF ; r32,r/m32 + BSR ; r16,r/m16 + BSR ; r32,r/m32 + BSWAP ; r32 + BT ; r/m16,r16 + BT ; r/m32,r32 + BT ; r/m16,imm8 + BT ; r/m32,imm8 + BTC ; r/m16,r16 + BTC ; r/m32,r32 + BTC ; r/m16,imm8 + BTC ; r/m32,imm8 + BTR ; r/m16,r16 + BTR ; r/m32,r32 + BTR ; r/m16,imm8 + BTR ; r/m32,imm8 + BTS ; r/m16,r16 + BTS ; r/m32,r32 + BTS ; r/m16,imm8 + BTS ; r/m32,imm8 + CALL ; rel16 + CALL ; r/m16 + CALL ; ptr16:16 + CALL ; m16:16 + CALL ; rel32 + CALL ; r/m32 + CALL ; ptr16:32 + CALL ; m16:32 + CBW + CDQ + CLC + CLD + CLI + CLTS + CMC + CMP ; general + CMPS ; [segreg:]m8,m8 + CMPS ; [segreg:]m16,m16 + CMPS ; [segreg:]m32,m32 + CMPSB + CMPSW + CMPSD + CMPXCHG ; r/m8,r8 + CMPXCHG ; r/m16,r16 + CMPXCHG ; r/m32,r32 + CWD + CWDE + DAA + DAS + DEC ; unary alterable + DEC ; r16 + DEC ; r32 + DIV ; AL,r/m8 + DIV ; AX,r/m16 + DIV ; EAX,r/m32 + ENTER ; imm16,imm8 + HLT + IDIV ; AL,r/m8 + IDIV ; AX,r/m16 + IDIV ; EAX,r/m32 + IMUL ; r/m8 + IMUL ; r/m16 + IMUL ; r/m32 + IMUL ; r16,r/m16 + IMUL ; r32,r/m32 + IMUL ; r16,r/m16,imm8 + IMUL ; r32,r/m32,imm8 + IMUL ; r16,imm8 + IMUL ; r32,imm8 + IMUL ; r16,r/m16,imm16 + IMUL ; r32,r/m32,imm32 + IMUL ; r16,imm16 + IMUL ; r32,imm32 + IN ; AL,imm8 + IN ; AX,imm8 + IN ; EAX,imm8 + IN ; AL,DX + IN ; AX,DX + IN ; EAX,DX + INC ; unary alterable + INC ; r16 + INC ; r32 + INSB + INSW + INSD + INT ; imm8 + INTO + INVD + INVLPG ; m + IRET + IRETD + JCC ; rel8 + JCC ; rel16/32 + JA + JAE + JB + JBE + JC + JCXZ + JECXZ + JE + JG + JGE + JL + JLE + JNA + JNAE + JNB + JNBE + JNC + JNE + JNG + JNGE + JNL + JNLE + JNO + JNP + JNS + JNZ + JO + JP + JPE + JPO + JS + JZ + JMP ; rel8 + JMP ; rel16 + JMP ; r/m16 + JMP ; ptr16:16 + JMP ; m16:16 + JMP ; rel32 + JMP ; r/m32 + JMP ; ptr16:32 + JMP ; m16:32 + LAHF + LAR ; r16,r/m16 + LAR ; r32,r/m32 + LEA ; r16,m + LEA ; r32,m + LEAVE + LGDT ; m16&32 + LIDT ; m16&32 + LDS ; r16,m16:16 + LDS ; r32,m16:32 + LES ; r16,m16:16 + LES ; r32,m16:32 + LFS ; r16,m16:16 + LFS ; r32,m16:32 + LGS ; r16,m16:16 + LGS ; r32,m16:32 + LSS ; r16,m16:16 + LSS ; r32,m16:32 + LLDT ; r/m16 + LMSW ; r/m16 + LOCK + LODS ; [segreg:]m8 + LODS ; [segreg:]m16 + LODS ; [segreg:]m32 + LODSB + LODSW + LODSD + LOOP ; rel8 + LOOPE ; rel8 + LOOPZ ; rel8 + LOOPNE ; rel8 + LOOPNZ ; rel8 + LSL ; r16,r/m16 + LSL ; r32,r/m32 + LTR ; r/m16 + MOV ; r/m8,r8 + MOV ; r/m16,r16 + MOV ; r/m32,r32 + MOV ; r8,r/m8 + MOV ; r16,r/m16 + MOV ; r32,r/m32 + MOV ; r/m16,Sreg + MOV ; Sreg,r/m16 + MOV ; AL,moffs8 + MOV ; AX,moffs16 + MOV ; EAX,moffs32 + MOV ; moffs8,AL + MOV ; moffs16,AX + MOV ; moffs32,EAX + MOV ; r8,imm8 + MOV ; r16,imm16 + MOV ; r32,imm32 + MOV ; r32,CR0/CR2/CR3 + MOV ; r/m8,imm8 + MOV ; r/m16,imm16 + MOV ; r/m32,imm32 + MOV ; r32,CR0/CR2/CR3 + MOV ; CR0/CR2/CR3,r32 + MOV ; r32,DR0/DR1/DR2/DR3/DR6/DR7 + MOV ; DR0/DR1/DR2/DR3/DR6/DR7,r32 + MOV ; r32,TR6/TR7 + MOV ; TR6/TR7,r32 + MOVS ; [segreg:]m8,m8 + MOVS ; [segreg:]m16,m16 + MOVS ; [segreg:]m32,m32 + MOVSB + MOVSW + MOVSD + MOVSX ; r16,r/m8 + MOVSX ; r32,r/m8 + MOVSX ; r32,r/m16 + MOVZX ; r16,r/m8 + MOVZX ; r32,r/m8 + MOVZX ; r32,r/m16 + MUL ; AL,r/m8 + MUL ; AX,r/m16 + MUL ; EAX,r/m32 + NEG ; unary alterable + NOP + NOT ; unary alterable + OR ; general + OUT ; imm8,AL + OUT ; imm8,AX + OUT ; imm8,EAX + OUT ; DX,AL + OUT ; DX,AX + OUT ; DX,EAX + OUTS ; [segreg:]m8 + OUTS ; [segreg:]m16 + OUTS ; [segreg:]m32 + OUTSB + OUTSW + OUTSD + POP ; m16 + POP ; m32 + POP ; r16 + POP ; r32 + POP ; DS + POP ; ES + POP ; FS + POP ; GS + POP ; SS + POPA + POPAD + POPF + POPFD + PUSH ; m16 + PUSH ; m32 + PUSH ; r16 + PUSH ; r32 + PUSH ; imm8 + PUSH ; imm16 + PUSH ; imm32 + PUSH ; CS + PUSH ; DS + PUSH ; ES + PUSH ; FS + PUSH ; GS + PUSH ; SS + PUSHA + PUSHAD + PUSHF + PUSHFD + RCL ; shiftcount + RCR ; shiftcount + ROL ; shiftcount + ROR ; shiftcount + REP ; INS/MOVS/OUTS/STOS + REPE ; CMPS/SCAS + REPNE ; CMPS/SCAS + RET + RET ; imm16 + SAHF + SAL ; shiftcount + SAR ; shiftcount + SHL ; shiftcount + SHR ; shiftcount + SBB ; general + SCASB + SCASW + SCASD + SETA ; r/m8 + SETAE ; r/m8 + SETB ; r/m8 + SETBE ; r/m8 + SETC ; r/m8 + SETE ; r/m8 + SETG ; r/m8 + SETGE ; r/m8 + SETL ; r/m8 + SETLE ; r/m8 + SETNA ; r/m8 + SETNAE ; r/m8 + SETNB ; r/m8 + SETNBE ; r/m8 + SETNC ; r/m8 + SETNE ; r/m8 + SETNG ; r/m8 + SETNGE ; r/m8 + SETNL ; r/m8 + SETNLE ; r/m8 + SETNO ; r/m8 + SETNP ; r/m8 + SETNS ; r/m8 + SETNZ ; r/m8 + SETO ; r/m8 + SETP ; r/m8 + SETPE ; r/m8 + SETPO ; r/m8 + SETS ; r/m8 + SETZ ; r/m8 + SGDT ; m + SHLD ; r/m16,r16,imm8 + SHLD ; r/m32,r32,imm8 + SHLD ; r/m16,r16,CL + SHLD ; r/m32,r32,CL + SHRD ; r/m16,r16,imm8 + SHRD ; r/m32,r32,imm8 + SHRD ; r/m16,r16,CL + SHRD ; r/m32,r32,CL + SIDT ; m + SLDT ; r/m16 + SMSW ; r/m16 + STC + STD + STI + STOSB + STOSW + STOSD + STR ; r/m16 + SUB ; general + TEST ; AL,imm8 + TEST ; AX,imm16 + TEST ; EAX,imm32 + TEST ; r/m8,imm8 + TEST ; r/m16,imm16 + TEST ; r/m32,imm32 + TEST ; r/m8,r8 + TEST ; r/m16,r16 + TEST ; r/m32/r32 + VERR ; r/m16 + VERW ; r/m16 + WAIT + WBINVD + XADD ; r/m8,r8 + XADD ; r/m16,r16 + XADD ; r/m32,r32 + XCHG ; AX,r16 + XCHG ; EAX,r32 + XCHG ; r/m8,r8 + XCHG ; r/m16,r16 + XCHG ; r/m32,r32 + XLAT ; [segreg:]m8 + XLATB + XOR ; general diff --git a/bin86-0.3/as/asm/xchg.asm b/bin86-0.3/as/asm/xchg.asm new file mode 100644 index 0000000..f05157f --- /dev/null +++ b/bin86-0.3/as/asm/xchg.asm @@ -0,0 +1,103 @@ + XCHG AX,BL ; illeg + XCHG AX,BYTE [BX] ; illeg + XCHG AX,DS ; illeg + XCHG AX,#1 ; illeg + + XCHG AX,AX + XCHG AX,BX + XCHG AX,CX + XCHG AX,DX + XCHG AX,SP + XCHG AX,BP + XCHG AX,SI + XCHG AX,DI + + XCHG AX,AX + XCHG BX,AX + XCHG CX,AX + XCHG DX,AX + XCHG SP,AX + XCHG BP,AX + XCHG SI,AX + XCHG DI,AX + + XCHG EAX,EAX + XCHG EAX,EBX + XCHG EAX,ECX + XCHG EAX,EDX + XCHG EAX,ESP + XCHG EAX,EBP + XCHG EAX,ESI + XCHG EAX,EDI + + XCHG EAX,EAX + XCHG EBX,EAX + XCHG ECX,EAX + XCHG EDX,EAX + XCHG ESP,EAX + XCHG EBP,EAX + XCHG ESI,EAX + XCHG EDI,EAX + + XCHG AL,AL + XCHG AL,AH + XCHG AL,BL + XCHG AL,BH + XCHG BL,CL + XCHG BL,CH + XCHG BL,DL + XCHG BL,DH + + XCHG [BX],AL + XCHG [BX],AH + XCHG [BX],BL + XCHG [BX],BH + XCHG [BX],CL + XCHG [BX],CH + XCHG [BX],DL + XCHG [BX],DH + + XCHG AL,[BX] + XCHG AH,[BX] + XCHG BL,[BX] + XCHG BH,[BX] + XCHG CL,[BX] + XCHG CH,[BX] + XCHG DL,[BX] + XCHG DH,[BX] + + XCHG [BX],AX + XCHG [BX],BX + XCHG [BX],CX + XCHG [BX],DX + XCHG [BX],SP + XCHG [BX],BP + XCHG [BX],SI + XCHG [BX],DI + + XCHG AX,[BX] + XCHG BX,[BX] + XCHG CX,[BX] + XCHG DX,[BX] + XCHG SP,[BX] + XCHG BP,[BX] + XCHG SI,[BX] + XCHG DI,[BX] + + XCHG [BX],EAX + XCHG [BX],EBX + XCHG [BX],ECX + XCHG [BX],EDX + XCHG [BX],ESP + XCHG [BX],EBP + XCHG [BX],ESI + XCHG [BX],EDI + + XCHG AX,[EBX] + XCHG BX,[EBX] + XCHG CX,[EBX] + XCHG DX,[EBX] + XCHG SP,[EBX] + XCHG BP,[EBX] + XCHG SI,[EBX] + XCHG DI,[EBX] diff --git a/bin86-0.3/as/assemble.c b/bin86-0.3/as/assemble.c new file mode 100644 index 0000000..4e96178 --- /dev/null +++ b/bin86-0.3/as/assemble.c @@ -0,0 +1,314 @@ +/* + * bin86/as/assemble.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* assemble.c - main loop for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "globvar.h" +#include "opcode.h" +#include "scan.h" + +PRIVATE bool_t nocolonlabel; /* set for labels not followed by ':' */ +PRIVATE void (*routine) P((void)); +PRIVATE pfv rout_table[] = +{ + pelse, + pelseif, + pelsifc, + pendif, + pif, + pifc, + + /* start of non-conditionals */ + palign, + pblkw, + pblock, + pbss, + pcomm, + pcomm1, + pdata, + pendb, + penter, + pentry, + pequ, + peven, + pexport, + pfail, + pfcb, + pfcc, + pfdb, + pfqb, + pget, + pglobl, + pident, + pimport, + plcomm, + plcomm1, + plist, + ploc, + pmaclist, + pmacro, + pmap, + porg, + pproceof, + prmb, + psect, + pset, + psetdp, + ptext, +#ifdef I80386 + puse16, + puse32, +#endif + pwarn, + /* end of pseudo-ops */ + +#ifdef I80386 + mbcc, + mbswap, + mcall, + mcalli, + mdivmul, + menter, + mEwGw, + mExGx, + mf_inher, + mf_m, + mf_m2, + mf_m2_ax, + mf_m2_m4, + mf_m2_m4_m8, + mf_m4_m8_optst, + mf_m4_m8_st, + mf_m4_m8_stst, + mf_m4_m8_m10_st, + mf_m10, + mf_optst, + mf_st, + mf_stst, + mf_w_inher, + mf_w_m, + mf_w_m2, + mf_w_m2_ax, + mgroup1, + mgroup2, + mgroup6, + mgroup7, + mgroup8, + mGvEv, + mGvMa, + mGvMp, + mimul, + min, + mincdec, + minher, + minher16, + minher32, + minhera, + mint, + mjcc, + mjcxz, + mlea, + mmov, + mmovx, + mnegnot, + mout, + mpushpop, + mret, + mseg, + msetcc, + mshdouble, + mtest, + mxchg, +#endif /* I80386 */ + +#ifdef MC6809 + mall, /* all address modes allowed, like LDA */ + malter, /* all but immediate, like STA */ + mimmed, /* immediate only (ANDCC, ORCC) */ + mindex, /* indexed (LEA's) */ + minher, /* inherent, like CLC or CLRA */ + mlong, /* long branches */ + mshort, /* short branches */ + msstak, /* S-stack (PSHS, PULS) */ + mswap, /* TFR, EXG */ + mustak, /* U-stack (PSHU,PULU) */ +#endif /* MC6809 */ +}; + +FORWARD void asline P((void)); + +/* + This uses registers as follows: A is for work and is not preserved by + the subroutines.B holds the last symbol code, X usually points to data + about the last symbol, U usually holds the value of last expression + or symbol, and Y points to the current char. The value in Y is needed + by READCH and GETSYM. EXPRES needs B and Y, and returns a value in U. + If the expression starts with an identifier, X must point to its string. + LOOKUP needs a string pointer in X and length in A. It returns a table + pointer in X (unless not assembling and not found), symbol type in A + and overflow in CC. +*/ + +PUBLIC void assemble() +{ + while (TRUE) + { + asline(); + if (label != NULL) /* must be confirmed if still set */ + { /* it is nulled by EQU, COMM and SET */ +#ifndef MC6809 +#define NEEDENDLABEL ILLAB + if (nocolonlabel) + error(NEEDENDLABEL); +#endif + label->type |= LABIT; /* confirm, perhaps redundant */ + if (label->type & REDBIT) + { + /* REDBIT meant 'GLOBLBIT' while LABIT was not set. */ + label->type |= EXPBIT; + label->type &= ~REDBIT; + } + if ((mcount | popflags) == 0) + /* unaccompanied label, display adr like EQU and SET */ + showlabel(); + label = NULL; /* reset for next line */ + } + skipline(); + listline(); + genbin(); + genobj(); + binmbuf = lc += lcjump +#ifdef I80386 + + immcount +#endif + ; + } +} + +PRIVATE void asline() +{ + register struct sym_s *symptr; + + postb = popflags = pcrflag = +#ifdef I80386 + sprefix = oprefix = aprefix = +#endif + immcount = lastexp.data = lcjump = 0; +#ifdef I80386 + sib = NO_SIB; +#endif +#if SIZEOF_OFFSET_T > 2 + fqflag = +#endif + fdflag = fcflag = FALSE; + readline(); + getsym(); + if (sym != IDENT) /* expect label, mnemonic or macro */ + return; /* anything else is a comment */ + symptr = gsymptr; + if (!ifflag) + /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */ + { + if (symptr == NULL || !(symptr->type & MNREGBIT) || + symptr->data & REGBIT || + symptr->value_reg_or_op.op.routine >= MIN_NONCOND) + return; + } + else if (!(symptr->type & (MACBIT | MNREGBIT))) + /* not macro, op, pseudo-op or register, expect label */ + { + if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */ + { + sym = COLON; + ++lineptr; + } + if (symptr->type & (LABIT | VARBIT)) + { + if (symptr->type & REDBIT) + labelerror(RELAB); + label = symptr; + } + else if (checksegrel(symptr)) + { + symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */ +#ifdef MC6809 +#if 0 + if (sym == COLON) + symptr->type |= EXPBIT; +#endif +#endif + symptr->data = (symptr->data & FORBIT) | lcdata; + /* remember if forward referenced */ + symptr->value_reg_or_op.value = lc; + /* unless changed by EQU,COMM or SET */ + label = symptr; + } + getsym(); + if (sym != IDENT) + { + if (sym == EQOP) + { + getsym(); + pequ(); + } + return; /* anything but ident is comment */ + } + symptr = gsymptr; + } + if (symptr->type & MACBIT) + { + entermac(symptr); + return; + } + if (!(symptr->type & MNREGBIT)) + { + error(OPEXP); + return; + } + if (symptr->data & REGBIT) + { + error(REGUID); + return; + } + mnsize = 0; + if ((page = (symptr->data & (PAGE1 | PAGE2))) != 0) + { +#ifdef MNSIZE + if (page == (PAGE1 | PAGE2)) + { + mnsize = 1; + page = 0; + } + else +#endif + { +#ifdef PAGE2_OPCODE + if (page == PAGE2) + page = PAGE2_OPCODE; + else +#endif + page = PAGE1_OPCODE; + mcount = 1; + } + } + opcode = symptr->value_reg_or_op.op.opcode; + routine = rout_table[symptr->value_reg_or_op.op.routine]; + getsym(); + (*routine)(); + if (sym != EOLSYM) + error(JUNK_AFTER_OPERANDS); +#ifdef I80386 + if (aprefix != 0) + ++mcount; + if (oprefix != 0) + ++mcount; + if (sprefix != 0) + ++mcount; +#endif +} diff --git a/bin86-0.3/as/byteord.h b/bin86-0.3/as/byteord.h new file mode 100644 index 0000000..01d2d85 --- /dev/null +++ b/bin86-0.3/as/byteord.h @@ -0,0 +1,24 @@ +/* + * bin86/as/byteord.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* byteord.h - byte order dependencies for C compiler, assembler, linker */ + +/* These are for the targets of everything and for linker source too. */ + +#ifdef I8086 +# define BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ +#endif + +#ifdef I80386 +# define BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 +#endif + +#ifdef MC6809 +# define BIG_ENDIAN 1 /* byte order in words is high-low */ +# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ +#endif diff --git a/bin86-0.3/as/chk b/bin86-0.3/as/chk new file mode 100755 index 0000000..ce55954 --- /dev/null +++ b/bin86-0.3/as/chk @@ -0,0 +1,9 @@ +for i in `ls asm/*.asm` +do + j=`basename $i .asm` + ./as asm/$j.asm -b $j.bin -o $j.obj > /dev/null + cmp $j.bin bin/$j.bin + cmp $j.obj obj/$j.obj + rm $j.bin $j.obj +done + diff --git a/bin86-0.3/as/const.h b/bin86-0.3/as/const.h new file mode 100644 index 0000000..7961cf5 --- /dev/null +++ b/bin86-0.3/as/const.h @@ -0,0 +1,430 @@ +/* + * bin86/as/const.h + * + * Copyright (C) 1992 Bruce Evans + */ + +#undef __BYTE_ORDER +#undef __LITTLE_ENDIAN +#undef __BIG_ENDIAN +#include "endian.h" +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#if __BYTE_ORDER == __BIG_ENDIAN +#define LOW_BYTE 3 +#else +#define LOW_BYTE 0 +#endif + +#define align(x) ((x) = (void *)(((int) (x) + (4-1)) & ~(4-1))) +/* const.h - constants for assembler */ + +/* major switches */ + +#define I80386 /* generate 80386 code */ +#undef MC6809 /* generate 6809 code */ +#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */ +#undef SOS_EDOS /* source OS is EDOS */ + +/* defaults */ + +#define DIRCHAR '/' /* character separating filename from dir */ +#define INBUFSIZE 8192 +#define SOS_EOLSTR "\012" + +/* defaults modified by switches */ + +#ifdef SOS_EDOS +# undef INBUFSIZE +# define INBUFSIZE 512 +# undef SOS_EOLSTR +# define SOS_EOLSTR "\015\012" +# define STAKSIZ 256 /* table grows up to stack less this */ +#endif + +/* booleans */ + +#define FALSE 0 +#define TRUE 1 + +/* ASCII constants */ + +#define ETB 23 + +/* C tricks */ + +#define EXTERN extern +#define FORWARD static +#define PRIVATE static +#define PUBLIC + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* O/S constants */ + +#define CREAT_PERMS 0666 +#define EOF (-1) +#define STDIN 0 +#define STDOUT 1 + +enum +{ +/* Register codes (internal to assembler). */ +#ifdef I80386 + +/* Index regs must be first. */ + BPREG, + BXREG, + DIREG, + SIREG, +#define MAX16BITINDREG SIREG + + EAXREG, + EBPREG, + EBXREG, + ECXREG, + EDIREG, + EDXREG, + ESIREG, + ESPREG, +#define MAXINDREG ESPREG + + AXREG, + CXREG, + DXREG, + SPREG, + + AHREG, + ALREG, + BHREG, + BLREG, + CHREG, + CLREG, + DHREG, + DLREG, + + CSREG, + DSREG, + ESREG, + FSREG, + GSREG, + SSREG, + + CR0REG, + CR2REG, + CR3REG, + DR0REG, + DR1REG, + DR2REG, + DR3REG, + DR6REG, + DR7REG, + TR3REG, + TR4REG, + TR5REG, + TR6REG, + TR7REG, + + ST0REG, + ST1REG, + ST2REG, + ST3REG, + ST4REG, + ST5REG, + ST6REG, + ST7REG, + + NOREG, +#endif /* I80386 */ + +#ifdef MC6809 + +/* Index regs must be first, then PC. */ + SREG, + UREG, + XREG, + YREG, +#define MAXINDREG YREG + + PCREG, + AREG, + BREG, + CCREG, + DPREG, + DREG, + + NOREG, +#endif /* MC6809 */ +}; + +#ifdef I80386 +enum +{ +/* Type and size keywords. */ + BYTEOP, + DWORDOP, + FWORDOP, + FAROP, + PTROP, + PWORDOP, + QWORDOP, + TBYTEOP, + WORDOP, +}; +#endif /* I80386 */ + +/* special chars */ + +#define EOL 0 +#define MACROCHAR '?' + +enum +{ +/* Symbol codes. */ + +/* The first 2 must be from chars in identifiers. */ + IDENT, + INTCONST, + +/* The next few are best for other possibly-multi-char tokens. */ + ADDOP, /* also ++ */ + BINCONST, + CHARCONST, + GREATERTHAN, /* also >> and context-sensitive */ + HEXCONST, + LESSTHAN, /* also << and context-sensitive */ + SUBOP, /* also -- */ + WHITESPACE, + + ANDOP, + COMMA, + EOLSYM, + EQOP, + IMMEDIATE, + INDIRECT, + LBRACKET, + LPAREN, + MACROARG, + NOTOP, + OROP, + OTHERSYM, + POSTINCOP, + PREDECOP, + RBRACKET, + RPAREN, + SLASH, /* context-sensitive */ + SLOP, + SROP, + STAR, /* context-sensitive */ + STRINGCONST, + COLON, +}; + +enum +{ +/* Error codes. */ + +/* Syntax errors. */ + COMEXP, + DELEXP, + FACEXP, + IREGEXP, + LABEXP, + LPEXP, + OPEXP, + RBEXP, + REGEXP, + RPEXP, + SPEXP, + +/* Expression errors. */ + ABSREQ, + NONIMPREQ, + RELBAD, + +/* Label errors. */ + ILLAB, + MACUID, + MISLAB, + MNUID, + REGUID, + RELAB, + UNBLAB, + UNLAB, + VARLAB, + +/* Addressing errors. */ + ABOUNDS, + DBOUNDS, + ILLMOD, + ILLREG, + +/* Control structure errors. */ + ELSEBAD, +#define ELSEIFBAD ELSEBAD + ENDBBAD, +#define ENDIFBAD ELSEBAD + EOFBLOCK, + EOFIF, + EOFLC, + EOFMAC, + FAILERR, + +/* Overflow errors. */ + BLOCKOV, + BWRAP, + COUNTOV, + COUNTUN, + GETOV, + IFOV, + + LINLONG, + MACOV, + OBJSYMOV, + OWRITE, + PAROV, + SYMOV, + SYMOUTOV, + +/* I/O errors. */ + OBJOUT, + +/* Miscellaneous errors. */ + AL_AX_EAX_EXP, + CTLINS, + FURTHER, + ILL_IMM_MODE, + ILL_IND_TO_IND, + ILL_IND, + ILL_IND_PTR, + ILL_SCALE, + ILL_SECTION, + ILL_SEG_REG, + ILL_SOURCE_EA, + ILL_SIZE, + IMM_REQ, + INDEX_REG_EXP, + IND_REQ, + MISMATCHED_SIZE, + NOIMPORT, + REENTER, + REL_REQ, + REPEATED_DISPL, + SEGREL, + SEG_REG_REQ, + SIZE_UNK, + + FP_REG_REQ, + FP_REG_NOT_ALLOWED, + ILL_FP_REG, + ILL_FP_REG_PAIR, + JUNK_AFTER_OPERANDS, + + ALREADY, + +/* Warnings. */ +#define MINWARN SHORTB + SHORTB, +}; + +/* symbol table entry */ + + /* type entry contains following flags */ +#define ENTBIT (1<<0) /* entry point (= OBJ_N_MASK) */ +#define COMMBIT (1<<1) /* common */ +#define LABIT (1<<2) /* label (a PC location or defined by EQU) */ +#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */ +#define MACBIT (1<<4) /* macro */ +#define REDBIT (1<<5) /* redefined (if with LABIT or VARBIT), to do + * with SA_MASK (if with COMMBIT), otherwise + * means globl */ +#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */ +#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */ + + /* data entry contains following flags, valid */ + /* for expressions as well as syms */ +#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT | PAGE1 */ +#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT | PAGE2 */ +#define REGBIT (1<<2) /* register = MNREGBIT | REGBIT */ +#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT | SIZEBIT */ +#define SEGM 0x0F /* 1st 4 bits reused for segment if !MNREGBIT */ +#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */ +#define FORBIT (1<<5) /* forward referenced */ +#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */ +#define UNDBIT (1<<7) /* undefined */ + +/* object code format (Introl) */ + +#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */ + +#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */ + +#define OBJ_ABS 0x40 /* absolute code command */ +#define OBJ_OFFSET_REL 0x80 /* offset relocation command */ +#define OBJ_SET_SEG 0x20 /* set segment command */ +#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */ +#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */ +#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */ +#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */ + +#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */ +#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */ +oops - RELBIT misplaced +#endif +#define OBJ_E_MASK 0x80 /* exported bit (symbols) */ +#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */ +oops - EXPBIT misplaced +#endif +#define OBJ_I_MASK 0x40 /* imported bit (symbols) */ +#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */ +oops - IMPBIT misplaced +#endif +#define OBJ_N_MASK 0x01 /* entry bit (symbols) */ +#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */ +oops - ENTBIT misplaced +#endif +#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */ +#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */ +#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */ +#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */ + +#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */ +#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */ + +#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */ +#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */ + +#define SYMLIS_NAMELEN 26 +#define SYMLIS_LEN (sizeof (struct sym_listing_s)) + +#define FILNAMLEN 64 /* max length of a file name */ +#define LINLEN 256 /* max length of input line */ +#define LINUM_LEN 5 /* length of formatted line number */ + +#define SPTSIZ 1024 /* number of symbol ptrs */ + /* pseudo-op flags */ +#define POPHI 1 /* set to print hi byte of adr */ +#define POPLO 2 /* to print lo byte of ADR */ +#define POPLC 4 /* to print LC */ +#define POPLONG 8 /* to print high word of ADR */ +#define MAXBLOCK 8 /* max nesting level of BLOCK stack */ +#define MAXGET 8 /* max nesting level of GET stack */ +#define MAXIF 8 /* max nesting level of IF stack */ +#define MACPSIZ (128 / sizeof (struct schain_s)) + /* size of macro param buffer */ +#define MAXMAC 8 /* max nesting level of macro stack */ +#define NLOC 16 /* number of location counters */ +#ifdef I80386 +#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */ +#endif + +/* special segments */ + +#define BSSLOC 3 +#define DATALOC 3 +#define DPLOC 2 +#define STRLOC 1 +#define TEXTLOC 0 diff --git a/bin86-0.3/as/det_endian.c b/bin86-0.3/as/det_endian.c new file mode 100644 index 0000000..50b5bdc --- /dev/null +++ b/bin86-0.3/as/det_endian.c @@ -0,0 +1,34 @@ +/* Determine the "endianness" of the CPU. + Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Contributed by Torbjorn Granlund (tege@sics.se). + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <stdio.h> + +main () +{ + unsigned long int i; + + if (sizeof (i) != 4) + puts ("#error \"Not a 32-bit machine!\""); + + i = (((((('4' << 8) + '3') << 8) + '2') << 8) + '1'); + + printf ("#define __BYTE_ORDER %.4s\n", (char *) &i); + + exit (0); +} diff --git a/bin86-0.3/as/error.c b/bin86-0.3/as/error.c new file mode 100644 index 0000000..343ec8c --- /dev/null +++ b/bin86-0.3/as/error.c @@ -0,0 +1,105 @@ +/* + * bin86/as/error.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* error.c - error routines for assembler */ + +#include <string.h> +#include "const.h" +#include "type.h" + +PRIVATE char *errormessage[] = +{ + "comma expected", + "delimiter expected", + "factor expected", + "index register expected", + "label expected", + "left parentheses expected", + "opcode expected", + "right bracket expected", + "register expected", + "right parentheses expected", + "space expected", + "absolute expression required", + "non-imported expression required", + "relocation impossible", + "illegal label", + "MACRO used as identifier", + "missing label", + "opcode used as identifier", + "register used as identifier", + "redefined label", + "unbound label", + "undefined label", + "variable used as label", + "address out of bounds", + "data out of bounds", + "illegal address mode", + "illegal register", + "no matching IF", + "no matching BLOCK", + "end of file in BLOCK", + "end of file in IF", + "location counter was undefined at end", + "end of file in MACRO", + "user-generated error", + "BLOCK stack overflow", + "binary file wrap-around", + "counter overflow", + "counter underflow", + "GET stack overflow", + "IF stack overflow", + "line too long", + "MACRO stack overflow", + "object symbol table overflow", + "program overwrite", + "parameter table overflow", + "symbol table overflow", + "output symbol table overflow", + "error writing object file", + "al, ax or eax expected", + "control character in string", + "futher errors suppressed", + "illegal immediate mode", + "illegal indirect to indirect", + "illegal indirection", + "illegal indirection from previous 'ptr'", + "illegal scale", + "illegal section", + "illegal segment register", + "illegal source effective address", + "illegal size", + "immediate expression expected", + "index register expected", + "indirect expression required", + "mismatched size", + "no imports with binary file output", + "multiple ENTER pseudo-ops", + "relative expression required", + "repeated displacement", + "segment or relocatability redefined", + "segment register required", + "size unknown", + "FP register required", + "FP register not allowed", + "illegal FP register", + "illegal FP register pair", + "junk after operands", + "already defined", + "short branch would do", + "unknown error", +}; + +/* build null-terminated error message for given error at given spot */ + +PUBLIC char *build_error_message(errnum, buf) +unsigned errnum; +char *buf; +{ + if (errnum >= sizeof errormessage / sizeof errormessage[0]) + errnum = sizeof errormessage / sizeof errormessage[0] - 1; + return strcpy(buf, errormessage[errnum]); +} diff --git a/bin86-0.3/as/express.c b/bin86-0.3/as/express.c new file mode 100644 index 0000000..7cd0b55 --- /dev/null +++ b/bin86-0.3/as/express.c @@ -0,0 +1,388 @@ +/* + * bin86/as/express.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* express.c - expression handler for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "globvar.h" +#include "scan.h" +#include "source.h" + +FORWARD void experror P((error_pt errnum)); +FORWARD void expundefined P((void)); +FORWARD void simple2 P((void)); +FORWARD void simple P((void)); +FORWARD void term P((void)); +FORWARD void factor2 P((void)); + +PUBLIC void absexpres() +{ + expres(); + chkabs(); +} + +/* check lastexp.data is abs */ + +PUBLIC void chkabs() +{ + if (lastexp.data & RELBIT) + { + if (pass != 0) + error(ABSREQ); + expundefined(); + } +} + +PRIVATE void experror(errnum) +error_pt errnum; +{ + error(errnum); + expundefined(); +} + +PRIVATE void expundefined() +{ + lastexp.data = FORBIT | UNDBIT; +} + +PUBLIC void nonimpexpres() +{ + expres(); + if (lastexp.data & IMPBIT) + experror(NONIMPREQ); +} + +/* generate relocation error if pass 2, make lastexp.data forward&undefined */ + +PUBLIC void showrelbad() +{ + if (pass != 0) + error(RELBAD); + expundefined(); +} + +PUBLIC void symabsexpres() +{ + getsym(); + absexpres(); +} + +PUBLIC void symexpres() +{ + getsym(); + expres(); +} + +/* + expres() parses expression = simple expression [op simple expression], + where op is =, < or >. + Parameters: sym, number in number, identifier from symname to lineptr - 1. + Returns value in lastexp. +*/ + +PUBLIC void expres() +{ + offset_t leftoffset; + + simple(); + leftoffset = lastexp.offset; + if (sym == EQOP) + { + simple2(); + if (leftoffset == lastexp.offset) + lastexp.offset = -1; + else + lastexp.offset = 0; + } + else if (sym == LESSTHAN) + { + /* context-sensitive, LESSTHAN really means less than here */ + simple2(); + if (leftoffset < lastexp.offset) + lastexp.offset = -1; + else + lastexp.offset = 0; + } + else if (sym == GREATERTHAN) + { + /* context-sensitive, GREATERTHAN really means greater than here */ + simple2(); + if (leftoffset > lastexp.offset) + lastexp.offset = -1; + else + lastexp.offset = 0; + } +} + +/* get symbol and 2nd simple expression, check both rel or both abs */ + +PRIVATE void simple2() +{ + unsigned char leftdata; + + leftdata = lastexp.data; + getsym(); + simple(); + if ((leftdata | lastexp.data) & IMPBIT || + (leftdata ^ lastexp.data) & (RELBIT | SEGM)) + showrelbad(); + else + lastexp.data = (leftdata & lastexp.data) & ~(RELBIT | SEGM); +} + +/* + simple() parses simple expression = [+-] term {op term}, + where op is +, -, or \ (OR). +*/ + +PRIVATE void simple() +{ + offset_t leftoffset; + unsigned char leftdata; + + if (sym == ADDOP || sym == SUBOP) + lastexp.data = lastexp.offset = 0; + else + term(); + while (TRUE) + { + leftoffset = lastexp.offset; + leftdata = lastexp.data; + if (sym == ADDOP) + { + getsym(); + term(); + if (leftdata & lastexp.data & RELBIT) + showrelbad(); /* rel + rel no good */ + else + lastexp.data |= leftdata; + lastexp.offset += leftoffset; + } + else if (sym == SUBOP) + { + getsym(); + term(); + /* check not abs - rel or rel - rel with mismatch */ + if (lastexp.data & RELBIT && + (!(leftdata & RELBIT) || + (leftdata | lastexp.data) & IMPBIT || + (leftdata ^ lastexp.data) & (RELBIT | SEGM))) + showrelbad(); + else + lastexp.data = ((leftdata | lastexp.data) & ~(RELBIT | SEGM)) + | ((leftdata ^ lastexp.data) & (RELBIT | SEGM)); + lastexp.offset = leftoffset - lastexp.offset; + } + else if (sym == OROP) + { + getsym(); + term(); + lastexp.data |= leftdata; + chkabs(); /* both must be absolute */ + lastexp.offset |= leftoffset; + } + else + return; + } +} + +/* term() parses term = factor {op factor}, where op is *, /, &, <<, or >>. */ + +PRIVATE void term() +{ + offset_t leftoffset; + + factor(); + while (TRUE) + { + leftoffset = lastexp.offset; + if (sym == STAR) + { + /* context-sensitive, STAR means multiplication here */ + factor2(); + lastexp.offset *= leftoffset; + } + else if (sym == SLASH) + { + /* context-sensitive, SLASH means division here */ + factor2(); + lastexp.offset = leftoffset / lastexp.offset; + } + else if (sym == ANDOP) + { + factor2(); + lastexp.offset &= leftoffset; + } + else if (sym == SLOP) + { + factor2(); + lastexp.offset = leftoffset << lastexp.offset; + } + else if (sym == SROP) + { + factor2(); + lastexp.offset = leftoffset >> lastexp.offset; + } + else + return; + } +} + +/* get symbol and 2nd or later factor, check both abs */ + +PRIVATE void factor2() +{ + unsigned char leftdata; + + leftdata = lastexp.data; + getsym(); + factor(); + lastexp.data |= leftdata; + chkabs(); +} + +/* + factor() parses factor = number | identifier | * | (expression) | ! factor, + ! is complementation. Returns value in lastexp.offset, possible flags + IMPBIT, FORBIT, RELBIT and UNDBIT in lastexp.data, and segment in SEGM + part of lastexp.data, and lastexp.sym at imported symbol if IMPBIT. + If the factor is an identifier, LOOKUP is used to get its value + (so the ident is installed in the symbol table if necessary, with + default flags inidata). If the identifier is not a label, + (could be imported, or later in the program), its FORBIT is set. + The expression FORBIT, IMPBIT, RELBIT, UNDBIT and SEGM are then + taken from the identifier. +*/ + +PUBLIC void factor() +{ + switch (sym) + { + case SLASH: + /* context-sensitive, SLASH means a hex number here */ + context_hexconst(); + case INTCONST: + lastexp.data = 0; /* absolute & not forward or undefined */ + lastexp.offset = number; + getsym(); + return; + case IDENT: + { + register struct sym_s *symptr; + + symptr = gsymptr; + if (symptr->type & (MNREGBIT | MACBIT)) + experror(symptr->type & MACBIT ? MACUID : + symptr->data & REGBIT ? REGUID : MNUID); + else + { + if (!(symptr->type & (LABIT | VARBIT))) + { + symptr->data |= FORBIT; + lastexp.sym = symptr; + } + if (pass == 0) + { + lastexp.data = symptr->data & + (FORBIT | RELBIT | UNDBIT | SEGM); + /* possible flags for pass 1 */ + lastexp.offset = symptr->value_reg_or_op.value; + } + else + { + if ((lastexp.data = symptr->data) & IMPBIT) + lastexp.offset = 0; /* value != 0 for commons */ + /* OK even if UNDBIT */ + else + { + lastexp.offset = symptr->value_reg_or_op.value; + if (lastexp.data & UNDBIT) + experror(UNBLAB); + } + } + } + getsym(); + return; + } + case LBRACKET: + if (!asld_compatible) + break; /* error, LPAREN is the grouping symbol */ + getsym(); + expres(); + if (sym != RBRACKET) + error(RBEXP); + else + getsym(); + return; + case LPAREN: + if (asld_compatible) + break; /* error, LBRACKET is the grouping symbol */ + getsym(); + expres(); + if (sym != RPAREN) + error(RPEXP); + else + getsym(); + return; + case NOTOP: + getsym(); + factor(); + chkabs(); + lastexp.offset = ~lastexp.offset; + return; + case STAR: + /* context-sensitive, STAR means location counter here */ + lastexp.offset = lc; + if ((lastexp.data = lcdata) & UNDBIT && pass != 0) + experror(UNBLAB); + getsym(); + return; + } + experror(FACEXP); +} + +/* + string compare for IFC/ELSEIFC + expects (<string1>,<string2>) + returns logical value in lastexp +*/ + +PUBLIC void scompare() +{ + /* prepare flags for OK, lastexp.offset for error */ + lastexp.data = lastexp.offset = 0; + if (sym != LPAREN) + experror(LPEXP); + else + { + register char *string1; + register char *string2; + + for (string2 = string1 = lineptr; *string2 != ')'; ++string2) + if (*string2 == 0 || *string2 == ')') + { + symname = string2; + experror(COMEXP); + return; + } + while (*string1++ == *string2++) + ; + if (string2[-1] == ')') + { + if (string1[-1] == ',') + lastexp.offset = TRUE; /* else leave FALSE */ + } + else /* FALSE, keep reading to verify syntax */ + for (; *string2 != ')'; ++string2) + if (*string2 == 0 || *string2 == ',') + { + symname = string2; + experror(RPEXP); + } + } +} diff --git a/bin86-0.3/as/file.h b/bin86-0.3/as/file.h new file mode 100644 index 0000000..180b19b --- /dev/null +++ b/bin86-0.3/as/file.h @@ -0,0 +1,18 @@ +/* + * bin86/as/file.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* file.h - global variables involving files for assembler */ + +EXTERN fd_t binfil; /* binary output file (0 = memory) */ +EXTERN char *filnamptr; /* file name pointer */ +EXTERN fd_t infil0; /* initial input file */ +EXTERN fd_t infil; /* current input file (stacked, 0 = memory) */ +EXTERN unsigned char infiln; /* innum when file was opened */ +EXTERN unsigned char innum; /* counter for calls to opem */ +EXTERN fd_t lstfil; /* list output file (0 = standard) */ +EXTERN fd_t objfil; /* object output file */ +EXTERN fd_t symfil; /* symbol table output file */ +EXTERN char *truefilename; /* in case actual source name is a tmpname */ diff --git a/bin86-0.3/as/flag.h b/bin86-0.3/as/flag.h new file mode 100644 index 0000000..21859cf --- /dev/null +++ b/bin86-0.3/as/flag.h @@ -0,0 +1,11 @@ +/* + * bin86/as/flag.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* flag.h - global structured-flag variables for assembler */ + +EXTERN struct flags_s list; /* listing on/off */ +EXTERN struct flags_s maclist; /* list macros on/off */ +EXTERN struct flags_s warn; /* warnings on/off */ diff --git a/bin86-0.3/as/genbin.c b/bin86-0.3/as/genbin.c new file mode 100644 index 0000000..c215249 --- /dev/null +++ b/bin86-0.3/as/genbin.c @@ -0,0 +1,226 @@ +/* + * bin86/as/genbin.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* genbin.c - binary code generation routines for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "file.h" +#include "globvar.h" + +PRIVATE char *asmbeg; /* beginning of assembler code */ + /* for overwrite check */ + /* bss-init to zero = NULL and not changed */ +PRIVATE offset_t binfbuf; /* binary code buffer for file (counter) */ +PRIVATE offset_t binmax; /* maximum value of binmbuf for pass 1 */ +PRIVATE offset_t binmin; /* minimum value of binmbuf for pass 1 */ + +FORWARD void putbinoffset P((offset_t offset, count_t size)); + +/* write header to binary file */ + +PUBLIC void binheader() +{ + if ((innum = binfil) != 0x0) + { + writec(0x0); /* binary header byte */ +#ifdef LONG_BINHEADER + writeoff(binmax - binmin); /* program length */ + writeoff(binfbuf = binmin); /* program start */ +#else + writew((unsigned) (binmax - binmin)); /* program length */ + writew((unsigned) (binfbuf = binmin)); /* program start */ +#endif + } +} + +/* write trailer to binary file */ + +PUBLIC void bintrailer() +{ + if ((innum = binfil) != 0x0) + { + writec(0xFF); /* binary trailer byte */ + writew(0x0); /* further trailer bytes */ +#ifdef LONG_BINHEADER + writeoff(pedata & UNDBIT ? binmin : progent); /* entry point */ +#else + writew(pedata & UNDBIT ? (unsigned) binmin : (unsigned) progent); +#endif + } +} + +/* generate binary code for current line */ + +PUBLIC void genbin() +{ + struct address_s *adrptr; + char *bufptr; + unsigned char remaining; + + if (binaryg && mcount != 0x0) + { + if (popflags) + { + if (fcflag) + { + bufptr = databuf.fcbuf; + remaining = mcount; + do + putbin(*bufptr++); + while (--remaining != 0x0); + } + if (fdflag) + { + adrptr = databuf.fdbuf; + remaining = mcount; + do + { + putbinoffset(adrptr->offset, 0x2); + ++adrptr; + } + while ((remaining -= 0x2) != 0x0); + } +#if SIZEOF_OFFSET_T > 0x2 + if (fqflag) + { + adrptr = databuf.fqbuf; + remaining = mcount; + do + { + putbinoffset(adrptr->offset, 0x4); + ++adrptr; + } + while ((remaining -= 0x4) != 0x0); + } +#endif + } + else + { + remaining = mcount - 0x1; /* count opcode immediately */ +#ifdef I80386 + if (aprefix != 0x0) + { + putbin(aprefix); + --remaining; + } + if (oprefix != 0x0) + { + putbin(oprefix); + --remaining; + } + if (sprefix != 0x0) + { + putbin(sprefix); + --remaining; + } +#endif + if (page != 0x0) + { + putbin(page); + --remaining; + } + putbin(opcode); + if (remaining != 0x0) + { + if (postb != 0x0) + { + putbin(postb); + --remaining; + } +#ifdef I80386 + if (sib != NO_SIB) + { + putbin(sib); + --remaining; + } +#endif + if (remaining != 0x0) + putbinoffset(lastexp.offset, remaining); + } +#ifdef I80386 + if (immcount != 0x0) + putbinoffset(immadr.offset, immcount); +#endif + } + /* else no code for this instruction, or already generated */ + } +} + +/* initialise private variables */ + +PUBLIC void initbin() +{ + binmin = -1; /* greater than anything */ +} + +/* write char to binary file or directly to memory */ + +PUBLIC void putbin(c) +opcode_pt c; +{ + if (binfil != 0x0) + { + if (!binaryc) /* pass 1, just record limits */ + { + if (binmbuf < binmin) + binmin = binmbuf; + if (++binmbuf > binmax) + binmax = binmbuf; + } + else + { + if (binfbuf > binmbuf) + error(BWRAP); /* file buffer ahead of memory buffer */ + else + { + innum = binfil; + while (binfbuf < binmbuf) + { + writec(0x0);/* pad with nulls if file buffer behind */ + ++binfbuf; + } + writec(c); + binmbuf = ++binfbuf; + } + } + } + else if (binaryc && !(lcdata & UNDBIT)) + /* memory output, and enabled */ + { + register char *bufptr; + + if ((bufptr = (char *) binmbuf) >= asmbeg && bufptr < heapptr) + error(OWRITE); + else + *bufptr = c; + ++binmbuf; + } +} + +/* write sized offset to binary file or directly to memory */ + +PRIVATE void putbinoffset(offset, size) +offset_t offset; +count_t size; +{ + char buf[sizeof offset]; + +#if SIZEOF_OFFSET_T > 0x2 + u4cn(buf, offset, size); +#else + u2cn(buf, offset, size); +#endif + putbin(buf[0]); + if (size > 0x1) + putbin(buf[1]); + if (size > 0x2) + { + putbin(buf[2]); + putbin(buf[3]); + } +} diff --git a/bin86-0.3/as/genlist.c b/bin86-0.3/as/genlist.c new file mode 100644 index 0000000..6286d4b --- /dev/null +++ b/bin86-0.3/as/genlist.c @@ -0,0 +1,454 @@ +/* + * bin86/as/genlist.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* genlist.c - generate listing and error reports for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "flag.h" +#include "file.h" +#include "globvar.h" +#include "macro.h" +#include "scan.h" +#include "source.h" + +#define CODE_LIST_LENGTH (sizeof (struct code_listing_s) - 1) + /* length of formatted code listing */ +#define MAXERR 6 /* maximum errors listed per line */ + +struct error_s /* to record error info */ +{ + unsigned char errnum; + unsigned char position; +}; + +/* code listing format */ + +struct code_listing_s +{ + union linum_macro_u + { + char linum[LINUM_LEN]; + struct + { + char pad[1]; + char mark[1]; + char level[1]; + } + macro; + } + linum_or_macro; + char padlinum[1]; + char lc[4]; + char padlc[1]; +#ifdef I80386 + char lprefix[2]; + char aprefix[2]; + char oprefix[2]; + char sprefix[2]; +#endif + char page[2]; + char opcode[2]; + char postb[2]; +#ifdef I80386 + char sib[2]; +#endif + char padopcode[1]; +#if SIZEOF_OFFSET_T > 2 + char displ4[2]; + char displ3[2]; +#endif + char displ2[2]; + char displ1[2]; + char reldispl[1]; + char paddispl[1]; +#ifdef I80386 + char imm4[2]; + char imm3[2]; + char imm2[2]; + char imm1[2]; + char relimm[1]; + char padimm[1]; +#endif + char nullterm; +}; + +PRIVATE struct error_s errbuf[MAXERR]; /* error buffer */ +PRIVATE unsigned char errcount; /* # errors in line */ +PRIVATE bool_t erroverflow; /* set if too many errors on line */ + +FORWARD char *build_1hex_number P((unsigned num, char *where)); +FORWARD void list1 P((fd_t fd)); +FORWARD void listcode P((void)); +FORWARD void listerrors P((void)); +FORWARD void paderrorline P((unsigned nspaces)); + +/* format 1 byte number as 2 hex digits, return ptr to end */ + +PRIVATE char *build_1hex_number(num, where) +unsigned num; +register char *where; +{ + static char hexdigits[] = "0123456789ABCDEF"; + + where[0] = hexdigits[(num % 256) / 16]; + where[1] = hexdigits[num % 16]; + return where + 2; +} + +/* format 2 byte number as 4 hex digits, return ptr to end */ + +PUBLIC char *build_2hex_number(num, where) +unsigned num; +char *where; +{ + return build_1hex_number(num, build_1hex_number(num / 256, where)); +} + +/* format 2 byte number as decimal with given width (pad with leading '0's) */ +/* return ptr to end */ + +PUBLIC char *build_number(num, width, where) +unsigned num; +unsigned width; +register char *where; +{ + static unsigned powers_of_10[] = {1, 10, 100, 1000, 10000,}; + unsigned char digit; + unsigned char power; + register unsigned power_of_10; + + power = 5; /* actually 1 more than power */ + do + { + for (digit = '0', power_of_10 = (powers_of_10 - 1)[power]; + num >= power_of_10; num -= power_of_10) + ++digit; + if (power <= width) + *where++ = digit; + } + while (--power != 0); + return where; +} + +/* record number and position of error (or error buffer overflow) */ + +PUBLIC void error(errnum) +error_pt errnum; +{ + register struct error_s *errptr; + register struct error_s *errptrlow; + unsigned char position; + + if (errnum < MINWARN || warn.current) + { + if (errcount >= MAXERR) + erroverflow = TRUE; + else + { + position = symname - linebuf; + for (errptr = errbuf + errcount; + errptr > errbuf && errptr->position > position; + errptr = errptrlow) + { + errptrlow = errptr - 1; + errptr->errnum = errptrlow->errnum; + errptr->position = errptrlow->position; + } + errptr->errnum = errnum; + errptr->position = position; + ++errcount; + if (errnum >= MINWARN) + ++totwarn; + else + ++toterr; + } + } +} + +/* list 1 line to list file if any errors or flags permit */ +/* list line to console as well if any errors and list file is not console */ + +PUBLIC void listline() +{ + if (!listpre) + { + if (errcount || list.current && (!macflag || mcount != 0) || + macflag && maclist.current) + list1(lstfil); + if (errcount) + { + if (lstfil != STDOUT) + list1(STDOUT); + errcount = 0; + erroverflow = FALSE; + } + } +} + +/* list 1 line unconditionally */ + +PRIVATE void list1(fd) +fd_t fd; +{ + innum = fd; + listcode(); + write(innum, linebuf, lineptr - linebuf); + writenl(); + if (errcount != 0) + listerrors(); + listpre = TRUE; +} + +/* list object code for 1 line */ + +PRIVATE void listcode() +{ + unsigned char count; + struct code_listing_s *listptr; + int numlength; + char *numptr; + + listptr = (struct code_listing_s *) heapptr; + memset((char *) listptr, ' ', sizeof *listptr); + listptr->nullterm = 0; + if (macflag) + { + listptr->linum_or_macro.macro.mark[0] = '+'; + listptr->linum_or_macro.macro.level[0] = maclevel + ('a' - 1); + } + else + { + numlength = LINUM_LEN; + numptr = listptr->linum_or_macro.linum; + if (infiln != infil0) + { + *numptr++ = infiln - infil0 + ('a' - 1); + numlength = LINUM_LEN - 1; + } + build_number(linum, numlength, numptr); + } + if ((count = mcount) != 0 || popflags & POPLC) + build_2hex_number((u16_t) lc, listptr->lc); + if (popflags & POPLO) + { +#if SIZEOF_OFFSET_T > 2 + if (popflags & POPLONG) + build_2hex_number((u16_t) (lastexp.offset / (offset_t) 0x10000L), + listptr->displ4); +#endif + if (popflags & POPHI) + build_2hex_number((u16_t) lastexp.offset, listptr->displ2); + else + build_1hex_number((u16_t) lastexp.offset, listptr->displ1); + if (lastexp.data & RELBIT) + listptr->reldispl[0] = '>'; + } + else if (count != 0) + { +#ifdef I80386 + if (aprefix != 0) + { + --count; + build_1hex_number(aprefix, listptr->aprefix); + } + if (oprefix != 0) + { + --count; + build_1hex_number(oprefix, listptr->oprefix); + } + if (sprefix != 0) + { + --count; + build_1hex_number(sprefix, listptr->sprefix); + } +#endif + if (page != 0) + { + build_1hex_number(page, listptr->page); + --count; + } + build_1hex_number(opcode, listptr->opcode); + --count; + if (postb != 0) + { + --count; + build_1hex_number(postb, +#ifdef MC6809 + count == 0 ? listptr->displ1 : +#endif + listptr->postb); + } +#ifdef I80386 + if (sib != NO_SIB) + { + --count; + build_1hex_number(sib, listptr->sib); + } +#endif + if (count > 0) + { + build_1hex_number((opcode_pt) lastexp.offset, listptr->displ1); + if (lastexp.data & RELBIT) + listptr->reldispl[0] = '>'; + } + if (count > 1) + build_1hex_number((opcode_pt) lastexp.offset >> 0x8, + listptr->displ2); +#if SIZEOF_OFFSET_T > 2 + if (count > 2) + { + build_1hex_number((opcode_pt) (lastexp.offset >> 0x10), + listptr->displ3); + build_1hex_number((opcode_pt) (lastexp.offset >> 0x18), + listptr->displ4); + } +#endif +#ifdef I80386 + if (immcount > 0) + { + build_1hex_number((opcode_pt) immadr.offset, listptr->imm1); + if (immadr.data & RELBIT) + listptr->relimm[0] = '>'; + } + if (immcount > 1) + build_1hex_number((opcode_pt) immadr.offset >> 0x8, + listptr->imm2); + if (immcount > 2) + { + build_1hex_number((opcode_pt) (immadr.offset >> 0x10), + listptr->imm3); + build_1hex_number((opcode_pt) (immadr.offset >> 0x18), + listptr->imm4); + } +#endif + } + writes((char *) listptr); +} + +/* list errors, assuming some */ + +PRIVATE void listerrors() +{ + unsigned char column; + unsigned char errcol; /* column # in error line */ + unsigned char errcolw; /* working column in error line */ + char *errmsg; + struct error_s *errptr; + char *linep; + unsigned char remaining; + + paderrorline(CODE_LIST_LENGTH - LINUM_LEN); + remaining = errcount; + column = 0; /* column to match with error column */ + errcolw = errcol = CODE_LIST_LENGTH; /* working & col number on err line */ + errptr = errbuf; + linep = linebuf; + do + { + while (column < errptr->position) + { + ++column; + if (*linep++ == '\t') /* next tab (standard tabs only) */ + errcolw = (errcolw + 8) & 0xf8; + else + ++errcolw; + while (errcolw > errcol) + { + writec(' '); + ++errcol; + } + } + if (errcolw < errcol) /* position under error on new line */ + { + writenl(); + paderrorline(errcolw - LINUM_LEN); + } + writec('^'); + writes(errmsg = build_error_message(errptr->errnum, heapptr)); + errcol += strlen(errmsg); + ++errptr; + } + while (--remaining != 0); + writenl(); + if (erroverflow) + { + paderrorline(CODE_LIST_LENGTH - LINUM_LEN); + writesn(build_error_message(FURTHER, heapptr)); + } +} + +/* pad out error line to begin under 1st char of source listing */ + +PRIVATE void paderrorline(nspaces) +unsigned nspaces; +{ + int nstars = LINUM_LEN; + + while (nstars-- != 0) + writec('*'); /* stars under line number */ + while (nspaces-- != 0) + writec(' '); /* spaces out to error position */ +} + +/* write 1 character */ + +PUBLIC void writec(c) +char c; +{ + write(innum, &c, 1); +} + +/* write newline */ + +PUBLIC void writenl() +{ + writes(SOS_EOLSTR); +} + +/* write 1 offset_t, order to suit target */ + +PUBLIC void writeoff(offset) +offset_t offset; +{ + char buf[sizeof offset]; + +#if SIZEOF_OFFSET_T > 2 + u4c4(buf, offset); +#else + u2c2(buf, offset); +#endif + write(innum, buf, sizeof buf); +} + +/* write string */ + +PUBLIC void writes(s) +char *s; +{ + write(innum, s, strlen(s)); +} + +/* write string followed by newline */ + +PUBLIC void writesn(s) +char *s; +{ + writes(s); + writenl(); +} + +/* write 1 word, order to suit target */ + +PUBLIC void writew(word) +unsigned word; +{ + char buf[2]; + + u2c2(buf, (u16_t) word); + write(innum, buf, sizeof buf); +} diff --git a/bin86-0.3/as/genobj.c b/bin86-0.3/as/genobj.c new file mode 100644 index 0000000..fc42394 --- /dev/null +++ b/bin86-0.3/as/genobj.c @@ -0,0 +1,669 @@ +/* + * bin86/as/genobj.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* genobj.c - object code generation routines for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "file.h" +#include "globvar.h" + +#define OBJBUFSIZE 512 /* size of object code output buffer */ +#define isge2byteoffset(offset) ((offset) >= 0x100) +#define isge4byteoffset(offset) ((offset) >= 0x10000L) + +PRIVATE char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */ +PRIVATE char *absbuf; /* start */ +PRIVATE char *absbufend; /* last location + 1 */ +PRIVATE char *absbufptr; /* current location */ +PRIVATE struct sym_s **arrext; /* array of external symbol ptrs */ +PRIVATE char hid_objbuf[OBJBUFSIZE]; /* object code buffer */ +PRIVATE unsigned numext; /* number of external symbols */ +PRIVATE char *objbuf; /* start */ +PRIVATE char *objbufend; /* last location + 1 */ +PRIVATE char *objbufptr; /* current location */ +PRIVATE unsigned char relsize; /* current relocation size, 0 init */ + /* local to genobjadr, but here */ + /* because of static re-init bug */ +PRIVATE offset_t rmbcount; /* accumulator for repeated RMB's */ + +FORWARD void flushabs P((void)); +FORWARD void flushrmb P((void)); +FORWARD void genobjadr P((struct address_s *adrptr, int size)); +FORWARD void putobj1 P((opcode_pt c)); +FORWARD void putobj4 P((u32_t offset)); +FORWARD void putobjoffset P((offset_t offset, count_t size)); +FORWARD void putobjword P((unsigned word)); +FORWARD void writeobj P((char *buf, unsigned count)); + +/* accumulate RMB requests into 1 (so + and - requests cancel) */ + +PUBLIC void accumulate_rmb(offset) +offset_t offset; +{ + if (objectc) + { + flushabs(); + rmbcount += offset; + } +} + +/* flush absolute object code buffer to object code buffer if necessary */ + +PRIVATE void flushabs() +{ + if (absbufptr > absbuf) + { + putobj1((absbufptr - absbuf) | OBJ_ABS); + { + register char *bufptr; + + bufptr = absbuf; + do + putobj1(*bufptr); + while (++bufptr < absbufptr); + absbufptr = absbuf; + } + } +} + +/* flush object code buffer if necessary */ + +PUBLIC void flushobj() +{ + int ntowrite; + + if ((ntowrite = objbufptr - objbuf) > 0) + { + if (write(objfil, objbuf, ntowrite) != ntowrite) + { + error(OBJOUT); + listline(); + finishup(); + } + objbufptr = objbuf; + } +} + +/* flush RMB count if necessary */ + +PRIVATE void flushrmb() +{ + count_t size; + + if (rmbcount != 0) + { +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(rmbcount)) + { + putobj1(OBJ_SKIP_4); + size = 4; + } + else +#endif + if (isge2byteoffset(rmbcount)) + { + putobj1(OBJ_SKIP_2); + size = 2; + } + else + { + putobj1(OBJ_SKIP_1); + size = 1; + } + putobjoffset(rmbcount, size); + rmbcount = 0; + } +} + +/* generate object code for current line */ + +/* + any address parameter is (regrettably) in lastexp + any immediate parameter is (corectly) in immadr +*/ + +PUBLIC void genobj() +{ + struct address_s *adrptr; + char *bufptr; + unsigned char remaining; + + if (objectc && mcount != 0) + { + if (popflags) + { + if (fcflag) + { + bufptr = databuf.fcbuf; + remaining = mcount; + do + putabs(*bufptr++); + while (--remaining != 0); + } + if (fdflag) + { + adrptr = databuf.fdbuf; + remaining = mcount; + do + genobjadr(adrptr++, 2); + while ((remaining -= 2) != 0); + } +#if SIZEOF_OFFSET_T > 2 + if (fqflag) + { + adrptr = databuf.fqbuf; + remaining = mcount; + do + genobjadr(adrptr++, 4); + while ((remaining -= 4) != 0); + } +#endif + } + else + { + remaining = mcount - 1; /* count opcode immediately */ +#ifdef I80386 + if (aprefix != 0) + { + putabs(aprefix); + --remaining; + } + if (oprefix != 0) + { + putabs(oprefix); + --remaining; + } + if (sprefix != 0) + { + putabs(sprefix); + --remaining; + } +#endif + if (page != 0) + { + putabs(page); + --remaining; + } + putabs(opcode); + if (remaining != 0) + { + if (postb != 0) + { + putabs(postb); + --remaining; + } +#ifdef I80386 + if (sib != NO_SIB) + { + putabs(sib); + --remaining; + } +#endif + if (remaining != 0) + genobjadr(&lastexp, remaining); + } + } +#ifdef I80386 + if (immcount != 0) + genobjadr(&immadr, immcount); +#endif + } +} + +/* generate object code for current address */ + +PRIVATE void genobjadr(adrptr, size) +struct address_s *adrptr; +smallcount_t size; +{ + unsigned char byte; + unsigned symnum; + + if (!(adrptr->data & RELBIT)) + { + /* absolute address */ + + char buf[sizeof(offset_t)]; + +#if SIZEOF_OFFSET_T > 2 + u4cn(buf, adrptr->offset, size); +#else + u2cn(buf, adrptr->offset, size); +#endif + putabs(buf[0]); + if (size > 1) + putabs(buf[1]); + if (size > 2) + { + putabs(buf[2]); + putabs(buf[3]); + } + } + else + { + /* relocatable address */ + if (size != relsize) + /* set reloc size index |00|0000xx| */ + putobj((relsize = size) == 4 ? 0x03 : relsize); + if (!(adrptr->data & IMPBIT)) + { + /* offset relocation (known offset) */ + putobj((adrptr->data & SEGM) | OBJ_OFFSET_REL | pcrflag); + putobjoffset(adrptr->offset, size); + } + else + { + /* symbol relocation (imported symbol + offset) */ + { + register struct sym_s **copyptr; + + for (copyptr = arrext, symnum = 0; + symnum < numext && *copyptr++ != adrptr->sym; ++symnum) + ; + } + byte = OBJ_SYMBOL_REL; + if (isge2byteoffset(symnum)) + byte = OBJ_SYMBOL_REL | OBJ_S_MASK; +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(adrptr->offset)) + { + byte |= 0x03; /* 4 byte offset */ + size = 4; + } + else +#endif + if (isge2byteoffset(adrptr->offset)) + { + byte |= 0x02; /* 2 byte offset */ + size = 2; + } + else if (adrptr->offset != 0) + { + byte |= 0x01; /* 1 byte offset */ + size = 1; + } + else + size = 0; + putobj(byte | pcrflag); + if (isge2byteoffset(symnum)) + putobjword(symnum); + else + putobj1(symnum); + if (adrptr->offset != 0) + putobjoffset(adrptr->offset, size); + } + } +} + +/* initialise private variables */ + +PUBLIC void initobj() +{ + absbufend = (absbufptr = absbuf = hid_absbuf) + sizeof hid_absbuf; + objbufend = (objbufptr = objbuf = hid_objbuf) + sizeof hid_objbuf; +} + +/* + write header to object file + also build array of imported/exported symbols +*/ + +PUBLIC void objheader() +{ + static char module_header[] = + { +#ifdef I80386 + 0xA3, 0x86, + 1, 0, + (char) (0xA3 + 0x86 + 1 + 0), +#endif +#ifdef MC6809 + 'S', '1', /* 2 byte magic number */ + 0, 1, /* 2 byte number of modules in file */ + 'S' + '1' + 0 + 1, /* 1 byte checksum */ +#endif + }; + static char seg_max_sizes[] = + { + 0x55, /* all segments have maximum size 2^16 */ + 0x55, /* this is encoded by 0b01 4 times per byte */ + 0x55, /* other codes are 0b00 = max size 2^8 */ + 0x55, /* 0b10 = max size 2^24, 0b11 = max 2^32 */ + }; + unsigned char byte; + register struct sym_s **copyptr; + struct sym_s **copytop; + struct sym_s **hashptr; + struct lc_s *lcp; + char module_name[FILNAMLEN + 1]; + char *nameptr; + unsigned offset; + unsigned segsizebytes; + unsigned size; + unsigned char sizebits; + unsigned strsiz; /* size of object string table */ + unsigned symosiz; /* size of object symbol table */ + register struct sym_s *symptr; + u32_t textlength; + + if ((objectc = objectg) == 0) + return; + writeobj(module_header, sizeof module_header); + + /* calculate number of imported/exported symbols */ + /* and lengths of symbol and string tables */ + /* build array of imported/exported symbols */ + + symosiz = 0; + if (truefilename == NULL) + truefilename = filnamptr; + nameptr = strrchr(truefilename, DIRCHAR); + strcpy(module_name, nameptr != NULL ? nameptr + 1 : truefilename); + if ((nameptr = strrchr(module_name, '.')) != NULL) + *nameptr = 0; + strsiz = strlen(module_name) + 1; + align(heapptr); + for (hashptr = spt, arrext = copyptr = (struct sym_s **) heapptr; + hashptr < spt_top;) + if ((symptr = *hashptr++) != NULL) + do + { + if ((symptr->type & EXPBIT || symptr->data & IMPBIT) || + !globals_only_in_obj && symptr->name[0] != '.' && + !(symptr->type & (MNREGBIT | MACBIT | VARBIT))) + { + if (copyptr >= (struct sym_s **) heapend) + { + heapptr = (char *) copyptr; + fatalerror(OBJSYMOV); + } + *copyptr++ = symptr; + strsiz += symptr->length + 1; +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(symptr->value_reg_or_op.value)) + size = 4 + 4; + /* 4 is size of offset into string table and flags */ + /* 2nd 4 is for 4 byte offset */ + else +#endif + if (isge2byteoffset(symptr->value_reg_or_op.value)) + size = 4 + 2; + else if (symptr->value_reg_or_op.value != 0) + size = 4 + 1; + else + size = 4; + symosiz += size; + ++numext; + } + } + while ((symptr = symptr->next) != NULL); + heapptr = (char *) (copytop = copyptr); + + /* calculate length of text, and number of seg size bytes in header */ + + textlength = segsizebytes = 0; + lcp = lctab; + do + if (lcp->lc != 0) + { + textlength += lcp->lc; /* assuming text starts at 0 */ +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(lcp->lc)) + segsizebytes += 4; + else +#endif + segsizebytes += 2; /* use 2 byte size if possible */ + } + while (++lcp < lctabtop); + +/* + offset to text = length of header since only 1 module + header consists of: + module header sizeof module_header + offset to start of text 4 + length of text 4 + length of string area 2 + class 1 + revision 1 + seg max sizes sizeof seg_max_sizes + seg size descriptors 4 + seg sizes segsizebytes + symbol count 2 + symbol offsets and types symosiz + strings strsiz +*/ + + /* offset to start of text */ + + putobj4((u32_t) (sizeof module_header + 4 + 4 + 2 + 1 + 1 + + sizeof seg_max_sizes + 4 + segsizebytes + 2 + + symosiz) + strsiz); + + /* length of text */ + + putobj4((u32_t) textlength); + + /* length of string area */ + + putobjword(strsiz); + + /* class and revision */ + + putobj1(0); + putobj1(0); + + /* segment max sizes (constant) */ + + writeobj(seg_max_sizes, sizeof seg_max_sizes); + + /* segment size descriptors */ + /* produce only 0 and 2 byte sizes */ + + lcp = lctabtop; + byte = 0; + sizebits = OBJ_SEGSZ_TWO << 6; + do + { + --lcp; + if (lcp->lc != 0) + { + byte |= sizebits; +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(lcp->lc)) + byte |= sizebits >> 1; /* XXX - convert size 2 to size 4 */ +#endif + } + if ((sizebits >>= 2) == 0) + { + putobj1(byte); + sizebits = OBJ_SEGSZ_TWO << 6; + } + } + while (lcp > lctab); + + /* segment sizes */ + + do /* lcp starts at lctab */ + if (lcp->lc != 0) + { +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(lcp->lc)) + putobj4(lcp->lc); + else +#endif + putobjword((unsigned) lcp->lc); + } + while (++lcp < lctabtop); + + /* symbol count */ + + putobjword(numext); + + /* symbol offsets and types */ + + offset = strlen(module_name) + 1; /* 1st symbol begins after name */ + for (copyptr = arrext; copyptr < copytop;) + { + putobjword(offset); + symptr = *copyptr++; + byte = symptr->type & OBJ_N_MASK; +#if SIZEOF_OFFSET_T > 2 + if (isge4byteoffset(symptr->value_reg_or_op.value)) + { + byte |= OBJ_SZ_FOUR; + size = 4; + } + else +#endif + if (isge2byteoffset(symptr->value_reg_or_op.value)) + { + byte |= OBJ_SZ_TWO; + size = 2; + } + else if (symptr->value_reg_or_op.value != 0) + { + byte |= OBJ_SZ_ONE; + size = 1; + } + else + size = 0; + if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT)) + { + byte |= OBJ_SA_MASK; + symptr->data &= ~OBJ_I_MASK; + } + putobjword((byte << 0x8) | + (symptr->type & OBJ_E_MASK) | /* |E|0000000| */ + ((symptr->data & (OBJ_I_MASK | OBJ_A_MASK | OBJ_SEGM_MASK)) ^ + /* |0|I|0|A|SEGM| */ + RELBIT)); /* RELBIT by negative logic */ + if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT)) + symptr->data |= OBJ_I_MASK; + if (size != 0) + putobjoffset(symptr->value_reg_or_op.value, size); + offset += symptr->length + 1; + } + + /* strings */ + + writeobj(module_name, strlen(module_name)); + putobj1(0); + for (copyptr = arrext; copyptr < copytop;) + { + symptr = *copyptr++; + writeobj(symptr->name, symptr->length); + putobj1(0); + } + putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */ +} + +/* write trailer to object file */ + +PUBLIC void objtrailer() +{ + if (objectc) + { + putobj(0); /* end of object file */ + flushobj(); + } +} + +/* write char to absolute object code buffer, flush if necessary */ + +PUBLIC void putabs(c) +opcode_pt c; +{ + if (objectc) + { + if (rmbcount != 0) + flushrmb(); + if (absbufptr >= absbufend) + flushabs(); + *absbufptr++ = c; + } +} + +/* write char to object code buffer, flush if necessary */ + +PUBLIC void putobj(c) +opcode_pt c; +{ + if (objectc) + { + flushabs(); + flushrmb(); + putobj1(c); + } +} + +/* write char to object code buffer assuming nothing in absolute & rmb bufs */ + +PRIVATE void putobj1(c) +opcode_pt c; +{ + if (objbufptr >= objbufend) + flushobj(); + *objbufptr++ = c; +} + +/* write 32 bit offset to object code buffer assuming ... */ + +PRIVATE void putobj4(offset) +u32_t offset; +{ + char buf[sizeof offset]; + + u4c4(buf, offset); + writeobj(buf, sizeof buf); +} + +/* write sized offset to object code buffer assuming ... */ + +PRIVATE void putobjoffset(offset, size) +offset_t offset; +count_t size; +{ + char buf[sizeof offset]; + +#if SIZEOF_OFFSET_T > 2 + u4cn(buf, offset, size); +#else + u2cn(buf, offset, size); +#endif + putobj1(buf[0]); + if (size > 1) + putobj1(buf[1]); + if (size > 2) + { + putobj1(buf[2]); + putobj1(buf[3]); + } +} + +/* write word to object code buffer assuming ... */ + +PRIVATE void putobjword(word) +unsigned word; +{ + char buf[sizeof word]; + + u2c2(buf, word); + putobj1(buf[0]); + putobj1(buf[1]); +} + +/* write several bytes to object code buffer assuming ... */ + +PRIVATE void writeobj(buf, count) +char *buf; +unsigned count; +{ + do + putobj1(*buf++); + while (--count); +} diff --git a/bin86-0.3/as/gensym.c b/bin86-0.3/as/gensym.c new file mode 100644 index 0000000..e06d3ce --- /dev/null +++ b/bin86-0.3/as/gensym.c @@ -0,0 +1,202 @@ +/* + * bin86/as/gensym.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* gensym.c - generate symbol table for assembler */ + +#include "const.h" +#include "type.h" +#include "flag.h" +#include "file.h" +#include "globvar.h" + +FORWARD int printsym P((register struct sym_s *symptr, unsigned column)); +FORWARD void sort P((struct sym_s **array, struct sym_s **top, + bool_pt nameflag)); + +/* sort labels in symbol table on name and value */ +/* if listing, write human-readable table to list file */ +/* if symbol file, write machine-readable tables to it */ +/* pointers become relative to start of file */ + +PUBLIC void gensym() +{ + unsigned column; + struct sym_s **copyptr; + struct sym_s **copytop; + register struct sym_s **hashptr; + unsigned label_count; /* number of labels */ + unsigned labels_length; /* length of all label strings */ + unsigned label_stringptr; /* offset of label str from start of file */ + register struct sym_s *symptr; + struct sym_s **symlptr; /* start of symbol output list */ + + labels_length = label_count = 0; + + /* make copy of all relavant symbol ptrs on heap */ + /* original ptrs can now be modified, but need to be an array for sort */ + + align(heapptr); + for (hashptr = spt, symlptr = copyptr = (struct sym_s **) heapptr; + hashptr < spt_top;) + if ((symptr = *hashptr++) != NULL) + do + if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) + { + if (copyptr >= (struct sym_s **) heapend) + { + heapptr = (char *) copyptr; + error(SYMOUTOV); /* avoid recursive fatalerror */ + listline(); /* the main job is OK if here */ + goto sort_symbols; + } + *copyptr++ = symptr; + ++label_count; + labels_length += symptr->length + 3; /* 3 for type, value */ + } + while ((symptr = symptr->next) != NULL); + +sort_symbols: + sort(symlptr, copyptr, TRUE); /* sort on name */ + heapptr = (char *) (copytop = copyptr); + if (list.global) + { + innum = lstfil; + writenl(); + writesn("Symbols:"); + for (copyptr = symlptr, column = 0; copyptr < copytop;) + column = printsym(*copyptr++, column); + if (column != 0) + writenl(); + } + if ((innum = symfil) != 0) + { + writew(mapnum); + label_count *= 2; /* now length of ptr table (2 bytes per ptr) */ + label_stringptr = label_count + 6; + /* offset to current string in symbol file */ + /* 6 is length of header */ + labels_length += label_stringptr; + /* offset to ptr table sorted on value */ + writew(labels_length + label_count); + /* total length of symbol file */ + writew(label_count); + for (copyptr = symlptr; copyptr < copytop;) + { + symptr = *copyptr++; + writew((unsigned) + (symptr->next = (struct sym_s *) label_stringptr)); + /* reuse "next" to record string position */ + label_stringptr += symptr->length + 3; + } + for (copyptr = symlptr; copyptr < copytop;) + { + symptr = *copyptr++; + writew((unsigned) symptr->value_reg_or_op.value); + writec(symptr->type); + write(innum, symptr->name, symptr->length - 1); + writec(symptr->name[symptr->length - 1] | 0x80); + } + sort(symlptr, copyptr, FALSE); + /* sort on value */ + for (copyptr = symlptr; copyptr < copytop;) + { + symptr = *copyptr++; + writew((unsigned) symptr->next); /* now has string position */ + } + } +} + +/* print symbol nicely formatted for given column */ + +PRIVATE int printsym(symptr, column) +register struct sym_s *symptr; +unsigned column; +{ + unsigned char length; + register struct sym_listing_s *listptr; + char *outname; + char *symname; + + listptr = (struct sym_listing_s *) heapptr; + memset((char *) listptr, ' ', SYMLIS_LEN); + listptr->nullterm = 0; + if ((length = symptr->length) > SYMLIS_NAMELEN) + { + outname = listptr->name; + outname[length = SYMLIS_NAMELEN] = '+'; + } + else + outname = (listptr->name + SYMLIS_NAMELEN) - length; + symname = symptr->name; + do + *outname++ = *symname++; + while (--length != 0); + listptr->ar[0] = symptr->data & RELBIT ? 'R' : 'A'; + listptr->segm[0] = (symptr->data & SEGM) + '0'; + if (symptr->type & COMMBIT) + listptr->cein[0] = 'C'; + else if (symptr->type & ENTBIT) + listptr->cein[0] = 'N'; + else if (symptr->type & EXPBIT) + listptr->cein[0] = 'E'; + else if (symptr->data & IMPBIT) + listptr->cein[0] = 'I'; +#if SIZEOF_OFFSET_T > 2 + build_2hex_number((unsigned) (symptr->value_reg_or_op.value >> 16), + listptr->value); +#endif + build_2hex_number((unsigned) symptr->value_reg_or_op.value, + listptr->value); + writes((char *) listptr); + if ((column += SYMLIS_LEN) > (80 - SYMLIS_LEN)) + { + writenl(); + column = 0; + } + return column; +} + +/* shell sort symbols */ + +PRIVATE void sort(array, top, nameflag) +struct sym_s **array; +struct sym_s **top; +bool_pt nameflag; +{ + int gap; + int i; + int j; + register struct sym_s **left; + register struct sym_s **right; + int size; + struct sym_s *swap; + + size = top - array; + /* choose gaps according to Knuth V3 p95 */ + for (gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j) + ; + do + { + for (j = gap; j < size; ++j) + for (i = j - gap; i >= 0; i -= gap) + { + left = &array[i]; + right = &array[i + gap]; + if ((bool_t) nameflag) + { + if (strcmp((*left)->name, (*right)->name) <= 0) + break; + } + else if ((unsigned) (*left)->value_reg_or_op.value <= + (*right)->value_reg_or_op.value) + break; + swap = *left; + *left = *right; + *right = swap; + } + } + while ((gap /= 3) != 0); +} diff --git a/bin86-0.3/as/globvar.h b/bin86-0.3/as/globvar.h new file mode 100644 index 0000000..e560abc --- /dev/null +++ b/bin86-0.3/as/globvar.h @@ -0,0 +1,95 @@ +/* + * bin86/as/globvar.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* globvar.h - global variables for assembler */ + +/* global control and bookkeeping */ + +EXTERN bool_t binaryc; /* current binary code flag */ +EXTERN bool_t binaryg; /* global binary code flag */ +EXTERN offset_t binmbuf; /* offset in binary code buffer for memory */ + +EXTERN unsigned char dirpag; /* direct page */ + +EXTERN bool_t globals_only_in_obj; /* global symbols only in object file */ + +EXTERN bool_t jumps_long; /* make all jumps long */ + +EXTERN unsigned char mapnum; /* global map number */ + +EXTERN bool_t objectc; /* current object code flag */ +EXTERN bool_t objectg; /* global object code flag */ + +EXTERN bool_t pass; /* pass, FALSE means 0, TRUE means 1 */ + +EXTERN offset_t progent; /* program entry point */ + +EXTERN bool_t symgen; /* generate symbol table flag */ + +EXTERN unsigned toterr; /* total errors */ +EXTERN unsigned totwarn; /* total warnings */ + +/* bookeeping for current line */ + +EXTERN char *linebuf; /* buffer */ + +/* for symbol table routines */ + +EXTERN char *heapend; /* end of free space for symbol list */ +EXTERN char *heapptr; /* next free space in symbol list */ +EXTERN unsigned char inidata; /* init sym entry data governed by "u" flag */ +EXTERN struct sym_s **spt; /* symbol pointer table */ +EXTERN struct sym_s **spt_top; /* top of symbol ptr table */ + +/* for translator */ + +EXTERN struct sym_s *label; /* non-null if valid label starts line */ +EXTERN unsigned char pedata; /* shows how PROGENT bound, flags like LCDATA*/ +EXTERN unsigned char popflags; /* pseudo-op flags */ + +/* for BLOCK stack */ + +EXTERN struct block_s *blockstak; /* stack ptr */ +EXTERN unsigned char blocklevel; /* nesting level */ + +/* for IF stack */ + +EXTERN struct if_s *ifstak; /* stack ptr */ +EXTERN unsigned char iflevel; /* nesting level */ +EXTERN bool_t ifflag; /* set if assembling */ + +/* location counters for various segments */ + +EXTERN offset_t lc; /* location counter */ +EXTERN unsigned char lcdata; /* shows how lc is bound */ + /* FORBIT is set if lc is forward referenced */ + /* RELBIT is is if lc is relocat. (not ASEG) */ +EXTERN offset_t lcjump; /* lc jump between lines */ +#define mcount (((unsigned char *) &lcjump)[LOW_BYTE]) + /* low byte of lcjump */ +EXTERN struct lc_s *lcptr; /* top of current spot in lctab */ +EXTERN struct lc_s *lctab; /* start of lctab */ +EXTERN struct lc_s *lctabtop; /* top of lctab */ + +/* for code generator */ + +EXTERN opsize_t mnsize; /* 1 if forced byte operand size, else 0 */ +EXTERN opcode_t page; +EXTERN opcode_t opcode; +EXTERN opcode_t postb; /* postbyte, 0 if none */ +EXTERN unsigned char pcrflag; /* OBJ_RMASK set if addressing is PC-relative */ + +#ifdef I80386 + +EXTERN opcode_t aprefix; /* address size prefix or 0 */ +EXTERN bool_t asld_compatible; /* asld compatibility flag */ +EXTERN opsize_t defsize; /* current default size */ +EXTERN opsize_t idefsize; /* initial default size */ +EXTERN opcode_t oprefix; /* operand size prefix or 0 */ +EXTERN opcode_t sprefix; /* segment prefix or 0 */ +EXTERN opcode_t sib; /* scale-index-base byte */ + +#endif diff --git a/bin86-0.3/as/keywords.c b/bin86-0.3/as/keywords.c new file mode 100644 index 0000000..5d0bf84 --- /dev/null +++ b/bin86-0.3/as/keywords.c @@ -0,0 +1,733 @@ +/* + * bin86/as/keywords.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* keywords.c - keywords for assembler */ + +#include "const.h" +#include "type.h" +#include "opcode.h" + +/* registers */ +/* the register code (internal to assembler) is given in 1 byte */ +/* the "opcode" field is not used */ + +PUBLIC char regs[] = +{ +#ifdef I80386 + 2, 'B', 'P', BPREG, 0, + 2, 'B', 'X', BXREG, 0, + 2, 'D', 'I', DIREG, 0, + 2, 'S', 'I', SIREG, 0, + + 3, 'E', 'A', 'X', EAXREG, 0, + 3, 'E', 'B', 'P', EBPREG, 0, + 3, 'E', 'B', 'X', EBXREG, 0, + 3, 'E', 'C', 'X', ECXREG, 0, + 3, 'E', 'D', 'I', EDIREG, 0, + 3, 'E', 'D', 'X', EDXREG, 0, + 3, 'E', 'S', 'I', ESIREG, 0, + 3, 'E', 'S', 'P', ESPREG, 0, + + 2, 'A', 'X', AXREG, 0, + 2, 'C', 'X', CXREG, 0, + 2, 'D', 'X', DXREG, 0, + 2, 'S', 'P', SPREG, 0, + + 2, 'A', 'H', AHREG, 0, + 2, 'A', 'L', ALREG, 0, + 2, 'B', 'H', BHREG, 0, + 2, 'B', 'L', BLREG, 0, + 2, 'C', 'H', CHREG, 0, + 2, 'C', 'L', CLREG, 0, + 2, 'D', 'H', DHREG, 0, + 2, 'D', 'L', DLREG, 0, + + 2, 'C', 'S', CSREG, 0, + 2, 'D', 'S', DSREG, 0, + 2, 'E', 'S', ESREG, 0, + 2, 'F', 'S', FSREG, 0, + 2, 'G', 'S', GSREG, 0, + 2, 'S', 'S', SSREG, 0, + + 3, 'C', 'R', '0', CR0REG, 0, + 3, 'C', 'R', '2', CR2REG, 0, + 3, 'C', 'R', '3', CR3REG, 0, + 3, 'D', 'R', '0', DR0REG, 0, + 3, 'D', 'R', '1', DR1REG, 0, + 3, 'D', 'R', '2', DR2REG, 0, + 3, 'D', 'R', '3', DR3REG, 0, + 3, 'D', 'R', '6', DR6REG, 0, + 3, 'D', 'R', '7', DR7REG, 0, + 3, 'T', 'R', '3', TR3REG, 0, + 3, 'T', 'R', '4', TR4REG, 0, + 3, 'T', 'R', '5', TR5REG, 0, + 3, 'T', 'R', '6', TR6REG, 0, + 3, 'T', 'R', '7', TR7REG, 0, + + 2, 'S', 'T', ST0REG, 0, +#endif /* I80386 */ + +#ifdef MC6809 + 1, 'A', AREG, 0, + 1, 'B', BREG, 0, + 2, 'C', 'C', CCREG, 0, + 1, 'D', DREG, 0, + 2, 'D', 'P', DPREG, 0, + 2, 'P', 'C', PCREG, 0, + 3, 'P', 'C', 'R', PCREG, 0, + 1, 'S', SREG, 0, + 1, 'U', UREG, 0, + 1, 'X', XREG, 0, + 1, 'Y', YREG, 0, +#endif + 0 /* end of register list */ +}; + +#ifdef I80386 + +/* type sizes */ +/* the "opcode" field gives the type size */ + +PUBLIC char typesizes[] = +{ + 4, 'B', 'Y', 'T', 'E', BYTEOP, 1, + 5, 'D', 'W', 'O', 'R', 'D', DWORDOP, 4, + 5, 'F', 'W', 'O', 'R', 'D', FWORDOP, 6, + 3, 'F', 'A', 'R', FAROP, 0, + 3, 'P', 'T', 'R', PTROP, 0, + 5, 'P', 'W', 'O', 'R', 'D', PWORDOP, 6, + 5, 'Q', 'W', 'O', 'R', 'D', QWORDOP, 8, + 5, 'T', 'B', 'Y', 'T', 'E', TBYTEOP, 10, + 4, 'W', 'O', 'R', 'D', WORDOP, 2, + 0 /* end of typesize list */ +}; + +#endif + +/* ops */ +/* the routine number is given in 1 byte */ +/* the opcode is given in 1 byte (it is not used for pseudo-ops) */ + +PUBLIC char ops[] = +{ + /* pseudo-ops. The "opcode" field is unused and padded with a null byte */ + /* conditionals - must be first */ + 4, 'E', 'L', 'S', 'E', ELSEOP, 0, + 6, 'E', 'L', 'S', 'E', 'I', 'F', ELSEIFOP, 0, + 7, 'E', 'L', 'S', 'E', 'I', 'F', 'C', ELSEIFCOP, 0, + 5, 'E', 'N', 'D', 'I', 'F', ENDIFOP, 0, + 2, 'I', 'F', IFOP, 0, + 3, 'I', 'F', 'C', IFCOP, 0, + + /* unconditionals */ + 6, '.', 'A', 'L', 'I', 'G', 'N', ALIGNOP, 0, + 6, '.', 'A', 'S', 'C', 'I', 'I', FCCOP, 0, + 5, '.', 'B', 'L', 'K', 'B', RMBOP, 0, + 5, '.', 'B', 'L', 'K', 'W', BLKWOP, 0, + 5, 'B', 'L', 'O', 'C', 'K', BLOCKOP, 0, + 4, '.', 'B', 'S', 'S', BSSOP, 0, + 5, '.', 'B', 'Y', 'T', 'E', FCBOP, 0, + 4, 'C', 'O', 'M', 'M', COMMOP, 0, + 5, '.', 'C', 'O', 'M', 'M', COMMOP1, 0, + 5, '.', 'D', 'A', 'T', 'A', DATAOP, 0, + 6, '.', 'D', 'A', 'T', 'A', '1', FCBOP, 0, + 6, '.', 'D', 'A', 'T', 'A', '2', FDBOP, 0, + 6, '.', 'D', 'A', 'T', 'A', '4', FQBOP, 0, + 2, 'D', 'B', FCBOP, 0, + 2, 'D', 'D', FQBOP, 0, + 7, '.', 'D', 'E', 'F', 'I', 'N', 'E', EXPORTOP, 0, + 2, 'D', 'W', FDBOP, 0, + 3, 'E', 'N', 'D', PROCEOFOP, 0, + 4, 'E', 'N', 'D', 'B', ENDBOP, 0, + 5, 'E', 'N', 'T', 'E', 'R', ENTEROP, 0, + 5, 'E', 'N', 'T', 'R', 'Y', ENTRYOP, 0, + 3, 'E', 'Q', 'U', EQUOP, 0, + 5, '.', 'E', 'V', 'E', 'N', EVENOP, 0, + 6, 'E', 'X', 'P', 'O', 'R', 'T', EXPORTOP, 0, + 6, 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0, + 7, '.', 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0, + 5, 'E', 'X', 'T', 'R', 'N', IMPORTOP, 0, + 4, 'F', 'A', 'I', 'L', FAILOP, 0, + 5, '.', 'F', 'A', 'I', 'L', FAILOP, 0, + 3, 'F', 'C', 'B', FCBOP, 0, + 3, 'F', 'C', 'C', FCCOP, 0, + 3, 'F', 'D', 'B', FDBOP, 0, + 3, 'G', 'E', 'T', GETOP, 0, + 6, '.', 'G', 'L', 'O', 'B', 'L', GLOBLOP, 0, + 5, 'I', 'D', 'E', 'N', 'T', IDENTOP, 0, + 6, 'I', 'M', 'P', 'O', 'R', 'T', IMPORTOP, 0, + 7, 'I', 'N', 'C', 'L', 'U', 'D', 'E', GETOP, 0, + 5, 'L', 'C', 'O', 'M', 'M', LCOMMOP, 0, + 6, '.', 'L', 'C', 'O', 'M', 'M', LCOMMOP1, 0, + 5, '.', 'L', 'I', 'S', 'T', LISTOP, 0, + 3, 'L', 'O', 'C', LOCOP, 0, + 5, '.', 'L', 'O', 'N', 'G', FQBOP, 0, + 8, '.', 'M', 'A', 'C', 'L', 'I', 'S', 'T', MACLISTOP, 0, + 5, 'M', 'A', 'C', 'R', 'O', MACROOP, 0, + 4, '.', 'M', 'A', 'P', MAPOP, 0, + 3, 'O', 'R', 'G', ORGOP, 0, + 4, '.', 'O', 'R', 'G', ORGOP, 0, + 6, 'P', 'U', 'B', 'L', 'I', 'C', EXPORTOP, 0, + 3, 'R', 'M', 'B', RMBOP, 0, + 4, '.', 'R', 'O', 'M', DATAOP, 0, + 5, '.', 'S', 'E', 'C', 'T', SECTOP, 0, + 3, 'S', 'E', 'T', SETOP, 0, + 5, 'S', 'E', 'T', 'D', 'P', SETDPOP, 0, + 6, '.', 'S', 'H', 'O', 'R', 'T', FDBOP, 0, + 6, '.', 'S', 'P', 'A', 'C', 'E', RMBOP, 0, + 5, '.', 'T', 'E', 'X', 'T', TEXTOP, 0, + 5, 'U', 'S', 'E', '1', '6', USE16OP, 0, + 5, 'U', 'S', 'E', '3', '2', USE32OP, 0, + 5, '.', 'W', 'A', 'R', 'N', WARNOP, 0, + 5, '.', 'W', 'O', 'R', 'D', FDBOP, 0, + 6, '.', 'Z', 'E', 'R', 'O', 'W', BLKWOP, 0, + + /* hardware ops. The opcode field is now used */ +#ifdef I80386 + 3, 'A', 'A', 'A', INHER, 0x37, + 3, 'A', 'A', 'D', INHER_A, 0xD5, + 3, 'A', 'A', 'M', INHER_A, 0xD4, + 3, 'A', 'A', 'S', INHER, 0x3F, + 3, 'A', 'D', 'C', GROUP1, 0x10, + 3, 'A', 'D', 'D', GROUP1, 0x00, + 3, 'A', 'N', 'D', GROUP1, 0x20, + 4, 'A', 'R', 'P', 'L', EwGw, 0x63, + 3, 'B', 'C', 'C', BCC, 0x73, + 3, 'B', 'C', 'S', BCC, 0x72, + 3, 'B', 'E', 'Q', BCC, 0x74, + 3, 'B', 'G', 'E', BCC, 0x7D, + 3, 'B', 'G', 'T', BCC, 0x7F, + 3, 'B', 'H', 'I', BCC, 0x77, + 4, 'B', 'H', 'I', 'S', BCC, 0x73, + 3, 'B', 'L', 'E', BCC, 0x7E, + 3, 'B', 'L', 'O', BCC, 0x72, + 4, 'B', 'L', 'O', 'S', BCC, 0x76, + 3, 'B', 'L', 'T', BCC, 0x7C, + 3, 'B', 'M', 'I', BCC, 0x78, + 3, 'B', 'N', 'E', BCC, 0x75, + 5, 'B', 'O', 'U', 'N', 'D', GvMa, 0x62, + 3, 'B', 'P', 'C', BCC, 0x7B, + 3, 'B', 'P', 'L', BCC, 0x79, + 3, 'B', 'P', 'S', BCC, 0x7A, + 2, 'B', 'R', CALL, JMP_OPCODE, + 3, 'B', 'V', 'C', BCC, 0x71, + 3, 'B', 'V', 'S', BCC, 0x70, + 4, 'C', 'A', 'L', 'L', CALL, JSR_OPCODE, + 5, 'C', 'A', 'L', 'L', 'F', CALLI, 0x9A, + 5, 'C', 'A', 'L', 'L', 'I', CALLI, 0x9A, + 3, 'C', 'B', 'W', INHER16, 0x98, + 3, 'C', 'L', 'C', INHER, 0xF8, + 3, 'C', 'L', 'D', INHER, 0xFC, + 3, 'C', 'L', 'I', INHER, 0xFA, + 3, 'C', 'M', 'C', INHER, 0xF5, + 3, 'C', 'M', 'P', GROUP1, CMP_OPCODE_BASE, + 4, 'C', 'M', 'P', 'S', INHER, CMPSW_OPCODE, + 5, 'C', 'M', 'P', 'S', 'B', INHER, CMPSB_OPCODE, + 5, 'C', 'M', 'P', 'S', 'D', INHER32, CMPSW_OPCODE, + 5, 'C', 'M', 'P', 'S', 'W', INHER16, CMPSW_OPCODE, + 4, 'C', 'M', 'P', 'W', INHER16, CMPSW_OPCODE, + 4, 'C', 'S', 'E', 'G', INHER, 0x2E, + 3, 'C', 'W', 'D', INHER16, 0x99, + 4, 'C', 'W', 'D', 'E', INHER32, 0x98, + 3, 'C', 'D', 'Q', INHER32, 0x99, + 3, 'D', 'A', 'A', INHER, 0x27, + 3, 'D', 'A', 'S', INHER, 0x2F, + 4, 'D', 'S', 'E', 'G', INHER, 0x3E, + 3, 'D', 'E', 'C', INCDEC, 0x08, + 3, 'D', 'I', 'V', DIVMUL, 0x30, + 5, 'E', 'N', 'T', 'E', 'R', ENTER, 0xC8, + 4, 'E', 'S', 'E', 'G', INHER, 0x26, + 4, 'F', 'S', 'E', 'G', INHER, 0x64, + 4, 'G', 'S', 'E', 'G', INHER, 0x65, + 3, 'H', 'L', 'T', INHER, 0xF4, + 4, 'I', 'D', 'I', 'V', DIVMUL, 0x38, + 4, 'I', 'M', 'U', 'L', IMUL, 0x28, + 2, 'I', 'N', IN, 0xEC, + 3, 'I', 'N', 'C', INCDEC, 0x00, + 3, 'I', 'N', 'S', INHER, 0x6D, + 4, 'I', 'N', 'S', 'B', INHER, 0x6C, + 4, 'I', 'N', 'S', 'D', INHER32, 0x6D, + 4, 'I', 'N', 'S', 'W', INHER16, 0x6D, + 3, 'I', 'N', 'T', INT, 0xCD, + 4, 'I', 'N', 'T', 'O', INHER, 0xCE, + 3, 'I', 'N', 'W', IN, 0xED, + 4, 'I', 'R', 'E', 'T', INHER16, 0xCF, + 5, 'I', 'R', 'E', 'T', 'D', INHER32, 0xCF, + 1, 'J', CALL, JMP_SHORT_OPCODE, + 2, 'J', 'A', JCC, 0x77, + 3, 'J', 'A', 'E', JCC, 0x73, + 2, 'J', 'B', JCC, 0x72, + 3, 'J', 'B', 'E', JCC, 0x76, + 2, 'J', 'C', JCC, 0x72, + 4, 'J', 'C', 'X', 'E', JCXZ, 0x2, + 4, 'J', 'C', 'X', 'Z', JCXZ, 0x2, + 5, 'J', 'E', 'C', 'X', 'E', JCXZ, 0x4, + 5, 'J', 'E', 'C', 'X', 'Z', JCXZ, 0x4, + 2, 'J', 'E', JCC, 0x74, + 2, 'J', 'G', JCC, 0x7F, + 3, 'J', 'G', 'E', JCC, 0x7D, + 2, 'J', 'L', JCC, 0x7C, + 3, 'J', 'L', 'E', JCC, 0x7E, + 3, 'J', 'M', 'P', CALL, JMP_SHORT_OPCODE, + 4, 'J', 'M', 'P', 'F', CALLI, 0xEA, + 4, 'J', 'M', 'P', 'I', CALLI, 0xEA, + 3, 'J', 'N', 'A', JCC, 0x76, + 4, 'J', 'N', 'A', 'E', JCC, 0x72, + 3, 'J', 'N', 'B', JCC, 0x73, + 4, 'J', 'N', 'B', 'E', JCC, 0x77, + 3, 'J', 'N', 'C', JCC, 0x73, + 3, 'J', 'N', 'E', JCC, 0x75, + 3, 'J', 'N', 'G', JCC, 0x7E, + 4, 'J', 'N', 'G', 'E', JCC, 0x7C, + 3, 'J', 'N', 'L', JCC, 0x7D, + 4, 'J', 'N', 'L', 'E', JCC, 0x7F, + 3, 'J', 'N', 'O', JCC, 0x71, + 3, 'J', 'N', 'P', JCC, 0x7B, + 3, 'J', 'N', 'S', JCC, 0x79, + 3, 'J', 'N', 'Z', JCC, 0x75, + 2, 'J', 'O', JCC, 0x70, + 2, 'J', 'P', JCC, 0x7A, + 3, 'J', 'P', 'E', JCC, 0x7A, + 3, 'J', 'P', 'O', JCC, 0x7B, + 2, 'J', 'S', JCC, 0x78, + 2, 'J', 'Z', JCC, 0x74, + 4, 'L', 'A', 'H', 'F', INHER, 0x9F, + 3, 'L', 'D', 'S', GvMp, 0xC5, + 3, 'L', 'E', 'A', LEA, 0x8D, + 5, 'L', 'E', 'A', 'V', 'E', INHER, 0xC9, + 3, 'L', 'E', 'S', GvMp, 0xC4, + 4, 'L', 'O', 'C', 'K', INHER, 0xF0, + 4, 'L', 'O', 'D', 'B', INHER, 0xAC, + 4, 'L', 'O', 'D', 'S', INHER, 0xAD, + 5, 'L', 'O', 'D', 'S', 'B', INHER, 0xAC, + 5, 'L', 'O', 'D', 'S', 'D', INHER32, 0xAD, + 5, 'L', 'O', 'D', 'S', 'W', INHER16, 0xAD, + 4, 'L', 'O', 'D', 'W', INHER16, 0xAD, + 4, 'L', 'O', 'O', 'P', JCC, 0xE2, + 5, 'L', 'O', 'O', 'P', 'E', JCC, 0xE1, + 6, 'L', 'O', 'O', 'P', 'N', 'E', JCC, 0xE0, + 6, 'L', 'O', 'O', 'P', 'N', 'Z', JCC, 0xE0, + 5, 'L', 'O', 'O', 'P', 'Z', JCC, 0xE1, + 3, 'M', 'O', 'V', MOV, 0x88, + 4, 'M', 'O', 'V', 'S', INHER, MOVSW_OPCODE, + 5, 'M', 'O', 'V', 'S', 'B', INHER, MOVSB_OPCODE, + 5, 'M', 'O', 'V', 'S', 'D', INHER32, MOVSW_OPCODE, + 5, 'M', 'O', 'V', 'S', 'W', INHER16, MOVSW_OPCODE, + 4, 'M', 'O', 'V', 'W', INHER16, MOVSW_OPCODE, + 3, 'M', 'U', 'L', DIVMUL, 0x20, + 3, 'N', 'E', 'G', NEGNOT, 0x18, + 3, 'N', 'O', 'P', INHER, 0x90, + 3, 'N', 'O', 'T', NEGNOT, 0x10, + 2, 'O', 'R', GROUP1, 0x08, + 3, 'O', 'U', 'T', OUT, 0xEE, + 4, 'O', 'U', 'T', 'S', INHER, 0x6F, + 5, 'O', 'U', 'T', 'S', 'B', INHER, 0x6E, + 5, 'O', 'U', 'T', 'S', 'D', INHER32, 0x6F, + 5, 'O', 'U', 'T', 'S', 'W', INHER16, 0x6F, + 4, 'O', 'U', 'T', 'W', OUT, 0xEF, + 3, 'P', 'O', 'P', PUSHPOP, POP_OPCODE, + 4, 'P', 'O', 'P', 'A', INHER16, 0x61, + 5, 'P', 'O', 'P', 'A', 'D', INHER32, 0x61, + 4, 'P', 'O', 'P', 'F', INHER16, 0x9D, + 5, 'P', 'O', 'P', 'F', 'D', INHER32, 0x9D, + 4, 'P', 'U', 'S', 'H', PUSHPOP, PUSH_OPCODE, + 5, 'P', 'U', 'S', 'H', 'A', INHER16, 0x60, + 6, 'P', 'U', 'S', 'H', 'A', 'D', INHER32, 0x60, + 5, 'P', 'U', 'S', 'H', 'F', INHER16, 0x9C, + 6, 'P', 'U', 'S', 'H', 'F', 'D', INHER32, 0x9C, + 3, 'R', 'C', 'L', GROUP2, 0x10, + 3, 'R', 'C', 'R', GROUP2, 0x18, + 3, 'R', 'O', 'L', GROUP2, 0x00, + 3, 'R', 'O', 'R', GROUP2, 0x08, + 3, 'R', 'E', 'P', INHER, 0xF3, + 4, 'R', 'E', 'P', 'E', INHER, 0xF3, + 5, 'R', 'E', 'P', 'N', 'E', INHER, 0xF2, + 5, 'R', 'E', 'P', 'N', 'Z', INHER, 0xF2, + 4, 'R', 'E', 'P', 'Z', INHER, 0xF3, + 3, 'R', 'E', 'T', RET, 0xC3, + 4, 'R', 'E', 'T', 'F', RET, 0xCB, + 4, 'R', 'E', 'T', 'I', RET, 0xCB, + 4, 'S', 'A', 'H', 'F', INHER, 0x9E, + 3, 'S', 'A', 'L', GROUP2, 0x20, + 3, 'S', 'A', 'R', GROUP2, 0x38, + 3, 'S', 'B', 'B', GROUP1, 0x18, + 4, 'S', 'C', 'A', 'B', INHER, 0xAE, + 4, 'S', 'C', 'A', 'S', INHER, 0xAF, + 5, 'S', 'C', 'A', 'S', 'B', INHER, 0xAE, + 5, 'S', 'C', 'A', 'S', 'D', INHER32, 0xAF, + 5, 'S', 'C', 'A', 'S', 'W', INHER16, 0xAF, + 4, 'S', 'C', 'A', 'W', INHER16, 0xAF, + 3, 'S', 'E', 'G', SEG, 0x06, + 3, 'S', 'H', 'L', GROUP2, 0x20, + 3, 'S', 'H', 'R', GROUP2, 0x28, + 4, 'S', 'S', 'E', 'G', INHER, 0x36, + 3, 'S', 'T', 'C', INHER, 0xF9, + 3, 'S', 'T', 'D', INHER, 0xFD, + 3, 'S', 'T', 'I', INHER, 0xFB, + 4, 'S', 'T', 'O', 'B', INHER, 0xAA, + 4, 'S', 'T', 'O', 'S', INHER, 0xAB, + 5, 'S', 'T', 'O', 'S', 'B', INHER, 0xAA, + 5, 'S', 'T', 'O', 'S', 'D', INHER32, 0xAB, + 5, 'S', 'T', 'O', 'S', 'W', INHER16, 0xAB, + 4, 'S', 'T', 'O', 'W', INHER16, 0xAB, + 3, 'S', 'U', 'B', GROUP1, 0x28, + 4, 'T', 'E', 'S', 'T', TEST, 0x84, + 4, 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE, + 4, 'X', 'C', 'H', 'G', XCHG, 0x86, + 4, 'X', 'L', 'A', 'T', INHER, 0xD7, + 5, 'X', 'L', 'A', 'T', 'B', INHER, 0xD7, + 3, 'X', 'O', 'R', GROUP1, 0x30, + + /* floating point */ + 5, 'F', '2', 'X', 'M', '1', F_INHER, 0x70, + 4, 'F', 'A', 'B', 'S', F_INHER, 0x61, + 4, 'F', 'A', 'D', 'D', F_M4_M8_STST, 0x00, + 5, 'F', 'A', 'D', 'D', 'P', F_STST, 0x60, + 4, 'F', 'B', 'L', 'D', F_M10, 0x74, + 5, 'F', 'B', 'S', 'T', 'P', F_M10, 0x76, + 4, 'F', 'C', 'H', 'S', F_INHER, 0x60, + 5, 'F', 'C', 'L', 'E', 'X', F_W_INHER, 0xE2, + 4, 'F', 'C', 'O', 'M', F_M4_M8_OPTST, 0x02, + 5, 'F', 'C', 'O', 'M', 'P', F_M4_M8_OPTST, 0x03, + 6, 'F', 'C', 'O', 'M', 'P', 'P', F_INHER, 0x19, + 4, 'F', 'C', 'O', 'S', F_INHER, 0x7F, + 7, 'F', 'D', 'E', 'C', 'S', 'T', 'P', F_INHER, 0x76, + 5, 'F', 'D', 'I', 'S', 'I', F_W_INHER, 0xE1, + 4, 'F', 'D', 'I', 'V', F_M4_M8_STST, 0x06, + 5, 'F', 'D', 'I', 'V', 'P', F_STST, 0x67, + 5, 'F', 'D', 'I', 'V', 'R', F_M4_M8_STST, 0x07, + 6, 'F', 'D', 'I', 'V', 'R', 'P', F_STST, 0x66, + 4, 'F', 'E', 'N', 'I', F_W_INHER, 0xE0, + 5, 'F', 'F', 'R', 'E', 'E', F_ST, 0x50, + 5, 'F', 'I', 'A', 'D', 'D', F_M2_M4, 0x20, + 5, 'F', 'I', 'C', 'O', 'M', F_M2_M4, 0x22, + 6, 'F', 'I', 'C', 'O', 'M', 'P', F_M2_M4, 0x23, + 5, 'F', 'I', 'D', 'I', 'V', F_M2_M4, 0x26, + 6, 'F', 'I', 'D', 'I', 'V', 'R', F_M2_M4, 0x27, + 4, 'F', 'I', 'L', 'D', F_M2_M4_M8, 0x30, + 5, 'F', 'I', 'M', 'U', 'L', F_M2_M4, 0x21, + 7, 'F', 'I', 'N', 'C', 'S', 'T', 'P', F_INHER, 0x77, + 5, 'F', 'I', 'N', 'I', 'T', F_W_INHER, 0xE3, + 4, 'F', 'I', 'S', 'T', F_M2_M4, 0x32, + 5, 'F', 'I', 'S', 'T', 'P', F_M2_M4_M8, 0x33, + 5, 'F', 'I', 'S', 'U', 'B', F_M2_M4, 0x24, + 6, 'F', 'I', 'S', 'U', 'B', 'R', F_M2_M4, 0x25, + 3, 'F', 'L', 'D', F_M4_M8_M10_ST, 0x10, + 4, 'F', 'L', 'D', '1', F_INHER, 0x68, + 6, 'F', 'L', 'D', 'L', '2', 'E', F_INHER, 0x6A, + 6, 'F', 'L', 'D', 'L', '2', 'T', F_INHER, 0x69, + 5, 'F', 'L', 'D', 'C', 'W', F_M2, 0x15, + 6, 'F', 'L', 'D', 'E', 'N', 'V', F_M, 0x14, + 6, 'F', 'L', 'D', 'L', 'G', '2', F_INHER, 0x6C, + 6, 'F', 'L', 'D', 'L', 'N', '2', F_INHER, 0x6D, + 5, 'F', 'L', 'D', 'P', 'I', F_INHER, 0x6B, + 4, 'F', 'L', 'D', 'Z', F_INHER, 0x6E, + 4, 'F', 'M', 'U', 'L', F_M4_M8_STST, 0x01, + 5, 'F', 'M', 'U', 'L', 'P', F_STST, 0x61, + 6, 'F', 'N', 'C', 'L', 'E', 'X', F_INHER, 0xE2, + 6, 'F', 'N', 'D', 'I', 'S', 'I', F_INHER, 0xE1, + 5, 'F', 'N', 'E', 'N', 'I', F_INHER, 0xE0, + 6, 'F', 'N', 'I', 'N', 'I', 'T', F_INHER, 0xE3, + 4, 'F', 'N', 'O', 'P', F_INHER, 0x50, + 6, 'F', 'N', 'S', 'A', 'V', 'E', F_M, 0x56, + 6, 'F', 'N', 'S', 'T', 'C', 'W', F_M2, 0x17, + 7, 'F', 'N', 'S', 'T', 'E', 'N', 'V', F_M, 0x16, + 6, 'F', 'N', 'S', 'T', 'S', 'W', F_M2_AX, 0x57, + 6, 'F', 'P', 'A', 'T', 'A', 'N', F_INHER, 0x73, + 5, 'F', 'P', 'R', 'E', 'M', F_INHER, 0x78, + 6, 'F', 'P', 'R', 'E', 'M', '1', F_INHER, 0x75, + 5, 'F', 'P', 'T', 'A', 'N', F_INHER, 0x72, + 7, 'F', 'R', 'N', 'D', 'I', 'N', 'T', F_INHER, 0x7C, + 6, 'F', 'R', 'S', 'T', 'O', 'R', F_M, 0x54, + 5, 'F', 'S', 'A', 'V', 'E', F_W_M, 0x56, + 6, 'F', 'S', 'C', 'A', 'L', 'E', F_INHER, 0x7D, + 6, 'F', 'S', 'E', 'T', 'P', 'M', F_INHER, 0xE4, + 4, 'F', 'S', 'I', 'N', F_INHER, 0x7E, + 7, 'F', 'S', 'I', 'N', 'C', 'O', 'S', F_INHER, 0x7B, + 5, 'F', 'S', 'Q', 'R', 'T', F_INHER, 0x7A, + 3, 'F', 'S', 'T', F_M4_M8_ST, FST_ENCODED, + 5, 'F', 'S', 'T', 'C', 'W', F_W_M2, 0x17, + 6, 'F', 'S', 'T', 'E', 'N', 'V', F_W_M, 0x16, + 4, 'F', 'S', 'T', 'P', F_M4_M8_M10_ST, FSTP_ENCODED, + 5, 'F', 'S', 'T', 'S', 'W', F_W_M2_AX, 0x57, + 4, 'F', 'S', 'U', 'B', F_M4_M8_STST, 0x04, + 5, 'F', 'S', 'U', 'B', 'P', F_STST, 0x65, + 5, 'F', 'S', 'U', 'B', 'R', F_M4_M8_STST, 0x05, + 6, 'F', 'S', 'U', 'B', 'R', 'P', F_STST, 0x64, + 4, 'F', 'T', 'S', 'T', F_INHER, 0x64, + 5, 'F', 'U', 'C', 'O', 'M', F_OPTST, 0x54, + 6, 'F', 'U', 'C', 'O', 'M', 'P', F_OPTST, 0x55, + 7, 'F', 'U', 'C', 'O', 'M', 'P', 'P', F_INHER, 0xA9, + 5, 'F', 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE, + 4, 'F', 'X', 'A', 'M', F_INHER, 0x65, + 4, 'F', 'X', 'C', 'H', F_OPTST, 0x11, + 7, 'F', 'X', 'T', 'R', 'A', 'C', 'T', F_INHER, 0x74, + 5, 'F', 'Y', 'L', '2', 'X', F_INHER, 0x71, + 7, 'F', 'Y', 'L', '2', 'X', 'P', '1', F_INHER, 0x79, +#endif /* I80386 */ + +#ifdef MC6809 + 3, 'A', 'B', 'X', INHER, 0x3A, + 4, 'A', 'D', 'C', 'A', ALL, 0x89, + 4, 'A', 'D', 'C', 'B', ALL, 0xC9, + 4, 'A', 'D', 'D', 'A', ALL, 0x8B, + 4, 'A', 'D', 'D', 'B', ALL, 0xCB, + 4, 'A', 'D', 'D', 'D', ALL, 0xC3, + 4, 'A', 'N', 'D', 'A', ALL, 0x84, + 4, 'A', 'N', 'D', 'B', ALL, 0xC4, + 5, 'A', 'N', 'D', 'C', 'C', IMMED, 0x1C, + 3, 'A', 'S', 'L', ALTER, 0x08, + 4, 'A', 'S', 'L', 'A', INHER, 0x48, + 4, 'A', 'S', 'L', 'B', INHER, 0x58, + 3, 'A', 'S', 'R', ALTER, 0x07, + 4, 'A', 'S', 'R', 'A', INHER, 0x47, + 4, 'A', 'S', 'R', 'B', INHER, 0x57, + 3, 'B', 'C', 'C', SHORT, 0x24, + 3, 'B', 'C', 'S', SHORT, 0x25, + 3, 'B', 'E', 'Q', SHORT, 0x27, + 3, 'B', 'G', 'E', SHORT, 0x2C, + 3, 'B', 'G', 'T', SHORT, 0x2E, + 3, 'B', 'H', 'I', SHORT, 0x22, + 3, 'B', 'H', 'S', SHORT, 0x24, + 4, 'B', 'I', 'T', 'A', ALL, 0X85, + 4, 'B', 'I', 'T', 'B', ALL, 0XC5, + 3, 'B', 'L', 'E', SHORT, 0x2F, + 3, 'B', 'L', 'O', SHORT, 0x25, + 3, 'B', 'L', 'S', SHORT, 0x23, + 3, 'B', 'L', 'T', SHORT, 0x2D, + 3, 'B', 'M', 'I', SHORT, 0x2B, + 3, 'B', 'N', 'E', SHORT, 0x26, + 3, 'B', 'P', 'L', SHORT, 0x2A, + 3, 'B', 'R', 'A', SHORT, 0x20, + 4, 'L', 'B', 'R', 'A', LONG, 0x16, + 3, 'B', 'R', 'N', SHORT, 0x21, + 3, 'B', 'S', 'R', SHORT, 0x8D, + 4, 'L', 'B', 'S', 'R', LONG, 0x17, + 3, 'B', 'V', 'C', SHORT, 0x28, + 3, 'B', 'V', 'S', SHORT, 0x29, + 3, 'C', 'L', 'R', ALTER, 0x0F, + 4, 'C', 'L', 'R', 'A', INHER, 0x4F, + 4, 'C', 'L', 'R', 'B', INHER, 0x5F, + 4, 'C', 'M', 'P', 'A', ALL, 0x81, + 4, 'C', 'M', 'P', 'B', ALL, 0xC1, + 4, 'C', 'M', 'P', 'X', ALL, 0x8C, + 3, 'C', 'O', 'M', ALTER, 0x03, + 4, 'C', 'O', 'M', 'A', INHER, 0x43, + 4, 'C', 'O', 'M', 'B', INHER, 0x53, + 4, 'C', 'W', 'A', 'I', IMMED, 0x3C, + 3, 'D', 'A', 'A', INHER, 0x19, + 3, 'D', 'E', 'C', ALTER, 0x0A, + 4, 'D', 'E', 'C', 'A', INHER, 0x4A, + 4, 'D', 'E', 'C', 'B', INHER, 0x5A, + 4, 'E', 'O', 'R', 'A', ALL, 0x88, + 4, 'E', 'O', 'R', 'B', ALL, 0xC8, + 3, 'E', 'X', 'G', SWAP, 0x1E, + 3, 'I', 'N', 'C', ALTER, 0x0C, + 4, 'I', 'N', 'C', 'A', INHER, 0x4C, + 4, 'I', 'N', 'C', 'B', INHER, 0x5C, + 3, 'J', 'M', 'P', ALTER, 0x0E, + 3, 'J', 'S', 'R', ALTER, 0x8D, + 3, 'L', 'D', 'A', ALL, 0x86, + 3, 'L', 'D', 'B', ALL, 0xC6, + 3, 'L', 'D', 'D', ALL, 0xCC, + 3, 'L', 'D', 'U', ALL, 0xCE, + 3, 'L', 'D', 'X', ALL, 0x8E, + 4, 'L', 'E', 'A', 'S', INDEXD, 0x32, + 4, 'L', 'E', 'A', 'U', INDEXD, 0x33, + 4, 'L', 'E', 'A', 'X', INDEXD, 0x30, + 4, 'L', 'E', 'A', 'Y', INDEXD, 0x31, + 3, 'L', 'S', 'L', ALTER, 0x08, + 4, 'L', 'S', 'L', 'A', INHER, 0x48, + 4, 'L', 'S', 'L', 'B', INHER, 0x58, + 3, 'L', 'S', 'R', ALTER, 0x04, + 4, 'L', 'S', 'R', 'A', INHER, 0x44, + 4, 'L', 'S', 'R', 'B', INHER, 0x54, + 3, 'M', 'U', 'L', INHER, 0x3D, + 3, 'N', 'E', 'G', ALTER, 0x00, + 4, 'N', 'E', 'G', 'A', INHER, 0x40, + 4, 'N', 'E', 'G', 'B', INHER, 0x50, + 3, 'N', 'O', 'P', INHER, 0x12, + 3, 'O', 'R', 'A', ALL, 0x8A, + 3, 'O', 'R', 'B', ALL, 0xCA, + 4, 'O', 'R', 'C', 'C', IMMED, 0x1A, + 4, 'P', 'S', 'H', 'S', SSTAK, 0x34, + 4, 'P', 'S', 'H', 'U', USTAK, 0x36, + 4, 'P', 'U', 'L', 'S', SSTAK, 0x35, + 4, 'P', 'U', 'L', 'U', USTAK, 0x37, + 3, 'R', 'O', 'L', ALTER, 0x09, + 4, 'R', 'O', 'L', 'A', INHER, 0x49, + 4, 'R', 'O', 'L', 'B', INHER, 0x59, + 3, 'R', 'O', 'R', ALTER, 0x06, + 4, 'R', 'O', 'R', 'A', INHER, 0x46, + 4, 'R', 'O', 'R', 'B', INHER, 0x56, + 3, 'R', 'T', 'I', INHER, 0x3B, + 3, 'R', 'T', 'S', INHER, 0x39, + 4, 'S', 'B', 'C', 'A', ALL, 0x82, + 4, 'S', 'B', 'C', 'B', ALL, 0xC2, + 3, 'S', 'E', 'X', INHER, 0x1D, + 3, 'S', 'T', 'A', ALTER, 0x87, + 3, 'S', 'T', 'B', ALTER, 0xC7, + 3, 'S', 'T', 'D', ALTER, 0xCD, + 3, 'S', 'T', 'U', ALTER, 0xCF, + 3, 'S', 'T', 'X', ALTER, 0x8F, + 4, 'S', 'U', 'B', 'A', ALL, 0x80, + 4, 'S', 'U', 'B', 'B', ALL, 0xC0, + 4, 'S', 'U', 'B', 'D', ALL, 0x83, + 3, 'S', 'W', 'I', INHER, 0x3F, + 4, 'S', 'Y', 'N', 'C', INHER, 0x13, + 3, 'T', 'F', 'R', SWAP, 0x1F, + 3, 'T', 'S', 'T', ALTER, 0x0D, + 4, 'T', 'S', 'T', 'A', INHER, 0x4D, + 4, 'T', 'S', 'T', 'B', INHER, 0x5D, +#endif /* MC6809 */ + 0 /* end of ops */ +}; + +PUBLIC char page1ops[] = +{ +#ifdef I80386 + 3, 'B', 'S', 'F', GvEv, 0xBC, + 3, 'B', 'S', 'R', GvEv, 0xBD, + 5, 'B', 'S', 'W', 'A', 'P', BSWAP, 0xC8, + 2, 'B', 'T', GROUP8, 0x20, + 3, 'B', 'T', 'C', GROUP8, 0x38, + 3, 'B', 'T', 'R', GROUP8, 0x30, + 3, 'B', 'T', 'S', GROUP8, 0x28, + 4, 'C', 'L', 'T', 'S', INHER, 0x06, + 7, 'C', 'M', 'P', 'X', 'C', 'H', 'G', ExGx, 0xA6, + 4, 'I', 'N', 'V', 'D', INHER, 0x08, + 6, 'I', 'N', 'V', 'L', 'P', 'G', GROUP7, 0x38, + 3, 'L', 'A', 'R', GvEv, 0x02, + 3, 'L', 'F', 'S', GvMp, 0xB4, + 4, 'L', 'G', 'D', 'T', GROUP7, 0x10, + 3, 'L', 'G', 'S', GvMp, 0xB5, + 4, 'L', 'I', 'D', 'T', GROUP7, 0x18, + 4, 'L', 'L', 'D', 'T', GROUP6, 0x10, + 4, 'L', 'M', 'S', 'W', GROUP7, 0x30, + 3, 'L', 'S', 'L', GvEv, 0x03, + 3, 'L', 'S', 'S', GvMp, 0xB2, + 3, 'L', 'T', 'R', GROUP6, 0x18, + 5, 'M', 'O', 'V', 'S', 'X', MOVX, 0xBE, + 5, 'M', 'O', 'V', 'Z', 'X', MOVX, 0xB6, + 4, 'S', 'E', 'T', 'A', SETCC, 0x97, + 5, 'S', 'E', 'T', 'A', 'E', SETCC, 0x93, + 4, 'S', 'E', 'T', 'B', SETCC, 0x92, + 5, 'S', 'E', 'T', 'B', 'E', SETCC, 0x96, + 4, 'S', 'E', 'T', 'C', SETCC, 0x92, + 4, 'S', 'E', 'T', 'E', SETCC, 0x94, + 4, 'S', 'E', 'T', 'G', SETCC, 0x9F, + 5, 'S', 'E', 'T', 'G', 'E', SETCC, 0x9D, + 4, 'S', 'E', 'T', 'L', SETCC, 0x9C, + 5, 'S', 'E', 'T', 'L', 'E', SETCC, 0x9E, + 5, 'S', 'E', 'T', 'N', 'A', SETCC, 0x96, + 6, 'S', 'E', 'T', 'N', 'A', 'E', SETCC, 0x92, + 5, 'S', 'E', 'T', 'N', 'B', SETCC, 0x93, + 6, 'S', 'E', 'T', 'N', 'B', 'E', SETCC, 0x97, + 5, 'S', 'E', 'T', 'N', 'C', SETCC, 0x93, + 5, 'S', 'E', 'T', 'N', 'E', SETCC, 0x95, + 5, 'S', 'E', 'T', 'N', 'G', SETCC, 0x9E, + 6, 'S', 'E', 'T', 'N', 'G', 'E', SETCC, 0x9C, + 5, 'S', 'E', 'T', 'N', 'L', SETCC, 0x9D, + 6, 'S', 'E', 'T', 'N', 'L', 'E', SETCC, 0x9F, + 5, 'S', 'E', 'T', 'N', 'O', SETCC, 0x91, + 5, 'S', 'E', 'T', 'N', 'P', SETCC, 0x9B, + 5, 'S', 'E', 'T', 'N', 'S', SETCC, 0x99, + 5, 'S', 'E', 'T', 'N', 'Z', SETCC, 0x95, + 4, 'S', 'E', 'T', 'O', SETCC, 0x90, + 4, 'S', 'E', 'T', 'P', SETCC, 0x9A, + 5, 'S', 'E', 'T', 'P', 'E', SETCC, 0x9A, + 5, 'S', 'E', 'T', 'P', 'O', SETCC, 0x9B, + 4, 'S', 'E', 'T', 'S', SETCC, 0x98, + 4, 'S', 'E', 'T', 'Z', SETCC, 0x94, + 4, 'S', 'G', 'D', 'T', GROUP7, 0x00, + 4, 'S', 'I', 'D', 'T', GROUP7, 0x08, + 4, 'S', 'H', 'L', 'D', SH_DOUBLE, 0xA4, + 4, 'S', 'H', 'R', 'D', SH_DOUBLE, 0xAC, + 4, 'S', 'L', 'D', 'T', GROUP6, 0x00, + 4, 'S', 'M', 'S', 'W', GROUP7, 0x20, + 3, 'S', 'T', 'R', GROUP6, 0x08, + 4, 'V', 'E', 'R', 'R', GROUP6, 0x20, + 4, 'V', 'E', 'R', 'W', GROUP6, 0x28, + 6, 'W', 'B', 'I', 'N', 'V', 'D', INHER, 0x09, + 4, 'X', 'A', 'D', 'D', ExGx, 0xC0, +#endif /* I80386 */ + +#ifdef MC6809 + 4, 'L', 'B', 'C', 'C', LONG, 0x24, + 4, 'L', 'B', 'C', 'S', LONG, 0x25, + 4, 'L', 'B', 'E', 'Q', LONG, 0x27, + 4, 'L', 'B', 'G', 'E', LONG, 0x2C, + 4, 'L', 'B', 'G', 'T', LONG, 0x2E, + 4, 'L', 'B', 'H', 'I', LONG, 0x22, + 4, 'L', 'B', 'H', 'S', LONG, 0x24, + 4, 'L', 'B', 'L', 'E', LONG, 0x2F, + 4, 'L', 'B', 'L', 'O', LONG, 0x25, + 4, 'L', 'B', 'L', 'S', LONG, 0x23, + 4, 'L', 'B', 'L', 'T', LONG, 0x2D, + 4, 'L', 'B', 'M', 'I', LONG, 0x2B, + 4, 'L', 'B', 'N', 'E', LONG, 0x26, + 4, 'L', 'B', 'P', 'L', LONG, 0x2A, + 4, 'L', 'B', 'R', 'N', LONG, 0x21, + 4, 'L', 'B', 'V', 'C', LONG, 0x28, + 4, 'L', 'B', 'V', 'S', LONG, 0x29, + 4, 'C', 'M', 'P', 'D', ALL, 0x83, + 4, 'C', 'M', 'P', 'Y', ALL, 0x8C, + 3, 'L', 'D', 'S', ALL, 0xCE, + 3, 'L', 'D', 'Y', ALL, 0x8E, + 3, 'S', 'T', 'S', ALTER, 0xCF, + 3, 'S', 'T', 'Y', ALTER, 0x8F, + 4, 'S', 'W', 'I', '2', INHER, 0x3F, +#endif /* MC6809 */ + 0 /* end of page 1 ops */ +}; + +PUBLIC char page2ops[] = +{ +#ifdef MC6809 + 4, 'C', 'M', 'P', 'S', ALL, 0x8C, + 4, 'C', 'M', 'P', 'U', ALL, 0x83, + 4, 'S', 'W', 'I', '3', INHER, 0x3F, +#endif + 0 /* end of page 2 ops */ +}; + +#ifdef I80386 +# ifdef MNSIZE +PUBLIC char bytesizeops[] = +{ + 4, 'A', 'D', 'C', 'B', GROUP1, 0x10, + 4, 'A', 'D', 'D', 'B', GROUP1, 0x00, + 4, 'A', 'N', 'D', 'B', GROUP1, 0x20, + 4, 'C', 'M', 'P', 'B', GROUP1, CMP_OPCODE_BASE, + 4, 'D', 'E', 'C', 'b', INCDEC, 0x08, + 4, 'D', 'I', 'V', 'B', DIVMUL, 0x30, + 5, 'I', 'D', 'I', 'V', 'B', DIVMUL, 0x38, + 5, 'I', 'M', 'U', 'L', 'B', IMUL, 0x28, + 3, 'I', 'N', 'B', IN, 0xEC, + 4, 'I', 'N', 'C', 'B', INCDEC, 0x00, + 4, 'M', 'O', 'V', 'B', MOV, 0x88, + 4, 'M', 'U', 'L', 'B', DIVMUL, 0x20, + 4, 'N', 'E', 'G', 'B', NEGNOT, 0x18, + 4, 'N', 'O', 'T', 'B', NEGNOT, 0x10, + 3, 'O', 'R', 'B', GROUP1, 0x08, + 4, 'O', 'U', 'T', 'B', OUT, 0xEE, + 4, 'R', 'C', 'L', 'B', GROUP2, 0x10, + 4, 'R', 'C', 'R', 'B', GROUP2, 0x18, + 4, 'R', 'O', 'L', 'B', GROUP2, 0x00, + 4, 'R', 'O', 'R', 'B', GROUP2, 0x08, + 4, 'S', 'A', 'L', 'B', GROUP2, 0x20, + 4, 'S', 'A', 'R', 'B', GROUP2, 0x38, + 4, 'S', 'H', 'L', 'B', GROUP2, 0x20, + 4, 'S', 'H', 'R', 'B', GROUP2, 0x28, + 4, 'S', 'B', 'B', 'B', GROUP1, 0x18, + 4, 'S', 'U', 'B', 'B', GROUP1, 0x28, + 5, 'T', 'E', 'S', 'T', 'B', TEST, 0x84, + 5, 'X', 'C', 'H', 'G', 'B', XCHG, 0x86, + 4, 'X', 'O', 'R', 'B', GROUP1, 0x30, + 0 /* end of byte size ops */ +}; +# endif /* MNSIZE */ +#endif /* I80386 */ diff --git a/bin86-0.3/as/macro.c b/bin86-0.3/as/macro.c new file mode 100644 index 0000000..103ed08 --- /dev/null +++ b/bin86-0.3/as/macro.c @@ -0,0 +1,174 @@ +/* + * bin86/as/macro.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* macro.c - expand macros for assembler */ + +#include "const.h" +#include "type.h" +#include "globvar.h" +#include "scan.h" +#undef EXTERN +#define EXTERN +#include "macro.h" + +/* + Enter macro: stack macro and get its parameters. + Parameters form a linked list of null-terminated strings of form + next:string. The first string is the macro number in 4 bytes. +*/ + +PUBLIC void entermac(symptr) +struct sym_s *symptr; +{ + if (maclevel >= MAXMAC) + error(MACOV); + else if (macpar + 2 > macptop) + error(PAROV); /* no room for 0th param */ + /* (2 structs to fit it!) */ + else + { + char ch; + struct schain_s *param1; + register char *reglineptr; + register char *stringptr; + + ++maclevel; + (--macstak)->text = (char *) symptr->value_reg_or_op.value; + macstak->parameters = param1 = macpar; + param1->next = NULL; + *(stringptr = build_number(++macnum, 3, param1->string)) = 0; + macpar = (struct schain_s *) (stringptr + 1); + /* TODO: alignment */ + getsym(); + if (sym != LPAREN) + return; /* no other params */ + reglineptr = lineptr; + stringptr = macpar->string; + while (TRUE) + { + if (stringptr >= (char *) macptop) + { + symname = reglineptr; + error(PAROV); + return; + } + ch = *reglineptr++; + if (ch == '/') + /* escaped means no special meaning for slash, comma, paren */ + ch = *reglineptr++; + else if (ch == ',' || ch == ')') + { + if (stringptr >= (char *) macptop) + { + symname = reglineptr; + error(PAROV); /* no room for null */ + return; + } + *stringptr = 0; + param1->next = macpar; /* ptr from previous */ + (param1 = macpar)->next = NULL; + /* this goes nowhere */ + macpar = (struct schain_s *) (stringptr + 1); + /* but is finished OK - TODO align */ + stringptr = macpar->string; + if (ch == ')') + return; + continue; + } + if ((*stringptr++ = ch) == 0) + { + symname = reglineptr; + error(RPEXP); + return; + } + } + } +} + +/* MACRO pseudo-op */ + +PUBLIC void pmacro() +{ + bool_t saving; + bool_t savingc; + struct sym_s *symptr; + + saving = /* prepare for bad macro */ + savingc = FALSE; /* normally don't save comments */ + macload = TRUE; /* show loading */ + if (label != NULL) + error(ILLAB); + else if (sym != IDENT) + error(LABEXP); + else + { + symptr = gsymptr; + if (symptr->type & MNREGBIT) + error(LABEXP); + else if (symptr->type & LABIT || symptr->data & FORBIT) + error(RELAB); + else if (pass == 0 || symptr->type & REDBIT) + /* copy on pass 0, also pass 1 if redefined */ + { + saving = TRUE; + if (symptr->type & MACBIT) + symptr->type |= REDBIT; + else + symptr->type |= MACBIT; + symptr->data = UNDBIT; /* undefined till end */ + symptr->value_reg_or_op.value = (unsigned) heapptr; + /* beginning of store for macro */ + /* value s.b. (char *) */ + getsym_nolookup(); /* test for "C" */ + if (sym == IDENT && lineptr == symname + 1 && *symname == 'C') + savingc = TRUE; + } + } + while (TRUE) + { + skipline(); + listline(); + readline(); + if (!macload) + break; /* macload cleared to show eof */ + getsym_nolookup(); + if (sym == IDENT) + { + if (lineptr == symname + 4 && strncmp(symname, "MEND", 4) == 0) + break; + } + else if (sym != MACROARG) + { + if (!savingc) + continue; /* don't save comment */ + } + if (!saving) + continue; + { + register char *reglineptr; + register char *regheapptr; + + reglineptr = linebuf; + regheapptr = heapptr; + do + { + if (regheapptr >= heapend) + { + heapptr = regheapptr; + fatalerror(SYMOV); /* won't fit */ + } + } + while ((*regheapptr++ = *reglineptr++) != EOLCHAR); + heapptr = regheapptr; + } + } + macload = FALSE; + if (saving) + { + *heapptr++ = ETB; + symptr->data = 0; + } +} diff --git a/bin86-0.3/as/macro.h b/bin86-0.3/as/macro.h new file mode 100644 index 0000000..9fdee58 --- /dev/null +++ b/bin86-0.3/as/macro.h @@ -0,0 +1,16 @@ +/* + * bin86/as/macro.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* macro.h - global variables for macro expansion for assembler */ + +EXTERN bool_t macflag; /* inside macro flag */ +EXTERN bool_t macload; /* loading macro flag */ +EXTERN unsigned macnum; /* macro call counter */ + +EXTERN unsigned char maclevel; /* nesting level */ +EXTERN struct schain_s *macpar; /* parameter save buffer */ +EXTERN struct schain_s *macptop; /* top of param buffer (+1) */ +EXTERN struct macro_s *macstak; /* stack ptr */ diff --git a/bin86-0.3/as/mops.c b/bin86-0.3/as/mops.c new file mode 100644 index 0000000..be4e0f6 --- /dev/null +++ b/bin86-0.3/as/mops.c @@ -0,0 +1,2840 @@ +/* + * bin86/as/mops.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* mops.c - handle pseudo-ops */ + +#include "const.h" +#include "type.h" +#include "globvar.h" +#include "opcode.h" +#include "scan.h" +#undef EXTERN +#define EXTERN +#include "address.h" + +#define is8bitadr(offset) ((offset_t) offset < 0x100) +#define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100) +#define pass2 pass + +FORWARD void mshort2 P((void)); +FORWARD reg_pt regchk P((void)); +FORWARD void reldata P((void)); + +#ifdef I80386 + +#define iswordadr(offset) ((offset_t) (offset) < 0x10000L) +#define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L) +#define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL) + +#define BYTE_SEGWORD 0x00 +#define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG) + +#define BASE_MASK 0x07 +#define BASE_SHIFT 0 +#define INDEX_MASK 0x38 +#define INDEX_SHIFT 3 +#define MOD_MASK 0xC0 +# define REG_MOD 0xC0 +# define MEM0_MOD 0x00 +# define MEM1_MOD 0x40 +# define MEM2_MOD 0x80 +#define REG_MASK 0x38 +#define REG_SHIFT 3 +#define RM_MASK 0x07 +#define RM_SHIFT 0 +# define D16_RM 0x06 +# define D32_RM 0x05 +# define SIB_NOBASE 0x05 +# define SIB_RM 0x04 +#define SREG_MASK 0x38 +#define SREG_SHIFT 3 +#define SS_MASK 0xC0 +#define SS_SHIFT 6 + +#define SEGMOV 0x04 +#define SIGNBIT 0x02 +#define TOREGBIT 0x02 +#define WORDBIT 0x01 + +PRIVATE opcode_t baseind16[] = +{ + 0x00, /* BP + BP, illegal */ + 0x00, /* BX + BP, illegal */ + 0x03, /* DI + BP */ + 0x02, /* SI + BP */ + 0x00, /* BP + BX, illegal */ + 0x00, /* BX + BX, illegal */ + 0x01, /* DI + BX */ + 0x00, /* SI + BX */ + 0x03, /* BP + DI */ + 0x01, /* BX + DI */ + 0x00, /* DI + DI, illegal */ + 0x00, /* SI + DI, illegal */ + 0x02, /* BP + SI */ + 0x00, /* BX + SI */ + 0x00, /* DI + SI, illegal */ + 0x00, /* SI + SI, illegal */ +}; + +PRIVATE opcode_t regbits[] = +{ + 0x05 << REG_SHIFT, /* BP */ + 0x03 << REG_SHIFT, /* BX */ + 0x07 << REG_SHIFT, /* DI */ + 0x06 << REG_SHIFT, /* SI */ + + 0x00 << REG_SHIFT, /* EAX */ + 0x05 << REG_SHIFT, /* EBP */ + 0x03 << REG_SHIFT, /* EBX */ + 0x01 << REG_SHIFT, /* ECX */ + 0x07 << REG_SHIFT, /* EDI */ + 0x02 << REG_SHIFT, /* EDX */ + 0x06 << REG_SHIFT, /* ESI */ + 0x04 << REG_SHIFT, /* ESP */ + + 0x00 << REG_SHIFT, /* AX */ + 0x01 << REG_SHIFT, /* CX */ + 0x02 << REG_SHIFT, /* DX */ + 0x04 << REG_SHIFT, /* SP */ + + 0x04 << REG_SHIFT, /* AH */ + 0x00 << REG_SHIFT, /* AL */ + 0x07 << REG_SHIFT, /* BH */ + 0x03 << REG_SHIFT, /* BL */ + 0x05 << REG_SHIFT, /* CH */ + 0x01 << REG_SHIFT, /* CL */ + 0x06 << REG_SHIFT, /* DH */ + 0x02 << REG_SHIFT, /* DL */ + + 0x01 << REG_SHIFT, /* CS */ + 0x03 << REG_SHIFT, /* DS */ + 0x00 << REG_SHIFT, /* ES */ + 0x04 << REG_SHIFT, /* FS */ + 0x05 << REG_SHIFT, /* GS */ + 0x02 << REG_SHIFT, /* SS */ + + 0x00 << REG_SHIFT, /* CR0 */ + 0x02 << REG_SHIFT, /* CR2 */ + 0x03 << REG_SHIFT, /* CR3 */ + + 0x00 << REG_SHIFT, /* DR0 */ + 0x01 << REG_SHIFT, /* DR1 */ + 0x02 << REG_SHIFT, /* DR2 */ + 0x03 << REG_SHIFT, /* DR3 */ + 0x06 << REG_SHIFT, /* DR6 */ + 0x07 << REG_SHIFT, /* DR7 */ + + 0x03 << REG_SHIFT, /* TR3 */ + 0x04 << REG_SHIFT, /* TR4 */ + 0x05 << REG_SHIFT, /* TR5 */ + 0x06 << REG_SHIFT, /* TR6 */ + 0x07 << REG_SHIFT, /* TR7 */ + + 0x00 << REG_SHIFT, /* ST(0) */ + 0x01 << REG_SHIFT, /* ST(1) */ + 0x02 << REG_SHIFT, /* ST(2) */ + 0x03 << REG_SHIFT, /* ST(3) */ + 0x04 << REG_SHIFT, /* ST(4) */ + 0x05 << REG_SHIFT, /* ST(5) */ + 0x06 << REG_SHIFT, /* ST(6) */ + 0x07 << REG_SHIFT, /* ST(7) */ +}; + +PRIVATE opsize_t regsize[] = +{ + 2, /* BP */ + 2, /* BX */ + 2, /* DI */ + 2, /* SI */ + + 4, /* EAX */ + 4, /* EBP */ + 4, /* EBX */ + 4, /* ECX */ + 4, /* EDI */ + 4, /* EDX */ + 4, /* ESI */ + 4, /* ESP */ + + 2, /* AX */ + 2, /* CX */ + 2, /* DX */ + 2, /* SP */ + + 1, /* AH */ + 1, /* AL */ + 1, /* BH */ + 1, /* BL */ + 1, /* CH */ + 1, /* CL */ + 1, /* DH */ + 1, /* DL */ + + 2, /* CS */ + 2, /* DS */ + 2, /* ES */ + 2, /* FS */ + 2, /* GS */ + 2, /* SS */ + + 4, /* CR0 */ + 4, /* CR2 */ + 4, /* CR3 */ + + 4, /* DR0 */ + 4, /* DR1 */ + 4, /* DR2 */ + 4, /* DR3 */ + 4, /* DR6 */ + 4, /* DR7 */ + + 4, /* TR3 */ + 4, /* TR4 */ + 4, /* TR5 */ + 4, /* TR6 */ + 4, /* TR7 */ + + 10, /* ST(0) */ + 10, /* ST(1) */ + 10, /* ST(2) */ + 10, /* ST(3) */ + 10, /* ST(4) */ + 10, /* ST(5) */ + 10, /* ST(6) */ + 10, /* ST(7) */ + + 0, /* NOREG */ +}; + +PRIVATE opcode_t regsegword[] = +{ + WORDBIT, /* BP */ + WORDBIT, /* BX */ + WORDBIT, /* DI */ + WORDBIT, /* SI */ + + WORDBIT, /* EAX */ + WORDBIT, /* EBP */ + WORDBIT, /* EBX */ + WORDBIT, /* ECX */ + WORDBIT, /* EDI */ + WORDBIT, /* EDX */ + WORDBIT, /* ESI */ + WORDBIT, /* ESP */ + + WORDBIT, /* AX */ + WORDBIT, /* CX */ + WORDBIT, /* DX */ + WORDBIT, /* SP */ + + BYTE_SEGWORD, /* AH */ + BYTE_SEGWORD, /* AL */ + BYTE_SEGWORD, /* BH */ + BYTE_SEGWORD, /* BL */ + BYTE_SEGWORD, /* CH */ + BYTE_SEGWORD, /* CL */ + BYTE_SEGWORD, /* DH */ + BYTE_SEGWORD, /* DL */ + + SEGMOV, /* CS */ + SEGMOV, /* DS */ + SEGMOV, /* ES */ + SEGMOV, /* FS */ + SEGMOV, /* GS */ + SEGMOV, /* SS */ + + 0x20, /* CR0 */ + 0x20, /* CR2 */ + 0x20, /* CR3 */ + + 0x21, /* DR0 */ + 0x21, /* DR1 */ + 0x21, /* DR2 */ + 0x21, /* DR3 */ + 0x21, /* DR6 */ + 0x21, /* DR7 */ + + 0x24, /* TR3 */ + 0x24, /* TR4 */ + 0x24, /* TR5 */ + 0x24, /* TR6 */ + 0x24, /* TR7 */ + + 0x00, /* ST(0) */ + 0x00, /* ST(1) */ + 0x00, /* ST(2) */ + 0x00, /* ST(3) */ + 0x00, /* ST(4) */ + 0x00, /* ST(5) */ + 0x00, /* ST(6) */ + 0x00, /* ST(7) */ + + 0x00, /* NOREG */ +}; + +PRIVATE opcode_t rm[] = +{ + 0x05, /* BP */ + 0x03, /* BX */ + 0x07, /* DI */ + 0x06, /* SI */ + + 0x00, /* EAX */ + 0x05, /* EBP */ + 0x03, /* EBX */ + 0x01, /* ECX */ + 0x07, /* EDI */ + 0x02, /* EDX */ + 0x06, /* ESI */ + 0x04, /* ESP */ + + 0x00, /* AX */ + 0x01, /* CX */ + 0x02, /* DX */ + 0x04, /* SP */ + + 0x04, /* AH */ + 0x00, /* AL */ + 0x07, /* BH */ + 0x03, /* BL */ + 0x05, /* CH */ + 0x01, /* CL */ + 0x06, /* DH */ + 0x02, /* DL */ + + 0x01, /* CS */ + 0x03, /* DS */ + 0x00, /* ES */ + 0x04, /* FS */ + 0x05, /* GS */ + 0x02, /* SS */ + + 0x00, /* CR0 */ + 0x00, /* CR2 */ + 0x00, /* CR3 */ + + 0x00, /* DR0 */ + 0x00, /* DR1 */ + 0x00, /* DR2 */ + 0x00, /* DR3 */ + 0x00, /* DR6 */ + 0x00, /* DR7 */ + + 0x00, /* TR3 */ + 0x00, /* TR4 */ + 0x00, /* TR5 */ + 0x00, /* TR6 */ + 0x00, /* TR7 */ + + 0x00, /* ST(0) */ + 0x00, /* ST(1) */ + 0x00, /* ST(2) */ + 0x00, /* ST(3) */ + 0x00, /* ST(4) */ + 0x00, /* ST(5) */ + 0x00, /* ST(6) */ + 0x00, /* ST(7) */ + + 0x04, /* null index reg for sib only */ +}; + +PRIVATE opcode_t rmfunny[] = +{ + 0x06, /* BP */ + 0x07, /* BX */ + 0x05, /* DI */ + 0x04, /* SI */ +}; + +PRIVATE opcode_t segoverride[] = +{ + 0x2E, /* CS */ + 0x3E, /* DS */ + 0x26, /* ES */ + 0x64, /* FS */ + 0x65, /* GS */ + 0x36, /* SS */ +}; + +PRIVATE opcode_t ss[] = /* scale to ss bits */ +{ + 0x00, /* x0, illegal */ + 0x00 << SS_SHIFT, /* x1 */ + 0x01 << SS_SHIFT, /* x2 */ + 0x00, /* x3, illegal */ + 0x02 << SS_SHIFT, /* x4 */ + 0x00, /* x5, illegal */ + 0x00, /* x6, illegal */ + 0x00, /* x7, illegal */ + 0x03 << SS_SHIFT, /* x8 */ +}; + +PRIVATE unsigned char calljmp_kludge; +PRIVATE opcode_t direction; +PRIVATE bool_t fpreg_allowed; +PRIVATE opcode_t segword; +/* + Values of segword: + BYTE_SEGWORD for byte ea's. + SEGMOV for segment registers + opcode for special registers + WORDBIT for other word and dword ea's +*/ + +PRIVATE struct ea_s source; +PRIVATE struct ea_s source2; +PRIVATE struct ea_s target; + +FORWARD void Eb P((struct ea_s *eap)); +FORWARD void Ew P((struct ea_s *eap)); +FORWARD void Ev P((struct ea_s *eap)); +FORWARD void Ex P((struct ea_s *eap)); +FORWARD void Gw P((struct ea_s *eap)); +FORWARD void Gv P((struct ea_s *eap)); +FORWARD void Gx P((struct ea_s *eap)); +FORWARD void buildea P((struct ea_s *eap)); +FORWARD void buildfloat P((void)); +FORWARD void buildfreg P((void)); +FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag)); +FORWARD void buildregular P((void)); +FORWARD void buildsegword P((struct ea_s *eap)); +FORWARD void buildunary P((opcode_pt opc)); +FORWARD opsize_pt displsize P((struct ea_s *eap)); +FORWARD reg_pt fpregchk P((void)); +FORWARD bool_pt getaccumreg P((struct ea_s *eap)); +FORWARD void getbinary P((void)); +FORWARD bool_pt getdxreg P((struct ea_s *eap)); +FORWARD void getea P((struct ea_s *eap)); +FORWARD void getimmed P((struct ea_s *eap, count_t immcount)); +FORWARD void getindirect P((struct ea_s *eap)); +FORWARD void getshift P((struct ea_s *eap)); +FORWARD reg_pt indregchk P((reg_pt matchreg)); +FORWARD void kgerror P((error_pt errnum)); +FORWARD void lbranch P((unsigned backamount)); +FORWARD void notbytesize P((struct ea_s *eap)); +FORWARD void notimmed P((struct ea_s *eap)); +FORWARD void notindirect P((struct ea_s *eap)); +FORWARD void notsegorspecreg P((struct ea_s *eap)); +FORWARD void yesimmed P((struct ea_s *eap)); +FORWARD void yes_samesize P((void)); + +PRIVATE void Eb(eap) +register struct ea_s *eap; +{ + Ex(eap); + if (eap->size != 0x1) + { +#ifndef NODEFAULTSIZE + if (eap->size == 0x0) + eap->size = 0x1; + else +#endif + kgerror(ILL_SIZE); + } +} + +PRIVATE void Ew(eap) +register struct ea_s *eap; +{ + Ex(eap); + if (eap->size != 0x2) + { +#ifndef NODEFAULTSIZE + if (eap->size == 0x0) + eap->size = 0x2; + else +#endif + kgerror(ILL_SIZE); + } +} + +PRIVATE void Ev(eap) +register struct ea_s *eap; +{ + Ex(eap); + notbytesize(eap); +} + +PRIVATE void Ex(eap) +register struct ea_s *eap; +{ + getea(eap); + notimmed(eap); + notsegorspecreg(eap); +} + +PRIVATE void Gd(eap) +register struct ea_s *eap; +{ + Gx(eap); + if (eap->size != 0x4) + kgerror(ILL_SIZE); +} + +PRIVATE void Gw(eap) +register struct ea_s *eap; +{ + Gx(eap); + if (eap->size != 0x2) + kgerror(ILL_SIZE); +} + +PRIVATE void Gv(eap) +register struct ea_s *eap; +{ + Gx(eap); + notbytesize(eap); +} + +PRIVATE void Gx(eap) +register struct ea_s *eap; +{ + Ex(eap); + notindirect(eap); +} + +PRIVATE void buildea(eap) +register struct ea_s *eap; +{ + opsize_t asize; + + ++mcount; + lastexp = eap->displ; + if (eap->indcount == 0x0) + postb = REG_MOD | rm[eap->base]; + else + { + if (eap->base == NOREG) + { + if (eap->index == NOREG) + { + if ((asize = displsize(eap)) > 0x2) + postb = D32_RM; + else + postb = D16_RM; + } + else + { + asize = 0x4; + postb = SIB_NOBASE; /* for sib later */ + } + } + else + { + if (eap->base > MAX16BITINDREG) + { + asize = 0x4; + postb = rm[eap->base]; + } + else + { + asize = 0x2; + if (!(lastexp.data & UNDBIT) && + !iswordorswordoffset(lastexp.offset)) + error(ABOUNDS); + if (eap->index == NOREG) + postb = rmfunny[eap->base]; + else if (eap->base <= MAX16BITINDREG) + postb = baseind16[eap->base + 0x4 * eap->index]; + } + } + if (asize != defsize) + aprefix = 0x67; + if (eap->base == NOREG) + mcount += asize; + else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) || + !is8bitsignedoffset(lastexp.offset)) + { + postb |= MEM2_MOD; + mcount += asize; + } + else if (lastexp.offset != 0x0 || + eap->base == BPREG && eap->index == NOREG || + eap->base == EBPREG) + { + postb |= MEM1_MOD; + ++mcount; + } + if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG)) + { + sib = ss[eap->scale] | + (rm[eap->index] << INDEX_SHIFT) | + (postb & RM_MASK); + postb = (postb & MOD_MASK) | SIB_RM; + ++mcount; + } + } +} + +PRIVATE void buildfloat() +{ + if (mcount != 0x0) + { + buildea(&source); + oprefix = 0x0; + postb |= (opcode & 0x07) << REG_SHIFT; + opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); + } +} + +PRIVATE void buildfreg() +{ + mcount += 0x2; + oprefix = 0x0; + postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG); + opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); +} + +PRIVATE void buildimm(eap, signflag) +register struct ea_s *eap; +bool_pt signflag; +{ + immadr = eap->displ; + immcount = eap->size; + if (!(immadr.data & (FORBIT | RELBIT | UNDBIT))) + { + if (immcount == 0x1) + { + if ((offset_t) (immadr.offset + 0x80) >= 0x180) + datatoobig(); + } + else if (signflag && is8bitsignedoffset(immadr.offset)) + { + opcode |= SIGNBIT; + immcount = 0x1; + } + else if (immcount == 0x2) + { + if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L) + datatoobig(); + } + } +} + +PRIVATE void buildregular() +{ + if (mcount != 0x0) + { + buildea(&target); + postb |= regbits[source.base]; + } +} + +/* Check size and build segword. */ + +PRIVATE void buildsegword(eap) +register struct ea_s *eap; +{ + if (eap->size == 0x0) +#ifdef NODEFAULTSIZE + kgerror(SIZE_UNK); +#else + eap->size = defsize; +#endif + if (eap->indcount != 0x0 || eap->base == NOREG) + { + segword = WORDBIT; + if (eap->size == 0x1) + segword = BYTE_SEGWORD; + } + else + segword = regsegword[eap->base]; +} + +PRIVATE void buildunary(opc) +opcode_pt opc; +{ + if (mcount != 0x0) + { + buildea(&target); + postb |= opcode; + opcode = opc; + } +} + +PRIVATE opsize_pt displsize(eap) +register struct ea_s *eap; +{ + opsize_t asize; + + asize = defsize; + if (!(eap->displ.data & UNDBIT)) + { + if (asize > 0x2) + { + if (!(eap->displ.data & (FORBIT | RELBIT)) && + iswordadr(eap->displ.offset)) + asize = 0x2; + } + else if (!iswordorswordoffset(eap->displ.offset)) + /* should really use iswordadr() */ + /* but compiler generates signed offsets */ + { + if (!(eap->displ.data & (FORBIT | RELBIT))) + asize = 0x4; + else if (pass2) + error(ABOUNDS); + } + } + return asize; +} + +PRIVATE reg_pt fpregchk() +{ + reg_pt fpreg; + + fpreg_allowed = TRUE; + fpreg = regchk(); + fpreg_allowed = FALSE; + if (fpreg != ST0REG) + return NOREG; + getsym(); + if (sym == LPAREN) + { + getsym(); + if (sym != INTCONST || (unsigned) number >= 0x8) + error(ILL_FP_REG); + else + { + fpreg += number; + getsym(); + if (sym != RPAREN) + error(RPEXP); + else + getsym(); + } + } + return fpreg; +} + +PRIVATE bool_pt getaccumreg(eap) +register struct ea_s *eap; +{ + if ((eap->base = regchk()) != AXREG && eap->base != ALREG + && eap->base != EAXREG) + return FALSE; + getsym(); + if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) + oprefix = 0x66; + return TRUE; +} + +/* + Get binary ea's in target & source (flipped if direction is set). + Put size in source if not already. + Initialise direction, segword, bump mcount. +*/ + +PRIVATE void getbinary() +{ + ++mcount; + getea(&target); + if (target.indcount == 0x0 && target.base == NOREG) + { + error(ILL_IMM_MODE); + target.base = AXREG; + target.size = defsize; + } + getcomma(); + getea(&source); + if (source.size == 0x0) + source.size = target.size; + else if (target.size != 0x0 && target.size != source.size) + { + kgerror(MISMATCHED_SIZE); + return; + } + if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV) + direction = 0x0; + else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV) + { + struct ea_s swap; + + direction = TOREGBIT; + swap = source; + source = target; + target = swap; + } + else if (target.indcount != 0x0) + { + kgerror(ILL_IND_TO_IND); + return; + } + else + { + kgerror(ILL_SEG_REG); + return; + } + buildsegword(&source); +} + +PRIVATE bool_pt getdxreg(eap) +register struct ea_s *eap; +{ + if ((eap->base = regchk()) != DXREG) + return FALSE; + getsym(); + return TRUE; +} + +/* parse effective address */ + +/* + Syntax is restrictive in that displacements must be in the right spots + and will not be added up. + + optional size-type prefix, which is + BYTE + BYTE PTR + WORD + WORD PTR + DWORD + DWORD PTR + PTR + reg + segreg + [scaled index] + where scaled index = + indreg + indreg*scale + indreg+indreg + indreg+indreg*scale + [scaled index+displ] + [scaled index-displ] + optional-immediate-prefix displ[scaled index] + [displ] + optional-imediate-prefix displ + (scaled index) -- anachronism + optional-imediate-prefix displ(scaled index) -- anachronism +*/ + +PRIVATE void getea(eap) +register struct ea_s *eap; +{ + bool_t leading_displ; + bool_t leading_immed; + register struct sym_s *symptr; + + leading_immed = leading_displ = lastexp.data = eap->indcount + = lastexp.offset = 0x0; + eap->index = eap->base = NOREG; + eap->scale = 0x1; + eap->size = mnsize; /* 0x1 for byte ops, else 0x0 */ + + if (sym == IDENT) + { + if ((symptr = gsymptr)->type & MNREGBIT) + { + if (symptr->data & SIZEBIT) + { + getsym(); + if (symptr->value_reg_or_op.op.opcode == 0x0) + eap->indcount = 0x2 - calljmp_kludge; + else + { + if (eap->size != 0x0) + { + if (eap->size != symptr->value_reg_or_op.op.opcode) + error(MISMATCHED_SIZE); + } + else + eap->size = symptr->value_reg_or_op.op.opcode; + if (eap->size > 0x1 && eap->size != defsize) + oprefix = 0x66; + if (sym == IDENT && + (symptr = gsymptr)->type & MNREGBIT && + symptr->data & SIZEBIT && + symptr->value_reg_or_op.op.routine == PTROP) + { + getsym(); + eap->indcount = 0x2 - calljmp_kludge; + } + } + } + } + if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT))) + symptr->data |= FORBIT; /* show seen in advance */ + } + if ((eap->base = regchk()) != NOREG) + { + getsym(); + if (eap->indcount != 0x0) + { + error(ILL_IND_PTR); + eap->indcount = 0x0; + } + if (eap->size != 0x0 && eap->size != regsize[eap->base]) + error(MISMATCHED_SIZE); + if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) + oprefix = 0x66; + eap->displ = lastexp; + return; + } + if (sym != lindirect) + { + if (sym == IMMEDIATE || sym == STAR) + { + /* context-sensitive, STAR means signed immediate here */ + leading_immed = TRUE; + getsym(); + } + leading_displ = TRUE; + expres(); + eap->displ = lastexp; + } + if (sym == lindirect) + { + getsym(); + eap->indcount = 0x2 - calljmp_kludge; + if ((eap->base = indregchk(NOREG)) != NOREG) + { + if (eap->indcount == 0x0 && leading_displ) + error(IND_REQ); + getsym(); + if (sym == ADDOP) + { + getsym(); + if ((eap->index = indregchk(eap->base)) != NOREG) + getsym(); + else + { + if (eap->indcount == 0x0) + error(IND_REQ); + if (leading_displ) + error(REPEATED_DISPL); + expres(); /* this eats ADDOP, SUBOP, MULOP */ + } + } + if (sym == STAR) + { + /* context-sensitive, STAR means scaled here*/ + if (eap->index == NOREG && eap->base == ESPREG) + { + error(INDEX_REG_EXP); + eap->base = EAXREG; + } + getsym(); + factor(); + chkabs(); + if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1) + { + if (eap->base <= MAX16BITINDREG || + lastexp.offset != 0x2 && lastexp.offset != 0x4 && + lastexp.offset != 0x8) + error(ILL_SCALE); + else + { + eap->scale = lastexp.offset; + if (eap->index == NOREG) + { + eap->index = eap->base; + eap->base = NOREG; + } + } + } + lastexp.data = lastexp.offset = 0x0; + } + if ((sym == ADDOP || sym == SUBOP)) + { + if (eap->indcount == 0x0) + error(IND_REQ); + if (leading_displ) + error(REPEATED_DISPL); + expres(); + } + } + else + { + if (leading_displ) + error(REPEATED_DISPL); + expres(); + } + if (sym != rindirect) + error(rindexp); + else + getsym(); + } + else if (!leading_immed && idefsize <= 0x2) + eap->indcount = 0x1; /* compatibility kludge */ + if (!leading_displ) + eap->displ = lastexp; +} + +PRIVATE void getimmed(eap, immcount) +struct ea_s *eap; +count_t immcount; +{ + getea(eap); + yesimmed(eap); + if (mcount != 0x0) + { + eap->size = immcount; + buildimm(eap, FALSE); + } +} + +PRIVATE void getindirect(eap) +register struct ea_s *eap; +{ + getea(eap); + if (eap->indcount == 0x0) + kgerror(IND_REQ); +} + +PRIVATE void getshift(eap) +register struct ea_s *eap; +{ + getcomma(); + getea(eap); + if (eap->base != CLREG) + yesimmed(eap); +} + +/* + Check if current symbol is a compatible index register. + Generate error if it is a reg but not a compatible index. + Return register number (adjusted if necessary to a legal index) or NOREG. +*/ + +PRIVATE reg_pt indregchk(matchreg) +reg_pt matchreg; +{ + reg_pt reg; + + if ((reg = regchk()) != NOREG) + { + switch (matchreg) + { + case BPREG: + case BXREG: + if (reg != DIREG && reg != SIREG) + { + reg = SIREG; + error(INDEX_REG_EXP); + } + break; + case DIREG: + case SIREG: + if (reg != BPREG && reg != BXREG) + { + reg = BXREG; + error(INDEX_REG_EXP); + } + break; + case NOREG: + break; + default: + if (reg <= MAX16BITINDREG || reg == ESPREG) + { + reg = EAXREG; + error(INDEX_REG_EXP); + } + break; + } + if (reg > MAXINDREG && calljmp_kludge == 0x0) + { + if (matchreg != NOREG) + reg = EAXREG; + else + reg = BXREG; + error(INDEX_REG_EXP); + } + } + return reg; +} + +PRIVATE void kgerror(errnum) +error_pt errnum; +{ + error(errnum); + sprefix = oprefix = aprefix = mcount = 0x0; +} + +PRIVATE void lbranch(backamount) +unsigned backamount; +{ + mcount += defsize + 0x1; + if (pass2) + { + reldata(); + if (!(lastexp.data & (RELBIT | UNDBIT))) + { + lastexp.offset = lastexp.offset - lc - lcjump; + if (backamount != 0x0 && !(lastexp.data & IMPBIT) && + lastexp.offset + backamount < 0x80 + backamount) + error(SHORTB); /* -0x8? to 0x7F, warning */ + } + } +} + +/* BCC (long branches emulated by short branch over & long jump) */ + +PUBLIC void mbcc() +{ + getea(&target); + if (target.indcount >= 0x2 || target.base != NOREG) + kgerror(REL_REQ); + else + { + if (defsize != 0x2) + { + page = PAGE1_OPCODE; + ++mcount; + opcode += 0x10; + lbranch(0x84); + } + else + { + aprefix = opcode ^ 0x1; /* kludged storage for short branch + over */ + oprefix = defsize + 0x1; + mcount += 0x2; + opcode = JMP_OPCODE; + lbranch(0x83); + mcount -= 0x2; + } + } +} + +/* bswap r32 */ + +PUBLIC void mbswap() +{ + ++mcount; + Gd(&target); + opcode |= rm[target.base]; +} + +/* BR, CALL, J, JMP */ + +PUBLIC void mcall() +{ + opcode_pt far; + bool_t indirect; + register struct sym_s *symptr; + + far = 0x0; + if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT && + symptr->data & SIZEBIT && + symptr->value_reg_or_op.op.routine == FAROP) + { + far = 0x8; + getsym(); + } + indirect = FALSE; + if (asld_compatible && idefsize <= 0x2) + { + calljmp_kludge = 0x2; + if (sym == INDIRECT) + { + calljmp_kludge = 0x0; + indirect = TRUE; + getsym(); + } + } + getea(&target); + if (indirect && target.indcount == 0x1) + target.indcount = 0x2; + calljmp_kludge = 0x0; + if (sym == COLON) + { + if (opcode == JMP_SHORT_OPCODE) + opcode = JMP_OPCODE; + ++mcount; + yesimmed(&target); + getsym(); + getea(&source); + yesimmed(&source); + if (mcount != 0x0) + { + if (opcode == JMP_OPCODE) + opcode = 0xEA; + else + opcode = 0x9A; + lastexp = source.displ; + if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && + defsize == 0x2 && + (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) + datatoobig(); + mcount += defsize; + target.size = 0x2; + buildimm(&target, FALSE); + } + } + else if (target.indcount >= 0x2 || target.base != NOREG) + { + ++mcount; + notsegorspecreg(&target); + if (target.indcount == 0) + notbytesize(&target); + if (mcount != 0x0) + { + if (opcode == JMP_SHORT_OPCODE) + opcode = JMP_OPCODE; + buildea(&target); + if (opcode == JMP_OPCODE) + opcode = 0x20; + else + opcode = 0x10; + postb |= opcode + far; + opcode = 0xFF; + } + } + else if (opcode == JMP_SHORT_OPCODE) + { + if (jumps_long) + { + opcode = JMP_OPCODE; + lbranch(0x83); + } + else + { + lastexp = target.displ; + if (lastexp.data & IMPBIT) + { + error(NONIMPREQ); + lastexp.data = FORBIT | UNDBIT; + } + mshort2(); + } + } + else + lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0); +} + +/* CALLI, JMPI */ + +PUBLIC void mcalli() +{ + bool_t indirect; + + ++mcount; + indirect = FALSE; + if (sym == INDIRECT) + { + getsym(); + indirect = TRUE; + } + getea(&target); + if (target.indcount >= 0x2 || target.base != NOREG) + indirect = TRUE; + if (indirect) + { + buildea(&target); + if (opcode == 0xEA) + opcode = 0x28; + else + opcode = 0x18; + postb |= opcode; + opcode = 0xFF; + } + else + { + getcomma(); + getea(&source); + yesimmed(&source); + if (mcount != 0x0) + { + lastexp = target.displ; + if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && + defsize == 0x2 && + (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) + datatoobig(); + mcount += defsize; + source.size = 0x2; + buildimm(&source, FALSE); + } + } +} + +/* DIV, IDIV, MUL */ + +PUBLIC void mdivmul() +{ + if (getaccumreg(&source)) + { + ++mcount; + getcomma(); + Ex(&target); + yes_samesize(); + buildunary(0xF6 | regsegword[source.base]); + } + else + mnegnot(); +} + +/* ENTER */ + +PUBLIC void menter() +{ + ++mcount; + getimmed(&target, 0x2); + getcomma(); + getimmed(&source, 0x1); + if (mcount != 0x0) + { + mcount += 2; + lastexp = target.displ; /* getimmed(&source) wiped it out */ + } +} + +/* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */ + +PUBLIC void mEwGw() +{ + ++mcount; + Ew(&target); + getcomma(); + Gw(&source); + oprefix = 0x0; + buildregular(); +} + +/* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */ + +PUBLIC void mExGx() +{ + ++mcount; + Ex(&target); + getcomma(); + Gx(&source); + yes_samesize(); + opcode |= segword; + buildregular(); +} + +PUBLIC void mf_inher() +{ + mcount += 0x2; + postb = REG_MOD | (opcode & ~REG_MOD); + opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6); + if (opcode == ESCAPE_OPCODE_BASE) + opcode = ESCAPE_OPCODE_BASE | 0x6; /* fix up encoding of fcompp */ +} + +/* [fldenv fnsave fnstenv frstor] mem */ + +PUBLIC void mf_m() +{ + ++mcount; + getindirect(&source); + if (source.size != 0x0) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* [fldcw fnstcw] mem2i */ + +PUBLIC void mf_m2() +{ + ++mcount; + getindirect(&source); + if (source.size != 0x0 && source.size != 0x2) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* fnstsw [mem2i ax] */ + +PUBLIC void mf_m2_ax() +{ + if (getaccumreg(&target)) + { + if (target.base != AXREG) + kgerror(ILLREG); + else + { + opcode = 0x74; + target.base = ST0REG; /* fake, really ax */ + buildfreg(); + } + } + else + mf_m2(); +} + +/* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */ + +PUBLIC void mf_m2_m4() +{ + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x2) + opcode |= 0x40; + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* [fild fistp] [mem2i mem4i mem8i] */ + +PUBLIC void mf_m2_m4_m8() +{ + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x2) + opcode |= 0x40; + else if (source.size == 0x8) + opcode |= 0x45; /* low bits 0 -> 5 and 3 -> 7 */ + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* [fcom fcomp] [mem4r mem8r optional-st(i)] */ + +PUBLIC void mf_m4_m8_optst() +{ + if (sym == EOLSYM) + { + target.base = ST1REG; + buildfreg(); + } + else + mf_m4_m8_st(); +} + +/* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */ + +PUBLIC void mf_m4_m8_stst() +{ + target.base = fpregchk(); + if (target.base != NOREG) + { + getcomma(); + source.base = fpregchk(); + if (source.base == NOREG) + { + error(FP_REG_REQ); + source.base = ST0REG; + } + if (target.base == ST0REG) + target.base = source.base; + else + { + if (source.base != ST0REG) + error(ILL_FP_REG_PAIR); + opcode |= 0x40; + if ((opcode & 0x07) >= 0x4) + opcode ^= 0x01; /* weird swap of fdiv/fdivr, fsub/fsubr */ + } + buildfreg(); + } + else + { + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x8) + opcode |= 0x40; + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); + } +} + +/* fst [mem4r mem8r st(i)] */ + +PUBLIC void mf_m4_m8_st() +{ + target.base = fpregchk(); + if (target.base != NOREG) + { + if (opcode == FST_ENCODED) + opcode |= 0x40; + buildfreg(); + } + else + { + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x8) + opcode |= 0x40; + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); + } +} + +/* [fld fstp] [mem4r mem8r mem10r st(i)] */ + +PUBLIC void mf_m4_m8_m10_st() +{ + target.base = fpregchk(); + if (target.base != NOREG) + { + if (opcode == FSTP_ENCODED) + opcode |= 0x40; + buildfreg(); + } + else + { + ++mcount; + getindirect(&source); + if (source.size == 0x0) + kgerror(SIZE_UNK); + else if (source.size == 0x8) + opcode |= 0x40; + else if (source.size == 0xA) + opcode |= 0x25; /* low bits 0 -> 5 and 3 -> 7 */ + else if (source.size != 0x4) + kgerror(ILL_SIZE); + buildfloat(); + } +} + +/* [fbld fbstp] mem10r */ + +PUBLIC void mf_m10() +{ + ++mcount; + getindirect(&source); + if (source.size != 0xA) + kgerror(ILL_SIZE); + buildfloat(); +} + +/* ffree st(i) */ + +PUBLIC void mf_st() +{ + target.base = fpregchk(); + if (target.base == NOREG) + kgerror(FP_REG_REQ); + buildfreg(); +} + +/* [fucom fucomp fxch] optional-st(i) */ + +PUBLIC void mf_optst() +{ + if (sym == EOLSYM) + { + target.base = ST1REG; + buildfreg(); + } + else + mf_st(); +} + +/* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */ + +PUBLIC void mf_stst() +{ + target.base = fpregchk(); + if (target.base == NOREG) + { + kgerror(FP_REG_REQ); + return; + } + getcomma(); + source.base = fpregchk(); + if (source.base == NOREG) + { + kgerror(FP_REG_REQ); + return; + } + if (source.base != ST0REG) + { + kgerror(ILL_FP_REG); + return; + } + buildfreg(); +} + +PUBLIC void mf_w_inher() +{ + sprefix = WAIT_OPCODE; + mf_inher(); +} + +/* [fsave fstenv] mem */ + +PUBLIC void mf_w_m() +{ + sprefix = WAIT_OPCODE; + mf_m(); +} + +/* fstcw mem2i */ + +PUBLIC void mf_w_m2() +{ + sprefix = WAIT_OPCODE; + mf_m2(); +} + +/* fstsw [mem2i ax] */ + +PUBLIC void mf_w_m2_ax() +{ + sprefix = WAIT_OPCODE; + mf_m2_ax(); +} + +/* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */ + +PUBLIC void mgroup1() +{ + getbinary(); + notsegorspecreg(&source); + if (mcount != 0x0) + { + if (source.base == NOREG) + { + if (target.indcount == 0x0 && (target.base == ALREG || + target.base == AXREG || + target.base == EAXREG && + (source.displ.data & (FORBIT | RELBIT | UNDBIT) || + !is8bitsignedoffset(source.displ.offset)))) + { + opcode |= 0x04 | segword; + buildimm(&source, FALSE); + } + else + { + buildunary(0x80 | segword); + buildimm(&source, TRUE); + } + } + else + { + opcode |= direction | segword; + buildregular(); + } + } +} + +/* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */ + +PUBLIC void mgroup2() +{ + ++mcount; + Ex(&target); + buildsegword(&target); + getshift(&source); + if (mcount != 0x0) + { + buildunary(0xD0 | segword); + if (source.base == CLREG) + opcode |= 0x2; + else if (source.displ.offset != 0x1) + { + opcode -= 0x10; + source.size = 0x1; + buildimm(&source, FALSE); + } + } +} + +/* LLDT, LTR, SLDT, STR, VERR, VERW */ + +PUBLIC void mgroup6() +{ + ++mcount; + Ew(&target); + oprefix = 0x0; + buildunary(0x0); +} + +/* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */ + +PUBLIC void mgroup7() +{ + ++mcount; + if (opcode == 0x20 || opcode == 0x30) + { + Ew(&target); + oprefix = 0x0; + } + else + { + getindirect(&target); + oprefix = 0x0; + if (target.size != 0x0 && target.size != 0x6) + error(MISMATCHED_SIZE); /* XXX - size 6 wrong for INVLPG? */ + } + buildunary(0x1); +} + +/* BT, BTR, BTS, BTC */ + +PUBLIC void mgroup8() +{ + ++mcount; + Ev(&target); + getcomma(); + /* Gv or Ib */ + getea(&source); + notindirect(&source); + notsegorspecreg(&source); + if (mcount != 0x0) + { + if (source.base == NOREG) + { + buildunary(0xBA); + source.size = 0x1; + buildimm(&source, TRUE); + } + else + { + yes_samesize(); + opcode += 0x83; + buildregular(); + } + } +} + +/* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */ + +PUBLIC void mGvEv() +{ + ++mcount; + Gv(&source); + getcomma(); + Ev(&target); + yes_samesize(); + buildregular(); +} + +/* bound [r16,m16&16 r32,m32&32] */ + +PUBLIC void mGvMa() +{ + ++mcount; + Gv(&source); + getcomma(); + getindirect(&target); + yes_samesize(); + buildregular(); +} + +/* LDS, LES, LFS, LGS, LSS */ + +PUBLIC void mGvMp() +{ + ++mcount; + Gv(&source); + getcomma(); + getindirect(&target); + if (target.size != 0x0 && target.size != 0x2 + source.size) + error(MISMATCHED_SIZE); + buildregular(); +} + +/* IMUL */ + +PUBLIC void mimul() +{ + ++mcount; + Ex(&target); + if (sym != COMMA) + { + buildsegword(&target); + buildunary(0xF6 | segword); + return; + } + getcomma(); + notindirect(&target); + source = target; /* direction is swapped */ + getea(&target); + notsegorspecreg(&target); + yes_samesize(); + if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG)) + { + page = PAGE1_OPCODE; + ++mcount; + opcode = 0xAF; + buildregular(); + } + else + { + if (sym == COMMA) + { + getsym(); + getea(&source2); + yesimmed(&source2); + } + else + { + source2 = target; + target = source; + } + source2.size = target.size; + if (is8bitsignedoffset(source2.displ.offset)) + { + source2.size = 0x1; + opcode = 0x6B; + } + else + { + source2.size = target.size; + opcode = 0x69; + } + buildregular(); + if (mcount != 0x0) + buildimm(&source2, FALSE); + } +} + +/* IN */ + +PUBLIC void min() +{ + ++mcount; + if (opcode & WORDBIT) /* inw; ind not supported */ + mnsize = 0x2; + if (sym == EOLSYM && mnsize != 0x0) + target.size = mnsize; + else + { + if (getaccumreg(&target)) + { + if (mnsize != 0x0 && regsize[target.base] != mnsize) + error(MISMATCHED_SIZE); + getcomma(); + } + else + target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG]; + opcode |= regsegword[target.base]; + if (!getdxreg(&source)) + { + getimmed(&source, 0x1); + opcode -= 0x8; + } + } + if (target.size > 0x1 && target.size != defsize) + oprefix = 0x66; +} + +/* DEC, INC */ + +PUBLIC void mincdec() +{ + ++mcount; + Ex(&target); + buildsegword(&target); + if (target.indcount == 0x0 && segword == WORDBIT) + opcode |= 0x40 | rm[target.base]; + else + buildunary(0xFE | segword); +} + +/* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */ +/* MOVSW, OUTSW, SCASW, STOSW */ + +PUBLIC void minher16() +{ + minher(); + if (defsize != 0x2) + oprefix = 0x66; +} + +/* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */ +/* MOVSD, OUTSD, SCASD, STOSD */ + +PUBLIC void minher32() +{ + minher(); + if (defsize != 0x4) + oprefix = 0x66; +} + +/* AAD, AAM */ + +PUBLIC void minhera() +{ + ++mcount; + if (sym == EOLSYM) + { + target.displ.offset = 0xA; + target.size = 0x1; + buildimm(&target, FALSE); + } + else + getimmed(&target, 0x1); +} + +/* INT */ + +PUBLIC void mint() +{ + ++mcount; + getimmed(&target, 0x1); + if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) && + (opcode_t) immadr.offset == 0x3) + { + immcount = 0x0; + opcode = 0xCC; + } +} + +/* JCC */ + +PUBLIC void mjcc() +{ + if (jumps_long && opcode < 0x80) /* above 0x80 means loop - not long */ + mbcc(); + else + mshort(); +} + +/* JCXZ, JECXZ */ + +PUBLIC void mjcxz() +{ + if (opcode != defsize) + { + aprefix = 0x67; + ++mcount; /* quick fix - mshort() needs to know */ + } + opcode = 0xE3; + mshort(); + if (aprefix != 0x0) + --mcount; /* quick fix - main routine bumps it again */ +} + +/* LEA */ + +PUBLIC void mlea() +{ + Gv(&source); /* back to front */ + getcomma(); + ++mcount; + getindirect(&target); + yes_samesize(); + buildregular(); +} + +/* MOV */ + +PUBLIC void mmov() +{ + getbinary(); + if (segword >= SEGMOV) + { + oprefix = 0x0; + notimmed(&source); + if (segword > SEGMOV) /* special reg */ + notindirect(&target); + } + if (mcount != 0x0) + { + if (target.base == NOREG && target.index == NOREG && + (source.base == ALREG || source.base == AXREG || + source.base == EAXREG)) + { + opcode = 0xA0 | (direction ^ TOREGBIT) | segword; + lastexp = target.displ; + if ((source.size = displsize(&target)) != defsize) + aprefix = 0x67; + mcount += source.size; + } + else if (source.base == NOREG) + { + if (target.indcount == 0x0) + opcode = 0xB0 | (segword << 0x3) | rm[target.base]; + else + { + buildea(&target); + opcode = 0xC6 | segword; + } + buildimm(&source, FALSE); + } + else + { + if (isspecreg(source.base)) + { + page = PAGE1_OPCODE; + ++mcount; + opcode = 0x0; + } + opcode |= direction | segword; + buildregular(); + } + } +} + +/* MOVSX, MOVZX */ + +PUBLIC void mmovx() +{ + ++mcount; + Gv(&source); + getcomma(); + Ex(&target); + if (target.size == 0x0) + kgerror(SIZE_UNK); + if (target.size > 0x2) + kgerror(ILL_SIZE); + oprefix = 0x0; + if (source.size != defsize) + oprefix = 0x66; + buildsegword(&target); + opcode |= segword; + buildregular(); +} + +/* NEG, NOT */ + +PUBLIC void mnegnot() +{ + ++mcount; + Ex(&target); + buildsegword(&target); + buildunary(0xF6 | segword); +} + +/* OUT */ + +PUBLIC void mout() +{ + ++mcount; + if (opcode & WORDBIT) /* outw; outd not supported */ + mnsize = 0x2; + if (sym == EOLSYM && mnsize != 0x0) + source.size = mnsize; + else + { + if (!getdxreg(&target)) + { + getimmed(&target, 0x1); + opcode -= 0x8; + } + if (sym == COMMA) + { + getsym(); + if (!getaccumreg(&source)) + kgerror(AL_AX_EAX_EXP); + else if (mnsize != 0x0 && regsize[source.base] != mnsize) + error(MISMATCHED_SIZE); + } + else + source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG]; + opcode |= regsegword[source.base]; + } + if (source.size > 0x1 && source.size != defsize) + oprefix = 0x66; +} + +/* POP, PUSH */ + +PUBLIC void mpushpop() +{ + opcode_t oldopcode; + + ++mcount; + getea(&target); + buildsegword(&target); + notbytesize(&target); + if ((oldopcode = opcode) == POP_OPCODE) + { + notimmed(&target); + if (target.base == CSREG) + kgerror(ILL_SEG_REG); + } + if (mcount != 0x0) + { + if (target.indcount == 0x0) + { + if (segword == SEGMOV) + { + switch (target.base) + { + case CSREG: + opcode = 0x0E; + break; + case DSREG: + opcode = 0x1E; + break; + case ESREG: + opcode = 0x06; + break; + case SSREG: + opcode = 0x16; + break; + case FSREG: + opcode = 0xA0; + page = PAGE1_OPCODE; + ++mcount; + break; + case GSREG: + opcode = 0xA8; + page = PAGE1_OPCODE; + ++mcount; + break; + } + if (oldopcode == POP_OPCODE) + ++opcode; + } + else if (target.base != NOREG) + { + opcode = 0x50 | rm[target.base]; + if (oldopcode == POP_OPCODE) + opcode |= 0x8; + } + else + { + opcode = 0x68; + if (oldopcode == POP_OPCODE) + ++opcode; + buildimm(&target, TRUE); + } + } + else + { + buildea(&target); + if (oldopcode == PUSH_OPCODE) + postb |= 0x6 << REG_SHIFT; + } + } +} + +/* RET, RETF */ + +PUBLIC void mret() +{ + ++mcount; + if (sym != EOLSYM) + { + --opcode; + getimmed(&target, 0x2); + } +} + +/* SEG CS/DS/ES/FS/GS/SS */ + +PUBLIC void mseg() +{ + reg_pt reg; + + if (regsegword[reg = regchk()] != SEGMOV) + error(SEG_REG_REQ); + else + { + getsym(); + ++mcount; + opcode = (segoverride - CSREG)[reg]; + } +} + +/* SETCC */ + +PUBLIC void msetcc() +{ + ++mcount; + Eb(&target); + if (mcount != 0x0) + buildea(&target); +} + +/* SHLD, SHRD */ + +PUBLIC void mshdouble() +{ + ++mcount; + Ev(&target); + getcomma(); + Gv(&source); + yes_samesize(); + buildregular(); + getshift(&source2); + lastexp = target.displ; /* getshift() wiped it out */ + if (mcount != 0x0) + { + if (source2.base == CLREG) + opcode |= 0x1; + else + { + source2.size = 0x1; + buildimm(&source2, FALSE); + } + } +} + +/* + TEST + Similar to the regular group1 operators. + It does not allow the sign extended immediate byte forms + and does not use the relevant direction bit. +*/ + +PUBLIC void mtest() +{ + getbinary(); + notsegorspecreg(&source); + if (source.base == NOREG) + { + if (mcount != 0x0) + { + if (target.indcount == 0x0 + && (target.base == ALREG || target.base == AXREG + || target.base == EAXREG)) + opcode = 0xA8 | segword; + else + { + buildea(&target); + opcode = 0xF6 | segword; + } + } + buildimm(&source, FALSE); + } + else + { + opcode |= segword; + buildregular(); + } +} + +/* + XCHG + Similar to the regular group1 operators. + It does not allow any of the immediate forms + and does not use the irrelevant direction bit. +*/ + +PUBLIC void mxchg() +{ + getbinary(); + notimmed(&source); + notsegorspecreg(&source); + if (target.indcount == 0x0) + { + if (target.base == AXREG || target.base == EAXREG) + { + opcode = 0x90 + rm[source.base]; + return; + } + if (source.base == AXREG || source.base == EAXREG) + { + opcode = 0x90 + rm[target.base]; + return; + } + } + opcode |= segword; + buildregular(); +} + +PRIVATE void notbytesize(eap) +register struct ea_s *eap; +{ + if (eap->size == 0x1) + kgerror(ILL_SIZE); +} + +PRIVATE void notimmed(eap) +register struct ea_s *eap; +{ + if (eap->indcount == 0x0 && eap->base == NOREG) + kgerror(ILL_IMM_MODE); +} + +PRIVATE void notindirect(eap) +register struct ea_s *eap; +{ + if (eap->indcount != 0x0) + kgerror(ILL_IND); +} + +PRIVATE void notsegorspecreg(eap) +register struct ea_s *eap; +{ + if (regsegword[eap->base] >= SEGMOV) + kgerror(ILLREG); +} + +PRIVATE void yesimmed(eap) +register struct ea_s *eap; +{ + if (eap->indcount == 0x1) + eap->indcount = 0x0; + if (eap->indcount != 0x0 || eap->base != NOREG) + kgerror(IMM_REQ); +} + +PRIVATE void yes_samesize() +{ + if (target.size == 0x0) + target.size = source.size; + else if (source.size != 0x0 && target.size != source.size) + kgerror(MISMATCHED_SIZE); +} + +#endif /* I80386 */ + +#ifdef MC6809 + +/* 6809 opcode constants */ + +/* bits for indexed addressing */ + +#define INDIRECTBIT 0x10 +#define INDEXBIT 0x80 /* except 5 bit offset */ +#define PCRELBIT 0x04 /* PC relative (in certain cases) */ +#define RRBITS 0x60 /* register select bits */ + +PRIVATE opcode_t rrindex[] = /* register and index bits for indexed adr */ +{ + 0x60 | INDEXBIT, /* S */ + 0x40 | INDEXBIT, /* U */ + 0x00 | INDEXBIT, /* X */ + 0x20 | INDEXBIT, /* Y */ + PCRELBIT | INDEXBIT, /* PC */ +}; + +PRIVATE opcode_t pushpull[] = /* push/pull codes */ +{ + 0x40, /* S */ + 0x40, /* U */ + 0x10, /* X */ + 0x20, /* Y */ + 0x80, /* PC */ + 0x02, /* A */ + 0x04, /* B */ + 0x01, /* CC */ + 0x08, /* DP */ + 0x06, /* D */ +}; + +PRIVATE opcode_t tfrexg1[] = /* transfer/exchange codes for source reg */ +{ + 0x40, /* S */ + 0x30, /* U */ + 0x10, /* X */ + 0x20, /* Y */ + 0x50, /* PC */ + 0x80, /* A */ + 0x90, /* B */ + 0xA0, /* CC */ + 0xB0, /* DP */ + 0x00, /* D */ +}; + +PRIVATE opcode_t tfrexg2[] = /* transfer/exchange codes for target reg */ +{ + 0x04, /* S */ + 0x03, /* U */ + 0x01, /* X */ + 0x02, /* Y */ + 0x05, /* PC */ + 0x08, /* A */ + 0x09, /* B */ + 0x0A, /* CC */ + 0x0B, /* DP */ + 0x00, /* D */ +}; + +FORWARD void checkpostinc P((void)); +FORWARD void doaltind P((void)); +FORWARD void do1altind P((void)); +FORWARD void fixupind P((void)); +FORWARD void getindexnopost P((void)); +FORWARD void inderror P((error_pt errnum)); +FORWARD reg_pt indreg P((reg_pt maxindex)); +FORWARD void predec1 P((void)); +FORWARD void sustack P((reg_pt stackreg)); + +PRIVATE void checkpostinc() +{ + if (sym == ADDOP) + { + if (postb & INDIRECTBIT) + inderror(ILLMOD); /* single-inc indirect illegal */ + else + { + lastexp.offset &= 0xFF00; /* for printing if postbyte is 0: ,X+ */ + getsym(); + } + } + else if (sym == POSTINCOP) + { + postb |= 0x1; + getsym(); + } + else + postb |= 0x4; + fixupind(); +} + +/* common code for all-mode ops, alterable-mode ops, indexed ops */ + +PRIVATE void doaltind() +{ + mcount += 0x2; + if (sym == LBRACKET) + { + postb = INDIRECTBIT; + getsym(); + do1altind(); + if (sym != RBRACKET) + error(RBEXP); + } + else + do1altind(); +} + +PRIVATE void do1altind() +{ + bool_t byteflag; /* set if direct or short indexed adr forced */ + char *oldlineptr; + char *oldsymname; + reg_pt reg; + bool_t wordflag; /* set if extended or long indexed adr forced*/ + + if ((reg = regchk()) != NOREG) + { + switch (reg) + { + case AREG: + postb |= 0x86; + break; + case BREG: + postb |= 0x85; + break; + case DREG: + postb |= 0x8B; + break; + default: + if (indreg(MAXINDREG) != NOREG) + checkpostinc(); + return; + } + getsym(); + if (sym != COMMA) + inderror(COMEXP); + else + getindexnopost(); + return; + } + else if (sym == SUBOP) /* could be -R or - in expression */ + { + oldlineptr = lineptr; /* save state */ + oldsymname = symname; + getsym(); + reg = regchk(); + lineptr = oldlineptr; + symname = oldsymname; + if (reg != NOREG) + { + predec1(); /* it's -R */ + return; + } + sym = SUBOP; + } + else if (sym == COMMA) + { + postb |= INDEXBIT; + getsym(); + if (sym == SUBOP) + { + predec1(); + return; + } + else if (sym != PREDECOP) + { + if (indreg(MAXINDREG) != NOREG) + checkpostinc(); + return; + } + } + if (sym == PREDECOP) + { + postb |= 0x83; + getindexnopost(); + return; + } + + /* should have expression */ + + wordflag = byteflag = FALSE; + if (sym == LESSTHAN) + { + /* context-sensitive, LESSTHAN means byte-sized here */ + byteflag = TRUE; + getsym(); + } + else if (sym == GREATERTHAN) + { + /* context-sensitive, GREATERTHAN means word-sized here */ + wordflag = TRUE; + getsym(); + } + expres(); + if (sym == COMMA) + { /* offset from register */ + getsym(); + if ((reg = indreg(PCREG)) == NOREG) + return; + postb |= 0x8; /* default 8 bit offset */ + if (reg == PCREG) + { + reldata(); + if (!(lastexp.data & (RELBIT | UNDBIT))) + { + lastexp.offset = lastexp.offset - lc; + if (page != 0x0) + lastexp.offset -= 0x4; /* extra for instruction */ + else + lastexp.offset -= 0x3; /* 3 byte instruction + assuming 8 bit offset */ + } + } + if (byteflag) + { + if (!(lastexp.data & (RELBIT | UNDBIT)) && + !is8bitsignedoffset(lastexp.offset)) + error(ABOUNDS); /* forced short form is impossible */ + ++mcount; + } + else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) || + !is8bitsignedoffset(lastexp.offset)) + { /* 16 bit offset */ + if (postb & PCRELBIT && !(lastexp.data & RELBIT)) + --lastexp.offset; /* instruction 1 longer than already + allowed */ + postb |= 0x1; + mcount += 0x2; + } + else if (!(postb & PCRELBIT) && + (offset_t) (lastexp.offset + 0x10) < 0x20 && + !(postb & INDIRECTBIT && lastexp.offset != 0x0)) + { /* 5 bit offset */ + postb &= RRBITS | INDIRECTBIT; + if (lastexp.offset == 0x0) + postb |= 0x84; /* index with zero offset */ + else + postb |= (lastexp.offset & 0x1F); + } + else /* 8 bit offset */ + ++mcount; + fixupind(); + } + else if (postb & INDIRECTBIT) + { /* extended indirect */ + postb = 0x9F; + mcount += 0x2; + fixupind(); + } + else if (postb & INDEXBIT) + inderror(ILLMOD); /* e.g. LEAX $10 */ + else + { + if (byteflag || !wordflag && !(lastexp.data & (FORBIT | RELBIT)) && + (lastexp.offset >> 0x8) == dirpag) + { /* direct addressing */ + if (opcode >= 0x80) + opcode |= 0x10; + } + else /* extended addressing */ + { + if (opcode < 0x80) + opcode |= 0x70; + else + opcode |= 0x30; + ++mcount; + if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) && + !(lastexp.data & IMPBIT) && + lastexp.offset + (0x81 - 0x3) < 0x101) + /* JSR or JMP could be done with BSR or BRA */ + error(SHORTB); + } + } +} + +PRIVATE void fixupind() +{ + if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */ + { + if (opcode < 0x80) + opcode |= 0x60; + else + opcode |= 0x20; + } +} + +PRIVATE void getindexnopost() +{ + getsym(); + if (indreg(MAXINDREG) != NOREG) + fixupind(); +} + +PRIVATE void inderror(errnum) +error_pt errnum; +{ + error(errnum); + if (postb & INDIRECTBIT) + sym = RBRACKET; /* fake right bracket to kill further errors */ + fixupind(); +} + +/* check current symbol is an index register (possibly excepting PC) */ +/* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */ +/* otherwise generate error, return FALSE */ + +PRIVATE reg_pt indreg(maxindex) +reg_pt maxindex; +{ + reg_pt reg; + + if ((reg = regchk()) == NOREG) + inderror(IREGEXP); + else if (reg > maxindex) + { + inderror(ILLREG); + reg = NOREG; + } + else + { + postb |= rrindex[reg]; + getsym(); + } + return reg; +} + +/* all-mode ops */ + +PUBLIC void mall() +{ + if (sym == IMMEDIATE) + mimmed(); + else + malter(); +} + +/* alterable mode ops */ + +PUBLIC void malter() +{ + postb = 0x0; /* not yet indexed or indirect */ + doaltind(); +} + +/* indexed mode ops */ + +PUBLIC void mindex() +{ + postb = INDEXBIT; /* indexed but not yet indirect */ + doaltind(); +} + +/* immediate ops */ + +PUBLIC void mimmed() +{ + opcode_t nybble; + + mcount += 0x2; + if (sym != IMMEDIATE) + error(ILLMOD); + else + { + if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 || + nybble == 0xC || nybble >= 0xE)) + ++mcount; /* magic for long immediate */ + symexpres(); + if (pass2 && mcount <= 0x2) + { + chkabs(); + checkdatabounds(); + } + } +} + +/* long branches */ + +PUBLIC void mlong() +{ + mcount += 0x3; /* may be 0x0 or 0x1 here */ + expres(); + if (pass2) + { + reldata(); + if (!(lastexp.data & (RELBIT | UNDBIT))) + { + lastexp.offset = lastexp.offset - lc - lcjump; + if (!(lastexp.data & IMPBIT) && + lastexp.offset + 0x81 < 0x101) + error(SHORTB); /* -0x81 to 0x7F, warning */ + } + } +} + +/* PSHS and PULS */ + +PUBLIC void msstak() +{ + sustack(SREG); +} + +/* TFR and EXG */ + +PUBLIC void mswap() +{ + reg_pt reg; + + mcount = 0x2; + if ((reg = regchk()) == NOREG) + error(REGEXP); + else + { + postb = tfrexg1[reg]; + getsym(); + if (sym != COMMA) + error(COMEXP); + else + { + getsym(); + if ((reg = regchk()) == NOREG) + error(REGEXP); + else if ((postb |= tfrexg2[reg]) + & 0x88 && (postb & 0x88) != 0x88) + error(ILLREG); /* registers not of same size */ + } + } +} + +/* PSHU and PULU */ + +PUBLIC void mustak() +{ + sustack(UREG); +} + +PRIVATE void predec1() +{ + if (postb & INDIRECTBIT) + inderror(ILLMOD); /* single-dec indirect illegal */ + else + { + postb |= 0x82; + getindexnopost(); + } +} + +/* common routine for PSHS/PULS/PSHU/PULU */ + +PRIVATE void sustack(stackreg) +reg_pt stackreg; +{ + reg_pt reg; + + mcount = 0x2; + while ((reg = regchk()) != NOREG) + { + if (reg == stackreg) + { + error(ILLREG); /* cannot stack self */ + break; + } + postb |= pushpull[reg]; + getsym(); + if (sym != COMMA) + break; + getsym(); + } +} + +#endif /* MC6809 */ + +/* routines common to all processors */ + +PUBLIC void getcomma() +{ + if (sym != COMMA) + error(COMEXP); + else + getsym(); +} + +/* inherent ops */ + +/* for I80386 */ +/* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */ +/* INVD, */ +/* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */ +/* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */ + +PUBLIC void minher() +{ + ++mcount; +} + +/* short branches */ + +PUBLIC void mshort() +{ + nonimpexpres(); + mshort2(); +} + +PRIVATE void mshort2() +{ + mcount += 0x2; + if (pass2) + { + reldata(); + if (lastexp.data & RELBIT) + showrelbad(); + else if (!(lastexp.data & UNDBIT)) + { + lastexp.offset = lastexp.offset - lc - mcount; + if (!is8bitsignedoffset(lastexp.offset)) + error(ABOUNDS); + } + } +} + +/* check if current symbol is a register, return register number or NOREG */ + +PRIVATE reg_pt regchk() +{ + register struct sym_s *symptr; + + if (sym == IDENT) + { + if ((symptr = gsymptr)->type & MNREGBIT) + { + if (symptr->data & REGBIT) + { +#ifdef I80386 + if (symptr->value_reg_or_op.reg == ST0REG && !fpreg_allowed) + error(FP_REG_NOT_ALLOWED); +#endif + return symptr->value_reg_or_op.reg; + } + } + else if (!(symptr->type & (LABIT | MACBIT | VARBIT))) + symptr->data |= FORBIT; /* show seen in advance */ + } + return NOREG; +} + +/* convert lastexp.data for PC relative */ + +PRIVATE void reldata() +{ + if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM)) + { + if ((lastexp.data ^ lcdata) & RELBIT) + showrelbad(); /* rel - abs is weird, abs - rel is bad */ + else + { + pcrflag = OBJ_R_MASK; + lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT; + /* segment is that of lastexp.data */ + } + } + else /* same file, segment and relocation */ + lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM); +} diff --git a/bin86-0.3/as/opcode.h b/bin86-0.3/as/opcode.h new file mode 100644 index 0000000..1e96079 --- /dev/null +++ b/bin86-0.3/as/opcode.h @@ -0,0 +1,162 @@ +/* + * bin86/as/opcode.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* opcode.h - routine numbers and special opcodes for assembler */ + +enum +{ +/* Pseudo-op routine numbers. + * Conditionals are first - this is used to test if op is a conditional. + */ + ELSEOP, + ELSEIFOP, + ELSEIFCOP, + ENDIFOP, + IFOP, + IFCOP, + +#define MIN_NONCOND ALIGNOP + ALIGNOP, + BLKWOP, + BLOCKOP, + BSSOP, + COMMOP, + COMMOP1, + DATAOP, + ENDBOP, + ENTEROP, + ENTRYOP, + EQUOP, + EVENOP, + EXPORTOP, + FAILOP, + FCBOP, + FCCOP, + FDBOP, + FQBOP, + GETOP, + GLOBLOP, + IDENTOP, + IMPORTOP, + LCOMMOP, + LCOMMOP1, + LISTOP, + LOCOP, + MACLISTOP, + MACROOP, + MAPOP, + ORGOP, + PROCEOFOP, + RMBOP, + SECTOP, + SETOP, + SETDPOP, + TEXTOP, +#ifdef I80386 + USE16OP, + USE32OP, +#endif + WARNOP, + +/* Machine-op routine numbers. */ +#ifdef I80386 + BCC, + BSWAP, + CALL, + CALLI, + DIVMUL, + ENTER, + EwGw, + ExGx, + F_INHER, + F_M, + F_M2, + F_M2_AX, + F_M2_M4, + F_M2_M4_M8, + F_M4_M8_OPTST, + F_M4_M8_ST, + F_M4_M8_STST, + F_M4_M8_M10_ST, + F_M10, + F_OPTST, + F_ST, + F_STST, + F_W_INHER, + F_W_M, + F_W_M2, + F_W_M2_AX, + GROUP1, + GROUP2, + GROUP6, + GROUP7, + GROUP8, + GvEv, + GvMa, + GvMp, + IMUL, + IN, + INCDEC, + INHER, + INHER16, + INHER32, + INHER_A, + INT, + JCC, + JCXZ, + LEA, + MOV, + MOVX, + NEGNOT, + OUT, + PUSHPOP, + RET, + SEG, + SETCC, + SH_DOUBLE, + TEST, + XCHG, +#endif /* I80386 */ + +#ifdef MC6809 + ALL, /* all address modes allowed, like LDA */ + ALTER, /* all but immediate, like STA */ + IMMED, /* immediate only (ANDCC, ORCC) */ + INDEXD, /* indexed (LEA's) */ + INHER, /* inherent, like CLC or CLRA */ + LONG, /* long branches */ + SHORT, /* short branches */ + SSTAK, /* S-stack (PSHS, PULS) */ + SWAP, /* TFR, EXG */ + USTAK, /* U-stack (PSHU,PULU) */ +#endif /* MC6809 */ +}; + +/* Special opcodes. */ +#ifdef I80386 +# define CMP_OPCODE_BASE 0x38 +# define CMPSB_OPCODE 0xA6 +# define CMPSW_OPCODE 0xA7 +# define ESCAPE_OPCODE_BASE 0xD8 +# define FST_ENCODED 0x12 +# define FSTP_ENCODED 0x13 +# define JMP_OPCODE 0xE9 +# define JMP_SHORT_OPCODE 0xEB +# define JSR_OPCODE 0xE8 +# define MOVSB_OPCODE 0xA4 +# define MOVSW_OPCODE 0xA5 +# define PAGE1_OPCODE 0x0F +# define POP_OPCODE 0x8F +# define PUSH_OPCODE 0xFF +# define WAIT_OPCODE 0x9B +#endif + +#ifdef MC6809 +# define JMP_OPCODE 0x7E +# define JSR_OPCODE 0xBD +# define PAGE1_OPCODE 0x10 +# define PAGE2_OPCODE 0x11 +#endif diff --git a/bin86-0.3/as/pops.c b/bin86-0.3/as/pops.c new file mode 100644 index 0000000..a475df6 --- /dev/null +++ b/bin86-0.3/as/pops.c @@ -0,0 +1,977 @@ +/* + * bin86/as/pops.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* pops.c - handle pseudo-ops for assembler */ + +#include "const.h" +#include "type.h" +#include "address.h" +#include "flag.h" +#include "globvar.h" +#include "opcode.h" +#include "scan.h" + +PRIVATE bool_t elseflag; /* set if ELSE/ELSEIF are enabled */ + /* depends on zero = FALSE init */ +PRIVATE bool_t lcommflag; + +FORWARD void bumpsem P((struct flags_s *flagptr)); +FORWARD void constdata P((unsigned size)); +FORWARD void docomm P((void)); +FORWARD void doelseif P((pfv func)); +FORWARD void doequset P((int labits)); +FORWARD void doentexp P((int entbits, int impbits)); +FORWARD void doif P((pfv func)); +FORWARD struct sym_s *needlabel P((void)); +FORWARD void showredefinedlabel P((void)); +FORWARD void setloc P((unsigned seg)); + +PRIVATE void bumpsem(flagptr) +register struct flags_s *flagptr; +{ + int newcount; + + if (flagptr->global &&pass != 0) + { + /* bump semaphore count by an expression (default 1), */ + /* then set currentflag iff semaphore count is plus */ + if (sym == EOLSYM) + lastexp.offset = 1; + else + { + absexpres(); + if (lastexp.data & UNDBIT) + return; + } + newcount = (int) lastexp.offset; +#ifdef I80386 /* really sizeof (offset_t) != sizeof (int) */ + if (newcount != lastexp.offset) + datatoobig(); +#endif + newcount += flagptr->semaphore; + if ((int) lastexp.offset >= 0) + { + if (newcount < flagptr->semaphore) + { + error(COUNTOV); + newcount = 0x7fff; + } + } + else if (newcount >= flagptr->semaphore) + { + error(COUNTUN); + newcount = -0x8000; + } + flagptr->semaphore = newcount; + flagptr->current = newcount >= 0; + } +} + +/* check symbol is either undefined */ +/* or has the same segment & relocatability as lc */ + +PUBLIC bool_pt checksegrel(symptr) +register struct sym_s *symptr; +{ + if ((symptr->type & LABIT || + symptr->data & IMPBIT && !(symptr->data & UNDBIT)) && + ((symptr->data ^ lcdata) & (RELBIT | SEGM))) + { + error(SEGREL); + return FALSE; + } + return TRUE; +} + +/* check address fits in 1 byte (possibly with sign truncated) */ + +PUBLIC void checkdatabounds() +{ + if (!(lastexp.data & UNDBIT) && + (offset_t) (lastexp.offset + 0x80) >= 0x180) + datatoobig(); +} + +/* allocate constant data (zero except for size 1), default zero for size 1 */ + +PRIVATE void constdata(size) +unsigned size; +{ + offset_t remaining; + + absexpres(); + if (!((lcdata |= lastexp.data) & UNDBIT)) + { + lcjump = lastexp.offset * size; + popflags = POPLONG | POPHI | POPLO | POPLC; + if (size == 1 && sym == COMMA) + { + symabsexpres(); + checkdatabounds(); + for (remaining = lcjump; remaining != 0; --remaining) + { + putbin((opcode_pt) lastexp.offset); /* fill byte */ + putabs((opcode_pt) lastexp.offset); + } + lastexp.offset = lcjump; + } + else + accumulate_rmb(lastexp.offset * size); + } +} + +PUBLIC void datatoobig() +{ + error(DBOUNDS); +} + +/* common routine for COMM/.COMM */ + +PRIVATE void docomm() +{ + register struct sym_s *labptr; + + absexpres(); /* if undefined, value 0 and size unchanged */ + labptr = label; + if (checksegrel(labptr)) + { + if (labptr->type & (EXPBIT | LABIT)) + labelerror(ALREADY); + else + { + if (!(labptr->type & COMMBIT) || + lastexp.offset > labptr->value_reg_or_op.value) + labptr->value_reg_or_op.value = lastexp.offset; + labptr->type |= COMMBIT; + if (lcommflag) + labptr->type |= REDBIT; /* kludge - COMMBIT | REDBIT => SA */ + labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT); + showlabel(); + } + } + lcommflag = FALSE; +} + +/* common routine for ELSEIF/ELSEIFC */ + +PRIVATE void doelseif(func) +pfv func; +{ + if (iflevel == 0) + error(ELSEIFBAD); + else + { + ifflag = FALSE; + if (elseflag) + { + (*func) (); + if (!(lastexp.data & UNDBIT) && lastexp.offset != 0) + /* expression valid and TRUE, enable assembling */ + { + ifflag = TRUE; + elseflag = FALSE; + } + } + } +} + +/* common routine for EQU/SET */ + +PRIVATE void doequset(labits) +unsigned char labits; +{ + register struct sym_s *labptr; + unsigned char olddata; + unsigned char oldtype; + + labptr = label; + /* set up new label flags in case labe isl used in expression */ + labptr->type = (oldtype = labptr->type) | labits; + labptr->data = (olddata = labptr->data) & ~IMPBIT; + /* non-imported now */ + nonimpexpres(); + lastexp.data |= olddata & FORBIT; /* take all but FORBIT from + expression */ + if (oldtype & LABIT && !(olddata & UNDBIT)) + /* this is a previously defined label */ + + /* + redefinition only allowed if same relocatability, segment and + value + */ + { + if ((olddata ^ lastexp.data) & (RELBIT | UNDBIT) || + labptr->value_reg_or_op.value != lastexp.offset) + { + showredefinedlabel(); + return; + } + } + labptr->data = lastexp.data; + labptr->value_reg_or_op.value = lastexp.offset; + showlabel(); +} + +/* common routine for ENTRY/EXPORT */ + +PRIVATE void doentexp(entbits, impbits) +unsigned char entbits; +unsigned char impbits; +{ + struct sym_s *symptr; + + while (TRUE) + { + if ((symptr = needlabel()) != NULL) + { + if (symptr->type & COMMBIT) + error(ALREADY); + else if (impbits != 0) + { + if (pass != 0) + ; + else if (symptr->type & (EXPBIT | LABIT)) + symptr->type |= EXPBIT; + else + { + symptr->type |= REDBIT; + if (!(symptr->data & IMPBIT)) + symptr->data |= IMPBIT | SEGM; + } + } + else + { + if (pass != 0) + { + if (!(symptr->type & LABIT)) + error(UNLAB); + } + else + { + symptr->type |= entbits | EXPBIT; + symptr->data &= ~IMPBIT; + } + } + } + getsym(); + if (sym != COMMA) + break; + getsym(); + } +} + +/* common routine for IF/IFC */ + +PRIVATE void doif(func) +pfv func; +{ + if (iflevel >= MAXIF) + error(IFOV); + else + { + ++iflevel; + --ifstak; + ifstak->elseflag = elseflag; + elseflag = FALSE; /* prepare */ + + + /* parse the argument. + * [Fare] moved it here to allow nested if's, as + * the argument must be parsed even if we are not assembling ! + */ + (*func) (); + + if ((ifstak->ifflag = ifflag) != FALSE) + /* else not assembling before, so not now & no ELSE's */ + { + /* [Fari]: was here! (*func) (); */ + if (!(lastexp.data & UNDBIT) && lastexp.offset == 0) + /* else expression invalid or FALSE, don't change flags */ + { + ifflag = FALSE; /* not assembling */ + elseflag = TRUE;/* but ELSE will change that */ + } + } + } +} + +PUBLIC void fatalerror(errnum) +error_pt errnum; +{ + error(errnum); + skipline(); + listline(); + finishup(); +} + +/* swap position with label position, do error, put back posn */ +/* also clear label ptr */ + +PUBLIC void labelerror(errnum) +error_pt errnum; +{ + struct sym_s *oldgsymptr; + char *oldlineptr; + unsigned char oldsym; + char *oldsymname; + + oldgsymptr = gsymptr; + oldlineptr = lineptr; + oldsym = sym; + oldsymname = symname; + lineptr = linebuf; + getsym(); /* 1st symbol is label or symbol after + * missing one */ + error(errnum); + gsymptr = oldgsymptr; + lineptr = oldlineptr; + sym = oldsym; + symname = oldsymname; + label = NULL; +} + +PRIVATE struct sym_s *needlabel() +{ + register struct sym_s *symptr; + + if (sym != IDENT || + (symptr = gsymptr)->type & (MACBIT | MNREGBIT | VARBIT)) + { + error(LABEXP); + return NULL; + } + return symptr; +} + +/* .ALIGN pseudo-op */ + +PUBLIC void palign() +{ + absexpres(); + if (!((lcdata |= lastexp.data) & UNDBIT)) + { + popflags = POPLONG | POPHI | POPLO | POPLC; + if (lastexp.offset != 0 && + (lcjump = lc % lastexp.offset) != 0) + accumulate_rmb(lcjump = lastexp.offset - lcjump); + } +} + +/* .BLKW pseudo-op */ + +PUBLIC void pblkw() +{ + constdata(2); +} + +/* BLOCK pseudo-op */ + +PUBLIC void pblock() +{ + if (blocklevel >= MAXBLOCK) + error(BLOCKOV); + else + { + register struct block_s *blockp; + + ++blocklevel; + blockp = blockstak; + blockstak = --blockp; + blockp->data = lcdata; + blockp->dp = dirpag; + blockp->lc = lc; + porg(); /* same as ORG apart from stacking */ + } +} + +/* .BSS pseudo-op */ + +PUBLIC void pbss() +{ + setloc(BSSLOC); +} + +/* COMM pseudo-op */ + +PUBLIC void pcomm() +{ + if (label == NULL) + labelerror(MISLAB); + else if (label->type & VARBIT) + labelerror(VARLAB); /* variable cannot be COMM'd */ + else + docomm(); +} + +/* .COMM pseudo-op */ + +PUBLIC void pcomm1() +{ + unsigned oldseg; + + if (label != NULL) + labelerror(ILLAB); + oldseg = lcdata & SEGM; + setloc(BSSLOC); + if ((label = needlabel()) != NULL && checksegrel(label)) + { + /* Like import. */ + if (label->type & (EXPBIT | LABIT)) + error(ALREADY); + else + label->data = lcdata | (FORBIT | IMPBIT | RELBIT); + getsym(); + getcomma(); + if (label->type & (EXPBIT | LABIT)) + absexpres(); /* just to check it */ + else + docomm(); + } + setloc(oldseg); +} + +/* .DATA pseudo-op */ + +PUBLIC void pdata() +{ + setloc(DATALOC); +} + +/* ELSE pseudo-op */ + +PUBLIC void pelse() +{ + if (iflevel == 0) + error(ELSEBAD); + else + { + ifflag = FALSE; /* assume ELSE disabled */ + if (elseflag) + { + ifflag = TRUE; /* ELSE enabled */ + elseflag = FALSE; + } + } +} + +/* ELSEIF pseudo-op */ + +PUBLIC void pelseif() +{ + doelseif(absexpres); +} + +/* ELSEIFC pseudo-op */ + +PUBLIC void pelsifc() +{ + doelseif(scompare); +} + +/* ENDB pseudo-op */ + +PUBLIC void pendb() +{ + if (label != NULL) + labelerror(ILLAB); + if (blocklevel == 0) + error(ENDBBAD); + else + { + register struct block_s *blockp; + + blockp = blockstak; + lcdata = blockp->data; + dirpag = blockp->dp; + accumulate_rmb(blockp->lc - lc); + lc = blockp->lc; + --blocklevel; + blockstak = blockp + 1; + } +} + +/* ENDIF pseudo-op */ + +PUBLIC void pendif() +{ + if (iflevel == 0) + error(ENDIFBAD); + else + { + ifflag = ifstak->ifflag; + elseflag = ifstak->elseflag; + ++ifstak; + --iflevel; + } +} + +/* ENTER pseudo-op */ + +PUBLIC void penter() +{ + if (!(pedata & UNDBIT)) + error(REENTER); + else + { + if (!((pedata = (pedata & ~UNDBIT) | lcdata) & UNDBIT)) + { + progent = lc; + popflags = POPLC; + } + } +} + +/* ENTRY pseudo-op */ + +PUBLIC void pentry() +{ + doentexp(ENTBIT, 0); +} + +/* EQU pseudo-op */ + +PUBLIC void pequ() +{ + register struct sym_s *labptr; + + if ((labptr = label) == NULL) + labelerror(MISLAB); + else if (labptr->type & COMMBIT) + showredefinedlabel(); /* common cannot be EQU'd */ + else if (labptr->type & VARBIT) + labelerror(VARLAB); /* variable cannot be EQU'd */ + else + doequset(LABIT); +} + +/* .EVEN pseudo-op */ + +PUBLIC void peven() +{ + popflags = POPLONG | POPHI | POPLO | POPLC; + accumulate_rmb(lcjump = lastexp.data = lc & 1); +} + +/* EXPORT pseudo-op */ + +PUBLIC void pexport() +{ + doentexp(0, 0); +} + +/* FAIL pseudo-op */ + +PUBLIC void pfail() +{ + error(FAILERR); +} + +/* FCB pseudo-op */ + +PUBLIC void pfcb() +{ + char *bufptr; + offset_t firstbyte; + + bufptr = databuf.fcbuf; + absexpres(); + firstbyte = lastexp.offset; + while (TRUE) + { + checkdatabounds(); + *bufptr++ = lastexp.offset; + ++mcount; /* won't overflow, line length limits it */ + if (sym != COMMA) + break; + symabsexpres(); + } + lastexp.offset = firstbyte; + popflags = POPLO | POPLC; + fcflag = TRUE; +} + +/* FCC pseudo-op */ + +PUBLIC void pfcc() +{ + register char *bufptr; + unsigned char byte; + char delimiter; + register char *reglineptr; + + bufptr = databuf.fcbuf; + reglineptr = symname; + if ((delimiter = *reglineptr) != EOLCHAR) + ++reglineptr; + while (TRUE) + { + if (*reglineptr == EOLCHAR) + { + symname = reglineptr; + error(DELEXP); + break; + } + if (*reglineptr == delimiter) + { + if (*++reglineptr != delimiter) + break; + } + else if (*reglineptr == '\\' && reglineptr[1] != EOLCHAR) + ++reglineptr; + if ((byte = *reglineptr) < ' ') + { + symname = reglineptr; + error(CTLINS); + byte = ' '; + } + *bufptr++ = byte; + ++reglineptr; + } + lineptr = reglineptr; + getsym(); + if (bufptr > databuf.fcbuf) + { + lastexp.offset = databuf.fcbuf[0]; /* show 1st char only */ + mcount = bufptr - databuf.fcbuf; + /* won't overflow, line length limits it */ + fcflag = TRUE; + popflags = POPLO | POPLC; + } +} + +/* FDB pseudo-op */ + +PUBLIC void pfdb() +{ + struct address_s *adrptr; + unsigned firstdata; + offset_t firstword; + + adrptr = databuf.fdbuf; + expres(); + firstword = lastexp.offset; + firstdata = lastexp.data; + while (TRUE) + { + *adrptr++ = lastexp; + mcount += 2; /* won't overflow, line length limits it */ + if (sym != COMMA) + break; + symexpres(); + } + lastexp.offset = firstword; + lastexp.data = firstdata; + popflags = POPHI | POPLO | POPLC; + fdflag = TRUE; +} + +#if SIZEOF_OFFSET_T > 2 + +/* FQB pseudo-op */ + +PUBLIC void pfqb() +{ + struct address_s *adrptr; + offset_t firstdata; + offset_t firstword; + + adrptr = databuf.fqbuf; + expres(); + firstword = lastexp.offset; + firstdata = lastexp.data; + while (TRUE) + { + *adrptr++ = lastexp; + mcount += 4; /* won't overflow, line length limits it */ + if (sym != COMMA) + break; + symexpres(); + } + lastexp.offset = firstword; + lastexp.data = firstdata; + popflags = POPLONG | POPHI | POPLO | POPLC; + fqflag = TRUE; +} + +#endif /* SIZEOF_OFFSET_T > 2 */ + +/* .GLOBL pseudo-op */ + +PUBLIC void pglobl() +{ + if (binaryg) + error(NOIMPORT); + doentexp(0, IMPBIT); +} + +/* IDENT pseudo-op (not complete) */ + +PUBLIC void pident() +{ + if (sym != IDENT) + error(LABEXP); + else + getsym_nolookup(); /* should save ident string */ +} + +/* IF pseudo-op */ + +PUBLIC void pif() +{ + doif(absexpres); +} + +/* IFC pseudo-op */ + +PUBLIC void pifc() +{ + doif(scompare); +} + +/* IMPORT pseudo-op */ + +PUBLIC void pimport() +{ + struct sym_s *symptr; + + if (binaryg) + error(NOIMPORT); + while (TRUE) + { + if ((symptr = needlabel()) != NULL && checksegrel(symptr)) + { + if (symptr->type & (COMMBIT | EXPBIT | LABIT)) + /* IMPORT is null if label (to be) declared */ + error(ALREADY); + else + /* get current segment from lcdata, no need to mask rest */ + symptr->data = lcdata | (FORBIT | IMPBIT | RELBIT); + } + getsym(); + if (sym != COMMA) + break; + getsym(); + } +} + +/* LCOMM pseudo-op */ + +PUBLIC void plcomm() +{ + lcommflag = TRUE; + pcomm(); +} + +/* .LCOMM pseudo-op */ + +PUBLIC void plcomm1() +{ + lcommflag = TRUE; + pcomm1(); +} + +/* .LIST pseudo-op */ + +PUBLIC void plist() +{ + bumpsem(&list); +} + +/* LOC pseudo-op */ + +PUBLIC void ploc() +{ + if (label != NULL) + labelerror(ILLAB); + absexpres(); + if (!(lastexp.data & UNDBIT)) + { + if (lastexp.offset >= NLOC) + datatoobig(); + else + setloc((unsigned) lastexp.offset); + } +} + +/* .MACLIST pseudo-op */ + +PUBLIC void pmaclist() +{ + bumpsem(&maclist); +} + +/* .MAP pseudo-op */ + +PUBLIC void pmap() +{ + absexpres(); + if (!(lastexp.data & UNDBIT)) + { + mapnum = lastexp.offset; + popflags = POPLO; + if (lastexp.offset >= 0x100) + datatoobig(); + } +} + +/* ORG pseudo-op */ + +PUBLIC void porg() +{ + if (label != NULL) + labelerror(ILLAB); + absexpres(); + if (!((lcdata = lastexp.data) & UNDBIT)) + { + accumulate_rmb(lastexp.offset - lc); + binmbuf = lc = lastexp.offset; + popflags = POPLC; + } +} + +/* RMB pseudo-op */ + +PUBLIC void prmb() +{ + constdata(1); +} + +/* .SECT pseudo-op */ + +PUBLIC void psect() +{ + if (label != NULL) + labelerror(ILLAB); + while (sym == IDENT) + { + if (!(gsymptr->type & MNREGBIT)) + error(ILL_SECTION); + else switch (gsymptr->value_reg_or_op.op.routine) + { + case BSSOP: + pbss(); + break; + case DATAOP: + pdata(); + break; + case TEXTOP: + ptext(); + break; + default: + error(ILL_SECTION); + break; + } + getsym(); + if (sym == COMMA) + getsym(); + } +} + +/* SET pseudo-op */ + +PUBLIC void pset() +{ + register struct sym_s *labptr; + + if ((labptr = label) == NULL) + labelerror(MISLAB); + else if (labptr->type & COMMBIT) + labelerror(RELAB); /* common cannot be SET'd */ + else + doequset(labptr->type & LABIT ? 0 : VARBIT); +} + +/* SETDP pseudo-op */ + +PUBLIC void psetdp() +{ + absexpres(); + if (!(lastexp.data & UNDBIT)) + { + dirpag = lastexp.offset; + popflags = POPLO; + if (lastexp.offset >= 0x100) + datatoobig(); + } +} + +/* .TEXT pseudo-op */ + +PUBLIC void ptext() +{ + setloc(TEXTLOC); +} + +/* .WARN pseudo-op */ + +PUBLIC void pwarn() +{ + bumpsem(&warn); +} + +#ifdef I80386 + +/* USE16 pseudo-op */ + +PUBLIC void puse16() +{ + defsize = 2; +} + +/* USE16 pseudo-op */ + +PUBLIC void puse32() +{ + defsize = 4; +} + +#endif + +/* show redefined label and error, and set REDBIT */ + +PRIVATE void showredefinedlabel() +{ + register struct sym_s *labptr; + + labptr = label; /* showlabel() will kill label prematurely */ + showlabel(); + if (!(labptr->type & REDBIT)) + { + labptr->type |= REDBIT; + labelerror(RELAB); + } +} + +PUBLIC void showlabel() +{ + register struct sym_s *labptr; + + labptr = label; + lastexp.data = labptr->data; + lastexp.offset = labptr->value_reg_or_op.value; + popflags = POPLONG | POPHI | POPLO; + label = NULL; /* show handled by COMM, EQU or SET */ +} + +/* set location segment */ + +PRIVATE void setloc(seg) +unsigned seg; +{ + if (pass != 0 && seg != (lcdata & SEGM)) + putobj(seg | OBJ_SET_SEG); + { + register struct lc_s *lcp; + + lcp = lcptr; + lcp->data = lcdata; + lcp->lc = lc; + lcptr = lcp = lctab + (unsigned char) seg; + lcdata = (lcp->data & ~SEGM) | (unsigned char) seg; + binmbuf = lc = lcp->lc; + popflags = POPLC; + } +} diff --git a/bin86-0.3/as/proto.h b/bin86-0.3/as/proto.h new file mode 100644 index 0000000..0b70a4b --- /dev/null +++ b/bin86-0.3/as/proto.h @@ -0,0 +1,256 @@ +/* + * bin86/as/proto.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* extern functions */ + +#if __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + +/* as.c */ +int main P((int argc, char **argv)); +void as_abort P((char *message)); +void finishup P((void)); +void initp1p2 P((void)); + +/* assemble.c */ +void assemble P((void)); + +/* error.c */ +char *build_error_message P((error_pt errnum, char *buf)); + +/* express.c */ +void absexpres P((void)); +void chkabs P((void)); +void nonimpexpres P((void)); +void showrelbad P((void)); +void symabsexpres P((void)); +void symexpres P((void)); +void expres P((void)); +void factor P((void)); +void scompare P((void)); + +/* genbin.c */ +void binheader P((void)); +void bintrailer P((void)); +void genbin P((void)); +void initbin P((void)); +void putbin P((opcode_pt c)); + +/* genlist.c */ +char *build_2hex_number P((unsigned num, char *where)); +char *build_number P((unsigned num, unsigned width, char *where)); +void error P((error_pt errnum)); +void listline P((void)); +void writec P((int c)); +void writenl P((void)); +void writeoff P((offset_t offset)); +void writes P((char *s)); +void writesn P((char *s)); +void writew P((unsigned word)); + +/* genobj.c */ +void accumulate_rmb P((offset_t offset)); +void flushobj P((void)); +void genobj P((void)); +void initobj P((void)); +void objheader P((void)); +void objtrailer P((void)); +void putabs P((opcode_pt c)); +void putobj P((opcode_pt c)); + +/* gensym.c */ +void gensym P((void)); + +/* macro.c */ +void entermac P((struct sym_s *symptr)); +void pmacro P((void)); + +/* mops.c */ +#ifdef I80386 +void mbcc P((void)); +void mbswap P((void)); +void mcall P((void)); +void mcalli P((void)); +void mdivmul P((void)); +void menter P((void)); +void mEwGw P((void)); +void mExGx P((void)); +void mf_inher P((void)); +void mf_m P((void)); +void mf_m2 P((void)); +void mf_m2_ax P((void)); +void mf_m2_m4 P((void)); +void mf_m2_m4_m8 P((void)); +void mf_m4_m8_optst P((void)); +void mf_m4_m8_st P((void)); +void mf_m4_m8_stst P((void)); +void mf_m4_m8_m10_st P((void)); +void mf_m10 P((void)); +void mf_optst P((void)); +void mf_st P((void)); +void mf_stst P((void)); +void mf_w_inher P((void)); +void mf_w_m P((void)); +void mf_w_m2 P((void)); +void mf_w_m2_ax P((void)); +void mgroup1 P((void)); +void mgroup2 P((void)); +void mgroup6 P((void)); +void mgroup7 P((void)); +void mgroup8 P((void)); +void mGvEv P((void)); +void mGvMa P((void)); +void mGvMp P((void)); +void mimul P((void)); +void min P((void)); +void mincdec P((void)); +void minher P((void)); +void minher16 P((void)); +void minher32 P((void)); +void minhera P((void)); +void mint P((void)); +void mjcc P((void)); +void mjcxz P((void)); +void mlea P((void)); +void mmov P((void)); +void mmovx P((void)); +void mnegnot P((void)); +void mout P((void)); +void mpushpop P((void)); +void mret P((void)); +void mseg P((void)); +void msetcc P((void)); +void mshdouble P((void)); +void mtest P((void)); +void mxchg P((void)); +#endif /* I80386 */ + +#ifdef MC6809 +void mall P((void)); +void malter P((void)); +void mimmed P((void)); +void mindex P((void)); +void minher P((void)); +void mlong P((void)); +void msstak P((void)); +void mswap P((void)); +void mustak P((void)); +#endif /* MC6809 */ + +void getcomma P((void)); +void mshort P((void)); + +/* pops.c */ +bool_pt checksegrel P((struct sym_s *symptr)); +void checkdatabounds P((void)); +void datatoobig P((void)); +void fatalerror P((error_pt errnum)); +void labelerror P((error_pt errnum)); +void palign P((void)); +void pblkw P((void)); +void pblock P((void)); +void pbss P((void)); +void pcomm P((void)); +void pcomm1 P((void)); +void pdata P((void)); +void pelse P((void)); +void pelseif P((void)); +void pelsifc P((void)); +void pendb P((void)); +void pendif P((void)); +void penter P((void)); +void pentry P((void)); +void pequ P((void)); +void peven P((void)); +void pexport P((void)); +void pfail P((void)); +void pfcb P((void)); +void pfcc P((void)); +void pfdb P((void)); +void pfqb P((void)); +void pglobl P((void)); +void pident P((void)); +void pif P((void)); +void pifc P((void)); +void pimport P((void)); +void plcomm P((void)); +void plcomm1 P((void)); +void plist P((void)); +void ploc P((void)); +void pmaclist P((void)); +void pmap P((void)); +void porg P((void)); +void prmb P((void)); +void psect P((void)); +void pset P((void)); +void psetdp P((void)); +void ptext P((void)); +void puse16 P((void)); +void puse32 P((void)); +void pwarn P((void)); +void showlabel P((void)); + +/* readsrc.c */ +void initsource P((void)); +fd_t open_input P((char *name)); +void pget P((void)); +void pproceof P((void)); +void readline P((void)); +void skipline P((void)); + +/* scan.c */ +void context_hexconst P((void)); +void getsym P((void)); +void getsym_nolookup P((void)); +void initscan P((void)); + +/* table.c */ +void inst_keywords P((void)); +struct sym_s *lookup P((void)); +void statistics P((void)); + +/* type.c */ +void u2c2 P((char *buf, u16_pt offset)); +void u4c4 P((char *buf, u32_t offset)); +void u2cn P((char *buf, u16_pt offset, unsigned count)); +void u4cn P((char *buf, u32_t offset, unsigned count)); +bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian)); + +char *strrchr(const char *s, int c); +void *malloc(int c); + +#if 0 +/* library - fcntl.h */ +int creat P((const char *__path, int __mode)); +int open P((const char *__path, int __oflag, ...)); + +/* library - stdlib.h */ +void abort P((void)); +void exit P((int __status)); +void *malloc P((unsigned __size)); + +/* library - string.h */ +int memcmp P((const void *__s1, const void *__s2, unsigned __max)); +void *memset P((void *__s, int __ch, unsigned __nbytes)); +char *strchr P((const char *__s, int __ch)); +int strcmp P((const char *__s1, const char *__s2)); +char *strcpy P((char *__target, const char *__source)); +unsigned strlen P((const char *__s)); +int strncmp P((const char *__s1, const char *__s2, int __max)); +char *strrchr P((const char *__s, int __ch)); + +/* library - unistd.h */ +char *brk P((char *__adr)); +int close P((int __fd)); +long lseek P((int __fd, long __offset, int __whence)); +int read P((int __fd, char *__buf, unsigned __nbytes)); +char *sbrk P((int __incr)); +int write P((int __fd, char *__buf, unsigned __nbytes)); + +#endif diff --git a/bin86-0.3/as/readsrc.c b/bin86-0.3/as/readsrc.c new file mode 100644 index 0000000..350fc4d --- /dev/null +++ b/bin86-0.3/as/readsrc.c @@ -0,0 +1,335 @@ +/* + * bin86/as/readsrc.c + * + * Copyright (C) 1992 Bruce Evans + */ + +#define MAXLINE 256 /* when this is made bigger, fix pfcc not + * to store the string length in a byte- + * sized variable */ + +/* readsrc.c - read source files for assembler */ + +#include <sys/types.h> +#include <fcntl.h> +#include "const.h" +#include "type.h" +#include "flag.h" +#include "file.h" +#include "globvar.h" +#include "macro.h" +#include "scan.h" +#undef EXTERN +#define EXTERN +#include "source.h" + +struct fcbstruct /* file control block structure */ +{ + fd_t fd; /* file descriptor */ + char *lineptr; /* current spot in line */ + char *buf; /* start of buffer (after partial line) */ + char *first; /* start of partial line before buf */ + char *limit; /* end of used part of input buffer */ + unsigned blocksize; /* chars from last read and partial line flag */ + struct fbufstruct *includer;/* buffer of file which included current one */ +}; + +struct fbufstruct /* file buffer structure */ +{ + struct fcbstruct fcb; /* status after opening an include sub-file */ + char fpartline[MAXLINE + 1];/* buffer for partial line */ + char fbuf[INBUFSIZE + 1]; /* buffer to read into */ + char fname[1]; /* file name (variable length), 1 for null */ +}; + +struct get_s /* to record included files */ +{ + fd_t fd; + unsigned line; + long position; +}; + +PRIVATE char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */ + +PRIVATE struct get_s hid_getstak[MAXGET]; /* GET stack */ +PRIVATE struct get_s *getstak; /* ptr */ + +PRIVATE struct fcbstruct input; /* current input file control block */ + /* input.lineptr is not kept up to date */ + /* input.fd depends on zero init */ +PRIVATE struct fbufstruct xyz; +PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */ + /* its fcb only to date in includes */ + +PRIVATE char hid_linebuf[LINLEN]; /* line buffer */ +PRIVATE char *maclinebuf; +PRIVATE char *maclineptr; + +FORWARD void clearsource P((void)); +FORWARD void line_too_long P((void)); + +PRIVATE void clearsource() +{ + input.includer = inputbuf; + inputbuf = &xyz; + input.first = input.limit = input.buf = inputbuf->fbuf; + *(lineptr = linebuf = input.first - 1) = EOLCHAR; + input.blocksize = 0; +} + +PRIVATE void line_too_long() +{ + symname = linebuf + (LINLEN - 1); /* spot for the error */ + error(LINLONG); /* so error is shown in column LINLEN - 1 */ +} + +/* initialise private variables */ + +PUBLIC void initsource() +{ + filnamptr = hid_filnambuf; + getstak = hid_getstak + MAXGET; + clearsource(); /* sentinel to invoke blank skipping */ +} + +PUBLIC fd_t open_input(name) +char *name; +{ + fd_t fd; + + if ((unsigned) (fd = open(name, O_RDONLY)) > 255) + as_abort("error opening input file"); + clearsource(); + return fd; +} + +/* + handle GET pseudo_op + stack state of current file, open new file and reset global state vars + file must be seekable for the buffer discard/restore method to work +*/ + +PUBLIC void pget() +{ +#if OLD + if (infiln >= MAXGET) + error(GETOV); + else + { + skipline(); + listline(); + if (infiln != 0) + { + --getstak; + getstak->fd = infil; + getstak->line = linum; + getstak->position = lseek(infil, 0L, 1) - (inbufend - inbufptr); + ++infiln; + linum = 0; + infil = open_input(lineptr - 1); + } + } +#else + abort(); +#endif +} + +/* process end of file */ +/* close file, unstack old file if current one is included */ +/* otherwise switch pass 0 to pass 1 or exit on pass 2 */ +/* end of file may be from phyical end of file or an END statement */ + +PUBLIC void pproceof() +{ + if (infiln != 0) + close(infil); + if (lineptr == linebuf) + list.current = FALSE; /* don't list line after last unless error */ + if (infiln == infil0) + /* all conditionals must be closed before end of main file (not GETs) */ + { + if (blocklevel != 0) + error(EOFBLOCK); + if (iflevel != 0) + error(EOFIF); + if (lcdata & UNDBIT) + error(EOFLC); + lcptr->data = lcdata; + lcptr->lc = lc; + } + /* macros must be closed before end of all files */ + if (macload) + error(EOFMAC); + listline(); /* last line or line after last if error */ + if (infiln != infil0) + { + infil = getstak->fd; + linum = getstak->line; + if (--infiln != 0) + lseek(infil, getstak->position, 0); + ++getstak; + } + else if (!pass) + { + pass = TRUE; + objheader(); /* while pass 1 data all valid */ + binmbuf = 0; /* reset zero variables */ + maclevel = iflevel = blocklevel = + totwarn = toterr = linum = macnum = 0; + initp1p2(); /* reset other varaiables */ + binaryc = binaryg; +#ifdef I80386 + defsize = idefsize; +#endif + list.current = list.global; + maclist.current = maclist.global; + + warn.current = TRUE; + if (warn.semaphore < 0) + warn.current = FALSE; + if (infiln != 0) + infil = open_input(filnamptr); + binheader(); + } + else + finishup(); +} + +/* + read 1 line of source. + Source line ends with '\n', line returned is null terminated without '\n'. + Control characters other than blank, tab and newline are discarded. + Long lines (length > LINLEN) are truncated, and an error is generated. + On EOF, calls pproceof(), and gets next line unless loading a macro. + This is where macro lines are recursively expanded. +*/ + +PUBLIC void readline() +{ + listpre = FALSE; /* not listed yet */ + if (maclevel != 0) + { + register char *bufptr; /* hold *bufptr in a reg char variable */ + register char *reglineptr; /* if possible (not done here) */ + char *oldbufptr; + struct schain_s *parameters; + char paramnum; + unsigned char remaining; /* space remaining in line + 2 */ + /* value 0 not used except for temp predec */ + /* value 1 means error already gen */ + /* values 1 and 2 mean no space */ + + for (; maclevel != 0; + macpar = macstak->parameters, ++macstak, --maclevel) + if (*(bufptr = macstak->text) != ETB) + /* nonempty macro, process it and return without continuing the for loop */ + { + if (!macflag) + { + maclinebuf = linebuf; + maclineptr = lineptr; + macflag = TRUE; + } + remaining = (unsigned char)LINLEN + 2; + lineptr = linebuf = reglineptr = hid_linebuf; + while (*bufptr++ != EOLCHAR) + { + if (bufptr[-1] == MACROCHAR && *bufptr >= '0' && *bufptr <= '9') + { + parameters = macstak->parameters; + for (paramnum = *bufptr++; paramnum-- != '0';) + if ((parameters = parameters->next) == NULL) + break; + if (parameters != NULL) + { + for (oldbufptr = bufptr, bufptr = parameters->string; + *bufptr++ != 0;) + { + if (--remaining <= 1) + { + if (remaining != 0) + line_too_long(); + remaining = 1; + break; /* forget rest, param on 1 line */ + } + *reglineptr++ = bufptr[-1]; + } + bufptr = oldbufptr; + } + } + else + { + if (--remaining <= 1) + { + if (remaining != 0) + line_too_long(); + remaining = 1; + } + else + *reglineptr++ = bufptr[-1]; + } + } + macstak->text = bufptr; + *reglineptr = EOLCHAR; + return; + } + } + if (macflag) + { + linebuf = maclinebuf; + lineptr = maclineptr; + macflag = FALSE; + } +again: + ++linum; + ++lineptr; /* if eof, this is input.limit + 1 */ + if (input.blocksize != 0) /* and this routine just resets eof */ + { + if (lineptr < input.limit) /* move back partial line */ + { + register char *col; + + col = input.buf; + while ((*--col = *--input.limit) != EOLCHAR) + ; + input.first = col + 1; + ++input.limit; + input.blocksize = 0; + } + else /* may be non-terminated line, don't stop */ + lineptr = input.limit; + } + if (lineptr == input.limit) + { + lineptr = input.first; + input.blocksize = read(infil, input.buf, INBUFSIZE); + if (input.blocksize < 0) + abort(); + if (input.blocksize == 0) + { + clearsource(); + pproceof(); + if (macload) + { + symname = lineptr; + return; /* macro not allowed across eof */ + } + goto again; + } + input.first = input.buf; + *(input.limit = input.buf + input.blocksize) = EOLCHAR; + } + linebuf = lineptr; + if (lineptr >= input.limit) + *(lineptr = input.limit = input.buf) = EOLCHAR; +} + +PUBLIC void skipline() +{ + register char *reglineptr; + + reglineptr = lineptr - 1; + while (*reglineptr != EOLCHAR) + ++reglineptr; + lineptr = reglineptr; +} diff --git a/bin86-0.3/as/scan.c b/bin86-0.3/as/scan.c new file mode 100644 index 0000000..d8c3cd2 --- /dev/null +++ b/bin86-0.3/as/scan.c @@ -0,0 +1,253 @@ +/* + * bin86/as/scan.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* scan.c - lexical analyser for assembler */ + +#include "const.h" +#include "type.h" +#include "globvar.h" +#undef EXTERN +#define EXTERN +#include "scan.h" + +PRIVATE int numbase; /* base for number */ + +PRIVATE char symofchar[256] = /* table to convert chars to their symbols */ +{ + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, EOLSYM, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + + WHITESPACE, EOLSYM, STRINGCONST, IMMEDIATE, /* !"# */ + HEXCONST, BINCONST, ANDOP, CHARCONST, /* $%&' */ + LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */ + COMMA, SUBOP, IDENT, SLASH, /* ,-./ */ + + INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */ + INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */ + INTCONST, INTCONST, COLON, EOLSYM, /* 89:; */ + LESSTHAN, EQOP, GREATERTHAN, MACROARG, /* <=>? */ + + INDIRECT, IDENT, IDENT, IDENT, /* @ABC */ + IDENT, IDENT, IDENT, IDENT, /* DEFG */ + IDENT, IDENT, IDENT, IDENT, /* HIJK */ + IDENT, IDENT, IDENT, IDENT, /* LMNO */ + IDENT, IDENT, IDENT, IDENT, /* PQRS */ + IDENT, IDENT, IDENT, IDENT, /* TUVW */ + IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */ + OTHERSYM, RBRACKET, OTHERSYM, IDENT, /* \]^_ */ + + OTHERSYM, IDENT, IDENT, IDENT, /* `abc */ + IDENT, IDENT, IDENT, IDENT, /* defg */ + IDENT, IDENT, IDENT, IDENT, /* hijk */ + IDENT, IDENT, IDENT, IDENT, /* lmno */ + IDENT, IDENT, IDENT, IDENT, /* pqrs */ + IDENT, IDENT, IDENT, IDENT, /* tuvw */ + IDENT, IDENT, IDENT, OTHERSYM, /* xyz{ */ + OROP, OTHERSYM, NOTOP, OTHERSYM, /* |}~ */ + + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, + WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE +}; + +FORWARD void intconst P((void)); + +PUBLIC void context_hexconst() +{ + numbase = 16; + intconst(); +} + +PUBLIC void getsym() +{ + register char *reglineptr; + + reglineptr = lineptr; +advance: + symname = reglineptr; + switch (sym = symofchar[*reglineptr++]) + { + case WHITESPACE: + goto advance; + case ADDOP: + if (*reglineptr == '+') + { + sym = POSTINCOP; + ++reglineptr; + } + break; + case BINCONST: + numbase = 2; + lineptr = reglineptr; + intconst(); + return; + case CHARCONST: + if ((number = *reglineptr) < ' ') + number = ' '; + if (*reglineptr != EOL) + ++reglineptr; + sym = INTCONST; + break; + case GREATERTHAN: /* context-sensitive */ + if (*reglineptr == '>') + { + sym = SROP; + ++reglineptr; + } + break; + case HEXCONST: + numbase = 16; + lineptr = reglineptr; + intconst(); + return; + case IDENT: + /* walk to end of identifier - magic INTCONST is max of INT, IDENT */ + while (symofchar[*reglineptr] <= INTCONST) + ++reglineptr; + lineptr = reglineptr; + gsymptr = lookup(); + return; + case INTCONST: + if (*(reglineptr - 1) == '0') + { + if (*reglineptr != 'x' && *reglineptr != 'X') + numbase = 8; + else + { + numbase = 16; + ++reglineptr; + } + } + else + { + --reglineptr; + numbase = 10; + } + lineptr = reglineptr; + intconst(); + return; + case LESSTHAN: /* context-sensitive */ + if (*reglineptr == '<') + { + sym = SLOP; + ++reglineptr; + } + break; + case SUBOP: + if (*reglineptr == '-') + { + sym = PREDECOP; + ++reglineptr; + } + break; + } + lineptr = reglineptr; + return; +} + +PUBLIC void getsym_nolookup() +{ + bool_t old_ifflag; + + old_ifflag = ifflag; + ifflag = FALSE; + getsym(); + ifflag = old_ifflag; +} + +PRIVATE void intconst() +{ + register char *reglineptr; + + number = 0; + reglineptr = lineptr; + for (; *reglineptr >= '0'; ++reglineptr) + { + if (*reglineptr > '9') + { + if (numbase != 16) + break; + if (*reglineptr >= 'a' && *reglineptr <= 'f') + { + if (number != 0) + number = numbase * number + (*reglineptr - 'a' + 10); + else + number = *reglineptr - 'a' + 10; + } + else if (*reglineptr >= 'A' && *reglineptr <= 'F') + { + if (number != 0) + number = numbase * number + (*reglineptr - 'A' + 10); + else + number = *reglineptr - 'A' + 10; + } + else + break; + } + else if (number != 0) + number = numbase * number + (*reglineptr - '0'); + else + number = *reglineptr - '0'; + } + if (*reglineptr == 'L' || *reglineptr == 'l') + ++reglineptr; + sym = INTCONST; + lineptr = reglineptr; +} + +PUBLIC void initscan() +{ + if (asld_compatible) + { + lindirect = LPAREN; + rindexp = RPEXP; + rindirect = RPAREN; + } + else + { + lindirect = LBRACKET; + rindexp = RBEXP; + rindirect = RBRACKET; + } +} diff --git a/bin86-0.3/as/scan.h b/bin86-0.3/as/scan.h new file mode 100644 index 0000000..f4421b7 --- /dev/null +++ b/bin86-0.3/as/scan.h @@ -0,0 +1,18 @@ +/* + * bin86/as/scan.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* scan.h - global variables for scanner for assembler */ + +#define EOLCHAR '\n' + +EXTERN struct sym_s *gsymptr; /* global symbol ptr */ +EXTERN char lindirect; /* left symbol for indirect addressing */ +EXTERN char *lineptr; /* current line position */ +EXTERN offset_t number; /* constant number */ +EXTERN int rindexp; /* error code for missing rindirect */ +EXTERN char rindirect; /* right symbol for indirect addressing */ +EXTERN char sym; /* current symbol */ +EXTERN char *symname; /* current symbol name */ diff --git a/bin86-0.3/as/source.h b/bin86-0.3/as/source.h new file mode 100644 index 0000000..5b4f847 --- /dev/null +++ b/bin86-0.3/as/source.h @@ -0,0 +1,10 @@ +/* + * bin86/as/source.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* source.h - global variables for source handlers for assembler */ + +EXTERN unsigned linum; /* line # */ +EXTERN bool_t listpre; /* flag to show line has already been listed */ diff --git a/bin86-0.3/as/table.c b/bin86-0.3/as/table.c new file mode 100644 index 0000000..eab6e4b --- /dev/null +++ b/bin86-0.3/as/table.c @@ -0,0 +1,229 @@ +/* + * bin86/as/table.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* table.c - symbol table handler for assembler */ + +#include "const.h" +#include "type.h" +#include "globvar.h" +#include "scan.h" + +#define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */ + +#ifdef I80386 +# ifdef MNSIZE +EXTERN char bytesizeops[]; +# endif +#endif +EXTERN char ops[]; +EXTERN char page1ops[]; +EXTERN char page2ops[]; +EXTERN char regs[]; +#ifdef I80386 +EXTERN char typesizes[]; +#endif + +#ifdef DEBUG +unsigned nhash; +unsigned nlookup; +unsigned nsym; +unsigned nx[30]; +FORWARD void printchain P((void)); +#endif + +FORWARD void install P((register char *keyptr, unsigned data)); + +PUBLIC void inst_keywords() +{ + install(regs, REGBIT); +#ifdef I80386 + install(typesizes, SIZEBIT); +#endif + install(ops, 0); + install(page1ops, PAGE1); + install(page2ops, PAGE2); +#ifdef I80386 +# ifdef MNSIZE + install(bytesizeops, PAGE1 | PAGE2); +# endif +#endif +} + +PRIVATE void install(keyptr, data) +register char *keyptr; +unsigned data; +{ + char lowcasebuf[20]; + unsigned namelength; + char *nameptr; + char *namend; + register struct sym_s *symptr; + + while (*keyptr != 0) + { + namelength = *keyptr++; + lineptr = (symname = keyptr) + namelength; + for (nameptr = lowcasebuf, namend = lowcasebuf + namelength; + nameptr < namend;) + { + if (*keyptr < 'A' || *keyptr > 'Z') + *nameptr++ = *keyptr++; + else + *nameptr++ = *keyptr++ + ('a' - 'A'); + } + symptr = lookup(); + symptr->type = MNREGBIT; + symptr->data = data; + symptr->value_reg_or_op.op.routine = *keyptr; + symptr->value_reg_or_op.op.opcode = keyptr[1]; + lineptr = (symname = lowcasebuf) + namelength; + symptr = lookup(); + symptr->type = MNREGBIT; + symptr->data = data; + symptr->value_reg_or_op.op.routine = *keyptr; + symptr->value_reg_or_op.op.opcode = keyptr[1]; + keyptr += 2; + } +} + +/* Lookup() searches symbol table for the string from symname to lineptr - 1. + * If string is not found and ifflag is TRUE, string is added to table, with + * type = 0 + * data = inidata (RELBIT | UNDBIT, possibly with IMPBIT | SEGM) + * Returns pointer to symbol entry (NULL if not found and not installed) + * unless symbol table overflows, when routine aborts. + */ + +PUBLIC struct sym_s *lookup() +{ + struct sym_s **hashptr; + register char *nameptr; + register struct sym_s *symptr; + register unsigned hashval; + register unsigned length; +#ifdef DEBUG + int tries; + + ++nlookup; + tries = 0; +#endif + + /* Hash function is a weighted xor of 1 to 4 chars in the string. + * This works seems to work better than looking at all the chars. + * It is important that the function be fast. + * The string comparision function should also be fast and it helps + * if it is optimized for mostly identical comparisions. + * The multiplication by MULTIPLIER should compile as a shift. + */ + +#define MULTIPLIER (SPTSIZ / (1 << USEFUL_BITS_IN_ASCII)) +#define USEFUL_BITS_IN_ASCII 6 + + nameptr = lineptr; + length = nameptr - symname; + if (length <= 3) + { + if (length <= 2) + hashval = hconv(nameptr[-1]) * MULTIPLIER; + else + hashval = hconv(nameptr[-2]) * MULTIPLIER, + hashval ^= hconv(nameptr[-1]); + } + else + hashval = hconv(nameptr[-(length / 2)]) * MULTIPLIER, + hashval ^= hconv(nameptr[-2]) << 2, + hashval ^= hconv(nameptr[-1]); + nameptr = symname; + if ((symptr = *(hashptr = spt + + (hashval ^ (hconv(nameptr[0]) << 1)) % SPTSIZ)) + != NULL) + { + do + { +#ifdef DEBUG + if (tries != 0) + --nx[tries]; + ++tries; + if (tries < sizeof nx / sizeof nx[0]) + ++nx[tries]; + if (tries >= 5) + printchain(hashptr - spt) +#endif + if ((unsigned char) length != symptr->length) + continue; + if (memcmp(symptr->name, nameptr, length) == 0) + return symptr; + } + while ((symptr = symptr->next) != NULL); + + /* Calculate last non-NULL hash ptr. + * This is faster than keeping hashptr up to date in previous loop + * since most lookups are successful and hash ptr is not needed. + */ + do + { + symptr = *hashptr; + hashptr = &symptr->next; + } + while (symptr->next != NULL); + } + if (!ifflag) + return NULL; + align(heapptr); + if (heapptr >= heapend) + fatalerror(SYMOV); +#ifdef DEBUG + ++nsym; + if (hashptr >= spt && hashptr < spt + SPTSIZ) + ++nhash; +#endif + *hashptr = symptr = (struct sym_s *) heapptr; + symptr->type = 0; + symptr->data = inidata; + symptr->length = length; + symptr->value_reg_or_op.value = (unsigned) (symptr->next = NULL); + heapptr = symptr->name; + do + *heapptr++ = *nameptr++; + while (--length != 0); + *heapptr++ = 0; + return symptr; +} + +#ifdef DEBUG + +static void printchain(hashval) +unsigned hashval; +{ + register struct sym_s *symptr; + + printf("%04x ", hashval); + for (symptr = spt[hashval]; symptr != NULL; symptr = symptr->next) + printf("%s ", symptr->name); + printf("\n"); +} + +#endif + +PUBLIC void statistics() +{ +#ifdef DEBUG + int i; + int weight; + + for (i = 0; i < SPTSIZ; ++i) + printchain(i); + printf("nhash = %d, nsym = %d, nlookup = %d nx =\n", nhash, nsym, nlookup); + weight = 0; + for (i = 0; i < 30; ++i) + { + printf("%5d", nx[i]); + weight += nx[i] * i; + } + printf("\n"); + printf("weight = %d%d\n", w; +#endif +} diff --git a/bin86-0.3/as/todo b/bin86-0.3/as/todo new file mode 100644 index 0000000..56c5424 --- /dev/null +++ b/bin86-0.3/as/todo @@ -0,0 +1,10 @@ +Improve string escaping. + +Produce bsd symbol tables. + +Accept gas format. + +Decide how to choose between 8-bit and 32-bit branches. 16-bit branches in +32-bit mode are unusable because top 16 bits of PC are messed up. + +Limit insns to specified processor (warn for 386 insns on 8086). diff --git a/bin86-0.3/as/type.h b/bin86-0.3/as/type.h new file mode 100644 index 0000000..cb2aed5 --- /dev/null +++ b/bin86-0.3/as/type.h @@ -0,0 +1,177 @@ +/* + * bin86/as/type.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* type.h - types for assembler */ + +/* redefine foo_t's because their use has become non-portable */ + +#define bool_t bool_T +#define count_t count_T +#define fd_t fd_T +#define indcount_t indcount_T +#define offset_t offset_T +#define opcode_t opcode_T +#define opsize_t opsize_T +#define scale_t scale_T +#define sem_t sem_T +#define smallcount_t smallcount_T +#define soffset_t soffset_T +#define u8_t u8_T +#define u16_t u16_T +#define u32_t u32_T + +typedef unsigned char bool_t; +typedef int bool_pt; /* change to int for ANSI C */ +typedef unsigned count_t; +typedef unsigned error_pt; +typedef int fd_t; +typedef unsigned char indcount_t; +#ifdef I80386 +typedef unsigned long offset_t; +typedef long soffset_t; +# define SIZEOF_OFFSET_T 4 /* non-portable */ +#endif +#ifdef MC6809 +typedef unsigned offset_t; +typedef int soffset_t; +# define SIZEOF_OFFSET_T 2 /* but sizeof (offset_t) often breaks cpp */ +#endif +typedef unsigned opcode_pt; +typedef unsigned char opcode_t; +typedef unsigned opsize_pt; +typedef unsigned char opsize_t; +typedef unsigned reg_pt; +typedef unsigned char scale_t; +typedef unsigned char smallcount_t; +typedef /* signed */ char sem_t; +typedef unsigned u16_pt; +typedef unsigned short u16_t; +typedef unsigned long u32_pt; +typedef unsigned long u32_t; + +/* symbol table entry */ + +struct sym_s +{ + struct sym_s *next; /* next symbol in hash chain (NULL if none) */ + /* zero offset because it is accessed most */ + unsigned char type; + unsigned char data; /* flags valid for expressions as well as syms*/ + union + { + offset_t value; /* value, if sym is a label */ + unsigned char reg; /* register code, if sym is a register */ + struct + { + unsigned char routine; /* routine number */ + opcode_t opcode; /* opcode, if sym is a hardware op */ + } + op; /* if sym is pseudo-op or hardware op */ + } + value_reg_or_op; + unsigned char length; /* length of symbol string */ + char name[1]; /* string of variable length */ +}; + +/* address */ + +struct address_s +{ + offset_t offset; + unsigned char data; + struct sym_s *sym; +}; + +#ifdef I80386 + +/* effective address */ + +struct ea_s +{ + indcount_t indcount; + opsize_t size; + reg_pt base; + reg_pt index; + scale_t scale; + struct address_s displ; +}; + +#endif + +/* flags */ + +struct flags_s +{ + bool_t global; + bool_t current; + int semaphore; +}; + +/* location counter */ + +struct lc_s +{ + unsigned char data; + offset_t lc; +}; + +/* string chain */ + +struct schain_s +{ + struct schain_s *next; + char string[2]; /* variable length */ +}; + +/* block stack */ + +struct block_s +{ + unsigned char data; + unsigned char dp; + offset_t lc; +}; + +/* if stack */ + +struct if_s +{ + bool_t ifflag; + bool_t elseflag; +}; + +/* macro stack */ + +struct macro_s +{ + char *text; + struct schain_s *parameters; +}; + +/* symbol listing format */ + +struct sym_listing_s +{ + char name[SYMLIS_NAMELEN]; + char zname[2]; + char segm[1]; + char pad1[1]; + char value[4]; + char pad2[1]; + char ar[1]; + char pad3[1]; + char cein[1]; + char pad4[1]; + char nullterm; +}; + +#if __STDC__ +typedef void (*pfv)(void); +#else +typedef void (*pfv)(); +#endif + +#include "proto.h" diff --git a/bin86-0.3/as/work/q b/bin86-0.3/as/work/q new file mode 100644 index 0000000..0f6fefe --- /dev/null +++ b/bin86-0.3/as/work/q @@ -0,0 +1,4 @@ +for i in $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s +do + $a/as $i -3 -w -u +done diff --git a/bin86-0.3/as/work/r b/bin86-0.3/as/work/r new file mode 100644 index 0000000..aca1637 --- /dev/null +++ b/bin86-0.3/as/work/r @@ -0,0 +1,4 @@ +for i in $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s $k/*.s +do + $lb/as $i -3 -w -u +done diff --git a/bin86-0.3/as/work/r-good b/bin86-0.3/as/work/r-good new file mode 100644 index 0000000..1fa22e6 --- /dev/null +++ b/bin86-0.3/as/work/r-good @@ -0,0 +1,1183 @@ +sgdt sidt sldt _aprefix _oprefix +sgdt sidt sldt _aprefix _oprefix +.byte CBW JB JNBE .C9 +sgdt sidt sldt _aprefix _oprefix +edx sal _notimmed _getimmed _yesimmed +sgdt sidt sldt _aprefix _oprefix _getshift +sgdt sidt sldt _aprefix _oprefix _getshift +sgdt sidt sldt _aprefix _oprefix _getshift +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +LCOMM REPE STOW .4 .4A +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +edx sal _notimmed _getimmed _yesimmed +edx sal _notimmed _getimmed _yesimmed +INC JNA REPNE SETNC .131 +edx sal _notimmed _getimmed _yesimmed +edx sal _notimmed _getimmed _yesimmed +qword outsd rcrb rorb _mdivmul +JNL ROL CMPB .2D .140 +BNE INW JMPI LOOPNE .141 +dr0 SALB SHLB .7D .154 +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +EXPORT RCLB ROLB .7F .156 +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +edx sal _notimmed _getimmed _yesimmed +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +scasw stosw setc smsw .19A +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +XLAT ADDB ANDB .B8 .1B4 +LGDT LIDT LLDT INCB .B4 +LGDT LIDT LLDT INCB .B4 .1B8 +LGDT LIDT LLDT INCB .B4 .1B8 +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +.byte CBW JB JNBE .C9 +BH JG PUSHA .F9 .1E9 +cmpsd iretd verr .FF .1EF +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +ELSEIF PUSHAD REP .E8 .1F4 +word insd xorb .EB ..FFFF +byte cmpsw .E .EA ..FFFE +byte cmpsw .E .EA ..FFFE .1FE +byte cmpsw .E .EA ..FFFE .1FE +byte cmpsw .E .EA ..FFFE .1FE +byte cmpsw .E .EA ..FFFE .1FE +CWD MOVSX NOTB .102 .202 +LCOMM REPE STOW .4 .4A .111 +LCOMM REPE STOW .4 .4A .111 +edx sal _notimmed _getimmed _yesimmed +INC JNA REPNE SETNC .131 +INB LOOP SETNB .134 .234 +BMI .2 .2A .139 .239 +JNL ROL CMPB .2D .140 +JNL ROL CMPB .2D .140 .240 +JNL ROL CMPB .2D .140 .240 +LCOMM REPE STOW .4 .4A .111 .211 +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +LGDT LIDT LLDT INCB .B4 .1B8 +.byte CBW JB JNBE .C9 .1C1 +.byte CBW JB JNBE .C9 .1C1 +edx sal _notimmed _getimmed _yesimmed +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +edx sal _notimmed _getimmed _yesimmed +word insd xorb .EB ..FFFF .1FF +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +LCOMM REPE STOW .4 .4A .111 .211 +LCOMM REPE STOW .4 .4A .111 .211 +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +edx sal _notimmed _getimmed _yesimmed +edx sal _notimmed _getimmed _yesimmed +INC JNA REPNE SETNC .131 .231 +INC JNA REPNE SETNC .131 .231 +edx sal _notimmed _getimmed _yesimmed +edx sal _notimmed _getimmed _yesimmed +qword outsd rcrb rorb _mdivmul +qword outsd rcrb rorb _mdivmul +JNL ROL CMPB .2D .140 .240 +JNL ROL CMPB .2D .140 .240 +BNE INW JMPI LOOPNE .141 +BNE INW JMPI LOOPNE .141 +dr0 SALB SHLB .7D .154 +dr0 SALB SHLB .7D .154 +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +EXPORT RCLB ROLB .7F .156 +EXPORT RCLB ROLB .7F .156 +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +edx sal _notimmed _getimmed _yesimmed +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +scasw stosw setc smsw .19A +retf testb _segword _marpl .19B +scasw stosw setc smsw .19A +ENDB SAR SBB .A0 .1A0 +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +jcxe jecxe .A .AA .1AA +XLAT ADDB ANDB .B8 .1B4 +XLAT ADDB ANDB .B8 .1B4 +LGDT LIDT LLDT INCB .B4 .1B8 +LGDT LIDT LLDT INCB .B4 .1B8 +LGDT LIDT LLDT INCB .B4 .1B8 +LGDT LIDT LLDT INCB .B4 .1B8 +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +.byte CBW JB JNBE .C9 .1C1 +.byte CBW JB JNBE .C9 .1C1 +byte cmpsw .E .EA ..FFFE .1FE +BH JG PUSHA .F9 .1E9 +BH JG PUSHA .F9 .1E9 +lodsw lmsw verw .FC .1EC +cmpsd iretd verr .FF .1EF +cmpsd iretd verr .FF .1EF +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +ELSEIF PUSHAD REP .E8 .1F4 +ELSEIF PUSHAD REP .E8 .1F4 +word insd xorb .EB ..FFFF .1FF +word insd xorb .EB ..FFFF .1FF +byte cmpsw .E .EA ..FFFE .1FE +byte cmpsw .E .EA ..FFFE .1FE +byte cmpsw .E .EA ..FFFE .1FE +byte cmpsw .E .EA ..FFFE .1FE +byte cmpsw .E .EA ..FFFE .1FE +byte cmpsw .E .EA ..FFFE .1FE +CWD MOVSX NOTB .102 .202 +CWD MOVSX NOTB .102 .202 +LCOMM REPE STOW .4 .4A .111 .211 +LCOMM REPE STOW .4 .4A .111 .211 +LCOMM REPE STOW .4 .4A .111 .211 +edx sal _notimmed _getimmed _yesimmed +INC JNA REPNE SETNC .131 .231 +INC JNA REPNE SETNC .131 .231 +IN JNC SETNA .133 .233 +INB LOOP SETNB .134 .234 +CMC JNE SETNG .135 .235 +INB LOOP SETNB .134 .234 +BMI .2 .2A .139 .239 +BMI .2 .2A .139 .239 +JNL ROL CMPB .2D .140 .240 +JNL ROL CMPB .2D .140 .240 +JNL ROL CMPB .2D .140 .240 +JNL ROL CMPB .2D .140 .240 +0000 .bss AAA .1C3 +0001 .list EXTERN .1C4 +0002 .byte CBW JB JNBE .C9 .1C1 +0003 AAD .1C2 +0004 .1C7 +0005 .D0 .1C8 +0006 .data DAA JBE .1C5 +0007 LAR .1C6 +0008 .C3 +0009 RCL .C4 .1D0 +000a .C1 .1C9 +000b SGDT SIDT SLDT .C2 +000c AAM .C7 +000d .C8 +000e .C5 +000f EBX DECb .C6 +0010 .1D7 +0011 .1D8 +0012 AAS JA .D9 .1D5 +0013 RCR .1D6 +0014 DAS .1D3 +0015 .C0 .1D4 +0016 DB JAE JNAE .1D1 +0017 EBP SETDP +0018 .D3 +0019 .D4 +001a .D1 +001b FAR .D2 +001c .D7 +001d POPAD .D8 .1C0 +001e .D5 .1D9 +001f EAX .D6 +0020 BLOCK BCC SETAE +0021 .1B0 +0022 .A9 .1A9 +0023 .warn +0024 CDQ +0025 SCAB .B0 +0026 +0027 +0028 FCC .org .A3 .1A3 +0029 ADCB .A4 .1A4 +002a .A1 .1A1 +002b FCB LODB .A2 .1A2 +002c .A7 .1A7 +002d .word .A8 .1A8 +002e .A5 .1A5 +002f EDX SAL .A6 .1A6 +0030 EDI BCS +0031 SBBB SUBB +0032 ADC JC SCAW .B9 +0033 ADD +0034 LDS LOCK SETBE +0035 ENDB SAR SBB .A0 .1A0 +0036 DD SCAS .1B9 +0037 +0038 LODS .B3 .1B7 +0039 LGDT LIDT LLDT INCB .B4 .1B8 +003a .B1 .1B5 +003b FDB .B2 .1B6 +003c CWDE LODW .B7 .1B3 +003d XLAT ADDB ANDB .B8 .1B4 +003e .B5 .1B1 +003f ECX .B6 .1B2 +0040 IF +0041 +0042 IFC .199 +0043 +0044 .zerow DEC LES XCHG +0045 .text SHR +0046 +0047 +0048 .193 +0049 ENTER _Ev .194 +004a _Ew .191 +004b _Ex .192 +004c .197 +004d SAHF _source2 .198 +004e .195 +004f .196 +0050 +0051 +0052 BEQ JE +0053 IRET +0054 LFS +0055 .190 +0056 LEA +0057 XCHGB +0058 SETGE .9C +0059 POPFD .9D +005a .9 .9A +005b .9B +005c NEG +005d +005e .9E +005f GET SHL .9F +0060 +0061 +0062 SEG .E9 +0063 NEGB +0064 LGS +0065 .F0 .1E0 +0066 BGE .1F9 +0067 +0068 .E3 .1F7 +0069 _Gv .E4 .1F8 +006a _Gw .E1 .1F5 +006b _Gx .E2 .1F6 +006c .E7 .1F3 +006d ELSEIF PUSHAD REP .E8 .1F4 +006e JNGE .E5 .1F1 +006f .E6 .1F2 +0070 AH +0071 BGT RET .1F0 +0072 BH JG PUSHA .F9 .1E9 +0073 +0074 CH +0075 .E0 +0076 DH JGE +0077 SET PUSHF +0078 .F3 .1E3 +0079 PUSHFD .F4 .1E4 +007a BHI .F1 .1E1 +007b .F2 .1E2 +007c .F7 .1E7 +007d .F8 .1E8 +007e .F5 .1E5 +007f LAHF .F6 .1E6 +0080 tr7 .187 +0081 .188 +0082 J .185 +0083 tr6 .186 +0084 .183 +0085 MULB .184 +0086 DI .181 +0087 .182 +0088 .6C +0089 .6D +008a JNLE .6 .6A +008b .6B +008c PUBLIC +008d IMULB .170 +008e .6E .189 +008f .6F +0090 CALLI .173 +0091 .174 +0092 .171 +0093 CALL DIV .172 +0094 .177 +0095 .178 +0096 .175 +0097 .176 +0098 .5C +0099 .5D .180 +009a .5 .5A .179 +009b .5B +009c +009d +009e ELSEIFC .5E +009f WAIT .5F +00a0 dr7 +00a1 FAIL BLT +00a2 JL +00a3 dr6 +00a4 SI dr3 +00a5 cr2 IDIV .150 +00a6 cr3 dr1 JLE .169 +00a7 dr2 IMPORT +00a8 .8C .167 +00a9 .8D .168 +00aa .8 .8A .165 +00ab .8B .166 +00ac .163 +00ad ENDIF HLT .164 +00ae .8E .161 +00af .8F .162 +00b0 AL BHIS +00b1 .160 +00b2 BL .159 +00b3 +00b4 CL +00b5 +00b6 DL BLE CLC +00b7 CLD +00b8 .7C .153 +00b9 dr0 SALB SHLB .7D .154 +00ba .7 .7A .151 +00bb cr0 SHLD .7B .152 +00bc BLO CLI SETLE .157 +00bd .158 +00be .7E .155 +00bf EXPORT RCLB ROLB .7F .156 +00c0 IN JNC SETNA .133 .233 +00c1 INB LOOP SETNB .134 .234 +00c2 INC JNA REPNE SETNC .131 .231 +00c3 JNB LOOPZ .132 .232 +00c4 JNG SETNE .137 .237 +00c5 .138 .238 +00c6 CMC JNE SETNG .135 .235 +00c7 ARPL .136 .236 +00c8 BLOS .2C +00c9 JNL ROL CMPB .2D .140 .240 +00ca BMI .2 .2A .139 .239 +00cb CMP LOOPNZ SETNL .2B +00cc JNO +00cd JNP +00ce SETNO .2E +00cf SETNP .2F +00d0 JNS .147 +00d1 .148 +00d2 INS POPA SETNS .145 +00d3 AND INT ROR .146 +00d4 SP .143 +00d5 .144 +00d6 BNE INW JMPI LOOPNE .141 +00d7 POPF .142 +00d8 .1C +00d9 SETNZ .1D +00da CMPS .1 .1A +00db END JNZ .1B +00dc SETNLE +00dd JMP .130 .230 +00de CMPW LOOPE .1E .149 +00df REPNZ XOR .1F +00e0 BPS +00e1 .120 .220 +00e2 JP .119 .219 +00e3 RMB +00e4 +00e5 BOUND +00e6 JPE SETPO +00e7 IDENT +00e8 SETNGE .4C .113 .213 +00e9 NOT .4D .114 .214 +00ea LCOMM REPE STOW .4 .4A .111 .211 +00eb .4B .112 .212 +00ec JPO SETPE .117 .217 +00ed MOV .118 .218 +00ee STOS .4E .115 .215 +00ef .4F .116 .216 +00f0 BPC SETNAE +00f1 POP +00f2 BP JO +00f3 +00f4 LOC SETNBE +00f5 NOP .110 .210 +00f6 .129 .229 +00f7 REPZ +00f8 COMM .3C .127 .227 +00f9 BPL .3D .128 .228 +00fa .3 .3A .125 .225 +00fb .3B .126 .226 +00fc .123 .223 +00fd STOB .124 .224 +00fe .3E .121 .221 +00ff .3F .122 .222 +0100 +0101 +0102 +0103 DIVB +0104 SS +0105 STR +0106 +0107 +0108 +0109 +010a ORG MOVW +010b IMUL +010c OR +010d ORB +010e MOVS +010f +0110 +0111 +0112 BR +0113 +0114 +0115 IDIVB +0116 LEAVE STC +0117 STD +0118 +0119 +011a +011b +011c EQU STI +011d MOVB +011e +011f +0120 ESI BTS +0121 +0122 +0123 BTR +0124 CS LSS +0125 +0126 DS +0127 ESP .even JCXZ JECXZ BSF +0128 ES +0129 +012a FS +012b +012c GS +012d +012e +012f +0130 BTC +0131 +0132 JS BT +0133 BSR +0134 +0135 +0136 +0137 LTR +0138 +0139 +013a JCXE JECXE +013b +013c +013d LSL +013e +013f PTR +0140 BVS +0141 SETZ +0142 MACRO +0143 +0144 ENTRY +0145 +0146 +0147 +0148 +0149 PWORD +014a SETS +014b +014c +014d SCASB STOSB +014e _jumps_long +014f OUT SCASD STOSD +0150 BVC +0151 DWORD EXTRN +0152 +0153 MUL XLATB SETL +0154 +0155 +0156 RETI SETO +0157 SETP +0158 INCLUDE SETA +0159 SETB +015a SCASW STOSW SETC SMSW +015b RETF TESTB +015c SETE +015d FWORD TEST +015e TBYTE SETG +015f +0160 _calljmp_kludge .107 .207 +0161 OUTB .108 .208 +0162 INTO OUTSW .105 .205 +0163 .106 .206 +0164 ELSE .103 .203 +0165 SUB .104 .204 +0166 DW MOVSW .101 .201 +0167 CWD MOVSX NOTB .102 .202 +0168 LODSW LMSW VERW +0169 +016a CLTS +016b +016c +016d CMPSB +016e INSW .109 .209 +016f CMPSD IRETD VERR +0170 AX +0171 MOVSB PUSH SARB SHRB +0172 BX .ascii OUTS +0173 .extern MOVSD SHRD +0174 CX +0175 .map OUTSB +0176 DX .space OUTW +0177 QWORD OUTSD RCRB RORB +0178 +0179 INSB .100 .200 +017a BYTE CMPSW +017b WORD INSD XORB +017c +017d LODSD +017e +017f LODSB +0180 +0181 +0182 JZ +0183 +0184 +0185 +0186 .comm +0187 +0188 +0189 +018a +018b +018c +018d +018e +018f +0190 _mgroup1 +0191 .maclist _mgroup2 +0192 _mgroup3 +0193 +0194 +0195 .globl _mgroup6 +0196 _mgroup7 +0197 _mgroup8 +0198 .long +0199 +019a +019b +019c +019d +019e +019f +01a0 +01a1 +01a2 +01a3 +01a4 +01a5 +01a6 .lcomm +01a7 +01a8 +01a9 +01aa +01ab +01ac +01ad +01ae +01af +01b0 +01b1 +01b2 +01b3 +01b4 +01b5 +01b6 +01b7 +01b8 +01b9 +01ba +01bb +01bc +01bd +01be +01bf +01c0 +01c1 +01c2 +01c3 +01c4 +01c5 +01c6 +01c7 +01c8 +01c9 +01ca .define +01cb +01cc +01cd .short +01ce +01cf +01d0 +01d1 .fail +01d2 +01d3 +01d4 +01d5 +01d6 +01d7 +01d8 +01d9 +01da +01db +01dc +01dd +01de +01df +01e0 +01e1 +01e2 +01e3 +01e4 .blkw +01e5 +01e6 +01e7 +01e8 +01e9 +01ea +01eb +01ec +01ed +01ee +01ef .align +01f0 +01f1 +01f2 +01f3 .blkb +01f4 +01f5 +01f6 +01f7 +01f8 +01f9 +01fa +01fb MOVZX +01fc +01fd +01fe +01ff +0200 if +0201 _gsymptr +0202 seg +0203 +0204 lgs +0205 bound +0206 bge setpo +0207 ident _mimul +0208 setnge _mcalli +0209 +020a lcomm repe stow +020b +020c setpe +020d rep +020e stos +020f +0210 setnae _getunary +0211 bgt ret +0212 je +0213 +0214 setnbe +0215 +0216 jge +0217 set repz +0218 comm +0219 +021a bhi +021b +021c +021d stob +021e +021f +0220 setna +0221 loop setnb +0222 ifc repne setnc +0223 loopz +0224 dec les setne +0225 shr +0226 setng +0227 arpl +0228 blos +0229 cmpb +022a _fqflag _fdflag _fcflag +022b loopnz setnl _mshort +022c +022d _mloadfullpointer +022e setno +022f setnp +0230 ah +0231 _min +0232 bh beq jg popa setns +0233 +0234 ch lfs +0235 +0236 dh jmpi lea loopne +0237 popf +0238 +0239 setnz +023a cmps +023b +023c neg setnle _buildea _yes_samesize +023d _sib +023e cmpw loope +023f get repnz shl _mmovx +0240 bcc _getbinary +0241 fail +0242 jb +0243 +0244 cdq +0245 idiv _minher32 +0246 +0247 import +0248 fcc +0249 _minher16 +024a +024b fcb +024c _displsize _getcomma +024d endif +024e +024f edx sal _notimmed _getimmed _yesimmed +0250 edi bcs bhis +0251 _mmov +0252 adc ja +0253 add +0254 lds _mshdouble +0255 sar sbb +0256 db +0257 +0258 +0259 salb shlb +025a _datatoobig +025b fdb shld _immcount +025c setle +025d +025e +025f ecx export rclb rolb +0260 aaa +0261 +0262 cbw +0263 aad +0264 +0265 mulb +0266 daa jbe +0267 lar +0268 +0269 rcl +026a jnle +026b _mint +026c public aam +026d imulb +026e +026f ebx +0270 calli +0271 +0272 aas jc +0273 call rcr +0274 das _opcode _asld_compatible +0275 +0276 dd jae +0277 ebp +0278 +0279 +027a +027b far +027c _mnsize +027d +027e elseifc +027f eax wait +0280 bps in +0281 _immadr +0282 +0283 rmb .WARN negb +0284 +0285 +0286 jpe +0287 _mtest +0288 .ORG +0289 not _baseind16 _direction +028a _chkabs +028b +028c jpo +028d elseif .WORD mov pushad +028e jnge +028f +0290 bpc _buildimm +0291 pop +0292 pusha .10E .20E +0293 _lbranch .10F .20F +0294 sp loc .10C .20C +0295 nop .10D _mretf .20D +0296 .10A .20A +0297 pushf .10B .20B +0298 +0299 bpl pushfd +029a +029b _buildsegword +029c +029d +029e +029f lahf +02a0 .BSS jnc +02a1 .LIST inb +02a2 .BYTE inc jna jp +02a3 jnb +02a4 jng xchg +02a5 +02a6 .DATA cmc jne _mxchg +02a7 +02a8 _minhera +02a9 enter jnl rol +02aa bmi _getaccumreg _regchk +02ab cmp +02ac jno +02ad jnp sahf +02ae _lc _mincdec +02af +02b0 jns +02b1 +02b2 bp ins jo +02b3 and int iret ror +02b4 +02b5 +02b6 bne inw _mbcc _mjcc +02b7 xchgb _notindirect _getindirect +02b8 setge +02b9 popfd +02ba +02bb end jnz _regsegword _mcall +02bc +02bd jmp +02be +02bf xor +02c0 TR7 block setae +02c1 blt +02c2 j +02c3 TR6 +02c4 +02c5 scab +02c6 di jle +02c7 +02c8 +02c9 adcb _databuf +02ca _notsegreg _indregchk _mseg _pcrflag +02cb lodb +02cc _mlea +02cd hlt _buildregular +02ce +02cf decb +02d0 _lcdata +02d1 sbbb subb +02d2 scaw _regbits +02d3 +02d4 lock setbe _segoverride +02d5 endb +02d6 ble clc scas +02d7 cld _mnegnot +02d8 lods +02d9 lgdt lidt lldt incb +02da +02db _mpushpop +02dc blo cli cwde lodw +02dd xlat addb andb +02de _nonimpexpres +02df _mret _showrelbad +02e0 DR7 _reldata _page +02e1 extern +02e2 jl jnbe +02e3 DR6 +02e4 si DR3 .ZEROW +02e5 CR2 .TEXT +02e6 CR3 DR1 +02e7 DR2 +02e8 +02e9 +02ea +02eb sgdt sidt sldt _aprefix _oprefix _getshift _sprefix +02ec +02ed _minher +02ee +02ef +02f0 al +02f1 +02f2 bl +02f3 div +02f4 cl +02f5 +02f6 dl jnae +02f7 setdp +02f8 +02f9 DR0 _mjcxz +02fa +02fb CR0 +02fc +02fd popad +02fe +02ff _target +0300 _rm +0301 +0302 .39 +0303 +0304 +0305 sub .40 +0306 .LCOMM +0307 cwd +0308 .33 +0309 .34 +030a .31 .12E .22E +030b .32 .12F .22F +030c .37 .12C .22C +030d .38 .12D .22D +030e .35 .12A .22A +030f .36 .12B .22B +0310 +0311 +0312 .49 +0313 +0314 +0315 .30 +0316 +0317 +0318 .43 .11C .21C +0319 .44 .11D .21D +031a .41 .11A .21A +031b movzx .42 .11B .21B +031c .47 +031d USE16 .48 +031e .45 .11E .21E +031f .46 .11F .21F +0320 bvs +0321 +0322 .19 .14E +0323 .14F +0324 .14C +0325 .20 .14D +0326 .COMM dw .14A +0327 .14B +0328 .13 +0329 .14 +032a .11 +032b .12 +032c .17 +032d .18 +032e _ss .15 +032f out .16 +0330 ax bvc .13C .23C +0331 .MACLIST USE32 .13D .23D +0332 bx .29 .13A .23A +0333 mul .13B .23B +0334 cx +0335 .GLOBL .10 +0336 dx .13E .23E +0337 .13F .23F +0338 .LONG .23 +0339 .24 +033a .21 +033b .22 +033c .27 +033d .28 +033e .25 +033f .26 +0340 esi bts +0341 _mEvGv +0342 .79 +0343 btr +0344 ss .BLKW lss +0345 .80 +0346 +0347 esp bsf +0348 .73 .15C +0349 .74 .15D _mGvEv +034a .71 .15A +034b .72 .15B +034c or .77 +034d .78 +034e .75 .15E +034f .ALIGN .76 .15F +0350 btc +0351 +0352 br .89 +0353 .BLKB bsr +0354 +0355 .70 +0356 +0357 ltr +0358 .83 +0359 .84 +035a .81 .16E +035b .82 .16F +035c .87 .16C +035d use16 lsl .88 .16D +035e .85 .16A +035f ptr .86 .16B +0360 .17C +0361 .17D +0362 .59 .17A +0363 .17B +0364 cs +0365 str .60 +0366 ds .17E +0367 .17F +0368 es .53 +0369 .54 +036a fs org .DEFINE .51 +036b .52 +036c gs .57 +036d .SHORT orb .58 +036e .55 +036f .56 +0370 _sym +0371 .FAIL use32 +0372 js bt .69 .18E +0373 .18F +0374 .18C +0375 .50 .18D +0376 stc .18A +0377 std .18B +0378 .63 +0379 .64 +037a .61 +037b .62 +037c equ sti .67 +037d .68 +037e .65 +037f .66 +0380 _source _buildunary +0381 outb +0382 into outsw +0383 +0384 else +0385 _factor +0386 movsw +0387 .EVEN movsx notb +0388 lodsw lmsw verw .FC .1EC +0389 .FD .1ED +038a clts .F .FA .1EA +038b .FB .1EB +038c +038d cmpsb +038e insw _expres .FE .1EE +038f cmpsd iretd verr .FF .1EF +0390 +0391 movsb push sarb shrb +0392 outs +0393 movsd shrd +0394 +0395 outsb +0396 outw +0397 qword outsd rcrb rorb _mdivmul +0398 .EC +0399 insb +039a byte cmpsw .E .EA ..FFFE .1FE +039b word insd xorb .EB ..FFFF .1FF +039c .1FC +039d lodsd .1FD +039e .EE .1FA +039f lodsb .EF _mout .1FB +03a0 +03a1 setz +03a2 macro .99 +03a3 +03a4 entry +03a5 _error _kgerror +03a6 _msetcc +03a7 +03a8 .93 +03a9 pword .94 +03aa sets .91 _notcsreg +03ab .92 +03ac .97 +03ad scasb stosb .98 _menter +03ae .95 +03af scasd stosd .96 +03b0 +03b1 dword extrn +03b2 +03b3 xlatb setl +03b4 +03b5 .90 +03b6 reti seto +03b7 setp +03b8 include seta .19C +03b9 setb .19D +03ba scasw stosw setc smsw .19A +03bb retf testb _segword _marpl .19B +03bc sete _getea +03bd fword test +03be tbyte setg .19E +03bf .19F +03c0 +03c1 +03c2 jz +03c3 +03c4 +03c5 +03c6 +03c7 jcxz jecxz +03c8 .BC +03c9 .BD +03ca .B .BA .1BE +03cb .BB .1BF +03cc _notbytesize .1BC +03cd .1BD +03ce .BE .1BA +03cf .BF .1BB +03d0 _getsym +03d1 +03d2 .ASCII +03d3 .EXTERN +03d4 +03d5 .MAP +03d6 .SPACE +03d7 +03d8 .AC .1AC +03d9 .AD .1AD +03da jcxe jecxe .A .AA .1AA +03db .AB .1AB +03dc _regsize _defsize +03dd +03de .AE .1AE +03df .AF .1AF +03e0 +03e1 +03e2 .1DE +03e3 divb _lcjump .1DF +03e4 .1DC +03e5 .1DD +03e6 _pass .1DA +03e7 .1DB +03e8 .DC +03e9 .DD +03ea movw .D .DA +03eb imul .DB _mbound +03ec _yeswordsize +03ed +03ee movs .DE +03ef .DF +03f0 _rmfunny .1CC +03f1 _postb .1CD +03f2 .1CA +03f3 .1CB +03f4 +03f5 idivb +03f6 leave .1CE +03f7 .1CF +03f8 .CC +03f9 .CD +03fa .C _getdxreg .CA +03fb .CB +03fc +03fd movb +03fe .CE +03ff _lastexp .CF +nhash = 731, nsym = 1463, nlookup = 18376 nx = + 011029 2760 2820 185 97 20 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 731 406 200 87 29 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +weight = 26368, compares = 27603 diff --git a/bin86-0.3/as/work/t b/bin86-0.3/as/work/t new file mode 100644 index 0000000..29ebfd6 --- /dev/null +++ b/bin86-0.3/as/work/t @@ -0,0 +1,3 @@ +cp work/$1 as +sync +time sh t1 diff --git a/bin86-0.3/as/work/t1 b/bin86-0.3/as/work/t1 new file mode 100644 index 0000000..c2a47d5 --- /dev/null +++ b/bin86-0.3/as/work/t1 @@ -0,0 +1,10 @@ +./as q -w -u +./as q -w -u +./as q -w -u +./as q -w -u +./as q -w -u +./as q -w -u +./as q -w -u +./as q -w -u +./as q -w -u +./as q -w -u diff --git a/bin86-0.3/as/work/z b/bin86-0.3/as/work/z new file mode 100644 index 0000000..108c07e --- /dev/null +++ b/bin86-0.3/as/work/z @@ -0,0 +1,5 @@ +r q -w -u +_exit b +c +_nhash/x +_hid_spt+0x40/32x diff --git a/bin86-0.3/bcc/bcc.c b/bin86-0.3/bcc/bcc.c new file mode 100644 index 0000000..58035c8 --- /dev/null +++ b/bin86-0.3/bcc/bcc.c @@ -0,0 +1,831 @@ +/* + * bin86/bcc/bcc.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* bcc.c - driver for Bruce's C compiler and for CvW's C compiler */ + +#define _POSIX_SOURCE 1 + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <unistd.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> + +#define FALSE 0 +#define FORWARD static +#ifndef NULL +#define NULL 0 +#endif +#define PRIVATE static +#define PUBLIC +#define TRUE 1 + +#if __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + +#define AS "as" +#define BAS86 +#define BCC86 +#define CC1 "cc1" +#define CC1_MINUS_O_BROKEN FALSE +#define CPP "cc1" +#define CPPFLAGS "-E" +#define CRTSO "crtso.o" +#define GCC "/usr/bin/gcc" +#define LD "ld" +#define STANDARD_CRTSO0_PREFIX "/usr/local/lib/i86/" +#define STANDARD_CRTSO3_PREFIX "/usr/local/lib/i386/" +#define STANDARD_EXEC_PREFIX "/usr/local/libexec/i386/bcc/" + +#ifdef CCC +#undef BCC86 +#undef CC1 +#define CC1 "c386" +#undef CC1_MINUS_O_BROKEN +#define CC1_MINUS_O_BROKEN TRUE +#undef CPP +#define CPP "cpp" /* could also use bcc-cc1 -E */ +#undef CPPFLAGS +#define CPPFLAGS "-traditional" +#undef GCC +#undef STANDARD_CRTSO0_PREFIX +#undef STANDARD_CRTSO3_PREFIX +#define STANDARD_CRTSO_PREFIX "/usr/local/lib/i386/" +#define STANDARD_EXEC_PREFIX_2 "/usr/local/bin/" +#endif /* CCC */ + +#ifdef MC6809 +#undef BAS86 +#undef BCC86 +#undef CRTSO +#undef GCC +#undef STANDARD_CRTSO0_PREFIX +#undef STANDARD_CRTSO3_PREFIX +#undef STANDARD_EXEC_PREFIX +#define STANDARD_EXEC_PREFIX "/usr/local/libexec/m09/bcc/" +#endif /* MC6809 */ + +#define ALLOC_UNIT 16 /* allocation unit for arg arrays */ +#define DIRCHAR '/' +#define START_ARGS 4 /* number of reserved args */ + +typedef unsigned char bool_T; /* boolean: TRUE if nonzero */ + +struct arg_s +{ + char *prog; + bool_T minus_O_broken; + int argc; + char **argv; + unsigned nr_allocated; +}; + +struct prefix_s +{ + char *name; + struct prefix_s *next; +}; + +PRIVATE struct arg_s asargs = { AS, }; +PRIVATE struct arg_s ccargs = { CC1, CC1_MINUS_O_BROKEN, }; +PRIVATE struct arg_s cppargs = { CPP, }; +#ifdef STANDARD_CRTSO_PREFIX +PRIVATE struct prefix_s crtso_prefix = { STANDARD_CRTSO_PREFIX, }; +#endif +#ifdef STANDARD_CRTSO0_PREFIX +PRIVATE struct prefix_s crtso0_prefix = { STANDARD_CRTSO0_PREFIX, }; +#endif +#ifdef STANDARD_CRTSO3_PREFIX +PRIVATE struct prefix_s crtso3_prefix = { STANDARD_CRTSO3_PREFIX, }; +#endif +PRIVATE struct prefix_s exec_prefix; +PRIVATE struct arg_s ldargs = { LD, }; +#ifdef BAS86 +PRIVATE struct arg_s ldrargs = { LD, }; +#endif +PRIVATE char *progname; +PRIVATE bool_T runerror; /* = FALSE */ +PRIVATE struct arg_s tmpargs; /* = empty */ +PRIVATE char *tmpdir; +PRIVATE bool_T verbose; /* = FALSE */ + +/* Who can say if the standard headers declared these? */ +int chmod P((const char *name, int mode)); +int execv P((char *name, char **argv)); +void exit P((int status)); +pid_t fork P((void)); +char *getenv P((const char *_name)); +pid_t getpid P((void)); +void *malloc P((unsigned size)); +void *realloc P((void *ptr, unsigned size)); +void (*signal P((int sig, void (*func) P((int sig))))) P((int sig)); +char *strcpy P((char *target, const char *source)); +size_t strlen P((const char *s)); +char *strrchr P((const char *s, int c)); +int unlink P((const char *name)); +pid_t wait P((int *status)); +int write P((int fd, char *buf, unsigned nbytes)); + +FORWARD void addarg P((struct arg_s *argp, char *arg)); +FORWARD void addprefix P((struct prefix_s *prefix, char *name)); +FORWARD void fatal P((char *message)); +FORWARD char *fixpath P((char *path, struct prefix_s *prefix, int mode)); +FORWARD void killtemps P((void)); +FORWARD void *my_malloc P((unsigned size, char *where)); +FORWARD char *my_mktemp P((void)); +FORWARD void my_unlink P((char *name)); +FORWARD void outofmemory P((char *where)); +FORWARD int run P((char *in_name, char *out_name, struct arg_s *argp)); +FORWARD void set_trap P((void)); +FORWARD void show_who P((char *message)); +FORWARD void startarg P((struct arg_s *argp)); +FORWARD char *stralloc P((char *s)); +FORWARD char *stralloc2 P((char *s1, char *s2)); +FORWARD void trap P((int signum)); +FORWARD void unsupported P((char *option, char *message)); +FORWARD void writen P((void)); +FORWARD void writes P((char *s)); +FORWARD void writesn P((char *s)); + +PUBLIC int main(argc, argv) +int argc; +char **argv; +{ + char *arg; + int argcount = argc; + bool_T *argdone = my_malloc((unsigned) argc * sizeof *argdone, "argdone"); + bool_T as_only = FALSE; + char *basename; +#ifdef BCC86 + bool_T bits32 = sizeof (char *) >= 4; + char *bits_arg; +#endif + bool_T cc_only = FALSE; +#ifdef CCC + bool_T cpp_pass = TRUE; +#else + bool_T cpp_pass = FALSE; +#endif +#ifdef BCC86 + char *crtso; +#endif + bool_T debug = FALSE; + bool_T echo = FALSE; + unsigned errcount = 0; + char ext; + char *f_out = NULL; + bool_T float_emulation = FALSE; +#ifdef BAS86 + bool_T gnu_objects = FALSE; +#endif + char *in_name; + int length; + unsigned ncisfiles = 0; + unsigned nifiles = 0; + unsigned npass_specs; + bool_T optimize = FALSE; + char *out_name; + bool_T profile = FALSE; + bool_T prep_only = FALSE; + bool_T prep_line_numbers = FALSE; + int status; + char *temp; + + progname = argv[0]; + addarg(&cppargs, CPPFLAGS); +#ifdef CCC + addarg(&asargs, "-j"); +#endif + addarg(&asargs, "-u"); + addarg(&asargs, "-w"); +#ifdef BCC86 + addarg(&ldargs, "-i"); +#endif +#ifdef BAS86 + addarg(&ldrargs, "-r"); +#endif + + /* pass 1 over argv to gather compile options */ + for (; --argc != 0;) + { + arg = *++argv; + *++argdone = TRUE; + if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0) + switch (arg[1]) + { +#ifdef BCC86 + case '0': + bits32 = FALSE; + break; + case '3': + bits32 = TRUE; + break; +#endif + case 'E': + prep_only = prep_line_numbers = cpp_pass = TRUE; + break; +#ifdef BAS86 + case 'G': + gnu_objects = TRUE; + break; +#endif + case 'P': + prep_only = cpp_pass = TRUE; + prep_line_numbers = FALSE; + break; + case 'O': + optimize = TRUE; /* unsupported( arg, "optimize" ); */ + break; + case 'S': + cc_only = TRUE; + break; + case 'V': + echo = TRUE; + break; + case 'c': + as_only = TRUE; + break; + case 'e': + cpp_pass = TRUE; + break; + case 'f': + float_emulation = TRUE; + ++errcount; + unsupported(arg, "float emulation"); + break; + case 'g': + debug = TRUE; /* unsupported( arg, "debug" ); */ + break; + case 'o': + if (--argc < 1) + { + ++errcount; + show_who("output file missing after -o\n"); + } + else + { + if (f_out != NULL) + show_who("more than one output file\n"); + f_out = *++argv; + *++argdone = TRUE; + } + break; + case 'p': + profile = TRUE; + ++errcount; + unsupported(arg, "profile"); + break; + case 'v': + verbose = TRUE; + break; + default: + *argdone = FALSE; + break; + } + else if (arg[0] == '-') + switch (arg[1]) + { + case 'A': + addarg(&asargs, arg + 2); + break; + case 'B': + addprefix(&exec_prefix, arg + 2); + break; + case 'C': + addarg(&ccargs, arg + 2); + break; + case 'D': + case 'I': + case 'U': +#ifndef CCC + addarg(&ccargs, arg); +#endif + addarg(&cppargs, arg); + break; + case 'L': + addarg(&ldargs, arg + 2); + break; + case 'P': + addarg(&cppargs, arg + 2); + break; +#ifdef CCC + case 'Q': + addarg(&ccargs, arg); + break; +#endif + case 'T': + tmpdir = arg + 2; + break; + case 't': + ++errcount; + unsupported(arg, "pass number"); + break; + default: + *argdone = FALSE; + break; + } + else + { + ++nifiles; + *argdone = FALSE; + length = strlen(arg); + if (length >= 2 && arg[length - 2] == '.' && + ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 's')) + ++ncisfiles; + } + } + npass_specs = prep_only + cc_only + as_only; + if (npass_specs != 0) + { + if (npass_specs > 1) + { + ++errcount; + show_who("more than 1 option from -E -P -S -c\n"); + } + if (f_out != NULL && ncisfiles > 1) + { + ++errcount; + show_who("cannot have more than 1 input with non-linked output\n"); + } + } + if (nifiles == 0) + { + ++errcount; + show_who("no input files\n"); + } + if (errcount != 0) + exit(1); + + if ((temp = getenv("BCC_EXEC_PREFIX")) != NULL) + addprefix(&exec_prefix, temp); + addprefix(&exec_prefix, STANDARD_EXEC_PREFIX); +#ifdef STANDARD_EXEC_PREFIX_2 + addprefix(&exec_prefix, STANDARD_EXEC_PREFIX_2); +#endif + cppargs.prog = fixpath(cppargs.prog, &exec_prefix, X_OK); + ccargs.prog = fixpath(ccargs.prog, &exec_prefix, X_OK); + asargs.prog = fixpath(asargs.prog, &exec_prefix, X_OK); + ldargs.prog = fixpath(ldargs.prog, &exec_prefix, X_OK); + ldrargs.prog = fixpath(ldrargs.prog, &exec_prefix, X_OK); + if (tmpdir == NULL && (tmpdir = getenv("TMPDIR")) == NULL) + tmpdir = "/tmp"; + + if (prep_only && !prep_line_numbers) + addarg(&cppargs, "-P"); +#ifdef BCC86 + if (bits32) + { + bits_arg = "-3"; + crtso = fixpath(CRTSO, &crtso3_prefix, R_OK); + } + else + { + bits_arg = "-0"; + crtso = fixpath(CRTSO, &crtso0_prefix, R_OK); + } + addarg(&ccargs, bits_arg); + addarg(&cppargs, bits_arg); + addarg(&asargs, bits_arg); +#ifdef BAS86 + if (!gnu_objects) + { + addarg(&ldargs, bits_arg); + addarg(&ldrargs, bits_arg); + addarg(&ldargs, crtso); + } +#endif /* BAS86 */ +#endif /* BCC86 */ +#if defined(BAS86) && !defined(BCC86) + if (!gnu_objects) + addarg(&ldargs, fixpath(CRTSO, &crtso_prefix, R_OK)); +#endif + if (ncisfiles < 2) + echo = FALSE; + set_trap(); + + /* pass 2 over argv to compile and assemble .c and .s files */ + /* and gather arguments for loader */ + for (argv -= (argc = argcount) - 1, argdone -= argcount - 1; --argc != 0;) + { + arg = *++argv; + if (!*++argdone) + { + length = strlen(arg); + if (length >= 2 && arg[length - 2] == '.' && + ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 's')) + { + if (echo || verbose) + { + writes(arg); + writesn(":"); + } + if ((basename = strrchr(arg, DIRCHAR)) == NULL) + basename = arg; + else + ++basename; + in_name = arg; + if (ext == 'c') + { + if (cpp_pass) + { + if (prep_only) + out_name = f_out; + else + out_name = my_mktemp(); + if (run(in_name, out_name, &cppargs) != 0) + continue; + in_name = out_name; + } + ext = 'i'; + } + if (ext == 'i') + { + if (prep_only) + continue; + if (cc_only) + { + if (f_out != NULL) + out_name = f_out; + else + { + out_name = stralloc(basename); + out_name[strlen(out_name) - 1] = 's'; + } + } + else + out_name = my_mktemp(); + if (run(in_name, out_name, &ccargs) != 0) + continue; + in_name = out_name; + ext = 's'; + } + if (ext == 's') + { + if (prep_only || cc_only) + continue; + out_name = stralloc(basename); + out_name[strlen(out_name) - 1] = 'o'; + if (as_only) + { + if (f_out != NULL) + out_name = f_out; + else + { + out_name = stralloc(basename); + out_name[strlen(out_name) - 1] = 'o'; + } + } + else + out_name = my_mktemp(); + addarg(&asargs, "-n"); + arg[length - 1] = 's'; + addarg(&asargs, arg); +#ifdef BCC86 + if (gnu_objects) + { + char *tmp_out_name; + + tmp_out_name = my_mktemp(); + status = run(in_name, tmp_out_name, &asargs); + asargs.argc -= 2; + if (status != 0) + continue; + if (run(tmp_out_name, out_name, &ldrargs) != 0) + continue; + } + else +#endif + { + status = run(in_name, out_name, &asargs); + asargs.argc -= 2; + if (status != 0) + continue; + } + ext = 'o'; + in_name = out_name; + } + if (ext == 'o') + { + if (prep_only || cc_only || as_only) + continue; + addarg(&ldargs, in_name); + } + } + else + addarg(&ldargs, arg); + } + } + + if (!prep_only && !cc_only && !as_only && !runerror) + { + if (f_out == NULL) + f_out = "a.out"; +#ifdef BCC86 + if (gnu_objects) + { + ldargs.prog = GCC; + run((char *) NULL, f_out, &ldargs); + } + else +#endif + { + addarg(&ldargs, "-lc"); + run((char *) NULL, f_out, &ldargs); + } + } + killtemps(); + return runerror ? 1 : 0; +} + +PRIVATE void addarg(argp, arg) +register struct arg_s *argp; +char *arg; +{ + int new_argc; + char **new_argv; + + if (argp->nr_allocated == 0) + startarg(argp); + new_argc = argp->argc + 1; + if (new_argc >= argp->nr_allocated) + { + argp->nr_allocated += ALLOC_UNIT; + new_argv = realloc(argp->argv, argp->nr_allocated * sizeof *argp->argv); + if (new_argv == NULL) + outofmemory("addarg"); + argp->argv = new_argv; + } + argp->argv[argp->argc] = arg; + argp->argv[argp->argc = new_argc] = NULL; +} + +PRIVATE void addprefix(prefix, name) +struct prefix_s *prefix; +char *name; +{ + struct prefix_s *new_prefix; + + if (prefix->name == NULL) + prefix->name = name; + else + { + new_prefix = my_malloc(sizeof *new_prefix, "addprefix"); + new_prefix->name = name; + new_prefix->next = NULL; + prefix->next = new_prefix; + } +} + +PRIVATE void fatal(message) +char *message; +{ + writesn(message); + killtemps(); + exit(1); +} + +PRIVATE char *fixpath(path, prefix, mode) +char *path; +struct prefix_s *prefix; +int mode; +{ + char *ppath; + + for (; prefix != NULL; prefix = prefix->next) + { + ppath = stralloc2(prefix->name, path); + if (access(ppath, mode) == 0) + return ppath; + free(ppath); + } + return path; +} + +PRIVATE void killtemps() +{ + while (tmpargs.argc > START_ARGS) + my_unlink(tmpargs.argv[--tmpargs.argc]); +} + +PRIVATE void *my_malloc(size, where) +unsigned size; +char *where; +{ + void *block; + + if ((block = malloc(size)) == NULL) + outofmemory(where); + return block; +} + +PRIVATE char *my_mktemp() +{ + char *p; + unsigned digit; + unsigned digits; + char *template; + static unsigned tmpnum; + + p = template = stralloc2(tmpdir, "/bccYYYYXXXX"); + p += strlen(p); + digits = getpid(); + while (*--p == 'X') + { + if ((digit = digits % 16) > 9) + digit += 'A' - ('9' + 1); + *p = digit + '0'; + digits /= 16; + } + digits = tmpnum; + while (*p == 'Y') + { + if ((digit = digits % 16) > 9) + digit += 'A' - ('9' + 1); + *p-- = digit + '0'; + digits /= 16; + } + ++tmpnum; + addarg(&tmpargs, template); + return template; +} + +PRIVATE void my_unlink(name) +char *name; +{ + if (verbose) + { + show_who("unlinking "); + writesn(name); + } + if (unlink(name) < 0 && verbose) + { + show_who("error unlinking "); + writesn(name); + } +} + +PRIVATE void outofmemory(where) +char *where; +{ + show_who("out of memory in "); + fatal(where); +} + +PRIVATE int run(in_name, out_name, argp) +char *in_name; +char *out_name; +struct arg_s *argp; +{ + int arg0; + int i; + int status; + + arg0 = 0; + if (in_name == NULL) + ++arg0; + if (out_name == NULL) + arg0 += 2; + else if (argp->minus_O_broken) + ++arg0; + if (argp->nr_allocated == 0) + startarg(argp); + argp->argv[arg0] = argp->prog; + i = arg0 + 1; + if (in_name != NULL) + argp->argv[i++] = in_name; + if (out_name != NULL) + { + if (!argp->minus_O_broken) + argp->argv[i++] = "-o"; + argp->argv[i++] = out_name; + } + if (verbose) + { + for (i = arg0; i < argp->argc; ++i) + { + writes(argp->argv[i]); + writes(" "); + } + writen(); + } + switch (fork()) + { + case -1: + show_who("fork failed"); + fatal(""); + case 0: + execv(argp->prog, argp->argv + arg0); + show_who("exec of "); + writes(argp->prog); + fatal(" failed"); + default: + wait(&status); + for (i = tmpargs.argc - 1; i >= START_ARGS; --i) + if (in_name == tmpargs.argv[i]) + { + my_unlink(in_name); + --tmpargs.argc; + memmove(tmpargs.argv + i, tmpargs.argv + i + 1, + (tmpargs.argc - i) * sizeof tmpargs.argv[0]); + break; + } + if (status != 0) + { + killtemps(); + runerror = TRUE; + } + return status; + } +} + +PRIVATE void set_trap() +{ + int signum; + +#ifndef _NSIG +#define NSIG _NSIG +#endif + for (signum = 0; signum <= _NSIG; ++signum) +#ifdef SIGCHLD + if (signum != SIGCHLD) +#endif + if (signal(signum, SIG_IGN) != SIG_IGN) + signal(signum, trap); +} + +PRIVATE void show_who(message) +char *message; +{ + writes(progname); + writes(": "); + writes(message); +} + +PRIVATE void startarg(argp) +struct arg_s *argp; +{ + argp->argv = my_malloc((argp->nr_allocated = ALLOC_UNIT) + * sizeof *argp->argv, "startarg"); + argp->argc = START_ARGS; + argp->argv[START_ARGS] = NULL; +} + +PRIVATE char *stralloc(s) +char *s; +{ + return strcpy(my_malloc(strlen(s) + 1, "stralloc"), s); +} + +PRIVATE char *stralloc2(s1, s2) +char *s1; +char *s2; +{ + return strcat(strcpy(my_malloc( + strlen(s1) + strlen(s2) + 1, "stralloc2"), s1), s2); +} + +PRIVATE void trap(signum) +int signum; +{ + signal(signum, SIG_IGN); + if (verbose) + show_who("caught signal"); + fatal(""); +} + +PRIVATE void unsupported(option, message) +char *option; +char *message; +{ + show_who("compiler option "); + writes(option); + writes(" ("); + writes(message); + writesn(") not supported yet"); +} + +PRIVATE void writen() +{ + writes("\n"); +} + +PRIVATE void writes(s) +char *s; +{ + write(2, s, strlen(s)); +} + +PRIVATE void writesn(s) +char *s; +{ + writes(s); + writen(); +} diff --git a/bin86-0.3/bcc/bcc.doc b/bin86-0.3/bcc/bcc.doc new file mode 100644 index 0000000..7f2a8ed --- /dev/null +++ b/bin86-0.3/bcc/bcc.doc @@ -0,0 +1,165 @@ +Bcc options +----------- + +bcc [-03EGOPSVcegv] [-Aas_option] [-Bexecutable_prefix] [-Ccc1_option] + [-Ddefine] [-Iinclude_dir] [-Lld_option] [-Qc386_option] [-Ttmpdir] + [-Uundef] [-o outfile] [-fpt error] [ld_options] [infiles] + +The 6809 version does not support -0, -3 or -G. +Only the c386 version supports -Q. + +defaults (off or none except for these): +-03 native +outfile stdout for preprocessor output + somewhere/file.[ci] -> file.s for compiler output + somewhere/file.[cis] -> file.o for assembler output + a.out for ld output + +-0 8086 target (works even on 80386 host) +-3 80386 target (works even on 8086 host) +-A pass remainder of option to assembler (e.g. -A-l -Alistfile for a listing) +-B prefix for executable search path (as usual; after the -B prefixes comes + the environment variable BCC_EXEC_PREFIX if that is set, followed by the + compiled-in default (something like /usr/libexec/i386/bcc/)) +-C pass remainder of option to cc1 (e.g. -C-c for caller-saves) +-D define (as usual) +-E produce preprocessor output (as usual) +-G produce gnu-Minix objects (link with gnu ld) +-I include search path (as usual) +-L pass remainder of option to linker +-O optimize (does nothing) +-P produce preprocessor output with no line numbers (as usual) +-Q pass full option to c386 +-S produce assembler file (as usual) +-T temporary directory (overrides previous value and default; default is + from the environment variable TMPDIR if that is set, otherwise /tmp) +-U undefine (as usual) +-V print names of files being compiled +-c produce object file (as usual) +-e run the preprocess pass separately. This takes less memory, and may help + or harm by giving more traditional semantics like token pasting with /**/. +-f error (float emulation not supported) +-g produce debugging info (does nothing) +-o output file name follows (assembler, object or executable) (as usual) +-p error (profiling not supported) +-t error (substitution of some cc passes not supported) +-v print names and args of subprocesses being run + +Other options are passed to the linker, in particular -i-, -lx, -M, -m, -s. +The -i option is always passed to the linker but can be cancelled using -i-. + +This is supposed to match the V7 manual except for -0, -3, -A, -C, -G, -L, +-T, -V, -e, -v and where not supported. + +cc1 options +---------- + +cc1 [-03EPcdfltw[-]] [-Ddefine] [-Iinclude_dir] [-Uundef] [-o outfile] [infile] + +The 6809 version does not support -0 or -3 but it supports -p. + +defaults (off or none except for these): +-03 native +-c on for 6809 +-f on for 6809 +outfile stdout +infile stdin + +-0 8086 target (works even on 80386 host) +-3 80386 target (works even on 8086 host) +-D define (as usual) +-E produce preprocessor output (as usual) +-I include search path (as usual) +-P produce preprocessor output with no line numbers (as usual) +-c produce code with caller saving regs before function calls +-d print debugging information in assembly output +-f produce code with 1st argument passed in a register +-l produce code for 2 3 1 0 long byte order (only works in 16-bit versions) +-o assembler output file name follows +-p produce (almost) position-independent code +-t print source code in assemby output +-w print what cc1 thinks is the location counter in assembly output + +All the options except -D, -I and -o may be turned off by following the +option letter by a '-'. Options are processed left to right so the last +setting has precedence. + +The following is defined before option processing: + +__BCC__ 1 + +The following may be defined after option processing: + +__AS09__ 1 if 6809 version +__AS386_16__ 1 if -0 option on 80*86 +__AS386_32__ 1 if -3 option on 80*86 +__CALLER_SAVES__ 1 if -c option +__FIRST_ARG_IN_AX__ 1 if -f option on 80*86 +__FIRST_ARG_IN_X__ 1 if -f option on 6809 +__LONG_BIG_ENDIAN__ 1 if -l option +__POS_INDEPENDENT__ 1 if -p option on 6809 + +The following are standard builtins: + +__FILE__ stringized name of current input file +__LINE__ current line number + +As options +---------- + +as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src + +The 6809 version does not support -0, -3, -a or -j. + +defaults (off or none except for these; no output is produced without a flag): +-03 native +list stdout (beware of clobbering next arg) +name basename of the source name + +-0 start with 16-bit code segment +-3 start with 32-bit code segment +-a enable partial compatibility with asld +-b produce binary file, filename may follow (obsolete) +-g only put global symbols in object file +-j force all jumps to be long +-l produce list file, filename may follow +-m print macro expansions in listing +-n name of module follows (goes in object instead of source name) +-o produce object file, filename follows +-s produce symbol file, filename follows (obsolete) +-u take undefined symbols as imported-with-unspecified segment +-w don't print warnings + +The -u and -w options are perhaps back to front because they are needed for +cc1 output and Minix's make does the wrong thing with .s files left around. +However, all assembler code not written by compilers should assemble with +them turned off. + +Ld options +---------- + +For the version that produces Minix a.out format: +ld [-03Mims[-]] [-T textaddr] [-llib_extension] [-o outfile] infile... + +For the version that produces gnu-Minix a.out format: +ld [-03Mimrs[-]] [-T textaddr] [-llib_extension] [-o outfile] infile... + +The 6809 version does not support -i or -r. + +defaults (off or none except for these): +-03 native +outfile a.out + +-0 produce header with 16-bit magic and use subdir i86 for -lx +-3 produce header with 32-bit magic and use subdir i386 for -lx +-M print symbols linked on stdout +-T text base address follows (in format suitable for strtoul) +-i separate I&D output +-lx add library /local/lib/subdir/libx.a to list of files linked +-m print modules linked on stdout +-o output file name follows +-r produce output suitable for further relocation +-s strip symbols + +All the options except -T, -l and -o may be turned off by following the option +letter by a '-', as for cc1. diff --git a/bin86-0.3/bccfp/Makefile b/bin86-0.3/bccfp/Makefile new file mode 100644 index 0000000..6caa362 --- /dev/null +++ b/bin86-0.3/bccfp/Makefile @@ -0,0 +1,44 @@ +# Makefile for bcc 386 software floating point library + +.SUFFIXES: .x # .x files are .s files that need C-preprocessing +.x.o: + $(CPP) $(CPPFLAGS) $< >tmp + $(AS) tmp -n $* -o $@ + +AS =as -3 +CFLAGS =-O +CPP =/lib/cpp +CPPFLAGS =-P +FPDIST =Makefile $(FPSRC) test.c bccfp.tex +FPSRC =fadd.x fcomp.x fdiv.x fmul.x fbsr.x \ + fperr.c fperror.x fptoi.x fpushd.x fpulld.x \ + fpushi.x fpushf.x fpullf.x frexp.x ftst.x \ + gcclib.x \ + fabs.x ldexp.x modf.c \ + fperr.h fplib.h +FPOBJ =fadd.o fcomp.o fdiv.o fmul.o fpbsr.o \ + fperr.o fperror.o fptoi.o fpushd.o fpulld.o \ + fpushi.o fpushf.o fpullf.o frexp.o ftst.o \ + fabs.o ldexp.o modf.o +JUNK =tmp +LIB =. + +test: test.c $(LIB)/libfp.a + $(CC) -o $@ test.c $(LIB)/libfp.a -lm + +$(FPOBJ): fplib.h +fperr.c fperror.x: fperr.h + +$(LIB)/libfp.a: $(FPOBJ) + ar rc $(LIB)/libfp.a $(FPOBJ) + rm -f $(JUNK) + +dist: $(FPDIST) + /bin/tar cvf - $(FPDIST) | /bin/compress -b 13 >bccfp.tar.Z + uue bccfp.tar.Z + +clean: + rm -f $(FPOBJ) $(JUNK) test + +realclean: clean + rm -f $(LIB)/libfp.a bccfp.tar.Z bccfp.uue diff --git a/bin86-0.3/bccfp/bccfp.tex b/bin86-0.3/bccfp/bccfp.tex new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bin86-0.3/bccfp/bccfp.tex diff --git a/bin86-0.3/bccfp/changes b/bin86-0.3/bccfp/changes new file mode 100644 index 0000000..2cc632a --- /dev/null +++ b/bin86-0.3/bccfp/changes @@ -0,0 +1,30 @@ +fcomp: +Fixes for negative 0 (perhaps this shouldn't be generated, like denormals +and infinities (these would cause even more trouble) but Fsub routine or +something generated one). + +frexp.x: +Deleted 3rd arg (used to return value when bcc wasn't doing it right). + +Fixed frexp(value = 0) and ldexp(value = 0) returning nonzero. + +Most files: +Changed comment symbol to '!' for new assembler (not the native ';' in +case this is ported to ACK someday). + +Avoided using ebp and unnecessary register saves. + +Changed assembler style to make it a bit more portable or like I do it +(no '$' for hex, 8[esp] instead of [esp+8], use only .define and not export +or .globl, use '#' (could use nothing) instead of '*' for immediate). +The partly-supported 8(ebp) and .globl would be still more portable. + +Changed terminology 'mantissa' to 'fraction'. + +Round to even. Required for 'paranioa' not to find any defects. + +Used preprocessor. + +Parametrized most of the magic numbers. Phew! + +Supported denormals. Now 'paranioa' doesn't find any flaws. diff --git a/bin86-0.3/bccfp/fabs.x b/bin86-0.3/bccfp/fabs.x new file mode 100644 index 0000000..fe81676 --- /dev/null +++ b/bin86-0.3/bccfp/fabs.x @@ -0,0 +1,17 @@ +! bcc 386 floating point routines (version 2) -- _fabs +! author: Bruce Evans + +#include "fplib.h" + +! double fabs(double value); +! returns the absolute value of a number +! this works for all NaNs, like the 80*87 fabs, but perhaps we should check +! for exceptions that can happen when an 80*87 register is loaded + + .globl _fabs + .align ALIGNMENT +_fabs: + mov eax,PC_SIZE+D_LOW[esp] + mov edx,PC_SIZE+D_HIGH[esp] + and edx,~D_SIGN_MASK + ret diff --git a/bin86-0.3/bccfp/fadd.x b/bin86-0.3/bccfp/fadd.x new file mode 100644 index 0000000..d1e60b1 --- /dev/null +++ b/bin86-0.3/bccfp/fadd.x @@ -0,0 +1,485 @@ +! bcc 386 floating point routines (version 2) +! -- Fadd, Faddd, Faddf, Fsub, Fsubd, Fsubf, normalize2 +! author: Bruce Evans + +#include "fplib.h" + +#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE) + + .extern Fpushf + .extern fpdenormal + .extern fpoverflow + .extern fpunderflow + + .globl Fadd + .align ALIGNMENT +Fadd: + push ebp + push edi + push esi + mov eax,FRAME_SIZE+D_LOW[esp] + mov edx,FRAME_SIZE+D_HIGH[esp] + mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp] + mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp] + call addition + mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax + mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx + pop esi + pop edi + pop ebp + ret #D_SIZE + + .globl Faddd + .align ALIGNMENT +Faddd: + push ebp + push edi + push esi + mov eax,FRAME_SIZE+D_LOW[esp] + mov edx,FRAME_SIZE+D_HIGH[esp] + mov ecx,D_HIGH[ebx] + mov ebx,D_LOW[ebx] + call addition + mov FRAME_SIZE+D_LOW[esp],eax + mov FRAME_SIZE+D_HIGH[esp],edx + pop esi + pop edi + pop ebp + ret + + .globl Faddf + .align ALIGNMENT +Faddf: + push ebp + push edi + push esi + call Fpushf + pop ebx ! yl + pop ecx ! yu + mov eax,FRAME_SIZE+D_LOW[esp] ! xl + mov edx,FRAME_SIZE+D_HIGH[esp] ! xu + call addition + mov FRAME_SIZE+D_LOW[esp],eax + mov FRAME_SIZE+D_HIGH[esp],edx + pop esi + pop edi + pop ebp + ret + + .globl Fsub + .align ALIGNMENT +Fsub: + push ebp + push edi + push esi + mov eax,FRAME_SIZE+D_LOW[esp] + mov edx,FRAME_SIZE+D_HIGH[esp] + mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp] + mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp] + xor ecx,#D_SIGN_MASK ! complement sign + call addition + mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax + mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx + pop esi + pop edi + pop ebp + ret #D_SIZE + + .globl Fsubd + .align ALIGNMENT +Fsubd: + push ebp + push edi + push esi + mov eax,FRAME_SIZE+D_LOW[esp] + mov edx,FRAME_SIZE+D_HIGH[esp] + mov ecx,D_HIGH[ebx] + mov ebx,D_LOW[ebx] + xor ecx,#D_SIGN_MASK ! complement sign + call addition + mov FRAME_SIZE+D_LOW[esp],eax + mov FRAME_SIZE+D_HIGH[esp],edx + pop esi + pop edi + pop ebp + ret + + .globl Fsubf + .align ALIGNMENT +Fsubf: + push ebp + push edi + push esi + call Fpushf + pop ebx ! yl + pop ecx ! yu + mov eax,FRAME_SIZE+D_LOW[esp] ! xl + mov edx,FRAME_SIZE+D_HIGH[esp] ! xu + xor ecx,#D_SIGN_MASK ! complement sign + call addition + mov FRAME_SIZE+D_LOW[esp],eax + mov FRAME_SIZE+D_HIGH[esp],edx + pop esi + pop edi + pop ebp + ret + + .align ALIGNMENT +exp_y_0: + +! Check for x denormal, to split off special case where both are denormal, +! so the norm bit (or 1 higher) is known to be set for addition, so addition +! can be done faster + + test esi,#D_EXP_MASK + jnz x_normal_exp_y_0 + test esi,esi ! test top bits of x fraction + jnz both_denorm ! denormal iff nonzero fraction with zero exp + test eax,eax ! test rest of fraction + jz return_edx_eax ! everything 0 (XXX - do signs matter?) +both_denorm: + call fpdenormal + test ebp,#D_SIGN_MASK + jnz denorm_subtract + +! Add denormal x to denormal or zero y + +#if D_NORM_BIT != D_EXP_SHIFT +#include "error, carry into norm bit does not go into exponent" +#endif + + add eax,ebx + adc esi,edi + or edx,esi + ret + +denorm_subtract: + sub eax,ebx + sbb esi,edi + or edx,esi + ret + + .align ALIGNMENT +x_normal_exp_y_0: + test edi,edi ! this is like the check for x denormal + jnz y_denorm + test ebx,ebx + jz return_edx_eax ! y = 0 +y_denorm: + call fpdenormal + or ecx,#1 << D_EXP_SHIFT ! normalize y by setting exponent to 1 + jmp got_y + + .align ALIGNMENT +return_edx_eax: + ret + + .align ALIGNMENT +add_bigshift: + cmp ecx,#D_FRAC_BIT+2 + jae return_edx_eax ! x dominates y + sub ecx,#REG_BIT + shrd ebp,ebx,cl + shrd ebx,edi,cl + shr edi,cl + add eax,edi + adc esi,#0 + xchg ebp,ebx + br normalize + + .align ALIGNMENT +addition: + mov esi,edx ! this mainly for consistent naming + and esi,#D_EXP_MASK | D_FRAC_MASK ! discard sign so comparison is simple + mov edi,ecx ! free cl for shifts + and edi,#D_EXP_MASK | D_FRAC_MASK + cmp esi,edi + ja xbigger + jb swap + cmp eax,ebx + jae xbigger +swap: + xchg edx,ecx + xchg eax,ebx + xchg esi,edi +xbigger: + +! edx holds sign of result from here on +! and exponent of result before the normalization step + + mov ebp,edx ! prepare difference of signs + xor ebp,ecx + + and ecx,#D_EXP_MASK ! extract exp_y and check for y 0 or denormal + beq exp_y_0 ! otherwise x is not 0 or denormal either + and edi,#D_FRAC_MASK ! extract fraction + or edi,#D_NORM_MASK ! normalize +got_y: + and esi,#D_FRAC_MASK ! extract fraction + or esi,#D_NORM_MASK ! normalize + + sub ecx,edx ! carries from non-exp bits in edx killed later + neg ecx + and ecx,#D_EXP_MASK + shr ecx,#D_EXP_SHIFT ! difference of exponents + +got_x_and_y: + and ebp,#D_SIGN_MASK ! see if signs are same + bne subtract ! else roundoff reg ebp has been cleared + + cmp cl,#REG_BIT + bhis add_bigshift + shrd ebp,ebx,cl + shrd ebx,edi,cl + shr edi,cl + add eax,ebx + adc esi,edi + +! result edx(D_SIGN_MASK | D_EXP_MASK bits):esi:eax:ebp but needs normalization + + mov edi,edx + and edi,#D_EXP_MASK + test esi,#D_NORM_MASK << 1 + jnz add_loverflow + +add_round: + cmp ebp,#1 << (REG_BIT-1) ! test roundoff register + jb add_done ! no rounding + jz tie +add_roundup: + add eax,#1 + adc esi,#0 + test esi,#D_NORM_MASK << 1 + jnz pre_add_loverflow ! rounding may cause overflow! +add_done: + mov ecx,edx ! duplicated code from 'done' + and edx,#D_SIGN_MASK + or edx,edi + and esi,#D_FRAC_MASK + or edx,esi + ret + + .align ALIGNMENT +tie: + test al,#1 ! tie case, round to even + jz add_done ! even, no rounding + jmp add_roundup + + .align ALIGNMENT +pre_add_loverflow: + sub ebp,ebp ! clear rounding register + ! probably avoiding tests for more rounding +add_loverflow: + shrd ebp,eax,#1 + jnc over_set_sticky_bit + or ebp,#1 +over_set_sticky_bit: + shrd eax,esi,#1 + shr esi,#1 + add edi,1 << D_EXP_SHIFT + cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT + jl add_round +overflow: + call fpoverflow + mov eax,ecx ! XXX - wrong reg + ret + +! result edx(D_SIGN_MASK | D_EXP_MASK bits): +! esi((D_NORM_MASK << 1) | D_NORM_MASK | D_FRAC_MASK bits):eax:ebp:ebx +! but needs normalization + + .align ALIGNMENT +normalize: + mov edi,edx + and edi,#D_EXP_MASK + test esi,#D_NORM_MASK << 1 + bne loverflow + +! result edx(D_SIGN_MASK bit):edi(D_EXP_MASK bits): +! esi(D_NORM_MASK | D_FRAC_MASK bits):eax:ebp:ebx +! but needs normalization + + .globl normalize2 +normalize2: + test esi,#D_NORM_MASK ! already-normalized is very common + jz normalize3 +round: + cmp ebp,#1 << (REG_BIT-1) ! test roundoff register + jb done ! no rounding + jz near_tie +roundup: + add eax,#1 + adc esi,#0 + test esi,#D_NORM_MASK << 1 + bne pre_loverflow ! rounding may cause overflow! +done: +cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT +jae overflow + and edx,#D_SIGN_MASK ! extract sign of largest and result + or edx,edi ! include exponent with sign + and esi,#D_FRAC_MASK ! discard norm bit + or edx,esi ! include fraction with sign and exponent + ret + + .align ALIGNMENT +near_tie: + test ebx,ebx + jnz roundup + test al,#1 ! tie case, round to even + jz done ! even, no rounding + jmp roundup + + .align ALIGNMENT +not_in_8_below: + shld ecx,esi,#REG_BIT-D_NORM_BIT+16 ! in 9 to 16 below? + jz not_in_16_below ! must be way below (17-20 for usual D_NORM_BIT) + mov cl,bsr_table[ecx] ! bsr(esi) - (D_NORM_BIT-16) + neg ecx ! (D_NORM_BIT-16) - bsr(esi) + add ecx,#16 + jmp got_shift + + .align ALIGNMENT +not_in_16_below: + mov cl,bsr_table[esi] ! bsr(esi) directly + neg ecx ! -bsr(esi) + add ecx,#D_NORM_BIT ! D_NORM_BIT - bsr(esi) + jmp got_shift + + .align ALIGNMENT +normalize3: + test esi,esi + jz shift32 + +! Find first nonzero bit in esi +! Don't use bsr, it is very slow (const + 3 * bit_found) +! We know that there is some nonzero bit, and the norm bit and above are clear + + sub ecx,ecx ! prepare unsigned extension of cl + shld ecx,esi,#REG_BIT-D_NORM_BIT+8 ! any bits in 8 below norm bit? + jz not_in_8_below + mov cl,bsr_table[ecx] ! bsr(esi) - (D_NORM_BIT-8) + neg ecx ! (D_NORM_BIT-8) - bsr(esi) + add ecx,#8 ! D_NORM_BIT - bsr(esi) +got_shift: + shld esi,eax,cl + shld eax,ebp,cl + shld ebp,ebx,cl + shl ebx,cl + shl ecx,D_EXP_SHIFT + sub edi,ecx + bhi round ! XXX - can rounding change the exponent to > 0? + ! not bgt since edi may be 0x80000000 + neg edi + shr edi,#D_EXP_SHIFT + inc edi + br fpunderflow + + .align ALIGNMENT +pre_loverflow: + sub ebp,ebp ! clear rounding registers + sub ebx,ebx ! probably avoiding tests for more rounding + +loverflow: + shr esi,#1 ! carry bit stayed in the reg + rcr eax,#1 + rcr ebp,#1 + rcr ebx,#1 + add edi,1 << D_EXP_SHIFT + cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT + blt round + call fpoverflow + mov eax,ecx ! XXX - wrong reg + ret + + .align ALIGNMENT +shift32: + test eax,eax + jz shift64 + mov esi,eax + mov eax,ebp + mov ebp,ebx + sub ebx,ebx + sub edi,#REG_BIT << D_EXP_SHIFT +shiftxx: + test esi,#~(D_NORM_MASK | D_FRAC_MASK) + jz over_adjust ! else too big already + shrd ebx,ebp,#D_BIT-D_FRAC_BIT + shrd ebp,eax,#D_BIT-D_FRAC_BIT + shrd eax,esi,#D_BIT-D_FRAC_BIT + shr esi,#D_BIT-D_FRAC_BIT + add edi,#(D_BIT-D_FRAC_BIT) << D_EXP_SHIFT +over_adjust: + test edi,edi + bgt normalize2 + neg edi + shr edi,#D_EXP_SHIFT + inc edi + br fpunderflow + + .align ALIGNMENT +shift64: + test ebp,ebp + jz shift96 + mov esi,ebp + mov eax,ebx + sub ebp,ebp + mov ebx,ebp + sub edi,#(2*REG_BIT) << D_EXP_SHIFT + jmp shiftxx + + .align ALIGNMENT +shift96: + test ebx,ebx ! XXX - this test is probably unnecessary + ! since the shift must be small unless we + ! are subtracting 2 almost-equal numbers, + ! and then the bits beyond 64 will mostly + ! be 0 + jz return_esi_eax ! all zero + mov esi,ebx + sub ebx,ebx + sub edi,#(3*REG_BIT) << D_EXP_SHIFT + jmp shiftxx + + .align ALIGNMENT +return_esi_eax: + mov edx,esi + ret + + .align ALIGNMENT +subtract: + sub ebp,ebp ! set up roundoff register + cmp ecx,#REG_BIT + jae subtract_bigshift + shrd ebp,ebx,cl + shrd ebx,edi,cl + shr edi,cl + neg ebp ! begin subtraction esi:eax:0 - edi:ebx:ebp + sbb eax,ebx + sbb esi,edi + sub ebx,ebx + mov edi,edx + and edi,#D_EXP_MASK + br normalize2 + + .align ALIGNMENT +subtract_bigshift: + cmp ecx,#D_FRAC_BIT+2 + bhis return_edx_eax ! x dominates y + sub ecx,#REG_BIT + shrd ebp,ebx,cl + shrd ebx,edi,cl + shr edi,cl + not ebp ! begin subtraction esi:eax:0:0 - 0:edi:ebx:ebp + not ebx + add ebp,#1 + adc ebx,#0 + cmc + sbb eax,edi + sbb esi,#0 + xchg ebp,ebx + mov edi,edx + and edi,#D_EXP_MASK + br normalize2 + + .data + .extern bsr_table diff --git a/bin86-0.3/bccfp/fcomp.x b/bin86-0.3/bccfp/fcomp.x new file mode 100644 index 0000000..71148ab --- /dev/null +++ b/bin86-0.3/bccfp/fcomp.x @@ -0,0 +1,89 @@ +! bcc 386 floating point routines (version 2) -- Fcomp, Fcompd, Fcompf +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + + .extern Fpushf + +! Pop 2 doubles from stack and compare them, return result in flags so +! normal signed branches work (unlike 80x87 which returns the result in +! the zero and carry flags). + + .globl Fcomp + .align ALIGNMENT +Fcomp: + pop ecx ! get return address + pop eax ! xl + pop edx ! xu + push ecx ! put back ret address - pop 2nd double later + +! All this popping is bad on 486's since plain mov takes 1+ cycle and pop +! takes 4 cycles. But this code is designed for 386's where popping is +! nominally the same speed and saves code space and so maybe instruction +! fetch time as well as the instruction to adjust the stack (ret #n takes +! no longer than plain ret but inhibits gotos). + + mov ebx,PC_SIZE+D_LOW[esp] ! yl + mov ecx,PC_SIZE+D_HIGH[esp] ! yu + jmp compare + +! Pop double from stack and compare with double at [ebx] + + .globl Fcompd + .align ALIGNMENT +Fcompd: + mov eax,PC_SIZE+D_LOW[esp] ! xl + mov edx,PC_SIZE+D_HIGH[esp] ! xu + mov ecx,D_HIGH[ebx] ! yu + mov ebx,D_LOW[ebx] ! yl + +compare: + test edx,#D_SIGN_MASK ! is x >= 0? + jz cmp0 ! yes; just compare x and y + test ecx,#D_SIGN_MASK ! no; but is y >= 0? + jz cmp0 ! yes; just compare x and y + + xchg edx,ecx ! x, y < 0, so ... + xchg eax,ebx ! ... swap x and y ... + xor edx,#D_SIGN_MASK ! ... and toggle signs + xor ecx,#D_SIGN_MASK + +cmp0: + cmp edx,ecx ! compare upper dwords + jnz checkneg0 ! if upper dwords differ, job is almost done + mov edx,eax ! upper dwords equal, so ... + mov ecx,ebx ! ... must make unsigned comparison of lower dwords + shr edx,#1 ! shift past sign + shr ecx,#1 + cmp edx,ecx ! compare top 31 bits of lower dwords + jnz return ! if these differ, job is done + and eax,#1 ! compare lowest bits + and ebx,#1 + cmp eax,ebx + +return: + ret #D_SIZE ! return, popping 1 double from stack + +checkneg0: + test edx,#D_EXP_MASK | D_FRAC_MASK ! check to catch unusual case ... + jnz recheck + test eax,eax + jnz recheck + test ecx,#D_EXP_MASK | D_FRAC_MASK + jnz recheck + test ebx,ebx + jz return ! ... both are (+-) zero, return 'z' + +recheck: + cmp edx,ecx ! the upper words were really different + ret #D_SIZE + + .globl Fcompf + .align ALIGNMENT +Fcompf: + call Fpushf + pop ebx ! yl + pop ecx ! yu + mov eax,PC_SIZE+D_LOW[esp] ! xl + mov edx,PC_SIZE+D_HIGH[esp] ! xu + jmp compare diff --git a/bin86-0.3/bccfp/fdiv.x b/bin86-0.3/bccfp/fdiv.x new file mode 100644 index 0000000..4a5cf74 --- /dev/null +++ b/bin86-0.3/bccfp/fdiv.x @@ -0,0 +1,312 @@ +#define EF_SIZE 4 + +! bcc 386 floating point routines (version 2) -- Fdiv, Fdivd, Fdivf +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + +#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE) + + .extern Fpushf + .extern fpdivzero + .extern fpoverflow + .extern fpunderflow + +! double Fdiv(double x, double y) returns x / y + +! pop 2 doubles from stack, divide first by second, and push quotient on stack + +! we denote upper and lower dwords of x and y (or their fractions) +! by (xu,xl), (yu,yl) + + .globl Fdivf + .align ALIGNMENT +Fdivf: + sub esp,#D_SIZE ! make space for dummy double on stack + push ebp + push edi ! save some regs + push esi + mov eax,FRAME_SIZE-PC_SIZE+D_SIZE[esp] ! move return address ... + mov FRAME_SIZE-PC_SIZE[esp],eax ! ... to usual spot + call Fpushf + pop esi ! yl + pop edi ! yu + mov eax,FRAME_SIZE+D_SIZE+D_LOW[esp] ! xl + mov edx,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! xu + jmp division + + .globl Fdiv + .align ALIGNMENT +Fdiv: + push ebp + push edi ! save some regs + push esi + mov eax,FRAME_SIZE+D_LOW[esp] ! xl + mov edx,FRAME_SIZE+D_HIGH[esp] ! xu + mov esi,FRAME_SIZE+D_SIZE+D_LOW[esp] ! yl + mov edi,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! yu + jmp division + + .align ALIGNMENT +exp_y_0: + mov ebx,edi + or ebx,esi + beq zerodivide + mov ebx,#1 +fix_y: + test edi,edi ! XXX - sloow + js y_unpacked + shld edi,esi,#1 + shl esi,#1 + dec bx + jmp fix_y + + .align ALIGNMENT +exp_x_0: + mov ecx,edx + or ecx,eax + beq retz + mov ecx,#1 ! change exponent from 0 to 1 +fix_x: + test edx,#1 << (REG_BIT-1-2) ! XXX - sloow + jnz x_unpacked + shld edx,eax,#1 + shl eax,#1 + dec cx + jmp fix_x + +! Fdivd pops double from stack, divides it by double at [ebx], +! and pushes quotient back on stack + + .globl Fdivd + .align ALIGNMENT +Fdivd: + sub esp,#D_SIZE ! make space for dummy double on stack + push ebp + push edi ! save some regs + push esi + mov eax,FRAME_SIZE-PC_SIZE+D_SIZE[esp] ! move return address ... + mov FRAME_SIZE-PC_SIZE[esp],eax ! ... to usual spot + mov eax,FRAME_SIZE+D_SIZE+D_LOW[esp] ! xl + mov edx,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! xu + mov esi,D_LOW[ebx] ! yl + mov edi,D_HIGH[ebx] ! yu + +division: + +! The full calculations are + +! (xu,xl,0) = yu * (zu,zl) + (0,r,0) (normal 96/32 -> 64 bit division) +! yl * zu = yu * q1 + r1 (32*32 -> 64 bit mul and 64/32 -> 32 bit div) + +! so + +! (xu,xl,0,0) = (yu,yl) * (zu,zl-q1) + (0,0,r-r1,yl*(q1-zl)) + +! where the calculations zl-q1, r-r1 and yl*(q1-zl) are more complicated +! than the notation suggests. They may be negative and the one with the +! multiplication may not fit in 32 bits and in both cases the overflow +! has to be moved into higher bit positions. + +! See Knuth for why (zu,zl-q1) is the correct 64-bit quotient to within +! 1 bit either way (assuming the normalization x < 2 * y). + +! We only need to calculate the remainder (0,0,r-r1,yl*(q1-zl)) to resolve +! tie cases. It tells whether the approximate quotient is too high or too +! low. + +#define NTEMPS 5 + + sub esp,#NTEMPS*GENREG_SIZE ! space to remember values for rounding of tie case + +! Offsets from esp for these values (offsets using FRAME_SIZE are invalid +! while these temps are active) +r = 0 +q1 = 4 +r1 = 8 +yl = 12 +zl = 16 + +! Step 1: unpack and normalize x to fraction in edx:eax (left shifted as +! far as possible less 2 so that x < y, and later z < y); unpack and normalize +! y to a fraction in edi:esi (left shifted as far as possible), put difference +! of signs (= sign of quotient) in ecx(D_SIGN_MASK) and difference of exponents +! (= exponent of quotient before normalization) in cx. + + mov ebp,edx ! xu + xor ebp,edi ! xu ^ yu + and ebp,#D_SIGN_MASK ! sign of result is difference of signs + +! Unpack y first to trap 0 / 0 + + mov ebx,edi ! remember yu for exponent of y + shld edi,esi,#D_BIT-D_FRAC_BIT ! extract fraction of y ... + shl esi,#D_BIT-D_FRAC_BIT + and ebx,#D_EXP_MASK ! exponent of y + jz exp_y_0 + shr ebx,#D_EXP_SHIFT ! in ebx (actually in bx, with high bits 0) + or edi,#D_NORM_MASK << (D_BIT-D_FRAC_BIT) ! normalize +y_unpacked: + +! Unpack x + + mov ecx,edx ! remember xu for exponent of x + shld edx,eax,#D_BIT-D_FRAC_BIT-2 ! extract fraction of x ... + shl eax,#D_BIT-D_FRAC_BIT-2 + and edx,#(D_NORM_MASK << (D_BIT-D_FRAC_BIT-2+1))-1 + ! XXX - above may be shifted 1 extra unnecessarily + and ecx,#D_EXP_MASK ! exponent of x + jz exp_x_0 + shr ecx,#D_EXP_SHIFT ! in ecx (actually in cx, with high bits 0) + or edx,#D_NORM_MASK << (D_BIT-D_FRAC_BIT-2) ! normalize +x_unpacked: + + sub cx,bx ! not ecx,ebx because we want to use high bit for sign + add cx,#D_EXP_BIAS ! adjust exponent of quotient + + or ecx,ebp ! include sign with exponent + +! Step 2: quotient of fractions -> (edx,eax) + +! 2a: (xu,xl,0) div yu = (zu,zl) -> (ebx,esi) + + div eax,edi ! (xu,xl) div yu = zu in eax; remainder (rem) in edx + mov ebx,eax ! save zu in ebx + sub eax,eax ! clear eax: (edx,eax) = (rem,0) + div eax,edi ! (rem,0) div yu = zl in eax + mov r[esp],edx + mov zl[esp],eax + xchg eax,esi ! store zl in esi; save yl in eax + mov yl[esp],eax + +! 2b: (yl * zu) div yu -> (0,eax) + + mul eax,ebx ! yl * zu -> (edx,eax) + div eax,edi ! (yl * zu) div yu in eax + mov q1[esp],eax + mov r1[esp],edx + +! 2c: (xu,xl) / (yu,yl) = (zu,zl) - (yl * zu) div yu -> (edx,eax) + + mov edx,ebx ! zu + xchg eax,esi ! eax <- zl; esi <- (yl * zu) div yu + sub eax,esi + sbb edx,#0 + +! Step 3: normalise quotient + + test edx,#1 << (REG_BIT-2) ! is fraction too small? (can only be by 1 bit) + jnz div4 + shld edx,eax,#1 ! yes; multiply fraction ... + shl eax,#1 ! ... by 2 ... + dec cx ! ... and decrement exponent + +! Step 4: shift and round + +div4: + mov ebx,eax ! save for rounding + shrd eax,edx,#D_BIT-D_FRAC_BIT-1 ! shift fraction of result ... + shr edx,#D_BIT-D_FRAC_BIT-1 ! ... to proper position + and ebx,#(1 << (D_BIT-D_FRAC_BIT-1))-1 ! look at bits shifted out + cmp ebx,#D_NORM_MASK >> (D_BIT-D_FRAC_BIT) ! compare with middle value + jb div5 ! below middle, don't round up + ja roundup ! above middle, round up + +! The low bits don't contain enough information to resolve the tie case, +! because the quotient itself is only an approximation. +! Calculate the exact remainder. +! This case is not very common, so don't worry much about speed. +! Unfortunately we had to save extra in all cases to prepare for it. + + push edx + push eax + + sub esi,esi ! the calculation requires 33 bits - carry to here + mov eax,2*GENREG_SIZE+q1[esp] + sub eax,2*GENREG_SIZE+zl[esp] + pushfd + mul dword EF_SIZE+2*GENREG_SIZE+yl[esp] + popfd + jnc foo + sub edx,2*GENREG_SIZE+yl[esp] + sbb esi,#0 +foo: + add edx,2*GENREG_SIZE+r[esp] + adc esi,#0 + sub edx,2*GENREG_SIZE+r1[esp] + sbb esi,#0 + mov ebx,eax + mov edi,edx + + pop eax + pop edx + +! Can finally decide rounding of tie case + + js div5 ! remainder < 0 from looking at top 64 bits + jnz roundup ! remainder > 0 from looking at top 64 bits + or edi,ebx ! test bottom 64 bits + jnz roundup ! remainder > 0 + + test al,#1 ! at last we know it is the tie case, check parity bit + jz div5 ! already even, otherwise round up to make even + +roundup: + add eax,#1 ! add rounding bit + adc edx,#0 + test edx,#D_NORM_MASK << 1 ! has fraction overflowed (very unlikely) + jz div5 +! Why were the shifts commented out? + shrd eax,edx,#1 ! yes, divide fraction ... + shr edx,#1 ! ... by 2 ... + inc cx ! ... and increment exponent + +! Step 5: put it all together + +div5: + mov ebx,ecx ! extract sign + and ebx,D_SIGN_MASK + cmp cx,#D_EXP_INFINITE ! is exponent too big? + jge overflow + test cx,cx + jle underflow + shl ecx,#D_EXP_SHIFT + + and edx,#D_FRAC_MASK ! remove norm bit + or edx,ecx ! include exponent ... + or edx,ebx ! ... and sign + +return: + add esp,#NTEMPS*GENREG_SIZE ! reclaim temp space + mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax ! "push" lower dword of product ... + mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx ! ... and upper dword + pop esi ! restore registers + pop edi + pop ebp + ret #D_SIZE + +retz: + sub edx,edx ! clear upper dword + sub eax,eax ! ... and lower dword + jmp return + +overflow: + mov edx,ecx ! put sign in usual reg + call fpoverflow + mov eax,ecx ! XXX - wrong reg + jmp return + +underflow: + mov esi,edx ! put upper part of fraction in usual reg + mov edx,ecx ! sign + movsx edi,cx ! put shift in usual reg + neg edi + inc edi + call fpunderflow + jmp return + +zerodivide: + mov edx,ebp ! sign + call fpdivzero + mov eax,ecx ! XXX - wrong reg + jmp return diff --git a/bin86-0.3/bccfp/fmul.x b/bin86-0.3/bccfp/fmul.x new file mode 100644 index 0000000..aa62b5c --- /dev/null +++ b/bin86-0.3/bccfp/fmul.x @@ -0,0 +1,150 @@ +! bcc 386 floating point routines (version 2) -- Fmul, Fmuld, Fmulf +! author: Bruce Evans + +#include "fplib.h" + +#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE) + + .extern Fpushf + .extern fpoverflow + .extern fpunderflow + .extern normalize2 + + .globl Fmul + .align ALIGNMENT +Fmul: + push ebp + push edi + push esi + mov eax,FRAME_SIZE+D_LOW[esp] + mov edx,FRAME_SIZE+D_HIGH[esp] + mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp] + mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp] + call multiplication + mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax + mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx + pop esi + pop edi + pop ebp + ret #D_SIZE + + .globl Fmuld + .align ALIGNMENT +Fmuld: + push ebp + push edi + push esi + mov eax,FRAME_SIZE+D_LOW[esp] + mov edx,FRAME_SIZE+D_HIGH[esp] + mov ecx,D_HIGH[ebx] + mov ebx,D_LOW[ebx] + call multiplication + mov FRAME_SIZE+D_LOW[esp],eax + mov FRAME_SIZE+D_HIGH[esp],edx + pop esi + pop edi + pop ebp + ret + + .globl Fmulf + .align ALIGNMENT +Fmulf: + push ebp + push edi + push esi + call Fpushf + pop ebx ! yl + pop ecx ! xu + mov eax,FRAME_SIZE+D_LOW[esp] ! xl + mov edx,FRAME_SIZE+D_HIGH[esp] ! xu + call multiplication + mov FRAME_SIZE+D_LOW[esp],eax + mov FRAME_SIZE+D_HIGH[esp],edx + pop esi + pop edi + pop ebp + ret + + .align ALIGNMENT +exp_x_0: + mov edx,#1 << D_EXP_SHIFT ! change exponent from 0 to 1 + jmp x_unpacked ! XXX - check for denormal? + + .align ALIGNMENT +exp_y_0: + mov ecx,#1 << D_EXP_SHIFT + jmp y_unpacked + + .align ALIGNMENT +multiplication: + mov ebp,edx ! xu + xor ebp,ecx ! xu ^ yu + and ebp,#D_SIGN_MASK ! sign of result is difference of signs + + mov esi,edx ! free edx for multiplications + and esi,#D_FRAC_MASK ! discard sign and exponent + and edx,#D_EXP_MASK ! exponent(x) + jz exp_x_0 + or esi,#D_NORM_MASK ! normalize +x_unpacked: + + mov edi,ecx ! this mainly for consistent naming + and edi,#D_FRAC_MASK + and ecx,#D_EXP_MASK ! exponent(y) + jz exp_y_0 + or edi,#D_NORM_MASK +y_unpacked: + + add ecx,edx ! add exponents + +! exponent is in ecx, sign in ebp, operands in esi:eax and edi:ebx, edx is free +! product to go in esi:eax:ebp:ebx +! terminology: x * y = (xu,xl) * (yu,yl) +! = (xu * yu,0,0) + (0,xu * yl + xl * yu,0) + (0,0,xl * yl) + + push ecx + push ebp + mov ecx,eax + mul ebx ! xl * yl + mov ebp,edx ! (xl * yl).u in ebp + xchg ebx,eax ! (xl * yl).l in ebx (final), yl in eax + mul esi ! xu * yl + push eax ! (xu * yl).l on stack + push edx ! (xu * yl).u on stack + mov eax,esi ! xu + mul edi ! xu * yu + mov esi,edx ! (xu * yu).u in esi (final except carries) + xchg ecx,eax ! (xu * yu).l in ecx, xl in eax + mul edi ! xl * yu + + add ebp,eax ! (xl * yl).u + (xl * yu).l + pop eax ! (xu * yl).u + adc eax,edx ! (xu * yl).u + (xl * yu).u + adc esi,#0 + pop edx ! (xu * yl).l + add ebp,edx ! ((xl * yl).u + (xl * yu).l) + (xu * yl).l + adc eax,ecx ! ((xu * yl).u + (xl * yu).u) + (xu * yu).l + adc esi,#0 + pop edx ! sign + pop edi ! exponent + sub edi,#(D_EXP_BIAS+1-(D_EXP_BIT+2)) << D_EXP_SHIFT ! adjust +! cmp edi,#(D_EXP_INFINITE-1+(D_EXP_BIT+2)) << D_EXP_SHIFT +! jae outofbounds ! 0 will be caught as underflow by normalize2 +cmp edi,#(2*D_EXP_INFINITE-(D_EXP_BIAS+1)+(D_EXP_BIT+2)) << D_EXP_SHIFT +ja underflow + br normalize2 + + .align ALIGNMENT +overflow: + mov edx,ebp ! put sign in usual reg + call fpoverflow + mov eax,ecx ! XXX - wrong reg + ret + + .align ALIGNMENT +underflow: + mov edx,ebp ! put sign in usual reg + neg edi + shr edi,#D_EXP_SHIFT + inc edi + br fpunderflow diff --git a/bin86-0.3/bccfp/fpbsr.x b/bin86-0.3/bccfp/fpbsr.x new file mode 100644 index 0000000..8ff38d7 --- /dev/null +++ b/bin86-0.3/bccfp/fpbsr.x @@ -0,0 +1,25 @@ +! bcc 386 floating point routines (version 2) -- bsr_table +! author: Bruce Evans + +#include "fplib.h" + + .globl bsr_table + .data + .align ALIGNMENT +bsr_table: ! table to replace bsr on range 0-255 +.byte -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 +.byte 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 +.byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +.byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 +.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 +.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 +.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 +.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 diff --git a/bin86-0.3/bccfp/fperr.c b/bin86-0.3/bccfp/fperr.c new file mode 100644 index 0000000..d5372dc --- /dev/null +++ b/bin86-0.3/bccfp/fperr.c @@ -0,0 +1,50 @@ +/* + * bin86/bccfp/fperr.c + * + * Copyright (C) 1992 Bruce Evans + */ + +#include <stdio.h> +#include <signal.h> + +#include "fperr.h" + +void fperr(errno) +int errno; +{ + +#if defined(DEBUG) || 0 + switch(errno) { + + case EFDENORMAL: + fputs("\nDenormal - ", stderr); + break; + + case EFINFINITY: + fputs("\nInfinity - ", stderr); + break; + + case EFNAN: + fputs("\nNaN - ", stderr); + break; + + case EFOVERFLOW: + fputs("\nOverflow - ", stderr); + break; + + case EFUNDERFLOW: + fputs("\nUnderflow - ", stderr); + break; + + case EFDIVZERO: + fputs("\nZero divide - ", stderr); + break; + + default: + fprintf(stderr, "\nUnknown error 0x%x - ", errno); + } + fflush(stderr); +#endif + + kill(getpid(), SIGFPE); +} diff --git a/bin86-0.3/bccfp/fperr.h b/bin86-0.3/bccfp/fperr.h new file mode 100644 index 0000000..42d54fd --- /dev/null +++ b/bin86-0.3/bccfp/fperr.h @@ -0,0 +1,14 @@ +/* + * bin86/bccfp/fperr.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* fperr.h */ + +#define EFDENORMAL 1 +#define EFINFINITY 2 +#define EFNAN 3 +#define EFOVERFLOW 4 +#define EFUNDERFLOW 5 +#define EFDIVZERO 6 diff --git a/bin86-0.3/bccfp/fperror.x b/bin86-0.3/bccfp/fperror.x new file mode 100644 index 0000000..04f3f74 --- /dev/null +++ b/bin86-0.3/bccfp/fperror.x @@ -0,0 +1,126 @@ +! bcc 386 floating point routines (version 2) +! --- fpdenormal, fperror, fpinfinity, fpNaN, fpoverflow, fpunderflow,fpdivzero +! author: Bruce Evans + +#include "fperr.h" +#include "fplib.h" + + .extern _fperr + +! Cause a denormal-operand exception +! Preserves all general registers if signal handler returns + + .globl fpdenormal + .align ALIGNMENT +fpdenormal: +#if 0 + push eax + mov eax,#EFDENORMAL + call fperror + pop eax +#endif + ret + +! Cause an exception with error code eax, preserving all genregs except eax + + .globl fperror + .align ALIGNMENT +fperror: + push ebp ! set up usual frame ... + mov ebp,esp ! ... for debugging + push edx ! save default + push ecx + push eax ! error code is arg to C routine + call _fperr + add esp,#GENREG_SIZE + pop ecx ! restore default + pop edx + pop ebp + ret + + .align ALIGNMENT +fphuge: + mov ecx,#D_HUGE_LOW ! prepare number +-HUGEVAL + or edx,#D_HUGE_HIGH ! ... in case signal handler returns + jmp fperror + +! Cause an infinite-operand exception +! Return +-HUGEVAL in edx:ecx with sign from edx + + .globl fpinfinity + .align ALIGNMENT +fpinfinity: + mov eax,#EFINFINITY + jmp fphuge ! almost right + +! Cause an NaN-operand exception +! Return +-HUGEVAL in edx:ecx with sign from edx + + .globl fpNaN + .align ALIGNMENT +fpNaN: + mov eax,#EFNAN ! there are different types of NaNs but... + jmp fphuge ! WRONG + +! Cause an overflow exception +! Return +-HUGEVAL in edx:ecx with sign from edx + + .globl fpoverflow + .align ALIGNMENT +fpoverflow: + mov eax,#EFOVERFLOW + jmp fphuge ! almost right + +! Cause an underflow exception (actually assume it is masked for now) +! Return denormal or 0.0 in edx:ecx +! XXX - this should cause a denormal exception or none for the denormal case +! Args: sign in edx, fraction in esi:eax, right shift in edi +! Returns: denormalized number in edx:eax + + .globl fpunderflow + .align ALIGNMENT +fpunderflow: +#if 0 + mov eax,#EFUNDERFLOW + jmp fperror +#endif + cmp edi,#REG_BIT + jb denormalize1 + mov eax,esi + sub esi,esi + sub edi,#REG_BIT + cmp edi,#REG_BIT + jb denormalize1 +denormalize_underflow: +#if 0 + mov eax,#EFUNDERFLOW + jmp fperror +#endif + sub eax,eax + mov edx,eax + ret + + .align ALIGNMENT +denormalize1: + mov ecx,edi + shrd eax,esi,cl + shr esi,cl + mov ecx,esi + or ecx,eax + jz denormalize_underflow + and edx,#D_SIGN_MASK + or edx,esi + ret + +! Cause an fp division by zero exception +! Return +-HUGEVAL in edx:ecx with sign from edx + + .globl fpdivzero + .align ALIGNMENT +fpdivzero: + mov eax,#EFDIVZERO + test edx,#D_EXP_MASK + jnz fphuge ! almost right + sub ecx,ecx + mov edx,ecx + jmp fperror diff --git a/bin86-0.3/bccfp/fplib.h b/bin86-0.3/bccfp/fplib.h new file mode 100644 index 0000000..b346c61 --- /dev/null +++ b/bin86-0.3/bccfp/fplib.h @@ -0,0 +1,49 @@ +/* + * bin86/bccfp/fplib.h + * + * Copyright (C) 1992 Bruce Evans + */ + +#define ALIGNMENT 4 +#define CHAR_BIT 8 +#define D_BIT (D_SIZE * CHAR_BIT) +#define D_EXP_BIAS ((1 << (D_EXP_BIT - 1)) - 1) +#define D_EXP_BIT 11 +#define D_EXP_INFINITE ((1 << D_EXP_BIT) - 1) +#define D_EXP_MASK (((1 << D_EXP_BIT) - 1) << D_EXP_SHIFT) +#define D_EXP_SHIFT (REG_BIT - (1 + D_EXP_BIT)) +#define D_FRAC_BIT 53 +#define D_FRAC_MASK (D_NORM_MASK - 1) +#define D_HIGH 4 +#define D_HUGE_HIGH (D_EXP_MASK - 1) +#define D_HUGE_LOW 0xFFFFFFFF +#define D_LOW 0 +#define D_NORM_BIT (D_FRAC_BIT - 1 - REG_BIT) +#define D_NORM_MASK (1 << D_NORM_BIT) +#define D_SIGN_BIT 63 +#define D_SIGN_MASK (1 << (D_SIGN_BIT - REG_BIT)) +#define D_SIZE 8 +#define F_BIT (F_SIZE * CHAR_BIT) +#define F_EXP_BIAS ((1 << (F_EXP_BIT - 1)) - 1) +#define F_EXP_BIT 8 +#define F_EXP_INFINITE ((1 << F_EXP_BIT) - 1) +#define F_EXP_MASK (((1 << F_EXP_BIT) - 1) << F_EXP_SHIFT) +#define F_EXP_SHIFT (REG_BIT - (1 + F_EXP_BIT)) +#define F_FRAC_BIT 24 +#define F_FRAC_MASK (F_NORM_MASK - 1) +#define F_HIGH 0 +#define F_HUGE_HIGH (F_EXP_MASK - 1) +#define F_NORM_BIT (F_FRAC_BIT - 1) +#define F_NORM_MASK (1 << F_NORM_BIT) +#define F_SIGN_BIT 31 +#define F_SIGN_MASK (1 << F_SIGN_BIT) +#define F_SIZE 4 +#define FREE_D_SIGN_BIT_TEST (D_SIGN_BIT % REG_BIT == REG_BIT - 1) +#define GENREG_SIZE 4 +#define INT_BIT 32 +#define INT_MAX 0x7FFFFFFF +#define INT_MIN (-0x7FFFFFFF - 1) +#define PC_SIZE 4 +#define REG_BIT 32 +#define SHORT_BIT 16 +#define UINT_MAX 0xFFFFFFFF diff --git a/bin86-0.3/bccfp/fptoi.x b/bin86-0.3/bccfp/fptoi.x new file mode 100644 index 0000000..30de729 --- /dev/null +++ b/bin86-0.3/bccfp/fptoi.x @@ -0,0 +1,117 @@ +! bcc 386 floating point routines (version 2) +! -- dtoi, dtol, dtoui, dtoul, ftoi, ftol (todo: ftoui, ftoul) +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + + .extern fpoverflow + .extern Fpushf + +! Convert double x at [ebx] to int and return in eax + + .globl dtoi + .globl dtol + .align ALIGNMENT +dtoi: +dtol: + mov eax,D_HIGH[ebx] + mov ecx,eax + and ecx,#D_EXP_MASK ! extract exponent + jz retz ! if 0 return 0 + test eax,#D_SIGN_MASK + jnz negative + call into_dtoui + cmp eax,#INT_MAX + ja overflow_int_max + ret + + .align ALIGNMENT +negative: + and eax,#~D_SIGN_MASK + call into_dtoui + cmp eax,#INT_MIN + ja overflow_int_min + neg eax + ret + + .align ALIGNMENT +overflow_int_max: + call fpoverflow + mov eax,#INT_MAX + ret + + .align ALIGNMENT +overflow_int_min: + js return ! actually INT_MIN is OK + call fpoverflow + mov eax,#INT_MIN +return: + ret + + .align ALIGNMENT +retz: + sub eax,eax ! clear return value + ret + +! Convert double x at [ebx] to unsigned and return in eax + + .globl dtoui + .globl dtoul + .align ALIGNMENT +dtoui: +dtoul: + mov eax,D_HIGH[ebx] + mov ecx,eax + and ecx,#D_EXP_MASK ! extract exponent + jz retz ! if 0 return 0 + test eax,#D_SIGN_MASK + jnz overflow_0 +into_dtoui: + mov edx,D_LOW[ebx] + + and eax,#D_FRAC_MASK ! extract fraction + or eax,#D_NORM_MASK ! restore normalization bit + + shr ecx,#D_EXP_SHIFT ! convert exponent to number + sub ecx,#D_EXP_BIAS+D_NORM_BIT ! adjust radix point + jl dtoui_rightshift ! should we shift left or right? + cmp ecx,#D_BIT-D_FRAC_BIT ! can shift left by at most this + ja overflow_uint_max ! if more, overflow + shld eax,edx,cl + ret + + .align ALIGNMENT +dtoui_rightshift: + neg ecx ! make shift count > 0 + cmp ecx,#REG_BIT ! big shifts would be taken mod REG_BIT ... + jae retz ! ... no good + shr eax,cl ! otherwise it is faster to do the shift ... + ret ! ... then to jump for the slightly smaller + ! ... shift counts that shift out all bits + + .align ALIGNMENT +overflow_0: + call fpoverflow + sub eax,eax + ret + + .align ALIGNMENT +overflow_uint_max: + call fpoverflow + mov eax,#UINT_MAX + ret + +! ftoi is like dtoi except ebx points to a float instead of a double. +! This is a quickly-written slowish version that does not take advantage +! of the float being smaller. + + .globl ftoi + .globl ftol + .align ALIGNMENT +ftoi: +ftol: + call Fpushf + mov ebx,esp + call dtoi + add esp,#D_SIZE + ret diff --git a/bin86-0.3/bccfp/fpulld.x b/bin86-0.3/bccfp/fpulld.x new file mode 100644 index 0000000..928a846 --- /dev/null +++ b/bin86-0.3/bccfp/fpulld.x @@ -0,0 +1,20 @@ +! bcc 386 floating point routines (version 2) -- Fpulld +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + +! Pop double from stack and store at address [ebx] + + .globl Fpulld + .align ALIGNMENT +Fpulld: + pop ecx + pop dword D_LOW[ebx] + pop dword D_HIGH[ebx] + jmp ecx ! return + +! This popping method is much slower on 486's because popping to memory +! takes 5+ while moving twice takes 2 and the return address doesn't +! have to be moved. However, popping is a little faster on a non-cached +! 386/20 with static column RAM although the memory access pattern is +! better for a double-width move than for popping. What about a cached 386? diff --git a/bin86-0.3/bccfp/fpullf.x b/bin86-0.3/bccfp/fpullf.x new file mode 100644 index 0000000..417ef92 --- /dev/null +++ b/bin86-0.3/bccfp/fpullf.x @@ -0,0 +1,101 @@ +! bcc 386 floating point routines (version 2) -- Fpullf +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + + .extern fpoverflow + .extern fpunderflow + +! pop double from stack, convert to float and store at address [ebx] + + .globl Fpullf + .align ALIGNMENT +Fpullf: + +! Step 1: load and shift left + + mov eax,PC_SIZE+D_LOW[esp] ! lower dword + mov edx,PC_SIZE+D_HIGH[esp] ! upper dword + mov ecx,edx ! copy upper dword into ecx ... + and ecx,#D_SIGN_MASK ! ... and extract sign + and edx,#D_EXP_MASK | D_FRAC_MASK ! extract exponent and fraction + sub edx,#(D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT ! adjust exponent bias + jz underflow + cmp edx,#F_EXP_INFINITE << D_EXP_SHIFT ! check if exponent lies in reduced range + jae outofbounds + shld edx,eax,#D_EXP_BIT-F_EXP_BIT ! shift exponent and fraction + +! Step 2: round + + test eax,#1 << (REG_BIT-1-(D_EXP_BIT-F_EXP_BIT)) ! test upper rounding bit + jz step3 ! below middle, don't round up + test eax,#(1 << (REG_BIT-1-(D_EXP_BIT-F_EXP_BIT)))-1 ! test other rounding bits + jnz roundup ! above middle, round up + test dl,#1 ! in middle, check parity bit + jz step3 ! already even, otherwise round up to make even + +roundup: + inc edx ! carry 1 + test edx,#F_FRAC_MASK ! is fraction now 0? (carry into F_EXPMASK) + jnz step3 ! no -- carry complete + cmp edx,#(F_EXP_INFINITE << F_EXP_SHIFT) & ~F_NORM_MASK ! yes (very unlikely): check for overflow + ! XXX - I think these tests say 0x7e7fffff overflows + jae overflow + +! Step 3: put it all together + +step3: + or edx,ecx ! include sign + mov F_HIGH[ebx],edx ! store the result in [ebx] + ret #D_SIZE ! return and release double from stack + + .align ALIGNMENT +outofbounds: + jns overflow ! have just compared exponent with the max +underflow: +! call fpunderflow ! XXX + push ecx ! save sign + mov ecx,edx + and ecx,#~D_FRAC_MASK ! assume fraction is below exp + cmp ecx,#-((D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT) ! was exp = 0? + jz exp_x_0 + shr ecx,#D_EXP_SHIFT + neg ecx + and edx,#D_FRAC_MASK + or edx,#D_NORM_MASK + shld edx,eax,#D_EXP_BIT-F_EXP_BIT-1 + shl eax,#D_EXP_BIT-F_EXP_BIT-1 + push ebx ! save to use for rounding + sub ebx,ebx + shrd ebx,eax,cl + shrd eax,edx,cl + shr edx,cl + cmp eax,#1 << (REG_BIT-1) + jb over_denorm_roundup + ja denorm_roundup + test dl,#1 + jz over_denorm_roundup +denorm_roundup: +#if F_NORM_BIT != F_EXP_SHIFT +#include "carry into norm bit doesn't go into low exp bit" +#endif + inc edx +over_denorm_roundup: + pop ebx + pop ecx + or edx,ecx + mov F_HIGH[ebx],edx + ret #D_SIZE + + .align ALIGNMENT +exp_x_0: ! XXX check for denormals - they underflow + pop ecx + mov dword F_HIGH[ebx],#0 + ret #D_SIZE + + .align ALIGNMENT +overflow: + mov edx,ebx ! put sign in usual reg + call fpoverflow + mov F_HIGH[ebx],dword #F_HUGE_HIGH ! XXX - should use infinity + ret #D_SIZE ! ... if fpoverflow does diff --git a/bin86-0.3/bccfp/fpushd.x b/bin86-0.3/bccfp/fpushd.x new file mode 100644 index 0000000..68caab0 --- /dev/null +++ b/bin86-0.3/bccfp/fpushd.x @@ -0,0 +1,60 @@ +! bcc 386 floating point routines (version 2) -- dtof, Fpushd, Fneg, Fnegd +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + + .extern Fpullf + +! dtof converts the double at [ebx] to a float and pushes the float onto +! the stack (D_SIZE bytes are allocated for the float although only the bottom +! F_SIZE are used). +! This is a quickly-written slowish version. + + .globl dtof + .align ALIGNMENT +dtof: + pop eax + sub esp,#D_SIZE ! build result here + push eax ! put back return address + call Fpushd + lea ebx,D_SIZE+PC_SIZE[esp] + call Fpullf + ret + +! Push double at address [ebx] onto stack + + .globl Fpushd + .align ALIGNMENT +Fpushd: + pop ecx + push dword D_HIGH[ebx] + push dword D_LOW[ebx] + jmp ecx ! return + +! Push double at address [ebx] onto stack, negating it on the way. + +! Don't worry about generating -0 because other routines have to allow for +! it anyway. + +! Perhaps this and Fneg should check for denormals and illegal operands +! (I think only signalling NaNs are illegal). +! fchs doesn't check, but fld does. +! Our Fpushd is not quite like fld because no conversions are involved. + + .globl Fnegd + .align ALIGNMENT +Fnegd: + pop ecx + mov eax,D_HIGH[ebx] + xor eax,#D_SIGN_MASK ! toggle sign + push eax + push dword D_LOW[ebx] + jmp ecx ! return + +! Negate double on stack + + .globl Fneg + .align ALIGNMENT +Fneg: + xorb PC_SIZE+D_SIZE-1[esp],D_SIGN_MASK >> (REG_BIT-CHAR_BIT) ! toggle sign + ret diff --git a/bin86-0.3/bccfp/fpushf.x b/bin86-0.3/bccfp/fpushf.x new file mode 100644 index 0000000..7cb2f8d --- /dev/null +++ b/bin86-0.3/bccfp/fpushf.x @@ -0,0 +1,74 @@ +! bcc 386 floating point routines (version 2) -- Fpushf, Fnegf +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + + .extern fpdenormal + +! Load float at [ebx], convert to double and push on stack + + .globl Fpushf + .align ALIGNMENT +Fpushf: + mov edx,F_HIGH[ebx] +into_Fpushf: + test edx,#F_EXP_MASK ! is exponent 0? + jz exp_x_0 + + mov ecx,edx ! extract sign + and ecx,#F_SIGN_MASK + + and edx,#F_EXP_MASK | F_FRAC_MASK ! extract exponent and fraction + sub eax,eax ! clear lower dword + shrd eax,edx,#D_EXP_BIT-F_EXP_BIT ! shift exponent and fraction to new position + shr edx,#D_EXP_BIT-F_EXP_BIT + + add edx,#(D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT ! adjust exponent bias + or edx,ecx ! include sign + + pop ecx + push edx ! upper dword + push eax ! lower dword + jmp ecx ! return + + .align ALIGNMENT +exp_x_0: + mov eax,edx + and eax,#F_FRAC_MASK + jnz x_denorm + pop ecx + push eax ! upper dword = 0 + push eax ! lower dword = 0 + jmp ecx ! return + + .align ALIGNMENT +x_denorm: + call fpdenormal + bsr ecx,eax ! zzzz + neg ecx + add ecx,#F_NORM_BIT + shl eax,cl + and eax,#F_FRAC_MASK + neg ecx + add ecx,#D_EXP_BIAS-F_EXP_BIAS+1 + shl ecx,#D_EXP_SHIFT + and edx,#F_SIGN_MASK ! assumed same as D_SIGN_MASK + or edx,ecx + sub ecx,ecx + shrd ecx,eax,#D_EXP_BIT-F_EXP_BIT + shr eax,#D_EXP_BIT-F_EXP_BIT + or edx,eax + + pop eax + push edx ! upper dword + push ecx ! lower dword + jmp eax ! return + +! Fnegf: as Fpushf, but negate double before pushing onto stack + + .globl Fnegf + .align ALIGNMENT +Fnegf: + mov edx,F_HIGH[ebx] + xor edx,#F_SIGN_MASK ! toggle sign + jmp into_Fpushf ! join Fpushf diff --git a/bin86-0.3/bccfp/fpushi.x b/bin86-0.3/bccfp/fpushi.x new file mode 100644 index 0000000..b19aae2 --- /dev/null +++ b/bin86-0.3/bccfp/fpushi.x @@ -0,0 +1,126 @@ +! bcc 386 floating point routines (version 2) +! -- Fpushi, Fpushl, Fpushs, Fpushc, Fpushuc, Fpushui, Fpushul, Fpushus +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + +! Convert the short in ax to double and push on stack + + .globl Fpushs + .align ALIGNMENT +Fpushs: + cwde + add eax,#0 ! fast 3-byte instruction to align + +! Convert the int or long in eax to double and push on stack + + .globl Fpushi + .globl Fpushl +! .align ALIGNMENT ! don't do this until it pads with nop's +Fpushi: +Fpushl: + test eax,eax + jz return_eax ! got 0 in eax + mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent + jns normalize ! sign and fraction bits already set up + mov ebx,#D_SIGN_MASK | ((D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT) ! adjust sign + neg eax ! adjust fraction + jmp normalize + + .align ALIGNMENT +ret1: + mov eax,#D_EXP_BIAS << D_EXP_SHIFT + add eax,#0 ! fast 3-byte instruction to align + +! .align ALIGNMENT ! don't do this until it pads with nop's +return_eax: + pop ecx + push eax ! upper dword + push dword #0 ! lower dword = 0 + jmp ecx ! return + +! Convert the (unsigned) char in al to double and push on stack + + .globl Fpushc + .globl Fpushuc + .align ALIGNMENT +Fpushc: +Fpushuc: + and eax,#(1 << CHAR_BIT)-1 + add eax,#0 ! fast 3-byte instruction to align + +! Convert the unsigned short in ax to double and push on stack + + .globl Fpushus +! .align ALIGNMENT ! don't do this until it pads with nop's +Fpushus: + and eax,#(1 << SHORT_BIT)-1 + add eax,#0 ! fast 3-byte instruction to align + +! Convert the unsigned int or long in eax to double and push on stack + + .globl Fpushui + .globl Fpushul +! .align ALIGNMENT ! don't do this until it pads with nop's +Fpushui: +Fpushul: + cmp eax,#1 ! this tests for both 0 and 1 + jb return_eax ! got 0 in eax + jz ret1 + mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent + +! .align ALIGNMENT ! don't do this until it pads with nop's +normalize: + sub edx,edx ! clear lower dword of result + +! Find first nonzero bit +! Don't use bsr, it is slow (const + 3n on 386, const + n on 486) + + sub ecx,ecx ! prepare unsigned extension of cl + test eax,#~D_FRAC_MASK + jnz large + test eax,#0xFF << (D_NORM_BIT-8) + jnz middle + shl eax,#8 + sub ebx,#8 << D_EXP_SHIFT + test eax,#0xFF << (D_NORM_BIT-8) + jnz middle + shl eax,#8 + sub ebx,#8 << D_EXP_SHIFT +middle: + shld ecx,eax,#D_NORM_BIT + mov cl,bsr_table[ecx] + add ecx,#REG_BIT-D_NORM_BIT-D_NORM_BIT + neg ecx + shl eax,cl + shl ecx,#D_EXP_SHIFT + sub ebx,ecx +return: + and eax,#D_FRAC_MASK ! remove normalization bit + or eax,ebx ! include exponent (and sign) to fraction + pop ecx + push eax ! upper dword + push edx ! lower dword + jmp ecx ! return + + .align ALIGNMENT +large: + shld ecx,eax,#REG_BIT-(D_NORM_BIT+8) + jnz huge + shld ecx,eax,#REG_BIT-D_NORM_BIT + mov cl,bsr_table[ecx] +got_shift_right: + shrd edx,eax,cl + shr eax,cl + shl ecx,#D_EXP_SHIFT + add ebx,ecx + jmp return + + .align ALIGNMENT +huge: + mov cl,bsr_table[ecx] + add cl,#8 + jmp got_shift_right + + .data + .extern bsr_table diff --git a/bin86-0.3/bccfp/frexp.x b/bin86-0.3/bccfp/frexp.x new file mode 100644 index 0000000..318fc34 --- /dev/null +++ b/bin86-0.3/bccfp/frexp.x @@ -0,0 +1,66 @@ +! bcc 386 floating point routines (version 2) -- _frexp +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + + .extern fpdenormal + +! void frexp(double value, int *exponent); +! splits a double into exponent and fraction (where 0.5 <= fraction < 1.0) + + .globl _frexp + .align ALIGNMENT +_frexp: +push ebx +#undef PC_SIZE +#define PC_SIZE 8 + mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x + mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x + mov edx,PC_SIZE+D_SIZE[esp] ! exponent pointer + mov ecx,ebx ! extract exponent here + and ecx,#D_EXP_MASK + jz exp_x_0 + + shr ecx,#D_EXP_SHIFT ! exponent + bias +got_x: + sub ecx,#D_EXP_BIAS-1 ! D_EXP_BIAS is for 1.x form, we want 0.1x form + mov [edx],ecx ! return exponent + and ebx,#D_SIGN_MASK | D_FRAC_MASK ! extract sign and fraction + or ebx,#(D_EXP_BIAS-1) << D_EXP_SHIFT ! set new exponent for 0.1x +mov edx,ebx +pop ebx + ret + + .align ALIGNMENT +exp_x_0: + test ebx,#D_FRAC_MASK + jnz xu_denorm + test eax,eax + jnz xl_denorm + mov [edx],ecx ! return zero exponent + mov ebx,ecx ! guard against -0 (may not be necessary) +mov edx,ebx +pop ebx + ret + + .align ALIGNMENT +xl_denorm: + call fpdenormal + bsr ecx,eax ! zzzz + neg ecx + add ecx,#REG_BIT-1 + shl eax,cl + shld ebx,eax,#D_NORM_BIT+1 + shl eax,#D_NORM_BIT+1 + sub ecx,#D_NORM_BIT+1 + jmp got_x + + .align ALIGNMENT +xu_denorm: + call fpdenormal + bsr ecx,ebx + neg ecx + add ecx,#D_NORM_BIT + shld ebx,eax,cl + shl eax,cl + jmp got_x diff --git a/bin86-0.3/bccfp/ftst.x b/bin86-0.3/bccfp/ftst.x new file mode 100644 index 0000000..2a92ef1 --- /dev/null +++ b/bin86-0.3/bccfp/ftst.x @@ -0,0 +1,28 @@ +! bcc 386 floating point routines (version 2) -- Ftst, Ftstd, Ftstf +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + +#if 0 /* bcc doesn't generate Ftst (but it might in future) */ + .globl Ftst +#endif + .align ALIGNMENT +Ftst: + cmp dword PC_SIZE+D_HIGH[esp],#0 ! need only test upper dword of x + ret #D_SIZE + +! Compare double at address [ebx] with 0 + + .globl Ftstd + .align ALIGNMENT +Ftstd: + cmp dword D_HIGH[ebx],#0 ! need only test upper dword of x + ret + +! Compare float at address [ebx] with 0 + + .globl Ftstf + .align ALIGNMENT +Ftstf: + cmp dword F_HIGH[ebx],#0 + ret diff --git a/bin86-0.3/bccfp/ldexp.x b/bin86-0.3/bccfp/ldexp.x new file mode 100644 index 0000000..bc9dd03 --- /dev/null +++ b/bin86-0.3/bccfp/ldexp.x @@ -0,0 +1,74 @@ +! bcc 386 floating point routines (version 2) -- _ldexp +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + + .extern fpoverflow + .extern fpunderflow + +! void ldexp(double value, int exponent); +! returns value * (2 ** exponent) + + .globl _ldexp + .align ALIGNMENT +_ldexp: +push ebx +#undef PC_SIZE +#define PC_SIZE 8 + mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x + mov ecx,PC_SIZE+D_SIZE[esp] ! exponent arg + mov eax,ebx ! extract exponent (of x) here + and eax,#D_EXP_MASK +! jz exp_y_0 ! may need check for preposterous exponent arg too + + shr eax,#D_EXP_SHIFT ! shift to low bits just for testing + jz underflow ! denormal? + add eax,ecx ! test-add the exponents + jz underflow ! XXX probably need to fiddle norm bit + cmp eax,#D_EXP_INFINITE ! check if still within range + jae outofbounds ! the unsigned compare catches all overflow cases + ! because the exponent of x is non-negative + + shl ecx,#D_EXP_SHIFT ! shift exponent arg bits into final position ... + add ebx,ecx ! ... safe to add it to exponent of x now + mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x +mov edx,ebx +pop ebx + ret + + + .align ALIGNMENT +outofbounds: + test ecx,ecx ! overflow or underflow? + jns overflow +underflow: + mov edx,ebx ! put sign in usual reg + push edi + push esi + mov edi,eax ! put exponent in usual reg + mov eax,2*GENREG_SIZE+PC_SIZE+D_LOW[esp] + ! put lower dword of x in usual reg + mov esi,ebx ! put upper dword of x in usual reg + and esi,#D_EXP_MASK | D_FRAC_MASK + test esi,#D_EXP_MASK + jz foo + and esi,#D_FRAC_MASK + or esi,#D_NORM_MASK +foo: + neg edi +! inc edi ! XXX ? + call fpunderflow + pop esi + pop edi + mov ebx,edx ! XXX = wrong reg +pop ebx + ret + + .align ALIGNMENT +overflow: + mov edx,ebx ! put sign in usual reg + call fpoverflow + mov eax,ecx ! XXX = wrong reg + mov ebx,edx ! XXX = wrong reg +pop ebx + ret diff --git a/bin86-0.3/bccfp/modf.c b/bin86-0.3/bccfp/modf.c new file mode 100644 index 0000000..a83f801 --- /dev/null +++ b/bin86-0.3/bccfp/modf.c @@ -0,0 +1,20 @@ +/* + * bin86/bccfp/modf.c + * + * Copyright (C) 1992 Bruce Evans + */ + +#include <math.h> + +/* Slooow version. */ + +double modf(x, pint) +double x; +double *pint; +{ + if (x >= 0) + *pint = floor(x); + else + *pint = ceil(x); + return x - *pint; +} diff --git a/bin86-0.3/bccfp/test.c b/bin86-0.3/bccfp/test.c new file mode 100644 index 0000000..05b5d84 --- /dev/null +++ b/bin86-0.3/bccfp/test.c @@ -0,0 +1,124 @@ +/* + * bin86/bccfp/test.c + * + * Copyright (C) 1992 Bruce Evans + */ + +#include <sys/times.h> +#include <limits.h> +#include <stdio.h> +#include <time.h> + +#define CONVTYPE int +#define MAX (MIN + NITER - 1) +#define MIN INT_MIN + +#define NITER 100000 + +double one = 1; +double two = 2; +double big = 1e99; + +double d; +double d1; +float f; + +int main() +{ + CONVTYPE cti; + CONVTYPE cto; + clock_t delta; + struct tms finish; + int i; + struct tms start; + +#if 0 + times(&start); + for (cti = MIN; cti <= MAX; ++cti) + { + d = cti; + cto = d; + if (cti != cto) + printf("%08x %08x\n", cti, cto); + if (cti % 10000000 == 0) + { + printf("%8x ok ", cti); + fflush(stdout); + } + } + times(&finish); + delta = finish.tms_utime - start.tms_utime; + printf("Time for %d i -> d and d -> i conversions was %g s (%d t)\n", + MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta); +#endif + + times(&start); + for (cti = MIN; cti <= MAX; ++cti) + d = cti; + times(&finish); + delta = finish.tms_utime - start.tms_utime; + printf("Time for %d i -> d conversions was %g s (%d t)\n", + MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta); + + times(&start); + for (cti = MIN; cti <= MAX; ++cti) + { + d = cti; + cto = d; + } + times(&finish); + delta = finish.tms_utime - start.tms_utime - delta; + printf("Time for %d d -> i conversions was %g s (%d t)\n", + MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta); + + d = 0; + times(&start); + for (i = 0; i < NITER; ++i) + d = d + 1; + times(&finish); + delta = finish.tms_utime - start.tms_utime; + printf("Time for adding %d 1.0's to 0.0 was %g s (%d t), result = %g\n", + NITER, delta / (double) CLOCKS_PER_SEC, delta, d); + + d = 0; + times(&start); + for (; d < NITER;) + d = d + 1; + times(&finish); + delta = finish.tms_utime - start.tms_utime; + printf("Time for adding %d 1.0's to 0.0 (d index) was %g s (%d t), result = %g\n", + NITER, delta / (double) CLOCKS_PER_SEC, delta, d); + + times(&start); + for (i = 1; i <= NITER; ++i) + { + d1 = i; + d = d1 * d1; + } + times(&finish); + delta = finish.tms_utime - start.tms_utime; + printf("Time for %d mults was %g s (%d t), result = %g\n", + NITER, delta / (double) CLOCKS_PER_SEC, delta, d); + + times(&start); + for (i = 1; i <= NITER; ++i) + { + d1 = i; + d = 1 / d1; + } + times(&finish); + delta = finish.tms_utime - start.tms_utime; + printf("Time for %d divs was %g s (%d t), result = %g\n", + NITER, delta / (double) CLOCKS_PER_SEC, delta, d); + + f = 0; + times(&start); + for (i = 0; i < NITER; ++i) + f = f + 1; + times(&finish); + delta = finish.tms_utime - start.tms_utime; + printf("Time for adding %d 1.0f's to 0.0f was %g s (%d t), result = %g\n", + NITER, delta / (double) CLOCKS_PER_SEC, delta, f); + + return 0; +} diff --git a/bin86-0.3/ld/6809/config.h b/bin86-0.3/ld/6809/config.h new file mode 100644 index 0000000..b2203ab --- /dev/null +++ b/bin86-0.3/ld/6809/config.h @@ -0,0 +1,34 @@ +/* + * bin86/ld/6809/config.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* config.h - configuration for linker */ + +/* one of these target processors must be defined */ + +#undef I8086 /* Intel 8086 */ +#undef I80386 /* Intel 80386 */ +#define MC6809 /* Motorola 6809 */ + +/* one of these target operating systems must be defined */ + +#define EDOS /* generate EDOS executable */ +#undef MINIX /* generate Minix executable */ + +/* these may need to be defined to suit the source processor */ + +#undef S_ALIGNMENT 4 /* source memory alignment, power of 2 */ + /* don't use for 8 bit processors */ + /* don't use even for 80386 - overhead for */ + /* alignment cancels improved access */ + +/* these should be defined if they are supported by the source compiler */ + +#undef PROTO /* compiler handles prototypes */ + +/* these must be defined to suit the source libraries */ + +#define CREAT_PERMS 0666 /* permissions for creat() */ +#define EXEC_PERMS 0111 /* extra permissions to set for executable */ diff --git a/bin86-0.3/ld/Makefile b/bin86-0.3/ld/Makefile new file mode 100644 index 0000000..a7da6d7 --- /dev/null +++ b/bin86-0.3/ld/Makefile @@ -0,0 +1,29 @@ +CC =gcc +CFLAGS =-O1 -fomit-frame-pointer +INC_CFLAGS =-DBSD_A_OUT -I../a.out.h -D__linux__ +LDFLAGS =-s + +OBJS =dumps.o io.o ld.o readobj.o table.o typeconv.o \ + writebin.o + +.SUFFIXES: +.SUFFIXES: .c .o + +.c.o: + $(CC) $(CFLAGS) $(INC_CFLAGS) -c $< + +all: ld86 + +ld86: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +clean: + $(RM) $(OBJS) ld86 core + +dumps.o: dumps.c const.h config.h obj.h type.h globvar.h +io.o: io.c const.h config.h type.h globvar.h +ld.o: ld.c const.h config.h type.h byteord.h globvar.h +readobj.o: readobj.c const.h config.h byteord.h obj.h type.h globvar.h +table.o: table.c const.h config.h align.h obj.h type.h globvar.h +typeconv.o: typeconv.c const.h config.h type.h globvar.h +writebin.o: writebin.c const.h config.h obj.h type.h globvar.h diff --git a/bin86-0.3/ld/align.h b/bin86-0.3/ld/align.h new file mode 100644 index 0000000..f34652c --- /dev/null +++ b/bin86-0.3/ld/align.h @@ -0,0 +1,14 @@ +/* + * bin86/ld/align.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* align.h - memory alignment requirements for linker */ + +#ifndef S_ALIGNMENT +# define align(x) +#else +# define align(x) ((x) = (void *)(((int) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))) + /* assumes sizeof(int) == sizeof(char *) */ +#endif diff --git a/bin86-0.3/ld/ar.h b/bin86-0.3/ld/ar.h new file mode 100644 index 0000000..780d457 --- /dev/null +++ b/bin86-0.3/ld/ar.h @@ -0,0 +1,24 @@ +/* + * bin86/ld/ar.h + * + * Copyright (C) 1992 Bruce Evans + */ + +#ifndef _AR_H +#define _AR_H + +#define ARMAG "!<arch>\n" +#define SARMAG 8 +#define ARFMAG "`\n" + +struct ar_hdr { + char ar_name[16]; + char ar_date[12]; + char ar_uid[6]; + char ar_gid[6]; + char ar_mode[8]; + char ar_size[10]; + char ar_fmag[2]; +}; + +#endif /* _AR_H */ diff --git a/bin86-0.3/ld/bugs b/bin86-0.3/ld/bugs new file mode 100644 index 0000000..b671f30 --- /dev/null +++ b/bin86-0.3/ld/bugs @@ -0,0 +1,17 @@ +1. Should cause error when an address which requires > 16 bits is referenced + using 16 bits. + +TODO: + integrate byteord.h with compiler as well as assembler + +TODO: + integrate align.h with compiler and assembler + use alignment for *86 like compiler - use more portable macro + ((x) + (-(int) (x) & MASK)) when it is either necessary or + faster + +TODO: + do malloc stuff better, as in compiler + +2. Error message about "foo.a is not an object file" is confusing - should + name archive member. diff --git a/bin86-0.3/ld/byteord.h b/bin86-0.3/ld/byteord.h new file mode 100644 index 0000000..0e2b403 --- /dev/null +++ b/bin86-0.3/ld/byteord.h @@ -0,0 +1,24 @@ +/* + * bin86/ld/byteord.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* byteord.h - byte order dependencies for C compiler, assembler, linker */ + +/* These are for the targets of everything and for linker source too. */ + +#ifdef I8086 +# define BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ +#endif + +#ifdef I80386 +# define BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 +#endif + +#ifdef MC6809 +# define BIG_ENDIAN 1 /* byte order in words is high-low */ +# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ +#endif diff --git a/bin86-0.3/ld/config.h b/bin86-0.3/ld/config.h new file mode 100644 index 0000000..173d1c4 --- /dev/null +++ b/bin86-0.3/ld/config.h @@ -0,0 +1,34 @@ +/* + * bin86/ld/config.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* config.h - configuration for linker */ + +/* one of these target processors must be defined */ + +#undef I8086 /* Intel 8086 */ +#define I80386 /* Intel 80386 */ +#undef MC6809 /* Motorola 6809 */ + +/* one of these target operating systems must be defined */ + +#undef EDOS /* generate EDOS executable */ +#define MINIX /* generate Minix executable */ + +/* these may need to be defined to suit the source processor */ + +#define S_ALIGNMENT 4 /* source memory alignment, power of 2 */ + /* don't use for 8 bit processors */ + /* don't use even for 80386 - overhead for */ + /* alignment cancels improved access */ + +/* these should be defined if they are supported by the source compiler */ + +#define PROTO /* compiler handles prototypes */ + +/* these must be defined to suit the source libraries */ + +#define CREAT_PERMS 0666 /* permissions for creat() */ +#define EXEC_PERMS 0111 /* extra permissions to set for executable */ diff --git a/bin86-0.3/ld/const.h b/bin86-0.3/ld/const.h new file mode 100644 index 0000000..a933bdc --- /dev/null +++ b/bin86-0.3/ld/const.h @@ -0,0 +1,20 @@ +/* + * bin86/ld/const.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* const.h - constants for linker */ + +#define FALSE 0 +#ifndef NULL +#define NULL 0 +#endif +#define TRUE 1 + +#define EXTERN extern +#define FORWARD static +#define PRIVATE static +#define PUBLIC + +#include "config.h" diff --git a/bin86-0.3/ld/dumps.c b/bin86-0.3/ld/dumps.c new file mode 100644 index 0000000..c91653f --- /dev/null +++ b/bin86-0.3/ld/dumps.c @@ -0,0 +1,72 @@ +/* + * bin86/ld/dumps.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* dumps.c - print data about symbols and modules for linker */ + +#include "const.h" +#include "obj.h" +#include "type.h" +#include "globvar.h" + +/* print list of modules and whether they are loaded */ + +PUBLIC void dumpmods() +{ + struct modstruct *modptr; + + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + { + putstr(modptr->loadflag ? "L " : " "); + putbstr(20, modptr->modname); + putbyte('\n'); + } +} + +/* print data about symbols (in loaded modules only) */ + +PUBLIC void dumpsyms() +{ + flags_t flags; + struct modstruct *modptr; + struct symstruct **symparray; + struct symstruct *symptr; + char uflag; + + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr) + { + uflag = FALSE; + if (((flags = symptr->flags) & (C_MASK | I_MASK)) == I_MASK) + uflag = TRUE; + putbstr(20, uflag ? "" : modptr->modname); + putstr(" "); + putbstr(20, symptr->name); + putstr(" "); + putbyte(hexdigit[flags & SEGM_MASK]); + putstr(" "); + if (uflag) + putstr(" "); + else +#ifdef LONG_OFFSETS + put08lx(symptr->value); +#else + put08x(symptr->value); +#endif + putstr(flags & A_MASK ? " A" : " R"); + if (uflag) + putstr(" U"); + if (flags & C_MASK) + putstr(" C"); + if (flags & N_MASK) + putstr(" N"); + putbyte('\n'); + } + } +} diff --git a/bin86-0.3/ld/globvar.h b/bin86-0.3/ld/globvar.h new file mode 100644 index 0000000..0c382c7 --- /dev/null +++ b/bin86-0.3/ld/globvar.h @@ -0,0 +1,18 @@ +/* + * bin86/ld/globvar.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* globvar.h - global variables for linker */ + +#ifdef EXTERN +EXTERN char hexdigit[]; +#else +#define EXTERN +PUBLIC char hexdigit[] = "0123456789abcdef"; +#endif +EXTERN unsigned errcount; /* count of errors */ +EXTERN struct entrylist *entryfirst; /* first on list of entry symbols */ +EXTERN struct modstruct *modfirst; /* data for 1st module */ +EXTERN struct redlist *redfirst; /* first on list of redefined symbols */ diff --git a/bin86-0.3/ld/io.c b/bin86-0.3/ld/io.c new file mode 100644 index 0000000..999dbd3 --- /dev/null +++ b/bin86-0.3/ld/io.c @@ -0,0 +1,583 @@ +/* + * bin86/ld/io.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* io.c - input/output and error modules for linker */ + +#include <sys/types.h> +#include <sys/stat.h> +#ifndef __linux__ +#define MY_STAT_H +#endif +#include <fcntl.h> +#include <unistd.h> +#include "const.h" +#include "obj.h" /* needed for LONG_OFFSETS and offset_t */ +#include "type.h" +#include "globvar.h" + +#define DRELBUFSIZE 2048 +#define ERR (-1) +#define ERRBUFSIZE 1024 +#define INBUFSIZE 1024 +#define OUTBUFSIZE 2048 +#define TRELBUFSIZE 1024 + +#ifdef BSD_A_OUT +PRIVATE char *drelbuf; /* extra output buffer for data relocations */ +PRIVATE char *drelbufptr; /* data relocation output buffer ptr */ +PRIVATE char *drelbuftop; /* data relocation output buffer top */ +#endif +PRIVATE char *errbuf; /* error buffer (actually uses STDOUT) */ +PRIVATE char *errbufptr; /* error buffer ptr */ +PRIVATE char *errbuftop; /* error buffer top */ +PRIVATE char *inbuf; /* input buffer */ +PRIVATE char *inbufend; /* input buffer top */ +PRIVATE char *inbufptr; /* end of input in input buffer */ +PRIVATE int infd; /* input file descriptor */ +PRIVATE char *inputname; /* name of current input file */ +PRIVATE char *outbuf; /* output buffer */ +PRIVATE char *outbufptr; /* output buffer ptr */ +PRIVATE char *outbuftop; /* output buffer top */ +PRIVATE int outfd; /* output file descriptor */ +PRIVATE unsigned outputperms; /* permissions of output file */ +PRIVATE char *outputname; /* name of output file */ +PRIVATE char *refname; /* name of program for error reference */ +#ifdef BSD_A_OUT +PRIVATE char *trelbuf; /* extra output buffer for text relocations */ +PRIVATE char *trelbufptr; /* text relocation output buffer ptr */ +PRIVATE char *trelbuftop; /* text relocation output buffer top */ +PRIVATE int trelfd; /* text relocation output file descriptor */ +#endif +PRIVATE unsigned warncount; /* count of warnings */ + +FORWARD void errexit P((char *message)); +FORWARD void flushout P((void)); +#ifdef BSD_A_OUT +FORWARD void flushtrel P((void)); +#endif +FORWARD void outhexdigs P((offset_t num)); +FORWARD void outputerror P((char *message)); +FORWARD void put04x P((unsigned num)); +FORWARD void putstrn P((char *message)); +FORWARD void refer P((void)); + +PUBLIC void ioinit(progname) +char *progname; +{ + infd = ERR; + if (*progname) + refname = progname; /* name must be static (is argv[0]) */ + else + refname = "link"; +#ifdef BSD_A_OUT + drelbuf = malloc(DRELBUFSIZE); + drelbuftop = drelbuf + DRELBUFSIZE; +#endif + errbuf = malloc(ERRBUFSIZE); + errbufptr = errbuf; + errbuftop = errbuf + ERRBUFSIZE; + inbuf = malloc(INBUFSIZE); + outbuf = malloc(OUTBUFSIZE);/* outbuf invalid if this fails but then */ + /* will not be used - tableinit() aborts */ + outbuftop = outbuf + OUTBUFSIZE; +#ifdef BSD_A_OUT + trelbuf = malloc(TRELBUFSIZE); + trelbuftop = trelbuf + TRELBUFSIZE; +#endif +} + +PUBLIC void closein() +{ + if (infd != ERR && close(infd) < 0) + inputerror("cannot close"); + infd = ERR; +} + +PUBLIC void closeout() +{ +#ifdef BSD_A_OUT + unsigned nbytes; +#endif + + flushout(); +#ifdef BSD_A_OUT + flushtrel(); + nbytes = drelbufptr - drelbuf; + if (write(trelfd, drelbuf, nbytes) != nbytes) + outputerror("cannot write"); +#endif + if (close(outfd) == ERR) + outputerror("cannot close"); +#ifdef BSD_A_OUT + if (close(trelfd) == ERR) + outputerror("cannot close"); +#endif +} + +PUBLIC void errtrace(name, level) +char *name; +{ + while (level-- > 0) + putbyte(' '); + putstrn(name); +} + +PUBLIC void executable() +{ + int oldmask; + + if (errcount == 0) + { + oldmask = umask(0); + umask(oldmask); + chmod(outputname, outputperms | (EXEC_PERMS & ~oldmask)); + } +} + +PUBLIC void flusherr() +{ + write(STDOUT_FILENO, errbuf, errbufptr - errbuf); + errbufptr = errbuf; +} + +PRIVATE void flushout() +{ + unsigned nbytes; + + nbytes = outbufptr - outbuf; + if (write(outfd, outbuf, nbytes) != nbytes) + outputerror("cannot write"); + outbufptr = outbuf; +} + +#ifdef BSD_A_OUT +PRIVATE void flushtrel() +{ + unsigned nbytes; + + nbytes = trelbufptr - trelbuf; + if (write(trelfd, trelbuf, nbytes) != nbytes) + outputerror("cannot write"); + trelbufptr = trelbuf; +} +#endif + +PUBLIC void openin(filename) +char *filename; +{ +#if 0 /* XXX - this probably won't work with constructed lib names? */ + if (infd == ERR || strcmp(inputname, filename) != 0) +#endif + { + closein(); + inputname = filename; /* this relies on filename being static */ + if ((infd = open(filename, O_RDONLY)) < 0) + inputerror("cannot open"); + inbufptr = inbufend = inbuf; + } +} + +PUBLIC void openout(filename) +char *filename; +{ + struct stat statbuf; + + outputname = filename; + if ((outfd = creat(filename, CREAT_PERMS)) == ERR) + outputerror("cannot open"); + if (fstat(outfd, &statbuf) != 0) + outputerror("cannot stat"); + outputperms = statbuf.st_mode; + chmod(filename, outputperms & ~EXEC_PERMS); +#ifdef BSD_A_OUT + drelbufptr = drelbuf; +#endif + outbufptr = outbuf; +#ifdef BSD_A_OUT + if ((trelfd = open(filename, O_WRONLY)) == ERR) + outputerror("cannot reopen"); + trelbufptr = trelbuf; +#endif +} + +PRIVATE void outhexdigs(num) +register offset_t num; +{ + if (num >= 0x10) + { + outhexdigs(num / 0x10); + num %= 0x10; + } + putbyte(hexdigit[num]); +} + +PRIVATE void put04x(num) +register unsigned num; +{ + putbyte(hexdigit[num / 0x1000]); + putbyte(hexdigit[(num / 0x100) & 0x0F]); + putbyte(hexdigit[(num / 0x10) & 0x0F]); + putbyte(hexdigit[num & 0x0F]); +} + +#ifdef LONG_OFFSETS + +PUBLIC void put08lx(num) +register offset_t num; +{ + put04x(num / 0x10000); + put04x(num % 0x10000); +} + +#else /* not LONG_OFFSETS */ + +PUBLIC void put08x(num) +register offset_t num; +{ + putstr("0000"); + put04x(num); +} + +#endif /* not LONG_OFFSETS */ + +PUBLIC void putbstr(width, str) +unsigned width; +char *str; +{ + unsigned length; + + for (length = strlen(str); length < width; ++length) + putbyte(' '); + putstr(str); +} + +PUBLIC void putbyte(ch) +int ch; +{ + register char *ebuf; + + ebuf = errbufptr; + if (ebuf >= errbuftop) + { + flusherr(); + ebuf = errbufptr; + } + *ebuf++ = ch; + errbufptr = ebuf; +} + +PUBLIC void putstr(message) +char *message; +{ + while (*message != 0) + putbyte(*message++); +} + +PRIVATE void putstrn(message) +char *message; +{ + putstr(message); + putbyte('\n'); + flusherr(); +} + +PUBLIC int readchar() +{ + int ch; + + register char *ibuf; + int nread; + + ibuf = inbufptr; + if (ibuf >= inbufend) + { + ibuf = inbufptr = inbuf; + nread = read(infd, ibuf, INBUFSIZE); + if (nread <= 0) + { + inbufend = ibuf; + return ERR; + } + inbufend = ibuf + nread; + } + ch = (unsigned char) *ibuf++; + inbufptr = ibuf; + return ch; +} + +PUBLIC void readin(buf, count) +char *buf; +unsigned count; +{ + int ch; + + while (count--) + { + if ((ch = readchar()) < 0) + prematureeof(); + *buf++ = ch; + } +} + +PUBLIC bool_pt readineofok(buf, count) +char *buf; +unsigned count; +{ + int ch; + + while (count--) + { + if ((ch = readchar()) < 0) + return TRUE; + *buf++ = ch; + } + return FALSE; +} + +PUBLIC void seekin(offset) +long offset; +{ + inbufptr = inbufend = inbuf; + if (lseek(infd, offset, SEEK_SET) < 0) + prematureeof(); +} + +PUBLIC void seekout(offset) +long offset; +{ + flushout(); + if (lseek(outfd, offset, SEEK_SET) != offset) + outputerror("cannot seek in"); +} + +#ifdef BSD_A_OUT +PUBLIC void seektrel(offset) +long offset; +{ + flushtrel(); + if (lseek(trelfd, offset, SEEK_SET) != offset) + outputerror("cannot seek in"); +} +#endif + +PUBLIC void writechar(ch) +int ch; +{ + register char *obuf; + + obuf = outbufptr; + if (obuf >= outbuftop) + { + flushout(); + obuf = outbufptr; + } + *obuf++ = ch; + outbufptr = obuf; +} + +#ifdef BSD_A_OUT +PUBLIC void writedrel(buf, count) +register char *buf; +unsigned count; +{ + register char *rbuf; + + rbuf = drelbufptr; + while (count--) + { + if (rbuf >= drelbuftop) + inputerror("data relocation buffer full while processing"); + *rbuf++ = *buf++; + } + drelbufptr = rbuf; +} +#endif + +PUBLIC void writeout(buf, count) +register char *buf; +unsigned count; +{ + register char *obuf; + + obuf = outbufptr; + while (count--) + { + if (obuf >= outbuftop) + { + outbufptr = obuf; + flushout(); + obuf = outbufptr; + } + *obuf++ = *buf++; + } + outbufptr = obuf; +} + +#ifdef BSD_A_OUT +PUBLIC void writetrel(buf, count) +register char *buf; +unsigned count; +{ + register char *rbuf; + + rbuf = trelbufptr; + while (count--) + { + if (rbuf >= trelbuftop) + { + trelbufptr = rbuf; + flushtrel(); + rbuf = trelbufptr; + } + *rbuf++ = *buf++; + } + trelbufptr = rbuf; +} +#endif + +/* error module */ + +PRIVATE void errexit(message) +char *message; +{ + putstrn(message); + exit(2); +} + +PUBLIC void fatalerror(message) +char *message; +{ + refer(); + errexit(message); +} + +PUBLIC void inputerror(message) +char *message; +{ + refer(); + putstr(message); + putstr(" input file "); + errexit(inputname); +} + +PUBLIC void input1error(message) +char *message; +{ + refer(); + putstr(inputname); + errexit(message); +} + +PRIVATE void outputerror(message) +char *message; +{ + refer(); + putstr(message); + putstr(" output file "); + errexit(outputname); +} + +PUBLIC void outofmemory() +{ + inputerror("out of memory while processing"); +} + +PUBLIC void prematureeof() +{ + inputerror("premature end of"); +} + +PUBLIC void redefined(name, message, archentry, deffilename, defarchentry) +char *name; +char *message; +char *archentry; +char *deffilename; +char *defarchentry; +{ + ++warncount; + refer(); + putstr("warning: "); + putstr(name); + putstr(" redefined"); + putstr(message); + putstr(" in file "); + putstr(inputname); + if (archentry != NULL) + { + putbyte('('); + putstr(archentry); + putbyte(')'); + } + putstr("; using definition in "); + putstr(deffilename); + if (defarchentry != NULL) + { + putbyte('('); + putstr(defarchentry); + putbyte(')'); + } + putbyte('\n'); +} + +PRIVATE void refer() +{ + putstr(refname); + putstr(": "); +} + +PUBLIC void reserved(name) +char *name; +{ + ++errcount; + putstr("incorrect use of reserved symbol: "); + putstrn(name); +} + +PUBLIC void size_error(seg, count, size) +char seg; +offset_t count; +offset_t size; +{ + refer(); + putstr("seg "); + outhexdigs((offset_t) seg); + putstr(" has wrong size "); + outhexdigs(count); + putstr(", supposed to be "); + outhexdigs(size); + errexit("\n"); +} + +PUBLIC void undefined(name) +char *name; +{ + ++errcount; + putstr("undefined symbol: "); + putstrn(name); +} + +PUBLIC void usage() +{ + putstr("usage: "); + putstr(refname); +#ifdef BSD_A_OUT + errexit("\ + [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\ + [-L libdir] [-Olibfile] [-T textaddr] infile..."); +#else + errexit("\ + [-03Mimstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\ + [-L libdir] [-Olibfile] [-T textaddr] infile..."); +#endif +} + +PUBLIC void use_error(message) +char *message; +{ + refer(); + putstrn(message); + usage(); +} diff --git a/bin86-0.3/ld/ld.c b/bin86-0.3/ld/ld.c new file mode 100644 index 0000000..04ffe83 --- /dev/null +++ b/bin86-0.3/ld/ld.c @@ -0,0 +1,180 @@ +/* + * bin86/ld/ld.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */ + +#ifdef STDC_HEADERS_MISSING +extern int errno; +#else +#include <errno.h> +#endif + +#include "const.h" +#include "byteord.h" +#include "type.h" +#include "globvar.h" + +#define MAX_LIBS (NR_STDLIBS + 5) +#define NR_STDLIBS 1 + +PUBLIC long text_base_address; /* XXX */ + +PRIVATE bool_t flag[128]; +PRIVATE char *libs[MAX_LIBS] = { +#ifdef MC6809 + "/usr/local/lib/m09/", +#else + /* One of the following values will be inserted at run time. */ +# define std386lib "/usr/local/lib/i386/" +# define std86lib "/usr/local/lib/i86/" +#endif + 0 +}; +PRIVATE int lastlib = NR_STDLIBS; + +FORWARD char *buildname P((char *pre, char *mid, char *suf)); +FORWARD char *expandlib P((char *fn)); + +PRIVATE char *buildname(pre, mid, suf) +char *pre; +char *mid; +char *suf; +{ + char *name; + + name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1); + strcpy(name, pre); + strcat(name, mid); + strcat(name, suf); + return name; +} + +PRIVATE char *expandlib(fn) +char *fn; +{ + char *path; + int i; + +#ifndef MC6809 + libs[0] = flag['3'] ? std386lib : std86lib; +#endif + + for (i = lastlib - 1; i >= 0; --i) + { + path = ourmalloc(strlen(libs[i]) + strlen(fn) + 1); + strcpy(path, libs[i]); + strcat(path, fn); + if (access(path, R_OK) == 0) + return path; + ourfree(path); + } + return NULL; +} + +PUBLIC int main(argc, argv) +int argc; +char **argv; +{ + register char *arg; + int argn; + static char crtprefix[] = "crt"; + static char crtsuffix[] = ".o"; + char *infilename; + static char libprefix[] = "lib"; + static char libsuffix[] = ".a"; + char *outfilename; + char *tfn; + + ioinit(argv[0]); + objinit(); + syminit(); + typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN); +#if 0 + flag['z'] = flag['3'] = sizeof(char *) >= 4; +#else + flag['z'] = 0; + flag['3'] = sizeof(char *) >= 4; +#endif + outfilename = NULL; + for (argn = 1; argn < argc; ++argn) + { + arg = argv[argn]; + if (*arg != '-') + readsyms(arg, flag['t']); + else + switch (arg[1]) + { + case '0': /* use 16-bit libraries */ + case '3': /* use 32-bit libraries */ + case 'M': /* print symbols linked */ + case 'i': /* separate I & D output */ + case 'm': /* print modules linked */ +#ifdef BSD_A_OUT + case 'r': /* relocatable output */ +#endif + case 's': /* strip symbols */ + case 't': /* trace modules linked */ + case 'z': /* unmapped zero page */ + if (arg[2] == 0) + flag[arg[1]] = TRUE; + else if (arg[2] == '-' && arg[3] == 0) + flag[arg[1]] = FALSE; + else + usage(); + if (arg[1] == '0') /* flag 0 is negative logic flag 3 */ + flag['3'] = !flag['0']; + break; + case 'C': /* startfile name */ + tfn = buildname(crtprefix, arg + 2, crtsuffix); + if ((infilename = expandlib(tfn)) == NULL) + fatalerror(tfn); + readsyms(infilename, flag['t']); + break; + case 'L': /* library path */ + if (lastlib < MAX_LIBS) + libs[lastlib++] = arg + 2; + else + fatalerror("too many library paths"); + break; + case 'O': /* library file name */ + if ((infilename = expandlib(arg + 2)) == NULL) + fatalerror(arg); + readsyms(infilename, flag['t']); + break; + case 'T': /* text base address */ + if (arg[2] != 0 || ++argn >= argc) + usage(); + errno = 0; + text_base_address = strtoul(argv[argn], (char **) NULL, 16); + if (errno != 0) + use_error("invalid text address"); + break; + case 'l': /* library name */ + tfn = buildname(libprefix, arg + 2, libsuffix); + if ((infilename = expandlib(tfn)) == NULL) + fatalerror(tfn); + readsyms(infilename, flag['t']); + break; + case 'o': /* output file name */ + if (arg[2] != 0 || ++argn >= argc || outfilename != NULL) + usage(); + outfilename = argv[argn]; + break; + default: + usage(); + } + } + linksyms(flag['r']); + if (outfilename == NULL) + outfilename = "a.out"; + writebin(outfilename, flag['i'], flag['3'], flag['s'], flag['z']); + if (flag['m']) + dumpmods(); + if (flag['M']) + dumpsyms(); + flusherr(); + return errcount ? 1 : 0; +} diff --git a/bin86-0.3/ld/obj.h b/bin86-0.3/ld/obj.h new file mode 100644 index 0000000..d9ba2ba --- /dev/null +++ b/bin86-0.3/ld/obj.h @@ -0,0 +1,58 @@ +/* + * bin86/ld/obj.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* obj.h - constants for Introl object modules */ + +#define OBJ_H + +#ifdef I80386 +# define LONG_OFFSETS /* others can use this, but wasteful */ +#endif + +#ifndef OMAGIC +# ifdef I80386 +# define OMAGIC 0x86A3 +# endif + +# ifdef I8086 +# define OMAGIC 0x86A0 +# endif + +# ifdef MC6809 +# define OMAGIC 0x5331 +# endif +#endif + +#ifdef LONG_OFFSETS +# define cntooffset cnu4 +# define offtocn u4cn +#else +# define cntooffset cnu2 +# define offtocn u2cn +#endif + +#ifdef MC6809 /* temp don't support alignment at all */ +# define ld_roundup( num, boundary, type ) (num) +#else +# define ld_roundup( num, boundary, type ) \ + (((num) + ((boundary) - 1)) & (type) ~((boundary) - 1)) +#endif + +#define MAX_OFFSET_SIZE 4 +#define NSEG 16 + +/* flag values |SZ|LXXXX|N|E|I|R|A|SEGM|, X not used */ + +#define A_MASK 0x0010 /* absolute */ +#define C_MASK 0x0020 /* common (internal only) */ +#define E_MASK 0x0080 /* exported */ +#define I_MASK 0x0040 /* imported */ +#define N_MASK 0x0100 /* entry point */ +#define R_MASK 0x0020 /* relative (in text only) */ +#define SEGM_MASK 0x000F /* segment (if not absolute) */ +#define SA_MASK 0x2000 /* offset is storage allocation */ +#define SZ_MASK 0xC000 /* size descriptor for value */ +#define SZ_SHIFT 14 diff --git a/bin86-0.3/ld/readobj.c b/bin86-0.3/ld/readobj.c new file mode 100644 index 0000000..5c4dd72 --- /dev/null +++ b/bin86-0.3/ld/readobj.c @@ -0,0 +1,368 @@ +/* + * bin86/ld/readobj.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* readobj.c - read object file for linker */ + +#include "ar.h" /* maybe local copy of <ar.h> for cross-link */ +#include "const.h" +#include "byteord.h" +#include "obj.h" +#include "type.h" +#include "globvar.h" + +/* + Linking takes 2 passes. The 1st pass reads through all files specified +in the command line, and all libraries. All public symbols are extracted +and stored in a chained hash table. For each module, its file and header +data recorded, and the resulting structures are chained together +(interleaved with the symbols). + + The symbol descriptors are separated from the symbol names, so we must +record all the descriptors of a module before putting the symbols in the +symbol table (poor design). The descriptors are stored in the symbol +table, then moved to the top of the table to make room for the symols. +The symbols referred to in a given module are linked together by a chain +beginning in the module descriptor. +*/ + +PRIVATE char convertsize[NSEG / 4] = {0, 1, 2, 4}; +PRIVATE struct entrylist *entrylast; /* last on list of entry symbols */ +PRIVATE struct redlist *redlast; /* last on list of redefined symbols */ +PRIVATE struct modstruct *modlast; /* data for last module */ + +FORWARD long readarheader P((char **parchentry)); +FORWARD unsigned readfileheader P((void)); +FORWARD void readmodule P((char *filename, char *archentry)); +FORWARD void reedmodheader P((void)); +FORWARD bool_pt redsym P((struct symstruct *symptr, offset_t value)); +FORWARD unsigned checksum P((char *string, unsigned length)); +FORWARD unsigned segbits P((unsigned seg, char *sizedesc)); + +/* initialise object file handler */ + +PUBLIC void objinit() +{ + modfirst = modlast = NULL; + entryfirst = entrylast = NULL; + redfirst = redlast = NULL; +} + +/* read all symbol definitions in an object file */ + +PUBLIC void readsyms(filename, trace) +char *filename; +bool_pt trace; +{ + char *archentry; + long filelength; + char filemagic[SARMAG]; + long filepos; + unsigned modcount; + + if (trace) + errtrace(filename, 0); + openin(filename); /* input is not open, so position is start */ + switch ((unsigned) readsize(2)) + { + case OMAGIC: + seekin(0L); + for (modcount = readfileheader(); modcount-- != 0;) + readmodule(filename, (char *) NULL); + break; + default: + seekin(0L); + readin(filemagic, sizeof filemagic); + if (strncmp(filemagic, ARMAG, sizeof filemagic) != 0) + input1error(" has bad magic number"); + filepos = SARMAG; + while ((filelength = readarheader(&archentry)) > 0) + { + if (trace) + errtrace(archentry, 2); + filepos += sizeof(struct ar_hdr); + for (modcount = readfileheader(); modcount-- != 0;) + { + readmodule(stralloc(filename), archentry); + modlast->textoffset += filepos; + } + seekin(filepos += ld_roundup(filelength, 2, long)); + } + break; + } + closein(); +} + +/* read archive header and return length */ + +PRIVATE long readarheader(parchentry) +char **parchentry; +{ + struct ar_hdr arheader; + char *endptr; + char *nameptr; + + if (readineofok((char *) &arheader, sizeof arheader)) + return 0; + strncpy (*parchentry = nameptr = ourmalloc(sizeof arheader.ar_name + 1), + arheader.ar_name, sizeof arheader.ar_name); + endptr = nameptr + sizeof arheader.ar_name; + do + *endptr = 0; + while (endptr > nameptr && *--endptr == ' '); + return strtoul(arheader.ar_size, (char **) NULL, 0); +} + +/* read and check file header of the object file just opened */ + +PRIVATE unsigned readfileheader() +{ + struct + { + char magic[2]; + char count[2]; /* really an int */ + } + fileheader; + char filechecksum; /* part of fileheader but would unalign */ + + readin((char *) &fileheader, sizeof fileheader); + readin(&filechecksum, sizeof filechecksum); + if (filechecksum != checksum((char *) &fileheader, sizeof fileheader)) + input1error(" is not an object file"); + return c2u2(fileheader.count); +} + +/* read the next module */ + +PRIVATE void readmodule(filename, archentry) +char *filename; +char *archentry; +{ + struct symdstruct /* to save parts of symbol before name known */ + { + offset_t dvalue; + flags_t dflags; + }; + struct symdstruct *endsymdptr; + flags_t flags; + unsigned nsymbol; + struct symdstruct *symdptr; + char *symname; + struct symstruct **symparray; + struct symstruct *symptr; + + reedmodheader(); + modlast->filename = filename; + modlast->archentry = archentry; + nsymbol = readsize(2); + symdptr = (struct symdstruct *) + ourmalloc(nsymbol * sizeof(struct symdstruct)); + for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; ++symdptr) + { + readsize(2); /* discard string offset, assume strings seq */ + symdptr->dflags = flags = readsize(2); + symdptr->dvalue = readconvsize((flags & SZ_MASK) >> SZ_SHIFT); + /* NB unsigned flags to give logical shift */ + /* bug in Xenix 2.5 cc causes (int) of the */ + /* argument to turn flags into an int */ + } + symdptr = (struct symdstruct *) + moveup(nsymbol * sizeof(struct symdstruct)); + modlast->symparray = symparray = (struct symstruct **) + ourmalloc((nsymbol + 1) * sizeof(struct symstruct *)); + symname = readstring(); /* module name */ + modlast->modname = stralloc(symname); /* likely OK overlapped copy */ + for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; + *symparray++ = symptr, release((char *) ++symdptr)) + { + symname = readstring(); + if ((flags = symdptr->dflags) & (E_MASK | I_MASK) && + (symptr = findsym(symname)) != NULL) + { + /* + weaken segment-checking by letting the maximum segment + (SEGM_MASK) mean any segment + */ + if ((symptr->flags & SEGM_MASK) == SEGM_MASK) + symptr->flags &= ~SEGM_MASK | (flags & SEGM_MASK); + else if ((flags & SEGM_MASK) == SEGM_MASK) + flags &= ~SEGM_MASK | (symptr->flags & SEGM_MASK); + if ((flags ^ symptr->flags) & (N_MASK | A_MASK | SEGM_MASK)) + { + redefined(symname, " with different segment or relocatability", + archentry, symptr->modptr->filename, + symptr->modptr->archentry); + continue; + } + if (symptr->flags & E_MASK) + { + if (flags & E_MASK && redsym(symptr, symdptr->dvalue)) + redefined(symname, "", archentry, symptr->modptr->filename, + symptr->modptr->archentry); + continue; + } + if (flags & I_MASK && symdptr->dvalue <= symptr->value) + continue; + } + else + symptr = addsym(symname); + symptr->modptr = modlast; + symptr->value = symdptr->dvalue; + symptr->flags = flags; + if (flags & N_MASK) + entrysym(symptr); + } + *symparray = NULL; +} + +/* put symbol on entry symbol list if it is not already */ + +PUBLIC void entrysym(symptr) +struct symstruct *symptr; +{ + register struct entrylist *elptr; + + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + if (symptr == elptr->elsymptr) + return; + elptr = (struct entrylist *) ourmalloc(sizeof(struct entrylist)); + elptr->elnext = NULL; + elptr->elsymptr = symptr; + if (entryfirst == NULL) + entryfirst = elptr; + else + entrylast->elnext = elptr; + entrylast = elptr; +} + +/* read the header of the next module */ + +PRIVATE void reedmodheader() +{ + struct + { + char htextoffset[4]; /* offset to module text in file */ + char htextsize[4]; /* size of text (may be 0 for last mod) */ + char stringssize[2]; /* size of string area */ + char hclass; /* module class */ + char revision; /* module revision */ + } + modheader; + unsigned seg; + unsigned count; + char *cptr; + struct modstruct *modptr; + + readin((char *) &modheader, sizeof modheader); + modptr = (struct modstruct *) ourmalloc(sizeof(struct modstruct)); + modptr->modnext = NULL; + modptr->textoffset = c4u4(modheader.htextoffset); + modptr->class = modheader.hclass; + readin(modptr->segmaxsize, sizeof modptr->segmaxsize); + readin(modptr->segsizedesc, sizeof modptr->segsizedesc); + cptr = modptr->segsize; + for (seg = 0; seg < NSEG; ++seg) + { + if ((count = segsizecount(seg, modptr)) != 0) + { + if (cptr == modptr->segsize) + ourmalloc(count - 1); /* 1st byte reserved in struct */ + else + ourmalloc(count); + readin(cptr, count); + cptr += count; + } + } + if (modfirst == NULL) + modfirst = modptr; + else + modlast->modnext = modptr; + modlast = modptr; +} + +PRIVATE bool_pt redsym(symptr, value) +register struct symstruct *symptr; +offset_t value; +{ + register struct redlist *rlptr; + char class; + + if (symptr->modptr->class != (class = modlast->class)) + for (rlptr = redfirst;; rlptr = rlptr->rlnext) + { + if (rlptr == NULL) + { + rlptr = (struct redlist *) + ourmalloc(sizeof(struct redlist)); + rlptr->rlnext = NULL; + rlptr->rlsymptr = symptr; + if (symptr->modptr->class < class) + /* prefer lower class - put other on redlist */ + { + rlptr->rlmodptr = modlast; + rlptr->rlvalue = value; + } + else + { + rlptr->rlmodptr = symptr->modptr; + symptr->modptr = modlast; + rlptr->rlvalue = symptr->value; + symptr->value = value; + } + if (redfirst == NULL) + redfirst = rlptr; + else + redlast->rlnext = rlptr; + redlast = rlptr; + return FALSE; + } + if (symptr == rlptr->rlsymptr && class == rlptr->rlmodptr->class) + break; + } + return TRUE; +} + +PRIVATE unsigned checksum(string, length) +char *string; +unsigned length; +{ + unsigned char sum; /* this is a 1-byte checksum */ + + for (sum = 0; length-- != 0;) + sum += *string++ & 0xFF; + return sum; +} + +PUBLIC offset_t readconvsize(countindex) +unsigned countindex; +{ + return readsize(convertsize[countindex]); +} + +PUBLIC offset_t readsize(count) +unsigned count; +{ + char buf[MAX_OFFSET_SIZE]; + + if (count == 0) + return 0; + readin(buf, count); + return cntooffset(buf, count); +} + +PRIVATE unsigned segbits(seg, sizedesc) +unsigned seg; +char *sizedesc; +{ + return 3 & ((unsigned) sizedesc[((NSEG - 1) - seg) / 4] >> (2 * (seg % 4))); + /* unsigned to give logical shift */ +} + +PUBLIC unsigned segsizecount(seg, modptr) +unsigned seg; +struct modstruct *modptr; +{ + return convertsize[segbits(seg, modptr->segsizedesc)]; +} diff --git a/bin86-0.3/ld/table.c b/bin86-0.3/ld/table.c new file mode 100644 index 0000000..557eec6 --- /dev/null +++ b/bin86-0.3/ld/table.c @@ -0,0 +1,202 @@ +/* + * bin86/ld/table.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* table.c - table-handler module for linker */ + +#include "const.h" +#include "align.h" +#include "obj.h" +#include "type.h" +#include "globvar.h" + +#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */ +#define HASHTABSIZE 256 + +PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* hash table */ +PRIVATE char *tableptr; /* next free spot in catchall table */ +PRIVATE char *tableend; /* ptr to spot after last in table */ + +FORWARD struct symstruct **gethashptr P((char *name)); + +/* initialise symbol table */ + +PUBLIC void syminit() +{ + unsigned i; + + for (i = sizeof(int) <= 2 ? 0xE000 : (unsigned) 0x38000; + i != 0; i -= 512) + if ((tableptr = malloc(i)) != NULL) + break; + if (tableptr == NULL) + outofmemory(); + tableend = tableptr + i; + for (i = 0; i < HASHTABSIZE; i++) + hashtab[i] = NULL; +} + +/* add named symbol to end of table - initialise only name and next fields */ +/* caller must not duplicate names of externals for findsym() to work */ + +PUBLIC struct symstruct *addsym(name) +char *name; +{ + struct symstruct **hashptr; + struct symstruct *oldsymptr; + struct symstruct *symptr; + + hashptr = gethashptr(name); + symptr = *hashptr; + while (symptr != NULL) + { + oldsymptr = symptr; + symptr = symptr->next; + } + align(tableptr); + symptr = (struct symstruct *) tableptr; + if ((tableptr = symptr->name + (strlen(name) + 1)) > tableend) + outofmemory(); + symptr->modptr = NULL; + symptr->next = NULL; + if (name != symptr->name) + strcpy(symptr->name, name); /* should't happen */ + if (*hashptr == NULL) + *hashptr = symptr; + else + oldsymptr->next = symptr; + return symptr; +} + +/* lookup named symbol */ + +PUBLIC struct symstruct *findsym(name) +char *name; +{ + struct symstruct *symptr; + + symptr = *gethashptr(name); + while (symptr != NULL && (!(symptr->flags & (E_MASK | I_MASK)) || + strcmp(symptr->name, name) != 0)) + symptr = symptr->next; + return symptr; +} + +/* convert name to a hash table ptr */ + +PRIVATE struct symstruct **gethashptr(name) +register char *name; +{ + register unsigned hashval; + + hashval = 0; + while (*name) + hashval = hashval * 2 + *name++; + return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1)); + +/* + +#asm + +GOLDEN EQU 157 +HASHTABSIZE EQU 256 + + CLRB can build value here since HASHTABSIZE <= 256 + LDA ,X + BEQ HASHVAL.EXIT +HASHVAL.LOOP + ADDB ,X+ + LSLB + LDA ,X + BNE HASHVAL.LOOP + RORB + LDA #GOLDEN + MUL +HASHVAL.EXIT +HASHVAL.EXIT + LDX #_hashtab + ABX discard A - same as taking mod HASHTABSIZE + ABX +#endasm + +*/ + +} + +/* move symbol descriptor entries to top of table (no error checking) */ + +PUBLIC char *moveup(nbytes) +unsigned nbytes; +{ + register char *source; + register char *target; + + source = tableptr; + target = tableend; + while (nbytes--) + *--target = *--source; + tableptr = source; + return tableend = target; +} + +/* our version of malloc */ + +PUBLIC char *ourmalloc(nbytes) +unsigned nbytes; +{ + char *allocptr; + + align(tableptr); + allocptr = tableptr; + if ((tableptr += nbytes) > tableend) + outofmemory(); + return allocptr; +} + +/* our version of free (release from bottom of table) */ + +PUBLIC void ourfree(cptr) +char *cptr; +{ + tableptr = cptr; +} + +/* read string from file into table at offset suitable for next symbol */ + +PUBLIC char *readstring() +{ + int c; + char *s; + char *start; + + align(tableptr); + start = s = ((struct symstruct *) tableptr)->name; + while (TRUE) + { + if (s >= tableend) + outofmemory(); + if ((c = readchar()) < 0) + prematureeof(); + if ((*s++ = c) == 0) + return start; + } + /* NOTREACHED */ +} + +/* release from top of table */ + +PUBLIC void release(cptr) +char *cptr; +{ + tableend = cptr; +} + +/* allocate space for string */ + +PUBLIC char *stralloc(s) +char *s; +{ + return strcpy(ourmalloc((unsigned) strlen(s) + 1), s); +} diff --git a/bin86-0.3/ld/type.h b/bin86-0.3/ld/type.h new file mode 100644 index 0000000..d5d9a8d --- /dev/null +++ b/bin86-0.3/ld/type.h @@ -0,0 +1,228 @@ +/* + * bin86/ld/type.h + * + * Copyright (C) 1992 Bruce Evans + */ + +/* type.h - types for linker */ + +typedef unsigned bool_pt; +typedef unsigned char bool_t; + +typedef unsigned short u2_t; +typedef unsigned u2_pt; +typedef unsigned long u4_t; +typedef unsigned long u4_pt; + +#ifdef OBJ_H /* obj.h is included */ + +/* Prevent the use of offset_t */ +#ifndef offset_t +#define offset_t offset_T +#endif + +typedef unsigned flags_t; /* unsigned makes shifts logical */ + +#ifdef LONG_OFFSETS +typedef unsigned long offset_t; +#else +typedef unsigned offset_t; +#endif + +struct entrylist /* list of entry symbols */ +{ + struct entrylist *elnext; /* next on list */ + struct symstruct *elsymptr; /* entry on list */ +}; + +struct modstruct /* module table entry format */ +{ + char *filename; /* file containing this module */ + char *archentry; /* name of component file for archives */ + char *modname; /* name of module */ + long textoffset; /* offset to module text in file */ + char class; /* class of module */ + char loadflag; /* set if module to be loaded */ + char segmaxsize[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for seg max size */ + /* 00 = 1, 01 = 2, 10 = 3, 11 = 4 */ + char segsizedesc[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for #bytes for size */ + /* 00 = 0, 01 = 1, 10 = 2, 11 = 4 */ + struct symstruct **symparray; /* ^array of ptrs to referenced syms */ + struct modstruct *modnext; /* next module in order of initial reading */ + char segsize[1]; /* up to 64 size bytes begin here */ +}; /* careful with sizeof( struct modstruct )!! */ + +struct redlist /* list of redefined (exported) symbols */ +{ + struct redlist *rlnext; /* next on list */ + struct symstruct *rlsymptr; /* to symbol with same name, flags */ + struct modstruct *rlmodptr; /* module for this redefinition */ + offset_t rlvalue; /* value for this redefinition */ +}; + +struct symstruct /* symbol table entry format */ +{ + struct modstruct *modptr; /* module where symbol is defined */ + offset_t value; /* value of symbol */ + flags_t flags; /* see below (unsigned makes shifts logical) */ + struct symstruct *next; /* next symbol with same hash value */ + char name[1]; /* name is any string beginning here */ +}; /* don't use sizeof( struct symstruct )!! */ + +#endif /* obj.h is included */ + +/* prototypes */ + +#if defined(PROTO) || __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + +/* dump.c */ +void dumpmods P((void)); +void dumpsyms P((void)); + +/* io.c */ +void ioinit P((char *progname)); +void closein P((void)); +void closeout P((void)); +void errtrace P((char *name, int level)); +void executable P((void)); +void flusherr P((void)); +void openin P((char *filename)); +void openout P((char *filename)); +void putstr P((char *message)); +#ifdef OBJ_H +void put08x P((offset_t num)); +void put08lx P((offset_t num)); +#endif +void putbstr P((unsigned width, char *str)); +void putbyte P((int ch)); +int readchar P((void)); +void readin P((char *buf, unsigned count)); +bool_pt readineofok P((char *buf, unsigned count)); +void seekin P((long offset)); +void seekout P((long offset)); +void seektrel P((long offset)); +void writechar P((int c)); +void writedrel P((char *buf, unsigned count)); +void writeout P((char *buf, unsigned count)); +void writetrel P((char *buf, unsigned count)); +void fatalerror P((char *message)); +void inputerror P((char *message)); +void input1error P((char *message)); +void outofmemory P((void)); +void prematureeof P((void)); +void redefined P((char *name, char *message, char *archentry, + char *deffilename, char *defarchentry)); +void reserved P((char *name)); +#ifdef OBJ_H +void size_error P((int seg, offset_t count, offset_t size)); +#endif +void undefined P((char *name)); +void usage P((void)); +void use_error P((char *message)); + +/* ld.c */ +int main P((int argc, char **argv)); + +/* readobj.c */ +void objinit P((void)); +void readsyms P((char *filename, bool_pt trace)); +#ifdef OBJ_H +void entrysym P((struct symstruct *symptr)); +offset_t readconvsize P((unsigned countindex)); +offset_t readsize P((unsigned count)); +unsigned segsizecount P((unsigned seg, struct modstruct *modptr)); +#endif + +/* table.c */ +void syminit P((void)); +struct symstruct *addsym P((char *name)); +struct symstruct *findsym P((char *name)); +char *moveup P((unsigned nbytes)); +char *ourmalloc P((unsigned nbytes)); +void ourfree P((char *cptr)); +char *readstring P((void)); +void release P((char *cptr)); +char *stralloc P((char *s)); + +/* typeconvert.c */ +u2_pt c2u2 P((char *buf)); +u4_t c4u4 P((char *buf)); +u2_pt cnu2 P((char *buf, unsigned count)); +u4_t cnu4 P((char *buf, unsigned count)); +void u2c2 P((char *buf, u2_pt offset)); +void u4c4 P((char *buf, u4_t offset)); +void u2cn P((char *buf, u2_pt offset, unsigned count)); +void u4cn P((char *buf, u4_t offset, unsigned count)); +bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian)); + +/* writebin.c */ +void writebin P((char *outfilename, bool_pt argsepid, bool_pt argbits32, + bool_pt argstripflag, bool_pt arguzp)); +void linksyms P((bool_pt argreloc_output)); + +/* Make offset_t safe for the standard includes */ +#undef offset_t + +/* library - fcntl.h */ +#undef NULL +#include <fcntl.h> +/* +int creat P((const char *_path, int _mode)); +int open P((const char *_path, int _oflag, ...)); +*/ + +/* library - sys/stat.h */ +#include <sys/stat.h> +#ifdef MY_STAT_H +int chmod P((const char *_path, mode_t _mode)); +int fstat P((int _fd, struct stat *_statbuf)); +mode_t umask P((mode_t _oldmask)); + /* it should be mode_t but it's hard to + * decide which systems define it, and where */ +#endif + +/* library - stdlib.h */ +#include <stdlib.h> +/* +void exit P((int _status)); +void *malloc P((unsigned _nbytes)); +unsigned long strtoul P((const char *_nptr, char **_endptr, int _base)); +*/ + +/* library - string.h */ +#include <string.h> +/* +void *memset P((void *_s, int _c, unsigned _nbytes)); +char *strcat P((char *_target, const char *_source)); +char *strchr P((const char *_s, int _ch)); +int strcmp P((const char *_s1, const char *_s2)); +char *strcpy P((char *_target, const char *_source)); +unsigned strlen P((const char *_s)); +char *strncat P((char *_target, const char *_source, unsigned _maxlength)); +int strncmp P((const char *_s1, const char *_s2, unsigned _nbytes)); +char *strncpy P((char *_target, const char *_source, unsigned _maxlength)); +char *strrchr P((const char *_s, int _ch)); +*/ + +/* library - unistd.h */ +#include <unistd.h> +/* +int access P((char *_path, int _amode)); +int close P((int _fd)); +long lseek P((int _fd, long _offset, int _whence)); +int read P((int _fd, char *_buf, unsigned _nbytes)); +int write P((int _fd, char *_buf, unsigned _nbytes)); +*/ + +#ifdef OBJ_H /* obj.h is included */ + +/* Prevent the use of offset_t */ +#ifndef offset_t +#define offset_t offset_T +#endif + +#endif diff --git a/bin86-0.3/ld/typeconv.c b/bin86-0.3/ld/typeconv.c new file mode 100644 index 0000000..1465106 --- /dev/null +++ b/bin86-0.3/ld/typeconv.c @@ -0,0 +1,540 @@ +/* + * bin86/ld/typeconv.c + * + * Copyright (C) 1992 Bruce Evans + */ + +/* typeconv.c - convert between char arrays and unsigneds */ + +/* + c2u2(): 2 byte array to 2 byte unsigned + c4u4(): 4 byte array to 4 byte unsigned + cnu2(): n byte array to 2 byte unsigned + cnu4(): n byte array to 4 byte unsigned + u2c2(): 2 byte unsigned to 2 byte array + u2cn(): 2 byte unsigned to n byte array + u4c4(): 4 byte unsigned to 4 byte array + u4cn(): 4 byte unsigned to n byte array + typeconv_init: (re)initialise for given byte order. + Default is no swapping, but the initialisation should be done + anyway to provide some validity checks (returns FALSE if error). + + Not provided: + c2u4(), c4u2(), u2c4(), u4c2(). + Each of these is best done by truncating or extending a return value + or argument to the appropiate fixed-count function. + c4u2() has too many cases to do in-line conveniently, and the others + are hardly more efficient when done in-line. + + 4 byte orderings for both char arrays and unsigneds are supported: + 0123 - little-endian + 3210 - big-endian + 2301 - little-endian with long words big-endian (pdp11) + 1032 - big-endian with long words little_endian (who knows?) + + The unsigned's byte order is that of the machine on which these + routines are running. + It is determined at run time initialisation since the compiler/ + preprocessor is too dumb to tell us at compile time. +*/ + +#include "const.h" +#include "type.h" +#include "globvar.h" + +FORWARD u2_pt c2u2_00 P((char *buf)); +FORWARD u4_pt c4u4_00 P((char *buf)); +FORWARD u2_pt c2u2_ss P((char *buf)); +FORWARD u4_pt c4u4_ss P((char *buf)); +FORWARD u4_pt c4u4_s0 P((char *buf)); +FORWARD u4_pt c4u4_0s P((char *buf)); +FORWARD void u2c2_00 P((char *buf, u2_pt offset)); +FORWARD void u4c4_00 P((char *buf, u4_t offset)); +FORWARD void u2c2_ss P((char *buf, u2_pt offset)); +FORWARD void u4c4_ss P((char *buf, u4_t offset)); +FORWARD void u4c4_s0 P((char *buf, u4_t offset)); +FORWARD void u4c4_0s P((char *buf, u4_t offset)); + +PRIVATE u2_pt (*pc2u2) P((char *buf)) = c2u2_00; +PRIVATE u4_pt (*pc4u4) P((char *buf)) = c4u4_00; +PRIVATE void (*pu2c2) P((char *buf, u2_pt offset)) = u2c2_00; +PRIVATE void (*pu4c4) P((char *buf, u4_t offset)) = u4c4_00; + +/* === char arrays to unsigneds === */ + +/* no bytes swapped, longwinded to avoid alignment problems */ + +PRIVATE u2_pt c2u2_00(buf) +register char *buf; +{ + u2_t offset; + + ((char *) &offset)[0] = buf[0]; + ((char *) &offset)[1] = buf[1]; + return offset; +} + +PRIVATE u4_pt c4u4_00(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[0]; + ((char *) &offset)[1] = buf[1]; + ((char *) &offset)[2] = buf[2]; + ((char *) &offset)[3] = buf[3]; + return offset; +} + +/* straight swapping for little-endian to big-endian and vice versa */ + +PRIVATE u2_pt c2u2_ss(buf) +register char *buf; +{ + u2_t offset; + + ((char *) &offset)[0] = buf[1]; + ((char *) &offset)[1] = buf[0]; + return offset; +} + +PRIVATE u4_pt c4u4_ss(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[3]; + ((char *) &offset)[1] = buf[2]; + ((char *) &offset)[2] = buf[1]; + ((char *) &offset)[3] = buf[0]; + return offset; +} + +/* wierd swapping for different-endian u2's, same-endian u4's */ + +PRIVATE u4_pt c4u4_s0(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[1]; + ((char *) &offset)[1] = buf[0]; + ((char *) &offset)[2] = buf[3]; + ((char *) &offset)[3] = buf[2]; + return offset; +} + +/* very wierd swapping for same-endian u2's, different-endian u4's */ + +PRIVATE u4_pt c4u4_0s(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[2]; + ((char *) &offset)[1] = buf[3]; + ((char *) &offset)[2] = buf[0]; + ((char *) &offset)[3] = buf[1]; + return offset; +} + +/* === entry points === */ + +PUBLIC u2_pt c2u2(buf) +char *buf; +{ + return (*pc2u2) (buf); +} + +PUBLIC u4_t c4u4(buf) +char *buf; +{ + return (*pc4u4) (buf); +} + +PUBLIC u2_pt cnu2(buf, count) +char *buf; +unsigned count; +{ + switch (count) + { + case 1: + return buf[0] & 0xFF; + case 2: + return (*pc2u2) (buf); + case 4: + return (u2_pt) (*pc4u4) (buf); + default: + return 0; + } +} + +PUBLIC u4_t cnu4(buf, count) +char *buf; +unsigned count; +{ + switch (count) + { + case 1: + return buf[0] & 0xFF; + case 2: + return (*pc2u2) (buf); + case 4: + return (*pc4u4) (buf); + default: + return 0; + } +} + +/* === unsigneds to char arrays === */ + +/* no bytes swapped, longwinded to avoid alignment problems */ + +PRIVATE void u2c2_00(buf, offset) +register char *buf; +u2_pt offset; +{ + + buf[0] = ((char *) &offset)[0]; + buf[1] = ((char *) &offset)[1]; +} + +PRIVATE void u4c4_00(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[0]; + buf[1] = ((char *) &offset)[1]; + buf[2] = ((char *) &offset)[2]; + buf[3] = ((char *) &offset)[3]; +} + +/* straight swapping for little-endian to big-endian and vice versa */ + +PRIVATE void u2c2_ss(buf, offset) +register char *buf; +u2_pt offset; +{ + u2_t offset2; + + offset2 = offset; + buf[0] = ((char *) &offset2)[1]; + buf[1] = ((char *) &offset2)[0]; +} + +PRIVATE void u4c4_ss(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[3]; + buf[1] = ((char *) &offset)[2]; + buf[2] = ((char *) &offset)[1]; + buf[3] = ((char *) &offset)[0]; +} + +/* wierd swapping for different-endian u2's, same-endian u4's */ + +PRIVATE void u4c4_s0(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[1]; + buf[1] = ((char *) &offset)[0]; + buf[2] = ((char *) &offset)[3]; + buf[3] = ((char *) &offset)[2]; +} + +/* very wierd swapping for same-endian u2's, different-endian u4's */ + +PRIVATE void u4c4_0s(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[2]; + buf[1] = ((char *) &offset)[3]; + buf[2] = ((char *) &offset)[0]; + buf[3] = ((char *) &offset)[1]; +} + +/* === entry points === */ + +PUBLIC void u2c2(buf, offset) +register char *buf; +u2_pt offset; +{ + (*pu2c2) (buf, offset); +} + +PUBLIC void u4c4(buf, offset) +register char *buf; +u4_t offset; +{ + (*pu4c4) (buf, offset); +} + +PUBLIC void u2cn(buf, offset, count) +register char *buf; +u2_pt offset; +unsigned count; +{ + switch (count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + (*pu2c2) (buf, offset); + return; + case 4: + (*pu4c4) (buf, (u4_t) offset); + return; + } +} + +PUBLIC void u4cn(buf, offset, count) +register char *buf; +u4_t offset; +unsigned count; +{ + switch (count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + (*pu2c2) (buf, (u2_pt) (u2_t) offset); + return; + case 4: + (*pu4c4) (buf, offset); + return; + } +} + +/* initialise type conversion, return FALSE if it cannot be handled */ + +PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) +bool_pt big_endian; +bool_pt long_big_endian; +{ + u2_pt conv2; + u4_pt conv4; + char *conv2ptr; + char *conv4ptr; + + if (sizeof(u2_t) != 2 || sizeof(u4_t) != 4) + /* dumb preprocessor's don't accept sizeof in #if expressions */ + return FALSE; + + if (big_endian) + { + conv2ptr = (conv4ptr = "\1\2\3\4") + 2; + if (!long_big_endian) + conv4ptr = "\3\4\1\2"; + } + else + { + conv2ptr = conv4ptr = "\4\3\2\1"; + if (long_big_endian) + conv4ptr = "\2\1\4\3"; + } + conv2 = c2u2_00(conv2ptr); + conv4 = c4u4_00(conv4ptr); + if (conv2 == 0x0304) + { + pc2u2 = c2u2_00; + pc4u4 = c4u4_00; + pu2c2 = u2c2_00; + pu4c4 = u4c4_00; + if (conv4 == 0x03040102L) + { + pc4u4 = c4u4_0s; + pu4c4 = u4c4_0s; + } + else if (conv4 != 0x01020304L) + return FALSE; + } + else if (conv2 == 0x0403) + { + pc2u2 = c2u2_ss; + pc4u4 = c4u4_ss; + pu2c2 = u2c2_ss; + pu4c4 = u4c4_ss; + if (conv4 == 0x02010403L) + { + pc4u4 = c4u4_s0; + pu4c4 = u4c4_s0; + } + else if (conv4 != 0x04030201L) + return FALSE; + } + else + return FALSE; + return TRUE; +} + +#ifdef DEBUG_TYPECONV + +main(int argc,char **argv) +{ + char *source; + char target[4]; + u2_t u2; + u2_t u2a; + u4_t u4; + u4_t u4a; + + printf("%u\n", typeconv_init(FALSE, FALSE)); + printf("%u\n", typeconv_init(FALSE, TRUE)); + printf("%u\n", typeconv_init(TRUE, FALSE)); + printf("%u\n", typeconv_init(TRUE, TRUE)); + + typeconv_init(FALSE, FALSE); + source = "\4\3\2\1"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source, 2); + u2cn(target, u2, 2); + if (strncmp(source, target, 2)) + printf("oops9\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source, 2); + u4cn(target, u4a, 2); + if (strncmp(source, target, 2)) + printf("oops10\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\4\3\0\0", 4)) + printf("oops11\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops12\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(FALSE, TRUE); + source = "\2\1\4\3"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source + 2, 2); + u2cn(target, u2, 2); + if (strncmp(source + 2, target, 2)) + printf("oops13\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source + 2, 2); + u4cn(target, u4a, 2); + if (strncmp(source + 2, target, 2)) + printf("oops14\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\0\0\4\3", 4)) + printf("oops15\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops16\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(TRUE, FALSE); + source = "\3\4\1\2"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source, 2); + u2cn(target, u2, 2); + if (strncmp(source, target, 2)) + printf("oops5\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source, 2); + u4cn(target, u4a, 2); + if (strncmp(source, target, 2)) + printf("oops6\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\3\4\0\0", 4)) + printf("oops7\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops8\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(TRUE, TRUE); + source = "\1\2\3\4"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source + 2, 2); + u2cn(target, u2, 2); + if (strncmp(source + 2, target, 2)) + printf("oops1\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source + 2, 2); + u4cn(target, u4a, 2); + if (strncmp(source + 2, target, 2)) + printf("oops2\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\0\0\3\4", 4)) + printf("oops3\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops4\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); +} + +#endif /* DEBUG_TYPECONV */ diff --git a/bin86-0.3/ld/writebin.c b/bin86-0.3/ld/writebin.c new file mode 100644 index 0000000..56b329d --- /dev/null +++ b/bin86-0.3/ld/writebin.c @@ -0,0 +1,949 @@ +/* + * bin86/ld/writebin.c + * + * Copyright (C) 1992 Bruce Evans + */ + +extern long text_base_address; +#define btextoffset text_base_address +static long bdataoffset; +#define page_size() 4096 + +/* writebin.c - write binary file for linker */ + +#ifdef A_OUT_H +# include A_OUT_H +#else +# ifdef BSD_A_OUT +# include "bsd-a.out.h" +# define A_MINHDR 0 +# define C_EXT N_EXT +# define C_STAT 0 +# define n_was_name n_un.n_name +# define n_was_numaux n_other +# define n_was_other n_numaux +# define n_was_sclass n_type +# define n_was_strx n_un.n_strx +# define n_was_type n_desc +# else /* not BSD_A_OUT */ +# include "a.out.h" /* maybe local copy of <a.out.h> for X-link */ +# define n_was_name n_name +# define n_was_numaux n_numaux +# define n_was_other n_other +# define n_was_sclass n_sclass +# define n_was_strx n_value +# define n_was_type n_type +# endif /* BSD_A_OUT */ +#endif + +#include "const.h" +#include "obj.h" +#include "type.h" +#undef EXTERN +#include "globvar.h" + +#ifdef EDOS +# define FILEHEADERLENGTH 0 +#endif +#ifdef MINIX +# ifdef BSD_A_OUT +# define FILEHEADERLENGTH sizeof (struct exec) +# else +# define FILEHEADERLENGTH A_MINHDR + /* part of header not counted in offsets */ +# endif +#endif +#define DPSEG 2 + +#define CM_MASK 0xC0 +#define MODIFY_MASK 0x3F +#define S_MASK 0x04 +#define OF_MASK 0x03 + +#define CM_SPECIAL 0 +#define CM_ABSOLUTE 0x40 +#define CM_OFFSET_RELOC 0x80 +#define CM_SYMBOL_RELOC 0xC0 + +#define CM_EOT 0 +#define CM_BYTE_SIZE 1 +#define CM_WORD_SIZE 2 +#define CM_LONG_SIZE 3 +#define CM_1_SKIP 17 +#define CM_2_SKIP 18 +#define CM_4_SKIP 19 +#define CM_0_SEG 32 + +#define ABS_TEXT_MAX 64 + +#define offsetof(struc, mem) ((int) &((struc *) 0)->mem) +#define memsizeof(struc, mem) sizeof(((struc *) 0)->mem) + +PRIVATE bool_t bits32; /* nonzero for 32-bit executable */ +PRIVATE offset_t combase[NSEG]; /* bases of common parts of segments */ +PRIVATE offset_t comsz[NSEG]; /* sizes of common parts of segments */ +PRIVATE char curseg; /* current segment, 0 to $F */ +PRIVATE offset_t edataoffset; /* end of data */ +PRIVATE offset_t endoffset; /* end of bss */ +PRIVATE offset_t etextoffset; /* end of text */ +PRIVATE offset_t etextpadoff; /* end of padded text */ +#ifdef BSD_A_OUT +PRIVATE unsigned ndreloc; /* number of data relocations */ +#endif +PRIVATE unsigned nsym; /* number of symbols written */ +#ifdef BSD_A_OUT +PRIVATE unsigned ntreloc; /* number of text relocations */ +PRIVATE bool_t reloc_output; /* nonzero to leave reloc info in output */ +#endif +PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */ +PRIVATE offset_t segadj[NSEG]; /* adjusts (file offset - seg offset) */ + /* depends on zero init */ +PRIVATE offset_t segbase[NSEG]; /* bases of data parts of segments */ +PRIVATE char segboundary[9] = "__seg0DH"; + /* name of seg boundary __seg0DL to __segfCH */ +PRIVATE offset_t segpos[NSEG]; /* segment positions for current module */ +PRIVATE offset_t segsz[NSEG]; /* sizes of data parts of segments */ + /* depends on zero init */ +PRIVATE bool_t sepid; /* nonzero for separate I & D */ +PRIVATE bool_t stripflag; /* nonzero to strip symbols */ +PRIVATE offset_t spos; /* position in current seg */ +PRIVATE bool_t uzp; /* nonzero for unmapped zero page */ + +#ifdef EDOS +FORWARD unsigned binheaderlength P((char *commandname)); +FORWARD char *idconvert P((struct entrylist *elptr, char *commandname)); +#endif +FORWARD void linkmod P((struct modstruct *modptr)); +FORWARD void linkrefs P((struct modstruct *modptr)); +FORWARD void padmod P((struct modstruct *modptr)); +FORWARD void setsym P((char *name, offset_t value)); +FORWARD void symres P((char *name)); +FORWARD void setseg P((unsigned newseg)); +FORWARD void skip P((unsigned countsize)); +#ifdef EDOS +FORWARD void writeheader P((char *commandname)); +#else +FORWARD void writeheader P((void)); +#endif +FORWARD void writenulls P((offset_t count)); + +/* link all symbols connected to entry symbols */ + +PUBLIC void linksyms(argreloc_output) +bool_pt argreloc_output; +{ + char needlink; + struct entrylist *elptr; + struct modstruct *modptr; + struct symstruct *symptr; + +#ifdef BSD_A_OUT + reloc_output = argreloc_output; + if (argreloc_output) + { + if (modfirst->modnext != NULL) + fatalerror("relocatable output only works for one input file"); + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + modptr->loadflag = TRUE; + return; + } +#endif + if ((symptr = findsym("_main")) != NULL) + entrysym(symptr); + do + { + if ((elptr = entryfirst) == NULL) + fatalerror("no start symbol"); + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + modptr->loadflag = FALSE; + for (; elptr != NULL; elptr = elptr->elnext) + linkrefs(elptr->elsymptr->modptr); + if ((symptr = findsym("start")) != NULL || + (symptr = findsym("crtso")) != NULL) + linkrefs(symptr->modptr); + needlink = FALSE; + { + struct redlist *prlptr; + struct redlist *rlptr; + + for (rlptr = redfirst; rlptr != NULL; + rlptr = (prlptr = rlptr)->rlnext) + if (rlptr->rlmodptr->loadflag && + rlptr->rlmodptr->class > rlptr->rlsymptr->modptr->class) + { + rlptr->rlsymptr->modptr = rlptr->rlmodptr; + rlptr->rlsymptr->value = rlptr->rlvalue; + if (rlptr == redfirst) + redfirst = rlptr->rlnext; + else + prlptr->rlnext = rlptr->rlnext; + needlink = TRUE; + } + } + } + while (needlink); +} + +/* write binary file */ + +PUBLIC void writebin(outfilename, argsepid, argbits32, argstripflag, arguzp) +char *outfilename; +bool_pt argsepid; +bool_pt argbits32; +bool_pt argstripflag; +bool_pt arguzp; +{ + char buf4[4]; +#ifdef EDOS + char *commandname; +#endif + char *cptr; + struct nlist extsym; + flags_t flags; + struct modstruct *modptr; + char seg; + unsigned sizecount; + offset_t tempoffset; + struct symstruct *symptr; + + sepid = argsepid; + bits32 = argbits32; + stripflag = argstripflag; +#ifdef BSD_A_OUT + uzp = arguzp && !reloc_output; +#else + uzp = arguzp; +#endif + if (uzp) + { + if (btextoffset == 0) + btextoffset = page_size(); + if (bdataoffset == 0 && sepid) + bdataoffset = page_size(); + } +#ifdef EDOS + commandname = stralloc(outfilename); + if ((cptr = strchr(commandname, ':')) != NULL) + commandname = cptr + 1; + if ((cptr = strrchr(commandname, '.')) != NULL) + *cptr = 0; +#endif + + /* reserve special symbols use curseg to pass parameter to symres() */ + for (curseg = 0; curseg < NSEG; ++curseg) + { + segboundary[5] = hexdigit[curseg]; /* to __segX?H */ + segboundary[6] = 'D'; + symres(segboundary); /* __segXDH */ + segboundary[7] = 'L'; + symres(segboundary); /* __segXDL */ + segboundary[6] = 'C'; + symres(segboundary); /* __segXCL */ + segboundary[7] = 'H'; + symres(segboundary); /* __segXCH */ + } +#ifdef EDOS + curseg = 0; /* data seg, s.b. variable */ +#else + curseg = 3; +#endif + symres("__edata"); + symres("__end"); + curseg = 0; /* text seg, s.b. variable */ + symres("__etext"); + + /* calculate segment and common sizes (sum over loaded modules) */ + /* use zero init of segsz[] */ + /* also relocate symbols relative to starts of their segments */ + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) + { + if (!(symptr->flags & (I_MASK | SA_MASK))) + { + /* relocate by offset of module in segment later */ + /* relocate by offset of segment in memory special */ + /* symbols get relocated improperly */ + symptr->value += segsz[symptr->flags & SEGM_MASK]; + } + else if (symptr->value == 0) + { +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + undefined(symptr->name); + } + else + { +#ifdef BSD_A_OUT +#if 0 + if (!reloc_output) +#else + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif +#endif + { + tempoffset = ld_roundup(symptr->value, 4, offset_t); + /* temp kludge quad alignment for 386 */ + symptr->value = comsz[seg = symptr->flags & SEGM_MASK]; + comsz[seg] += tempoffset; + } + if (!(symptr->flags & SA_MASK)) + symptr->flags |= C_MASK; + } + } + for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg) + { + segsz[seg] += cntooffset(cptr, + sizecount = segsizecount((unsigned) seg, modptr)); +#ifndef EDOS + + /* adjust sizes to even to get quad boundaries */ + /* this should be specifiable dynamically */ + segsz[seg] = ld_roundup(segsz[seg], 4, offset_t); + comsz[seg] = ld_roundup(comsz[seg], 4, offset_t); +#endif + cptr += sizecount; + } + } + + /* calculate seg positions now their sizes are known */ + /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */ + /* assume seg 0 is text and rest are data */ +#ifdef EDOS + if (btextoffset == 0) + btextoffset = binheaderlength(commandname); +#endif + segpos[0] = segbase[0] = spos = btextoffset; + combase[0] = segbase[0] + segsz[0]; + segadj[1] = segadj[0] = -btextoffset; + etextpadoff = etextoffset = combase[0] + comsz[0]; + if (sepid) + { + etextpadoff = ld_roundup(etextoffset, 0x10, offset_t); + segadj[1] += etextpadoff - bdataoffset; + } + else if (bdataoffset == 0) + bdataoffset = etextpadoff; + segpos[1] = segbase[1] = edataoffset = bdataoffset; + combase[1] = segbase[1] + segsz[1]; + for (seg = 2; seg < NSEG; ++seg) + { + segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1]; + if (seg == DPSEG) + { + /* temporarily have fixed DP seg */ + /* adjust if nec so it only spans 1 page */ + tempoffset = segsz[seg] + comsz[seg]; + if (tempoffset > 0x100) + fatalerror("direct page segment too large"); + if ((((segbase[seg] + tempoffset) ^ segbase[seg]) & ~0xFF) != 0) + segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF) & ~0xFF; + } + combase[seg] = segbase[seg] + segsz[seg]; + segadj[seg] = segadj[seg - 1]; + } + + /* relocate symbols by offsets of segments in memory */ + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) + { + if (symptr->flags & (C_MASK | SA_MASK)) + { +#ifdef BSD_A_OUT +#if 0 + if (!reloc_output) +#else + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif +#endif + symptr->value += combase[symptr->flags & SEGM_MASK]; + } + else +#ifdef BSD_A_OUT + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif + symptr->value += segbase[symptr->flags & SEGM_MASK]; + } + } + + /* adjust special symbols */ + for (seg = 0; seg < NSEG; ++seg) + { + if (segsz[seg] != 0) + /* only count data of nonzero length */ + edataoffset = segbase[seg] + segsz[seg]; + segboundary[5] = hexdigit[seg]; /* to __segX?H */ + segboundary[6] = 'D'; + setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]); + /* __segXDH */ + segboundary[7] = 'L'; + setsym(segboundary, tempoffset); /* __segXDL */ + segboundary[6] = 'C'; + setsym(segboundary, tempoffset = combase[seg]); + /* __segXCL */ + segboundary[7] = 'H'; + setsym(segboundary, tempoffset + comsz[seg]); + /* __segXCH */ + } + setsym("__etext", etextoffset); + setsym("__edata", edataoffset); + setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]); + + openout(outfilename); +#ifdef BSD_A_OUT + if (reloc_output) + seektrel(FILEHEADERLENGTH + + (long) (etextpadoff - btextoffset) + + (long) (edataoffset - bdataoffset)); +#endif +#ifdef EDOS + writeheader(commandname); +#else + writeheader(); +#endif + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + linkmod(modptr); + padmod(modptr); + } + + /* dump symbol table */ +#ifdef MINIX + if (!stripflag) + { +#ifdef BSD_A_OUT + unsigned stringoff; +#endif + + seekout(FILEHEADERLENGTH + + (long) (etextpadoff - btextoffset) + + (long) (edataoffset - bdataoffset) +#ifdef BSD_A_OUT + + ((long) ndreloc + ntreloc) + * (long) sizeof(struct relocation_info) +#endif + ); + extsym.n_was_numaux = extsym.n_was_type = 0; +#ifdef BSD_A_OUT + stringoff = 4; +#endif + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr) + { +#ifdef BSD_A_OUT + offtocn((char *) &extsym.n_was_strx, + (offset_t) stringoff, 4); +#else + strncpy((char *) &extsym.n_was_name, symptr->name, + sizeof extsym.n_was_name); +#endif + u4cn((char *) &extsym.n_value, (u4_t) symptr->value, + sizeof extsym.n_value); + if ((flags = symptr->flags) & A_MASK) + extsym.n_was_sclass = N_ABS; + else if (flags & (E_MASK | I_MASK)) + extsym.n_was_sclass = C_EXT; + else + extsym.n_was_sclass = C_STAT; + if (!(flags & I_MASK) || +#ifdef BSD_A_OUT + !reloc_output && +#endif + flags & C_MASK) + switch (flags & (A_MASK | SEGM_MASK)) + { + case 0: + extsym.n_was_sclass |= N_TEXT; + case A_MASK: + break; + default: + if (flags & (C_MASK | SA_MASK)) + extsym.n_was_sclass |= N_BSS; + else + extsym.n_was_sclass |= N_DATA; + break; + } + writeout((char *) &extsym, sizeof extsym); + ++nsym; +#ifdef BSD_A_OUT + stringoff += strlen(symptr->name) + 1; +#endif + } + } +#ifdef BSD_A_OUT + offtocn((char *) &extsym.n_was_strx, (offset_t) stringoff, 4); + writeout((char *) &extsym.n_was_strx, 4); + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr) + writeout(symptr->name, strlen(symptr->name) + 1); + } +#endif + seekout((long) offsetof(struct exec, a_syms)); + u4cn(buf4, (u4_t) nsym * sizeof extsym, + memsizeof(struct exec, a_syms)); + writeout(buf4, memsizeof(struct exec, a_syms)); +#if defined (BSD_A_OUT) && !defined(__linux__) + seekout((long) offsetof(struct exec, a_trsize)); + u4cn(buf4, (u4_t) ntreloc * sizeof(struct relocation_info), + memsizeof(struct exec, a_trsize)); + writeout(buf4, memsizeof(struct exec, a_trsize)); + seekout((long) offsetof(struct exec, a_drsize)); + u4cn(buf4, (u4_t) ndreloc * sizeof(struct relocation_info), + memsizeof(struct exec, a_drsize)); + writeout(buf4, memsizeof(struct exec, a_drsize)); +#endif + } +#endif /* MINIX */ + closeout(); +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + executable(); +} + +#ifdef EDOS + +PRIVATE unsigned binheaderlength(commandname) +char *commandname; +{ + unsigned count; + char *name; + struct entrylist *elptr; + struct symstruct *startptr; + + count = 2 + 2 + 1; /* len len nul */ + startptr = findsym("start"); + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + { + name = idconvert(elptr, commandname); + count += strlen(name) + 1 + 2 + 1; /* nul off flg */ + ourfree(name); + if (startptr != NULL) + count += 6; /* LBSR $xxxx and LBRA $xxxx */ + } + return count; +} + +/* convert name of symbol (entry) list element to a Basic identifier */ +/* new name is built in storage obtained from stralloc() */ +/* the special name _main is converted to the command name first */ +/* copy upper case and numerals, convert lower case to upper, ignore rest */ + +PRIVATE char *idconvert(elptr, commandname) +struct entrylist *elptr; +char *commandname; +{ + char *name; + char *newname; + + if (strcmp(name = elptr->elsymptr->name, "_main") == 0) + name = commandname; + newname = stralloc(name); + { + register char *t; + register char *s; + + t = newname; + s = name; + do + { + if (*s >= '0' && *s <= '9' || *s >= 'A' && *s <= 'Z') + *t++ = *s; + if (*s >= 'a' && *s <= 'z') + *t++ = *s + ('A' - 'a'); + } + while (*s++); + *t = 0; + } + if (*newname < 'A') /* numeral or null */ + fatalerror("bad entry name"); + return newname; +} + +#endif /* EDOS */ + +PRIVATE void linkmod(modptr) +struct modstruct *modptr; +{ + char buf[ABS_TEXT_MAX]; + int command; + unsigned char modify; + offset_t offset; + int symbolnum; + struct symstruct **symparray; + struct symstruct *symptr; + + setseg(0); + relocsize = 2; + symparray = modptr->symparray; + openin(modptr->filename); /* does nothing if already open */ + seekin((long) modptr->textoffset); + while (TRUE) + { + if ((command = readchar()) < 0) + prematureeof(); + modify = command & MODIFY_MASK; + switch (command & CM_MASK) + { + case CM_SPECIAL: + switch (modify) + { + case CM_EOT: + segpos[curseg] = spos; + return; + case CM_BYTE_SIZE: + relocsize = 1; + break; + case CM_WORD_SIZE: + relocsize = 2; + break; + case CM_LONG_SIZE: +#ifdef LONG_OFFSETS + relocsize = 4; + break; +#else + fatalerror("relocation by long offsets not implemented"); +#endif + case CM_1_SKIP: + skip(1); + break; + case CM_2_SKIP: + skip(2); + break; + case CM_4_SKIP: + skip(4); + break; + default: + if ((modify -= CM_0_SEG) >= NSEG) + inputerror("bad data in"); + setseg((unsigned) modify); + break; + } + break; + case CM_ABSOLUTE: + if (modify == 0) + modify = ABS_TEXT_MAX; + readin(buf, (unsigned) modify); + writeout(buf, (unsigned) modify); + spos += (int) modify; + break; + case CM_OFFSET_RELOC: + offset = readsize(relocsize); + if (modify & R_MASK) + offset -= (spos + relocsize); + offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize); + writeout(buf, relocsize); +#ifdef BSD_A_OUT + if (reloc_output) + { + u4_t bitfield; + + if (curseg == 0) + { + ++ntreloc; + offtocn(buf, spos, 4); + writetrel(buf, 4); + } + else + { + ++ndreloc; + offtocn(buf, spos - segbase[1], 4); + writedrel(buf, 4); + } + if ((modify & SEGM_MASK) == 0) + bitfield = N_TEXT; + else + bitfield = N_DATA; + if (modify & R_MASK) + bitfield |= 1L << 24; + if (relocsize == 2) + bitfield |= 1L << 25; + else if (relocsize == 4) + bitfield |= 1L << 26; + u4cn(buf, bitfield, 4); + if (curseg == 0) + writetrel(buf, 4); + else + writedrel(buf, 4); + } +#endif /* BSD_A_OUT */ + spos += relocsize; + break; + case CM_SYMBOL_RELOC: + symptr = symparray[symbolnum = readconvsize((unsigned) + (modify & S_MASK ? 2 : 1))]; + offset = readconvsize((unsigned) modify & OF_MASK); + if (modify & R_MASK) + offset -= (spos + relocsize); +#ifdef BSD_A_OUT + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif + offset += symptr->value; + offtocn(buf, offset, relocsize); + writeout(buf, relocsize); +#ifdef BSD_A_OUT + if (reloc_output) + { + u4_t bitfield; + + if (curseg == 0) + { + ++ntreloc; + offtocn(buf, spos, 4); + writetrel(buf, 4); + } + else + { + ++ndreloc; + offtocn(buf, spos - segbase[1], 4); + writedrel(buf, 4); + } + if (symptr->flags & I_MASK) + bitfield = (1L << 27) | symbolnum; + else if ((symptr->flags & SEGM_MASK) == 0) + bitfield = N_TEXT; + else if (symptr->flags & (C_MASK | SA_MASK)) + bitfield = N_BSS; + else + bitfield = N_DATA; + if (modify & R_MASK) + bitfield |= 1L << 24; + if (relocsize == 2) + bitfield |= 1L << 25; + else if (relocsize == 4) + bitfield |= 1L << 26; + u4cn(buf, bitfield, 4); + if (curseg == 0) + writetrel(buf, 4); + else + writedrel(buf, 4); + } +#endif /* BSD_A_OUT */ + spos += relocsize; + } + } +} + +PRIVATE void linkrefs(modptr) +struct modstruct *modptr; +{ + register struct symstruct **symparray; + register struct symstruct *symptr; + + modptr->loadflag = TRUE; + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr->loadflag == FALSE) + linkrefs(symptr->modptr); +} + +PRIVATE void padmod(modptr) +struct modstruct *modptr; +{ + offset_t count; + char seg; + offset_t size; + unsigned sizecount; + char *sizeptr; + + for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg) + { + size = cntooffset(sizeptr, + sizecount = segsizecount((unsigned) seg, modptr)); + sizeptr += sizecount; + if ((count = segpos[seg] - segbase[seg]) != size) + size_error(seg, count, size); + + /* pad to quad boundary */ + /* not padding in-between common areas which sometimes get into file */ + if ((size = ld_roundup(segpos[seg], 4, offset_t) - segpos[seg]) != 0) + { + setseg(seg); + writenulls(size); + segpos[seg] = spos; + } + segbase[seg] = segpos[seg]; + } +} + +PRIVATE void setsym(name, value) +char *name; +offset_t value; +{ + struct symstruct *symptr; + +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + if ((symptr = findsym(name)) != NULL) + symptr->value = value; +} + +PRIVATE void symres(name) +register char *name; +{ + register struct symstruct *symptr; + + if ((symptr = findsym(name)) != NULL) + { + if ((symptr->flags & SEGM_MASK) == SEGM_MASK) + symptr->flags &= ~SEGM_MASK | curseg; + if (symptr->flags != (I_MASK | curseg) || symptr->value != 0) + reserved(name); +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + symptr->flags = E_MASK | curseg; /* show defined, not common */ + } +} + +/* set new segment */ + +PRIVATE void setseg(newseg) +unsigned newseg; +{ + if (newseg != curseg) + { + segpos[curseg] = spos; + spos = segpos[curseg = newseg]; + seekout(FILEHEADERLENGTH + (long) spos + (long) segadj[curseg]); + } +} + +PRIVATE void skip(countsize) +unsigned countsize; +{ + writenulls((offset_t) readsize(countsize)); +} + +#ifdef EDOS + +PRIVATE void writeheader(commandname) +char *commandname; +{ + char buf[MAX_OFFSET_SIZE]; + offset_t offset; + unsigned headlength; + char *name; + struct entrylist *elptr; + struct symstruct *startptr; + + headlength = binheaderlength(commandname); + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + headlength -= 6; + offset = headlength; + startptr = findsym("start"); + offtocn(buf, edataoffset, 2); + writeout(buf, 2); + writechar(0xFF); /* dummy data length 0xFFFF takes everything */ + writechar(0xFF); + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + { + name = idconvert(elptr, commandname); + writeout(name, (unsigned) strlen(name) + 1); + ourfree(name); + offtocn(buf, startptr == NULL ? elptr->elsymptr->value : offset, 2); + writeout(buf, 2); + writechar(0x82); /* 8 = set flags from here, 2 = cmd line */ + offset += 6; /* LBSR $xxxx and LBRA $xxxx */ + } + writechar(0); + if (startptr != NULL) + { + offset = headlength + 3; /* over 1st LBSR */ + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + { + writechar(0x17); /* LBSR */ + offtocn(buf, startptr->value - offset, 2); + writeout(buf, 2); + writechar(0x16); /* LBRA */ + offtocn(buf, elptr->elsymptr->value - offset - 3, 2); + writeout(buf, 2); + offset += 6; + } + } +} + +#endif /* EDOS */ + +#ifdef MINIX + +PRIVATE void writeheader() +{ + struct exec header; + + memset(&header, 0, sizeof header); + header.a_magic[0] = A_MAGIC0; + header.a_magic[1] = A_MAGIC1; +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + { + header.a_flags = sepid ? A_SEP : A_EXEC; + if (uzp) + header.a_flags |= A_UZP; + } +#ifdef BSD_A_OUT + header.a_cpu = (bits32 || reloc_output) ? A_I80386 : A_I8086; +#else + header.a_cpu = bits32 ? A_I80386 : A_I8086; +#endif + header.a_hdrlen = FILEHEADERLENGTH; + offtocn((char *) &header.a_text, etextpadoff - btextoffset, + sizeof header.a_text); + offtocn((char *) &header.a_data, edataoffset - bdataoffset, + sizeof header.a_data); + offtocn((char *) &header.a_bss, endoffset - edataoffset, + sizeof header.a_bss); +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + { + if (uzp) + offtocn((char *) &header.a_entry, page_size(), + sizeof header.a_entry); + offtocn((char *) &header.a_total, (offset_t) + (endoffset < 0x00010000L ? 0x00010000L : endoffset + 0x0008000L), + sizeof header.a_total); + } + writeout((char *) &header, FILEHEADERLENGTH); +} + +#endif /* MINIX */ + +PRIVATE void writenulls(count) +offset_t count; +{ + spos += count; + while (count--) + writechar(0); +} diff --git a/ld/6809/config.h b/ld/6809/config.h new file mode 100644 index 0000000..dc5fed4 --- /dev/null +++ b/ld/6809/config.h @@ -0,0 +1,28 @@ +/* config.h - configuration for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +/* one of these target processors must be defined */ + +#undef I8086 /* Intel 8086 */ +#undef I80386 /* Intel 80386 */ +#define MC6809 /* Motorola 6809 */ + +/* one of these target operating systems must be defined */ + +#define EDOS /* generate EDOS executable */ +#undef MINIX /* generate Minix executable */ + +/* these may need to be defined to suit the source processor */ + +#define HOST_8BIT /* enable some 8-bit optimizations */ + +/* #define S_ALIGNMENT 4 */ /* source memory alignment, power of 2 */ + /* don't use for 8 bit processors */ + /* don't use even for 80386 - overhead for */ + /* alignment cancels improved access */ + +/* these must be defined to suit the source libraries */ + +#define CREAT_PERMS 0666 /* permissions for creat() */ +#define EXEC_PERMS 0111 /* extra permissions to set for executable */ diff --git a/ld/Makefile b/ld/Makefile new file mode 100644 index 0000000..756a25c --- /dev/null +++ b/ld/Makefile @@ -0,0 +1,18 @@ +CFLAGS =-O -DBSD_A_OUT -DSTANDARD_GNU_A_OUT +LDFLAGS =-N -s + +OBJS =dumps.o io.o ld.o readobj.o table.o typeconv.o writebin.o + +ld: $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -o $@ + +clean: + rm -f $(OBJS) ld + +dumps.o: dumps.c const.h config.h obj.h type.h globvar.h +io.o: io.c const.h config.h obj.h type.h globvar.h +ld.o: ld.c const.h config.h byteord.h type.h globvar.h +readobj.o: readobj.c const.h config.h byteord.h obj.h type.h globvar.h +table.o: table.c const.h config.h align.h obj.h type.h globvar.h +typeconv.o: typeconv.c const.h config.h type.h globvar.h +writebin.o: writebin.c const.h config.h obj.h type.h globvar.h diff --git a/ld/Makefile.minix b/ld/Makefile.minix new file mode 100644 index 0000000..7f819fa --- /dev/null +++ b/ld/Makefile.minix @@ -0,0 +1,20 @@ +CFLAGS =-O -DBSD_A_OUT +LDFLAGS = + +OBJS =dumps.o io.o ld.o readobj.o table.o typeconv.o writebin.o + +ld: $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -o $@ + chmem =232000 $@ + +clean: + rm -f $(OBJS) ld + +dumps.o: dumps.c const.h config.h obj.h type.h globvar.h +io.o: io.c const.h config.h obj.h type.h globvar.h +ld.o: ld.c const.h config.h byteord.h type.h globvar.h +readobj.o: readobj.c ar.h const.h config.h byteord.h obj.h type.h globvar.h +table.o: table.c const.h config.h align.h obj.h type.h globvar.h +typeconv.o: typeconv.c const.h config.h type.h globvar.h +writebin.o: writebin.c bsd-a.out.h a.out.gnu.h const.h config.h obj.h type.h \ + globvar.h diff --git a/ld/README.1994 b/ld/README.1994 new file mode 100644 index 0000000..669c8a8 --- /dev/null +++ b/ld/README.1994 @@ -0,0 +1,17 @@ +The `bcc' and `ld' parts of the bin86 distribution are now covered by the +GNU GPL. The next release of the `as' part will be covered by the GPL. +The `a.out.h' part is no longer used and should be deleted. The `bccfp' +belongs in another package and may be deleted. + +`ld' is now correctly ported to linux. It now defaults to the target +a.out format for output. However, it still requires its own special +format for input. It is best used as a post-processor for `as' to +produce objects in a.out format. Then the target ld can be used to +link the objects. The post-processing step is: + + ld86 -r -o tmpfile.o file.o && mv tmpfile.o file.o + +This can be handled more simply by using the `bcc' compiler driver as +the assembler and never calling as86 or ld86 directly: + + AS86="bcc -G -0 -c" diff --git a/ld/align.h b/ld/align.h new file mode 100644 index 0000000..ba33fb8 --- /dev/null +++ b/ld/align.h @@ -0,0 +1,10 @@ +/* align.h - memory alignment requirements for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#ifndef S_ALIGNMENT +# define align(x) +#else +# define align(x) ((x) = ((int) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1)) + /* assumes sizeof(int) == sizeof(char *) */ +#endif @@ -0,0 +1,17 @@ +1. Should cause error when an address which requires > 16 bits is referenced + using 16 bits. + +TODO: + integrate byteord.h with compiler as well as assembler + +TODO: + integrate align.h with compiler and assembler + use alignment for *86 like compiler - use more portable macro + ((x) + (-(int) (x) & MASK)) when it is either necessary or + faster + +TODO: + do malloc stuff better, as in compiler + +2. Error message about "foo.a is not an object file" is confusing - should + name archive member. diff --git a/ld/byteord.h b/ld/byteord.h new file mode 100644 index 0000000..57d17b9 --- /dev/null +++ b/ld/byteord.h @@ -0,0 +1,20 @@ +/* byteord.h - byte order dependencies for C compiler, assembler, linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +/* These are for the targets of everything and for linker source too. */ + +#ifdef I8086 +# define BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ +#endif + +#ifdef I80386 +# define BIG_ENDIAN 0 +# define LONG_BIG_ENDIAN 0 +#endif + +#ifdef MC6809 +# define BIG_ENDIAN 1 /* byte order in words is high-low */ +# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ +#endif diff --git a/ld/config.h b/ld/config.h new file mode 100644 index 0000000..201c153 --- /dev/null +++ b/ld/config.h @@ -0,0 +1,28 @@ +/* config.h - configuration for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +/* one of these target processors must be defined */ + +#undef I8086 /* Intel 8086 */ +#define I80386 /* Intel 80386 */ +#undef MC6809 /* Motorola 6809 */ + +/* one of these target operating systems must be defined */ + +#undef EDOS /* generate EDOS executable */ +#define MINIX /* generate Minix executable */ + +/* these may need to be defined to suit the source processor */ + +#undef HOST_8BIT /* enable some 8-bit optimizations */ + +/* #define S_ALIGNMENT 4 */ /* source memory alignment, power of 2 */ + /* don't use for 8 bit processors */ + /* don't use even for 80386 - overhead for */ + /* alignment cancels improved access */ + +/* these must be defined to suit the source libraries */ + +#define CREAT_PERMS 0666 /* permissions for creat() */ +#define EXEC_PERMS 0111 /* extra permissions to set for executable */ diff --git a/ld/const.h b/ld/const.h new file mode 100644 index 0000000..7705e15 --- /dev/null +++ b/ld/const.h @@ -0,0 +1,14 @@ +/* const.h - constants for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#define FALSE 0 +#define NULL 0 +#define TRUE 1 + +#define EXTERN extern +#define FORWARD static +#define PRIVATE static +#define PUBLIC + +#include "config.h" diff --git a/ld/dumps.c b/ld/dumps.c new file mode 100644 index 0000000..5027fac --- /dev/null +++ b/ld/dumps.c @@ -0,0 +1,68 @@ +/* dumps.c - print data about symbols and modules for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#include "const.h" +#include "obj.h" +#include "type.h" +#include "globvar.h" + +/* print list of modules and whether they are loaded */ + +PUBLIC void dumpmods() +{ + struct modstruct *modptr; + + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + { + putstr(modptr->loadflag ? "L " : " "); + putbstr(20, modptr->modname); + putbyte('\n'); + } +} + +/* print data about symbols (in loaded modules only) */ + +PUBLIC void dumpsyms() +{ + flags_t flags; + struct modstruct *modptr; + struct symstruct **symparray; + struct symstruct *symptr; + char uflag; + + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr) + { + uflag = FALSE; + if (((flags = symptr->flags) & (C_MASK | I_MASK)) == I_MASK) + uflag = TRUE; + putbstr(20, uflag ? "" : modptr->modname); + putstr(" "); + putbstr(20, symptr->name); + putstr(" "); + putbyte(hexdigit[flags & SEGM_MASK]); + putstr(" "); + if (uflag) + putstr(" "); + else +#ifdef LONG_OFFSETS + put08lx(symptr->value); +#else + put08x(symptr->value); +#endif + putstr(flags & A_MASK ? " A" : " R"); + if (uflag) + putstr(" U"); + if (flags & C_MASK) + putstr(" C"); + if (flags & N_MASK) + putstr(" N"); + putbyte('\n'); + } + } +} diff --git a/ld/globvar.h b/ld/globvar.h new file mode 100644 index 0000000..0351a6b --- /dev/null +++ b/ld/globvar.h @@ -0,0 +1,14 @@ +/* globvar.h - global variables for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#ifdef EXTERN +EXTERN char hexdigit[]; +#else +#define EXTERN +PUBLIC char hexdigit[] = "0123456789abcdef"; +#endif +EXTERN unsigned errcount; /* count of errors */ +EXTERN struct entrylist *entryfirst; /* first on list of entry symbols */ +EXTERN struct modstruct *modfirst; /* data for 1st module */ +EXTERN struct redlist *redfirst; /* first on list of redefined symbols */ @@ -0,0 +1,606 @@ +/* io.c - input/output and error modules for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#include "const.h" +#include "obj.h" /* needed for LONG_OFFSETS and offset_t */ +#include "type.h" +#include "globvar.h" + +#ifdef STDC_HEADERS_MISSING +void exit P((int status)); +void *malloc P((unsigned size)); +#else +#undef NULL +#include <stdlib.h> +#endif + +#ifdef POSIX_HEADERS_MISSING +#define O_RDONLY 0 +#define O_WRONLY 1 +#define SEEK_SET 0 +#define STDOUT_FILENO 0 +#include <sys/stat.h> +#define mode_t unsigned short +#define off_t long +int chmod P((const char *path, int mode)); +int close P((int fd)); +int creat P((const char *path, int mode)); +int fstat P((int fd, struct stat *statbuf)); +off_t lseek P((int fd, off_t offset, int whence)); +int open P((const char *path, int oflag, ...)); +int read P((int fd, void *buf, unsigned nbytes)); +mode_t umask P((int oldmask)); +int write P((int fd, const void *buf, unsigned nbytes)); +#else +#undef NULL +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#endif + +#define DRELBUFSIZE 3072 +#define ERR (-1) +#define ERRBUFSIZE 1024 +#define INBUFSIZE 1024 +#define OUTBUFSIZE 2048 +#define TRELBUFSIZE 1024 + +#ifdef BSD_A_OUT +PRIVATE char *drelbuf; /* extra output buffer for data relocations */ +PRIVATE char *drelbufptr; /* data relocation output buffer ptr */ +PRIVATE char *drelbuftop; /* data relocation output buffer top */ +#endif +PRIVATE char *errbuf; /* error buffer (actually uses STDOUT) */ +PRIVATE char *errbufptr; /* error buffer ptr */ +PRIVATE char *errbuftop; /* error buffer top */ +PRIVATE char *inbuf; /* input buffer */ +PRIVATE char *inbufend; /* input buffer top */ +PRIVATE char *inbufptr; /* end of input in input buffer */ +PRIVATE int infd; /* input file descriptor */ +PRIVATE char *inputname; /* name of current input file */ +PRIVATE char *outbuf; /* output buffer */ +PRIVATE char *outbufptr; /* output buffer ptr */ +PRIVATE char *outbuftop; /* output buffer top */ +PRIVATE int outfd; /* output file descriptor */ +PRIVATE mode_t outputperms; /* permissions of output file */ +PRIVATE char *outputname; /* name of output file */ +PRIVATE char *refname; /* name of program for error reference */ +#ifdef BSD_A_OUT +PRIVATE char *trelbuf; /* extra output buffer for text relocations */ +PRIVATE char *trelbufptr; /* text relocation output buffer ptr */ +PRIVATE char *trelbuftop; /* text relocation output buffer top */ +PRIVATE int trelfd; /* text relocation output file descriptor */ +#endif +PRIVATE unsigned warncount; /* count of warnings */ + +FORWARD void errexit P((char *message)); +FORWARD void flushout P((void)); +#ifdef BSD_A_OUT +FORWARD void flushtrel P((void)); +#endif +FORWARD void outhexdigs P((offset_t num)); +FORWARD void outputerror P((char *message)); +FORWARD void put04x P((unsigned num)); +FORWARD void putstrn P((char *message)); +FORWARD void refer P((void)); + +PUBLIC void ioinit(progname) +char *progname; +{ + infd = ERR; + if (*progname) + refname = progname; /* name must be static (is argv[0]) */ + else + refname = "link"; +#ifdef BSD_A_OUT + drelbuf = malloc(DRELBUFSIZE); + drelbuftop = drelbuf + DRELBUFSIZE; +#endif + errbuf = malloc(ERRBUFSIZE); + errbufptr = errbuf; + errbuftop = errbuf + ERRBUFSIZE; + inbuf = malloc(INBUFSIZE); + outbuf = malloc(OUTBUFSIZE);/* outbuf invalid if this fails but then */ + /* will not be used - tableinit() aborts */ + outbuftop = outbuf + OUTBUFSIZE; +#ifdef BSD_A_OUT + trelbuf = malloc(TRELBUFSIZE); + trelbuftop = trelbuf + TRELBUFSIZE; +#endif +} + +PUBLIC void closein() +{ + if (infd != ERR && close(infd) < 0) + inputerror("cannot close"); + infd = ERR; +} + +PUBLIC void closeout() +{ +#ifdef BSD_A_OUT + unsigned nbytes; +#endif + + flushout(); +#ifdef BSD_A_OUT + flushtrel(); + nbytes = drelbufptr - drelbuf; + if (write(trelfd, drelbuf, nbytes) != nbytes) + outputerror("cannot write"); +#endif + if (close(outfd) == ERR) + outputerror("cannot close"); +#ifdef BSD_A_OUT + if (close(trelfd) == ERR) + outputerror("cannot close"); +#endif +} + +PUBLIC void errtrace(name, level) +char *name; +int level; +{ + while (level-- > 0) + putbyte(' '); + putstrn(name); +} + +PUBLIC void executable() +{ + mode_t oldmask; + + if (errcount == 0) + { + oldmask = umask(0); + umask(oldmask); + chmod(outputname, outputperms | (EXEC_PERMS & ~oldmask)); + } +} + +PUBLIC void flusherr() +{ + write(STDOUT_FILENO, errbuf, (unsigned) (errbufptr - errbuf)); + errbufptr = errbuf; +} + +PRIVATE void flushout() +{ + unsigned nbytes; + + nbytes = outbufptr - outbuf; + if (write(outfd, outbuf, nbytes) != nbytes) + outputerror("cannot write"); + outbufptr = outbuf; +} + +#ifdef BSD_A_OUT +PRIVATE void flushtrel() +{ + unsigned nbytes; + + nbytes = trelbufptr - trelbuf; + if (write(trelfd, trelbuf, nbytes) != nbytes) + outputerror("cannot write"); + trelbufptr = trelbuf; +} +#endif + +PUBLIC void openin(filename) +char *filename; +{ +#if 0 /* XXX - this probably won't work with constructed lib names? */ + if (infd == ERR || strcmp(inputname, filename) != 0) +#endif + { + closein(); + inputname = filename; /* this relies on filename being static */ + if ((infd = open(filename, O_RDONLY)) < 0) + inputerror("cannot open"); + inbufptr = inbufend = inbuf; + } +} + +PUBLIC void openout(filename) +char *filename; +{ + struct stat statbuf; + + outputname = filename; + if ((outfd = creat(filename, CREAT_PERMS)) == ERR) + outputerror("cannot open"); + if (fstat(outfd, &statbuf) != 0) + outputerror("cannot stat"); + outputperms = statbuf.st_mode; + chmod(filename, outputperms & ~EXEC_PERMS); +#ifdef BSD_A_OUT + drelbufptr = drelbuf; +#endif + outbufptr = outbuf; +#ifdef BSD_A_OUT + if ((trelfd = open(filename, O_WRONLY)) == ERR) + outputerror("cannot reopen"); + trelbufptr = trelbuf; +#endif +} + +PRIVATE void outhexdigs(num) +register offset_t num; +{ + if (num >= 0x10) + { + outhexdigs(num / 0x10); + num %= 0x10; + } + putbyte(hexdigit[num]); +} + +PRIVATE void put04x(num) +register unsigned num; +{ + putbyte(hexdigit[num / 0x1000]); + putbyte(hexdigit[(num / 0x100) & 0x0F]); + putbyte(hexdigit[(num / 0x10) & 0x0F]); + putbyte(hexdigit[num & 0x0F]); +} + +#ifdef LONG_OFFSETS + +PUBLIC void put08lx(num) +register offset_t num; +{ + put04x(num / 0x10000); + put04x(num % 0x10000); +} + +#else /* not LONG_OFFSETS */ + +PUBLIC void put08x(num) +register offset_t num; +{ + putstr("0000"); + put04x(num); +} + +#endif /* not LONG_OFFSETS */ + +PUBLIC void putbstr(width, str) +unsigned width; +char *str; +{ + unsigned length; + + for (length = strlen(str); length < width; ++length) + putbyte(' '); + putstr(str); +} + +PUBLIC void putbyte(ch) +int ch; +{ + register char *ebuf; + + ebuf = errbufptr; + if (ebuf >= errbuftop) + { + flusherr(); + ebuf = errbufptr; + } + *ebuf++ = ch; + errbufptr = ebuf; +} + +PUBLIC void putstr(message) +char *message; +{ + while (*message != 0) + putbyte(*message++); +} + +PRIVATE void putstrn(message) +char *message; +{ + putstr(message); + putbyte('\n'); + flusherr(); +} + +PUBLIC int readchar() +{ + int ch; + + register char *ibuf; + int nread; + + ibuf = inbufptr; + if (ibuf >= inbufend) + { + ibuf = inbufptr = inbuf; + nread = read(infd, ibuf, INBUFSIZE); + if (nread <= 0) + { + inbufend = ibuf; + return ERR; + } + inbufend = ibuf + nread; + } + ch = (unsigned char) *ibuf++; + inbufptr = ibuf; + return ch; +} + +PUBLIC void readin(buf, count) +char *buf; +unsigned count; +{ + int ch; + + while (count--) + { + if ((ch = readchar()) < 0) + prematureeof(); + *buf++ = ch; + } +} + +PUBLIC bool_pt readineofok(buf, count) +char *buf; +unsigned count; +{ + int ch; + + while (count--) + { + if ((ch = readchar()) < 0) + return TRUE; + *buf++ = ch; + } + return FALSE; +} + +PUBLIC void seekin(offset) +unsigned long offset; +{ + inbufptr = inbufend = inbuf; + if (lseek(infd, (off_t) offset, SEEK_SET) != offset) + prematureeof(); +} + +PUBLIC void seekout(offset) +unsigned long offset; +{ + flushout(); + if (lseek(outfd, (off_t) offset, SEEK_SET) != offset) + outputerror("cannot seek in"); +} + +#ifdef BSD_A_OUT +PUBLIC void seektrel(offset) +unsigned long offset; +{ + flushtrel(); + if (lseek(trelfd, (off_t) offset, SEEK_SET) != offset) + outputerror("cannot seek in"); +} +#endif + +PUBLIC void writechar(ch) +int ch; +{ + register char *obuf; + + obuf = outbufptr; + if (obuf >= outbuftop) + { + flushout(); + obuf = outbufptr; + } + *obuf++ = ch; + outbufptr = obuf; +} + +#ifdef BSD_A_OUT +PUBLIC void writedrel(buf, count) +register char *buf; +unsigned count; +{ + register char *rbuf; + + rbuf = drelbufptr; + while (count--) + { + if (rbuf >= drelbuftop) + inputerror("data relocation buffer full while processing"); + *rbuf++ = *buf++; + } + drelbufptr = rbuf; +} +#endif + +PUBLIC void writeout(buf, count) +register char *buf; +unsigned count; +{ + register char *obuf; + + obuf = outbufptr; + while (count--) + { + if (obuf >= outbuftop) + { + outbufptr = obuf; + flushout(); + obuf = outbufptr; + } + *obuf++ = *buf++; + } + outbufptr = obuf; +} + +#ifdef BSD_A_OUT +PUBLIC void writetrel(buf, count) +register char *buf; +unsigned count; +{ + register char *rbuf; + + rbuf = trelbufptr; + while (count--) + { + if (rbuf >= trelbuftop) + { + trelbufptr = rbuf; + flushtrel(); + rbuf = trelbufptr; + } + *rbuf++ = *buf++; + } + trelbufptr = rbuf; +} +#endif + +/* error module */ + +PRIVATE void errexit(message) +char *message; +{ + putstrn(message); + exit(2); +} + +PUBLIC void fatalerror(message) +char *message; +{ + refer(); + errexit(message); +} + +PUBLIC void inputerror(message) +char *message; +{ + refer(); + putstr(message); + putstr(" input file "); + errexit(inputname); +} + +PUBLIC void input1error(message) +char *message; +{ + refer(); + putstr(inputname); + errexit(message); +} + +PRIVATE void outputerror(message) +char *message; +{ + refer(); + putstr(message); + putstr(" output file "); + errexit(outputname); +} + +PUBLIC void outofmemory() +{ + inputerror("out of memory while processing"); +} + +PUBLIC void prematureeof() +{ + inputerror("premature end of"); +} + +PUBLIC void redefined(name, message, archentry, deffilename, defarchentry) +char *name; +char *message; +char *archentry; +char *deffilename; +char *defarchentry; +{ + ++warncount; + refer(); + putstr("warning: "); + putstr(name); + putstr(" redefined"); + putstr(message); + putstr(" in file "); + putstr(inputname); + if (archentry != NULL) + { + putbyte('('); + putstr(archentry); + putbyte(')'); + } + putstr("; using definition in "); + putstr(deffilename); + if (defarchentry != NULL) + { + putbyte('('); + putstr(defarchentry); + putbyte(')'); + } + putbyte('\n'); +} + +PRIVATE void refer() +{ + putstr(refname); + putstr(": "); +} + +PUBLIC void reserved(name) +char *name; +{ + ++errcount; + putstr("incorrect use of reserved symbol: "); + putstrn(name); +} + +PUBLIC void size_error(seg, count, size) +char seg; +offset_t count; +offset_t size; +{ + refer(); + putstr("seg "); + outhexdigs((offset_t) seg); + putstr(" has wrong size "); + outhexdigs(count); + putstr(", supposed to be "); + outhexdigs(size); + errexit("\n"); +} + +PUBLIC void undefined(name) +char *name; +{ + ++errcount; + putstr("undefined symbol: "); + putstrn(name); +} + +PUBLIC void usage() +{ + putstr("usage: "); + putstr(refname); +#ifdef BSD_A_OUT + errexit("\ + [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\ + [-Llibdir] [-Olibfile] [-T textaddr] infile..."); +#else + errexit("\ + [-03Mimstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\ + [-Llibdir] [-Olibfile] [-T textaddr] infile..."); +#endif +} + +PUBLIC void use_error(message) +char *message; +{ + refer(); + putstrn(message); + usage(); +} @@ -0,0 +1,187 @@ +/* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */ + +/* Copyright (C) 1994 Bruce Evans */ + +#include "const.h" +#include "byteord.h" +#include "type.h" +#include "globvar.h" + +#ifdef STDC_HEADERS_MISSING +extern int errno; +char *strcat P((char *dest, const char *src)); +unsigned long strtoul P((const char *s, char **endptr, int base)); +#else +#undef NULL +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#endif + +#ifdef POSIX_HEADERS_MISSING +#define R_OK 0 +int access P((const char *path, int amode)); +#else +#undef NULL +#include <unistd.h> +#endif + +#define MAX_LIBS (NR_STDLIBS + 5) +#define NR_STDLIBS 1 + +PUBLIC long text_base_address; /* XXX */ + +PRIVATE bool_t flag[128]; +PRIVATE char *libs[MAX_LIBS] = { +#ifdef MC6809 + "/usr/local/lib/m09/", +#else + /* One of the following values will be inserted at run time. */ +# define std386lib "/usr/local/lib/i386/" +# define std86lib "/usr/local/lib/i86/" +#endif + 0 +}; +PRIVATE int lastlib = NR_STDLIBS; + +FORWARD char *buildname P((char *pre, char *mid, char *suf)); +FORWARD char *expandlib P((char *fn)); + +PRIVATE char *buildname(pre, mid, suf) +char *pre; +char *mid; +char *suf; +{ + char *name; + + name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1); + strcpy(name, pre); + strcat(name, mid); + strcat(name, suf); + return name; +} + +PRIVATE char *expandlib(fn) +char *fn; +{ + char *path; + int i; + +#ifndef MC6809 + libs[0] = flag['3'] ? std386lib : std86lib; +#endif + + for (i = lastlib - 1; i >= 0; --i) + { + path = ourmalloc(strlen(libs[i]) + strlen(fn) + 1); + strcpy(path, libs[i]); + strcat(path, fn); + if (access(path, R_OK) == 0) + return path; + ourfree(path); + } + return NULL; +} + +PUBLIC int main(argc, argv) +int argc; +char **argv; +{ + register char *arg; + int argn; + static char crtprefix[] = "crt"; + static char crtsuffix[] = ".o"; + char *infilename; + static char libprefix[] = "lib"; + static char libsuffix[] = ".a"; + char *outfilename; + char *tfn; + + ioinit(argv[0]); + objinit(); + syminit(); + typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN); +#ifndef MC6809 + flag['z'] = flag['3'] = sizeof(char *) >= 4; +#endif + outfilename = NULL; + for (argn = 1; argn < argc; ++argn) + { + arg = argv[argn]; + if (*arg != '-') + readsyms(arg, flag['t']); + else + switch (arg[1]) + { + case '0': /* use 16-bit libraries */ + case '3': /* use 32-bit libraries */ + case 'M': /* print symbols linked */ + case 'i': /* separate I & D output */ + case 'm': /* print modules linked */ +#ifdef BSD_A_OUT + case 'r': /* relocatable output */ +#endif + case 's': /* strip symbols */ + case 't': /* trace modules linked */ + case 'z': /* unmapped zero page */ + if (arg[2] == 0) + flag[(int) arg[1]] = TRUE; + else if (arg[2] == '-' && arg[3] == 0) + flag[(int) arg[1]] = FALSE; + else + usage(); + if (arg[1] == '0') /* flag 0 is negative logic flag 3 */ + flag['3'] = !flag['0']; + break; + case 'C': /* startfile name */ + tfn = buildname(crtprefix, arg + 2, crtsuffix); + if ((infilename = expandlib(tfn)) == NULL) + fatalerror(tfn); /* XXX - need to describe failure */ + readsyms(infilename, flag['t']); + break; + case 'L': /* library path */ + if (lastlib < MAX_LIBS) + libs[lastlib++] = arg + 2; + else + fatalerror("too many library paths"); + break; + case 'O': /* library file name */ + if ((infilename = expandlib(arg + 2)) == NULL) + fatalerror(arg); /* XXX */ + readsyms(infilename, flag['t']); + break; + case 'T': /* text base address */ + if (arg[2] != 0 || ++argn >= argc) + usage(); + errno = 0; + text_base_address = strtoul(argv[argn], (char **) NULL, 16); + if (errno != 0) + use_error("invalid text address"); + break; + case 'l': /* library name */ + tfn = buildname(libprefix, arg + 2, libsuffix); + if ((infilename = expandlib(tfn)) == NULL) + fatalerror(tfn); /* XXX */ + readsyms(infilename, flag['t']); + break; + case 'o': /* output file name */ + if (arg[2] != 0 || ++argn >= argc || outfilename != NULL) + usage(); + outfilename = argv[argn]; + break; + default: + usage(); + } + } + linksyms(flag['r']); + if (outfilename == NULL) + outfilename = "a.out"; + writebin(outfilename, flag['i'], flag['3'], flag['s'], + flag['z'] & flag['3']); + if (flag['m']) + dumpmods(); + if (flag['M']) + dumpsyms(); + flusherr(); + return errcount ? 1 : 0; +} diff --git a/ld/obj.h b/ld/obj.h new file mode 100644 index 0000000..e0a52dc --- /dev/null +++ b/ld/obj.h @@ -0,0 +1,54 @@ +/* obj.h - constants for Introl object modules */ + +/* Copyright (C) 1994 Bruce Evans */ + +#define OBJ_H + +#ifdef I80386 +# define LONG_OFFSETS /* others can use this, but wasteful */ +#endif + +#ifndef OMAGIC +# ifdef I80386 +# define OMAGIC 0x86A3 +# endif + +# ifdef I8086 +# define OMAGIC 0x86A0 +# endif + +# ifdef MC6809 +# define OMAGIC 0x5331 +# endif +#endif + +#ifdef LONG_OFFSETS +# define cntooffset cnu4 +# define offtocn u4cn +#else +# define cntooffset cnu2 +# define offtocn u2cn +#endif + +#ifdef MC6809 /* temp don't support alignment at all */ +# define roundup( num, boundary, type ) (num) +#else +# define roundup( num, boundary, type ) \ + (((num) + ((boundary) - 1)) & (type) ~((boundary) - 1)) +#endif + +#define MAX_OFFSET_SIZE 4 +#define NSEG 16 + +/* flag values |SZ|LXXXX|N|E|I|R|A|SEGM|, X not used */ + +#define A_MASK 0x0010 /* absolute */ +#define C_MASK 0x0020 /* common (internal only) */ +#define E_MASK 0x0080 /* exported */ +#define I_MASK 0x0040 /* imported */ +#define N_MASK 0x0100 /* entry point */ +#define R_MASK 0x0020 /* relative (in text only) */ +#define SEGM_MASK 0x000F /* segment (if not absolute) */ +#define SA_MASK 0x2000 /* offset is storage allocation */ +#define SZ_MASK 0xC000 /* size descriptor for value */ +#define SZ_SHIFT 14 diff --git a/ld/readobj.c b/ld/readobj.c new file mode 100644 index 0000000..791436f --- /dev/null +++ b/ld/readobj.c @@ -0,0 +1,374 @@ +/* readobj.c - read object file for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#include "ar.h" /* maybe local copy of <ar.h> for cross-link */ +#include "const.h" +#include "byteord.h" +#include "obj.h" +#include "type.h" +#include "globvar.h" + +#ifdef STDC_HEADERS_MISSING +int strncmp P((const char *s1, const char *s2, unsigned n)); +char *strncpy P((char *dest, const char *src, unsigned n)); +unsigned long strtoul P((const char *s, char **endptr, int base)); +#else +#undef NULL +#include <stdlib.h> +#include <string.h> +#endif + +/* + Linking takes 2 passes. The 1st pass reads through all files specified +in the command line, and all libraries. All public symbols are extracted +and stored in a chained hash table. For each module, its file and header +data recorded, and the resulting structures are chained together +(interleaved with the symbols). + + The symbol descriptors are separated from the symbol names, so we must +record all the descriptors of a module before putting the symbols in the +symbol table (poor design). The descriptors are stored in the symbol +table, then moved to the top of the table to make room for the symols. +The symbols referred to in a given module are linked together by a chain +beginning in the module descriptor. +*/ + +PRIVATE unsigned convertsize[NSEG / 4] = {0, 1, 2, 4}; +PRIVATE struct entrylist *entrylast; /* last on list of entry symbols */ +PRIVATE struct redlist *redlast; /* last on list of redefined symbols */ +PRIVATE struct modstruct *modlast; /* data for last module */ + +FORWARD long readarheader P((char **parchentry)); +FORWARD unsigned readfileheader P((void)); +FORWARD void readmodule P((char *filename, char *archentry)); +FORWARD void reedmodheader P((void)); +FORWARD bool_pt redsym P((struct symstruct *symptr, offset_t value)); +FORWARD unsigned checksum P((char *string, unsigned length)); +FORWARD unsigned segbits P((unsigned seg, char *sizedesc)); + +/* initialise object file handler */ + +PUBLIC void objinit() +{ + modfirst = modlast = NULL; + entryfirst = entrylast = NULL; + redfirst = redlast = NULL; +} + +/* read all symbol definitions in an object file */ + +PUBLIC void readsyms(filename, trace) +char *filename; +bool_pt trace; +{ + char *archentry; + long filelength; + char filemagic[SARMAG]; + unsigned long filepos; + unsigned modcount; + + if (trace) + errtrace(filename, 0); + openin(filename); /* input is not open, so position is start */ + switch ((unsigned) readsize(2)) + { + case OMAGIC: + seekin((unsigned long) 0); + for (modcount = readfileheader(); modcount-- != 0;) + readmodule(filename, (char *) NULL); + break; + default: + seekin((unsigned long) 0); + readin(filemagic, sizeof filemagic); + if (strncmp(filemagic, ARMAG, sizeof filemagic) != 0) + input1error(" has bad magic number"); + filepos = SARMAG; + while ((filelength = readarheader(&archentry)) > 0) + { + if (trace) + errtrace(archentry, 2); + filepos += sizeof(struct ar_hdr); + for (modcount = readfileheader(); modcount-- != 0;) + { + readmodule(stralloc(filename), archentry); + modlast->textoffset += filepos; + } + seekin(filepos += roundup(filelength, 2, long)); + } + break; + } + closein(); +} + +/* read archive header and return length */ + +PRIVATE long readarheader(parchentry) +char **parchentry; +{ + struct ar_hdr arheader; + char *endptr; + char *nameptr; + + if (readineofok((char *) &arheader, sizeof arheader)) + return 0; + strncpy (*parchentry = nameptr = ourmalloc(sizeof arheader.ar_name + 1), + arheader.ar_name, sizeof arheader.ar_name); + endptr = nameptr + sizeof arheader.ar_name; + do + *endptr = 0; + while (endptr > nameptr && *--endptr == ' '); + return strtoul(arheader.ar_size, (char **) NULL, 0); +} + +/* read and check file header of the object file just opened */ + +PRIVATE unsigned readfileheader() +{ + struct + { + char magic[2]; + char count[2]; /* really an int */ + } + fileheader; + char filechecksum; /* part of fileheader but would unalign */ + + readin((char *) &fileheader, sizeof fileheader); + readin(&filechecksum, sizeof filechecksum); + if (filechecksum != checksum((char *) &fileheader, sizeof fileheader)) + input1error(" is not an object file"); + return c2u2(fileheader.count); +} + +/* read the next module */ + +PRIVATE void readmodule(filename, archentry) +char *filename; +char *archentry; +{ + struct symdstruct /* to save parts of symbol before name known */ + { + offset_t dvalue; + flags_t dflags; + }; + struct symdstruct *endsymdptr; + flags_t flags; + unsigned nsymbol; + struct symdstruct *symdptr; + char *symname; + struct symstruct **symparray; + struct symstruct *symptr; + + reedmodheader(); + modlast->filename = filename; + modlast->archentry = archentry; + nsymbol = readsize(2); + symdptr = (struct symdstruct *) + ourmalloc(nsymbol * sizeof(struct symdstruct)); + for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; ++symdptr) + { + readsize(2); /* discard string offset, assume strings seq */ + symdptr->dflags = flags = readsize(2); + symdptr->dvalue = readconvsize((flags & SZ_MASK) >> SZ_SHIFT); + /* NB unsigned flags to give logical shift */ + /* bug in Xenix 2.5 cc causes (int) of the */ + /* argument to turn flags into an int */ + } + symdptr = (struct symdstruct *) + moveup(nsymbol * sizeof(struct symdstruct)); + modlast->symparray = symparray = (struct symstruct **) + ourmalloc((nsymbol + 1) * sizeof(struct symstruct *)); + symname = readstring(); /* module name */ + modlast->modname = stralloc(symname); /* likely OK overlapped copy */ + for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; + *symparray++ = symptr, release((char *) ++symdptr)) + { + symname = readstring(); + if ((flags = symdptr->dflags) & (E_MASK | I_MASK) && + (symptr = findsym(symname)) != NULL) + { + /* + weaken segment-checking by letting the maximum segment + (SEGM_MASK) mean any segment + */ + if ((symptr->flags & SEGM_MASK) == SEGM_MASK) + symptr->flags &= ~(flags_t) SEGM_MASK | (flags & SEGM_MASK); + else if ((flags & SEGM_MASK) == SEGM_MASK) + flags &= ~(flags_t) SEGM_MASK | (symptr->flags & SEGM_MASK); + if ((flags ^ symptr->flags) & (N_MASK | A_MASK | SEGM_MASK)) + { + redefined(symname, " with different segment or relocatability", + archentry, symptr->modptr->filename, + symptr->modptr->archentry); + continue; + } + if (symptr->flags & E_MASK) + { + if (flags & E_MASK && redsym(symptr, symdptr->dvalue)) + redefined(symname, "", archentry, symptr->modptr->filename, + symptr->modptr->archentry); + continue; + } + if (flags & I_MASK && symdptr->dvalue <= symptr->value) + continue; + } + else + symptr = addsym(symname); + symptr->modptr = modlast; + symptr->value = symdptr->dvalue; + symptr->flags = flags; + if (flags & N_MASK) + entrysym(symptr); + } + *symparray = NULL; +} + +/* put symbol on entry symbol list if it is not already */ + +PUBLIC void entrysym(symptr) +struct symstruct *symptr; +{ + register struct entrylist *elptr; + + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + if (symptr == elptr->elsymptr) + return; + elptr = (struct entrylist *) ourmalloc(sizeof(struct entrylist)); + elptr->elnext = NULL; + elptr->elsymptr = symptr; + if (entryfirst == NULL) + entryfirst = elptr; + else + entrylast->elnext = elptr; + entrylast = elptr; +} + +/* read the header of the next module */ + +PRIVATE void reedmodheader() +{ + struct + { + char htextoffset[4]; /* offset to module text in file */ + char htextsize[4]; /* size of text (may be 0 for last mod) */ + char stringssize[2]; /* size of string area */ + char hclass; /* module class */ + char revision; /* module revision */ + } + modheader; + unsigned seg; + unsigned count; + char *cptr; + struct modstruct *modptr; + + readin((char *) &modheader, sizeof modheader); + modptr = (struct modstruct *) ourmalloc(sizeof(struct modstruct)); + modptr->modnext = NULL; + modptr->textoffset = c4u4(modheader.htextoffset); + modptr->class = modheader.hclass; + readin(modptr->segmaxsize, sizeof modptr->segmaxsize); + readin(modptr->segsizedesc, sizeof modptr->segsizedesc); + cptr = modptr->segsize; + for (seg = 0; seg < NSEG; ++seg) + { + if ((count = segsizecount(seg, modptr)) != 0) + { + if (cptr == modptr->segsize) + ourmalloc(count - 1); /* 1st byte reserved in struct */ + else + ourmalloc(count); + readin(cptr, count); + cptr += count; + } + } + if (modfirst == NULL) + modfirst = modptr; + else + modlast->modnext = modptr; + modlast = modptr; +} + +PRIVATE bool_pt redsym(symptr, value) +register struct symstruct *symptr; +offset_t value; +{ + register struct redlist *rlptr; + char class; + + if (symptr->modptr->class != (class = modlast->class)) + for (rlptr = redfirst;; rlptr = rlptr->rlnext) + { + if (rlptr == NULL) + { + rlptr = (struct redlist *) + ourmalloc(sizeof(struct redlist)); + rlptr->rlnext = NULL; + rlptr->rlsymptr = symptr; + if (symptr->modptr->class < class) + /* prefer lower class - put other on redlist */ + { + rlptr->rlmodptr = modlast; + rlptr->rlvalue = value; + } + else + { + rlptr->rlmodptr = symptr->modptr; + symptr->modptr = modlast; + rlptr->rlvalue = symptr->value; + symptr->value = value; + } + if (redfirst == NULL) + redfirst = rlptr; + else + redlast->rlnext = rlptr; + redlast = rlptr; + return FALSE; + } + if (symptr == rlptr->rlsymptr && class == rlptr->rlmodptr->class) + break; + } + return TRUE; +} + +PRIVATE unsigned checksum(string, length) +char *string; +unsigned length; +{ + unsigned char sum; /* this is a 1-byte checksum */ + + for (sum = 0; length-- != 0;) + sum += *string++ & 0xFF; + return sum; +} + +PUBLIC offset_t readconvsize(countindex) +unsigned countindex; +{ + return readsize(convertsize[countindex]); +} + +PUBLIC offset_t readsize(count) +unsigned count; +{ + char buf[MAX_OFFSET_SIZE]; + + if (count == 0) + return 0; + readin(buf, count); + return cntooffset(buf, count); +} + +PRIVATE unsigned segbits(seg, sizedesc) +unsigned seg; +char *sizedesc; +{ + return 3 & ((unsigned) sizedesc[((NSEG - 1) - seg) / 4] >> (2 * (seg % 4))); + /* unsigned to give logical shift */ +} + +PUBLIC unsigned segsizecount(seg, modptr) +unsigned seg; +struct modstruct *modptr; +{ + return convertsize[segbits(seg, modptr->segsizedesc)]; +} diff --git a/ld/table.c b/ld/table.c new file mode 100644 index 0000000..5260741 --- /dev/null +++ b/ld/table.c @@ -0,0 +1,205 @@ +/* table.c - table-handler module for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#include "const.h" +#include "align.h" +#include "obj.h" +#include "type.h" +#include "globvar.h" + +#ifdef STDC_HEADERS_MISSING +void *malloc P((unsigned size)); +#else +#undef NULL +#include <stdlib.h> +#endif + +#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */ +#define HASHTABSIZE 256 + +PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* hash table */ +PRIVATE char *tableptr; /* next free spot in catchall table */ +PRIVATE char *tableend; /* ptr to spot after last in table */ + +FORWARD struct symstruct **gethashptr P((char *name)); + +/* initialise symbol table */ + +PUBLIC void syminit() +{ + unsigned i; + + for (i = sizeof(int) <= 2 ? 0xE000 : (unsigned) 0x38000; + i != 0; i -= 512) + if ((tableptr = malloc(i)) != NULL) + break; + if (tableptr == NULL) + outofmemory(); + tableend = tableptr + i; + for (i = 0; i < HASHTABSIZE; i++) + hashtab[i] = NULL; +} + +/* add named symbol to end of table - initialise only name and next fields */ +/* caller must not duplicate names of externals for findsym() to work */ + +PUBLIC struct symstruct *addsym(name) +char *name; +{ + struct symstruct **hashptr; + struct symstruct *oldsymptr; + struct symstruct *symptr; + + hashptr = gethashptr(name); + symptr = *hashptr; + while (symptr != NULL) + { + oldsymptr = symptr; + symptr = symptr->next; + } + align(tableptr); + symptr = (struct symstruct *) tableptr; + if ((tableptr = symptr->name + (strlen(name) + 1)) > tableend) + outofmemory(); + symptr->modptr = NULL; + symptr->next = NULL; + if (name != symptr->name) + strcpy(symptr->name, name); /* should't happen */ + if (*hashptr == NULL) + *hashptr = symptr; + else + oldsymptr->next = symptr; + return symptr; +} + +/* lookup named symbol */ + +PUBLIC struct symstruct *findsym(name) +char *name; +{ + struct symstruct *symptr; + + symptr = *gethashptr(name); + while (symptr != NULL && (!(symptr->flags & (E_MASK | I_MASK)) || + strcmp(symptr->name, name) != 0)) + symptr = symptr->next; + return symptr; +} + +/* convert name to a hash table ptr */ + +PRIVATE struct symstruct **gethashptr(name) +register char *name; +{ + register unsigned hashval; + + hashval = 0; + while (*name) + hashval = hashval * 2 + *name++; + return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1)); + +/* + +#asm + +GOLDEN EQU 157 +HASHTABSIZE EQU 256 + + CLRB can build value here since HASHTABSIZE <= 256 + LDA ,X + BEQ HASHVAL.EXIT +HASHVAL.LOOP + ADDB ,X+ + LSLB + LDA ,X + BNE HASHVAL.LOOP + RORB + LDA #GOLDEN + MUL +HASHVAL.EXIT +HASHVAL.EXIT + LDX #_hashtab + ABX discard A - same as taking mod HASHTABSIZE + ABX +#endasm + +*/ + +} + +/* move symbol descriptor entries to top of table (no error checking) */ + +PUBLIC char *moveup(nbytes) +unsigned nbytes; +{ + register char *source; + register char *target; + + source = tableptr; + target = tableend; + while (nbytes--) + *--target = *--source; + tableptr = source; + return tableend = target; +} + +/* our version of malloc */ + +PUBLIC char *ourmalloc(nbytes) +unsigned nbytes; +{ + char *allocptr; + + align(tableptr); + allocptr = tableptr; + if ((tableptr += nbytes) > tableend) + outofmemory(); + return allocptr; +} + +/* our version of free (release from bottom of table) */ + +PUBLIC void ourfree(cptr) +char *cptr; +{ + tableptr = cptr; +} + +/* read string from file into table at offset suitable for next symbol */ + +PUBLIC char *readstring() +{ + int c; + char *s; + char *start; + + align(tableptr); + start = s = ((struct symstruct *) tableptr)->name; + while (TRUE) + { + if (s >= tableend) + outofmemory(); + if ((c = readchar()) < 0) + prematureeof(); + if ((*s++ = c) == 0) + return start; + } + /* NOTREACHED */ +} + +/* release from top of table */ + +PUBLIC void release(cptr) +char *cptr; +{ + tableend = cptr; +} + +/* allocate space for string */ + +PUBLIC char *stralloc(s) +char *s; +{ + return strcpy(ourmalloc((unsigned) strlen(s) + 1), s); +} diff --git a/ld/type.h b/ld/type.h new file mode 100644 index 0000000..142ea53 --- /dev/null +++ b/ld/type.h @@ -0,0 +1,163 @@ +/* type.h - types for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +typedef int bool_pt; +typedef unsigned char bool_t; + +typedef unsigned short u2_t; +typedef unsigned u2_pt; +typedef unsigned long u4_t; +typedef unsigned long u4_pt; + +#ifdef HOST_8BIT +typedef char fastin_t; +#else +typedef int fastin_t; +#endif +typedef int fastin_pt; + +#ifdef OBJ_H /* obj.h is included */ + +typedef unsigned flags_t; /* unsigned makes shifts logical */ + +#ifdef LONG_OFFSETS +typedef unsigned long offset_t; +#else +typedef unsigned offset_t; +#endif + +struct entrylist /* list of entry symbols */ +{ + struct entrylist *elnext; /* next on list */ + struct symstruct *elsymptr; /* entry on list */ +}; + +struct modstruct /* module table entry format */ +{ + char *filename; /* file containing this module */ + char *archentry; /* name of component file for archives */ + char *modname; /* name of module */ + unsigned long textoffset; /* offset to module text in file */ + char class; /* class of module */ + char loadflag; /* set if module to be loaded */ + char segmaxsize[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for seg max size */ + /* 00 = 1, 01 = 2, 10 = 3, 11 = 4 */ + char segsizedesc[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for #bytes for size */ + /* 00 = 0, 01 = 1, 10 = 2, 11 = 4 */ + struct symstruct **symparray; /* ^array of ptrs to referenced syms */ + struct modstruct *modnext; /* next module in order of initial reading */ + char segsize[1]; /* up to 64 size bytes begin here */ +}; /* careful with sizeof( struct modstruct )!! */ + +struct redlist /* list of redefined (exported) symbols */ +{ + struct redlist *rlnext; /* next on list */ + struct symstruct *rlsymptr; /* to symbol with same name, flags */ + struct modstruct *rlmodptr; /* module for this redefinition */ + offset_t rlvalue; /* value for this redefinition */ +}; + +struct symstruct /* symbol table entry format */ +{ + struct modstruct *modptr; /* module where symbol is defined */ + offset_t value; /* value of symbol */ + flags_t flags; /* see below (unsigned makes shifts logical) */ + struct symstruct *next; /* next symbol with same hash value */ + char name[1]; /* name is any string beginning here */ +}; /* don't use sizeof( struct symstruct )!! */ + +#endif /* obj.h is included */ + +/* prototypes */ + +#ifdef __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + +/* dump.c */ +void dumpmods P((void)); +void dumpsyms P((void)); + +/* io.c */ +void ioinit P((char *progname)); +void closein P((void)); +void closeout P((void)); +void errtrace P((char *name, int level)); +void executable P((void)); +void flusherr P((void)); +void openin P((char *filename)); +void openout P((char *filename)); +void putstr P((char *message)); +#ifdef OBJ_H +void put08x P((offset_t num)); +void put08lx P((offset_t num)); +#endif +void putbstr P((unsigned width, char *str)); +void putbyte P((int ch)); +int readchar P((void)); +void readin P((char *buf, unsigned count)); +bool_pt readineofok P((char *buf, unsigned count)); +void seekin P((unsigned long offset)); +void seekout P((unsigned long offset)); +void seektrel P((unsigned long offset)); +void writechar P((int c)); +void writedrel P((char *buf, unsigned count)); +void writeout P((char *buf, unsigned count)); +void writetrel P((char *buf, unsigned count)); +void fatalerror P((char *message)); +void inputerror P((char *message)); +void input1error P((char *message)); +void outofmemory P((void)); +void prematureeof P((void)); +void redefined P((char *name, char *message, char *archentry, + char *deffilename, char *defarchentry)); +void reserved P((char *name)); +#ifdef OBJ_H +void size_error P((int seg, offset_t count, offset_t size)); +#endif +void undefined P((char *name)); +void usage P((void)); +void use_error P((char *message)); + +/* ld.c */ +int main P((int argc, char **argv)); + +/* readobj.c */ +void objinit P((void)); +void readsyms P((char *filename, bool_pt trace)); +#ifdef OBJ_H +void entrysym P((struct symstruct *symptr)); +offset_t readconvsize P((unsigned countindex)); +offset_t readsize P((unsigned count)); +unsigned segsizecount P((unsigned seg, struct modstruct *modptr)); +#endif + +/* table.c */ +void syminit P((void)); +struct symstruct *addsym P((char *name)); +struct symstruct *findsym P((char *name)); +char *moveup P((unsigned nbytes)); +char *ourmalloc P((unsigned nbytes)); +void ourfree P((char *cptr)); +char *readstring P((void)); +void release P((char *cptr)); +char *stralloc P((char *s)); + +/* typeconvert.c */ +u2_pt c2u2 P((char *buf)); +u4_t c4u4 P((char *buf)); +u2_pt cnu2 P((char *buf, unsigned count)); +u4_t cnu4 P((char *buf, unsigned count)); +void u2c2 P((char *buf, u2_pt offset)); +void u4c4 P((char *buf, u4_t offset)); +void u2cn P((char *buf, u2_pt offset, unsigned count)); +void u4cn P((char *buf, u4_t offset, unsigned count)); +bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian)); + +/* writebin.c */ +void writebin P((char *outfilename, bool_pt argsepid, bool_pt argbits32, + bool_pt argstripflag, bool_pt arguzp)); +void linksyms P((bool_pt argreloc_output)); diff --git a/ld/typeconv.c b/ld/typeconv.c new file mode 100644 index 0000000..82dafdd --- /dev/null +++ b/ld/typeconv.c @@ -0,0 +1,536 @@ +/* typeconv.c - convert between char arrays and unsigneds */ + +/* Copyright (C) 1994 Bruce Evans */ + +/* + c2u2(): 2 byte array to 2 byte unsigned + c4u4(): 4 byte array to 4 byte unsigned + cnu2(): n byte array to 2 byte unsigned + cnu4(): n byte array to 4 byte unsigned + u2c2(): 2 byte unsigned to 2 byte array + u2cn(): 2 byte unsigned to n byte array + u4c4(): 4 byte unsigned to 4 byte array + u4cn(): 4 byte unsigned to n byte array + typeconv_init: (re)initialise for given byte order. + Default is no swapping, but the initialisation should be done + anyway to provide some validity checks (returns FALSE if error). + + Not provided: + c2u4(), c4u2(), u2c4(), u4c2(). + Each of these is best done by truncating or extending a return value + or argument to the appropiate fixed-count function. + c4u2() has too many cases to do in-line conveniently, and the others + are hardly more efficient when done in-line. + + 4 byte orderings for both char arrays and unsigneds are supported: + 0123 - little-endian + 3210 - big-endian + 2301 - little-endian with long words big-endian (pdp11) + 1032 - big-endian with long words little_endian (who knows?) + + The unsigned's byte order is that of the machine on which these + routines are running. + It is determined at run time initialisation since the compiler/ + preprocessor is too dumb to tell us at compile time. +*/ + +#include "const.h" +#include "type.h" +#include "globvar.h" + +FORWARD u2_pt c2u2_00 P((char *buf)); +FORWARD u4_pt c4u4_00 P((char *buf)); +FORWARD u2_pt c2u2_ss P((char *buf)); +FORWARD u4_pt c4u4_ss P((char *buf)); +FORWARD u4_pt c4u4_s0 P((char *buf)); +FORWARD u4_pt c4u4_0s P((char *buf)); +FORWARD void u2c2_00 P((char *buf, u2_pt offset)); +FORWARD void u4c4_00 P((char *buf, u4_t offset)); +FORWARD void u2c2_ss P((char *buf, u2_pt offset)); +FORWARD void u4c4_ss P((char *buf, u4_t offset)); +FORWARD void u4c4_s0 P((char *buf, u4_t offset)); +FORWARD void u4c4_0s P((char *buf, u4_t offset)); + +PRIVATE u2_pt (*pc2u2) P((char *buf)) = c2u2_00; +PRIVATE u4_pt (*pc4u4) P((char *buf)) = c4u4_00; +PRIVATE void (*pu2c2) P((char *buf, u2_pt offset)) = u2c2_00; +PRIVATE void (*pu4c4) P((char *buf, u4_t offset)) = u4c4_00; + +/* === char arrays to unsigneds === */ + +/* no bytes swapped, longwinded to avoid alignment problems */ + +PRIVATE u2_pt c2u2_00(buf) +register char *buf; +{ + u2_t offset; + + ((char *) &offset)[0] = buf[0]; + ((char *) &offset)[1] = buf[1]; + return offset; +} + +PRIVATE u4_pt c4u4_00(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[0]; + ((char *) &offset)[1] = buf[1]; + ((char *) &offset)[2] = buf[2]; + ((char *) &offset)[3] = buf[3]; + return offset; +} + +/* straight swapping for little-endian to big-endian and vice versa */ + +PRIVATE u2_pt c2u2_ss(buf) +register char *buf; +{ + u2_t offset; + + ((char *) &offset)[0] = buf[1]; + ((char *) &offset)[1] = buf[0]; + return offset; +} + +PRIVATE u4_pt c4u4_ss(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[3]; + ((char *) &offset)[1] = buf[2]; + ((char *) &offset)[2] = buf[1]; + ((char *) &offset)[3] = buf[0]; + return offset; +} + +/* wierd swapping for different-endian u2's, same-endian u4's */ + +PRIVATE u4_pt c4u4_s0(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[1]; + ((char *) &offset)[1] = buf[0]; + ((char *) &offset)[2] = buf[3]; + ((char *) &offset)[3] = buf[2]; + return offset; +} + +/* very wierd swapping for same-endian u2's, different-endian u4's */ + +PRIVATE u4_pt c4u4_0s(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[2]; + ((char *) &offset)[1] = buf[3]; + ((char *) &offset)[2] = buf[0]; + ((char *) &offset)[3] = buf[1]; + return offset; +} + +/* === entry points === */ + +PUBLIC u2_pt c2u2(buf) +char *buf; +{ + return (*pc2u2) (buf); +} + +PUBLIC u4_t c4u4(buf) +char *buf; +{ + return (*pc4u4) (buf); +} + +PUBLIC u2_pt cnu2(buf, count) +char *buf; +unsigned count; +{ + switch (count) + { + case 1: + return buf[0] & 0xFF; + case 2: + return (*pc2u2) (buf); + case 4: + return (u2_pt) (*pc4u4) (buf); + default: + return 0; + } +} + +PUBLIC u4_t cnu4(buf, count) +char *buf; +unsigned count; +{ + switch (count) + { + case 1: + return buf[0] & 0xFF; + case 2: + return (*pc2u2) (buf); + case 4: + return (*pc4u4) (buf); + default: + return 0; + } +} + +/* === unsigneds to char arrays === */ + +/* no bytes swapped, longwinded to avoid alignment problems */ + +PRIVATE void u2c2_00(buf, offset) +register char *buf; +u2_pt offset; +{ + + buf[0] = ((char *) &offset)[0]; + buf[1] = ((char *) &offset)[1]; +} + +PRIVATE void u4c4_00(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[0]; + buf[1] = ((char *) &offset)[1]; + buf[2] = ((char *) &offset)[2]; + buf[3] = ((char *) &offset)[3]; +} + +/* straight swapping for little-endian to big-endian and vice versa */ + +PRIVATE void u2c2_ss(buf, offset) +register char *buf; +u2_pt offset; +{ + u2_t offset2; + + offset2 = offset; + buf[0] = ((char *) &offset2)[1]; + buf[1] = ((char *) &offset2)[0]; +} + +PRIVATE void u4c4_ss(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[3]; + buf[1] = ((char *) &offset)[2]; + buf[2] = ((char *) &offset)[1]; + buf[3] = ((char *) &offset)[0]; +} + +/* wierd swapping for different-endian u2's, same-endian u4's */ + +PRIVATE void u4c4_s0(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[1]; + buf[1] = ((char *) &offset)[0]; + buf[2] = ((char *) &offset)[3]; + buf[3] = ((char *) &offset)[2]; +} + +/* very wierd swapping for same-endian u2's, different-endian u4's */ + +PRIVATE void u4c4_0s(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[2]; + buf[1] = ((char *) &offset)[3]; + buf[2] = ((char *) &offset)[0]; + buf[3] = ((char *) &offset)[1]; +} + +/* === entry points === */ + +PUBLIC void u2c2(buf, offset) +register char *buf; +u2_pt offset; +{ + (*pu2c2) (buf, offset); +} + +PUBLIC void u4c4(buf, offset) +register char *buf; +u4_t offset; +{ + (*pu4c4) (buf, offset); +} + +PUBLIC void u2cn(buf, offset, count) +register char *buf; +u2_pt offset; +unsigned count; +{ + switch (count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + (*pu2c2) (buf, offset); + return; + case 4: + (*pu4c4) (buf, (u4_t) offset); + return; + } +} + +PUBLIC void u4cn(buf, offset, count) +register char *buf; +u4_t offset; +unsigned count; +{ + switch (count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + (*pu2c2) (buf, (u2_pt) (u2_t) offset); + return; + case 4: + (*pu4c4) (buf, offset); + return; + } +} + +/* initialise type conversion, return FALSE if it cannot be handled */ + +PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) +bool_pt big_endian; +bool_pt long_big_endian; +{ + u2_pt conv2; + u4_pt conv4; + char *conv2ptr; + char *conv4ptr; + + if (sizeof(u2_t) != 2 || sizeof(u4_t) != 4) + /* dumb preprocessor's don't accept sizeof in #if expressions */ + return FALSE; + + if (big_endian) + { + conv2ptr = (conv4ptr = "\1\2\3\4") + 2; + if (!long_big_endian) + conv4ptr = "\3\4\1\2"; + } + else + { + conv2ptr = conv4ptr = "\4\3\2\1"; + if (long_big_endian) + conv4ptr = "\2\1\4\3"; + } + conv2 = c2u2_00(conv2ptr); + conv4 = c4u4_00(conv4ptr); + if (conv2 == 0x0304) + { + pc2u2 = c2u2_00; + pc4u4 = c4u4_00; + pu2c2 = u2c2_00; + pu4c4 = u4c4_00; + if (conv4 == 0x03040102L) + { + pc4u4 = c4u4_0s; + pu4c4 = u4c4_0s; + } + else if (conv4 != 0x01020304L) + return FALSE; + } + else if (conv2 == 0x0403) + { + pc2u2 = c2u2_ss; + pc4u4 = c4u4_ss; + pu2c2 = u2c2_ss; + pu4c4 = u4c4_ss; + if (conv4 == 0x02010403L) + { + pc4u4 = c4u4_s0; + pu4c4 = u4c4_s0; + } + else if (conv4 != 0x04030201L) + return FALSE; + } + else + return FALSE; + return TRUE; +} + +#ifdef DEBUG_TYPECONV + +main() +{ + char *source; + char target[4]; + u2_t u2; + u2_t u2a; + u4_t u4; + u4_t u4a; + + printf("%u\n", typeconv_init(FALSE, FALSE)); + printf("%u\n", typeconv_init(FALSE, TRUE)); + printf("%u\n", typeconv_init(TRUE, FALSE)); + printf("%u\n", typeconv_init(TRUE, TRUE)); + + typeconv_init(FALSE, FALSE); + source = "\4\3\2\1"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source, 2); + u2cn(target, u2, 2); + if (strncmp(source, target, 2)) + printf("oops9\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source, 2); + u4cn(target, u4a, 2); + if (strncmp(source, target, 2)) + printf("oops10\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\4\3\0\0", 4)) + printf("oops11\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops12\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(FALSE, TRUE); + source = "\2\1\4\3"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source + 2, 2); + u2cn(target, u2, 2); + if (strncmp(source + 2, target, 2)) + printf("oops13\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source + 2, 2); + u4cn(target, u4a, 2); + if (strncmp(source + 2, target, 2)) + printf("oops14\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\0\0\4\3", 4)) + printf("oops15\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops16\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(TRUE, FALSE); + source = "\3\4\1\2"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source, 2); + u2cn(target, u2, 2); + if (strncmp(source, target, 2)) + printf("oops5\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source, 2); + u4cn(target, u4a, 2); + if (strncmp(source, target, 2)) + printf("oops6\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\3\4\0\0", 4)) + printf("oops7\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops8\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(TRUE, TRUE); + source = "\1\2\3\4"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source + 2, 2); + u2cn(target, u2, 2); + if (strncmp(source + 2, target, 2)) + printf("oops1\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source + 2, 2); + u4cn(target, u4a, 2); + if (strncmp(source + 2, target, 2)) + printf("oops2\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\0\0\3\4", 4)) + printf("oops3\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops4\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); +} + +#endif /* DEBUG_TYPECONV */ diff --git a/ld/writebin.c b/ld/writebin.c new file mode 100644 index 0000000..a95280c --- /dev/null +++ b/ld/writebin.c @@ -0,0 +1,989 @@ +extern long text_base_address; +#define btextoffset text_base_address +static long bdataoffset; +#define page_size() 4096 + +/* writebin.c - write binary file for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#ifdef A_OUT_H +# include A_OUT_H +#else +# ifdef BSD_A_OUT +# ifdef STANDARD_GNU_A_OUT +# include <a.out.h> +# define RELOC_INFO_SIZE 8 /* unportable bitfields - bcc doesn't pack */ +# else +# include "bsd-a.out.h" +# define RELOC_INFO_SIZE (sizeof (struct relocation_info)) +# endif +# define C_EXT N_EXT +# define C_STAT 0 +# define n_was_name n_un.n_name +# define n_was_numaux n_other +# define n_was_other n_numaux +# define n_was_sclass n_type +# define n_was_strx n_un.n_strx +# define n_was_type n_desc +# else /* not BSD_A_OUT */ +# include "a.out.h" /* maybe local copy of <a.out.h> for X-link */ +# define n_was_name n_name +# define n_was_numaux n_numaux +# define n_was_other n_other +# define n_was_sclass n_sclass +# define n_was_strx n_value +# define n_was_type n_type +# endif /* BSD_A_OUT */ +#endif + +#include "const.h" +#include "obj.h" +#include "type.h" +#undef EXTERN +#include "globvar.h" + +#ifdef STDC_HEADERS_MISSING +void *memset P((void *s, int c, unsigned n)); +#else +#undef NULL +#include <string.h> +#endif + +#ifdef EDOS +# define FILEHEADERLENGTH 0 +#endif +#ifdef MINIX +# ifdef BSD_A_OUT +# ifdef STANDARD_GNU_A_OUT +# define FILEHEADERLENGTH 32 +# else +# define FILEHEADERLENGTH 48 +# endif +# else +# define FILEHEADERLENGTH A_MINHDR + /* part of header not counted in offsets */ +# endif +#endif +#define DPSEG 2 + +#define CM_MASK 0xC0 +#define MODIFY_MASK 0x3F +#define S_MASK 0x04 +#define OF_MASK 0x03 + +#define CM_SPECIAL 0 +#define CM_ABSOLUTE 0x40 +#define CM_OFFSET_RELOC 0x80 +#define CM_SYMBOL_RELOC 0xC0 + +#define CM_EOT 0 +#define CM_BYTE_SIZE 1 +#define CM_WORD_SIZE 2 +#define CM_LONG_SIZE 3 +#define CM_1_SKIP 17 +#define CM_2_SKIP 18 +#define CM_4_SKIP 19 +#define CM_0_SEG 32 + +#define ABS_TEXT_MAX 64 + +#define offsetof(struc, mem) ((int) &((struc *) 0)->mem) +#define memsizeof(struc, mem) sizeof(((struc *) 0)->mem) + +PRIVATE bool_t bits32; /* nonzero for 32-bit executable */ +PRIVATE offset_t combase[NSEG]; /* bases of common parts of segments */ +PRIVATE offset_t comsz[NSEG]; /* sizes of common parts of segments */ +PRIVATE fastin_t curseg; /* current segment, 0 to $F */ +PRIVATE offset_t edataoffset; /* end of data */ +PRIVATE offset_t endoffset; /* end of bss */ +PRIVATE offset_t etextoffset; /* end of text */ +PRIVATE offset_t etextpadoff; /* end of padded text */ +#ifdef BSD_A_OUT +PRIVATE unsigned ndreloc; /* number of data relocations */ +#endif +PRIVATE unsigned nsym; /* number of symbols written */ +#ifdef BSD_A_OUT +PRIVATE unsigned ntreloc; /* number of text relocations */ +PRIVATE bool_t reloc_output; /* nonzero to leave reloc info in output */ +#endif +PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */ +PRIVATE offset_t segadj[NSEG]; /* adjusts (file offset - seg offset) */ + /* depends on zero init */ +PRIVATE offset_t segbase[NSEG]; /* bases of data parts of segments */ +PRIVATE char segboundary[9] = "__seg0DH"; + /* name of seg boundary __seg0DL to __segfCH */ +PRIVATE offset_t segpos[NSEG]; /* segment positions for current module */ +PRIVATE offset_t segsz[NSEG]; /* sizes of data parts of segments */ + /* depends on zero init */ +PRIVATE bool_t sepid; /* nonzero for separate I & D */ +PRIVATE bool_t stripflag; /* nonzero to strip symbols */ +PRIVATE offset_t spos; /* position in current seg */ +PRIVATE bool_t uzp; /* nonzero for unmapped zero page */ + +#ifdef EDOS +FORWARD unsigned binheaderlength P((char *commandname)); +FORWARD char *idconvert P((struct entrylist *elptr, char *commandname)); +#endif +FORWARD void linkmod P((struct modstruct *modptr)); +FORWARD void linkrefs P((struct modstruct *modptr)); +FORWARD void padmod P((struct modstruct *modptr)); +FORWARD void setsym P((char *name, offset_t value)); +FORWARD void symres P((char *name)); +FORWARD void setseg P((fastin_pt newseg)); +FORWARD void skip P((unsigned countsize)); +#ifdef EDOS +FORWARD void writeheader P((char *commandname)); +#else +FORWARD void writeheader P((void)); +#endif +FORWARD void writenulls P((offset_t count)); + +/* link all symbols connected to entry symbols */ + +PUBLIC void linksyms(argreloc_output) +bool_pt argreloc_output; +{ + char needlink; + struct entrylist *elptr; + struct modstruct *modptr; + struct symstruct *symptr; + +#ifdef BSD_A_OUT + reloc_output = argreloc_output; + if (argreloc_output) + { + if (modfirst->modnext != NULL) + fatalerror("relocatable output only works for one input file"); + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + modptr->loadflag = TRUE; + return; + } +#endif + if ((symptr = findsym("_main")) != NULL) + entrysym(symptr); + do + { + if ((elptr = entryfirst) == NULL) + fatalerror("no start symbol"); + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + modptr->loadflag = FALSE; + for (; elptr != NULL; elptr = elptr->elnext) + linkrefs(elptr->elsymptr->modptr); + if ((symptr = findsym("start")) != NULL) + linkrefs(symptr->modptr); + needlink = FALSE; + { + struct redlist *prlptr; + struct redlist *rlptr; + + for (rlptr = redfirst; rlptr != NULL; + rlptr = (prlptr = rlptr)->rlnext) + if (rlptr->rlmodptr->loadflag && + rlptr->rlmodptr->class > rlptr->rlsymptr->modptr->class) + { + rlptr->rlsymptr->modptr = rlptr->rlmodptr; + rlptr->rlsymptr->value = rlptr->rlvalue; + if (rlptr == redfirst) + redfirst = rlptr->rlnext; + else + prlptr->rlnext = rlptr->rlnext; + needlink = TRUE; + } + } + } + while (needlink); +} + +/* write binary file */ + +PUBLIC void writebin(outfilename, argsepid, argbits32, argstripflag, arguzp) +char *outfilename; +bool_pt argsepid; +bool_pt argbits32; +bool_pt argstripflag; +bool_pt arguzp; +{ + char buf4[4]; +#ifdef EDOS + char *commandname; +#endif + char *cptr; + struct nlist extsym; + flags_t flags; + struct modstruct *modptr; + fastin_t seg; + unsigned sizecount; + offset_t tempoffset; + + sepid = argsepid; + bits32 = argbits32; + stripflag = argstripflag; +#ifdef BSD_A_OUT + uzp = arguzp && !reloc_output; +#else + uzp = arguzp; +#endif + if (uzp) + { + if (btextoffset == 0) + btextoffset = page_size(); + if (bdataoffset == 0 && sepid) + bdataoffset = page_size(); + } +#ifdef EDOS + commandname = stralloc(outfilename); + if ((cptr = strchr(commandname, ':')) != NULL) + commandname = cptr + 1; + if ((cptr = strrchr(commandname, '.')) != NULL) + *cptr = 0; +#endif + + /* reserve special symbols use curseg to pass parameter to symres() */ + for (curseg = 0; curseg < NSEG; ++curseg) + { + segboundary[5] = hexdigit[curseg]; /* to __segX?H */ + segboundary[6] = 'D'; + symres(segboundary); /* __segXDH */ + segboundary[7] = 'L'; + symres(segboundary); /* __segXDL */ + segboundary[6] = 'C'; + symres(segboundary); /* __segXCL */ + segboundary[7] = 'H'; + symres(segboundary); /* __segXCH */ + } +#ifdef EDOS + curseg = 0; /* data seg, s.b. variable */ +#else + curseg = 3; +#endif + symres("__edata"); + symres("__end"); + curseg = 0; /* text seg, s.b. variable */ + symres("__etext"); + + /* calculate segment and common sizes (sum over loaded modules) */ + /* use zero init of segsz[] */ + /* also relocate symbols relative to starts of their segments */ + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) + { + if (!(symptr->flags & (I_MASK | SA_MASK))) + { + /* relocate by offset of module in segment later */ + /* relocate by offset of segment in memory special */ + /* symbols get relocated improperly */ + symptr->value += segsz[symptr->flags & SEGM_MASK]; + } + else if (symptr->value == 0) + { +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + undefined(symptr->name); + } + else + { +#ifdef BSD_A_OUT +#if 0 + if (!reloc_output) +#else + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif +#endif + { + tempoffset = roundup(symptr->value, 4, offset_t); + /* temp kludge quad alignment for 386 */ + symptr->value = comsz[seg = symptr->flags & SEGM_MASK]; + comsz[seg] += tempoffset; + } + if (!(symptr->flags & SA_MASK)) + symptr->flags |= C_MASK; + } + } + for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg) + { + segsz[seg] += cntooffset(cptr, + sizecount = segsizecount((unsigned) seg, modptr)); +#ifndef EDOS + + /* adjust sizes to even to get quad boundaries */ + /* this should be specifiable dynamically */ + segsz[seg] = roundup(segsz[seg], 4, offset_t); + comsz[seg] = roundup(comsz[seg], 4, offset_t); +#endif + cptr += sizecount; + } + } + + /* calculate seg positions now their sizes are known */ + /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */ + /* assume seg 0 is text and rest are data */ +#ifdef EDOS + if (btextoffset == 0) + btextoffset = binheaderlength(commandname); +#endif + segpos[0] = segbase[0] = spos = btextoffset; + combase[0] = segbase[0] + segsz[0]; + segadj[1] = segadj[0] = -btextoffset; + etextpadoff = etextoffset = combase[0] + comsz[0]; + if (sepid) + { + etextpadoff = roundup(etextoffset, 0x10, offset_t); + segadj[1] += etextpadoff - bdataoffset; + } + else if (bdataoffset == 0) + bdataoffset = etextpadoff; + segpos[1] = segbase[1] = edataoffset = bdataoffset; + combase[1] = segbase[1] + segsz[1]; + for (seg = 2; seg < NSEG; ++seg) + { + segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1]; + if (seg == DPSEG) + { + /* temporarily have fixed DP seg */ + /* adjust if nec so it only spans 1 page */ + tempoffset = segsz[seg] + comsz[seg]; + if (tempoffset > 0x100) + fatalerror("direct page segment too large"); + if ((((segbase[seg] + tempoffset) ^ segbase[seg]) + & ~(offset_t) 0xFF) != 0) + segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF) + & ~(offset_t) 0xFF; + } + combase[seg] = segbase[seg] + segsz[seg]; + segadj[seg] = segadj[seg - 1]; + } + + /* relocate symbols by offsets of segments in memory */ + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) + { + if (symptr->flags & (C_MASK | SA_MASK)) + { +#ifdef BSD_A_OUT +#if 0 + if (!reloc_output) +#else + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif +#endif + symptr->value += combase[symptr->flags & SEGM_MASK]; + } + else +#ifdef BSD_A_OUT + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif + symptr->value += segbase[symptr->flags & SEGM_MASK]; + } + } + + /* adjust special symbols */ + for (seg = 0; seg < NSEG; ++seg) + { + if (segsz[seg] != 0) + /* only count data of nonzero length */ + edataoffset = segbase[seg] + segsz[seg]; + segboundary[5] = hexdigit[seg]; /* to __segX?H */ + segboundary[6] = 'D'; + setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]); + /* __segXDH */ + segboundary[7] = 'L'; + setsym(segboundary, tempoffset); /* __segXDL */ + segboundary[6] = 'C'; + setsym(segboundary, tempoffset = combase[seg]); + /* __segXCL */ + segboundary[7] = 'H'; + setsym(segboundary, tempoffset + comsz[seg]); + /* __segXCH */ + } + setsym("__etext", etextoffset); + setsym("__edata", edataoffset); + setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]); + + openout(outfilename); +#ifdef BSD_A_OUT + if (reloc_output) + seektrel(FILEHEADERLENGTH + + (unsigned long) (etextpadoff - btextoffset) + + (unsigned long) (edataoffset - bdataoffset)); +#endif +#ifdef EDOS + writeheader(commandname); +#else + writeheader(); +#endif + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + linkmod(modptr); + padmod(modptr); + } + + /* dump symbol table */ +#ifdef MINIX + if (!stripflag) + { +#ifdef BSD_A_OUT + unsigned stringoff; +#endif + + seekout(FILEHEADERLENGTH + + (unsigned long) (etextpadoff - btextoffset) + + (unsigned long) (edataoffset - bdataoffset) +#ifdef BSD_A_OUT + + ((unsigned long) ndreloc + ntreloc) * RELOC_INFO_SIZE +#endif + ); + extsym.n_was_numaux = extsym.n_was_type = 0; +#ifdef BSD_A_OUT + stringoff = 4; +#endif + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr) + { +#ifdef BSD_A_OUT + offtocn((char *) &extsym.n_was_strx, + (offset_t) stringoff, 4); +#else + strncpy((char *) &extsym.n_was_name, symptr->name, + sizeof extsym.n_was_name); +#endif + u4cn((char *) &extsym.n_value, (u4_t) symptr->value, + sizeof extsym.n_value); + if ((flags = symptr->flags) & A_MASK) + extsym.n_was_sclass = N_ABS; + else if (flags & (E_MASK | I_MASK)) + extsym.n_was_sclass = C_EXT; + else + extsym.n_was_sclass = C_STAT; + if (!(flags & I_MASK) || +#ifdef BSD_A_OUT + !reloc_output && +#endif + flags & C_MASK) + switch (flags & (A_MASK | SEGM_MASK)) + { + case 0: + extsym.n_was_sclass |= N_TEXT; + case A_MASK: + break; + default: + if (flags & (C_MASK | SA_MASK)) + extsym.n_was_sclass |= N_BSS; + else + extsym.n_was_sclass |= N_DATA; + break; + } + writeout((char *) &extsym, sizeof extsym); + ++nsym; +#ifdef BSD_A_OUT + stringoff += strlen(symptr->name) + 1; +#endif + } + } +#ifdef BSD_A_OUT + offtocn((char *) &extsym.n_was_strx, (offset_t) stringoff, 4); + writeout((char *) &extsym.n_was_strx, 4); + for (modptr = modfirst; modptr != NULL; modptr = modptr->modnext) + if (modptr->loadflag) + { + register struct symstruct **symparray; + register struct symstruct *symptr; + + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr == modptr) + writeout(symptr->name, strlen(symptr->name) + 1); + } +#endif + seekout((unsigned long) offsetof(struct exec, a_syms)); + u4cn(buf4, (u4_t) nsym * sizeof extsym, + memsizeof(struct exec, a_syms)); + writeout(buf4, memsizeof(struct exec, a_syms)); +#ifdef BSD_A_OUT + seekout((unsigned long) offsetof(struct exec, a_trsize)); + u4cn(buf4, (u4_t) ntreloc * RELOC_INFO_SIZE, + memsizeof(struct exec, a_trsize)); + writeout(buf4, memsizeof(struct exec, a_trsize)); + seekout((unsigned long) offsetof(struct exec, a_drsize)); + u4cn(buf4, (u4_t) ndreloc * RELOC_INFO_SIZE, + memsizeof(struct exec, a_drsize)); + writeout(buf4, memsizeof(struct exec, a_drsize)); +#endif + } +#endif /* MINIX */ + closeout(); +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + executable(); +} + +#ifdef EDOS + +PRIVATE unsigned binheaderlength(commandname) +char *commandname; +{ + unsigned count; + char *name; + struct entrylist *elptr; + struct symstruct *startptr; + + count = 2 + 2 + 1; /* len len nul */ + startptr = findsym("start"); + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + { + name = idconvert(elptr, commandname); + count += strlen(name) + 1 + 2 + 1; /* nul off flg */ + ourfree(name); + if (startptr != NULL) + count += 6; /* LBSR $xxxx and LBRA $xxxx */ + } + return count; +} + +/* convert name of symbol (entry) list element to a Basic identifier */ +/* new name is built in storage obtained from stralloc() */ +/* the special name _main is converted to the command name first */ +/* copy upper case and numerals, convert lower case to upper, ignore rest */ + +PRIVATE char *idconvert(elptr, commandname) +struct entrylist *elptr; +char *commandname; +{ + char *name; + char *newname; + + if (strcmp(name = elptr->elsymptr->name, "_main") == 0) + name = commandname; + newname = stralloc(name); + { + register char *t; + register char *s; + + t = newname; + s = name; + do + { + if (*s >= '0' && *s <= '9' || *s >= 'A' && *s <= 'Z') + *t++ = *s; + if (*s >= 'a' && *s <= 'z') + *t++ = *s + ('A' - 'a'); + } + while (*s++); + *t = 0; + } + if (*newname < 'A') /* numeral or null */ + fatalerror("bad entry name"); + return newname; +} + +#endif /* EDOS */ + +PRIVATE void linkmod(modptr) +struct modstruct *modptr; +{ + char buf[ABS_TEXT_MAX]; + int command; + unsigned char modify; + offset_t offset; + int symbolnum; + struct symstruct **symparray; + struct symstruct *symptr; + + setseg(0); + relocsize = 2; + symparray = modptr->symparray; + openin(modptr->filename); /* does nothing if already open */ + seekin(modptr->textoffset); + while (TRUE) + { + if ((command = readchar()) < 0) + prematureeof(); + modify = command & MODIFY_MASK; + switch (command & CM_MASK) + { + case CM_SPECIAL: + switch (modify) + { + case CM_EOT: + segpos[curseg] = spos; + return; + case CM_BYTE_SIZE: + relocsize = 1; + break; + case CM_WORD_SIZE: + relocsize = 2; + break; + case CM_LONG_SIZE: +#ifdef LONG_OFFSETS + relocsize = 4; + break; +#else + fatalerror("relocation by long offsets not implemented"); +#endif + case CM_1_SKIP: + skip(1); + break; + case CM_2_SKIP: + skip(2); + break; + case CM_4_SKIP: + skip(4); + break; + default: + if ((modify -= CM_0_SEG) >= NSEG) + inputerror("bad data in"); + setseg(modify); + break; + } + break; + case CM_ABSOLUTE: + if (modify == 0) + modify = ABS_TEXT_MAX; + readin(buf, (unsigned) modify); + writeout(buf, (unsigned) modify); + spos += (int) modify; + break; + case CM_OFFSET_RELOC: + offset = readsize(relocsize); + if (modify & R_MASK) + offset -= (spos + relocsize); + offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize); + writeout(buf, relocsize); +#ifdef BSD_A_OUT + if (reloc_output) + { + u4_t bitfield; + + if (curseg == 0) + { + ++ntreloc; + offtocn(buf, spos, 4); + writetrel(buf, 4); + } + else + { + ++ndreloc; + offtocn(buf, spos - segbase[1], 4); + writedrel(buf, 4); + } + if ((modify & SEGM_MASK) == 0) + bitfield = N_TEXT; + else + bitfield = N_DATA; + if (modify & R_MASK) + bitfield |= 1L << 24; + if (relocsize == 2) + bitfield |= 1L << 25; + else if (relocsize == 4) + bitfield |= 1L << 26; + u4cn(buf, bitfield, 4); + if (curseg == 0) + writetrel(buf, 4); + else + writedrel(buf, 4); + } +#endif /* BSD_A_OUT */ + spos += relocsize; + break; + case CM_SYMBOL_RELOC: + symptr = symparray[symbolnum = readconvsize((unsigned) + (modify & S_MASK ? 2 : 1))]; + offset = readconvsize((unsigned) modify & OF_MASK); + if (modify & R_MASK) + offset -= (spos + relocsize); +#ifdef BSD_A_OUT + if (!reloc_output || !(symptr->flags & I_MASK)) +#endif + offset += symptr->value; + offtocn(buf, offset, relocsize); + writeout(buf, relocsize); +#ifdef BSD_A_OUT + if (reloc_output) + { + u4_t bitfield; + + if (curseg == 0) + { + ++ntreloc; + offtocn(buf, spos, 4); + writetrel(buf, 4); + } + else + { + ++ndreloc; + offtocn(buf, spos - segbase[1], 4); + writedrel(buf, 4); + } + if (symptr->flags & I_MASK) + bitfield = (1L << 27) | symbolnum; + else if ((symptr->flags & SEGM_MASK) == 0) + bitfield = N_TEXT; + else if (symptr->flags & (C_MASK | SA_MASK)) + bitfield = N_BSS; + else + bitfield = N_DATA; + if (modify & R_MASK) + bitfield |= 1L << 24; + if (relocsize == 2) + bitfield |= 1L << 25; + else if (relocsize == 4) + bitfield |= 1L << 26; + u4cn(buf, bitfield, 4); + if (curseg == 0) + writetrel(buf, 4); + else + writedrel(buf, 4); + } +#endif /* BSD_A_OUT */ + spos += relocsize; + } + } +} + +PRIVATE void linkrefs(modptr) +struct modstruct *modptr; +{ + register struct symstruct **symparray; + register struct symstruct *symptr; + + modptr->loadflag = TRUE; + for (symparray = modptr->symparray; + (symptr = *symparray) != NULL; ++symparray) + if (symptr->modptr->loadflag == FALSE) + linkrefs(symptr->modptr); +} + +PRIVATE void padmod(modptr) +struct modstruct *modptr; +{ + offset_t count; + fastin_t seg; + offset_t size; + unsigned sizecount; + char *sizeptr; + + for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg) + { + size = cntooffset(sizeptr, + sizecount = segsizecount((unsigned) seg, modptr)); + sizeptr += sizecount; + if ((count = segpos[seg] - segbase[seg]) != size) + size_error(seg, count, size); + + /* pad to quad boundary */ + /* not padding in-between common areas which sometimes get into file */ + if ((size = roundup(segpos[seg], 4, offset_t) - segpos[seg]) != 0) + { + setseg(seg); + writenulls(size); + segpos[seg] = spos; + } + segbase[seg] = segpos[seg]; + } +} + +PRIVATE void setsym(name, value) +char *name; +offset_t value; +{ + struct symstruct *symptr; + +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + if ((symptr = findsym(name)) != NULL) + symptr->value = value; +} + +PRIVATE void symres(name) +register char *name; +{ + register struct symstruct *symptr; + + if ((symptr = findsym(name)) != NULL) + { + if ((symptr->flags & SEGM_MASK) == SEGM_MASK) + symptr->flags &= ~SEGM_MASK | curseg; + if (symptr->flags != (I_MASK | curseg) || symptr->value != 0) + reserved(name); +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + symptr->flags = E_MASK | curseg; /* show defined, not common */ + } +} + +/* set new segment */ + +PRIVATE void setseg(newseg) +fastin_pt newseg; +{ + if (newseg != curseg) + { + segpos[curseg] = spos; + spos = segpos[curseg = newseg]; + seekout(FILEHEADERLENGTH + (unsigned long) spos + + (unsigned long) segadj[curseg]); + } +} + +PRIVATE void skip(countsize) +unsigned countsize; +{ + writenulls((offset_t) readsize(countsize)); +} + +#ifdef EDOS + +PRIVATE void writeheader(commandname) +char *commandname; +{ + char buf[MAX_OFFSET_SIZE]; + offset_t offset; + unsigned headlength; + char *name; + struct entrylist *elptr; + struct symstruct *startptr; + + headlength = binheaderlength(commandname); + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + headlength -= 6; + offset = headlength; + startptr = findsym("start"); + offtocn(buf, edataoffset, 2); + writeout(buf, 2); + writechar(0xFF); /* dummy data length 0xFFFF takes everything */ + writechar(0xFF); + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + { + name = idconvert(elptr, commandname); + writeout(name, (unsigned) strlen(name) + 1); + ourfree(name); + offtocn(buf, startptr == NULL ? elptr->elsymptr->value : offset, 2); + writeout(buf, 2); + writechar(0x82); /* 8 = set flags from here, 2 = cmd line */ + offset += 6; /* LBSR $xxxx and LBRA $xxxx */ + } + writechar(0); + if (startptr != NULL) + { + offset = headlength + 3; /* over 1st LBSR */ + for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) + { + writechar(0x17); /* LBSR */ + offtocn(buf, startptr->value - offset, 2); + writeout(buf, 2); + writechar(0x16); /* LBRA */ + offtocn(buf, elptr->elsymptr->value - offset - 3, 2); + writeout(buf, 2); + offset += 6; + } + } +} + +#endif /* EDOS */ + +#ifdef MINIX + +PRIVATE void writeheader() +{ + struct exec header; + + memset(&header, 0, sizeof header); +#ifdef STANDARD_GNU_A_OUT +#ifdef N_SET_MAGIC + N_SET_MAGIC(header, OMAGIC); +#else + *(unsigned short *) &header.a_magic = OMAGIC; /* XXX - works for 386BSD */ +#endif +#else + header.a_magic[0] = A_MAGIC0; + header.a_magic[1] = A_MAGIC1; +#endif +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + { +#ifdef STANDARD_GNU_A_OUT +#ifdef N_SET_FLAGS + N_SET_FLAGS(header, 0); +#else + /* XXX - works for 386BSD */ +#endif +#else + header.a_flags = sepid ? A_SEP : A_EXEC; + if (uzp) + header.a_flags |= A_UZP; +#endif + } +#ifdef BSD_A_OUT +#ifdef STANDARD_GNU_A_OUT +#ifdef N_SET_FLAGS + N_SET_MACHTYPE(header, M_386); +#else + /* XXX - works for 386BSD which doesn't define its own machtype :-( */ +#endif +#else + header.a_cpu = (bits32 || reloc_output) ? A_I80386 : A_I8086; +#endif +#else + header.a_cpu = bits32 ? A_I80386 : A_I8086; +#endif +#ifndef STANDARD_GNU_A_OUT + header.a_hdrlen = FILEHEADERLENGTH; +#endif + offtocn((char *) &header.a_text, etextpadoff - btextoffset, + sizeof header.a_text); + offtocn((char *) &header.a_data, edataoffset - bdataoffset, + sizeof header.a_data); + offtocn((char *) &header.a_bss, endoffset - edataoffset, + sizeof header.a_bss); +#ifdef BSD_A_OUT + if (!reloc_output) +#endif + { + if (uzp) + offtocn((char *) &header.a_entry, page_size(), + sizeof header.a_entry); +#ifndef STANDARD_GNU_A_OUT + offtocn((char *) &header.a_total, (offset_t) + (endoffset < 0x00010000L ? 0x00010000L : endoffset + 0x0008000L), + sizeof header.a_total); +#endif + } + writeout((char *) &header, FILEHEADERLENGTH); +} + +#endif /* MINIX */ + +PRIVATE void writenulls(count) +offset_t count; +{ + spos += count; + while (count--) + writechar(0); +} |