Index: third_party/yasm/patched-yasm/modules/arch/x86/x86expr.c |
=================================================================== |
--- third_party/yasm/patched-yasm/modules/arch/x86/x86expr.c (revision 165590) |
+++ third_party/yasm/patched-yasm/modules/arch/x86/x86expr.c (working copy) |
@@ -25,7 +25,6 @@ |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <util.h> |
-/*@unused@*/ RCSID("$Id: x86expr.c 2199 2009-05-10 05:24:46Z peter $"); |
#include <libyasm.h> |
@@ -34,6 +33,7 @@ |
typedef struct x86_checkea_reg3264_data { |
int *regs; /* total multiplier for each reg */ |
+ unsigned char vsib_mode; |
unsigned char bits; |
unsigned char addrsize; |
} x86_checkea_reg3264_data; |
@@ -58,6 +58,20 @@ |
return 0; |
*regnum = (unsigned int)(ei->data.reg & 0xF); |
break; |
+ case X86_XMMREG: |
+ if (data->vsib_mode != 1) |
+ return 0; |
+ if (data->bits != 64 && (ei->data.reg & 0x8) == 0x8) |
+ return 0; |
+ *regnum = 17+(unsigned int)(ei->data.reg & 0xF); |
+ break; |
+ case X86_YMMREG: |
+ if (data->vsib_mode != 2) |
+ return 0; |
+ if (data->bits != 64 && (ei->data.reg & 0x8) == 0x8) |
+ return 0; |
+ *regnum = 17+(unsigned int)(ei->data.reg & 0xF); |
+ break; |
case X86_RIP: |
if (data->bits != 64) |
return 0; |
@@ -606,6 +620,11 @@ |
} |
/*@fallthrough@*/ |
default: |
+ /* If SIB is required, but we're in 16-bit mode, set to 32. */ |
+ if (bits == 16 && x86_ea->need_sib == 1) { |
+ *addrsize = 32; |
+ break; |
+ } |
/* check for use of 16 or 32-bit registers; if none are used |
* default to bits setting. |
*/ |
@@ -643,14 +662,20 @@ |
REG64_R13, |
REG64_R14, |
REG64_R15, |
- REG64_RIP |
+ REG64_RIP, |
+ SIMDREGS |
} reg3264type; |
- int reg3264mult[17] = {0, 0, 0, 0, 0, 0, 0, 0, |
- 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ int reg3264mult[33] = |
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
x86_checkea_reg3264_data reg3264_data; |
int basereg = REG3264_NONE; /* "base" register (for SIB) */ |
int indexreg = REG3264_NONE; /* "index" register (for SIB) */ |
+ int regcount = 17; /* normally don't check SIMD regs */ |
+ if (x86_ea->vsib_mode != 0) |
+ regcount = 33; |
+ |
/* We can only do 64-bit addresses in 64-bit mode. */ |
if (*addrsize == 64 && bits != 64) { |
yasm_error_set(YASM_ERROR_TYPE, |
@@ -665,6 +690,7 @@ |
} |
reg3264_data.regs = reg3264mult; |
+ reg3264_data.vsib_mode = x86_ea->vsib_mode; |
reg3264_data.bits = bits; |
reg3264_data.addrsize = *addrsize; |
if (x86_ea->ea.disp.abs) { |
@@ -698,7 +724,7 @@ |
* Also, if an indexreg hasn't been assigned, try to find one. |
* Meanwhile, check to make sure there's no negative register mults. |
*/ |
- for (i=0; i<17; i++) { |
+ for (i=0; i<regcount; i++) { |
if (reg3264mult[i] < 0) { |
yasm_error_set(YASM_ERROR_VALUE, |
N_("invalid effective address")); |
@@ -711,10 +737,26 @@ |
indexreg = i; |
} |
- /* Handle certain special cases of indexreg mults when basereg is |
- * empty. |
- */ |
- if (indexreg != REG3264_NONE && basereg == REG3264_NONE) |
+ if (x86_ea->vsib_mode != 0) { |
+ /* For VSIB, the SIMD register needs to go into the indexreg. |
+ * Also check basereg (must be a GPR if present) and indexreg |
+ * (must be a SIMD register). |
+ */ |
+ if (basereg >= SIMDREGS && |
+ (indexreg == REG3264_NONE || reg3264mult[indexreg] == 1)) { |
+ int temp = basereg; |
+ basereg = indexreg; |
+ indexreg = temp; |
+ } |
+ if (basereg >= REG64_RIP || indexreg < SIMDREGS) { |
+ yasm_error_set(YASM_ERROR_VALUE, |
+ N_("invalid effective address")); |
+ return 1; |
+ } |
+ } else if (indexreg != REG3264_NONE && basereg == REG3264_NONE) |
+ /* Handle certain special cases of indexreg mults when basereg is |
+ * empty. |
+ */ |
switch (reg3264mult[indexreg]) { |
case 1: |
/* Only optimize this way if nosplit wasn't specified */ |
@@ -741,7 +783,7 @@ |
/* Make sure there's no other registers than the basereg and indexreg |
* we just found. |
*/ |
- for (i=0; i<17; i++) |
+ for (i=0; i<regcount; i++) |
if (i != basereg && i != indexreg && reg3264mult[i] != 0) { |
yasm_error_set(YASM_ERROR_VALUE, |
N_("invalid effective address")); |
@@ -861,10 +903,17 @@ |
x86_ea->sib |= 040; |
/* Any scale field is valid, just leave at 0. */ |
else { |
- if (yasm_x86__set_rex_from_reg(rex, &low3, (unsigned int) |
- (X86_REG64 | indexreg), bits, |
- X86_REX_X)) |
- return 1; |
+ if (indexreg >= SIMDREGS) { |
+ if (yasm_x86__set_rex_from_reg(rex, &low3, |
+ (unsigned int)(X86_XMMREG | (indexreg-SIMDREGS)), |
+ bits, X86_REX_X)) |
+ return 1; |
+ } else { |
+ if (yasm_x86__set_rex_from_reg(rex, &low3, |
+ (unsigned int)(X86_REG64 | indexreg), |
+ bits, X86_REX_X)) |
+ return 1; |
+ } |
x86_ea->sib |= low3 << 3; |
/* Set scale field, 1 case -> 0, so don't bother. */ |
switch (reg3264mult[indexreg]) { |