[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.
This commit is contained in:
parent
f5f82abc99
commit
5e47b08dc8
5 changed files with 168 additions and 47 deletions
87
i386-asm.c
87
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;
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
10
i386-tok.h
10
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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
41
x86_64-asm.h
41
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 ))
|
||||
|
|
Loading…
Reference in a new issue