diff --git a/i386-asm.c b/i386-asm.c index 136fe60..71c451a 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -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]; } diff --git a/i386-asm.h b/i386-asm.h index 7a8fb0d..65d5179 100644 --- a/i386-asm.h +++ b/i386-asm.h @@ -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) diff --git a/i386-tok.h b/i386-tok.h index c54e0e7..cf65897 100644 --- a/i386-tok.h +++ b/i386-tok.h @@ -185,6 +185,7 @@ DEF_WLX(btr) DEF_WLX(btc) + DEF_WLX(lar) DEF_WLX(lsl) /* generic FP ops */ diff --git a/tests/asmtest.S b/tests/asmtest.S index ebc17fc..0bbd764 100644 --- a/tests/asmtest.S +++ b/tests/asmtest.S @@ -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 diff --git a/x86_64-asm.h b/x86_64-asm.h index 73a9f57..5855d2a 100644 --- a/x86_64-asm.h +++ b/x86_64-asm.h @@ -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)