diff --git a/i386-asm.c b/i386-asm.c index 2ffa53b..a036e49 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -893,6 +893,15 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) pc = 0; if (pa->instr_type & OPC_MODRM) { + if (!nb_ops) { + /* A modrm opcode without operands is a special case (e.g. mfence). + It has a group and acts as if there's an register operand 0 + (ax). */ + i = 0; + ops[i].type = OP_REG; + ops[i].reg = 0; + goto modrm_found; + } /* first look for an ea operand */ for(i = 0;i < nb_ops; i++) { if (op_type[i] & OP_EA) diff --git a/tests/asmtest.S b/tests/asmtest.S index 79419b9..bf51c44 100644 --- a/tests/asmtest.S +++ b/tests/asmtest.S @@ -607,6 +607,13 @@ int $0x10 rdmsr rdpmc ud2 +#ifdef __x86_64__ + syscall + sysret + lfence + mfence + sfence +#endif emms movd %edx, %mm3 diff --git a/x86_64-asm.h b/x86_64-asm.h index cf67e69..a40b697 100644 --- a/x86_64-asm.h +++ b/x86_64-asm.h @@ -88,6 +88,9 @@ ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA DEF_ASM_OP0(rdtsc, 0x0f31) DEF_ASM_OP0(rdmsr, 0x0f32) DEF_ASM_OP0(rdpmc, 0x0f33) + + DEF_ASM_OP0(syscall, 0x0f05) + DEF_ASM_OP0(sysret, 0x0f07) DEF_ASM_OP0(ud2, 0x0f0b) /* NOTE: we took the same order as gas opcode definition order */ @@ -482,6 +485,9 @@ ALT(DEF_ASM_OP2(movhps, 0x0f17, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) DEF_ASM_OP2(sqrtps, 0x0f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) DEF_ASM_OP2(subps, 0x0f5c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) + DEF_ASM_OP0L(lfence, 0x0fae, 5, OPC_MODRM) + DEF_ASM_OP0L(mfence, 0x0fae, 6, OPC_MODRM) + DEF_ASM_OP0L(sfence, 0x0fae, 7, OPC_MODRM) #undef ALT #undef DEF_ASM_OP0 #undef DEF_ASM_OP0L