diff --git a/src/compiler/asm_target.c b/src/compiler/asm_target.c index b6918267e..23cca4492 100644 --- a/src/compiler/asm_target.c +++ b/src/compiler/asm_target.c @@ -709,6 +709,10 @@ static void init_asm_x86(PlatformTarget* target) reg_instr(target, "pushw", "r16/mem/imm16"); reg_instr(target, "popw", "w:r16/mem"); + reg_instr_clob(target, "popcntw", cc_flag_mask, "w:r16, r16/mem"); + reg_instr_clob(target, "popcntl", cc_flag_mask, "w:r32, r32/mem"); + reg_instr_clob(target, "popcntq", cc_flag_mask, "w:r64, r64/mem"); + target->clobber_name_list = X86ClobberNames; target->extra_clobbers = "~{flags},~{dirflag},~{fspr}"; if (target->arch == ARCH_TYPE_X86) diff --git a/test/unit/asm/popcnt.c3 b/test/unit/asm/popcnt.c3 new file mode 100644 index 000000000..a4b6f0b7d --- /dev/null +++ b/test/unit/asm/popcnt.c3 @@ -0,0 +1,25 @@ +module test::inline_asm::popcnt @if (env::X86_64); + +fn void popcntw() @test +{ + short src = 0xF0; + short count = 0; + asm { popcntw count, src; } + assert(count == 4, "inline asm: popcntw failed"); +} + +fn void popcntl() @test +{ + int src = 0xF0F0; + int count = 0; + asm { popcntl count, src; } + assert(count == 8, "inline asm: popcntl failed"); +} + +fn void popcntq() @test +{ + long src = 0xF0F0_F0F0; + long count = 0; + asm { popcntq count, src; } + assert(count == 16, "inline asm: popcntq failed"); +}