Date: Mon, 15 Sep 1997 14:04:50 +1100 From: Bill Currie 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 Content-type: Multipart/Mixed; boundary=Message-Boundary-28453 Comments: Authenticated sender is Precedence: bulk --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 #include #include + #include + #include #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 ID %type constID ! %type const offset %token KID UID --- 185,191 ---- %type ID %type constID ! %type const offset scaledindex %token KID UID *************** *** 177,194 **** %token JCC JCCL JCXZ LOOP SETCC %token SHIFT SHLRD %token ONEBYTE TWOBYTE ASCADJ ! %token 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 JCC JCCL JCXZ LOOP SETCC %token SHIFT SHLRD %token ONEBYTE TWOBYTE ASCADJ ! %token 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++; + $$=symtab; + symtab=symtab->next; + } + struct_lines + ENDS { set_symbol($2, struct_pc)->type = SYM_abs; + $4->next=symtab; + symtab=$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; iname, '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; ivalue; 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--