delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1997/09/14/22:05:51

Date: Mon, 15 Sep 1997 14:04:50 +1100
From: Bill Currie <billc AT blackmagic DOT tait DOT co DOT nz>
Subject: djasm patches
To: djgpp-workers AT delorie DOT com
Message-id: <199709150209.OAA17385@teleng1.tait.co.nz gatekeeper.tait.co.nz>
Organization: Tait Electronics Limited
MIME-version: 1.0
Comments: Authenticated sender is <billc AT blackmagic DOT tait DOT co DOT nz>

--Message-Boundary-28453
Content-type: text/plain; charset=US-ASCII
Content-transfer-encoding: 7BIT
Content-description: Mail message body

These are relative to the first 2.02 alpha (31 aug?).

- most 386/486 instructions now implemented (a few still missing, I 
have to find out which ones, mostly variants)
- sign extension used whenever possible for offsets and immediate 
values.
- compiles with `-Wall -Werror'
- structure and untion definitions (see my djgpp.asm for details)
- `.sys' file type support (you still have to code the device header 
by hand though)
- 32 bit addressing.

There may be others, but I can't remeber them.
Bill
--
Leave others their otherness.


--Message-Boundary-28453
Content-type: text/plain; charset=US-ASCII
Content-transfer-encoding: 7BIT
Content-description: Text from file 'djasm.patch'

*** djasm.y~	Tue Aug 13 02:43:10 1996
--- djasm.y	Fri Sep 12 22:18:24 1997
***************
*** 9,14 ****
--- 9,16 ----
  #include <coff.h>
  #include <fcntl.h>
  #include <time.h>
+ #include <ctype.h>
+ #include <unistd.h>
  
  #define SMALL_EXE_HEADER 0
  #if SMALL_EXE_HEADER
***************
*** 21,26 ****
--- 23,31 ----
  
  #define YYERROR_VERBOSE
  
+ #define MAX(a,b) ((a)>(b)?(a):(b))
+ #define MIN(a,b) ((a)<(b)?(a):(b))
+ 
  void yyerror(char *s);
  
  #define OUT_exe 0
***************
*** 29,34 ****
--- 34,40 ----
  #define OUT_h   3
  #define OUT_inc 4
  #define OUT_s   5
+ #define OUT_sys 6
  
  char *ext_types[] = {
    "exe",
***************
*** 37,42 ****
--- 43,49 ----
    "h",
    "inc",
    "ah",
+   "sys",
    0
  };
  
***************
*** 98,103 ****
--- 105,111 ----
  #define REL_abs32	1
  #define REL_16		2
  #define REL_8		3
+ #define REL_abs8	4
  
  typedef struct Patch {
    struct Patch *next;
***************
*** 110,127 ****
  Symbol *get_symbol(char *name, int create);
  Symbol *set_symbol(Symbol *sym, int value);
  Symbol *zerosym;
  
  struct {
    int regs;
    int offset;
    int nsyms;
    Symbol *syms[10];
! } _modrm = { 0, 0, 0 };
  
  unsigned char sreg_overrides[] = {
    0x26, 0x2e, 0x36, 0x3e, 0x64, 0x65
  };
  
  void emit(void *v, int len);
  void emitb(int b);
  void emitw(int w);
--- 118,151 ----
  Symbol *get_symbol(char *name, int create);
  Symbol *set_symbol(Symbol *sym, int value);
  Symbol *zerosym;
+ void destroy_symbol(Symbol *sym, int undef_error);
+ void destroy_locals(void);
+ void add_struct_element(Symbol *s);
+ int set_structor_symbols(Symbol *ele, Symbol *struc, int base, int type);
+ void emit_struct(Symbol *ele, int tp, Symbol *struc);
+ void build_struct(Symbol *ele, int tp, Symbol *struc);
+ int undefs = 0;
  
  struct {
    int regs;
    int offset;
+   int addr16;
+   int addr32;
    int nsyms;
    Symbol *syms[10];
! } _modrm = { 0, 0, 0, 0, 0 };
  
  unsigned char sreg_overrides[] = {
    0x26, 0x2e, 0x36, 0x3e, 0x64, 0x65
  };
  
+ int struct_tp;
+ int struct_pc;
+ char *struct_sym;
+ 
+ int yylex(void);
+ int yylex1(void);
+ 
  void emit(void *v, int len);
  void emitb(int b);
  void emitw(int w);
***************
*** 129,137 ****
--- 153,163 ----
  void emits(Symbol *s, int offset, int rel);
  void modrm(int mod, int reg, int rm);
  void reg(int reg);
+ void addr32(int sib);
  void sortsyms();
  
  int istemp(char *symname, char which);
+ int islocal(char *symname);
  void do_sreg_pop(int sreg);
  void do_sreg_push(int sreg);
  void do_align(int p2, int val);
***************
*** 159,165 ****
  
  %type <sym> ID
  %type <relsym> constID
! %type <i> const offset
  
  %token <sym> KID UID
  
--- 185,191 ----
  
  %type <sym> ID
  %type <relsym> constID
! %type <i> const offset scaledindex
  
  %token <sym> KID UID
  
***************
*** 177,194 ****
  %token <i> JCC JCCL JCXZ LOOP SETCC
  %token <i> SHIFT SHLRD
  %token <i> ONEBYTE TWOBYTE ASCADJ
! %token <i> BITTEST GROUP3 GROUP3B GROUP3D GROUP3W GROUP6 GROUP7
! %token ALIGN
! %token BSS
  %token CALL CALLF COPYRIGHT
! %token DB DD DEC DECB DECD DECW DUP DW
  %token IN INC INCB INCD INCW INT INCLUDE
  %token JMPW JMPB JMPF
! %token LINKCOFF
  %token MOV MOVB MOVD MOVW
  %token IMUL IMULB IMULD IMULW
  %token ORG OUT
! %token POP POPW POPD PUSH PUSHW PUSHD
  %token RCS_ID RET RETF RETD RETFD
  %token STACK START
  %token TEST TESTB TESTD TESTW TYPE
--- 203,220 ----
  %token <i> JCC JCCL JCXZ LOOP SETCC
  %token <i> SHIFT SHLRD
  %token <i> ONEBYTE TWOBYTE ASCADJ
! %token <i> BITTEST GROUP3 GROUP3B GROUP3D GROUP3W GROUP6 GROUP7 STRUCT
! %token ALIGN ARPL
! %token BOUND BSS BSF BSR
  %token CALL CALLF COPYRIGHT
! %token DB DD DEC DECB DECD DECW DUP DW ENDS ENTER
  %token IN INC INCB INCD INCW INT INCLUDE
  %token JMPW JMPB JMPF
! %token LAR LEA LINKCOFF LSL
  %token MOV MOVB MOVD MOVW
  %token IMUL IMULB IMULD IMULW
  %token ORG OUT
! %token POP POPW POPD PUSH PUSHW PUSHB PUSHD
  %token RCS_ID RET RETF RETD RETFD
  %token STACK START
  %token TEST TESTB TESTD TESTW TYPE
***************
*** 204,572 ****
  };
  
  struct opcode opcodes[] = {
!   "aaa", ONEBYTE, 0x37,
!   "aad", ASCADJ, 0xd5,
!   "aam", ASCADJ, 0xd4,
!   "aas", ONEBYTE, 0x3f,
!   "cbw", ONEBYTE, 0x98,
!   "cwde", TWOBYTE, 0x6698,
!   "clc", ONEBYTE, 0xf8,
!   "cld", ONEBYTE, 0xfc,
!   "cli", ONEBYTE, 0xfa,
!   "clts", TWOBYTE, 0x0f06,
!   "cmc", ONEBYTE, 0xf5,
!   "cmpsb", ONEBYTE, 0xa6,
!   "cmpsw", ONEBYTE, 0xa7,
!   "cmpsd", TWOBYTE, 0x66a7,
!   "cpuid", TWOBYTE, 0x0fa2,
!   "cwd", ONEBYTE, 0x99,
!   "cdq", TWOBYTE, 0x6699,
!   "daa", ONEBYTE, 0x27,
!   "das", ONEBYTE, 0x2f,
!   "hlt", ONEBYTE, 0xf4,
!   "insb", ONEBYTE, 0x6c,
!   "insw", ONEBYTE, 0x6d,
!   "insd", TWOBYTE, 0x666d,
!   "into", ONEBYTE, 0xce,
!   "iret", ONEBYTE, 0xcf,
!   "iretd", TWOBYTE, 0x66cf,
!   "lahf", ONEBYTE, 0x9f,
!   "leave", ONEBYTE, 0xc9,
!   "lock", ONEBYTE, 0xf0,
!   "lodsb", ONEBYTE, 0xac,
!   "lodsw", ONEBYTE, 0xad,
!   "lodsd", TWOBYTE, 0x66ad,
!   "movsb", ONEBYTE, 0xa4,
!   "movsw", ONEBYTE, 0xa5,
!   "movsd", TWOBYTE, 0x66a5,
!   "nop", ONEBYTE, 0x90,
!   "outsb", ONEBYTE, 0x6e,
!   "outsw", ONEBYTE, 0x6f,
!   "outsd", TWOBYTE, 0x666f,
!   "popa", ONEBYTE, 0x61,
!   "popad", TWOBYTE, 0x6661,
!   "popf", ONEBYTE, 0x9d,
!   "popfd", TWOBYTE, 0x669d,
!   "pusha", ONEBYTE, 0x60,
!   "pushad", TWOBYTE, 0x6660,
!   "pushf", ONEBYTE, 0x9c,
!   "pushfd", TWOBYTE, 0x669c,
!   "rep", ONEBYTE, 0xf3,
!   "repe", ONEBYTE, 0xf3,
!   "repz", ONEBYTE, 0xf3,
!   "repne", ONEBYTE, 0xf2,
!   "repnz", ONEBYTE, 0xf2,
!   "sahf", ONEBYTE, 0x9e,
!   "scasb", ONEBYTE, 0xae,
!   "scasw", ONEBYTE, 0xaf,
!   "scasd", TWOBYTE, 0x66af,
!   "stc", ONEBYTE, 0xf9,
!   "std", ONEBYTE, 0xfd,
!   "sti", ONEBYTE, 0xfb,
!   "stosb", ONEBYTE, 0xaa,
!   "stosw", ONEBYTE, 0xab,
!   "stosd", TWOBYTE, 0x66ab,
!   "wait", ONEBYTE, 0x9b,
!   "fwait", ONEBYTE, 0x9b,
!   "xlat", ONEBYTE, 0xd7,
!   "xlatb", ONEBYTE, 0xd7,
! 
!   ".addrsize", ONEBYTE, 0x67,
!   ".opsize", ONEBYTE, 0x66,
!   ".segcs", ONEBYTE, 0x2e,
!   ".segds", ONEBYTE, 0x3e,
!   ".seges", ONEBYTE, 0x26,
!   ".segss", ONEBYTE, 0x36,
!   ".segfs", ONEBYTE, 0x64,
!   ".seggs", ONEBYTE, 0x65,
! 
!   ".align", ALIGN, NO_ATTR,
!   ".bss", BSS, NO_ATTR,
!   ".copyright", COPYRIGHT, NO_ATTR,
!   ".db", DB, NO_ATTR,
!   ".dd", DD, NO_ATTR,
!   ".dup", DUP, NO_ATTR,
!   ".dw", DW, NO_ATTR,
!   ".id", RCS_ID, NO_ATTR,
!   ".include", INCLUDE, NO_ATTR,
!   ".linkcoff", LINKCOFF, NO_ATTR,
!   ".org", ORG, NO_ATTR,
!   ".stack", STACK, NO_ATTR,
!   ".start", START, NO_ATTR,
!   ".type", TYPE, NO_ATTR,
! 
!   "adc", ARITH2, 2,
!   "adcb", ARITH2B, 2,
!   "adcd", ARITH2D, 2,
!   "adcw", ARITH2W, 2,
!   "add", ARITH2, 0,
!   "addb", ARITH2B, 0,
!   "addd", ARITH2D, 0,
!   "addw", ARITH2W, 0,
!   "and", ARITH2, 4,
!   "andb", ARITH2B, 4,
!   "andd", ARITH2D, 4,
!   "andw", ARITH2W, 4,
!   "bt", BITTEST, 4,
!   "btc", BITTEST, 7,
!   "btr", BITTEST, 6,
!   "bts", BITTEST, 5,
!   "call", CALL, NO_ATTR,
!   "callf", CALLF, NO_ATTR,
!   "cmp", ARITH2, 7,
!   "cmpb", ARITH2B, 7,
!   "cmpd", ARITH2D, 7,
!   "cmpw", ARITH2W, 7,
!   "dec", DEC, NO_ATTR,
!   "decb", DECB, NO_ATTR,
!   "decd", DECD, NO_ATTR,
!   "decw", DECW, NO_ATTR,
!   "div", GROUP3, 6,
!   "divb", GROUP3B, 6,
!   "divd", GROUP3D, 6,
!   "divw", GROUP3W, 6,
!   "idiv", GROUP3, 7,
!   "idivb", GROUP3B, 7,
!   "idivd", GROUP3D, 7,
!   "idivw", GROUP3W, 7,
!   "imul", IMUL, NO_ATTR,
!   "imulb", IMULB, NO_ATTR,
!   "imuld", IMULD, NO_ATTR,
!   "imulw", IMULW, NO_ATTR,
!   "in", IN, NO_ATTR,
!   "inc", INC, NO_ATTR,
!   "incb", INCB, NO_ATTR,
!   "incd", INCD, NO_ATTR,
!   "incw", INCW, NO_ATTR,
!   "int", INT, NO_ATTR,
! 
!   "jo", JCC, 0,
!   "jno", JCC, 1,
!   "jb", JCC, 2,
!   "jc", JCC, 2,
!   "jnae", JCC, 2,
!   "jnb", JCC, 3,
!   "jnc", JCC, 3,
!   "jae", JCC, 3,
!   "jz", JCC, 4,
!   "je", JCC, 4,
!   "jnz", JCC, 5,
!   "jne", JCC, 5,
!   "jbe", JCC, 6,
!   "jna", JCC, 6,
!   "jnbe", JCC, 7,
!   "ja", JCC, 7,
!   "js", JCC, 8,
!   "jns", JCC, 9,
!   "jp", JCC, 10,
!   "jpe", JCC, 10,
!   "jnp", JCC, 11,
!   "jpo", JCC, 11,
!   "jl", JCC, 12,
!   "jnge", JCC, 12,
!   "jnl", JCC, 13,
!   "jge", JCC, 13,
!   "jle", JCC, 14,
!   "jng", JCC, 14,
!   "jnle", JCC, 15,
!   "jg", JCC, 15,
! 
!   "jol", JCCL, 0,
!   "jnol", JCCL, 1,
!   "jbl", JCCL, 2,
!   "jcl", JCCL, 2,
!   "jnael", JCCL, 2,
!   "jnbl", JCCL, 3,
!   "jncl", JCCL, 3,
!   "jael", JCCL, 3,
!   "jzl", JCCL, 4,
!   "jel", JCCL, 4,
!   "jnzl", JCCL, 5,
!   "jnel", JCCL, 5,
!   "jbel", JCCL, 6,
!   "jnal", JCCL, 6,
!   "jnbel", JCCL, 7,
!   "jal", JCCL, 7,
!   "jsl", JCCL, 8,
!   "jnsl", JCCL, 9,
!   "jpl", JCCL, 10,
!   "jpel", JCCL, 10,
!   "jnpl", JCCL, 11,
!   "jpol", JCCL, 11,
!   "jll", JCCL, 12,
!   "jngel", JCCL, 12,
!   "jnll", JCCL, 13,
!   "jgel", JCCL, 13,
!   "jlel", JCCL, 14,
!   "jngl", JCCL, 14,
!   "jnlel", JCCL, 15,
!   "jgl", JCCL, 15,
! 
!   "jcxz", JCXZ, 0,
!   "jecxz", JCXZ, 1,
! 
!   "jmp", JMPB, NO_ATTR,
!   "jmpf", JMPF, NO_ATTR,
!   "jmpl", JMPW, NO_ATTR,
!   "lds", LXS, 0xc5,
!   "les", LXS, 0xc4,
!   "lfs", LXS, 0x0fb4,
!   "lgs", LXS, 0x0fb5,
!   "lss", LXS, 0x0fb2,
!   "lgdt", GROUP7, 2,
!   "lidt", GROUP7, 3,
!   "lldt", GROUP6, 2,
!   "lmsw", GROUP7, 6,
!   "loop", LOOP, 0xe2,
!   "loope", LOOP, 0xe1,
!   "loopne", LOOP, 0xe0,
!   "loopnz", LOOP, 0xe0,
!   "loopz", LOOP, 0xe1,
!   "ltr", GROUP6, 3,
!   "mov", MOV, NO_ATTR,
!   "movb", MOVB, NO_ATTR,
!   "movd", MOVD, NO_ATTR,
!   "movw", MOVW, NO_ATTR,
!   "movsx", MOVSZX, 0xbe,
!   "movzx", MOVSZX, 0xb6,
!   "mul", GROUP3, 4,
!   "mulb", GROUP3B, 4,
!   "muld", GROUP3D, 4,
!   "mulw", GROUP3W, 4,
!   "not", GROUP3, 2,
!   "neg", GROUP3, 3,
!   "or", ARITH2, 1,
!   "orb", ARITH2B, 1,
!   "ord", ARITH2D, 1,
!   "orw", ARITH2W, 1,
!   "out", OUT, NO_ATTR,
!   "pop", POP, NO_ATTR,
!   "popw", POPW, NO_ATTR,
!   "popd", POPD, NO_ATTR,
!   "push", PUSH, NO_ATTR,
!   "pushw", PUSHW, NO_ATTR,
!   "pushd", PUSHD, NO_ATTR,
!   "rcl", SHIFT, 2,
!   "rcr", SHIFT, 3,
!   "ret", RET, NO_ATTR,
!   "retd", RETD, NO_ATTR,
!   "retf", RETF, NO_ATTR,
!   "retfd", RETFD, NO_ATTR,
!   "rol", SHIFT, 0,
!   "ror", SHIFT, 1,
!   "sar", SHIFT, 7,
!   "sbb", ARITH2, 3,
!   "sbbb", ARITH2B, 3,
!   "sbbd", ARITH2D, 3,
!   "sbbw", ARITH2W, 3,
! 
!   "seto", SETCC, 0,
!   "setno", SETCC, 1,
!   "setb", SETCC, 2,
!   "setc", SETCC, 2,
!   "setnae", SETCC, 2,
!   "setnb", SETCC, 3,
!   "setnc", SETCC, 3,
!   "setae", SETCC, 3,
!   "setz", SETCC, 4,
!   "sete", SETCC, 4,
!   "setnz", SETCC, 5,
!   "setne", SETCC, 5,
!   "setbe", SETCC, 6,
!   "setna", SETCC, 6,
!   "setnbe", SETCC, 7,
!   "seta", SETCC, 7,
!   "sets", SETCC, 8,
!   "setns", SETCC, 9,
!   "setp", SETCC, 10,
!   "setpe", SETCC, 10,
!   "setnp", SETCC, 11,
!   "setpo", SETCC, 11,
!   "setl", SETCC, 12,
!   "setnge", SETCC, 12,
!   "setnl", SETCC, 13,
!   "setge", SETCC, 13,
!   "setle", SETCC, 14,
!   "setng", SETCC, 14,
!   "setnle", SETCC, 15,
!   "setg", SETCC, 15,
! 
!   "sgdt", GROUP7, 0,
!   "sidt", GROUP7, 1,
!   "sldt", GROUP6, 0,
!   "sal", SHIFT, 4,
!   "shl", SHIFT, 4,
!   "shld", SHLRD, 0xa4,
!   "shr", SHIFT, 5,
!   "shrd", SHLRD, 0xac,
!   "smsw", GROUP7, 4,
!   "str", GROUP6, 1,
!   "sub", ARITH2, 5,
!   "subb", ARITH2B, 5,
!   "subd", ARITH2D, 5,
!   "subw", ARITH2W, 5,
!   "test", TEST, NO_ATTR,
!   "testb", TESTB, NO_ATTR,
!   "testw", TESTW, NO_ATTR,
!   "testd", TESTD, NO_ATTR,
!   "verr", GROUP6, 4,
!   "verw", GROUP6, 5,
!   "xchg", XCHG, NO_ATTR,
!   "xor", ARITH2, 6,
!   "xorb", ARITH2B, 6,
!   "xord", ARITH2D, 6,
!   "xorw", ARITH2W, 6,
! 
!   "al", REG8, 0,
!   "cl", REG8, 1,
!   "dl", REG8, 2,
!   "bl", REG8, 3,
!   "ah", REG8, 4,
!   "ch", REG8, 5,
!   "dh", REG8, 6,
!   "bh", REG8, 7,
! 
!   "es", SREG, 0,
!   "cs", SREG, 1,
!   "ss", SREG, 2,
!   "ds", SREG, 3,
!   "fs", SREG, 4,
!   "gs", SREG, 5,
! 
!   "ax", REG16, 0,
!   "cx", REG16, 1,
!   "dx", REG16, 2,
!   "bx", REG16, 3,
!   "sp", REG16, 4,
!   "bp", REG16, 5,
!   "si", REG16, 6,
!   "di", REG16, 7,
! 
!   "eax", REG32, 0,
!   "ecx", REG32, 1,
!   "edx", REG32, 2,
!   "ebx", REG32, 3,
!   "esp", REG32, 4,
!   "ebp", REG32, 5,
!   "esi", REG32, 6,
!   "edi", REG32, 7,
! 
!   "cr0", CRREG, 0,
!   "cr2", CRREG, 2,
!   "cr3", CRREG, 3,
! 
!   "dr0", DRREG, 0,
!   "dr1", DRREG, 1,
!   "dr2", DRREG, 2,
!   "dr3", DRREG, 3,
!   "dr6", DRREG, 6,
!   "dr7", DRREG, 7,
! 
!   "tr3", TRREG, 3,
!   "tr4", TRREG, 4,
!   "tr5", TRREG, 5,
!   "tr6", TRREG, 6,
!   "tr7", TRREG, 7};
  %}
  
  %start lines
--- 230,611 ----
  };
  
  struct opcode opcodes[] = {
!   {"aaa", ONEBYTE, 0x37},
!   {"aad", ASCADJ, 0xd5},
!   {"aam", ASCADJ, 0xd4},
!   {"aas", ONEBYTE, 0x3f},
!   {"cbw", ONEBYTE, 0x98},
!   {"cwde", TWOBYTE, 0x6698},
!   {"clc", ONEBYTE, 0xf8},
!   {"cld", ONEBYTE, 0xfc},
!   {"cli", ONEBYTE, 0xfa},
!   {"clts", TWOBYTE, 0x0f06},
!   {"cmc", ONEBYTE, 0xf5},
!   {"cmpsb", ONEBYTE, 0xa6},
!   {"cmpsw", ONEBYTE, 0xa7},
!   {"cmpsd", TWOBYTE, 0x66a7},
!   {"cpuid", TWOBYTE, 0x0fa2},
!   {"cwd", ONEBYTE, 0x99},
!   {"cdq", TWOBYTE, 0x6699},
!   {"daa", ONEBYTE, 0x27},
!   {"das", ONEBYTE, 0x2f},
!   {"hlt", ONEBYTE, 0xf4},
!   {"insb", ONEBYTE, 0x6c},
!   {"insw", ONEBYTE, 0x6d},
!   {"insd", TWOBYTE, 0x666d},
!   {"into", ONEBYTE, 0xce},
!   {"iret", ONEBYTE, 0xcf},
!   {"iretd", TWOBYTE, 0x66cf},
!   {"lahf", ONEBYTE, 0x9f},
!   {"leave", ONEBYTE, 0xc9},
!   {"lock", ONEBYTE, 0xf0},
!   {"lodsb", ONEBYTE, 0xac},
!   {"lodsw", ONEBYTE, 0xad},
!   {"lodsd", TWOBYTE, 0x66ad},
!   {"movsb", ONEBYTE, 0xa4},
!   {"movsw", ONEBYTE, 0xa5},
!   {"movsd", TWOBYTE, 0x66a5},
!   {"nop", ONEBYTE, 0x90},
!   {"outsb", ONEBYTE, 0x6e},
!   {"outsw", ONEBYTE, 0x6f},
!   {"outsd", TWOBYTE, 0x666f},
!   {"popa", ONEBYTE, 0x61},
!   {"popad", TWOBYTE, 0x6661},
!   {"popf", ONEBYTE, 0x9d},
!   {"popfd", TWOBYTE, 0x669d},
!   {"pusha", ONEBYTE, 0x60},
!   {"pushad", TWOBYTE, 0x6660},
!   {"pushf", ONEBYTE, 0x9c},
!   {"pushfd", TWOBYTE, 0x669c},
!   {"rep", ONEBYTE, 0xf3},
!   {"repe", ONEBYTE, 0xf3},
!   {"repz", ONEBYTE, 0xf3},
!   {"repne", ONEBYTE, 0xf2},
!   {"repnz", ONEBYTE, 0xf2},
!   {"sahf", ONEBYTE, 0x9e},
!   {"scasb", ONEBYTE, 0xae},
!   {"scasw", ONEBYTE, 0xaf},
!   {"scasd", TWOBYTE, 0x66af},
!   {"stc", ONEBYTE, 0xf9},
!   {"std", ONEBYTE, 0xfd},
!   {"sti", ONEBYTE, 0xfb},
!   {"stosb", ONEBYTE, 0xaa},
!   {"stosw", ONEBYTE, 0xab},
!   {"stosd", TWOBYTE, 0x66ab},
!   {"wait", ONEBYTE, 0x9b},
!   {"fwait", ONEBYTE, 0x9b},
!   {"xlat", ONEBYTE, 0xd7},
!   {"xlatb", ONEBYTE, 0xd7},
! 
!   {".addrsize", ONEBYTE, 0x67},
!   {".opsize", ONEBYTE, 0x66},
!   {".segcs", ONEBYTE, 0x2e},
!   {".segds", ONEBYTE, 0x3e},
!   {".seges", ONEBYTE, 0x26},
!   {".segss", ONEBYTE, 0x36},
!   {".segfs", ONEBYTE, 0x64},
!   {".seggs", ONEBYTE, 0x65},
! 
!   {".align", ALIGN, NO_ATTR},
!   {".bss", BSS, NO_ATTR},
!   {".copyright", COPYRIGHT, NO_ATTR},
!   {".db", DB, NO_ATTR},
!   {".dd", DD, NO_ATTR},
!   {".dup", DUP, NO_ATTR},
!   {".dw", DW, NO_ATTR},
!   {".ends",ENDS, NO_ATTR},
!   {".id", RCS_ID, NO_ATTR},
!   {".include", INCLUDE, NO_ATTR},
!   {".linkcoff", LINKCOFF, NO_ATTR},
!   {".org", ORG, NO_ATTR},
!   {".stack", STACK, NO_ATTR},
!   {".start", START, NO_ATTR},
!   {".struct", STRUCT, 's'},
!   {".type", TYPE, NO_ATTR},
!   {".union", STRUCT, 'u'},
! 
!   {"adc", ARITH2, 2},
!   {"adcb", ARITH2B, 2},
!   {"adcd", ARITH2D, 2},
!   {"adcw", ARITH2W, 2},
!   {"add", ARITH2, 0},
!   {"addb", ARITH2B, 0},
!   {"addd", ARITH2D, 0},
!   {"addw", ARITH2W, 0},
!   {"and", ARITH2, 4},
!   {"andb", ARITH2B, 4},
!   {"andd", ARITH2D, 4},
!   {"andw", ARITH2W, 4},
!   {"arpl", ARPL, NO_ATTR},
!   {"bound", BOUND, NO_ATTR},
!   {"bsf", BSF, NO_ATTR},
!   {"bsr", BSR, NO_ATTR},
!   {"bt", BITTEST, 4},
!   {"btc", BITTEST, 7},
!   {"btr", BITTEST, 6},
!   {"bts", BITTEST, 5},
!   {"call", CALL, NO_ATTR},
!   {"callf", CALLF, NO_ATTR},
!   {"cmp", ARITH2, 7},
!   {"cmpb", ARITH2B, 7},
!   {"cmpd", ARITH2D, 7},
!   {"cmpw", ARITH2W, 7},
!   {"dec", DEC, NO_ATTR},
!   {"decb", DECB, NO_ATTR},
!   {"decd", DECD, NO_ATTR},
!   {"decw", DECW, NO_ATTR},
!   {"div", GROUP3, 6},
!   {"divb", GROUP3B, 6},
!   {"divd", GROUP3D, 6},
!   {"divw", GROUP3W, 6},
!   {"enter", ENTER, NO_ATTR},
!   {"idiv", GROUP3, 7},
!   {"idivb", GROUP3B, 7},
!   {"idivd", GROUP3D, 7},
!   {"idivw", GROUP3W, 7},
!   {"imul", IMUL, NO_ATTR},
!   {"imulb", IMULB, NO_ATTR},
!   {"imuld", IMULD, NO_ATTR},
!   {"imulw", IMULW, NO_ATTR},
!   {"in", IN, NO_ATTR},
!   {"inc", INC, NO_ATTR},
!   {"incb", INCB, NO_ATTR},
!   {"incd", INCD, NO_ATTR},
!   {"incw", INCW, NO_ATTR},
!   {"int", INT, NO_ATTR},
! 
!   {"jo", JCC, 0},
!   {"jno", JCC, 1},
!   {"jb", JCC, 2},
!   {"jc", JCC, 2},
!   {"jnae", JCC, 2},
!   {"jnb", JCC, 3},
!   {"jnc", JCC, 3},
!   {"jae", JCC, 3},
!   {"jz", JCC, 4},
!   {"je", JCC, 4},
!   {"jnz", JCC, 5},
!   {"jne", JCC, 5},
!   {"jbe", JCC, 6},
!   {"jna", JCC, 6},
!   {"jnbe", JCC, 7},
!   {"ja", JCC, 7},
!   {"js", JCC, 8},
!   {"jns", JCC, 9},
!   {"jp", JCC, 10},
!   {"jpe", JCC, 10},
!   {"jnp", JCC, 11},
!   {"jpo", JCC, 11},
!   {"jl", JCC, 12},
!   {"jnge", JCC, 12},
!   {"jnl", JCC, 13},
!   {"jge", JCC, 13},
!   {"jle", JCC, 14},
!   {"jng", JCC, 14},
!   {"jnle", JCC, 15},
!   {"jg", JCC, 15},
! 
!   {"jol", JCCL, 0},
!   {"jnol", JCCL, 1},
!   {"jbl", JCCL, 2},
!   {"jcl", JCCL, 2},
!   {"jnael", JCCL, 2},
!   {"jnbl", JCCL, 3},
!   {"jncl", JCCL, 3},
!   {"jael", JCCL, 3},
!   {"jzl", JCCL, 4},
!   {"jel", JCCL, 4},
!   {"jnzl", JCCL, 5},
!   {"jnel", JCCL, 5},
!   {"jbel", JCCL, 6},
!   {"jnal", JCCL, 6},
!   {"jnbel", JCCL, 7},
!   {"jal", JCCL, 7},
!   {"jsl", JCCL, 8},
!   {"jnsl", JCCL, 9},
!   {"jpl", JCCL, 10},
!   {"jpel", JCCL, 10},
!   {"jnpl", JCCL, 11},
!   {"jpol", JCCL, 11},
!   {"jll", JCCL, 12},
!   {"jngel", JCCL, 12},
!   {"jnll", JCCL, 13},
!   {"jgel", JCCL, 13},
!   {"jlel", JCCL, 14},
!   {"jngl", JCCL, 14},
!   {"jnlel", JCCL, 15},
!   {"jgl", JCCL, 15},
! 
!   {"jcxz", JCXZ, 0},
!   {"jecxz", JCXZ, 1},
! 
!   {"jmp", JMPB, NO_ATTR},
!   {"jmpf", JMPF, NO_ATTR},
!   {"jmpl", JMPW, NO_ATTR},
!   {"lar", LAR, NO_ATTR},
!   {"lds", LXS, 0xc5},
!   {"lea", LEA, NO_ATTR},
!   {"les", LXS, 0xc4},
!   {"lfs", LXS, 0x0fb4},
!   {"lgs", LXS, 0x0fb5},
!   {"lsl", LSL, NO_ATTR},
!   {"lss", LXS, 0x0fb2},
!   {"lgdt", GROUP7, 2},
!   {"lidt", GROUP7, 3},
!   {"lldt", GROUP6, 2},
!   {"lmsw", GROUP7, 6},
!   {"loop", LOOP, 0xe2},
!   {"loope", LOOP, 0xe1},
!   {"loopne", LOOP, 0xe0},
!   {"loopnz", LOOP, 0xe0},
!   {"loopz", LOOP, 0xe1},
!   {"ltr", GROUP6, 3},
!   {"mov", MOV, NO_ATTR},
!   {"movb", MOVB, NO_ATTR},
!   {"movd", MOVD, NO_ATTR},
!   {"movw", MOVW, NO_ATTR},
!   {"movsx", MOVSZX, 0xbe},
!   {"movzx", MOVSZX, 0xb6},
!   {"mul", GROUP3, 4},
!   {"mulb", GROUP3B, 4},
!   {"muld", GROUP3D, 4},
!   {"mulw", GROUP3W, 4},
!   {"not", GROUP3, 2},
!   {"neg", GROUP3, 3},
!   {"or", ARITH2, 1},
!   {"orb", ARITH2B, 1},
!   {"ord", ARITH2D, 1},
!   {"orw", ARITH2W, 1},
!   {"out", OUT, NO_ATTR},
!   {"pop", POP, NO_ATTR},
!   {"popw", POPW, NO_ATTR},
!   {"popd", POPD, NO_ATTR},
!   {"push", PUSH, NO_ATTR},
!   {"pushb", PUSHB, NO_ATTR},
!   {"pushw", PUSHW, NO_ATTR},
!   {"pushd", PUSHD, NO_ATTR},
!   {"rcl", SHIFT, 2},
!   {"rcr", SHIFT, 3},
!   {"ret", RET, NO_ATTR},
!   {"retd", RETD, NO_ATTR},
!   {"retf", RETF, NO_ATTR},
!   {"retfd", RETFD, NO_ATTR},
!   {"rol", SHIFT, 0},
!   {"ror", SHIFT, 1},
!   {"sar", SHIFT, 7},
!   {"sbb", ARITH2, 3},
!   {"sbbb", ARITH2B, 3},
!   {"sbbd", ARITH2D, 3},
!   {"sbbw", ARITH2W, 3},
! 
!   {"seto", SETCC, 0},
!   {"setno", SETCC, 1},
!   {"setb", SETCC, 2},
!   {"setc", SETCC, 2},
!   {"setnae", SETCC, 2},
!   {"setnb", SETCC, 3},
!   {"setnc", SETCC, 3},
!   {"setae", SETCC, 3},
!   {"setz", SETCC, 4},
!   {"sete", SETCC, 4},
!   {"setnz", SETCC, 5},
!   {"setne", SETCC, 5},
!   {"setbe", SETCC, 6},
!   {"setna", SETCC, 6},
!   {"setnbe", SETCC, 7},
!   {"seta", SETCC, 7},
!   {"sets", SETCC, 8},
!   {"setns", SETCC, 9},
!   {"setp", SETCC, 10},
!   {"setpe", SETCC, 10},
!   {"setnp", SETCC, 11},
!   {"setpo", SETCC, 11},
!   {"setl", SETCC, 12},
!   {"setnge", SETCC, 12},
!   {"setnl", SETCC, 13},
!   {"setge", SETCC, 13},
!   {"setle", SETCC, 14},
!   {"setng", SETCC, 14},
!   {"setnle", SETCC, 15},
!   {"setg", SETCC, 15},
! 
!   {"sgdt", GROUP7, 0},
!   {"sidt", GROUP7, 1},
!   {"sldt", GROUP6, 0},
!   {"sal", SHIFT, 4},
!   {"shl", SHIFT, 4},
!   {"shld", SHLRD, 0xa4},
!   {"shr", SHIFT, 5},
!   {"shrd", SHLRD, 0xac},
!   {"smsw", GROUP7, 4},
!   {"str", GROUP6, 1},
!   {"sub", ARITH2, 5},
!   {"subb", ARITH2B, 5},
!   {"subd", ARITH2D, 5},
!   {"subw", ARITH2W, 5},
!   {"test", TEST, NO_ATTR},
!   {"testb", TESTB, NO_ATTR},
!   {"testw", TESTW, NO_ATTR},
!   {"testd", TESTD, NO_ATTR},
!   {"verr", GROUP6, 4},
!   {"verw", GROUP6, 5},
!   {"xchg", XCHG, NO_ATTR},
!   {"xor", ARITH2, 6},
!   {"xorb", ARITH2B, 6},
!   {"xord", ARITH2D, 6},
!   {"xorw", ARITH2W, 6},
! 
!   {"al", REG8, 0},
!   {"cl", REG8, 1},
!   {"dl", REG8, 2},
!   {"bl", REG8, 3},
!   {"ah", REG8, 4},
!   {"ch", REG8, 5},
!   {"dh", REG8, 6},
!   {"bh", REG8, 7},
! 
!   {"es", SREG, 0},
!   {"cs", SREG, 1},
!   {"ss", SREG, 2},
!   {"ds", SREG, 3},
!   {"fs", SREG, 4},
!   {"gs", SREG, 5},
! 
!   {"ax", REG16, 0},
!   {"cx", REG16, 1},
!   {"dx", REG16, 2},
!   {"bx", REG16, 3},
!   {"sp", REG16, 4},
!   {"bp", REG16, 5},
!   {"si", REG16, 6},
!   {"di", REG16, 7},
! 
!   {"eax", REG32, 0},
!   {"ecx", REG32, 1},
!   {"edx", REG32, 2},
!   {"ebx", REG32, 3},
!   {"esp", REG32, 4},
!   {"ebp", REG32, 5},
!   {"esi", REG32, 6},
!   {"edi", REG32, 7},
! 
!   {"cr0", CRREG, 0},
!   {"cr2", CRREG, 2},
!   {"cr3", CRREG, 3},
! 
!   {"dr0", DRREG, 0},
!   {"dr1", DRREG, 1},
!   {"dr2", DRREG, 2},
!   {"dr3", DRREG, 3},
!   {"dr6", DRREG, 6},
!   {"dr7", DRREG, 7},
! 
!   {"tr3", TRREG, 3},
!   {"tr4", TRREG, 4},
!   {"tr5", TRREG, 5},
!   {"tr6", TRREG, 6},
!   {"tr7", TRREG, 7},
! };
  %}
  
  %start lines
***************
*** 586,591 ****
--- 625,644 ----
  	| ID ':'			{ set_symbol($1, pc)->type |= (pc?SYM_data:SYM_code); }
  	| ID '=' const			{ set_symbol($1, $3)->type = SYM_abs; }
  	| ID '=' PC offset		{ set_symbol($1, pc + $4)->type = SYM_abs; }
+ 	| ID '=' const '-' PC		{ set_symbol($1, $3 - pc)->type = SYM_abs; }
+ 	| STRUCT ID '\n'		{ struct_pc=0;
+ 					  struct_tp=$1;
+ 					  struct_sym=$2->name;
+ 					  lineno++;
+ 					  $<sym>$=symtab;
+ 					  symtab=symtab->next;
+ 					}
+ 	  struct_lines
+ 	  ENDS				{ set_symbol($2, struct_pc)->type = SYM_abs;
+ 					  $<sym>4->next=symtab;
+ 					  symtab=$<sym>4;
+ 	  				}
+ 	| ID STRUCT ID			{ emit_struct($1,$2,$3); }
  	| error
  
  	| ONEBYTE			{ emitb($1); }
***************
*** 607,617 ****
  	| ARITH2 REG8 ',' regmem	{ emitb($1*8+2); reg($2); }
  
  	| ARITH2W regmem ',' constID	{ emitb(0x81); reg($1); emits($4.sym,$4.ofs,REL_abs); }
! 	| ARITH2 REG16 ',' constID	{ if ($2)
! 					      {emitb(0x81); modrm(3, $1, $2);}
! 					  else
  					      modrm (0,$1,5);
! 					  emits($4.sym,$4.ofs,REL_abs);
  					}
  	| ARITH2 REG16 ',' REG16	{ emitb($1*8+1); modrm(3, $4, $2); }
  	| ARITH2 regmem ',' REG16	{ emitb($1*8+1); reg($4); }
--- 660,678 ----
  	| ARITH2 REG8 ',' regmem	{ emitb($1*8+2); reg($2); }
  
  	| ARITH2W regmem ',' constID	{ emitb(0x81); reg($1); emits($4.sym,$4.ofs,REL_abs); }
! 	| ARITH2 REG16 ',' constID	{ if ($2) {
! 					      int v=$4.ofs+$4.sym->value;
! 					      if ($4.sym->defined && v>=-128 && v<=127) {
! 						  emitb(0x83); modrm(3, $1, $2);
! 						  emits($4.sym,$4.ofs,REL_abs8);
! 					      } else {
! 						  emitb(0x81); modrm(3, $1, $2);
! 						  emits($4.sym,$4.ofs,REL_abs);
! 					      }
! 					  } else {
  					      modrm (0,$1,5);
! 					      emits($4.sym,$4.ofs,REL_abs);
! 					  }
  					}
  	| ARITH2 REG16 ',' REG16	{ emitb($1*8+1); modrm(3, $4, $2); }
  	| ARITH2 regmem ',' REG16	{ emitb($1*8+1); reg($4); }
***************
*** 619,639 ****
  
  	| ARITH2D regmem ',' constID	{ emitb(0x66); emitb(0x81); reg($1); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  	| ARITH2 REG32 ',' constID	{ emitb(0x66);
! 					  if ($2)
! 					      {emitb(0x81); modrm(3, $1, $2);}
! 					  else
  					      modrm (0,$1,5);
! 					  emits($4.sym,$4.ofs,REL_abs);	emitw($4.ofs >>	16); }
  	| ARITH2 REG32 ',' REG32	{ emitb(0x66); emitb($1*8+1); modrm(3, $4, $2); }
  	| ARITH2 regmem ',' REG32	{ emitb(0x66); emitb($1*8+1); reg($4); }
  	| ARITH2 REG32 ',' regmem	{ emitb(0x66); emitb($1*8+3); reg($2); }
  
  	| ASCADJ			{ emitb($1); emitb(0x0a); }
  	| ASCADJ const			{ emitb($1); emitb($2); }
  
  	| ALIGN const			{ do_align($2,0x90); }
  	| ALIGN const ',' const		{ do_align($2,$4); }
  
  	| BITTEST REG16 ',' REG16	{ emitb(0x0f); emitb($1*8+0x83); modrm(3, $4, $2); }
  	| BITTEST regmem ',' REG16	{ emitb(0x0f); emitb($1*8+0x83); reg($4); }
  	| BITTEST REG32 ',' REG32	{ emitb(0x66); emitb(0x0f); emitb($1*8+0x83); modrm(3, $4, $2); }
--- 680,715 ----
  
  	| ARITH2D regmem ',' constID	{ emitb(0x66); emitb(0x81); reg($1); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  	| ARITH2 REG32 ',' constID	{ emitb(0x66);
! 					  if ($2) {
! 					      int v=$4.ofs+$4.sym->value;
! 					      if ($4.sym->defined && v>=-128 && v<=127) {
! 						  emitb(0x83); modrm(3, $1, $2);
! 						  emits($4.sym,$4.ofs,REL_abs8);
! 					      } else {
! 						  emitb(0x81); modrm(3, $1, $2);
! 						  emits($4.sym,$4.ofs,REL_abs32);
! 					      }
! 					  } else {
  					      modrm (0,$1,5);
! 					      emits($4.sym,$4.ofs,REL_abs32);
! 					  }
! 					}
  	| ARITH2 REG32 ',' REG32	{ emitb(0x66); emitb($1*8+1); modrm(3, $4, $2); }
  	| ARITH2 regmem ',' REG32	{ emitb(0x66); emitb($1*8+1); reg($4); }
  	| ARITH2 REG32 ',' regmem	{ emitb(0x66); emitb($1*8+3); reg($2); }
  
+ 	| ARPL REG16 ',' REG16		{ emitb(0x63); modrm(3,$4,$2); }
+ 	| ARPL regmem ',' REG16		{ emitb(0x63); reg($4); }
+ 
  	| ASCADJ			{ emitb($1); emitb(0x0a); }
  	| ASCADJ const			{ emitb($1); emitb($2); }
  
  	| ALIGN const			{ do_align($2,0x90); }
  	| ALIGN const ',' const		{ do_align($2,$4); }
  
+ 	| BOUND REG16 ',' regmem	{ emitb(0x62); reg($2); }
+ 	| BOUND REG32 ',' regmem	{ emitb(0x66); emitb(0x62); reg($2); }
+ 
  	| BITTEST REG16 ',' REG16	{ emitb(0x0f); emitb($1*8+0x83); modrm(3, $4, $2); }
  	| BITTEST regmem ',' REG16	{ emitb(0x0f); emitb($1*8+0x83); reg($4); }
  	| BITTEST REG32 ',' REG32	{ emitb(0x66); emitb(0x0f); emitb($1*8+0x83); modrm(3, $4, $2); }
***************
*** 642,649 ****
--- 718,736 ----
  	| BITTEST regmem ',' const	{ emitb(0x0f); emitb(0xba); reg($1); emitb($4); }
  	| BITTEST REG32 ',' const	{ emitb(0x66); emitb(0x0f); emitb(0xba); modrm(3, $1, $2); emitb($4); }
  
+ 	| BSF REG16 ',' REG16		{ emitb(0x0f); emitb(0xbc); modrm(3, $4, $2); }
+ 	| BSF REG16 ',' regmem		{ emitb(0x0f); emitb(0xbc); reg($2); }
+ 	| BSF REG32 ',' REG32		{ emitb(0x66); emitb(0x0f); emitb(0xbc); modrm(3, $4, $2); }
+ 	| BSF REG32 ',' regmem		{ emitb(0x66); emitb(0x0f); emitb(0xbc); reg($2); }
+ 
+ 	| BSR REG16 ',' REG16		{ emitb(0x0f); emitb(0xbd); modrm(3, $4, $2); }
+ 	| BSR REG16 ',' regmem		{ emitb(0x0f); emitb(0xbd); reg($2); }
+ 	| BSR REG32 ',' REG32		{ emitb(0x66); emitb(0x0f); emitb(0xbd); modrm(3, $4, $2); }
+ 	| BSR REG32 ',' regmem		{ emitb(0x66); emitb(0x0f); emitb(0xbd); reg($2); }
+ 
  	| CALL ID			{ emitb(0xe8); emits($2,0,REL_16); $2->type |= SYM_code; }
  	| CALLF regmem			{ emitb(0xff); reg(3); }
+ 	| CALLF const ':' constID	{ emitb(0x9a); emits($4.sym,$4.ofs,REL_abs); emitw($2); }
  
  	| COPYRIGHT STRING		{ strbuf[strbuflen] = 0; add_copyright(strbuf); }
  	| RCS_ID			{ strbuf[strbuflen] = 0; add_rcs_ident(strbuf); }
***************
*** 659,664 ****
--- 746,753 ----
  	| DECW regmem			{ emitb(0xff); reg(1); }
  	| DECD regmem			{ emitb(0x66); emitb(0xff); reg(1); }
  
+ 	| ENTER const ',' const		{ emitb(0xc8); emitw($2); emitb($4); }
+ 
  	| IN REG8 ',' const		{ emitb(0xe4); emitb($4); }
  	| IN REG16 ',' const		{ emitb(0xe5); emitb($4); }
  	| IN REG32 ',' const		{ emitb(0x66); emitb(0xe5); emitb($4);}
***************
*** 729,737 ****
--- 818,835 ----
  	| JMPF regmem			{ emitb(0xff); reg(5); }
  	| JMPF const ':' constID	{ emitb(0xea); emits($4.sym,$4.ofs,REL_abs); emitw($2); }
  
+ 	| LAR REG16 ',' REG16		{ emitb(0x0f); emitb(0x02); modrm(3, $4, $2); }
+ 	| LAR REG16 ',' regmem		{ emitb(0x0f); emitb(0x02); reg($2); }
+ 
+ 	| LEA REG16 ',' regmem		{ emitb(0x8d); reg($2); }
+ 	| LEA REG32 ',' regmem		{ emitb(0x66); emitb(0x8d); reg($2); }
+ 
  	| LINKCOFF STRING		{ strbuf[strbuflen]=0; do_linkcoff(strbuf); }
  	| LOOP ID			{ emitb($1); emits($2,0,REL_8); }
  
+ 	| LSL REG16 ',' REG16		{ emitb(0x0f); emitb(0x03); modrm(3, $4, $2); }
+ 	| LSL REG16 ',' regmem		{ emitb(0x0f); emitb(0x03); reg($2); }
+ 
  	| LXS REG16 ',' regmem		{ if ($1>>8) emitb($1>>8); emitb($1 & 0xff); reg($2); }
  	| LXS REG32 ',' regmem		{ emitb(0x66); if ($1>>8) emitb($1>>8); emitb($1 & 0xff); reg($2); }
  
***************
*** 818,823 ****
--- 916,922 ----
  	| PUSH SREG			{ do_sreg_push($2); }
  	| PUSHW regmem			{ emitb(0xff); reg(6); }
  	| PUSHD regmem			{ emitb(0x66); emitb(0xff); reg(6); }
+ 	| PUSHB const			{ emitb(0x6a); emitb($2); }
  	| PUSHW constID			{ emitb(0x68); emits($2.sym,$2.ofs,REL_abs); }
  	| PUSHD constID			{ emitb(0x66); emitb(0x68); emits($2.sym,$2.ofs,REL_abs); emitw($2.ofs >> 16); }
  
***************
*** 890,895 ****
--- 989,1048 ----
  	| XCHG regmem ',' REG32		{ emitb(0x66); emitb(0x87); reg($4); }
  	;
  
+ struct_lines
+ 	:
+ 	| struct_lines struct_line '\n'	{ lineno++; }
+ 	;
+ 
+ struct_line
+ 	:
+ 	| ID ':'			{ add_struct_element($1); }
+ 	| ID STRUCT ID			{ build_struct($1,$2,$3); }
+ 	| struct_db
+ 	| ID				{ add_struct_element($1); }
+ 	  struct_db
+ 	;
+ 
+ struct_db
+ 	: DB				{ if (struct_tp=='s') {
+ 					      struct_pc++;
+ 					  } else {
+ 					      struct_pc=MAX(struct_pc,1);
+ 					  }
+ 					}
+ 	| DB const DUP			{ if (struct_tp=='s') {
+ 					      struct_pc+=$2;
+ 					  } else {
+ 					      struct_pc=MAX(struct_pc,$2);
+ 					  }
+ 					}
+ 	| DW				{ if (struct_tp=='s') {
+ 					      struct_pc+=2;
+ 					  } else {
+ 					      struct_pc=MAX(struct_pc,2);
+ 					  }
+ 					}
+ 	| DW const DUP			{ if (struct_tp=='s') {
+ 					      struct_pc+=2*$2;
+ 					  } else {
+ 					      struct_pc=MAX(struct_pc,2*$2);
+ 					  }
+ 					}
+ 	| DD				{ if (struct_tp=='s') {
+ 					      struct_pc+=4;
+ 					  } else {
+ 					      struct_pc=MAX(struct_pc,4);
+ 					  }
+ 					}
+ 	| DD const DUP			{ if (struct_tp=='s') {
+ 					      struct_pc+=4*$2;
+ 					  } else {
+ 					      struct_pc=MAX(struct_pc,4*$2);
+ 					  }
+ 					}
+ 	;
+  
+ 
  dbitem
  	: const				{ emitb($1); }
  	| STRING			{ emit(strbuf, strbuflen); }
***************
*** 937,947 ****
  
  regmemitem
  	: SREG ':' regmemitem		{ emitb(sreg_overrides[$1]); }
! 	| REG16				{ _modrm.regs |= (1<<$1); }
  	| UID				{ _modrm.syms[_modrm.nsyms++] = $1; }
  	| const				{ _modrm.offset += $1; }
  	;
  
  const
  	: NUMBER			{ $$ = $1; }
  	| KID				{ $$ = $1->value; }
--- 1090,1133 ----
  
  regmemitem
  	: SREG ':' regmemitem		{ emitb(sreg_overrides[$1]); }
! 	| REG16				{ if (_modrm.addr32) {
! 					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
! 					      yyerror("Cannot mix 16 and 32 bit addressing");
! 					  } else {
! 					      _modrm.regs |= (1<<$1);
! 					      _modrm.addr16=1;
! 					  }
! 					}
! 	| REG32				{ addr32((1<<$1)|0x100); }
! 	| scaledindex			{ addr32($1); }
  	| UID				{ _modrm.syms[_modrm.nsyms++] = $1; }
  	| const				{ _modrm.offset += $1; }
  	;
  
+ scaledindex
+ 	: REG32 '*' const		{ if ($3==1 || $3==2 || $3==4 || $3==8)
+ 					      $$ = (1<<($1)) | ($3<<8);
+ 					  else {
+ 					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
+ 					      yyerror("Scale must be 1,2,4 or 8");
+ 					  }
+ 					}
+ 	| const '*' REG32		{ if ($1==1 || $1==2 || $1==4 || $1==8)
+ 					      $$ = (1<<($3)) | ($1<<8);
+ 					  else {
+ 					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
+ 					      yyerror("Scale must be 1,2,4 or 8");
+ 					  }
+ 					}
+ 	| REG32 OP_SHL const		{ if ($3>=0 && $3<=3)
+ 					      $$ = (1<<($1)) | (0x100<<$3);
+ 					  else {
+ 					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
+ 					      yyerror("Shift must be 0,1,2 or 3");
+ 					  }
+ 					}
+ 	;
+ 
  const
  	: NUMBER			{ $$ = $1; }
  	| KID				{ $$ = $1->value; }
***************
*** 1014,1025 ****
    return strcmp (((struct opcode *)e1)->name, ((struct opcode *)e2)->name);
  }
  
! main(int argc, char **argv)
  {
    Symbol *s;
    Patch *p;
    unsigned char exe[EXE_HEADER_SIZE+4];
-   int undefs=0;
    int symcount = 0;
    int min_uninit;
    time_t now;
--- 1200,1210 ----
    return strcmp (((struct opcode *)e1)->name, ((struct opcode *)e2)->name);
  }
  
! int main(int argc, char **argv)
  {
    Symbol *s;
    Patch *p;
    unsigned char exe[EXE_HEADER_SIZE+4];
    int symcount = 0;
    int min_uninit;
    time_t now;
***************
*** 1034,1040 ****
  
    if (argc < 2)
    {
!     printf("usage: djasm infile [outfile] [mapfile]\n");
      exit(1);
    }
    inname = argv[1];
--- 1219,1225 ----
  
    if (argc < 2)
    {
!     fprintf(stderr,"usage: djasm infile [outfile] [mapfile]\n");
      exit(1);
    }
    inname = argv[1];
***************
*** 1063,1069 ****
      {
        fprintf(stderr, "Undefined symbol `%s', first used on line %d\n", s->name, s->first_used);
        for (p=s->patches; p; p=p->next)
!         printf("\treferenced on line %d\n", p->lineno);
        undefs++;
      }
    }
--- 1248,1254 ----
      {
        fprintf(stderr, "Undefined symbol `%s', first used on line %d\n", s->name, s->first_used);
        for (p=s->patches; p; p=p->next)
!         fprintf(stderr,"\treferenced on line %d\n", p->lineno);
        undefs++;
      }
    }
***************
*** 1166,1171 ****
--- 1351,1357 ----
      case OUT_exe:
      case OUT_com:
      case OUT_bin:
+     case OUT_sys:
        outfile = fopen(outfilename, "wb");
        break;
      case OUT_h:
***************
*** 1193,1198 ****
--- 1379,1385 ----
        break;
  
      case OUT_bin:
+     case OUT_sys:
        fwrite(outbin, bsspc, 1, outfile);
        break;
  
***************
*** 1222,1248 ****
          leader = INC_LEADER;
        else
          leader = S_LEADER;
        if (image_type == OUT_exe)
          for (i=0; i<EXE_HEADER_SIZE; i++)
          {
- 	  if ((i%15) == 0)
- 	    fputs(leader, outfile);
            fprintf(outfile, "0x%02x", exe[i]);
            if ((i&15) == 15)
            {
              fputc('\n', outfile);
            }
            else
              fputc(',', outfile);
          }
        for (i=((image_type==OUT_com)?0x100:0); i<bsspc; i++)
        {
- 	if ((i&15) == 0)
- 	  fputs(leader, outfile);
          fprintf(outfile, "0x%02x", outbin[i]);
          if ((i&15) == 15)
          {
            fputc('\n', outfile);
          }
          else
            if (i<bsspc-1)
--- 1409,1434 ----
          leader = INC_LEADER;
        else
          leader = S_LEADER;
+       fputs(leader, outfile);
        if (image_type == OUT_exe)
          for (i=0; i<EXE_HEADER_SIZE; i++)
          {
            fprintf(outfile, "0x%02x", exe[i]);
            if ((i&15) == 15)
            {
              fputc('\n', outfile);
+             fputs(leader, outfile);
            }
            else
              fputc(',', outfile);
          }
        for (i=((image_type==OUT_com)?0x100:0); i<bsspc; i++)
        {
          fprintf(outfile, "0x%02x", outbin[i]);
          if ((i&15) == 15)
          {
            fputc('\n', outfile);
+           fputs(leader, outfile);
          }
          else
            if (i<bsspc-1)
***************
*** 1284,1296 ****
      fputc('\n', mapfile);
      fclose(mapfile);
    }
  }
  
  void yyerror(char *s)
  {
    fprintf(stderr, "%s:%d: %s\n", inname, lineno, s);
    strbuf[strbuflen] = 0;
!   fprintf(stderr, "Last token was `%s' (%s)\n", last_token, yytname[yytranslate[last_tret]]);
    total_errors++;
  }
  
--- 1470,1483 ----
      fputc('\n', mapfile);
      fclose(mapfile);
    }
+   return 0;
  }
  
  void yyerror(char *s)
  {
    fprintf(stderr, "%s:%d: %s\n", inname, lineno, s);
    strbuf[strbuflen] = 0;
!   fprintf(stderr, "Last token was `%s' (%s)\n", last_token, yytname[(unsigned char)yytranslate[last_tret]]);
    total_errors++;
  }
  
***************
*** 1315,1331 ****
    return s;
  }
  
  Symbol *set_symbol(Symbol *s, int value)
  {
    if (istemp(s->name, 'b'))
      s->defined = 0;
    if (s->defined)
!     printf("Warning: symbol %s redefined\n", s->name);
    s->value = value;
    s->defined = 1;
    while (s->patches)
    {
!     int v, o;
      unsigned char *cp;
      Patch *p = s->patches;
      s->patches = s->patches->next;
--- 1502,1620 ----
    return s;
  }
  
+ void add_struct_element(Symbol *s)
+ {
+   if (islocal(s->name) || istemp(s->name,0)) {
+     yyerror("Cannot have local or temporary labels within a structure");
+   } else {
+     char *id=alloca(strlen(s->name)+strlen(struct_sym)+2);
+     strcpy(id,struct_sym);
+     strcat(id,".");
+     strcat(id,s->name);
+     if (!s->defined && !s->patches) {
+       /* only delete fresh symbols */
+       destroy_symbol(s,0);
+     }
+     if (struct_tp=='s') {
+       /* .struct */
+       set_symbol(get_symbol(id,1),struct_pc);
+     } else {
+       /* .union */
+       set_symbol(get_symbol(id,1),0);
+     }
+   }
+ }
+ 
+ int is_structure(Symbol *s)
+ {
+   char *n=s->name;
+   size_t l=strlen(n);
+   if (!s->next) {
+     /* the elements of a struct or union always follow the symbol */
+     return 0;
+   }
+   s=s->next;
+   if (strncmp(n,s->name,l) || s->name[l]!='.') {
+     /* Structure elements always have the structure name followed by a period before
+      * the element name.
+      */
+     return 0;
+   }
+   return 1;
+ }
+ 
+ int set_structure_symbols(Symbol *ele, Symbol *struc, int tp, int base, int type)
+ {
+   if (tp!='s') {
+     yyerror("must use `.struct' to emit structures or unions");
+     return 0;
+   }
+   if (!struc->defined) {
+     yyerror("undefined symbol used in struct");
+     return 0;
+   }
+   if (!is_structure(struc)) {
+     yyerror("symbol must be a .struct or .union");
+     return 0;
+   }
+   set_symbol(ele,base)->type|=type;
+   {
+     int sLen=strlen(struc->name);
+     int eLen=strlen(ele->name);
+     Symbol *s=struc->next;
+     while (s && !strncmp(s->name,struc->name,sLen) && s->name[sLen]=='.') {
+       char *id=alloca(strlen(s->name)-sLen+eLen+1);
+       strcpy(id,ele->name);
+       strcpy(id+eLen,s->name+sLen);
+       set_symbol(get_symbol(id,1),base+s->value)->type|=type;
+       s=s->next;
+     }
+   }
+   return 1;
+ }
+ 
+ void emit_struct(Symbol *ele, int tp, Symbol *struc)
+ {
+   int i;
+ 
+   if (set_structure_symbols(ele,struc,tp,pc,(pc?SYM_data:SYM_code)))
+     for (i=0; i<struc->value; i++) emitb(0); /* only unitialized structures supported */
+ }
+ 
+ void build_struct(Symbol *ele, int tp, Symbol *struc)
+ {
+   if (islocal(ele->name) || istemp(ele->name,0)) {
+     yyerror("Cannot have local or temporary labels within a structure");
+   } else {
+     char *id=alloca(strlen(ele->name)+strlen(struct_sym)+2);
+     strcpy(id,struct_sym);
+     strcat(id,".");
+     strcat(id,ele->name);
+     if (!ele->defined && !ele->patches) {
+       /* only delete fresh symbols */
+       destroy_symbol(ele,0);
+     }
+     set_structure_symbols(get_symbol(id,1),struc,tp,struct_pc,0);
+     if (struct_tp=='s')
+       struct_pc+=struc->value;
+     else
+       struct_pc+=MAX(struct_pc,struc->value);
+   }
+ }
+ 					
  Symbol *set_symbol(Symbol *s, int value)
  {
+   if (!islocal(s->name) && !istemp(s->name,0))
+     destroy_locals();
    if (istemp(s->name, 'b'))
      s->defined = 0;
    if (s->defined)
!     fprintf(stderr,"Warning: symbol %s redefined\n", s->name);
    s->value = value;
    s->defined = 1;
    while (s->patches)
    {
!     int v=0, o=0;
      unsigned char *cp;
      Patch *p = s->patches;
      s->patches = s->patches->next;
***************
*** 1388,1393 ****
--- 1677,1742 ----
    return s;
  }
  
+ void destroy_symbol(Symbol *sym, int undef_error)
+ {
+   Symbol **s=&symtab;
+   while (*s)
+   {
+     if (*s==sym)
+     {
+       Symbol *_s=*s;
+       if (undef_error && !_s->defined && _s->patches)
+       {
+ 	Patch *p,*_p;
+ 	fprintf(stderr, "Undefined symbol `%s', first used on line %d\n", _s->name, _s->first_used);
+ 	for (p=_s->patches; p; p=_p) {
+ 	  fprintf(stderr,"\treferenced on line %d\n", p->lineno);
+ 	  _p=p->next;
+ 	  free(p);
+ 	}
+ 	undefs++;
+       }
+       _s=(*s)->next;
+       free(*s);
+       *s=_s;
+     }
+     else
+     {
+       s=&(*s)->next;
+     }
+   }
+ }
+ 
+ void destroy_locals(void)
+ {
+   Symbol **s=&symtab;
+   while (*s)
+   {
+     if (islocal((*s)->name))
+     {
+       Symbol *_s=*s;
+       if (!_s->defined && _s->patches)
+       {
+ 	Patch *p,*_p;
+ 	fprintf(stderr, "Undefined symbol `%s', first used on line %d\n", _s->name, _s->first_used);
+ 	for (p=_s->patches; p; p=_p) {
+ 	  fprintf(stderr,"\treferenced on line %d\n", p->lineno);
+ 	  _p=p->next;
+ 	  free(p);
+ 	}
+ 	undefs++;
+       }
+       _s=(*s)->next;
+       free(*s);
+       *s=_s;
+     }
+     else
+     {
+       s=&(*s)->next;
+     }
+   }
+ }
+ 
  void sortsyms(int (*sortf)(void const *,void const *))
  {
    int ns, i;
***************
*** 1452,1457 ****
--- 1801,1810 ----
        v = s->value + offset;
        emitw(v);
        break;
+     case REL_abs8:
+       v = s->value + offset;
+       emitb(v);
+       break;
      case REL_16:
        v = s->value - pc - 2 + offset;
        emitw(v);
***************
*** 1460,1466 ****
        v = s->value - pc - 1 + offset;
        if (v < -128 || v > 127)
        {
! 	fprintf(stderr, "%s:%d: 8-bit relocation too big (%d); use long form", inname, lineno, v);
  	total_errors++;
        }
        emitb(v);
--- 1813,1819 ----
        v = s->value - pc - 1 + offset;
        if (v < -128 || v > 127)
        {
! 	fprintf(stderr, "%s:%d: 8-bit relocation too big (%d); use long form\n", inname, lineno, v);
  	total_errors++;
        }
        emitb(v);
***************
*** 1486,1492 ****
    case REL_8:
      if (offset < -128 || offset > 127)
      {
!       fprintf(stderr, "%s:%d: 8-bit relocation offset too big (%d); use long form", inname, lineno, offset);
        total_errors++;
      }
      emitb(offset);
--- 1839,1845 ----
    case REL_8:
      if (offset < -128 || offset > 127)
      {
!       fprintf(stderr, "%s:%d: 8-bit relocation offset too big (%d); use long form\n", inname, lineno, offset);
        total_errors++;
      }
      emitb(offset);
***************
*** 1499,1504 ****
--- 1852,1887 ----
    emitb((mod<<6) | (reg<<3) | rm);
  }
  
+ int findreg(int regbits)
+ {
+   int i=0;
+   while (regbits) {
+     regbits>>=1;
+     i++;
+   }
+   return i?i-1:4;
+ }
+ 
+ int findscl(int sclbits)
+ {
+   static int bits[]={0,0,1,0,2,0,0,0,3};
+   return bits[sclbits];
+ }
+ 
+ int nooffset(int mbyte, int needsib)
+ {
+     if (_modrm.offset == 0 && _modrm.nsyms == 0) {
+       emitb(mbyte);
+       if (needsib)
+ 	emitb(mbyte>>8);
+       if (mbyte&0100)
+         emitb(0);
+       _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
+       return 1;
+     }
+     return 0;
+ }
+ 
  int reg2mbyte[] = { 0x48, 0x88, 0x60, 0xa0, 0x40, 0x80, 0x20, 0x08 };
  
  void reg(int which)
***************
*** 1506,1542 ****
    int i;
    int v;
    int mbyte = which << 3;
  
!   if (_modrm.regs == 0)
!   {
!     emitb(movacc ? movacc : mbyte + 6);
      movacc=0;
!   }
!   else if (_modrm.regs == 0x20 && _modrm.offset == 0 && _modrm.nsyms == 0)
!   {
!     emitb(mbyte + 0x86);
!   }
!   else
!   {
!     for (i=0; i<8; i++)
!       if (reg2mbyte[i] == _modrm.regs)
        {
!         mbyte |= i;
!         break;
        }
-     if (i == 8)
-     {
-       printf("%s:%s: Invalid registers in R/M\n", inname, lineno);
-       total_errors ++;
      }
!     if (_modrm.offset == 0 && _modrm.nsyms == 0)
!     {
!       emitb(mbyte);
!       _modrm.nsyms = _modrm.regs = _modrm.offset = 0;
        return;
!     }
!     emitb(mbyte + 0x80);
    }
    v = _modrm.offset;
    for (i=0; i<_modrm.nsyms; i++)
    {
--- 1889,1960 ----
    int i;
    int v;
    int mbyte = which << 3;
+   int needsib = 0;
  
!   if (_modrm.regs == 0) {
!     /* This handles the case of displacement only addressing (no register
!      * ofsets)
!      */
!     mbyte=movacc ? movacc : mbyte + (_modrm.addr32 ? 5 : 6);
      movacc=0;
!   } else if (_modrm.regs == 0x20 && _modrm.offset == 0 && _modrm.nsyms == 0) {
!     /* [bp+0] */
!     nooffset(mbyte|0106,0);
!     return;
!   } else {
!     if (_modrm.addr32) {
!       if (_modrm.addr32&0xff) {
! 	int sib= findreg( _modrm.addr32     &0xff)    |
! 	        (findreg((_modrm.addr32>>8 )&0xff)<<3)|
! 	        (findscl((_modrm.addr32>>16)&0x0f)<<6);
! 	if (sib==045 && _modrm.offset == 0 && _modrm.nsyms == 0) {
! 	  /* [ebp+0] */
! 	  nooffset(mbyte|0104|(045<<8),1);
! 	  return;
! 	} else if (sib==044) {
! 	  /* [esp] */
! 	  mbyte|=(sib<<8)|004;
! 	  needsib=1;
! 	} else if ((sib&070)==0040) {
! 	  /* no index */
! 	  mbyte|=sib&007;
! 	} else if ((sib&007)==0005) {
! 	  /* ebp is base */
! 	  mbyte|=(sib<<8)|004;
! 	  needsib=1;
! 	  if (nooffset(mbyte|0100,1))
! 	    return;
! 	} else {
! 	  mbyte|=(sib<<8)|004;
! 	  needsib=1;
! 	}
!       } else {
! 	int sib=(005				     )|
! 	        (findreg((_modrm.addr32>>8 )&0xff)<<3)|
! 		(findscl((_modrm.addr32>>16)&0x0f)<<6);
! 	mbyte|=(sib<<8)|004;
! 	if (nooffset(mbyte|0200,1))
! 	  return;
!       }
!     } else {
!       /* 16 bit addressing */
!       for (i=0; i<8; i++)
! 	if (reg2mbyte[i] == _modrm.regs)
! 	{
! 	  mbyte |= i;
! 	  break;
! 	}
!       if (i == 8)
        {
! 	fprintf(stderr,"%s:%d: Invalid registers in R/M\n", inname, lineno);
! 	total_errors ++;
        }
      }
!     if (nooffset(mbyte,needsib))
        return;
!     mbyte|=0200;
    }
+ 
    v = _modrm.offset;
    for (i=0; i<_modrm.nsyms; i++)
    {
***************
*** 1549,1564 ****
        p = (Patch *)malloc(sizeof(Patch));
        p->next = s->patches;
        s->patches = p;
!       p->location = pc;
        p->lineno = lineno;
!       p->rel = REL_abs;
      }
!   }   
!   emitw(v);
!   _modrm.nsyms = _modrm.regs = _modrm.offset = 0;
  }
  
! int yylex()
  {
    last_tret = yylex1();
    return last_tret;
--- 1967,2041 ----
        p = (Patch *)malloc(sizeof(Patch));
        p->next = s->patches;
        s->patches = p;
!       p->location = pc+1; /* ALL bytes emitted below, accounts for yet to be emitted mbyte */
        p->lineno = lineno;
!       p->rel = _modrm.addr32 ? REL_abs32 : REL_abs;
!       _modrm.regs=0; /* force offset field to be full size (2/4 bytes rather than 1) */
      }
!   }
!   if (_modrm.regs && v>=-128 && v<=127) {
!     emitb(mbyte^0300); /* change mod from 2/4 ((d)word offset) to 1 (byte offset) */
!     if (needsib)
!       emitb(mbyte>>8);
!     emitb(v);
!   } else {
!     emitb(mbyte);
!     if (needsib)
!       emitb(mbyte>>8);
!     if (_modrm.addr32)
!       emitd(v);
!     else
!       emitw(v);
!   }
! 
!   _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
  }
  
! void addr32(int sib)
! {
!   char *err=0;
! 
!   if (_modrm.addr16) {
!     err="Cannot mix 16 and 32 bit addressing";
!   } else {
!     if (!_modrm.addr32) emitb(0x67);
!     _modrm.addr32|=0x1000000;
!     if ((sib&0xf00)>0x100) {
!       if ((sib&0xff)==0x10) {
! 	err="esp cannot be scaled";
!       } else if (_modrm.addr32&0xff00) {
! 	err="scaled index already used";
!       } else {
! 	_modrm.addr32|=sib<<8;
!       }
!     } else {
!       if (!(_modrm.addr32&0xff)) {
! 	_modrm.addr32|=(sib&0xff)|0x1000000;
!       } else if (!(_modrm.addr32&0xff00)) {
! 	if ((sib&0xff)==0x10) {
! 	  if ((_modrm.addr32&0xff)==0x10) {
! 	    err="esp cannot be the index";
! 	  } else {
! 	    _modrm.addr32=(_modrm.addr32&0xff)<<8;
! 	    _modrm.addr32|=(sib&0xff)|0x1010000;
! 	  }
! 	} else {
! 	  _modrm.addr32|=sib<<8;
! 	}
!       } else {
! 	err="scaled index already used";
!       }
!     }
!   }
!   if (err) {
!     yyerror(err);
!     _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
!   } else {
!     _modrm.regs=-1;
!   }
! }
! 
! int yylex(void)
  {
    last_tret = yylex1();
    return last_tret;
***************
*** 1568,1584 ****
    char c1, c2;
    int token;
  } twochars[] = {
!   '=', '=', '=',
!   '>', '=', OP_GE,
!   '<', '=', OP_LE,
!   '<', '>', OP_NE,
!   '!', '=', OP_NE,
!   '&', '&', OP_AND,
!   '|', '|', OP_OR,
!   '<', '<', OP_SHL,
!   '>', '>', OP_SHR};
  
! int yylex1()
  {
    int c, c2, i, oldc;
    struct opcode *opp, op;
--- 2045,2062 ----
    char c1, c2;
    int token;
  } twochars[] = {
!   {'=', '=', '='},
!   {'>', '=', OP_GE},
!   {'<', '=', OP_LE},
!   {'<', '>', OP_NE},
!   {'!', '=', OP_NE},
!   {'&', '&', OP_AND},
!   {'|', '|', OP_OR},
!   {'<', '<', OP_SHL},
!   {'>', '>', OP_SHR}
! };
  
! int yylex1(void)
  {
    int c, c2, i, oldc;
    struct opcode *opp, op;
***************
*** 1610,1617 ****
      case '$':
      case '.':
      case '@':
!       ungetc(c, infile);
!       fscanf(infile, "%[a-zA-Z0-9_$.@]", strbuf);
        strcpy(last_token, strbuf);
        if (strcmp(strbuf, ".") == 0)
          return PC;
--- 2088,2104 ----
      case '$':
      case '.':
      case '@':
!     case '?':
!       if (c=='?')
! 	{
! 	  strbuf[0]=c;
! 	  fscanf(infile, "%[a-zA-Z0-9_$.@]", strbuf+1);
! 	}
!       else
! 	{
! 	  ungetc(c, infile);
! 	  fscanf(infile, "%[a-zA-Z0-9_$.@]", strbuf);
! 	}
        strcpy(last_token, strbuf);
        if (strcmp(strbuf, ".") == 0)
          return PC;
***************
*** 1723,1728 ****
--- 2210,2221 ----
    return 1;
  }
  
+ int islocal(char *symname)
+ {
+   if (symname[0]!='?') return 0;
+   return 1;
+ }
+ 
  void do_sreg_pop(int sreg)
  {
    switch (sreg)
***************
*** 1859,1865 ****
        return;
      }
    }
!   printf("Unknown output type: `%s'\n", t);
  }
  
  void set_image_type(char *t)
--- 2352,2358 ----
        return;
      }
    }
!   fprintf(stderr,"Unknown output type: `%s'\n", t);
  }
  
  void set_image_type(char *t)
***************
*** 1883,1889 ****
        return;
      }
    }
!   printf("Unknown output type: `%s'\n", t);
  }
  
  void do_include(char *fname)
--- 2376,2382 ----
        return;
      }
    }
!   fprintf(stderr,"Unknown output type: `%s'\n", t);
  }
  
  void do_include(char *fname)
***************
*** 1922,1933 ****
    SCNHDR *f_thdr;		/* Text section header */
    SCNHDR *f_dhdr;		/* Data section header */
    SCNHDR *f_bhdr;		/* Bss section header */
!   AOUTHDR f_ohdr;		/* Optional file header (a.out) */
    SYMENT *symbol;
    RELOC *rp;
    int cnt, i;
    void *base;
!   int textbase, database, bssbase, delta;
    char smallname[9];
  
    f = open (filename, O_RDONLY | O_BINARY);
--- 2415,2426 ----
    SCNHDR *f_thdr;		/* Text section header */
    SCNHDR *f_dhdr;		/* Data section header */
    SCNHDR *f_bhdr;		/* Bss section header */
! /*  AOUTHDR f_ohdr;*/		/* Optional file header (a.out) */
    SYMENT *symbol;
    RELOC *rp;
    int cnt, i;
    void *base;
!   int textbase, database, bssbase/*, delta*/;
    char smallname[9];
  
    f = open (filename, O_RDONLY | O_BINARY);
***************
*** 1966,1974 ****
      emitb (0);
  
  #ifdef DEBUG_RELOC
!   printf ("textbase is at %04x\n", textbase);
!   printf ("database is at %04x\n", database);
!   printf ("bssbase  is at %04x\n", bssbase);
  #endif
  
    symbol = (void *) data + header->f_symptr;
--- 2459,2467 ----
      emitb (0);
  
  #ifdef DEBUG_RELOC
!   printf (stderr,"textbase is at %04x\n", textbase);
!   printf (stderr,"database is at %04x\n", database);
!   printf (stderr,"bssbase  is at %04x\n", bssbase);
  #endif
  
    symbol = (void *) data + header->f_symptr;
***************
*** 2000,2006 ****
  	      break;
  	    case N_UNDEF:
  	      if (symbol->e_value == 0)
! 		0;  /* Nothing -- external reference.  */
  	      else if (!get_symbol (p, 0))
  		{
  		  /* New common variable.  */
--- 2493,2499 ----
  	      break;
  	    case N_UNDEF:
  	      if (symbol->e_value == 0)
! 		/*0*/;  /* Nothing -- external reference.  */
  	      else if (!get_symbol (p, 0))
  		{
  		  /* New common variable.  */
***************
*** 2028,2034 ****
  
        for (; cnt > 0; cnt--, rp++)
  	{
! 	  Symbol *s;
  	  int delta;
  
  	  if (symbol[rp->r_symndx].e.e.e_zeroes == 0)
--- 2521,2527 ----
  
        for (; cnt > 0; cnt--, rp++)
  	{
! 	  Symbol *s=0;
  	  int delta;
  
  	  if (symbol[rp->r_symndx].e.e.e_zeroes == 0)

--Message-Boundary-28453--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019