From 3ba467795a364e7a95ba04a99ffc6ed2c2d2959d Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 27 May 2002 23:19:35 +0000 Subject: [PATCH] Deal with another case of address/operand size confusion, BR 560873 --- assemble.c | 31 ++++++++++++++++++++++++++----- insns.dat | 12 ++++++------ test/br560873.asm | 24 ++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 test/br560873.asm diff --git a/assemble.c b/assemble.c index b87b1040..9f557595 100644 --- a/assemble.c +++ b/assemble.c @@ -22,9 +22,11 @@ * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2 * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2 * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit - * assembly mode or the address-size override on the operand + * assembly mode or the operand-size override on the operand * \37 - a word constant, from the _segment_ part of operand 0 * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2 + * \44, \45, \46 - select between \3[012] and \4[012] depending on 16/32 bit + * assembly mode or the address-size override on the operand * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit @@ -590,12 +592,18 @@ static long calcsize (long segment, long offset, int bits, case 030: case 031: case 032: length += 2; break; case 034: case 035: case 036: - length += ((ins->oprs[c-034].addr_size ? - ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break; + if ( ins->oprs[c-034].type & (BITS16|BITS32) ) + length += (ins->oprs[c-034].type & BITS16) ? 2 : 4; + else + length += (bits == 16) ? 2 : 4; + break; case 037: length += 2; break; case 040: case 041: case 042: length += 4; break; + case 044: case 045: case 046: + length += ((ins->oprs[c-044].addr_size ? + ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); break; case 050: case 051: case 052: length++; break; case 060: case 061: case 062: @@ -799,9 +807,11 @@ static void gencode (long segment, long offset, int bits, break; case 034: case 035: case 036: + if ( ins->oprs[c-034].type & (BITS16|BITS32) ) + size = (ins->oprs[c-034].type & BITS16) ? 2 : 4; + else + size = (bits == 16) ? 2 : 4; data = ins->oprs[c-034].offset; - size = ((ins->oprs[c-034].addr_size ? - ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); if (size==2 && (data < -65536L || data > 65535L)) errfunc (ERR_WARNING, "word value exceeds bounds"); out (offset, segment, &data, OUT_ADDRESS+size, @@ -827,6 +837,17 @@ static void gencode (long segment, long offset, int bits, offset += 4; break; + case 044: case 045: case 046: + data = ins->oprs[c-044].offset; + size = ((ins->oprs[c-044].addr_size ? + ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); + if (size==2 && (data < -65536L || data > 65535L)) + errfunc (ERR_WARNING, "word value exceeds bounds"); + out (offset, segment, &data, OUT_ADDRESS+size, + ins->oprs[c-044].segment, ins->oprs[c-044].wrt); + offset += size; + break; + case 050: case 051: case 052: if (ins->oprs[c-050].segment != segment) errfunc (ERR_NONFATAL, "short relative jump outside segment"); diff --git a/insns.dat b/insns.dat index e2bd2250..66bc8e63 100644 --- a/insns.dat +++ b/insns.dat @@ -573,12 +573,12 @@ MOV reg_dess,reg16 \301\1\x8E\110 8086 MOV reg_fsgs,reg16 \301\1\x8E\110 386 MOV reg_dess,reg32 \301\1\x8E\110 386 MOV reg_fsgs,reg32 \301\1\x8E\110 386 -MOV reg_al,mem_offs \301\1\xA0\35 8086,SM -MOV reg_ax,mem_offs \301\320\1\xA1\35 8086,SM -MOV reg_eax,mem_offs \301\321\1\xA1\35 386,SM -MOV mem_offs,reg_al \300\1\xA2\34 8086,SM -MOV mem_offs,reg_ax \300\320\1\xA3\34 8086,SM -MOV mem_offs,reg_eax \300\321\1\xA3\34 386,SM +MOV reg_al,mem_offs \301\1\xA0\45 8086,SM +MOV reg_ax,mem_offs \301\320\1\xA1\45 8086,SM +MOV reg_eax,mem_offs \301\321\1\xA1\45 386,SM +MOV mem_offs,reg_al \300\1\xA2\44 8086,SM +MOV mem_offs,reg_ax \300\320\1\xA3\44 8086,SM +MOV mem_offs,reg_eax \300\321\1\xA3\44 386,SM MOV reg32,reg_cr4 \2\x0F\x20\204 PENT,PRIV MOV reg32,reg_creg \2\x0F\x20\101 386,PRIV MOV reg32,reg_dreg \2\x0F\x21\101 386,PRIV diff --git a/test/br560873.asm b/test/br560873.asm new file mode 100644 index 00000000..1aebd0af --- /dev/null +++ b/test/br560873.asm @@ -0,0 +1,24 @@ +label: + bits 16 + call far dword label + mov [label],ax + mov [label],eax + mov [word label],ax + mov [word label],eax + mov [dword label],ax + mov [dword label],eax + push 3700 + push word 3700 + push dword 3700 + + bits 32 + call far word label + mov [label],ax + mov [label],eax + mov [word label],ax + mov [word label],eax + mov [dword label],ax + mov [dword label],eax + push 3700 + push word 3700 + push dword 3700