aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--i386-asm.c87
-rw-r--r--i386-asm.h2
-rw-r--r--i386-tok.h10
-rw-r--r--tests/asmtest.S75
-rw-r--r--x86_64-asm.h41
5 files changed, 168 insertions, 47 deletions
diff --git a/i386-asm.c b/i386-asm.c
index 772b74a..435dd15 100644
--- a/i386-asm.c
+++ b/i386-asm.c
@@ -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;
diff --git a/i386-asm.h b/i386-asm.h
index af21443..6b03f4a 100644
--- a/i386-asm.h
+++ b/i386-asm.h
@@ -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))
diff --git a/i386-tok.h b/i386-tok.h
index b0ca3ed..eedbc18 100644
--- a/i386-tok.h
+++ b/i386-tok.h
@@ -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)
diff --git a/tests/asmtest.S b/tests/asmtest.S
index e235c80..0876aa8 100644
--- a/tests/asmtest.S
+++ b/tests/asmtest.S
@@ -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
diff --git a/x86_64-asm.h b/x86_64-asm.h
index cc2c3a5..d7c0d77 100644
--- a/x86_64-asm.h
+++ b/x86_64-asm.h
@@ -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 ))