From 5e47b08dc80281e27f0cd7c15d0d91a2e1c0a636 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 9 May 2016 21:38:01 +0200 Subject: [PATCH] [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. --- i386-asm.c | 87 ++++++++++++++++++++++++++++++++++++++++--------- i386-asm.h | 2 +- i386-tok.h | 10 ++---- tests/asmtest.S | 75 +++++++++++++++++++++++++++++++++++++----- x86_64-asm.h | 41 ++++++++++++++--------- 5 files changed, 168 insertions(+), 47 deletions(-) diff --git a/i386-asm.c b/i386-asm.c index 772b74ad..435dd15a 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 af21443a..6b03f4a7 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 b0ca3edb..eedbc183 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 e235c802..0876aa83 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 cc2c3a5a..d7c0d778 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 ))