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) is_pic = And(shared.is_pic) not_is_pic = Not(shared.is_pic) all_ones_funcaddrs_and_not_is_pic = And(shared.allones_funcaddrs, Not(shared.is_pic)) not_all_ones_funcaddrs_and_not_is_pic = And(Not(shared.allones_funcaddrs), Not(shared.is_pic)) # Presets corresponding to x86 CPUs. baseline = Preset() nehalem = Preset(has_sse3, has_ssse3, has_sse41, has_sse42, has_popcnt) haswell = Preset(nehalem, has_bmi1, has_bmi2, has_lzcnt) broadwell = Preset(haswell) skylake = Preset(broadwell) cannonlake = Preset(skylake) icelake = Preset(cannonlake)
enc_both(base.fill.f64, r.ffillSib32, 0xf2, 0x0f, 0x10) enc_both(base.regfill.f64, r.fregfill32, 0xf2, 0x0f, 0x10) enc_both(base.spill.f32, r.fspillSib32, 0xf3, 0x0f, 0x11) enc_both(base.regspill.f32, r.fregspill32, 0xf3, 0x0f, 0x11) enc_both(base.spill.f64, r.fspillSib32, 0xf2, 0x0f, 0x11) enc_both(base.regspill.f64, r.fregspill32, 0xf2, 0x0f, 0x11) # # Function addresses. # # Non-PIC, all-ones funcaddresses. X86_32.enc(base.func_addr.i32, *r.fnaddr4(0xb8), isap=And(Not(allones_funcaddrs), Not(is_pic))) X86_64.enc(base.func_addr.i64, *r.fnaddr8.rex(0xb8, w=1), isap=And(Not(allones_funcaddrs), Not(is_pic))) # Non-PIC, all-zeros funcaddresses. X86_32.enc(base.func_addr.i32, *r.allones_fnaddr4(0xb8), isap=And(allones_funcaddrs, Not(is_pic))) X86_64.enc(base.func_addr.i64, *r.allones_fnaddr8.rex(0xb8, w=1), isap=And(allones_funcaddrs, Not(is_pic))) # 64-bit, colocated, both PIC and non-PIC. Use the lea instruction's # pc-relative field. X86_64.enc(base.func_addr.i64,
enc_both(base.fill.f32, r.ffillSib32, 0x66, 0x0f, 0x6e) enc_both(base.regfill.f32, r.fregfill32, 0x66, 0x0f, 0x6e) enc_both(base.fill.f64, r.ffillSib32, 0xf3, 0x0f, 0x7e) enc_both(base.regfill.f64, r.fregfill32, 0xf3, 0x0f, 0x7e) enc_both(base.spill.f32, r.fspillSib32, 0x66, 0x0f, 0x7e) enc_both(base.regspill.f32, r.fregspill32, 0x66, 0x0f, 0x7e) enc_both(base.spill.f64, r.fspillSib32, 0x66, 0x0f, 0xd6) enc_both(base.regspill.f64, r.fregspill32, 0x66, 0x0f, 0xd6) # # Function addresses. # X86_32.enc(base.func_addr.i32, *r.fnaddr4(0xb8), isap=Not(allones_funcaddrs)) X86_64.enc(base.func_addr.i64, *r.fnaddr8.rex(0xb8, w=1), isap=And(Not(allones_funcaddrs), Not(is_pic))) X86_32.enc(base.func_addr.i32, *r.allones_fnaddr4(0xb8), isap=allones_funcaddrs) X86_64.enc(base.func_addr.i64, *r.allones_fnaddr8.rex(0xb8, w=1), isap=And(allones_funcaddrs, Not(is_pic))) X86_64.enc(base.func_addr.i64, *r.got_fnaddr8.rex(0x8b, w=1), isap=is_pic) # # Global addresses.
enc_both(base.fill.f32, r.ffiSib32, 0x66, 0x0f, 0x6e) enc_both(base.regfill.f32, r.frfi32, 0x66, 0x0f, 0x6e) enc_both(base.fill.f64, r.ffiSib32, 0xf3, 0x0f, 0x7e) enc_both(base.regfill.f64, r.frfi32, 0xf3, 0x0f, 0x7e) enc_both(base.spill.f32, r.fspSib32, 0x66, 0x0f, 0x7e) enc_both(base.regspill.f32, r.frsp32, 0x66, 0x0f, 0x7e) enc_both(base.spill.f64, r.fspSib32, 0x66, 0x0f, 0xd6) enc_both(base.regspill.f64, r.frsp32, 0x66, 0x0f, 0xd6) # # Function addresses. # I32.enc(base.func_addr.i32, *r.fnaddr4(0xb8), isap=Not(allones_funcaddrs)) I64.enc(base.func_addr.i64, *r.fnaddr8.rex(0xb8, w=1), isap=And(Not(allones_funcaddrs), Not(is_pic))) I32.enc(base.func_addr.i32, *r.allones_fnaddr4(0xb8), isap=allones_funcaddrs) I64.enc(base.func_addr.i64, *r.allones_fnaddr8.rex(0xb8, w=1), isap=And(allones_funcaddrs, Not(is_pic))) I64.enc(base.func_addr.i64, *r.got_fnaddr8.rex(0x8b, w=1), isap=is_pic) # # Global addresses. #
enc_both(base.regfill.f32, r.fregfill32, 0xf3, 0x0f, 0x10) enc_both(base.fill.f64, r.ffillSib32, 0xf2, 0x0f, 0x10) enc_both(base.regfill.f64, r.fregfill32, 0xf2, 0x0f, 0x10) enc_both(base.spill.f32, r.fspillSib32, 0xf3, 0x0f, 0x11) enc_both(base.regspill.f32, r.fregspill32, 0xf3, 0x0f, 0x11) enc_both(base.spill.f64, r.fspillSib32, 0xf2, 0x0f, 0x11) enc_both(base.regspill.f64, r.fregspill32, 0xf2, 0x0f, 0x11) # # Function addresses. # # Non-PIC, all-ones funcaddresses. X86_32.enc(base.func_addr.i32, *r.fnaddr4(0xb8), isap=And(Not(allones_funcaddrs), Not(is_pic))) X86_64.enc(base.func_addr.i64, *r.fnaddr8.rex(0xb8, w=1), isap=And(Not(allones_funcaddrs), Not(is_pic))) # Non-PIC, all-zeros funcaddresses. X86_32.enc(base.func_addr.i32, *r.allones_fnaddr4(0xb8), isap=And(allones_funcaddrs, Not(is_pic))) X86_64.enc(base.func_addr.i64, *r.allones_fnaddr8.rex(0xb8, w=1), isap=And(allones_funcaddrs, Not(is_pic))) # 64-bit, colocated, both PIC and non-PIC. Use the lea instruction's # pc-relative field. X86_64.enc(base.func_addr.i64, *r.pcrel_fnaddr8.rex(0x8d, w=1), instp=IsColocatedFunc(FuncAddr.func_ref)) # 64-bit, non-colocated, PIC.
enc_both(base.fill.f32, r.ffiSib32, 0x66, 0x0f, 0x6e) enc_both(base.regfill.f32, r.frfi32, 0x66, 0x0f, 0x6e) enc_both(base.fill.f64, r.ffiSib32, 0xf3, 0x0f, 0x7e) enc_both(base.regfill.f64, r.frfi32, 0xf3, 0x0f, 0x7e) enc_both(base.spill.f32, r.fspSib32, 0x66, 0x0f, 0x7e) enc_both(base.regspill.f32, r.frsp32, 0x66, 0x0f, 0x7e) enc_both(base.spill.f64, r.fspSib32, 0x66, 0x0f, 0xd6) enc_both(base.regspill.f64, r.frsp32, 0x66, 0x0f, 0xd6) # # Function addresses. # I32.enc(base.func_addr.i32, *r.fnaddr4(0xb8), isap=Not(allones_funcaddrs)) I64.enc(base.func_addr.i64, *r.fnaddr8.rex(0xb8, w=1), isap=Not(allones_funcaddrs)) I32.enc(base.func_addr.i32, *r.allones_fnaddr4(0xb8), isap=allones_funcaddrs) I64.enc(base.func_addr.i64, *r.allones_fnaddr8.rex(0xb8, w=1), isap=allones_funcaddrs) # # Global addresses. # I32.enc(base.globalsym_addr.i32, *r.gvaddr4(0xb8)) I64.enc(base.globalsym_addr.i64, *r.gvaddr8.rex(0xb8, w=1))