use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AmdgpuEncodingFormat {
SOP1,
SOP2,
SOPC,
SOPK,
SOPP,
VOP1,
VOP2,
VOPC,
VOP3,
VOP3P,
SMEM,
FLAT,
DS,
MIMG,
EXP,
VINTRP,
}
impl AmdgpuEncodingFormat {
pub fn size_bits(&self) -> u32 {
match self {
AmdgpuEncodingFormat::SOP1
| AmdgpuEncodingFormat::SOP2
| AmdgpuEncodingFormat::SOPC
| AmdgpuEncodingFormat::SOPK
| AmdgpuEncodingFormat::SOPP
| AmdgpuEncodingFormat::VOP1
| AmdgpuEncodingFormat::VOP2
| AmdgpuEncodingFormat::VOPC
| AmdgpuEncodingFormat::VINTRP => 32,
AmdgpuEncodingFormat::VOP3
| AmdgpuEncodingFormat::VOP3P
| AmdgpuEncodingFormat::SMEM
| AmdgpuEncodingFormat::FLAT
| AmdgpuEncodingFormat::DS
| AmdgpuEncodingFormat::MIMG
| AmdgpuEncodingFormat::EXP => 64,
}
}
pub fn is_64bit(&self) -> bool {
self.size_bits() == 64
}
pub fn is_32bit(&self) -> bool {
self.size_bits() == 32
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum AmdgpuOpcode {
SMovB32 = 21000,
SMovB64 = 21001,
SNotB32 = 21002,
SWqmB32 = 21003,
SWqmB64 = 21004,
SBrevB32 = 21005,
SBcnt1I32B32 = 21006,
SBcnt1I32B64 = 21007,
SFlbitI32B32 = 21008,
SFlbitI32B64 = 21009,
SAbsI32 = 21010,
SSextI32I8 = 21011,
SSextI32I16 = 21012,
SAndSaveexecB64 = 21013,
SOrSaveexecB64 = 21014,
SXorSaveexecB64 = 21015,
SAndn2SaveexecB64 = 21016,
SOrn2SaveexecB64 = 21017,
SNandSaveexecB64 = 21018,
SAddU32 = 21030,
SSubU32 = 21031,
SAddI32 = 21032,
SSubI32 = 21033,
SAndB32 = 21034,
SAndB64 = 21035,
SOrB32 = 21036,
SOrB64 = 21037,
SXorB32 = 21038,
SXorB64 = 21039,
SLshlB32 = 21040,
SLshlB64 = 21041,
SLshrB32 = 21042,
SLshrB64 = 21043,
SAshrI32 = 21044,
SAshrI64 = 21045,
SMulI32 = 21046,
SMinU32 = 21047,
SMinI32 = 21048,
SMaxU32 = 21049,
SMaxI32 = 21050,
SCselectB32 = 21051,
SCselectB64 = 21052,
SCmpEqI32 = 21060,
SCmpLgI32 = 21061,
SCmpGtI32 = 21062,
SCmpGeI32 = 21063,
SCmpLtI32 = 21064,
SCmpLeI32 = 21065,
SCmpEqU32 = 21066,
SCmpLgU32 = 21067,
SCmpGtU32 = 21068,
SCmpGeU32 = 21069,
SCmpLtU32 = 21070,
SCmpLeU32 = 21071,
SCmpEqU64 = 21072,
SCmpLgU64 = 21073,
SMovkI32 = 21080,
SCmpkEqI32 = 21081,
SCmpkLgI32 = 21082,
SCmpkGtI32 = 21083,
SCmpkGeI32 = 21084,
SCmpkLtI32 = 21085,
SCmpkLeI32 = 21086,
SCmpkEqU32 = 21087,
SCmpkLgU32 = 21088,
SAddkI32 = 21089,
SMulkI32 = 21090,
SNop = 21100,
SWaitcnt = 21101,
SBranch = 21102,
SCbranchScc0 = 21103,
SCbranchScc1 = 21104,
SCbranchVccz = 21105,
SCbranchVccnz = 21106,
SCbranchExecz = 21107,
SCbranchExecnz = 21108,
SEndpgm = 21109,
VNop = 21200,
VMovB32 = 21201,
VReadfirstlaneB32 = 21202,
VCvtF32I32 = 21203,
VCvtF32U32 = 21204,
VCvtI32F32 = 21205,
VCvtU32F32 = 21206,
VCvtF16F32 = 21207,
VCvtF32F16 = 21208,
VRcpF32 = 21209,
VRcpF64 = 21210,
VRsqF32 = 21211,
VRsqF64 = 21212,
VSqrtF32 = 21213,
VSqrtF64 = 21214,
VLogF32 = 21215,
VExpF32 = 21216,
VFractF32 = 21217,
VFractF64 = 21218,
VCosF32 = 21219,
VSinF32 = 21220,
VCeilF32 = 21221,
VCeilF64 = 21222,
VFloorF32 = 21223,
VFloorF64 = 21224,
VTruncF32 = 21225,
VTruncF64 = 21226,
VRndneF32 = 21227,
VRndneF64 = 21228,
VMovB64 = 21229,
VAddF32 = 21250,
VSubF32 = 21251,
VSubrevF32 = 21252,
VMulF32 = 21253,
VMulU32U24 = 21254,
VMulI32I24 = 21255,
VMacF32 = 21256,
VMaddF32 = 21257,
VMulLegacyF32 = 21258,
VMinF32 = 21259,
VMaxF32 = 21260,
VMinI32 = 21261,
VMaxI32 = 21262,
VMinU32 = 21263,
VMaxU32 = 21264,
VAndB32 = 21265,
VOrB32 = 21266,
VXorB32 = 21267,
VLshlB32 = 21268,
VLshrB32 = 21269,
VAshrI32 = 21270,
VLshlrevB32 = 21271,
VLshrrevB32 = 21272,
VAshrrevI32 = 21273,
VAddcU32 = 21274,
VSubbU32 = 21275,
VSubbrevU32 = 21276,
VCmpF32Eq = 21300,
VCmpF32Lg = 21301,
VCmpF32Gt = 21302,
VCmpF32Ge = 21303,
VCmpF32Lt = 21304,
VCmpF32Le = 21305,
VCmpF32Neq = 21306,
VCmpF32Nlg = 21307,
VCmpF32Ngt = 21308,
VCmpF32Nge = 21309,
VCmpF32Nlt = 21310,
VCmpF32Nle = 21311,
VCmpU32Eq = 21312,
VCmpU32Lg = 21313,
VCmpU32Gt = 21314,
VCmpU32Ge = 21315,
VCmpU32Lt = 21316,
VCmpU32Le = 21317,
VCmpI32Eq = 21318,
VCmpI32Gt = 21319,
VCmpI32Ge = 21320,
VCmpI32Lt = 21321,
VCmpI32Le = 21322,
VCmpF64Eq = 21323,
VCmpF64Lg = 21324,
VCmpF64Gt = 21325,
VCmpF64Ge = 21326,
VCmpF64Lt = 21327,
VCmpF64Le = 21328,
VAddF32Vop3 = 21400,
VSubF32Vop3 = 21401,
VMulF32Vop3 = 21402,
VAddF64 = 21403,
VSubF64 = 21404,
VMulF64 = 21405,
VMulHiU32 = 21406,
VMulHiI32 = 21407,
VDivScaleF32 = 21408,
VDivScaleF64 = 21409,
VMadF32 = 21410,
VMadF64 = 21411,
VMadI32I24 = 21412,
VMadU32U24 = 21413,
VFmaF32 = 21414,
VFmaF64 = 21415,
VPermB32 = 21416,
VAlignbitB32 = 21417,
VAlignbyteB32 = 21418,
VBfeU32 = 21419,
VBfeI32 = 21420,
VBfiB32 = 21421,
VInterpP1F32 = 21422,
VInterpP2F32 = 21423,
VInterpMovF32 = 21424,
VPkAddF16 = 21440,
VPkSubF16 = 21441,
VPkMulF16 = 21442,
VPkFmaF16 = 21443,
VPkAddU16 = 21444,
VPkMulU16 = 21445,
VPkMadU16 = 21446,
VPkMinF16 = 21447,
VPkMaxF16 = 21448,
VPkAddI16 = 21449,
VPkMulI16 = 21450,
SLoadDword = 21500,
SLoadDwordX2 = 21501,
SLoadDwordX4 = 21502,
SLoadDwordX8 = 21503,
SLoadDwordX16 = 21504,
SStoreDword = 21505,
SStoreDwordX2 = 21506,
SStoreDwordX4 = 21507,
SBufferLoadDword = 21508,
SBufferLoadDwordX2 = 21509,
SBufferLoadDwordX4 = 21510,
SBufferLoadDwordX8 = 21511,
SBufferLoadDwordX16 = 21512,
SBufferStoreDword = 21513,
SBufferStoreDwordX2 = 21514,
SBufferStoreDwordX4 = 21515,
SDcacheInv = 21516,
FlatLoadDword = 21530,
FlatLoadDwordX2 = 21531,
FlatLoadDwordX3 = 21532,
FlatLoadDwordX4 = 21533,
FlatStoreDword = 21534,
FlatStoreDwordX2 = 21535,
FlatStoreDwordX3 = 21536,
FlatStoreDwordX4 = 21537,
FlatAtomicAdd = 21538,
FlatAtomicSub = 21539,
FlatAtomicMin = 21540,
FlatAtomicMax = 21541,
FlatAtomicAnd = 21542,
FlatAtomicOr = 21543,
FlatAtomicXor = 21544,
FlatAtomicInc = 21545,
FlatAtomicDec = 21546,
FlatAtomicCmpswap = 21547,
GlobalLoadDword = 21548,
GlobalLoadDwordX2 = 21549,
GlobalLoadDwordX4 = 21550,
GlobalStoreDword = 21551,
GlobalStoreDwordX2 = 21552,
GlobalStoreDwordX4 = 21553,
GlobalAtomicAdd = 21554,
ScratchLoadDword = 21555,
ScratchStoreDword = 21556,
DsWriteB32 = 21570,
DsWriteB64 = 21571,
DsWriteB96 = 21572,
DsWriteB128 = 21573,
DsReadB32 = 21574,
DsReadB64 = 21575,
DsReadB96 = 21576,
DsReadB128 = 21577,
DsAddU32 = 21578,
DsSubU32 = 21579,
DsMinU32 = 21580,
DsMaxU32 = 21581,
DsAndB32 = 21582,
DsOrB32 = 21583,
DsXorB32 = 21584,
DsIncU32 = 21585,
DsDecU32 = 21586,
DsCmpstB32 = 21587,
DsSwizzleB32 = 21588,
DsPermuteB32 = 21589,
ImageLoad = 21600,
ImageLoadMip = 21601,
ImageLoadPck = 21602,
ImageLoadPckSgn = 21603,
ImageStore = 21604,
ImageStoreMip = 21605,
ImageStorePck = 21606,
ImageSample = 21607,
ImageSampleB = 21608,
ImageSampleD = 21609,
ImageSampleL = 21610,
ImageSampleC = 21611,
ImageSampleCl = 21612,
ImageSampleCd = 21613,
ImageGather4 = 21614,
ImageGather4B = 21615,
ImageGather4C = 21616,
ImageGetResinfo = 21617,
ImageAtomicSwap = 21618,
ImageAtomicAdd = 21619,
ImageAtomicMin = 21620,
ImageAtomicMax = 21621,
Exp = 21630,
ExpParam0 = 21631,
ExpParam1 = 21632,
ExpParam2 = 21633,
ExpParam3 = 21634,
ExpParam4 = 21635,
ExpParam5 = 21636,
ExpParam6 = 21637,
ExpParam7 = 21638,
ExpPos0 = 21639,
ExpMrt0 = 21640,
ExpMrtZ = 21641,
ExpNull = 21642,
VInterpP1F32Intrp = 21650,
VInterpP2F32Intrp = 21651,
VInterpMovF32Intrp = 21652,
VSwapB32 = 21700,
VCndmaskB32 = 21701,
VAddF16 = 21702,
VSubF16 = 21703,
VMulF16 = 21704,
VFmaF16 = 21705,
VMadMixF32 = 21706,
VDpp = 21707,
VScreenPartition4seB32 = 21708,
}
#[derive(Debug, Clone)]
pub struct AmdgpuInstrDesc {
pub opcode: AmdgpuOpcode,
pub mnemonic: &'static str,
pub encoding_format: AmdgpuEncodingFormat,
pub num_operands: u8,
pub num_defs: u8, pub num_srcs: u8, pub can_use_sgpr: bool, pub can_use_vgpr: bool, pub can_use_imm: bool, pub is_commutative: bool, pub writes_exec: bool, pub writes_vcc: bool, pub writes_scc: bool, pub reads_exec: bool, pub is_atomic: bool, pub is_load: bool, pub is_store: bool, pub may_load: bool,
pub may_store: bool,
pub has_side_effects: bool,
}
impl AmdgpuInstrDesc {
pub fn new(opcode: AmdgpuOpcode, mnemonic: &'static str, format: AmdgpuEncodingFormat) -> Self {
Self {
opcode,
mnemonic,
encoding_format: format,
num_operands: 0,
num_defs: 0,
num_srcs: 0,
can_use_sgpr: true,
can_use_vgpr: true,
can_use_imm: false,
is_commutative: false,
writes_exec: false,
writes_vcc: false,
writes_scc: false,
reads_exec: false,
is_atomic: false,
is_load: false,
is_store: false,
may_load: false,
may_store: false,
has_side_effects: false,
}
}
}
pub struct AmdgpuInstrInfo {
descriptors: HashMap<AmdgpuOpcode, AmdgpuInstrDesc>,
by_mnemonic: HashMap<String, AmdgpuOpcode>,
}
impl AmdgpuInstrInfo {
pub fn new() -> Self {
let mut info = Self {
descriptors: HashMap::new(),
by_mnemonic: HashMap::new(),
};
info.populate();
info
}
fn populate(&mut self) {
self.add_sop1(AmdgpuOpcode::SMovB32, "s_mov_b32", 1, 1, false);
self.add_sop1(AmdgpuOpcode::SMovB64, "s_mov_b64", 1, 1, false);
self.add_sop1(AmdgpuOpcode::SNotB32, "s_not_b32", 1, 1, false);
self.add_sop1(AmdgpuOpcode::SWqmB32, "s_wqm_b32", 1, 1, false);
self.add_sop1(AmdgpuOpcode::SBrevB32, "s_brev_b32", 1, 1, false);
self.add_sop1(AmdgpuOpcode::SAbsI32, "s_abs_i32", 1, 1, false);
self.add_sop2(AmdgpuOpcode::SAddU32, "s_add_u32", 2, false);
self.add_sop2(AmdgpuOpcode::SSubU32, "s_sub_u32", 2, false);
self.add_sop2(AmdgpuOpcode::SAndB32, "s_and_b32", 2, true);
self.add_sop2(AmdgpuOpcode::SOrB32, "s_or_b32", 2, true);
self.add_sop2(AmdgpuOpcode::SXorB32, "s_xor_b32", 2, true);
self.add_sop2(AmdgpuOpcode::SMulI32, "s_mul_i32", 2, true);
self.add_sop2(AmdgpuOpcode::SMinU32, "s_min_u32", 2, true);
self.add_sop2(AmdgpuOpcode::SMaxU32, "s_max_u32", 2, true);
self.add_sopc(AmdgpuOpcode::SCmpEqI32, "s_cmp_eq_i32");
self.add_sopc(AmdgpuOpcode::SCmpLgI32, "s_cmp_lg_i32");
self.add_sopc(AmdgpuOpcode::SCmpGtI32, "s_cmp_gt_i32");
self.add_sopc(AmdgpuOpcode::SCmpEqU32, "s_cmp_eq_u32");
self.add_sopk(AmdgpuOpcode::SMovkI32, "s_movk_i32");
self.add_sopk(AmdgpuOpcode::SAddkI32, "s_addk_i32");
self.add_sopk(AmdgpuOpcode::SMulkI32, "s_mulk_i32");
self.add_sopp(AmdgpuOpcode::SNop, "s_nop");
self.add_sopp(AmdgpuOpcode::SWaitcnt, "s_waitcnt");
self.add_sopp(AmdgpuOpcode::SBranch, "s_branch");
self.add_sopp(AmdgpuOpcode::SEndpgm, "s_endpgm");
self.add_vop1(AmdgpuOpcode::VMovB32, "v_mov_b32", 1, 1);
self.add_vop1(AmdgpuOpcode::VRcpF32, "v_rcp_f32", 1, 1);
self.add_vop1(AmdgpuOpcode::VSqrtF32, "v_sqrt_f32", 1, 1);
self.add_vop1(AmdgpuOpcode::VLogF32, "v_log_f32", 1, 1);
self.add_vop1(AmdgpuOpcode::VExpF32, "v_exp_f32", 1, 1);
self.add_vop2(AmdgpuOpcode::VAddF32, "v_add_f32", 2, true);
self.add_vop2(AmdgpuOpcode::VSubF32, "v_sub_f32", 2, false);
self.add_vop2(AmdgpuOpcode::VMulF32, "v_mul_f32", 2, true);
self.add_vop2(AmdgpuOpcode::VMinF32, "v_min_f32", 2, true);
self.add_vop2(AmdgpuOpcode::VMaxF32, "v_max_f32", 2, true);
self.add_vop2(AmdgpuOpcode::VAndB32, "v_and_b32", 2, true);
self.add_vop2(AmdgpuOpcode::VOrB32, "v_or_b32", 2, true);
self.add_vop2(AmdgpuOpcode::VXorB32, "v_xor_b32", 2, true);
self.add_vopc(AmdgpuOpcode::VCmpF32Eq, "v_cmp_eq_f32");
self.add_vopc(AmdgpuOpcode::VCmpF32Lt, "v_cmp_lt_f32");
self.add_vopc(AmdgpuOpcode::VCmpF32Gt, "v_cmp_gt_f32");
self.add_vop3(AmdgpuOpcode::VAddF32Vop3, "v_add_f32", 3, true);
self.add_vop3(AmdgpuOpcode::VMulF32Vop3, "v_mul_f32", 3, true);
self.add_vop3(AmdgpuOpcode::VFmaF32, "v_fma_f32", 3, false);
self.add_vop3(AmdgpuOpcode::VAddF64, "v_add_f64", 3, true);
self.add_vop3(AmdgpuOpcode::VMadF32, "v_mad_f32", 3, false);
self.add_vop3p(AmdgpuOpcode::VPkAddF16, "v_pk_add_f16", 3, true);
self.add_vop3p(AmdgpuOpcode::VPkMulF16, "v_pk_mul_f16", 3, true);
self.add_vop3p(AmdgpuOpcode::VPkFmaF16, "v_pk_fma_f16", 3, false);
self.add_smem(AmdgpuOpcode::SLoadDword, "s_load_dword", false, true, false);
self.add_smem(
AmdgpuOpcode::SLoadDwordX4,
"s_load_dwordx4",
false,
true,
false,
);
self.add_smem(
AmdgpuOpcode::SStoreDword,
"s_store_dword",
false,
false,
true,
);
self.add_flat(AmdgpuOpcode::FlatLoadDword, "flat_load_dword", true, false);
self.add_flat(
AmdgpuOpcode::FlatStoreDword,
"flat_store_dword",
false,
true,
);
self.add_flat(
AmdgpuOpcode::GlobalLoadDword,
"global_load_dword",
true,
false,
);
self.add_flat(
AmdgpuOpcode::GlobalStoreDword,
"global_store_dword",
false,
true,
);
self.add_ds(AmdgpuOpcode::DsWriteB32, "ds_write_b32", false, true);
self.add_ds(AmdgpuOpcode::DsReadB32, "ds_read_b32", true, false);
self.add_ds(AmdgpuOpcode::DsAddU32, "ds_add_u32", true, true);
self.add_mimg(AmdgpuOpcode::ImageLoad, "image_load", true, false);
self.add_mimg(AmdgpuOpcode::ImageStore, "image_store", false, true);
self.add_mimg(AmdgpuOpcode::ImageSample, "image_sample", true, false);
self.add_exp(AmdgpuOpcode::Exp, "exp", 0);
self.add_exp(AmdgpuOpcode::ExpMrt0, "exp_mrt0", 0);
}
fn register(&mut self, desc: AmdgpuInstrDesc) {
self.by_mnemonic
.insert(desc.mnemonic.to_string(), desc.opcode);
self.descriptors.insert(desc.opcode, desc);
}
fn add_sop1(
&mut self,
op: AmdgpuOpcode,
mnemonic: &'static str,
num_srcs: u8,
num_defs: u8,
_commutative: bool,
) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::SOP1);
d.num_operands = num_srcs + num_defs;
d.num_defs = num_defs;
d.num_srcs = num_srcs;
self.register(d);
}
fn add_sop2(
&mut self,
op: AmdgpuOpcode,
mnemonic: &'static str,
num_srcs: u8,
commutative: bool,
) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::SOP2);
d.num_operands = 1 + num_srcs;
d.num_defs = 1;
d.num_srcs = num_srcs;
d.is_commutative = commutative;
self.register(d);
}
fn add_sopc(&mut self, op: AmdgpuOpcode, mnemonic: &'static str) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::SOPC);
d.num_srcs = 2;
d.num_operands = 2;
d.writes_scc = true;
self.register(d);
}
fn add_sopk(&mut self, op: AmdgpuOpcode, mnemonic: &'static str) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::SOPK);
d.num_srcs = 1;
d.num_defs = 1;
d.num_operands = 2;
d.can_use_imm = true;
self.register(d);
}
fn add_sopp(&mut self, op: AmdgpuOpcode, mnemonic: &'static str) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::SOPP);
d.num_operands = 0;
self.register(d);
}
fn add_vop1(&mut self, op: AmdgpuOpcode, mnemonic: &'static str, num_srcs: u8, num_defs: u8) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::VOP1);
d.num_operands = num_srcs + num_defs;
d.num_defs = num_defs;
d.num_srcs = num_srcs;
d.can_use_sgpr = true;
d.can_use_vgpr = true;
d.reads_exec = true;
self.register(d);
}
fn add_vop2(
&mut self,
op: AmdgpuOpcode,
mnemonic: &'static str,
num_srcs: u8,
commutative: bool,
) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::VOP2);
d.num_operands = 1 + num_srcs;
d.num_defs = 1;
d.num_srcs = num_srcs;
d.can_use_sgpr = true;
d.can_use_vgpr = true;
d.is_commutative = commutative;
d.reads_exec = true;
self.register(d);
}
fn add_vopc(&mut self, op: AmdgpuOpcode, mnemonic: &'static str) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::VOPC);
d.num_operands = 2;
d.num_srcs = 2;
d.writes_vcc = true;
d.reads_exec = true;
self.register(d);
}
fn add_vop3(
&mut self,
op: AmdgpuOpcode,
mnemonic: &'static str,
num_srcs: u8,
commutative: bool,
) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::VOP3);
d.num_operands = 1 + num_srcs;
d.num_defs = 1;
d.num_srcs = num_srcs;
d.can_use_sgpr = true;
d.can_use_vgpr = true;
d.is_commutative = commutative;
d.reads_exec = true;
self.register(d);
}
fn add_vop3p(
&mut self,
op: AmdgpuOpcode,
mnemonic: &'static str,
num_srcs: u8,
commutative: bool,
) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::VOP3P);
d.num_operands = 1 + num_srcs;
d.num_defs = 1;
d.num_srcs = num_srcs;
d.is_commutative = commutative;
d.reads_exec = true;
self.register(d);
}
fn add_smem(
&mut self,
op: AmdgpuOpcode,
mnemonic: &'static str,
is_load: bool,
_may_load: bool,
is_store: bool,
) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::SMEM);
d.num_operands = 3; d.is_load = is_load;
d.is_store = is_store;
d.may_load = is_load;
d.may_store = is_store;
d.can_use_sgpr = true;
self.register(d);
}
fn add_flat(
&mut self,
op: AmdgpuOpcode,
mnemonic: &'static str,
is_load: bool,
is_store: bool,
) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::FLAT);
d.num_operands = 2;
d.is_load = is_load;
d.is_store = is_store;
d.may_load = is_load;
d.may_store = is_store;
self.register(d);
}
fn add_ds(&mut self, op: AmdgpuOpcode, mnemonic: &'static str, is_load: bool, is_store: bool) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::DS);
d.num_operands = 2;
d.is_load = is_load;
d.is_store = is_store;
d.may_load = is_load;
d.may_store = is_store;
self.register(d);
}
fn add_mimg(
&mut self,
op: AmdgpuOpcode,
mnemonic: &'static str,
is_load: bool,
is_store: bool,
) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::MIMG);
d.num_operands = 4;
d.is_load = is_load;
d.is_store = is_store;
d.may_load = is_load;
d.may_store = is_store;
self.register(d);
}
fn add_exp(&mut self, op: AmdgpuOpcode, mnemonic: &'static str, num_srcs: u8) {
let mut d = AmdgpuInstrDesc::new(op, mnemonic, AmdgpuEncodingFormat::EXP);
d.num_operands = num_srcs;
d.num_srcs = num_srcs;
self.register(d);
}
pub fn get(&self, opcode: AmdgpuOpcode) -> Option<&AmdgpuInstrDesc> {
self.descriptors.get(&opcode)
}
pub fn lookup_by_mnemonic(&self, mnemonic: &str) -> Option<AmdgpuOpcode> {
self.by_mnemonic.get(mnemonic).copied()
}
pub fn count(&self) -> usize {
self.descriptors.len()
}
}
impl Default for AmdgpuInstrInfo {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_instr_info_count() {
let info = AmdgpuInstrInfo::new();
assert!(info.count() >= 60); }
#[test]
fn test_lookup_sop1() {
let info = AmdgpuInstrInfo::new();
let desc = info.get(AmdgpuOpcode::SMovB32).unwrap();
assert_eq!(desc.mnemonic, "s_mov_b32");
assert_eq!(desc.encoding_format, AmdgpuEncodingFormat::SOP1);
}
#[test]
fn test_lookup_vop2() {
let info = AmdgpuInstrInfo::new();
let desc = info.get(AmdgpuOpcode::VAddF32).unwrap();
assert_eq!(desc.mnemonic, "v_add_f32");
assert_eq!(desc.encoding_format, AmdgpuEncodingFormat::VOP2);
assert!(desc.is_commutative);
}
#[test]
fn test_lookup_flat() {
let info = AmdgpuInstrInfo::new();
let desc = info.get(AmdgpuOpcode::GlobalLoadDword).unwrap();
assert!(desc.is_load);
assert!(!desc.is_store);
}
#[test]
fn test_lookup_ds() {
let info = AmdgpuInstrInfo::new();
let desc = info.get(AmdgpuOpcode::DsWriteB32).unwrap();
assert!(desc.is_store);
assert_eq!(desc.encoding_format, AmdgpuEncodingFormat::DS);
}
#[test]
fn test_lookup_mimg() {
let info = AmdgpuInstrInfo::new();
let desc = info.get(AmdgpuOpcode::ImageSample).unwrap();
assert!(desc.is_load);
assert_eq!(desc.encoding_format, AmdgpuEncodingFormat::MIMG);
}
#[test]
fn test_encoding_format_sizes() {
assert_eq!(AmdgpuEncodingFormat::SOP1.size_bits(), 32);
assert_eq!(AmdgpuEncodingFormat::VOP3.size_bits(), 64);
assert!(AmdgpuEncodingFormat::VOP3.is_64bit());
assert!(AmdgpuEncodingFormat::SOP1.is_32bit());
}
#[test]
fn test_mnemonic_lookup() {
let info = AmdgpuInstrInfo::new();
assert_eq!(
info.lookup_by_mnemonic("s_endpgm"),
Some(AmdgpuOpcode::SEndpgm)
);
}
}