Add some ISA predicates for Intel CPUID features.

Guard the popcnt instruction on the proper CPUID bits.
This commit is contained in:
Jakob Stoklund Olesen
2017-07-12 16:05:20 -07:00
parent 435a15b88d
commit 5cbcd59cf0
5 changed files with 41 additions and 9 deletions

View File

@@ -1,6 +1,6 @@
; binary emission of 32-bit code.
test binemit
isa intel
isa intel has_sse42 has_popcnt
; The binary encodings can be verified with the command:
;

View File

@@ -1,7 +1,7 @@
; binary emission of 64-bit code.
test binemit
set is_64bit
isa intel
isa intel has_sse42 has_popcnt
; The binary encodings can be verified with the command:
;

View File

@@ -2,10 +2,10 @@
test compile
set is_64bit=0
isa intel
isa intel has_sse42 has_popcnt
set is_64bit=1
isa intel
isa intel has_sse42 has_popcnt
; Constants.

View File

@@ -7,6 +7,7 @@ from base import instructions as base
from base.formats import UnaryImm
from .defs import I32, I64
from . import recipes as r
from . import settings as cfg
for inst, opc in [
(base.iadd, 0x01),
@@ -81,10 +82,11 @@ for inst, rrr in [
I64.enc(inst.i32.i32, *r.rc(0xd3, rrr=rrr))
# Population count.
I32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8))
I64.enc(base.popcnt.i64, *r.urm.rex(0xf3, 0x0f, 0xb8, w=1))
I64.enc(base.popcnt.i32, *r.urm.rex(0xf3, 0x0f, 0xb8))
I64.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8))
I32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt)
I64.enc(base.popcnt.i64, *r.urm.rex(0xf3, 0x0f, 0xb8, w=1),
isap=cfg.use_popcnt)
I64.enc(base.popcnt.i32, *r.urm.rex(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt)
I64.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt)
# Loads and stores.
I32.enc(base.store.i32.i32, *r.st(0x89))

View File

@@ -2,10 +2,40 @@
Intel settings.
"""
from __future__ import absolute_import
from cdsl.settings import SettingGroup
from cdsl.settings import SettingGroup, BoolSetting
from cdsl.predicates import And
import base.settings as shared
from .defs import ISA
ISA.settings = SettingGroup('intel', parent=shared.group)
# The has_* settings here correspond to CPUID bits.
# CPUID.01H:EDX
has_sse2 = BoolSetting("SSE2: CPUID.01H:EDX.SSE2[bit 26]")
# CPUID.01H:ECX
has_sse3 = BoolSetting("SSE3: CPUID.01H:ECX.SSE3[bit 0]")
has_ssse3 = BoolSetting("SSSE3: CPUID.01H:ECX.SSSE3[bit 9]")
has_sse41 = BoolSetting("SSE4.1: CPUID.01H:ECX.SSE4_1[bit 19]")
has_sse42 = BoolSetting("SSE4.2: CPUID.01H:ECX.SSE4_2[bit 20]")
has_popcnt = BoolSetting("POPCNT: CPUID.01H:ECX.POPCNT[bit 23]")
has_avx = BoolSetting("AVX: CPUID.01H:ECX.AVX[bit 28]")
# CPUID.(EAX=07H, ECX=0H):EBX
has_bmi1 = BoolSetting("BMI1: CPUID.(EAX=07H, ECX=0H):EBX.BMI1[bit 3]")
has_bmi2 = BoolSetting("BMI2: CPUID.(EAX=07H, ECX=0H):EBX.BMI2[bit 8]")
# CPUID.EAX=80000001H:ECX
has_lzcnt = BoolSetting("LZCNT: CPUID.EAX=80000001H:ECX.LZCNT[bit 5]")
# The use_* settings here are used to determine if a feature can be used.
use_sse41 = And(has_sse41)
use_sse42 = And(has_sse42, use_sse41)
use_popcnt = And(has_popcnt, has_sse42)
use_bmi1 = And(has_bmi1)
use_lzcnt = And(has_lzcnt)
ISA.settings.close(globals())