x86-asm: Fix lar opcode operands

lar can accept multiple sizes as well (wlx), like lsl.  When using
autosize it's important to look at the destination operand first;
when it's a register that one determines the size, not the input
operand.
This commit is contained in:
Michael Matz 2016-07-11 21:41:15 +02:00
parent e3f2a68311
commit 5692716770
5 changed files with 15 additions and 3 deletions

View File

@ -733,7 +733,11 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
autosize = NBWLX-2;
#endif
if (s == autosize) {
for(i = 0; s == autosize && i < nb_ops; i++) {
/* Check for register operands providing hints about the size.
Start from the end, i.e. destination operands. This matters
only for opcodes accepting different sized registers, lar and lsl
are such opcodes. */
for(i = nb_ops - 1; s == autosize && i >= 0; i--) {
if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
s = reg_to_size[ops[i].type & OP_REG];
}

View File

@ -341,7 +341,7 @@ ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
/* segments */
DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
ALT(DEF_ASM_OP2(larw, 0x0f02, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG))
DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)

View File

@ -185,6 +185,7 @@
DEF_WLX(btr)
DEF_WLX(btc)
DEF_WLX(lar)
DEF_WLX(lsl)
/* generic FP ops */

View File

@ -625,8 +625,15 @@ int $0x10
clflush 0x1000(%rax,%rcx)
fxsaveq (%rdx)
fxrstorq (%rcx)
#endif
lar %ax,%dx
lar %eax,%dx
lar %ax,%edx
lar %eax,%edx
lar %ax,%rdx
lar %eax,%rdx
emms
movd %edx, %mm3
movd 0x1000, %mm2

View File

@ -359,7 +359,7 @@ ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
/* segments */
DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
ALT(DEF_ASM_OP2(larw, 0x0f02, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG))
DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
DEF_ASM_OP1(lgdtq, 0x0f01, 2, OPC_MODRM, OPT_EA)
DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)