[x86] Fix some asm problems

A bag of assembler fixes, to be either compatible with GAS
(e.g. order of 'test' operands), accept more instructions,
count correct foo{bwlq} variants on x86_64, fix modrm/sib bytes
on x86_64 to not use %rip relative addressing mode, to not use
invalid insns in tests/asmtest.S for x86_64.

Result is that now output of GAS and of tcc on tests/asmtest.S
is mostly the same.
master
Michael Matz 2016-05-09 21:38:01 +02:00
parent f5f82abc99
commit 5e47b08dc8
5 changed files with 168 additions and 47 deletions

View File

@ -115,11 +115,13 @@ enum {
#define OP_ADDR (1 << OPT_ADDR)
#define OP_INDIR (1 << OPT_INDIR)
#ifdef TCC_TARGET_X86_64
# define OP_REG64 (1 << OPT_REG64)
# define OP_IM64 (1 << OPT_IM64)
# define OP_REG64 (1 << OPT_REG64)
# define OP_IM64 (1 << OPT_IM64)
# define OP_EA32 (OP_EA << 1)
#else
# define OP_REG64 0
# define OP_IM64 0
# define OP_EA32 0
#endif
#define OP_EA 0x40000000
@ -268,15 +270,17 @@ static inline int get_reg_shift(TCCState *s1)
return shift;
}
static int asm_parse_reg(void)
static int asm_parse_reg(int *type)
{
int reg = 0;
*type = 0;
if (tok != '%')
goto error_32;
next();
if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
reg = tok - TOK_ASM_eax;
#ifdef TCC_TARGET_X86_64
*type = OP_EA32;
} else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) {
reg = tok - TOK_ASM_rax;
#endif
@ -393,20 +397,23 @@ static void parse_operand(TCCState *s1, Operand *op)
}
}
if (tok == '(') {
int type = 0;
next();
if (tok != ',') {
op->reg = asm_parse_reg();
op->reg = asm_parse_reg(&type);
}
if (tok == ',') {
next();
if (tok != ',') {
op->reg2 = asm_parse_reg();
op->reg2 = asm_parse_reg(&type);
}
if (tok == ',') {
next();
op->shift = get_reg_shift(s1);
}
}
if (type & OP_EA32)
op->type |= OP_EA32;
skip(')');
}
if (op->reg == -1 && op->reg2 == -1)
@ -493,10 +500,15 @@ static inline void asm_modrm(int reg, Operand *op)
gen_expr16(&op->e);
} else if (tcc_state->seg_size == 32)
#endif
{
{
#ifdef TCC_TARGET_X86_64
g(0x04 + (reg << 3));
g(0x25);
#else
g(0x05 + (reg << 3));
gen_expr32(&op->e);
}
#endif
gen_expr32(&op->e);
}
} else {
sib_reg1 = op->reg;
/* fist compute displacement encoding */
@ -583,6 +595,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
int nb_ops, s;
Operand ops[MAX_OPERANDS], *pop;
int op_type[3]; /* decoded op type */
int alltypes; /* OR of all operand types */
int autosize;
#ifdef I386_ASM_16
static int a32 = 0, o32 = 0, addr32 = 0, data32 = 0;
#endif
@ -596,6 +610,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
pop = ops;
nb_ops = 0;
seg_prefix = 0;
alltypes = 0;
for(;;) {
if (tok == ';' || tok == TOK_LINEFEED)
break;
@ -645,6 +660,13 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
continue;
} else if (pa->instr_type & OPC_B) {
#ifdef TCC_TARGET_X86_64
/* Some instructions don't have the full size but only
bwl form. insb e.g. */
if ((pa->instr_type & OPC_WLQ) != OPC_WLQ
&& !(opcode >= pa->sym && opcode < pa->sym + NBWLX-1))
continue;
#endif
if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX))
continue;
s = opcode - pa->sym;
@ -659,6 +681,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
if (pa->nb_ops != nb_ops)
continue;
/* now decode and check each operand */
alltypes = 0;
for(i = 0; i < nb_ops; i++) {
int op1, op2;
op1 = pa->op_type[i];
@ -687,9 +710,10 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
}
if (op1 & OPT_EA)
v |= OP_EA;
op_type[i] = v;
op_type[i] = v;
if ((ops[i].type & v) == 0)
goto next;
alltypes |= ops[i].type;
}
/* all is matching ! */
break;
@ -725,12 +749,19 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
}
}
/* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
if (s == NBWLX-1) {
for(i = 0; s == NBWLX-1 && i < nb_ops; i++) {
autosize = NBWLX-1;
#ifdef TCC_TARGET_X86_64
/* XXX the autosize should rather be zero, to not have to adjust this
all the time. */
if ((pa->instr_type & OPC_WLQ) != OPC_WLQ)
autosize = NBWLX-2;
#endif
if (s == autosize) {
for(i = 0; s == autosize && i < nb_ops; i++) {
if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
s = reg_to_size[ops[i].type & OP_REG];
}
if (s == NBWLX-1) {
if (s == autosize) {
if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
(ops[0].type & (OP_SEG | OP_IM8S | OP_IM32 | OP_IM64)))
s = 2;
@ -770,14 +801,38 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
addr32 = data32 = 0;
#else
#ifdef TCC_TARGET_X86_64
/* Generate addr32 prefix if needed */
for(i = 0; i < nb_ops; i++) {
if (ops[i].type & OP_EA32) {
g(0x67);
break;
}
}
#endif
/* generate data16 prefix if needed */
if (s == 1 || (pa->instr_type & OPC_D16))
g(0x66);
#ifdef TCC_TARGET_X86_64
else if (s == 3) {
if (s == 3 || (alltypes & OP_REG64)) {
/* generate REX prefix */
if ((opcode != TOK_ASM_push && opcode != TOK_ASM_pop)
|| !(ops[0].type & OP_REG64))
int default64 = 0;
for(i = 0; i < nb_ops; i++) {
if (op_type[i] == OP_REG64) {
/* If only 64bit regs are accepted in one operand
this is a default64 instruction without need for
REX prefixes. */
default64 = 1;
break;
}
}
/* XXX find better encoding for the default64 instructions. */
if (((opcode != TOK_ASM_push && opcode != TOK_ASM_pop
&& opcode != TOK_ASM_pushw && opcode != TOK_ASM_pushl
&& opcode != TOK_ASM_pushq && opcode != TOK_ASM_popw
&& opcode != TOK_ASM_popl && opcode != TOK_ASM_popq
&& opcode != TOK_ASM_call && opcode != TOK_ASM_jmp))
&& !default64)
g(0x48);
}
#endif
@ -838,7 +893,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
goto no_short_jump;
if (sym->r != cur_text_section->sh_num)
goto no_short_jump;
jmp_disp = ops[0].e.v + sym->jnext - ind - 2;
jmp_disp = ops[0].e.v + sym->jnext - ind - 2 - (v >= 0xff);
if (jmp_disp == (int8_t)jmp_disp) {
/* OK to generate jump */
is_short_jmp = 1;

View File

@ -165,8 +165,8 @@ ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))

View File

@ -126,12 +126,8 @@
DEF_BWLX(shr)
DEF_BWLX(sar)
DEF_ASM(shldw)
DEF_ASM(shldl)
DEF_ASM(shld)
DEF_ASM(shrdw)
DEF_ASM(shrdl)
DEF_ASM(shrd)
DEF_WLX(shld)
DEF_WLX(shrd)
DEF_ASM(pushw)
DEF_ASM(pushl)
@ -150,7 +146,7 @@
DEF_BWL(in)
DEF_BWL(out)
DEF_WL(movzb)
DEF_WLX(movzb)
DEF_ASM(movzwl)
DEF_ASM(movsbw)
DEF_ASM(movsbl)

View File

@ -38,7 +38,7 @@ mov %al, 0x10000
mov $1, %edx
mov $1, %dx
mov $1, %dl
mov $1, %cl
movb $2, 0x100(%ebx,%edx,2)
movw $2, 0x100(%ebx,%edx,2)
movl $2, 0x100(%ebx,%edx,2)
@ -48,12 +48,20 @@ movw %ax, 0x100(%ebx,%edx,2)
mov %eax, 0x12(,%edx,2)
#ifdef __i386__
mov %cr3, %edx
mov %ecx, %cr3
movl %cr3, %eax
movl %tr3, %eax
movl %db3, %ebx
movl %dr6, %eax
#else
mov %cr3, %rdx
mov %rcx, %cr3
movq %cr3, %rax
movq %db3, %rbx
movq %dr6, %rax
#endif
movl %fs, %ecx
movl %ebx, %fs
@ -69,18 +77,28 @@ movl %ebx, %fs
movzb 0x1000, %ax
#ifdef __i386__
pushl %eax
pushw %ax
push %eax
push %cs
#else
pushq %rax
push %rax
#endif
pushw %ax
push %gs
push $1
push $100
#ifdef __i386__
popl %eax
popw %ax
pop %eax
pop %ds
#else
popq %rax
pop %rax
#endif
popw %ax
pop %fs
xchg %eax, %ecx
@ -111,11 +129,13 @@ movl %ebx, %fs
leal 0x1000(%ebx), %ecx
lea 0x1000(%ebx), %ecx
#ifdef __i386__
les 0x2000, %eax
lds 0x2000, %ebx
lss 0x2000, %edx
#endif
lfs 0x2000, %ecx
lgs 0x2000, %edx
lss 0x2000, %edx
addl $0x123, %eax
add $0x123, %ebx
@ -195,7 +215,11 @@ shrd %eax, %edx
L4:
call 0x1000
call L4
#ifdef __i386__
call *%eax
#else
call *%rax
#endif
call *0x1000
call func1
@ -204,19 +228,37 @@ call func1
L5:
L6:
#ifdef __i386__
lcall $0x100, $0x1000
#else
lcall *0x100
lcall *(%rax)
#endif
jmp 0x1000
#ifdef __i386__
jmp *%eax
#else
jmp *%rax
#endif
jmp *0x1000
#ifdef __i386__
ljmp $0x100, $0x1000
#else
ljmp *0x100
ljmp *(%rdi)
#endif
ret
retl
ret $10
#ifdef __i386__
retl
retl $10
#else
retq
retq $10
#endif
lret
@ -436,8 +478,10 @@ fucomip %st(5), %st
int $3
int $0x10
#ifdef __i386__
pusha
popa
#endif
clc
cld
cli
@ -445,19 +489,27 @@ int $0x10
cmc
lahf
sahf
#ifdef __i386__
pushfl
popfl
#else
pushfq
popfq
#endif
pushf
popf
stc
std
sti
#ifdef __i386__
aaa
aas
daa
das
aad
aam
into
#endif
cbw
cwd
cwde
@ -468,7 +520,6 @@ int $0x10
cltd
leave
int3
into
iret
rsm
hlt
@ -558,10 +609,12 @@ int $0x10
#ifdef __i386__
boundl %edx, 0x10000
boundw %bx, 0x1000
arpl %bx, 0x1000
#endif
lar 0x1000, %eax
lgdt 0x1000
lidt 0x1000
@ -579,15 +632,21 @@ int $0x10
verr 0x1000
verw 0x1000
#ifdef __i386__
push %ds
pushw %ds
pushl %ds
pop %ds
popw %ds
popl %ds
#endif
fxsave 1(%ebx)
fxrstor 1(%ecx)
#ifdef __i386__
pushl $1
#else
pushq $1
#endif
pushw $1
push $1

View File

@ -5,8 +5,8 @@
DEF_ASM_OP0(cmc, 0xf5)
DEF_ASM_OP0(lahf, 0x9f)
DEF_ASM_OP0(sahf, 0x9e)
DEF_ASM_OP0(pushfl, 0x9c)
DEF_ASM_OP0(popfl, 0x9d)
DEF_ASM_OP0(pushfq, 0x9c)
DEF_ASM_OP0(popfq, 0x9d)
DEF_ASM_OP0(pushf, 0x9c)
DEF_ASM_OP0(popf, 0x9d)
DEF_ASM_OP0(stc, 0xf9)
@ -34,14 +34,15 @@
DEF_ASM_OP0(hlt, 0xf4)
DEF_ASM_OP0(wait, 0x9b)
DEF_ASM_OP0(nop, 0x90)
DEF_ASM_OP0(pause, 0xf390)
DEF_ASM_OP0(xlat, 0xd7)
/* strings */
ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWLQ))
ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWLQ))
ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWLQ))
ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWLQ))
ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWLQ))
ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWLQ))
@ -90,8 +91,10 @@ ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WLQ, OPT_IM8, OPT_REGW | OPT_EA
DEF_ASM_OP0(ud2, 0x0f0b)
/* NOTE: we took the same order as gas opcode definition order */
/* Right now we can't express the fact that 0xa1/0xa3 can't use $eax and a
32 bit moffset as operands.
ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWLQ, OPT_ADDR, OPT_EAX))
ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLQ, OPT_EAX, OPT_ADDR))
ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLQ, OPT_EAX, OPT_ADDR)) */
ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG))
ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG))
ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLQ, OPT_IM, OPT_REG))
@ -102,25 +105,28 @@ ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WLQ, OPT_EA | OPT_REG, OPT_SEG))
ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WLQ, OPT_CR, OPT_REG64))
ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WLQ, OPT_DB, OPT_REG64))
ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WLQ, OPT_TR, OPT_REG64))
ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WLQ, OPT_REG64, OPT_CR))
ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WLQ, OPT_REG64, OPT_DB))
ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WLQ, OPT_REG64, OPT_TR))
ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
ALT(DEF_ASM_OP2(movslq, 0x4863, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG))
ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WLQ, OPT_REG8 | OPT_EA, OPT_REGW))
ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
ALT(DEF_ASM_OP1(pushq, 0x6a, 0, 0, OPT_IM8S))
ALT(DEF_ASM_OP1(push, 0x6a, 0, 0, OPT_IM8S))
ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_D16, OPT_IM8S))
ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLQ, OPT_REG64))
ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLQ, OPT_REG16))
ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WLQ, OPT_REG64 | OPT_EA))
ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_D16, OPT_IM16))
ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WLQ, OPT_IM32))
ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WLQ, OPT_SEG))
DEF_ASM_OP1(pushb, 0x6a, 0, OPC_B, OPT_IM8S)
ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLQ, OPT_REGW))
ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLQ, OPT_REG64))
ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLQ, OPT_REG16))
ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WLQ, OPT_REGW | OPT_EA))
ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WLQ, OPT_SEG))
@ -154,8 +160,8 @@ ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLQ, OPT_IMNO64, OPT_EAX))
ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_IMNO64, OPT_EA | OPT_REG))
ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLQ, OPT_IM8S, OPT_EA | OPT_REG))
ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG))
ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG))
ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG))
ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWLQ, OPT_IMNO64, OPT_EAX))
ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWLQ, OPT_IMNO64, OPT_EA | OPT_REG))
@ -206,7 +212,9 @@ ALT(DEF_ASM_OP1(setob, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
DEF_ASM_OP0(leave, 0xc9)
DEF_ASM_OP0(ret, 0xc3)
DEF_ASM_OP0(retq, 0xc3)
ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
ALT(DEF_ASM_OP1(retq, 0xc2, 0, 0, OPT_IM16))
DEF_ASM_OP0(lret, 0xcb)
ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
@ -216,7 +224,7 @@ ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
DEF_ASM_OP1(jecxz, 0x67e3, 0, OPC_SHORTJMP, OPT_ADDR)
/* float */
/* specific fcomp handling */
@ -224,6 +232,8 @@ ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
ALT(DEF_ASM_OP2(fadd, 0xdcc0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
ALT(DEF_ASM_OP2(fmul, 0xdcc8, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
@ -334,7 +344,7 @@ ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WLQ, OPT_EA | OPT_REG, OPT_REG))
DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
@ -346,8 +356,8 @@ ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
/* 486 */
DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_REG | OPT_EA ))
ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_REG | OPT_EA ))
DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
@ -383,6 +393,7 @@ ALT(DEF_ASM_OP2(cmova, 0x0f47, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_
/* mmx */
DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
ALT(DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG64, OPT_MMX ))
ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
ALT(DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ))
ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))