1*61046927SAndroid Build Coastguard Worker // Copyright © 2022 Collabora, Ltd.
2*61046927SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
3*61046927SAndroid Build Coastguard Worker
4*61046927SAndroid Build Coastguard Worker use crate::ir::*;
5*61046927SAndroid Build Coastguard Worker use crate::legalize::{
6*61046927SAndroid Build Coastguard Worker src_is_reg, src_is_upred_reg, swap_srcs_if_not_reg, LegalizeBuildHelpers,
7*61046927SAndroid Build Coastguard Worker LegalizeBuilder,
8*61046927SAndroid Build Coastguard Worker };
9*61046927SAndroid Build Coastguard Worker use bitview::*;
10*61046927SAndroid Build Coastguard Worker
11*61046927SAndroid Build Coastguard Worker use std::collections::HashMap;
12*61046927SAndroid Build Coastguard Worker use std::ops::Range;
13*61046927SAndroid Build Coastguard Worker
14*61046927SAndroid Build Coastguard Worker pub struct ShaderModel70 {
15*61046927SAndroid Build Coastguard Worker sm: u8,
16*61046927SAndroid Build Coastguard Worker }
17*61046927SAndroid Build Coastguard Worker
18*61046927SAndroid Build Coastguard Worker impl ShaderModel70 {
new(sm: u8) -> Self19*61046927SAndroid Build Coastguard Worker pub fn new(sm: u8) -> Self {
20*61046927SAndroid Build Coastguard Worker assert!(sm >= 70);
21*61046927SAndroid Build Coastguard Worker Self { sm }
22*61046927SAndroid Build Coastguard Worker }
23*61046927SAndroid Build Coastguard Worker
has_uniform_alu(&self) -> bool24*61046927SAndroid Build Coastguard Worker fn has_uniform_alu(&self) -> bool {
25*61046927SAndroid Build Coastguard Worker self.sm >= 75
26*61046927SAndroid Build Coastguard Worker }
27*61046927SAndroid Build Coastguard Worker }
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker impl ShaderModel for ShaderModel70 {
sm(&self) -> u830*61046927SAndroid Build Coastguard Worker fn sm(&self) -> u8 {
31*61046927SAndroid Build Coastguard Worker self.sm
32*61046927SAndroid Build Coastguard Worker }
33*61046927SAndroid Build Coastguard Worker
num_regs(&self, file: RegFile) -> u3234*61046927SAndroid Build Coastguard Worker fn num_regs(&self, file: RegFile) -> u32 {
35*61046927SAndroid Build Coastguard Worker match file {
36*61046927SAndroid Build Coastguard Worker RegFile::GPR => {
37*61046927SAndroid Build Coastguard Worker // Volta+ has a maximum of 253 registers. Presumably
38*61046927SAndroid Build Coastguard Worker // because two registers get burned for UGPRs? Unclear
39*61046927SAndroid Build Coastguard Worker // on why we need it on Volta though.
40*61046927SAndroid Build Coastguard Worker 253
41*61046927SAndroid Build Coastguard Worker }
42*61046927SAndroid Build Coastguard Worker RegFile::UGPR => {
43*61046927SAndroid Build Coastguard Worker if self.has_uniform_alu() {
44*61046927SAndroid Build Coastguard Worker 63
45*61046927SAndroid Build Coastguard Worker } else {
46*61046927SAndroid Build Coastguard Worker 0
47*61046927SAndroid Build Coastguard Worker }
48*61046927SAndroid Build Coastguard Worker }
49*61046927SAndroid Build Coastguard Worker RegFile::Pred => 7,
50*61046927SAndroid Build Coastguard Worker RegFile::UPred => {
51*61046927SAndroid Build Coastguard Worker if self.has_uniform_alu() {
52*61046927SAndroid Build Coastguard Worker 7
53*61046927SAndroid Build Coastguard Worker } else {
54*61046927SAndroid Build Coastguard Worker 0
55*61046927SAndroid Build Coastguard Worker }
56*61046927SAndroid Build Coastguard Worker }
57*61046927SAndroid Build Coastguard Worker RegFile::Carry => 0,
58*61046927SAndroid Build Coastguard Worker RegFile::Bar => 16,
59*61046927SAndroid Build Coastguard Worker RegFile::Mem => RegRef::MAX_IDX + 1,
60*61046927SAndroid Build Coastguard Worker }
61*61046927SAndroid Build Coastguard Worker }
62*61046927SAndroid Build Coastguard Worker
crs_size(&self, max_crs_depth: u32) -> u3263*61046927SAndroid Build Coastguard Worker fn crs_size(&self, max_crs_depth: u32) -> u32 {
64*61046927SAndroid Build Coastguard Worker assert!(max_crs_depth == 0);
65*61046927SAndroid Build Coastguard Worker 0
66*61046927SAndroid Build Coastguard Worker }
67*61046927SAndroid Build Coastguard Worker
op_can_be_uniform(&self, op: &Op) -> bool68*61046927SAndroid Build Coastguard Worker fn op_can_be_uniform(&self, op: &Op) -> bool {
69*61046927SAndroid Build Coastguard Worker if !self.has_uniform_alu() {
70*61046927SAndroid Build Coastguard Worker return false;
71*61046927SAndroid Build Coastguard Worker }
72*61046927SAndroid Build Coastguard Worker
73*61046927SAndroid Build Coastguard Worker match op {
74*61046927SAndroid Build Coastguard Worker Op::R2UR(_)
75*61046927SAndroid Build Coastguard Worker | Op::S2R(_)
76*61046927SAndroid Build Coastguard Worker | Op::BMsk(_)
77*61046927SAndroid Build Coastguard Worker | Op::BRev(_)
78*61046927SAndroid Build Coastguard Worker | Op::Flo(_)
79*61046927SAndroid Build Coastguard Worker | Op::IAdd3(_)
80*61046927SAndroid Build Coastguard Worker | Op::IAdd3X(_)
81*61046927SAndroid Build Coastguard Worker | Op::IMad(_)
82*61046927SAndroid Build Coastguard Worker | Op::IMad64(_)
83*61046927SAndroid Build Coastguard Worker | Op::ISetP(_)
84*61046927SAndroid Build Coastguard Worker | Op::Lop3(_)
85*61046927SAndroid Build Coastguard Worker | Op::Mov(_)
86*61046927SAndroid Build Coastguard Worker | Op::PLop3(_)
87*61046927SAndroid Build Coastguard Worker | Op::PopC(_)
88*61046927SAndroid Build Coastguard Worker | Op::Prmt(_)
89*61046927SAndroid Build Coastguard Worker | Op::PSetP(_)
90*61046927SAndroid Build Coastguard Worker | Op::Sel(_)
91*61046927SAndroid Build Coastguard Worker | Op::Shf(_)
92*61046927SAndroid Build Coastguard Worker | Op::Shl(_)
93*61046927SAndroid Build Coastguard Worker | Op::Shr(_)
94*61046927SAndroid Build Coastguard Worker | Op::Vote(_)
95*61046927SAndroid Build Coastguard Worker | Op::Copy(_)
96*61046927SAndroid Build Coastguard Worker | Op::Pin(_)
97*61046927SAndroid Build Coastguard Worker | Op::Unpin(_) => true,
98*61046927SAndroid Build Coastguard Worker Op::Ldc(op) => op.offset.is_zero(),
99*61046927SAndroid Build Coastguard Worker // UCLEA USHL USHR
100*61046927SAndroid Build Coastguard Worker _ => false,
101*61046927SAndroid Build Coastguard Worker }
102*61046927SAndroid Build Coastguard Worker }
103*61046927SAndroid Build Coastguard Worker
legalize_op(&self, b: &mut LegalizeBuilder, op: &mut Op)104*61046927SAndroid Build Coastguard Worker fn legalize_op(&self, b: &mut LegalizeBuilder, op: &mut Op) {
105*61046927SAndroid Build Coastguard Worker as_sm70_op_mut(op).legalize(b);
106*61046927SAndroid Build Coastguard Worker }
107*61046927SAndroid Build Coastguard Worker
encode_shader(&self, s: &Shader<'_>) -> Vec<u32>108*61046927SAndroid Build Coastguard Worker fn encode_shader(&self, s: &Shader<'_>) -> Vec<u32> {
109*61046927SAndroid Build Coastguard Worker encode_sm70_shader(self, s)
110*61046927SAndroid Build Coastguard Worker }
111*61046927SAndroid Build Coastguard Worker }
112*61046927SAndroid Build Coastguard Worker
113*61046927SAndroid Build Coastguard Worker /// A per-op trait that implements Volta+ opcode semantics
114*61046927SAndroid Build Coastguard Worker trait SM70Op {
legalize(&mut self, b: &mut LegalizeBuilder)115*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder);
encode(&self, e: &mut SM70Encoder<'_>)116*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>);
117*61046927SAndroid Build Coastguard Worker }
118*61046927SAndroid Build Coastguard Worker
119*61046927SAndroid Build Coastguard Worker struct SM70Encoder<'a> {
120*61046927SAndroid Build Coastguard Worker sm: &'a ShaderModel70,
121*61046927SAndroid Build Coastguard Worker ip: usize,
122*61046927SAndroid Build Coastguard Worker labels: &'a HashMap<Label, usize>,
123*61046927SAndroid Build Coastguard Worker inst: [u32; 4],
124*61046927SAndroid Build Coastguard Worker }
125*61046927SAndroid Build Coastguard Worker
126*61046927SAndroid Build Coastguard Worker impl BitViewable for SM70Encoder<'_> {
bits(&self) -> usize127*61046927SAndroid Build Coastguard Worker fn bits(&self) -> usize {
128*61046927SAndroid Build Coastguard Worker BitView::new(&self.inst).bits()
129*61046927SAndroid Build Coastguard Worker }
130*61046927SAndroid Build Coastguard Worker
get_bit_range_u64(&self, range: Range<usize>) -> u64131*61046927SAndroid Build Coastguard Worker fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
132*61046927SAndroid Build Coastguard Worker BitView::new(&self.inst).get_bit_range_u64(range)
133*61046927SAndroid Build Coastguard Worker }
134*61046927SAndroid Build Coastguard Worker }
135*61046927SAndroid Build Coastguard Worker
136*61046927SAndroid Build Coastguard Worker impl BitMutViewable for SM70Encoder<'_> {
set_bit_range_u64(&mut self, range: Range<usize>, val: u64)137*61046927SAndroid Build Coastguard Worker fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
138*61046927SAndroid Build Coastguard Worker BitMutView::new(&mut self.inst).set_bit_range_u64(range, val);
139*61046927SAndroid Build Coastguard Worker }
140*61046927SAndroid Build Coastguard Worker }
141*61046927SAndroid Build Coastguard Worker
142*61046927SAndroid Build Coastguard Worker impl SetFieldU64 for SM70Encoder<'_> {
set_field_u64(&mut self, range: Range<usize>, val: u64)143*61046927SAndroid Build Coastguard Worker fn set_field_u64(&mut self, range: Range<usize>, val: u64) {
144*61046927SAndroid Build Coastguard Worker BitMutView::new(&mut self.inst).set_field_u64(range, val);
145*61046927SAndroid Build Coastguard Worker }
146*61046927SAndroid Build Coastguard Worker }
147*61046927SAndroid Build Coastguard Worker
148*61046927SAndroid Build Coastguard Worker impl SM70Encoder<'_> {
set_opcode(&mut self, opcode: u16)149*61046927SAndroid Build Coastguard Worker fn set_opcode(&mut self, opcode: u16) {
150*61046927SAndroid Build Coastguard Worker self.set_field(0..12, opcode);
151*61046927SAndroid Build Coastguard Worker }
152*61046927SAndroid Build Coastguard Worker
set_reg(&mut self, range: Range<usize>, reg: RegRef)153*61046927SAndroid Build Coastguard Worker fn set_reg(&mut self, range: Range<usize>, reg: RegRef) {
154*61046927SAndroid Build Coastguard Worker assert!(range.len() == 8);
155*61046927SAndroid Build Coastguard Worker assert!(reg.file() == RegFile::GPR);
156*61046927SAndroid Build Coastguard Worker self.set_field(range, reg.base_idx());
157*61046927SAndroid Build Coastguard Worker }
158*61046927SAndroid Build Coastguard Worker
set_ureg(&mut self, range: Range<usize>, reg: RegRef)159*61046927SAndroid Build Coastguard Worker fn set_ureg(&mut self, range: Range<usize>, reg: RegRef) {
160*61046927SAndroid Build Coastguard Worker assert!(self.sm.sm >= 75);
161*61046927SAndroid Build Coastguard Worker assert!(range.len() == 8);
162*61046927SAndroid Build Coastguard Worker assert!(reg.file() == RegFile::UGPR);
163*61046927SAndroid Build Coastguard Worker assert!(reg.base_idx() <= 63);
164*61046927SAndroid Build Coastguard Worker self.set_field(range, reg.base_idx());
165*61046927SAndroid Build Coastguard Worker }
166*61046927SAndroid Build Coastguard Worker
set_pred_reg(&mut self, range: Range<usize>, reg: RegRef)167*61046927SAndroid Build Coastguard Worker fn set_pred_reg(&mut self, range: Range<usize>, reg: RegRef) {
168*61046927SAndroid Build Coastguard Worker assert!(range.len() == 3);
169*61046927SAndroid Build Coastguard Worker assert!(reg.base_idx() <= 7);
170*61046927SAndroid Build Coastguard Worker assert!(reg.comps() == 1);
171*61046927SAndroid Build Coastguard Worker self.set_field(range, reg.base_idx());
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker
set_reg_src(&mut self, range: Range<usize>, src: Src)174*61046927SAndroid Build Coastguard Worker fn set_reg_src(&mut self, range: Range<usize>, src: Src) {
175*61046927SAndroid Build Coastguard Worker assert!(src.src_mod.is_none());
176*61046927SAndroid Build Coastguard Worker match src.src_ref {
177*61046927SAndroid Build Coastguard Worker SrcRef::Zero => self.set_reg(range, RegRef::zero(RegFile::GPR, 1)),
178*61046927SAndroid Build Coastguard Worker SrcRef::Reg(reg) => self.set_reg(range, reg),
179*61046927SAndroid Build Coastguard Worker _ => panic!("Not a register"),
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker }
182*61046927SAndroid Build Coastguard Worker
set_pred_dst(&mut self, range: Range<usize>, dst: Dst)183*61046927SAndroid Build Coastguard Worker fn set_pred_dst(&mut self, range: Range<usize>, dst: Dst) {
184*61046927SAndroid Build Coastguard Worker match dst {
185*61046927SAndroid Build Coastguard Worker Dst::None => {
186*61046927SAndroid Build Coastguard Worker self.set_pred_reg(range, RegRef::zero(RegFile::Pred, 1));
187*61046927SAndroid Build Coastguard Worker }
188*61046927SAndroid Build Coastguard Worker Dst::Reg(reg) => self.set_pred_reg(range, reg),
189*61046927SAndroid Build Coastguard Worker _ => panic!("Not a register"),
190*61046927SAndroid Build Coastguard Worker }
191*61046927SAndroid Build Coastguard Worker }
192*61046927SAndroid Build Coastguard Worker
set_pred_src_file( &mut self, range: Range<usize>, not_bit: usize, src: Src, file: RegFile, )193*61046927SAndroid Build Coastguard Worker fn set_pred_src_file(
194*61046927SAndroid Build Coastguard Worker &mut self,
195*61046927SAndroid Build Coastguard Worker range: Range<usize>,
196*61046927SAndroid Build Coastguard Worker not_bit: usize,
197*61046927SAndroid Build Coastguard Worker src: Src,
198*61046927SAndroid Build Coastguard Worker file: RegFile,
199*61046927SAndroid Build Coastguard Worker ) {
200*61046927SAndroid Build Coastguard Worker // The default for predicates is true
201*61046927SAndroid Build Coastguard Worker let true_reg = RegRef::new(file, 7, 1);
202*61046927SAndroid Build Coastguard Worker
203*61046927SAndroid Build Coastguard Worker let (not, reg) = match src.src_ref {
204*61046927SAndroid Build Coastguard Worker SrcRef::True => (false, true_reg),
205*61046927SAndroid Build Coastguard Worker SrcRef::False => (true, true_reg),
206*61046927SAndroid Build Coastguard Worker SrcRef::Reg(reg) => {
207*61046927SAndroid Build Coastguard Worker assert!(reg.file() == file);
208*61046927SAndroid Build Coastguard Worker (false, reg)
209*61046927SAndroid Build Coastguard Worker }
210*61046927SAndroid Build Coastguard Worker _ => panic!("Not a register"),
211*61046927SAndroid Build Coastguard Worker };
212*61046927SAndroid Build Coastguard Worker self.set_pred_reg(range, reg);
213*61046927SAndroid Build Coastguard Worker self.set_bit(not_bit, not ^ src_mod_is_bnot(src.src_mod));
214*61046927SAndroid Build Coastguard Worker }
215*61046927SAndroid Build Coastguard Worker
set_pred_src(&mut self, range: Range<usize>, not_bit: usize, src: Src)216*61046927SAndroid Build Coastguard Worker fn set_pred_src(&mut self, range: Range<usize>, not_bit: usize, src: Src) {
217*61046927SAndroid Build Coastguard Worker self.set_pred_src_file(range, not_bit, src, RegFile::Pred);
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker
set_upred_src(&mut self, range: Range<usize>, not_bit: usize, src: Src)220*61046927SAndroid Build Coastguard Worker fn set_upred_src(&mut self, range: Range<usize>, not_bit: usize, src: Src) {
221*61046927SAndroid Build Coastguard Worker self.set_pred_src_file(range, not_bit, src, RegFile::UPred);
222*61046927SAndroid Build Coastguard Worker }
223*61046927SAndroid Build Coastguard Worker
set_src_cb(&mut self, range: Range<usize>, cx_bit: usize, cb: &CBufRef)224*61046927SAndroid Build Coastguard Worker fn set_src_cb(&mut self, range: Range<usize>, cx_bit: usize, cb: &CBufRef) {
225*61046927SAndroid Build Coastguard Worker let mut v = BitMutView::new_subset(self, range);
226*61046927SAndroid Build Coastguard Worker v.set_field(6..22, cb.offset);
227*61046927SAndroid Build Coastguard Worker match cb.buf {
228*61046927SAndroid Build Coastguard Worker CBuf::Binding(idx) => {
229*61046927SAndroid Build Coastguard Worker v.set_field(22..27, idx);
230*61046927SAndroid Build Coastguard Worker self.set_bit(cx_bit, false);
231*61046927SAndroid Build Coastguard Worker }
232*61046927SAndroid Build Coastguard Worker CBuf::BindlessUGPR(reg) => {
233*61046927SAndroid Build Coastguard Worker assert!(reg.base_idx() <= 63);
234*61046927SAndroid Build Coastguard Worker assert!(reg.file() == RegFile::UGPR);
235*61046927SAndroid Build Coastguard Worker v.set_field(0..6, reg.base_idx());
236*61046927SAndroid Build Coastguard Worker self.set_bit(cx_bit, true);
237*61046927SAndroid Build Coastguard Worker }
238*61046927SAndroid Build Coastguard Worker CBuf::BindlessSSA(_) => panic!("SSA values must be lowered"),
239*61046927SAndroid Build Coastguard Worker }
240*61046927SAndroid Build Coastguard Worker }
241*61046927SAndroid Build Coastguard Worker
set_pred(&mut self, pred: &Pred)242*61046927SAndroid Build Coastguard Worker fn set_pred(&mut self, pred: &Pred) {
243*61046927SAndroid Build Coastguard Worker assert!(!pred.is_false());
244*61046927SAndroid Build Coastguard Worker self.set_pred_reg(
245*61046927SAndroid Build Coastguard Worker 12..15,
246*61046927SAndroid Build Coastguard Worker match pred.pred_ref {
247*61046927SAndroid Build Coastguard Worker PredRef::None => RegRef::zero(RegFile::Pred, 1),
248*61046927SAndroid Build Coastguard Worker PredRef::Reg(reg) => reg,
249*61046927SAndroid Build Coastguard Worker PredRef::SSA(_) => panic!("SSA values must be lowered"),
250*61046927SAndroid Build Coastguard Worker },
251*61046927SAndroid Build Coastguard Worker );
252*61046927SAndroid Build Coastguard Worker self.set_bit(15, pred.pred_inv);
253*61046927SAndroid Build Coastguard Worker }
254*61046927SAndroid Build Coastguard Worker
set_dst(&mut self, dst: Dst)255*61046927SAndroid Build Coastguard Worker fn set_dst(&mut self, dst: Dst) {
256*61046927SAndroid Build Coastguard Worker match dst {
257*61046927SAndroid Build Coastguard Worker Dst::None => self.set_reg(16..24, RegRef::zero(RegFile::GPR, 1)),
258*61046927SAndroid Build Coastguard Worker Dst::Reg(reg) => self.set_reg(16..24, reg),
259*61046927SAndroid Build Coastguard Worker _ => panic!("Not a register"),
260*61046927SAndroid Build Coastguard Worker }
261*61046927SAndroid Build Coastguard Worker }
262*61046927SAndroid Build Coastguard Worker
set_udst(&mut self, dst: Dst)263*61046927SAndroid Build Coastguard Worker fn set_udst(&mut self, dst: Dst) {
264*61046927SAndroid Build Coastguard Worker match dst {
265*61046927SAndroid Build Coastguard Worker Dst::None => self.set_ureg(16..24, RegRef::zero(RegFile::UGPR, 1)),
266*61046927SAndroid Build Coastguard Worker Dst::Reg(reg) => self.set_ureg(16..24, reg),
267*61046927SAndroid Build Coastguard Worker _ => panic!("Not a register"),
268*61046927SAndroid Build Coastguard Worker }
269*61046927SAndroid Build Coastguard Worker }
270*61046927SAndroid Build Coastguard Worker
set_bar_reg(&mut self, range: Range<usize>, reg: RegRef)271*61046927SAndroid Build Coastguard Worker fn set_bar_reg(&mut self, range: Range<usize>, reg: RegRef) {
272*61046927SAndroid Build Coastguard Worker assert!(range.len() == 4);
273*61046927SAndroid Build Coastguard Worker assert!(reg.file() == RegFile::Bar);
274*61046927SAndroid Build Coastguard Worker assert!(reg.comps() == 1);
275*61046927SAndroid Build Coastguard Worker self.set_field(range, reg.base_idx());
276*61046927SAndroid Build Coastguard Worker }
277*61046927SAndroid Build Coastguard Worker
set_bar_dst(&mut self, range: Range<usize>, dst: Dst)278*61046927SAndroid Build Coastguard Worker fn set_bar_dst(&mut self, range: Range<usize>, dst: Dst) {
279*61046927SAndroid Build Coastguard Worker self.set_bar_reg(range, *dst.as_reg().unwrap());
280*61046927SAndroid Build Coastguard Worker }
281*61046927SAndroid Build Coastguard Worker
set_bar_src(&mut self, range: Range<usize>, src: Src)282*61046927SAndroid Build Coastguard Worker fn set_bar_src(&mut self, range: Range<usize>, src: Src) {
283*61046927SAndroid Build Coastguard Worker assert!(src.src_mod.is_none());
284*61046927SAndroid Build Coastguard Worker self.set_bar_reg(range, *src.src_ref.as_reg().unwrap());
285*61046927SAndroid Build Coastguard Worker }
286*61046927SAndroid Build Coastguard Worker
set_instr_deps(&mut self, deps: &InstrDeps)287*61046927SAndroid Build Coastguard Worker fn set_instr_deps(&mut self, deps: &InstrDeps) {
288*61046927SAndroid Build Coastguard Worker self.set_field(105..109, deps.delay);
289*61046927SAndroid Build Coastguard Worker self.set_bit(109, deps.yld);
290*61046927SAndroid Build Coastguard Worker self.set_field(110..113, deps.wr_bar().unwrap_or(7));
291*61046927SAndroid Build Coastguard Worker self.set_field(113..116, deps.rd_bar().unwrap_or(7));
292*61046927SAndroid Build Coastguard Worker self.set_field(116..122, deps.wt_bar_mask);
293*61046927SAndroid Build Coastguard Worker self.set_field(122..126, deps.reuse_mask);
294*61046927SAndroid Build Coastguard Worker }
295*61046927SAndroid Build Coastguard Worker }
296*61046927SAndroid Build Coastguard Worker
297*61046927SAndroid Build Coastguard Worker //
298*61046927SAndroid Build Coastguard Worker // Helpers for encoding of ALU instructions
299*61046927SAndroid Build Coastguard Worker //
300*61046927SAndroid Build Coastguard Worker
301*61046927SAndroid Build Coastguard Worker struct ALURegRef {
302*61046927SAndroid Build Coastguard Worker pub reg: RegRef,
303*61046927SAndroid Build Coastguard Worker pub abs: bool,
304*61046927SAndroid Build Coastguard Worker pub neg: bool,
305*61046927SAndroid Build Coastguard Worker pub swizzle: SrcSwizzle,
306*61046927SAndroid Build Coastguard Worker }
307*61046927SAndroid Build Coastguard Worker
308*61046927SAndroid Build Coastguard Worker struct ALUCBufRef {
309*61046927SAndroid Build Coastguard Worker pub cb: CBufRef,
310*61046927SAndroid Build Coastguard Worker pub abs: bool,
311*61046927SAndroid Build Coastguard Worker pub neg: bool,
312*61046927SAndroid Build Coastguard Worker pub swizzle: SrcSwizzle,
313*61046927SAndroid Build Coastguard Worker }
314*61046927SAndroid Build Coastguard Worker
315*61046927SAndroid Build Coastguard Worker enum ALUSrc {
316*61046927SAndroid Build Coastguard Worker None,
317*61046927SAndroid Build Coastguard Worker Imm32(u32),
318*61046927SAndroid Build Coastguard Worker Reg(ALURegRef),
319*61046927SAndroid Build Coastguard Worker UReg(ALURegRef),
320*61046927SAndroid Build Coastguard Worker CBuf(ALUCBufRef),
321*61046927SAndroid Build Coastguard Worker }
322*61046927SAndroid Build Coastguard Worker
src_is_zero_or_gpr(src: &Src) -> bool323*61046927SAndroid Build Coastguard Worker fn src_is_zero_or_gpr(src: &Src) -> bool {
324*61046927SAndroid Build Coastguard Worker match src.src_ref {
325*61046927SAndroid Build Coastguard Worker SrcRef::Zero => true,
326*61046927SAndroid Build Coastguard Worker SrcRef::Reg(reg) => reg.file() == RegFile::GPR,
327*61046927SAndroid Build Coastguard Worker _ => false,
328*61046927SAndroid Build Coastguard Worker }
329*61046927SAndroid Build Coastguard Worker }
330*61046927SAndroid Build Coastguard Worker
src_mod_has_abs(src_mod: SrcMod) -> bool331*61046927SAndroid Build Coastguard Worker fn src_mod_has_abs(src_mod: SrcMod) -> bool {
332*61046927SAndroid Build Coastguard Worker match src_mod {
333*61046927SAndroid Build Coastguard Worker SrcMod::None | SrcMod::FNeg | SrcMod::INeg | SrcMod::BNot => false,
334*61046927SAndroid Build Coastguard Worker SrcMod::FAbs | SrcMod::FNegAbs => true,
335*61046927SAndroid Build Coastguard Worker }
336*61046927SAndroid Build Coastguard Worker }
337*61046927SAndroid Build Coastguard Worker
src_mod_has_neg(src_mod: SrcMod) -> bool338*61046927SAndroid Build Coastguard Worker fn src_mod_has_neg(src_mod: SrcMod) -> bool {
339*61046927SAndroid Build Coastguard Worker match src_mod {
340*61046927SAndroid Build Coastguard Worker SrcMod::None | SrcMod::FAbs => false,
341*61046927SAndroid Build Coastguard Worker SrcMod::FNeg | SrcMod::FNegAbs | SrcMod::INeg | SrcMod::BNot => true,
342*61046927SAndroid Build Coastguard Worker }
343*61046927SAndroid Build Coastguard Worker }
344*61046927SAndroid Build Coastguard Worker
src_mod_is_bnot(src_mod: SrcMod) -> bool345*61046927SAndroid Build Coastguard Worker fn src_mod_is_bnot(src_mod: SrcMod) -> bool {
346*61046927SAndroid Build Coastguard Worker match src_mod {
347*61046927SAndroid Build Coastguard Worker SrcMod::None => false,
348*61046927SAndroid Build Coastguard Worker SrcMod::BNot => true,
349*61046927SAndroid Build Coastguard Worker _ => panic!("Not an predicate source modifier"),
350*61046927SAndroid Build Coastguard Worker }
351*61046927SAndroid Build Coastguard Worker }
352*61046927SAndroid Build Coastguard Worker
dst_is_bar(dst: Dst) -> bool353*61046927SAndroid Build Coastguard Worker fn dst_is_bar(dst: Dst) -> bool {
354*61046927SAndroid Build Coastguard Worker match dst {
355*61046927SAndroid Build Coastguard Worker Dst::None => false,
356*61046927SAndroid Build Coastguard Worker Dst::SSA(ssa) => ssa.file().unwrap() == RegFile::Bar,
357*61046927SAndroid Build Coastguard Worker Dst::Reg(reg) => reg.file() == RegFile::Bar,
358*61046927SAndroid Build Coastguard Worker }
359*61046927SAndroid Build Coastguard Worker }
360*61046927SAndroid Build Coastguard Worker
361*61046927SAndroid Build Coastguard Worker impl ALUSrc {
from_src(src: Option<&Src>, op_is_uniform: bool) -> ALUSrc362*61046927SAndroid Build Coastguard Worker fn from_src(src: Option<&Src>, op_is_uniform: bool) -> ALUSrc {
363*61046927SAndroid Build Coastguard Worker let Some(src) = src else {
364*61046927SAndroid Build Coastguard Worker return ALUSrc::None;
365*61046927SAndroid Build Coastguard Worker };
366*61046927SAndroid Build Coastguard Worker
367*61046927SAndroid Build Coastguard Worker match src.src_ref {
368*61046927SAndroid Build Coastguard Worker SrcRef::Zero | SrcRef::Reg(_) => {
369*61046927SAndroid Build Coastguard Worker let reg = match src.src_ref {
370*61046927SAndroid Build Coastguard Worker SrcRef::Zero => {
371*61046927SAndroid Build Coastguard Worker let file = if op_is_uniform {
372*61046927SAndroid Build Coastguard Worker RegFile::UGPR
373*61046927SAndroid Build Coastguard Worker } else {
374*61046927SAndroid Build Coastguard Worker RegFile::GPR
375*61046927SAndroid Build Coastguard Worker };
376*61046927SAndroid Build Coastguard Worker RegRef::zero(file, 1)
377*61046927SAndroid Build Coastguard Worker }
378*61046927SAndroid Build Coastguard Worker SrcRef::Reg(reg) => reg,
379*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid source ref"),
380*61046927SAndroid Build Coastguard Worker };
381*61046927SAndroid Build Coastguard Worker assert!(reg.comps() <= 2);
382*61046927SAndroid Build Coastguard Worker let alu_ref = ALURegRef {
383*61046927SAndroid Build Coastguard Worker reg: reg,
384*61046927SAndroid Build Coastguard Worker abs: src_mod_has_abs(src.src_mod),
385*61046927SAndroid Build Coastguard Worker neg: src_mod_has_neg(src.src_mod),
386*61046927SAndroid Build Coastguard Worker swizzle: src.src_swizzle,
387*61046927SAndroid Build Coastguard Worker };
388*61046927SAndroid Build Coastguard Worker if op_is_uniform {
389*61046927SAndroid Build Coastguard Worker assert!(reg.file() == RegFile::UGPR);
390*61046927SAndroid Build Coastguard Worker ALUSrc::Reg(alu_ref)
391*61046927SAndroid Build Coastguard Worker } else {
392*61046927SAndroid Build Coastguard Worker match reg.file() {
393*61046927SAndroid Build Coastguard Worker RegFile::GPR => ALUSrc::Reg(alu_ref),
394*61046927SAndroid Build Coastguard Worker RegFile::UGPR => ALUSrc::UReg(alu_ref),
395*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid ALU register file"),
396*61046927SAndroid Build Coastguard Worker }
397*61046927SAndroid Build Coastguard Worker }
398*61046927SAndroid Build Coastguard Worker }
399*61046927SAndroid Build Coastguard Worker SrcRef::Imm32(i) => {
400*61046927SAndroid Build Coastguard Worker assert!(src.src_mod.is_none());
401*61046927SAndroid Build Coastguard Worker assert!(src.src_swizzle.is_none());
402*61046927SAndroid Build Coastguard Worker ALUSrc::Imm32(i)
403*61046927SAndroid Build Coastguard Worker }
404*61046927SAndroid Build Coastguard Worker SrcRef::CBuf(cb) => {
405*61046927SAndroid Build Coastguard Worker let alu_ref = ALUCBufRef {
406*61046927SAndroid Build Coastguard Worker cb: cb,
407*61046927SAndroid Build Coastguard Worker abs: src_mod_has_abs(src.src_mod),
408*61046927SAndroid Build Coastguard Worker neg: src_mod_has_neg(src.src_mod),
409*61046927SAndroid Build Coastguard Worker swizzle: src.src_swizzle,
410*61046927SAndroid Build Coastguard Worker };
411*61046927SAndroid Build Coastguard Worker ALUSrc::CBuf(alu_ref)
412*61046927SAndroid Build Coastguard Worker }
413*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid ALU source"),
414*61046927SAndroid Build Coastguard Worker }
415*61046927SAndroid Build Coastguard Worker }
416*61046927SAndroid Build Coastguard Worker
has_src_mod(&self) -> bool417*61046927SAndroid Build Coastguard Worker pub fn has_src_mod(&self) -> bool {
418*61046927SAndroid Build Coastguard Worker match self {
419*61046927SAndroid Build Coastguard Worker ALUSrc::Reg(reg) | ALUSrc::UReg(reg) => reg.abs || reg.neg,
420*61046927SAndroid Build Coastguard Worker ALUSrc::CBuf(cb) => cb.abs || cb.neg,
421*61046927SAndroid Build Coastguard Worker _ => false,
422*61046927SAndroid Build Coastguard Worker }
423*61046927SAndroid Build Coastguard Worker }
424*61046927SAndroid Build Coastguard Worker }
425*61046927SAndroid Build Coastguard Worker
426*61046927SAndroid Build Coastguard Worker impl SM70Encoder<'_> {
set_swizzle(&mut self, range: Range<usize>, swizzle: SrcSwizzle)427*61046927SAndroid Build Coastguard Worker fn set_swizzle(&mut self, range: Range<usize>, swizzle: SrcSwizzle) {
428*61046927SAndroid Build Coastguard Worker assert!(range.len() == 2);
429*61046927SAndroid Build Coastguard Worker
430*61046927SAndroid Build Coastguard Worker self.set_field(
431*61046927SAndroid Build Coastguard Worker range,
432*61046927SAndroid Build Coastguard Worker match swizzle {
433*61046927SAndroid Build Coastguard Worker SrcSwizzle::None => 0x00_u8,
434*61046927SAndroid Build Coastguard Worker SrcSwizzle::Xx => 0x02_u8,
435*61046927SAndroid Build Coastguard Worker SrcSwizzle::Yy => 0x03_u8,
436*61046927SAndroid Build Coastguard Worker },
437*61046927SAndroid Build Coastguard Worker );
438*61046927SAndroid Build Coastguard Worker }
439*61046927SAndroid Build Coastguard Worker
set_alu_reg( &mut self, range: Range<usize>, abs_bit: usize, neg_bit: usize, swizzle_range: Range<usize>, file: RegFile, is_fp16_alu: bool, has_mod: bool, reg: &ALURegRef, )440*61046927SAndroid Build Coastguard Worker fn set_alu_reg(
441*61046927SAndroid Build Coastguard Worker &mut self,
442*61046927SAndroid Build Coastguard Worker range: Range<usize>,
443*61046927SAndroid Build Coastguard Worker abs_bit: usize,
444*61046927SAndroid Build Coastguard Worker neg_bit: usize,
445*61046927SAndroid Build Coastguard Worker swizzle_range: Range<usize>,
446*61046927SAndroid Build Coastguard Worker file: RegFile,
447*61046927SAndroid Build Coastguard Worker is_fp16_alu: bool,
448*61046927SAndroid Build Coastguard Worker has_mod: bool,
449*61046927SAndroid Build Coastguard Worker reg: &ALURegRef,
450*61046927SAndroid Build Coastguard Worker ) {
451*61046927SAndroid Build Coastguard Worker match file {
452*61046927SAndroid Build Coastguard Worker RegFile::GPR => self.set_reg(range, reg.reg),
453*61046927SAndroid Build Coastguard Worker RegFile::UGPR => self.set_ureg(range, reg.reg),
454*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid ALU src register file"),
455*61046927SAndroid Build Coastguard Worker }
456*61046927SAndroid Build Coastguard Worker
457*61046927SAndroid Build Coastguard Worker if has_mod {
458*61046927SAndroid Build Coastguard Worker self.set_bit(abs_bit, reg.abs);
459*61046927SAndroid Build Coastguard Worker self.set_bit(neg_bit, reg.neg);
460*61046927SAndroid Build Coastguard Worker } else {
461*61046927SAndroid Build Coastguard Worker assert!(!reg.abs && !reg.neg);
462*61046927SAndroid Build Coastguard Worker }
463*61046927SAndroid Build Coastguard Worker
464*61046927SAndroid Build Coastguard Worker if is_fp16_alu {
465*61046927SAndroid Build Coastguard Worker self.set_swizzle(swizzle_range, reg.swizzle);
466*61046927SAndroid Build Coastguard Worker } else {
467*61046927SAndroid Build Coastguard Worker assert!(reg.swizzle == SrcSwizzle::None);
468*61046927SAndroid Build Coastguard Worker }
469*61046927SAndroid Build Coastguard Worker }
470*61046927SAndroid Build Coastguard Worker
encode_alu_src0( &mut self, src: &ALUSrc, file: RegFile, is_fp16_alu: bool, )471*61046927SAndroid Build Coastguard Worker fn encode_alu_src0(
472*61046927SAndroid Build Coastguard Worker &mut self,
473*61046927SAndroid Build Coastguard Worker src: &ALUSrc,
474*61046927SAndroid Build Coastguard Worker file: RegFile,
475*61046927SAndroid Build Coastguard Worker is_fp16_alu: bool,
476*61046927SAndroid Build Coastguard Worker ) {
477*61046927SAndroid Build Coastguard Worker let reg = match src {
478*61046927SAndroid Build Coastguard Worker ALUSrc::None => return,
479*61046927SAndroid Build Coastguard Worker ALUSrc::Reg(reg) => reg,
480*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid ALU src"),
481*61046927SAndroid Build Coastguard Worker };
482*61046927SAndroid Build Coastguard Worker self.set_alu_reg(24..32, 73, 72, 74..76, file, is_fp16_alu, true, reg);
483*61046927SAndroid Build Coastguard Worker }
484*61046927SAndroid Build Coastguard Worker
encode_alu_src2( &mut self, src: &ALUSrc, file: RegFile, is_fp16_alu: bool, bit74_75_are_mod: bool, )485*61046927SAndroid Build Coastguard Worker fn encode_alu_src2(
486*61046927SAndroid Build Coastguard Worker &mut self,
487*61046927SAndroid Build Coastguard Worker src: &ALUSrc,
488*61046927SAndroid Build Coastguard Worker file: RegFile,
489*61046927SAndroid Build Coastguard Worker is_fp16_alu: bool,
490*61046927SAndroid Build Coastguard Worker bit74_75_are_mod: bool,
491*61046927SAndroid Build Coastguard Worker ) {
492*61046927SAndroid Build Coastguard Worker let reg = match src {
493*61046927SAndroid Build Coastguard Worker ALUSrc::None => return,
494*61046927SAndroid Build Coastguard Worker ALUSrc::Reg(reg) => reg,
495*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid ALU src"),
496*61046927SAndroid Build Coastguard Worker };
497*61046927SAndroid Build Coastguard Worker self.set_alu_reg(
498*61046927SAndroid Build Coastguard Worker 64..72,
499*61046927SAndroid Build Coastguard Worker 74,
500*61046927SAndroid Build Coastguard Worker 75,
501*61046927SAndroid Build Coastguard Worker 81..83,
502*61046927SAndroid Build Coastguard Worker file,
503*61046927SAndroid Build Coastguard Worker is_fp16_alu,
504*61046927SAndroid Build Coastguard Worker bit74_75_are_mod,
505*61046927SAndroid Build Coastguard Worker reg,
506*61046927SAndroid Build Coastguard Worker );
507*61046927SAndroid Build Coastguard Worker }
508*61046927SAndroid Build Coastguard Worker
encode_alu_reg(&mut self, reg: &ALURegRef, is_fp16_alu: bool)509*61046927SAndroid Build Coastguard Worker fn encode_alu_reg(&mut self, reg: &ALURegRef, is_fp16_alu: bool) {
510*61046927SAndroid Build Coastguard Worker self.set_alu_reg(
511*61046927SAndroid Build Coastguard Worker 32..40,
512*61046927SAndroid Build Coastguard Worker 62,
513*61046927SAndroid Build Coastguard Worker 63,
514*61046927SAndroid Build Coastguard Worker 60..62,
515*61046927SAndroid Build Coastguard Worker RegFile::GPR,
516*61046927SAndroid Build Coastguard Worker is_fp16_alu,
517*61046927SAndroid Build Coastguard Worker true,
518*61046927SAndroid Build Coastguard Worker reg,
519*61046927SAndroid Build Coastguard Worker );
520*61046927SAndroid Build Coastguard Worker }
521*61046927SAndroid Build Coastguard Worker
encode_alu_ureg(&mut self, reg: &ALURegRef, is_fp16_alu: bool)522*61046927SAndroid Build Coastguard Worker fn encode_alu_ureg(&mut self, reg: &ALURegRef, is_fp16_alu: bool) {
523*61046927SAndroid Build Coastguard Worker self.set_ureg(32..40, reg.reg);
524*61046927SAndroid Build Coastguard Worker self.set_bit(62, reg.abs);
525*61046927SAndroid Build Coastguard Worker self.set_bit(63, reg.neg);
526*61046927SAndroid Build Coastguard Worker
527*61046927SAndroid Build Coastguard Worker if is_fp16_alu {
528*61046927SAndroid Build Coastguard Worker self.set_swizzle(60..62, reg.swizzle);
529*61046927SAndroid Build Coastguard Worker } else {
530*61046927SAndroid Build Coastguard Worker assert!(reg.swizzle == SrcSwizzle::None);
531*61046927SAndroid Build Coastguard Worker }
532*61046927SAndroid Build Coastguard Worker
533*61046927SAndroid Build Coastguard Worker self.set_bit(91, true);
534*61046927SAndroid Build Coastguard Worker }
535*61046927SAndroid Build Coastguard Worker
encode_alu_imm(&mut self, imm: &u32)536*61046927SAndroid Build Coastguard Worker fn encode_alu_imm(&mut self, imm: &u32) {
537*61046927SAndroid Build Coastguard Worker self.set_field(32..64, *imm);
538*61046927SAndroid Build Coastguard Worker }
539*61046927SAndroid Build Coastguard Worker
encode_alu_cb(&mut self, cb: &ALUCBufRef, is_fp16_alu: bool)540*61046927SAndroid Build Coastguard Worker fn encode_alu_cb(&mut self, cb: &ALUCBufRef, is_fp16_alu: bool) {
541*61046927SAndroid Build Coastguard Worker self.set_src_cb(32..59, 91, &cb.cb);
542*61046927SAndroid Build Coastguard Worker self.set_bit(62, cb.abs);
543*61046927SAndroid Build Coastguard Worker self.set_bit(63, cb.neg);
544*61046927SAndroid Build Coastguard Worker
545*61046927SAndroid Build Coastguard Worker if is_fp16_alu {
546*61046927SAndroid Build Coastguard Worker self.set_swizzle(60..62, cb.swizzle);
547*61046927SAndroid Build Coastguard Worker } else {
548*61046927SAndroid Build Coastguard Worker assert!(cb.swizzle == SrcSwizzle::None);
549*61046927SAndroid Build Coastguard Worker }
550*61046927SAndroid Build Coastguard Worker }
551*61046927SAndroid Build Coastguard Worker
encode_alu_base( &mut self, opcode: u16, dst: Option<&Dst>, src0: Option<&Src>, src1: Option<&Src>, src2: Option<&Src>, is_fp16_alu: bool, )552*61046927SAndroid Build Coastguard Worker fn encode_alu_base(
553*61046927SAndroid Build Coastguard Worker &mut self,
554*61046927SAndroid Build Coastguard Worker opcode: u16,
555*61046927SAndroid Build Coastguard Worker dst: Option<&Dst>,
556*61046927SAndroid Build Coastguard Worker src0: Option<&Src>,
557*61046927SAndroid Build Coastguard Worker src1: Option<&Src>,
558*61046927SAndroid Build Coastguard Worker src2: Option<&Src>,
559*61046927SAndroid Build Coastguard Worker is_fp16_alu: bool,
560*61046927SAndroid Build Coastguard Worker ) {
561*61046927SAndroid Build Coastguard Worker if let Some(dst) = dst {
562*61046927SAndroid Build Coastguard Worker self.set_dst(*dst);
563*61046927SAndroid Build Coastguard Worker }
564*61046927SAndroid Build Coastguard Worker
565*61046927SAndroid Build Coastguard Worker let src0 = ALUSrc::from_src(src0, false);
566*61046927SAndroid Build Coastguard Worker let src1 = ALUSrc::from_src(src1, false);
567*61046927SAndroid Build Coastguard Worker let src2 = ALUSrc::from_src(src2, false);
568*61046927SAndroid Build Coastguard Worker
569*61046927SAndroid Build Coastguard Worker // Bits 74..76 are used both for the swizzle on src0 and for the source
570*61046927SAndroid Build Coastguard Worker // modifier for the register source of src1 and src2. When both are
571*61046927SAndroid Build Coastguard Worker // registers, it's used for src2. The hardware elects to always support
572*61046927SAndroid Build Coastguard Worker // a swizzle and not support source modifiers in that case.
573*61046927SAndroid Build Coastguard Worker let bit74_75_are_mod = !is_fp16_alu
574*61046927SAndroid Build Coastguard Worker || matches!(src1, ALUSrc::None)
575*61046927SAndroid Build Coastguard Worker || matches!(src2, ALUSrc::None);
576*61046927SAndroid Build Coastguard Worker debug_assert!(bit74_75_are_mod || !src0.has_src_mod());
577*61046927SAndroid Build Coastguard Worker
578*61046927SAndroid Build Coastguard Worker self.encode_alu_src0(&src0, RegFile::GPR, is_fp16_alu);
579*61046927SAndroid Build Coastguard Worker
580*61046927SAndroid Build Coastguard Worker let form = match &src2 {
581*61046927SAndroid Build Coastguard Worker ALUSrc::None | ALUSrc::Reg(_) => {
582*61046927SAndroid Build Coastguard Worker self.encode_alu_src2(
583*61046927SAndroid Build Coastguard Worker &src2,
584*61046927SAndroid Build Coastguard Worker RegFile::GPR,
585*61046927SAndroid Build Coastguard Worker is_fp16_alu,
586*61046927SAndroid Build Coastguard Worker bit74_75_are_mod,
587*61046927SAndroid Build Coastguard Worker );
588*61046927SAndroid Build Coastguard Worker match &src1 {
589*61046927SAndroid Build Coastguard Worker ALUSrc::None => 1_u8, // form
590*61046927SAndroid Build Coastguard Worker ALUSrc::Reg(reg1) => {
591*61046927SAndroid Build Coastguard Worker self.encode_alu_reg(reg1, is_fp16_alu);
592*61046927SAndroid Build Coastguard Worker 1_u8 // form
593*61046927SAndroid Build Coastguard Worker }
594*61046927SAndroid Build Coastguard Worker ALUSrc::UReg(reg1) => {
595*61046927SAndroid Build Coastguard Worker self.encode_alu_ureg(reg1, is_fp16_alu);
596*61046927SAndroid Build Coastguard Worker 6_u8 // form
597*61046927SAndroid Build Coastguard Worker }
598*61046927SAndroid Build Coastguard Worker ALUSrc::Imm32(imm1) => {
599*61046927SAndroid Build Coastguard Worker self.encode_alu_imm(imm1);
600*61046927SAndroid Build Coastguard Worker 4_u8 // form
601*61046927SAndroid Build Coastguard Worker }
602*61046927SAndroid Build Coastguard Worker ALUSrc::CBuf(cb1) => {
603*61046927SAndroid Build Coastguard Worker self.encode_alu_cb(cb1, is_fp16_alu);
604*61046927SAndroid Build Coastguard Worker 5_u8 // form
605*61046927SAndroid Build Coastguard Worker }
606*61046927SAndroid Build Coastguard Worker }
607*61046927SAndroid Build Coastguard Worker }
608*61046927SAndroid Build Coastguard Worker ALUSrc::UReg(reg2) => {
609*61046927SAndroid Build Coastguard Worker self.encode_alu_ureg(reg2, is_fp16_alu);
610*61046927SAndroid Build Coastguard Worker self.encode_alu_src2(
611*61046927SAndroid Build Coastguard Worker &src1,
612*61046927SAndroid Build Coastguard Worker RegFile::GPR,
613*61046927SAndroid Build Coastguard Worker is_fp16_alu,
614*61046927SAndroid Build Coastguard Worker bit74_75_are_mod,
615*61046927SAndroid Build Coastguard Worker );
616*61046927SAndroid Build Coastguard Worker 7_u8 // form
617*61046927SAndroid Build Coastguard Worker }
618*61046927SAndroid Build Coastguard Worker ALUSrc::Imm32(imm2) => {
619*61046927SAndroid Build Coastguard Worker self.encode_alu_imm(imm2);
620*61046927SAndroid Build Coastguard Worker self.encode_alu_src2(
621*61046927SAndroid Build Coastguard Worker &src1,
622*61046927SAndroid Build Coastguard Worker RegFile::GPR,
623*61046927SAndroid Build Coastguard Worker is_fp16_alu,
624*61046927SAndroid Build Coastguard Worker bit74_75_are_mod,
625*61046927SAndroid Build Coastguard Worker );
626*61046927SAndroid Build Coastguard Worker 2_u8 // form
627*61046927SAndroid Build Coastguard Worker }
628*61046927SAndroid Build Coastguard Worker ALUSrc::CBuf(cb2) => {
629*61046927SAndroid Build Coastguard Worker // TODO set_src_cx
630*61046927SAndroid Build Coastguard Worker self.encode_alu_cb(cb2, is_fp16_alu);
631*61046927SAndroid Build Coastguard Worker self.encode_alu_src2(
632*61046927SAndroid Build Coastguard Worker &src1,
633*61046927SAndroid Build Coastguard Worker RegFile::GPR,
634*61046927SAndroid Build Coastguard Worker is_fp16_alu,
635*61046927SAndroid Build Coastguard Worker bit74_75_are_mod,
636*61046927SAndroid Build Coastguard Worker );
637*61046927SAndroid Build Coastguard Worker 3_u8 // form
638*61046927SAndroid Build Coastguard Worker }
639*61046927SAndroid Build Coastguard Worker };
640*61046927SAndroid Build Coastguard Worker
641*61046927SAndroid Build Coastguard Worker self.set_field(0..9, opcode);
642*61046927SAndroid Build Coastguard Worker self.set_field(9..12, form);
643*61046927SAndroid Build Coastguard Worker }
644*61046927SAndroid Build Coastguard Worker
encode_alu( &mut self, opcode: u16, dst: Option<&Dst>, src0: Option<&Src>, src1: Option<&Src>, src2: Option<&Src>, )645*61046927SAndroid Build Coastguard Worker fn encode_alu(
646*61046927SAndroid Build Coastguard Worker &mut self,
647*61046927SAndroid Build Coastguard Worker opcode: u16,
648*61046927SAndroid Build Coastguard Worker dst: Option<&Dst>,
649*61046927SAndroid Build Coastguard Worker src0: Option<&Src>,
650*61046927SAndroid Build Coastguard Worker src1: Option<&Src>,
651*61046927SAndroid Build Coastguard Worker src2: Option<&Src>,
652*61046927SAndroid Build Coastguard Worker ) {
653*61046927SAndroid Build Coastguard Worker self.encode_alu_base(opcode, dst, src0, src1, src2, false);
654*61046927SAndroid Build Coastguard Worker }
655*61046927SAndroid Build Coastguard Worker
encode_fp16_alu( &mut self, opcode: u16, dst: Option<&Dst>, src0: Option<&Src>, src1: Option<&Src>, src2: Option<&Src>, )656*61046927SAndroid Build Coastguard Worker fn encode_fp16_alu(
657*61046927SAndroid Build Coastguard Worker &mut self,
658*61046927SAndroid Build Coastguard Worker opcode: u16,
659*61046927SAndroid Build Coastguard Worker dst: Option<&Dst>,
660*61046927SAndroid Build Coastguard Worker src0: Option<&Src>,
661*61046927SAndroid Build Coastguard Worker src1: Option<&Src>,
662*61046927SAndroid Build Coastguard Worker src2: Option<&Src>,
663*61046927SAndroid Build Coastguard Worker ) {
664*61046927SAndroid Build Coastguard Worker self.encode_alu_base(opcode, dst, src0, src1, src2, true);
665*61046927SAndroid Build Coastguard Worker }
666*61046927SAndroid Build Coastguard Worker
encode_ualu( &mut self, opcode: u16, dst: Option<&Dst>, src0: Option<&Src>, src1: Option<&Src>, src2: Option<&Src>, )667*61046927SAndroid Build Coastguard Worker fn encode_ualu(
668*61046927SAndroid Build Coastguard Worker &mut self,
669*61046927SAndroid Build Coastguard Worker opcode: u16,
670*61046927SAndroid Build Coastguard Worker dst: Option<&Dst>,
671*61046927SAndroid Build Coastguard Worker src0: Option<&Src>,
672*61046927SAndroid Build Coastguard Worker src1: Option<&Src>,
673*61046927SAndroid Build Coastguard Worker src2: Option<&Src>,
674*61046927SAndroid Build Coastguard Worker ) {
675*61046927SAndroid Build Coastguard Worker if let Some(dst) = dst {
676*61046927SAndroid Build Coastguard Worker self.set_udst(*dst);
677*61046927SAndroid Build Coastguard Worker }
678*61046927SAndroid Build Coastguard Worker
679*61046927SAndroid Build Coastguard Worker let src0 = ALUSrc::from_src(src0, true);
680*61046927SAndroid Build Coastguard Worker let src1 = ALUSrc::from_src(src1, true);
681*61046927SAndroid Build Coastguard Worker let src2 = ALUSrc::from_src(src2, true);
682*61046927SAndroid Build Coastguard Worker
683*61046927SAndroid Build Coastguard Worker // All uniform ALU requires bit 91 set
684*61046927SAndroid Build Coastguard Worker self.set_bit(91, true);
685*61046927SAndroid Build Coastguard Worker
686*61046927SAndroid Build Coastguard Worker self.encode_alu_src0(&src0, RegFile::UGPR, false);
687*61046927SAndroid Build Coastguard Worker let form = match &src2 {
688*61046927SAndroid Build Coastguard Worker ALUSrc::None | ALUSrc::Reg(_) => {
689*61046927SAndroid Build Coastguard Worker self.encode_alu_src2(&src2, RegFile::UGPR, false, true);
690*61046927SAndroid Build Coastguard Worker match &src1 {
691*61046927SAndroid Build Coastguard Worker ALUSrc::None => 1_u8, // form
692*61046927SAndroid Build Coastguard Worker ALUSrc::Reg(reg1) => {
693*61046927SAndroid Build Coastguard Worker self.encode_alu_ureg(reg1, false);
694*61046927SAndroid Build Coastguard Worker 1_u8 // form
695*61046927SAndroid Build Coastguard Worker }
696*61046927SAndroid Build Coastguard Worker ALUSrc::UReg(_) => panic!("UALU never has UReg"),
697*61046927SAndroid Build Coastguard Worker ALUSrc::Imm32(imm1) => {
698*61046927SAndroid Build Coastguard Worker self.encode_alu_imm(imm1);
699*61046927SAndroid Build Coastguard Worker 4_u8 // form
700*61046927SAndroid Build Coastguard Worker }
701*61046927SAndroid Build Coastguard Worker ALUSrc::CBuf(_) => panic!("UALU does not support cbufs"),
702*61046927SAndroid Build Coastguard Worker }
703*61046927SAndroid Build Coastguard Worker }
704*61046927SAndroid Build Coastguard Worker ALUSrc::UReg(_) => panic!("UALU never has UReg"),
705*61046927SAndroid Build Coastguard Worker ALUSrc::Imm32(imm2) => {
706*61046927SAndroid Build Coastguard Worker self.encode_alu_imm(imm2);
707*61046927SAndroid Build Coastguard Worker self.encode_alu_src2(&src1, RegFile::UGPR, false, true);
708*61046927SAndroid Build Coastguard Worker 2_u8 // form
709*61046927SAndroid Build Coastguard Worker }
710*61046927SAndroid Build Coastguard Worker ALUSrc::CBuf(_) => panic!("UALU does not support cbufs"),
711*61046927SAndroid Build Coastguard Worker };
712*61046927SAndroid Build Coastguard Worker
713*61046927SAndroid Build Coastguard Worker self.set_field(0..9, opcode);
714*61046927SAndroid Build Coastguard Worker self.set_field(9..12, form);
715*61046927SAndroid Build Coastguard Worker }
716*61046927SAndroid Build Coastguard Worker
set_rnd_mode(&mut self, range: Range<usize>, rnd_mode: FRndMode)717*61046927SAndroid Build Coastguard Worker fn set_rnd_mode(&mut self, range: Range<usize>, rnd_mode: FRndMode) {
718*61046927SAndroid Build Coastguard Worker assert!(range.len() == 2);
719*61046927SAndroid Build Coastguard Worker self.set_field(
720*61046927SAndroid Build Coastguard Worker range,
721*61046927SAndroid Build Coastguard Worker match rnd_mode {
722*61046927SAndroid Build Coastguard Worker FRndMode::NearestEven => 0_u8,
723*61046927SAndroid Build Coastguard Worker FRndMode::NegInf => 1_u8,
724*61046927SAndroid Build Coastguard Worker FRndMode::PosInf => 2_u8,
725*61046927SAndroid Build Coastguard Worker FRndMode::Zero => 3_u8,
726*61046927SAndroid Build Coastguard Worker },
727*61046927SAndroid Build Coastguard Worker );
728*61046927SAndroid Build Coastguard Worker }
729*61046927SAndroid Build Coastguard Worker }
730*61046927SAndroid Build Coastguard Worker
731*61046927SAndroid Build Coastguard Worker //
732*61046927SAndroid Build Coastguard Worker // Legalization helpers
733*61046927SAndroid Build Coastguard Worker //
734*61046927SAndroid Build Coastguard Worker
op_gpr(op: &impl DstsAsSlice) -> RegFile735*61046927SAndroid Build Coastguard Worker fn op_gpr(op: &impl DstsAsSlice) -> RegFile {
736*61046927SAndroid Build Coastguard Worker if op.is_uniform() {
737*61046927SAndroid Build Coastguard Worker RegFile::UGPR
738*61046927SAndroid Build Coastguard Worker } else {
739*61046927SAndroid Build Coastguard Worker RegFile::GPR
740*61046927SAndroid Build Coastguard Worker }
741*61046927SAndroid Build Coastguard Worker }
742*61046927SAndroid Build Coastguard Worker
743*61046927SAndroid Build Coastguard Worker /// Helper to legalize extended or external instructions
744*61046927SAndroid Build Coastguard Worker ///
745*61046927SAndroid Build Coastguard Worker /// These are instructions which reach out external units such as load/store
746*61046927SAndroid Build Coastguard Worker /// and texture ops. They typically can't take anything but GPRs and are the
747*61046927SAndroid Build Coastguard Worker /// only types of instructions that support vectors. They also can never be
748*61046927SAndroid Build Coastguard Worker /// uniform so we always evict uniform sources.
749*61046927SAndroid Build Coastguard Worker ///
legalize_ext_instr(op: &mut impl SrcsAsSlice, b: &mut LegalizeBuilder)750*61046927SAndroid Build Coastguard Worker fn legalize_ext_instr(op: &mut impl SrcsAsSlice, b: &mut LegalizeBuilder) {
751*61046927SAndroid Build Coastguard Worker let src_types = op.src_types();
752*61046927SAndroid Build Coastguard Worker for (i, src) in op.srcs_as_mut_slice().iter_mut().enumerate() {
753*61046927SAndroid Build Coastguard Worker match src_types[i] {
754*61046927SAndroid Build Coastguard Worker SrcType::SSA | SrcType::GPR => match &mut src.src_ref {
755*61046927SAndroid Build Coastguard Worker SrcRef::Zero | SrcRef::True | SrcRef::False => {
756*61046927SAndroid Build Coastguard Worker assert!(src_types[i] != SrcType::SSA);
757*61046927SAndroid Build Coastguard Worker }
758*61046927SAndroid Build Coastguard Worker SrcRef::SSA(ssa) => {
759*61046927SAndroid Build Coastguard Worker b.copy_ssa_ref_if_uniform(ssa);
760*61046927SAndroid Build Coastguard Worker }
761*61046927SAndroid Build Coastguard Worker _ => panic!("Unsupported source reference"),
762*61046927SAndroid Build Coastguard Worker },
763*61046927SAndroid Build Coastguard Worker SrcType::ALU
764*61046927SAndroid Build Coastguard Worker | SrcType::F16
765*61046927SAndroid Build Coastguard Worker | SrcType::F16v2
766*61046927SAndroid Build Coastguard Worker | SrcType::F32
767*61046927SAndroid Build Coastguard Worker | SrcType::F64
768*61046927SAndroid Build Coastguard Worker | SrcType::I32
769*61046927SAndroid Build Coastguard Worker | SrcType::B32 => {
770*61046927SAndroid Build Coastguard Worker panic!("ALU srcs must be legalized explicitly");
771*61046927SAndroid Build Coastguard Worker }
772*61046927SAndroid Build Coastguard Worker SrcType::Pred => {
773*61046927SAndroid Build Coastguard Worker panic!("Predicates must be legalized explicitly");
774*61046927SAndroid Build Coastguard Worker }
775*61046927SAndroid Build Coastguard Worker SrcType::Carry => {
776*61046927SAndroid Build Coastguard Worker panic!("Carry is invalid on Volta+");
777*61046927SAndroid Build Coastguard Worker }
778*61046927SAndroid Build Coastguard Worker SrcType::Bar => (),
779*61046927SAndroid Build Coastguard Worker }
780*61046927SAndroid Build Coastguard Worker }
781*61046927SAndroid Build Coastguard Worker }
782*61046927SAndroid Build Coastguard Worker
783*61046927SAndroid Build Coastguard Worker //
784*61046927SAndroid Build Coastguard Worker // Implementations of SM70Op for each op we support on Volta+
785*61046927SAndroid Build Coastguard Worker //
786*61046927SAndroid Build Coastguard Worker
787*61046927SAndroid Build Coastguard Worker impl SM70Op for OpFAdd {
legalize(&mut self, b: &mut LegalizeBuilder)788*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
789*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
790*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
791*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
792*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F32);
793*61046927SAndroid Build Coastguard Worker }
794*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)795*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
796*61046927SAndroid Build Coastguard Worker if src_is_zero_or_gpr(&self.srcs[1]) {
797*61046927SAndroid Build Coastguard Worker e.encode_alu(
798*61046927SAndroid Build Coastguard Worker 0x021,
799*61046927SAndroid Build Coastguard Worker Some(&self.dst),
800*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
801*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
802*61046927SAndroid Build Coastguard Worker None,
803*61046927SAndroid Build Coastguard Worker )
804*61046927SAndroid Build Coastguard Worker } else {
805*61046927SAndroid Build Coastguard Worker e.encode_alu(
806*61046927SAndroid Build Coastguard Worker 0x021,
807*61046927SAndroid Build Coastguard Worker Some(&self.dst),
808*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
809*61046927SAndroid Build Coastguard Worker Some(&Src::new_zero()),
810*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
811*61046927SAndroid Build Coastguard Worker )
812*61046927SAndroid Build Coastguard Worker };
813*61046927SAndroid Build Coastguard Worker e.set_bit(77, self.saturate);
814*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
815*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
816*61046927SAndroid Build Coastguard Worker }
817*61046927SAndroid Build Coastguard Worker }
818*61046927SAndroid Build Coastguard Worker
819*61046927SAndroid Build Coastguard Worker impl SM70Op for OpFFma {
legalize(&mut self, b: &mut LegalizeBuilder)820*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
821*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
822*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
823*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
824*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F32);
825*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_both_not_reg(src1, src2, gpr, SrcType::F32);
826*61046927SAndroid Build Coastguard Worker }
827*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)828*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
829*61046927SAndroid Build Coastguard Worker e.encode_alu(
830*61046927SAndroid Build Coastguard Worker 0x023,
831*61046927SAndroid Build Coastguard Worker Some(&self.dst),
832*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
833*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
834*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
835*61046927SAndroid Build Coastguard Worker );
836*61046927SAndroid Build Coastguard Worker e.set_bit(76, self.dnz);
837*61046927SAndroid Build Coastguard Worker e.set_bit(77, self.saturate);
838*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
839*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
840*61046927SAndroid Build Coastguard Worker }
841*61046927SAndroid Build Coastguard Worker }
842*61046927SAndroid Build Coastguard Worker
843*61046927SAndroid Build Coastguard Worker impl SM70Op for OpFMnMx {
legalize(&mut self, b: &mut LegalizeBuilder)844*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
845*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
846*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
847*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
848*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F32);
849*61046927SAndroid Build Coastguard Worker }
850*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)851*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
852*61046927SAndroid Build Coastguard Worker e.encode_alu(
853*61046927SAndroid Build Coastguard Worker 0x009,
854*61046927SAndroid Build Coastguard Worker Some(&self.dst),
855*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
856*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
857*61046927SAndroid Build Coastguard Worker Some(&Src::new_zero()),
858*61046927SAndroid Build Coastguard Worker );
859*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.min);
860*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
861*61046927SAndroid Build Coastguard Worker }
862*61046927SAndroid Build Coastguard Worker }
863*61046927SAndroid Build Coastguard Worker
864*61046927SAndroid Build Coastguard Worker impl SM70Op for OpFMul {
legalize(&mut self, b: &mut LegalizeBuilder)865*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
866*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
867*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
868*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
869*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F32);
870*61046927SAndroid Build Coastguard Worker }
871*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)872*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
873*61046927SAndroid Build Coastguard Worker e.encode_alu(
874*61046927SAndroid Build Coastguard Worker 0x020,
875*61046927SAndroid Build Coastguard Worker Some(&self.dst),
876*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
877*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
878*61046927SAndroid Build Coastguard Worker Some(&Src::new_zero()),
879*61046927SAndroid Build Coastguard Worker );
880*61046927SAndroid Build Coastguard Worker e.set_bit(76, self.dnz);
881*61046927SAndroid Build Coastguard Worker e.set_bit(77, self.saturate);
882*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
883*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
884*61046927SAndroid Build Coastguard Worker e.set_field(84..87, 0x4_u8); // TODO: PDIV
885*61046927SAndroid Build Coastguard Worker }
886*61046927SAndroid Build Coastguard Worker }
887*61046927SAndroid Build Coastguard Worker
888*61046927SAndroid Build Coastguard Worker impl SM70Encoder<'_> {
set_float_cmp_op(&mut self, range: Range<usize>, op: FloatCmpOp)889*61046927SAndroid Build Coastguard Worker fn set_float_cmp_op(&mut self, range: Range<usize>, op: FloatCmpOp) {
890*61046927SAndroid Build Coastguard Worker assert!(range.len() == 4);
891*61046927SAndroid Build Coastguard Worker self.set_field(
892*61046927SAndroid Build Coastguard Worker range,
893*61046927SAndroid Build Coastguard Worker match op {
894*61046927SAndroid Build Coastguard Worker FloatCmpOp::OrdLt => 0x01_u8,
895*61046927SAndroid Build Coastguard Worker FloatCmpOp::OrdEq => 0x02_u8,
896*61046927SAndroid Build Coastguard Worker FloatCmpOp::OrdLe => 0x03_u8,
897*61046927SAndroid Build Coastguard Worker FloatCmpOp::OrdGt => 0x04_u8,
898*61046927SAndroid Build Coastguard Worker FloatCmpOp::OrdNe => 0x05_u8,
899*61046927SAndroid Build Coastguard Worker FloatCmpOp::OrdGe => 0x06_u8,
900*61046927SAndroid Build Coastguard Worker FloatCmpOp::UnordLt => 0x09_u8,
901*61046927SAndroid Build Coastguard Worker FloatCmpOp::UnordEq => 0x0a_u8,
902*61046927SAndroid Build Coastguard Worker FloatCmpOp::UnordLe => 0x0b_u8,
903*61046927SAndroid Build Coastguard Worker FloatCmpOp::UnordGt => 0x0c_u8,
904*61046927SAndroid Build Coastguard Worker FloatCmpOp::UnordNe => 0x0d_u8,
905*61046927SAndroid Build Coastguard Worker FloatCmpOp::UnordGe => 0x0e_u8,
906*61046927SAndroid Build Coastguard Worker FloatCmpOp::IsNum => 0x07_u8,
907*61046927SAndroid Build Coastguard Worker FloatCmpOp::IsNan => 0x08_u8,
908*61046927SAndroid Build Coastguard Worker },
909*61046927SAndroid Build Coastguard Worker );
910*61046927SAndroid Build Coastguard Worker }
911*61046927SAndroid Build Coastguard Worker
set_pred_set_op(&mut self, range: Range<usize>, op: PredSetOp)912*61046927SAndroid Build Coastguard Worker fn set_pred_set_op(&mut self, range: Range<usize>, op: PredSetOp) {
913*61046927SAndroid Build Coastguard Worker assert!(range.len() == 2);
914*61046927SAndroid Build Coastguard Worker self.set_field(
915*61046927SAndroid Build Coastguard Worker range,
916*61046927SAndroid Build Coastguard Worker match op {
917*61046927SAndroid Build Coastguard Worker PredSetOp::And => 0_u8,
918*61046927SAndroid Build Coastguard Worker PredSetOp::Or => 1_u8,
919*61046927SAndroid Build Coastguard Worker PredSetOp::Xor => 2_u8,
920*61046927SAndroid Build Coastguard Worker },
921*61046927SAndroid Build Coastguard Worker );
922*61046927SAndroid Build Coastguard Worker }
923*61046927SAndroid Build Coastguard Worker
set_int_cmp_op(&mut self, range: Range<usize>, op: IntCmpOp)924*61046927SAndroid Build Coastguard Worker fn set_int_cmp_op(&mut self, range: Range<usize>, op: IntCmpOp) {
925*61046927SAndroid Build Coastguard Worker assert!(range.len() == 3);
926*61046927SAndroid Build Coastguard Worker self.set_field(
927*61046927SAndroid Build Coastguard Worker range,
928*61046927SAndroid Build Coastguard Worker match op {
929*61046927SAndroid Build Coastguard Worker IntCmpOp::Eq => 2_u8,
930*61046927SAndroid Build Coastguard Worker IntCmpOp::Ne => 5_u8,
931*61046927SAndroid Build Coastguard Worker IntCmpOp::Lt => 1_u8,
932*61046927SAndroid Build Coastguard Worker IntCmpOp::Le => 3_u8,
933*61046927SAndroid Build Coastguard Worker IntCmpOp::Gt => 4_u8,
934*61046927SAndroid Build Coastguard Worker IntCmpOp::Ge => 6_u8,
935*61046927SAndroid Build Coastguard Worker },
936*61046927SAndroid Build Coastguard Worker );
937*61046927SAndroid Build Coastguard Worker }
938*61046927SAndroid Build Coastguard Worker }
939*61046927SAndroid Build Coastguard Worker
940*61046927SAndroid Build Coastguard Worker impl SM70Op for OpFSet {
legalize(&mut self, b: &mut LegalizeBuilder)941*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
942*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
943*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
944*61046927SAndroid Build Coastguard Worker if !src_is_reg(src0, gpr) && src_is_reg(src1, gpr) {
945*61046927SAndroid Build Coastguard Worker std::mem::swap(src0, src1);
946*61046927SAndroid Build Coastguard Worker self.cmp_op = self.cmp_op.flip();
947*61046927SAndroid Build Coastguard Worker }
948*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F32);
949*61046927SAndroid Build Coastguard Worker }
950*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)951*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
952*61046927SAndroid Build Coastguard Worker e.encode_alu(
953*61046927SAndroid Build Coastguard Worker 0x00a,
954*61046927SAndroid Build Coastguard Worker Some(&self.dst),
955*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
956*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
957*61046927SAndroid Build Coastguard Worker None,
958*61046927SAndroid Build Coastguard Worker );
959*61046927SAndroid Build Coastguard Worker e.set_float_cmp_op(76..80, self.cmp_op);
960*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
961*61046927SAndroid Build Coastguard Worker e.set_field(87..90, 0x7_u8); // TODO: src predicate
962*61046927SAndroid Build Coastguard Worker }
963*61046927SAndroid Build Coastguard Worker }
964*61046927SAndroid Build Coastguard Worker
965*61046927SAndroid Build Coastguard Worker impl SM70Op for OpFSetP {
legalize(&mut self, b: &mut LegalizeBuilder)966*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
967*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
968*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
969*61046927SAndroid Build Coastguard Worker if !src_is_reg(src0, gpr) && src_is_reg(src1, gpr) {
970*61046927SAndroid Build Coastguard Worker std::mem::swap(src0, src1);
971*61046927SAndroid Build Coastguard Worker self.cmp_op = self.cmp_op.flip();
972*61046927SAndroid Build Coastguard Worker }
973*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F32);
974*61046927SAndroid Build Coastguard Worker }
975*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)976*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
977*61046927SAndroid Build Coastguard Worker e.encode_alu(
978*61046927SAndroid Build Coastguard Worker 0x00b,
979*61046927SAndroid Build Coastguard Worker None,
980*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
981*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
982*61046927SAndroid Build Coastguard Worker None,
983*61046927SAndroid Build Coastguard Worker );
984*61046927SAndroid Build Coastguard Worker
985*61046927SAndroid Build Coastguard Worker e.set_pred_set_op(74..76, self.set_op);
986*61046927SAndroid Build Coastguard Worker e.set_float_cmp_op(76..80, self.cmp_op);
987*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
988*61046927SAndroid Build Coastguard Worker
989*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.dst);
990*61046927SAndroid Build Coastguard Worker e.set_pred_dst(84..87, Dst::None); // dst1
991*61046927SAndroid Build Coastguard Worker
992*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.accum);
993*61046927SAndroid Build Coastguard Worker }
994*61046927SAndroid Build Coastguard Worker }
995*61046927SAndroid Build Coastguard Worker
996*61046927SAndroid Build Coastguard Worker impl SM70Op for OpFSwzAdd {
legalize(&mut self, b: &mut LegalizeBuilder)997*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
998*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
999*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1000*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F32);
1001*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src1, gpr, SrcType::F32);
1002*61046927SAndroid Build Coastguard Worker }
1003*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1004*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1005*61046927SAndroid Build Coastguard Worker e.set_opcode(0x822);
1006*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
1007*61046927SAndroid Build Coastguard Worker
1008*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.srcs[0]);
1009*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.srcs[1]);
1010*61046927SAndroid Build Coastguard Worker
1011*61046927SAndroid Build Coastguard Worker let mut subop = 0x0_u8;
1012*61046927SAndroid Build Coastguard Worker
1013*61046927SAndroid Build Coastguard Worker for (i, swz_op) in self.ops.iter().enumerate() {
1014*61046927SAndroid Build Coastguard Worker let swz_op = match swz_op {
1015*61046927SAndroid Build Coastguard Worker FSwzAddOp::Add => 0,
1016*61046927SAndroid Build Coastguard Worker FSwzAddOp::SubRight => 2,
1017*61046927SAndroid Build Coastguard Worker FSwzAddOp::SubLeft => 1,
1018*61046927SAndroid Build Coastguard Worker FSwzAddOp::MoveLeft => 3,
1019*61046927SAndroid Build Coastguard Worker };
1020*61046927SAndroid Build Coastguard Worker
1021*61046927SAndroid Build Coastguard Worker subop |= swz_op << ((self.ops.len() - i - 1) * 2);
1022*61046927SAndroid Build Coastguard Worker }
1023*61046927SAndroid Build Coastguard Worker
1024*61046927SAndroid Build Coastguard Worker e.set_field(32..40, subop);
1025*61046927SAndroid Build Coastguard Worker
1026*61046927SAndroid Build Coastguard Worker e.set_bit(77, false); // NDV
1027*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
1028*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
1029*61046927SAndroid Build Coastguard Worker }
1030*61046927SAndroid Build Coastguard Worker }
1031*61046927SAndroid Build Coastguard Worker
1032*61046927SAndroid Build Coastguard Worker impl SM70Op for OpMuFu {
legalize(&mut self, _b: &mut LegalizeBuilder)1033*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1034*61046927SAndroid Build Coastguard Worker // Nothing to do
1035*61046927SAndroid Build Coastguard Worker }
1036*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1037*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1038*61046927SAndroid Build Coastguard Worker e.encode_alu(0x108, Some(&self.dst), None, Some(&self.src), None);
1039*61046927SAndroid Build Coastguard Worker e.set_field(
1040*61046927SAndroid Build Coastguard Worker 74..80,
1041*61046927SAndroid Build Coastguard Worker match self.op {
1042*61046927SAndroid Build Coastguard Worker MuFuOp::Cos => 0_u8,
1043*61046927SAndroid Build Coastguard Worker MuFuOp::Sin => 1_u8,
1044*61046927SAndroid Build Coastguard Worker MuFuOp::Exp2 => 2_u8,
1045*61046927SAndroid Build Coastguard Worker MuFuOp::Log2 => 3_u8,
1046*61046927SAndroid Build Coastguard Worker MuFuOp::Rcp => 4_u8,
1047*61046927SAndroid Build Coastguard Worker MuFuOp::Rsq => 5_u8,
1048*61046927SAndroid Build Coastguard Worker MuFuOp::Rcp64H => 6_u8,
1049*61046927SAndroid Build Coastguard Worker MuFuOp::Rsq64H => 7_u8,
1050*61046927SAndroid Build Coastguard Worker MuFuOp::Sqrt => 8_u8,
1051*61046927SAndroid Build Coastguard Worker MuFuOp::Tanh => 9_u8,
1052*61046927SAndroid Build Coastguard Worker },
1053*61046927SAndroid Build Coastguard Worker );
1054*61046927SAndroid Build Coastguard Worker }
1055*61046927SAndroid Build Coastguard Worker }
1056*61046927SAndroid Build Coastguard Worker
1057*61046927SAndroid Build Coastguard Worker impl SM70Op for OpDAdd {
legalize(&mut self, b: &mut LegalizeBuilder)1058*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1059*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1060*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1061*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1062*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F64);
1063*61046927SAndroid Build Coastguard Worker }
1064*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1065*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1066*61046927SAndroid Build Coastguard Worker e.encode_alu(
1067*61046927SAndroid Build Coastguard Worker 0x029,
1068*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1069*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1070*61046927SAndroid Build Coastguard Worker None,
1071*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1072*61046927SAndroid Build Coastguard Worker );
1073*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
1074*61046927SAndroid Build Coastguard Worker }
1075*61046927SAndroid Build Coastguard Worker }
1076*61046927SAndroid Build Coastguard Worker
1077*61046927SAndroid Build Coastguard Worker impl SM70Op for OpDFma {
legalize(&mut self, b: &mut LegalizeBuilder)1078*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1079*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1080*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
1081*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1082*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F64);
1083*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_both_not_reg(src1, src2, gpr, SrcType::F64);
1084*61046927SAndroid Build Coastguard Worker }
1085*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1086*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1087*61046927SAndroid Build Coastguard Worker e.encode_alu(
1088*61046927SAndroid Build Coastguard Worker 0x02b,
1089*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1090*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1091*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1092*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1093*61046927SAndroid Build Coastguard Worker );
1094*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
1095*61046927SAndroid Build Coastguard Worker }
1096*61046927SAndroid Build Coastguard Worker }
1097*61046927SAndroid Build Coastguard Worker
1098*61046927SAndroid Build Coastguard Worker impl SM70Op for OpDMul {
legalize(&mut self, b: &mut LegalizeBuilder)1099*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1100*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1101*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1102*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1103*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F64);
1104*61046927SAndroid Build Coastguard Worker }
1105*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1106*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1107*61046927SAndroid Build Coastguard Worker e.encode_alu(
1108*61046927SAndroid Build Coastguard Worker 0x028,
1109*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1110*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1111*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1112*61046927SAndroid Build Coastguard Worker None,
1113*61046927SAndroid Build Coastguard Worker );
1114*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
1115*61046927SAndroid Build Coastguard Worker }
1116*61046927SAndroid Build Coastguard Worker }
1117*61046927SAndroid Build Coastguard Worker
1118*61046927SAndroid Build Coastguard Worker impl SM70Op for OpDSetP {
legalize(&mut self, b: &mut LegalizeBuilder)1119*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1120*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1121*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1122*61046927SAndroid Build Coastguard Worker if !src_is_reg(src0, gpr) && src_is_reg(src1, gpr) {
1123*61046927SAndroid Build Coastguard Worker std::mem::swap(src0, src1);
1124*61046927SAndroid Build Coastguard Worker self.cmp_op = self.cmp_op.flip();
1125*61046927SAndroid Build Coastguard Worker }
1126*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F64);
1127*61046927SAndroid Build Coastguard Worker }
1128*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1129*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1130*61046927SAndroid Build Coastguard Worker if src_is_zero_or_gpr(&self.srcs[1]) {
1131*61046927SAndroid Build Coastguard Worker e.encode_alu(
1132*61046927SAndroid Build Coastguard Worker 0x02a,
1133*61046927SAndroid Build Coastguard Worker None,
1134*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1135*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1136*61046927SAndroid Build Coastguard Worker None,
1137*61046927SAndroid Build Coastguard Worker )
1138*61046927SAndroid Build Coastguard Worker } else {
1139*61046927SAndroid Build Coastguard Worker e.encode_alu(
1140*61046927SAndroid Build Coastguard Worker 0x02a,
1141*61046927SAndroid Build Coastguard Worker None,
1142*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1143*61046927SAndroid Build Coastguard Worker None,
1144*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1145*61046927SAndroid Build Coastguard Worker )
1146*61046927SAndroid Build Coastguard Worker };
1147*61046927SAndroid Build Coastguard Worker
1148*61046927SAndroid Build Coastguard Worker e.set_pred_set_op(74..76, self.set_op);
1149*61046927SAndroid Build Coastguard Worker e.set_float_cmp_op(76..80, self.cmp_op);
1150*61046927SAndroid Build Coastguard Worker
1151*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.dst);
1152*61046927SAndroid Build Coastguard Worker e.set_pred_dst(84..87, Dst::None); /* dst1 */
1153*61046927SAndroid Build Coastguard Worker
1154*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.accum);
1155*61046927SAndroid Build Coastguard Worker }
1156*61046927SAndroid Build Coastguard Worker }
1157*61046927SAndroid Build Coastguard Worker
1158*61046927SAndroid Build Coastguard Worker impl SM70Op for OpHAdd2 {
legalize(&mut self, b: &mut LegalizeBuilder)1159*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1160*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1161*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1162*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1163*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F16v2);
1164*61046927SAndroid Build Coastguard Worker }
1165*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1166*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1167*61046927SAndroid Build Coastguard Worker if src_is_zero_or_gpr(&self.srcs[1]) {
1168*61046927SAndroid Build Coastguard Worker e.encode_fp16_alu(
1169*61046927SAndroid Build Coastguard Worker 0x030,
1170*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1171*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1172*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1173*61046927SAndroid Build Coastguard Worker None,
1174*61046927SAndroid Build Coastguard Worker )
1175*61046927SAndroid Build Coastguard Worker } else {
1176*61046927SAndroid Build Coastguard Worker e.encode_fp16_alu(
1177*61046927SAndroid Build Coastguard Worker 0x030,
1178*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1179*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1180*61046927SAndroid Build Coastguard Worker None,
1181*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1182*61046927SAndroid Build Coastguard Worker )
1183*61046927SAndroid Build Coastguard Worker };
1184*61046927SAndroid Build Coastguard Worker
1185*61046927SAndroid Build Coastguard Worker e.set_bit(77, self.saturate);
1186*61046927SAndroid Build Coastguard Worker e.set_bit(78, self.f32);
1187*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
1188*61046927SAndroid Build Coastguard Worker e.set_bit(85, false); // .BF16_V2 (SM90+)
1189*61046927SAndroid Build Coastguard Worker }
1190*61046927SAndroid Build Coastguard Worker }
1191*61046927SAndroid Build Coastguard Worker
1192*61046927SAndroid Build Coastguard Worker impl SM70Op for OpHFma2 {
legalize(&mut self, b: &mut LegalizeBuilder)1193*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1194*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1195*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
1196*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1197*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F16v2);
1198*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src1, gpr, SrcType::F16v2);
1199*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_both_not_reg(src1, src2, gpr, SrcType::F16v2);
1200*61046927SAndroid Build Coastguard Worker
1201*61046927SAndroid Build Coastguard Worker // HFMA2 doesn't have fabs or fneg on SRC2.
1202*61046927SAndroid Build Coastguard Worker if !src2.src_mod.is_none() {
1203*61046927SAndroid Build Coastguard Worker b.copy_alu_src_and_lower_fmod(src2, SrcType::F16v2);
1204*61046927SAndroid Build Coastguard Worker }
1205*61046927SAndroid Build Coastguard Worker }
1206*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1207*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1208*61046927SAndroid Build Coastguard Worker // HFMA2 doesn't have fneg and fabs on SRC2.
1209*61046927SAndroid Build Coastguard Worker assert!(self.srcs[2].src_mod.is_none());
1210*61046927SAndroid Build Coastguard Worker
1211*61046927SAndroid Build Coastguard Worker e.encode_fp16_alu(
1212*61046927SAndroid Build Coastguard Worker 0x031,
1213*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1214*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1215*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1216*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1217*61046927SAndroid Build Coastguard Worker );
1218*61046927SAndroid Build Coastguard Worker
1219*61046927SAndroid Build Coastguard Worker e.set_bit(76, self.dnz);
1220*61046927SAndroid Build Coastguard Worker e.set_bit(77, self.saturate);
1221*61046927SAndroid Build Coastguard Worker e.set_bit(78, self.f32);
1222*61046927SAndroid Build Coastguard Worker e.set_bit(79, false); // .RELU (SM86+)
1223*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
1224*61046927SAndroid Build Coastguard Worker e.set_bit(85, false); // .BF16_V2 (SM86+)
1225*61046927SAndroid Build Coastguard Worker }
1226*61046927SAndroid Build Coastguard Worker }
1227*61046927SAndroid Build Coastguard Worker
1228*61046927SAndroid Build Coastguard Worker impl SM70Op for OpHMul2 {
legalize(&mut self, b: &mut LegalizeBuilder)1229*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1230*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1231*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1232*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1233*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F16v2);
1234*61046927SAndroid Build Coastguard Worker }
1235*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1236*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1237*61046927SAndroid Build Coastguard Worker e.encode_fp16_alu(
1238*61046927SAndroid Build Coastguard Worker 0x032,
1239*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1240*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1241*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1242*61046927SAndroid Build Coastguard Worker None,
1243*61046927SAndroid Build Coastguard Worker );
1244*61046927SAndroid Build Coastguard Worker
1245*61046927SAndroid Build Coastguard Worker e.set_bit(76, self.dnz);
1246*61046927SAndroid Build Coastguard Worker e.set_bit(77, self.saturate);
1247*61046927SAndroid Build Coastguard Worker e.set_bit(78, false); // .F32 (SM70-SM75)
1248*61046927SAndroid Build Coastguard Worker e.set_bit(79, false); // .RELU (SM86+)
1249*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
1250*61046927SAndroid Build Coastguard Worker e.set_bit(85, false); // .BF16_V2 (SM90+)
1251*61046927SAndroid Build Coastguard Worker }
1252*61046927SAndroid Build Coastguard Worker }
1253*61046927SAndroid Build Coastguard Worker
1254*61046927SAndroid Build Coastguard Worker impl SM70Op for OpHSet2 {
legalize(&mut self, b: &mut LegalizeBuilder)1255*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1256*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1257*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1258*61046927SAndroid Build Coastguard Worker if !src_is_reg(src0, gpr) && src_is_reg(src1, gpr) {
1259*61046927SAndroid Build Coastguard Worker std::mem::swap(src0, src1);
1260*61046927SAndroid Build Coastguard Worker self.cmp_op = self.cmp_op.flip();
1261*61046927SAndroid Build Coastguard Worker }
1262*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F16v2);
1263*61046927SAndroid Build Coastguard Worker }
1264*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1265*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1266*61046927SAndroid Build Coastguard Worker if src_is_zero_or_gpr(&self.srcs[1]) {
1267*61046927SAndroid Build Coastguard Worker e.encode_fp16_alu(
1268*61046927SAndroid Build Coastguard Worker 0x033,
1269*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1270*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1271*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1272*61046927SAndroid Build Coastguard Worker None,
1273*61046927SAndroid Build Coastguard Worker )
1274*61046927SAndroid Build Coastguard Worker } else {
1275*61046927SAndroid Build Coastguard Worker e.encode_fp16_alu(
1276*61046927SAndroid Build Coastguard Worker 0x033,
1277*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1278*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1279*61046927SAndroid Build Coastguard Worker None,
1280*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1281*61046927SAndroid Build Coastguard Worker )
1282*61046927SAndroid Build Coastguard Worker };
1283*61046927SAndroid Build Coastguard Worker
1284*61046927SAndroid Build Coastguard Worker e.set_bit(65, false); // .BF16_V2 (SM90+)
1285*61046927SAndroid Build Coastguard Worker e.set_pred_set_op(69..71, self.set_op);
1286*61046927SAndroid Build Coastguard Worker
1287*61046927SAndroid Build Coastguard Worker // This differentiate between integer and fp16 output
1288*61046927SAndroid Build Coastguard Worker e.set_bit(71, true); // .BF
1289*61046927SAndroid Build Coastguard Worker e.set_float_cmp_op(76..80, self.cmp_op);
1290*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
1291*61046927SAndroid Build Coastguard Worker
1292*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.accum);
1293*61046927SAndroid Build Coastguard Worker }
1294*61046927SAndroid Build Coastguard Worker }
1295*61046927SAndroid Build Coastguard Worker
1296*61046927SAndroid Build Coastguard Worker impl SM70Op for OpHSetP2 {
legalize(&mut self, b: &mut LegalizeBuilder)1297*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1298*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1299*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1300*61046927SAndroid Build Coastguard Worker if !src_is_reg(src0, gpr) && src_is_reg(src1, gpr) {
1301*61046927SAndroid Build Coastguard Worker std::mem::swap(src0, src1);
1302*61046927SAndroid Build Coastguard Worker self.cmp_op = self.cmp_op.flip();
1303*61046927SAndroid Build Coastguard Worker }
1304*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F16v2);
1305*61046927SAndroid Build Coastguard Worker }
1306*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1307*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1308*61046927SAndroid Build Coastguard Worker if src_is_zero_or_gpr(&self.srcs[1]) {
1309*61046927SAndroid Build Coastguard Worker e.encode_fp16_alu(
1310*61046927SAndroid Build Coastguard Worker 0x034,
1311*61046927SAndroid Build Coastguard Worker None,
1312*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1313*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1314*61046927SAndroid Build Coastguard Worker None,
1315*61046927SAndroid Build Coastguard Worker )
1316*61046927SAndroid Build Coastguard Worker } else {
1317*61046927SAndroid Build Coastguard Worker e.encode_fp16_alu(
1318*61046927SAndroid Build Coastguard Worker 0x034,
1319*61046927SAndroid Build Coastguard Worker None,
1320*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1321*61046927SAndroid Build Coastguard Worker None,
1322*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1323*61046927SAndroid Build Coastguard Worker )
1324*61046927SAndroid Build Coastguard Worker };
1325*61046927SAndroid Build Coastguard Worker
1326*61046927SAndroid Build Coastguard Worker e.set_bit(65, false); // .BF16_V2 (SM90+)
1327*61046927SAndroid Build Coastguard Worker e.set_pred_set_op(69..71, self.set_op);
1328*61046927SAndroid Build Coastguard Worker e.set_bit(71, self.horizontal); // .H_AND
1329*61046927SAndroid Build Coastguard Worker e.set_float_cmp_op(76..80, self.cmp_op);
1330*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
1331*61046927SAndroid Build Coastguard Worker
1332*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.dsts[0]);
1333*61046927SAndroid Build Coastguard Worker e.set_pred_dst(84..87, self.dsts[1]);
1334*61046927SAndroid Build Coastguard Worker
1335*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.accum);
1336*61046927SAndroid Build Coastguard Worker }
1337*61046927SAndroid Build Coastguard Worker }
1338*61046927SAndroid Build Coastguard Worker
1339*61046927SAndroid Build Coastguard Worker impl SM70Op for OpHMnMx2 {
legalize(&mut self, b: &mut LegalizeBuilder)1340*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1341*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1342*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1343*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1344*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::F16v2);
1345*61046927SAndroid Build Coastguard Worker }
1346*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1347*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1348*61046927SAndroid Build Coastguard Worker assert!(e.sm.sm >= 80);
1349*61046927SAndroid Build Coastguard Worker
1350*61046927SAndroid Build Coastguard Worker e.encode_fp16_alu(
1351*61046927SAndroid Build Coastguard Worker 0x040,
1352*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1353*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1354*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1355*61046927SAndroid Build Coastguard Worker None,
1356*61046927SAndroid Build Coastguard Worker );
1357*61046927SAndroid Build Coastguard Worker
1358*61046927SAndroid Build Coastguard Worker // This differentiate between integer and fp16 output
1359*61046927SAndroid Build Coastguard Worker e.set_bit(78, false); // .F32 (SM86)
1360*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
1361*61046927SAndroid Build Coastguard Worker e.set_bit(81, false); // .NAN
1362*61046927SAndroid Build Coastguard Worker e.set_bit(82, false); // .XORSIGN
1363*61046927SAndroid Build Coastguard Worker e.set_bit(85, false); // .BF16_V2
1364*61046927SAndroid Build Coastguard Worker
1365*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.min);
1366*61046927SAndroid Build Coastguard Worker }
1367*61046927SAndroid Build Coastguard Worker }
1368*61046927SAndroid Build Coastguard Worker
1369*61046927SAndroid Build Coastguard Worker impl SM70Op for OpBMsk {
legalize(&mut self, b: &mut LegalizeBuilder)1370*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1371*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1372*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(&mut self.pos, gpr, SrcType::ALU);
1373*61046927SAndroid Build Coastguard Worker }
1374*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1375*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1376*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1377*61046927SAndroid Build Coastguard Worker e.encode_ualu(
1378*61046927SAndroid Build Coastguard Worker 0x09b,
1379*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1380*61046927SAndroid Build Coastguard Worker Some(&self.pos),
1381*61046927SAndroid Build Coastguard Worker Some(&self.width),
1382*61046927SAndroid Build Coastguard Worker None,
1383*61046927SAndroid Build Coastguard Worker )
1384*61046927SAndroid Build Coastguard Worker } else {
1385*61046927SAndroid Build Coastguard Worker e.encode_alu(
1386*61046927SAndroid Build Coastguard Worker 0x01b,
1387*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1388*61046927SAndroid Build Coastguard Worker Some(&self.pos),
1389*61046927SAndroid Build Coastguard Worker Some(&self.width),
1390*61046927SAndroid Build Coastguard Worker None,
1391*61046927SAndroid Build Coastguard Worker )
1392*61046927SAndroid Build Coastguard Worker };
1393*61046927SAndroid Build Coastguard Worker
1394*61046927SAndroid Build Coastguard Worker e.set_bit(75, self.wrap);
1395*61046927SAndroid Build Coastguard Worker }
1396*61046927SAndroid Build Coastguard Worker }
1397*61046927SAndroid Build Coastguard Worker
1398*61046927SAndroid Build Coastguard Worker impl SM70Op for OpBRev {
legalize(&mut self, _b: &mut LegalizeBuilder)1399*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1400*61046927SAndroid Build Coastguard Worker // Nothing to do
1401*61046927SAndroid Build Coastguard Worker }
1402*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1403*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1404*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1405*61046927SAndroid Build Coastguard Worker e.encode_ualu(0x0be, Some(&self.dst), None, Some(&self.src), None)
1406*61046927SAndroid Build Coastguard Worker } else {
1407*61046927SAndroid Build Coastguard Worker e.encode_alu(0x101, Some(&self.dst), None, Some(&self.src), None)
1408*61046927SAndroid Build Coastguard Worker }
1409*61046927SAndroid Build Coastguard Worker }
1410*61046927SAndroid Build Coastguard Worker }
1411*61046927SAndroid Build Coastguard Worker
1412*61046927SAndroid Build Coastguard Worker impl SM70Op for OpFlo {
legalize(&mut self, _b: &mut LegalizeBuilder)1413*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1414*61046927SAndroid Build Coastguard Worker // Nothing to do
1415*61046927SAndroid Build Coastguard Worker }
1416*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1417*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1418*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1419*61046927SAndroid Build Coastguard Worker e.encode_ualu(0x0bd, Some(&self.dst), None, Some(&self.src), None)
1420*61046927SAndroid Build Coastguard Worker } else {
1421*61046927SAndroid Build Coastguard Worker e.encode_alu(0x100, Some(&self.dst), None, Some(&self.src), None)
1422*61046927SAndroid Build Coastguard Worker };
1423*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, Dst::None);
1424*61046927SAndroid Build Coastguard Worker e.set_field(74..75, self.return_shift_amount as u8);
1425*61046927SAndroid Build Coastguard Worker e.set_field(73..74, self.signed as u8);
1426*61046927SAndroid Build Coastguard Worker let not_mod = matches!(self.src.src_mod, SrcMod::BNot);
1427*61046927SAndroid Build Coastguard Worker e.set_field(63..64, not_mod)
1428*61046927SAndroid Build Coastguard Worker }
1429*61046927SAndroid Build Coastguard Worker }
1430*61046927SAndroid Build Coastguard Worker
1431*61046927SAndroid Build Coastguard Worker impl SM70Op for OpIAbs {
legalize(&mut self, _b: &mut LegalizeBuilder)1432*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1433*61046927SAndroid Build Coastguard Worker // Nothing to do
1434*61046927SAndroid Build Coastguard Worker }
1435*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1436*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1437*61046927SAndroid Build Coastguard Worker e.encode_alu(0x013, Some(&self.dst), None, Some(&self.src), None)
1438*61046927SAndroid Build Coastguard Worker }
1439*61046927SAndroid Build Coastguard Worker }
1440*61046927SAndroid Build Coastguard Worker
1441*61046927SAndroid Build Coastguard Worker impl SM70Op for OpIAdd3 {
legalize(&mut self, b: &mut LegalizeBuilder)1442*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1443*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1444*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
1445*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1446*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src2, src1, gpr);
1447*61046927SAndroid Build Coastguard Worker if !src0.src_mod.is_none() && !src1.src_mod.is_none() {
1448*61046927SAndroid Build Coastguard Worker assert!(self.overflow[0].is_none());
1449*61046927SAndroid Build Coastguard Worker assert!(self.overflow[1].is_none());
1450*61046927SAndroid Build Coastguard Worker let val = b.alloc_ssa(gpr, 1);
1451*61046927SAndroid Build Coastguard Worker b.push_op(OpIAdd3 {
1452*61046927SAndroid Build Coastguard Worker srcs: [Src::new_zero(), *src0, Src::new_zero()],
1453*61046927SAndroid Build Coastguard Worker overflow: [Dst::None; 2],
1454*61046927SAndroid Build Coastguard Worker dst: val.into(),
1455*61046927SAndroid Build Coastguard Worker });
1456*61046927SAndroid Build Coastguard Worker *src0 = val.into();
1457*61046927SAndroid Build Coastguard Worker }
1458*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::I32);
1459*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_both_not_reg(src1, src2, gpr, SrcType::I32);
1460*61046927SAndroid Build Coastguard Worker if !self.overflow[0].is_none() || !self.overflow[1].is_none() {
1461*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_ineg_imm(src1, gpr, SrcType::I32);
1462*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_ineg_imm(src2, gpr, SrcType::I32);
1463*61046927SAndroid Build Coastguard Worker }
1464*61046927SAndroid Build Coastguard Worker }
1465*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1466*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1467*61046927SAndroid Build Coastguard Worker // Hardware requires at least one of these be unmodified
1468*61046927SAndroid Build Coastguard Worker assert!(
1469*61046927SAndroid Build Coastguard Worker self.srcs[0].src_mod.is_none() || self.srcs[1].src_mod.is_none()
1470*61046927SAndroid Build Coastguard Worker );
1471*61046927SAndroid Build Coastguard Worker
1472*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1473*61046927SAndroid Build Coastguard Worker e.encode_ualu(
1474*61046927SAndroid Build Coastguard Worker 0x090,
1475*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1476*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1477*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1478*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1479*61046927SAndroid Build Coastguard Worker )
1480*61046927SAndroid Build Coastguard Worker } else {
1481*61046927SAndroid Build Coastguard Worker e.encode_alu(
1482*61046927SAndroid Build Coastguard Worker 0x010,
1483*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1484*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1485*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1486*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1487*61046927SAndroid Build Coastguard Worker )
1488*61046927SAndroid Build Coastguard Worker };
1489*61046927SAndroid Build Coastguard Worker
1490*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, false.into());
1491*61046927SAndroid Build Coastguard Worker e.set_pred_src(77..80, 80, false.into());
1492*61046927SAndroid Build Coastguard Worker
1493*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.overflow[0]);
1494*61046927SAndroid Build Coastguard Worker e.set_pred_dst(84..87, self.overflow[1]);
1495*61046927SAndroid Build Coastguard Worker }
1496*61046927SAndroid Build Coastguard Worker }
1497*61046927SAndroid Build Coastguard Worker
1498*61046927SAndroid Build Coastguard Worker impl SM70Op for OpIAdd3X {
legalize(&mut self, b: &mut LegalizeBuilder)1499*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1500*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1501*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
1502*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1503*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src2, src1, gpr);
1504*61046927SAndroid Build Coastguard Worker if !src0.src_mod.is_none() && !src1.src_mod.is_none() {
1505*61046927SAndroid Build Coastguard Worker let val = b.alloc_ssa(gpr, 1);
1506*61046927SAndroid Build Coastguard Worker b.push_op(OpIAdd3X {
1507*61046927SAndroid Build Coastguard Worker srcs: [Src::new_zero(), *src0, Src::new_zero()],
1508*61046927SAndroid Build Coastguard Worker overflow: [Dst::None; 2],
1509*61046927SAndroid Build Coastguard Worker dst: val.into(),
1510*61046927SAndroid Build Coastguard Worker carry: [false.into(); 2],
1511*61046927SAndroid Build Coastguard Worker });
1512*61046927SAndroid Build Coastguard Worker *src0 = val.into();
1513*61046927SAndroid Build Coastguard Worker }
1514*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::B32);
1515*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_both_not_reg(src1, src2, gpr, SrcType::B32);
1516*61046927SAndroid Build Coastguard Worker if !self.is_uniform() {
1517*61046927SAndroid Build Coastguard Worker b.copy_src_if_upred(&mut self.carry[0]);
1518*61046927SAndroid Build Coastguard Worker b.copy_src_if_upred(&mut self.carry[1]);
1519*61046927SAndroid Build Coastguard Worker }
1520*61046927SAndroid Build Coastguard Worker }
1521*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1522*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1523*61046927SAndroid Build Coastguard Worker // Hardware requires at least one of these be unmodified
1524*61046927SAndroid Build Coastguard Worker assert!(
1525*61046927SAndroid Build Coastguard Worker self.srcs[0].src_mod.is_none() || self.srcs[1].src_mod.is_none()
1526*61046927SAndroid Build Coastguard Worker );
1527*61046927SAndroid Build Coastguard Worker
1528*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1529*61046927SAndroid Build Coastguard Worker e.encode_ualu(
1530*61046927SAndroid Build Coastguard Worker 0x090,
1531*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1532*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1533*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1534*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1535*61046927SAndroid Build Coastguard Worker );
1536*61046927SAndroid Build Coastguard Worker
1537*61046927SAndroid Build Coastguard Worker e.set_upred_src(87..90, 90, self.carry[0]);
1538*61046927SAndroid Build Coastguard Worker e.set_upred_src(77..80, 80, self.carry[1]);
1539*61046927SAndroid Build Coastguard Worker } else {
1540*61046927SAndroid Build Coastguard Worker e.encode_alu(
1541*61046927SAndroid Build Coastguard Worker 0x010,
1542*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1543*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1544*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1545*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1546*61046927SAndroid Build Coastguard Worker );
1547*61046927SAndroid Build Coastguard Worker
1548*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.carry[0]);
1549*61046927SAndroid Build Coastguard Worker e.set_pred_src(77..80, 80, self.carry[1]);
1550*61046927SAndroid Build Coastguard Worker }
1551*61046927SAndroid Build Coastguard Worker
1552*61046927SAndroid Build Coastguard Worker e.set_bit(74, true); // .X
1553*61046927SAndroid Build Coastguard Worker
1554*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.overflow[0]);
1555*61046927SAndroid Build Coastguard Worker e.set_pred_dst(84..87, self.overflow[1]);
1556*61046927SAndroid Build Coastguard Worker }
1557*61046927SAndroid Build Coastguard Worker }
1558*61046927SAndroid Build Coastguard Worker
1559*61046927SAndroid Build Coastguard Worker impl SM70Op for OpIDp4 {
legalize(&mut self, b: &mut LegalizeBuilder)1560*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1561*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1562*61046927SAndroid Build Coastguard Worker let [src_type0, src_type1] = &mut self.src_types;
1563*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
1564*61046927SAndroid Build Coastguard Worker if swap_srcs_if_not_reg(src0, src1, gpr) {
1565*61046927SAndroid Build Coastguard Worker std::mem::swap(src_type0, src_type1);
1566*61046927SAndroid Build Coastguard Worker }
1567*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::ALU);
1568*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_ineg_imm(src1, gpr, SrcType::I32);
1569*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src2, gpr, SrcType::ALU);
1570*61046927SAndroid Build Coastguard Worker }
1571*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1572*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1573*61046927SAndroid Build Coastguard Worker e.encode_alu(
1574*61046927SAndroid Build Coastguard Worker 0x026,
1575*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1576*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1577*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1578*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1579*61046927SAndroid Build Coastguard Worker );
1580*61046927SAndroid Build Coastguard Worker
1581*61046927SAndroid Build Coastguard Worker e.set_bit(
1582*61046927SAndroid Build Coastguard Worker 73,
1583*61046927SAndroid Build Coastguard Worker match self.src_types[0] {
1584*61046927SAndroid Build Coastguard Worker IntType::U8 => false,
1585*61046927SAndroid Build Coastguard Worker IntType::I8 => true,
1586*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid DP4 source type"),
1587*61046927SAndroid Build Coastguard Worker },
1588*61046927SAndroid Build Coastguard Worker );
1589*61046927SAndroid Build Coastguard Worker e.set_bit(
1590*61046927SAndroid Build Coastguard Worker 74,
1591*61046927SAndroid Build Coastguard Worker match self.src_types[1] {
1592*61046927SAndroid Build Coastguard Worker IntType::U8 => false,
1593*61046927SAndroid Build Coastguard Worker IntType::I8 => true,
1594*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid DP4 source type"),
1595*61046927SAndroid Build Coastguard Worker },
1596*61046927SAndroid Build Coastguard Worker );
1597*61046927SAndroid Build Coastguard Worker }
1598*61046927SAndroid Build Coastguard Worker }
1599*61046927SAndroid Build Coastguard Worker
1600*61046927SAndroid Build Coastguard Worker impl SM70Op for OpIMad {
legalize(&mut self, b: &mut LegalizeBuilder)1601*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1602*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1603*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
1604*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1605*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::ALU);
1606*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_both_not_reg(src1, src2, gpr, SrcType::ALU);
1607*61046927SAndroid Build Coastguard Worker }
1608*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1609*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1610*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1611*61046927SAndroid Build Coastguard Worker e.encode_ualu(
1612*61046927SAndroid Build Coastguard Worker 0x0a4,
1613*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1614*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1615*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1616*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1617*61046927SAndroid Build Coastguard Worker )
1618*61046927SAndroid Build Coastguard Worker } else {
1619*61046927SAndroid Build Coastguard Worker e.encode_alu(
1620*61046927SAndroid Build Coastguard Worker 0x024,
1621*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1622*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1623*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1624*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1625*61046927SAndroid Build Coastguard Worker )
1626*61046927SAndroid Build Coastguard Worker };
1627*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, Dst::None);
1628*61046927SAndroid Build Coastguard Worker e.set_bit(73, self.signed);
1629*61046927SAndroid Build Coastguard Worker }
1630*61046927SAndroid Build Coastguard Worker }
1631*61046927SAndroid Build Coastguard Worker
1632*61046927SAndroid Build Coastguard Worker impl SM70Op for OpIMad64 {
legalize(&mut self, b: &mut LegalizeBuilder)1633*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1634*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1635*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
1636*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1637*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::ALU);
1638*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_both_not_reg(src1, src2, gpr, SrcType::ALU);
1639*61046927SAndroid Build Coastguard Worker }
1640*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1641*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1642*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1643*61046927SAndroid Build Coastguard Worker e.encode_ualu(
1644*61046927SAndroid Build Coastguard Worker 0x0a5,
1645*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1646*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1647*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1648*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1649*61046927SAndroid Build Coastguard Worker )
1650*61046927SAndroid Build Coastguard Worker } else {
1651*61046927SAndroid Build Coastguard Worker e.encode_alu(
1652*61046927SAndroid Build Coastguard Worker 0x025,
1653*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1654*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1655*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1656*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1657*61046927SAndroid Build Coastguard Worker )
1658*61046927SAndroid Build Coastguard Worker };
1659*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, Dst::None);
1660*61046927SAndroid Build Coastguard Worker e.set_bit(73, self.signed);
1661*61046927SAndroid Build Coastguard Worker }
1662*61046927SAndroid Build Coastguard Worker }
1663*61046927SAndroid Build Coastguard Worker
1664*61046927SAndroid Build Coastguard Worker impl SM70Op for OpIMnMx {
legalize(&mut self, b: &mut LegalizeBuilder)1665*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1666*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1667*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1668*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1669*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::ALU);
1670*61046927SAndroid Build Coastguard Worker }
1671*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1672*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1673*61046927SAndroid Build Coastguard Worker e.encode_alu(
1674*61046927SAndroid Build Coastguard Worker 0x017,
1675*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1676*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1677*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1678*61046927SAndroid Build Coastguard Worker None,
1679*61046927SAndroid Build Coastguard Worker );
1680*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.min);
1681*61046927SAndroid Build Coastguard Worker e.set_bit(
1682*61046927SAndroid Build Coastguard Worker 73,
1683*61046927SAndroid Build Coastguard Worker match self.cmp_type {
1684*61046927SAndroid Build Coastguard Worker IntCmpType::U32 => false,
1685*61046927SAndroid Build Coastguard Worker IntCmpType::I32 => true,
1686*61046927SAndroid Build Coastguard Worker },
1687*61046927SAndroid Build Coastguard Worker );
1688*61046927SAndroid Build Coastguard Worker }
1689*61046927SAndroid Build Coastguard Worker }
1690*61046927SAndroid Build Coastguard Worker
1691*61046927SAndroid Build Coastguard Worker impl SM70Op for OpISetP {
legalize(&mut self, b: &mut LegalizeBuilder)1692*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1693*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1694*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1695*61046927SAndroid Build Coastguard Worker if !src_is_reg(src0, gpr) && src_is_reg(src1, gpr) {
1696*61046927SAndroid Build Coastguard Worker std::mem::swap(src0, src1);
1697*61046927SAndroid Build Coastguard Worker self.cmp_op = self.cmp_op.flip();
1698*61046927SAndroid Build Coastguard Worker }
1699*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::ALU);
1700*61046927SAndroid Build Coastguard Worker if !self.is_uniform() {
1701*61046927SAndroid Build Coastguard Worker b.copy_src_if_upred(&mut self.low_cmp);
1702*61046927SAndroid Build Coastguard Worker b.copy_src_if_upred(&mut self.accum);
1703*61046927SAndroid Build Coastguard Worker }
1704*61046927SAndroid Build Coastguard Worker }
1705*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1706*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1707*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1708*61046927SAndroid Build Coastguard Worker e.encode_ualu(
1709*61046927SAndroid Build Coastguard Worker 0x08c,
1710*61046927SAndroid Build Coastguard Worker None,
1711*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1712*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1713*61046927SAndroid Build Coastguard Worker None,
1714*61046927SAndroid Build Coastguard Worker );
1715*61046927SAndroid Build Coastguard Worker
1716*61046927SAndroid Build Coastguard Worker e.set_upred_src(68..71, 71, self.low_cmp);
1717*61046927SAndroid Build Coastguard Worker e.set_upred_src(87..90, 90, self.accum);
1718*61046927SAndroid Build Coastguard Worker } else {
1719*61046927SAndroid Build Coastguard Worker e.encode_alu(
1720*61046927SAndroid Build Coastguard Worker 0x00c,
1721*61046927SAndroid Build Coastguard Worker None,
1722*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1723*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1724*61046927SAndroid Build Coastguard Worker None,
1725*61046927SAndroid Build Coastguard Worker );
1726*61046927SAndroid Build Coastguard Worker
1727*61046927SAndroid Build Coastguard Worker e.set_pred_src(68..71, 71, self.low_cmp);
1728*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.accum);
1729*61046927SAndroid Build Coastguard Worker }
1730*61046927SAndroid Build Coastguard Worker
1731*61046927SAndroid Build Coastguard Worker e.set_bit(72, self.ex);
1732*61046927SAndroid Build Coastguard Worker
1733*61046927SAndroid Build Coastguard Worker e.set_field(
1734*61046927SAndroid Build Coastguard Worker 73..74,
1735*61046927SAndroid Build Coastguard Worker match self.cmp_type {
1736*61046927SAndroid Build Coastguard Worker IntCmpType::U32 => 0_u32,
1737*61046927SAndroid Build Coastguard Worker IntCmpType::I32 => 1_u32,
1738*61046927SAndroid Build Coastguard Worker },
1739*61046927SAndroid Build Coastguard Worker );
1740*61046927SAndroid Build Coastguard Worker e.set_pred_set_op(74..76, self.set_op);
1741*61046927SAndroid Build Coastguard Worker e.set_int_cmp_op(76..79, self.cmp_op);
1742*61046927SAndroid Build Coastguard Worker
1743*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.dst);
1744*61046927SAndroid Build Coastguard Worker e.set_pred_dst(84..87, Dst::None); // dst1
1745*61046927SAndroid Build Coastguard Worker }
1746*61046927SAndroid Build Coastguard Worker }
1747*61046927SAndroid Build Coastguard Worker
src_as_lop_imm(src: &Src) -> Option<bool>1748*61046927SAndroid Build Coastguard Worker fn src_as_lop_imm(src: &Src) -> Option<bool> {
1749*61046927SAndroid Build Coastguard Worker let x = match src.src_ref {
1750*61046927SAndroid Build Coastguard Worker SrcRef::Zero => false,
1751*61046927SAndroid Build Coastguard Worker SrcRef::True => true,
1752*61046927SAndroid Build Coastguard Worker SrcRef::False => false,
1753*61046927SAndroid Build Coastguard Worker SrcRef::Imm32(i) => {
1754*61046927SAndroid Build Coastguard Worker if i == 0 {
1755*61046927SAndroid Build Coastguard Worker false
1756*61046927SAndroid Build Coastguard Worker } else if i == !0 {
1757*61046927SAndroid Build Coastguard Worker true
1758*61046927SAndroid Build Coastguard Worker } else {
1759*61046927SAndroid Build Coastguard Worker return None;
1760*61046927SAndroid Build Coastguard Worker }
1761*61046927SAndroid Build Coastguard Worker }
1762*61046927SAndroid Build Coastguard Worker _ => return None,
1763*61046927SAndroid Build Coastguard Worker };
1764*61046927SAndroid Build Coastguard Worker Some(x ^ src.src_mod.is_bnot())
1765*61046927SAndroid Build Coastguard Worker }
1766*61046927SAndroid Build Coastguard Worker
fold_lop_src(src: &Src, x: &mut u8)1767*61046927SAndroid Build Coastguard Worker fn fold_lop_src(src: &Src, x: &mut u8) {
1768*61046927SAndroid Build Coastguard Worker if let Some(i) = src_as_lop_imm(src) {
1769*61046927SAndroid Build Coastguard Worker *x = if i { !0 } else { 0 };
1770*61046927SAndroid Build Coastguard Worker }
1771*61046927SAndroid Build Coastguard Worker if src.src_mod.is_bnot() {
1772*61046927SAndroid Build Coastguard Worker *x = !*x;
1773*61046927SAndroid Build Coastguard Worker }
1774*61046927SAndroid Build Coastguard Worker }
1775*61046927SAndroid Build Coastguard Worker
1776*61046927SAndroid Build Coastguard Worker impl SM70Op for OpLop3 {
legalize(&mut self, b: &mut LegalizeBuilder)1777*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1778*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1779*61046927SAndroid Build Coastguard Worker // Fold constants and modifiers if we can
1780*61046927SAndroid Build Coastguard Worker self.op = LogicOp3::new_lut(&|mut x, mut y, mut z| {
1781*61046927SAndroid Build Coastguard Worker fold_lop_src(&self.srcs[0], &mut x);
1782*61046927SAndroid Build Coastguard Worker fold_lop_src(&self.srcs[1], &mut y);
1783*61046927SAndroid Build Coastguard Worker fold_lop_src(&self.srcs[2], &mut z);
1784*61046927SAndroid Build Coastguard Worker self.op.eval(x, y, z)
1785*61046927SAndroid Build Coastguard Worker });
1786*61046927SAndroid Build Coastguard Worker for src in &mut self.srcs {
1787*61046927SAndroid Build Coastguard Worker src.src_mod = SrcMod::None;
1788*61046927SAndroid Build Coastguard Worker if src_as_lop_imm(src).is_some() {
1789*61046927SAndroid Build Coastguard Worker src.src_ref = SrcRef::Zero;
1790*61046927SAndroid Build Coastguard Worker }
1791*61046927SAndroid Build Coastguard Worker }
1792*61046927SAndroid Build Coastguard Worker
1793*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
1794*61046927SAndroid Build Coastguard Worker if !src_is_reg(src0, gpr) && src_is_reg(src1, gpr) {
1795*61046927SAndroid Build Coastguard Worker std::mem::swap(src0, src1);
1796*61046927SAndroid Build Coastguard Worker self.op = LogicOp3::new_lut(&|x, y, z| self.op.eval(y, x, z))
1797*61046927SAndroid Build Coastguard Worker }
1798*61046927SAndroid Build Coastguard Worker if !src_is_reg(src2, gpr) && src_is_reg(src1, gpr) {
1799*61046927SAndroid Build Coastguard Worker std::mem::swap(src2, src1);
1800*61046927SAndroid Build Coastguard Worker self.op = LogicOp3::new_lut(&|x, y, z| self.op.eval(x, z, y))
1801*61046927SAndroid Build Coastguard Worker }
1802*61046927SAndroid Build Coastguard Worker
1803*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::ALU);
1804*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src2, gpr, SrcType::ALU);
1805*61046927SAndroid Build Coastguard Worker }
1806*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1807*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1808*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1809*61046927SAndroid Build Coastguard Worker e.encode_ualu(
1810*61046927SAndroid Build Coastguard Worker 0x092,
1811*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1812*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1813*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1814*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1815*61046927SAndroid Build Coastguard Worker );
1816*61046927SAndroid Build Coastguard Worker
1817*61046927SAndroid Build Coastguard Worker e.set_upred_src(87..90, 90, SrcRef::False.into());
1818*61046927SAndroid Build Coastguard Worker } else {
1819*61046927SAndroid Build Coastguard Worker e.encode_alu(
1820*61046927SAndroid Build Coastguard Worker 0x012,
1821*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1822*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1823*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1824*61046927SAndroid Build Coastguard Worker Some(&self.srcs[2]),
1825*61046927SAndroid Build Coastguard Worker );
1826*61046927SAndroid Build Coastguard Worker
1827*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, SrcRef::False.into());
1828*61046927SAndroid Build Coastguard Worker }
1829*61046927SAndroid Build Coastguard Worker
1830*61046927SAndroid Build Coastguard Worker e.set_field(72..80, self.op.lut);
1831*61046927SAndroid Build Coastguard Worker e.set_bit(80, false); // .PAND
1832*61046927SAndroid Build Coastguard Worker e.set_field(81..84, 7_u32); // pred
1833*61046927SAndroid Build Coastguard Worker }
1834*61046927SAndroid Build Coastguard Worker }
1835*61046927SAndroid Build Coastguard Worker
1836*61046927SAndroid Build Coastguard Worker impl SM70Op for OpPopC {
legalize(&mut self, _b: &mut LegalizeBuilder)1837*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1838*61046927SAndroid Build Coastguard Worker // Nothing to do
1839*61046927SAndroid Build Coastguard Worker }
1840*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1841*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1842*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1843*61046927SAndroid Build Coastguard Worker e.encode_ualu(0x0bf, Some(&self.dst), None, Some(&self.src), None)
1844*61046927SAndroid Build Coastguard Worker } else {
1845*61046927SAndroid Build Coastguard Worker e.encode_alu(0x109, Some(&self.dst), None, Some(&self.src), None)
1846*61046927SAndroid Build Coastguard Worker };
1847*61046927SAndroid Build Coastguard Worker
1848*61046927SAndroid Build Coastguard Worker let not_mod = matches!(self.src.src_mod, SrcMod::BNot);
1849*61046927SAndroid Build Coastguard Worker e.set_field(63..64, not_mod);
1850*61046927SAndroid Build Coastguard Worker }
1851*61046927SAndroid Build Coastguard Worker }
1852*61046927SAndroid Build Coastguard Worker
1853*61046927SAndroid Build Coastguard Worker impl SM70Op for OpShf {
legalize(&mut self, b: &mut LegalizeBuilder)1854*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1855*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1856*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(&mut self.low, gpr, SrcType::ALU);
1857*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_both_not_reg(
1858*61046927SAndroid Build Coastguard Worker &self.shift,
1859*61046927SAndroid Build Coastguard Worker &mut self.high,
1860*61046927SAndroid Build Coastguard Worker gpr,
1861*61046927SAndroid Build Coastguard Worker SrcType::ALU,
1862*61046927SAndroid Build Coastguard Worker );
1863*61046927SAndroid Build Coastguard Worker }
1864*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1865*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1866*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
1867*61046927SAndroid Build Coastguard Worker e.encode_ualu(
1868*61046927SAndroid Build Coastguard Worker 0x099,
1869*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1870*61046927SAndroid Build Coastguard Worker Some(&self.low),
1871*61046927SAndroid Build Coastguard Worker Some(&self.shift),
1872*61046927SAndroid Build Coastguard Worker Some(&self.high),
1873*61046927SAndroid Build Coastguard Worker )
1874*61046927SAndroid Build Coastguard Worker } else {
1875*61046927SAndroid Build Coastguard Worker e.encode_alu(
1876*61046927SAndroid Build Coastguard Worker 0x019,
1877*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1878*61046927SAndroid Build Coastguard Worker Some(&self.low),
1879*61046927SAndroid Build Coastguard Worker Some(&self.shift),
1880*61046927SAndroid Build Coastguard Worker Some(&self.high),
1881*61046927SAndroid Build Coastguard Worker )
1882*61046927SAndroid Build Coastguard Worker };
1883*61046927SAndroid Build Coastguard Worker
1884*61046927SAndroid Build Coastguard Worker e.set_field(
1885*61046927SAndroid Build Coastguard Worker 73..75,
1886*61046927SAndroid Build Coastguard Worker match self.data_type {
1887*61046927SAndroid Build Coastguard Worker IntType::I64 => 0_u8,
1888*61046927SAndroid Build Coastguard Worker IntType::U64 => 1_u8,
1889*61046927SAndroid Build Coastguard Worker IntType::I32 => 2_u8,
1890*61046927SAndroid Build Coastguard Worker IntType::U32 => 3_u8,
1891*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid shift data type"),
1892*61046927SAndroid Build Coastguard Worker },
1893*61046927SAndroid Build Coastguard Worker );
1894*61046927SAndroid Build Coastguard Worker e.set_bit(75, self.wrap);
1895*61046927SAndroid Build Coastguard Worker e.set_bit(76, self.right);
1896*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.dst_high);
1897*61046927SAndroid Build Coastguard Worker }
1898*61046927SAndroid Build Coastguard Worker }
1899*61046927SAndroid Build Coastguard Worker
1900*61046927SAndroid Build Coastguard Worker impl SM70Op for OpF2F {
legalize(&mut self, _b: &mut LegalizeBuilder)1901*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1902*61046927SAndroid Build Coastguard Worker // Nothing to do
1903*61046927SAndroid Build Coastguard Worker }
1904*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1905*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1906*61046927SAndroid Build Coastguard Worker assert!(!self.integer_rnd);
1907*61046927SAndroid Build Coastguard Worker if self.src_type.bits() <= 32 && self.dst_type.bits() <= 32 {
1908*61046927SAndroid Build Coastguard Worker e.encode_alu(0x104, Some(&self.dst), None, Some(&self.src), None)
1909*61046927SAndroid Build Coastguard Worker } else {
1910*61046927SAndroid Build Coastguard Worker e.encode_alu(0x110, Some(&self.dst), None, Some(&self.src), None)
1911*61046927SAndroid Build Coastguard Worker };
1912*61046927SAndroid Build Coastguard Worker
1913*61046927SAndroid Build Coastguard Worker if self.high {
1914*61046927SAndroid Build Coastguard Worker e.set_field(60..62, 1_u8); // .H1
1915*61046927SAndroid Build Coastguard Worker }
1916*61046927SAndroid Build Coastguard Worker
1917*61046927SAndroid Build Coastguard Worker e.set_field(75..77, (self.dst_type.bits() / 8).ilog2());
1918*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
1919*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
1920*61046927SAndroid Build Coastguard Worker e.set_field(84..86, (self.src_type.bits() / 8).ilog2());
1921*61046927SAndroid Build Coastguard Worker }
1922*61046927SAndroid Build Coastguard Worker }
1923*61046927SAndroid Build Coastguard Worker
1924*61046927SAndroid Build Coastguard Worker impl SM70Op for OpF2FP {
legalize(&mut self, b: &mut LegalizeBuilder)1925*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
1926*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
1927*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
1928*61046927SAndroid Build Coastguard Worker swap_srcs_if_not_reg(src0, src1, gpr);
1929*61046927SAndroid Build Coastguard Worker
1930*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::ALU);
1931*61046927SAndroid Build Coastguard Worker }
1932*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1933*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1934*61046927SAndroid Build Coastguard Worker e.encode_alu(
1935*61046927SAndroid Build Coastguard Worker 0x03e,
1936*61046927SAndroid Build Coastguard Worker Some(&self.dst),
1937*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
1938*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
1939*61046927SAndroid Build Coastguard Worker Some(&Src::new_zero()),
1940*61046927SAndroid Build Coastguard Worker );
1941*61046927SAndroid Build Coastguard Worker
1942*61046927SAndroid Build Coastguard Worker // .MERGE_C behavior
1943*61046927SAndroid Build Coastguard Worker // Use src1 and src2, src0 is unused
1944*61046927SAndroid Build Coastguard Worker // src1 get converted and packed in the lower 16 bits of dest.
1945*61046927SAndroid Build Coastguard Worker // src2 lower or high 16 bits (decided by .H1 flag) get packed in the upper of dest.
1946*61046927SAndroid Build Coastguard Worker e.set_bit(78, false); // TODO: .MERGE_C
1947*61046927SAndroid Build Coastguard Worker e.set_bit(72, false); // .H1 (MERGE_C only)
1948*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(79..81, self.rnd_mode);
1949*61046927SAndroid Build Coastguard Worker }
1950*61046927SAndroid Build Coastguard Worker }
1951*61046927SAndroid Build Coastguard Worker
1952*61046927SAndroid Build Coastguard Worker impl SM70Op for OpF2I {
legalize(&mut self, _b: &mut LegalizeBuilder)1953*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1954*61046927SAndroid Build Coastguard Worker // Nothing to do
1955*61046927SAndroid Build Coastguard Worker }
1956*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1957*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1958*61046927SAndroid Build Coastguard Worker if self.src_type.bits() <= 32 && self.dst_type.bits() <= 32 {
1959*61046927SAndroid Build Coastguard Worker e.encode_alu(0x105, Some(&self.dst), None, Some(&self.src), None)
1960*61046927SAndroid Build Coastguard Worker } else {
1961*61046927SAndroid Build Coastguard Worker e.encode_alu(0x111, Some(&self.dst), None, Some(&self.src), None)
1962*61046927SAndroid Build Coastguard Worker };
1963*61046927SAndroid Build Coastguard Worker
1964*61046927SAndroid Build Coastguard Worker e.set_bit(72, self.dst_type.is_signed());
1965*61046927SAndroid Build Coastguard Worker e.set_field(75..77, (self.dst_type.bits() / 8).ilog2());
1966*61046927SAndroid Build Coastguard Worker e.set_bit(77, false); // NTZ
1967*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
1968*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
1969*61046927SAndroid Build Coastguard Worker e.set_field(84..86, (self.src_type.bits() / 8).ilog2());
1970*61046927SAndroid Build Coastguard Worker }
1971*61046927SAndroid Build Coastguard Worker }
1972*61046927SAndroid Build Coastguard Worker
1973*61046927SAndroid Build Coastguard Worker impl SM70Op for OpI2F {
legalize(&mut self, _b: &mut LegalizeBuilder)1974*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1975*61046927SAndroid Build Coastguard Worker // Nothing to do
1976*61046927SAndroid Build Coastguard Worker }
1977*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1978*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1979*61046927SAndroid Build Coastguard Worker if self.src_type.bits() <= 32 && self.dst_type.bits() <= 32 {
1980*61046927SAndroid Build Coastguard Worker e.encode_alu(0x106, Some(&self.dst), None, Some(&self.src), None)
1981*61046927SAndroid Build Coastguard Worker } else {
1982*61046927SAndroid Build Coastguard Worker e.encode_alu(0x112, Some(&self.dst), None, Some(&self.src), None)
1983*61046927SAndroid Build Coastguard Worker };
1984*61046927SAndroid Build Coastguard Worker
1985*61046927SAndroid Build Coastguard Worker e.set_field(60..62, 0_u8); // TODO: subop
1986*61046927SAndroid Build Coastguard Worker e.set_bit(74, self.src_type.is_signed());
1987*61046927SAndroid Build Coastguard Worker e.set_field(75..77, (self.dst_type.bits() / 8).ilog2());
1988*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
1989*61046927SAndroid Build Coastguard Worker e.set_field(84..86, (self.src_type.bits() / 8).ilog2());
1990*61046927SAndroid Build Coastguard Worker }
1991*61046927SAndroid Build Coastguard Worker }
1992*61046927SAndroid Build Coastguard Worker
1993*61046927SAndroid Build Coastguard Worker impl SM70Op for OpFRnd {
legalize(&mut self, _b: &mut LegalizeBuilder)1994*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1995*61046927SAndroid Build Coastguard Worker // Nothing to do
1996*61046927SAndroid Build Coastguard Worker }
1997*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)1998*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
1999*61046927SAndroid Build Coastguard Worker if self.src_type.bits() <= 32 && self.dst_type.bits() <= 32 {
2000*61046927SAndroid Build Coastguard Worker e.encode_alu(0x107, Some(&self.dst), None, Some(&self.src), None)
2001*61046927SAndroid Build Coastguard Worker } else {
2002*61046927SAndroid Build Coastguard Worker e.encode_alu(0x113, Some(&self.dst), None, Some(&self.src), None)
2003*61046927SAndroid Build Coastguard Worker };
2004*61046927SAndroid Build Coastguard Worker
2005*61046927SAndroid Build Coastguard Worker e.set_field(84..86, (self.src_type.bits() / 8).ilog2());
2006*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.ftz);
2007*61046927SAndroid Build Coastguard Worker e.set_rnd_mode(78..80, self.rnd_mode);
2008*61046927SAndroid Build Coastguard Worker e.set_field(75..77, (self.dst_type.bits() / 8).ilog2());
2009*61046927SAndroid Build Coastguard Worker }
2010*61046927SAndroid Build Coastguard Worker }
2011*61046927SAndroid Build Coastguard Worker
2012*61046927SAndroid Build Coastguard Worker impl SM70Op for OpMov {
legalize(&mut self, _b: &mut LegalizeBuilder)2013*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2014*61046927SAndroid Build Coastguard Worker // Nothing to do
2015*61046927SAndroid Build Coastguard Worker }
2016*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2017*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2018*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
2019*61046927SAndroid Build Coastguard Worker e.set_opcode(0xc82);
2020*61046927SAndroid Build Coastguard Worker e.set_udst(self.dst);
2021*61046927SAndroid Build Coastguard Worker
2022*61046927SAndroid Build Coastguard Worker // umov is encoded like a non-uniform ALU op
2023*61046927SAndroid Build Coastguard Worker let src = ALUSrc::from_src(Some(&self.src), true);
2024*61046927SAndroid Build Coastguard Worker let form: u8 = match &src {
2025*61046927SAndroid Build Coastguard Worker ALUSrc::Reg(reg) => {
2026*61046927SAndroid Build Coastguard Worker e.encode_alu_ureg(reg, false);
2027*61046927SAndroid Build Coastguard Worker 0x6 // form
2028*61046927SAndroid Build Coastguard Worker }
2029*61046927SAndroid Build Coastguard Worker ALUSrc::Imm32(imm) => {
2030*61046927SAndroid Build Coastguard Worker e.encode_alu_imm(imm);
2031*61046927SAndroid Build Coastguard Worker 0x4 // form
2032*61046927SAndroid Build Coastguard Worker }
2033*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid umov src"),
2034*61046927SAndroid Build Coastguard Worker };
2035*61046927SAndroid Build Coastguard Worker e.set_field(9..12, form);
2036*61046927SAndroid Build Coastguard Worker } else {
2037*61046927SAndroid Build Coastguard Worker e.encode_alu(0x002, Some(&self.dst), None, Some(&self.src), None);
2038*61046927SAndroid Build Coastguard Worker e.set_field(72..76, self.quad_lanes);
2039*61046927SAndroid Build Coastguard Worker }
2040*61046927SAndroid Build Coastguard Worker }
2041*61046927SAndroid Build Coastguard Worker }
2042*61046927SAndroid Build Coastguard Worker
2043*61046927SAndroid Build Coastguard Worker impl SM70Op for OpPrmt {
legalize(&mut self, b: &mut LegalizeBuilder)2044*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2045*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
2046*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
2047*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::ALU);
2048*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src1, gpr, SrcType::ALU);
2049*61046927SAndroid Build Coastguard Worker }
2050*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2051*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2052*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
2053*61046927SAndroid Build Coastguard Worker e.encode_ualu(
2054*61046927SAndroid Build Coastguard Worker 0x96,
2055*61046927SAndroid Build Coastguard Worker Some(&self.dst),
2056*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
2057*61046927SAndroid Build Coastguard Worker Some(&self.sel),
2058*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
2059*61046927SAndroid Build Coastguard Worker )
2060*61046927SAndroid Build Coastguard Worker } else {
2061*61046927SAndroid Build Coastguard Worker e.encode_alu(
2062*61046927SAndroid Build Coastguard Worker 0x16,
2063*61046927SAndroid Build Coastguard Worker Some(&self.dst),
2064*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
2065*61046927SAndroid Build Coastguard Worker Some(&self.sel),
2066*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
2067*61046927SAndroid Build Coastguard Worker )
2068*61046927SAndroid Build Coastguard Worker };
2069*61046927SAndroid Build Coastguard Worker
2070*61046927SAndroid Build Coastguard Worker e.set_field(
2071*61046927SAndroid Build Coastguard Worker 72..75,
2072*61046927SAndroid Build Coastguard Worker match self.mode {
2073*61046927SAndroid Build Coastguard Worker PrmtMode::Index => 0_u8,
2074*61046927SAndroid Build Coastguard Worker PrmtMode::Forward4Extract => 1_u8,
2075*61046927SAndroid Build Coastguard Worker PrmtMode::Backward4Extract => 2_u8,
2076*61046927SAndroid Build Coastguard Worker PrmtMode::Replicate8 => 3_u8,
2077*61046927SAndroid Build Coastguard Worker PrmtMode::EdgeClampLeft => 4_u8,
2078*61046927SAndroid Build Coastguard Worker PrmtMode::EdgeClampRight => 5_u8,
2079*61046927SAndroid Build Coastguard Worker PrmtMode::Replicate16 => 6_u8,
2080*61046927SAndroid Build Coastguard Worker },
2081*61046927SAndroid Build Coastguard Worker );
2082*61046927SAndroid Build Coastguard Worker }
2083*61046927SAndroid Build Coastguard Worker }
2084*61046927SAndroid Build Coastguard Worker
2085*61046927SAndroid Build Coastguard Worker impl SM70Op for OpSel {
legalize(&mut self, b: &mut LegalizeBuilder)2086*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2087*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
2088*61046927SAndroid Build Coastguard Worker if !self.is_uniform() {
2089*61046927SAndroid Build Coastguard Worker b.copy_src_if_upred(&mut self.cond);
2090*61046927SAndroid Build Coastguard Worker }
2091*61046927SAndroid Build Coastguard Worker let [src0, src1] = &mut self.srcs;
2092*61046927SAndroid Build Coastguard Worker if swap_srcs_if_not_reg(src0, src1, gpr) {
2093*61046927SAndroid Build Coastguard Worker self.cond = self.cond.bnot();
2094*61046927SAndroid Build Coastguard Worker }
2095*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(src0, gpr, SrcType::ALU);
2096*61046927SAndroid Build Coastguard Worker }
2097*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2098*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2099*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
2100*61046927SAndroid Build Coastguard Worker e.encode_ualu(
2101*61046927SAndroid Build Coastguard Worker 0x087,
2102*61046927SAndroid Build Coastguard Worker Some(&self.dst),
2103*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
2104*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
2105*61046927SAndroid Build Coastguard Worker None,
2106*61046927SAndroid Build Coastguard Worker );
2107*61046927SAndroid Build Coastguard Worker
2108*61046927SAndroid Build Coastguard Worker e.set_upred_src(87..90, 90, self.cond);
2109*61046927SAndroid Build Coastguard Worker } else {
2110*61046927SAndroid Build Coastguard Worker e.encode_alu(
2111*61046927SAndroid Build Coastguard Worker 0x007,
2112*61046927SAndroid Build Coastguard Worker Some(&self.dst),
2113*61046927SAndroid Build Coastguard Worker Some(&self.srcs[0]),
2114*61046927SAndroid Build Coastguard Worker Some(&self.srcs[1]),
2115*61046927SAndroid Build Coastguard Worker None,
2116*61046927SAndroid Build Coastguard Worker );
2117*61046927SAndroid Build Coastguard Worker
2118*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.cond);
2119*61046927SAndroid Build Coastguard Worker }
2120*61046927SAndroid Build Coastguard Worker }
2121*61046927SAndroid Build Coastguard Worker }
2122*61046927SAndroid Build Coastguard Worker
2123*61046927SAndroid Build Coastguard Worker impl SM70Op for OpShfl {
legalize(&mut self, b: &mut LegalizeBuilder)2124*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2125*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
2126*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(&mut self.src, gpr, SrcType::GPR);
2127*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg_or_imm(&mut self.lane, gpr, SrcType::ALU);
2128*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg_or_imm(&mut self.c, gpr, SrcType::ALU);
2129*61046927SAndroid Build Coastguard Worker }
2130*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2131*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2132*61046927SAndroid Build Coastguard Worker assert!(self.lane.src_mod.is_none());
2133*61046927SAndroid Build Coastguard Worker assert!(self.c.src_mod.is_none());
2134*61046927SAndroid Build Coastguard Worker
2135*61046927SAndroid Build Coastguard Worker match &self.lane.src_ref {
2136*61046927SAndroid Build Coastguard Worker SrcRef::Zero | SrcRef::Reg(_) => match &self.c.src_ref {
2137*61046927SAndroid Build Coastguard Worker SrcRef::Zero | SrcRef::Reg(_) => {
2138*61046927SAndroid Build Coastguard Worker e.set_opcode(0x389);
2139*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.lane);
2140*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.c);
2141*61046927SAndroid Build Coastguard Worker }
2142*61046927SAndroid Build Coastguard Worker SrcRef::Imm32(imm_c) => {
2143*61046927SAndroid Build Coastguard Worker e.set_opcode(0x589);
2144*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.lane);
2145*61046927SAndroid Build Coastguard Worker e.set_field(40..53, *imm_c & 0x1f1f);
2146*61046927SAndroid Build Coastguard Worker }
2147*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid instruction form"),
2148*61046927SAndroid Build Coastguard Worker },
2149*61046927SAndroid Build Coastguard Worker SrcRef::Imm32(imm_lane) => match &self.c.src_ref {
2150*61046927SAndroid Build Coastguard Worker SrcRef::Zero | SrcRef::Reg(_) => {
2151*61046927SAndroid Build Coastguard Worker e.set_opcode(0x989);
2152*61046927SAndroid Build Coastguard Worker e.set_field(53..58, *imm_lane & 0x1f);
2153*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.c);
2154*61046927SAndroid Build Coastguard Worker }
2155*61046927SAndroid Build Coastguard Worker SrcRef::Imm32(imm_c) => {
2156*61046927SAndroid Build Coastguard Worker e.set_opcode(0xf89);
2157*61046927SAndroid Build Coastguard Worker e.set_field(40..53, *imm_c & 0x1f1f);
2158*61046927SAndroid Build Coastguard Worker e.set_field(53..58, *imm_lane & 0x1f);
2159*61046927SAndroid Build Coastguard Worker }
2160*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid instruction form"),
2161*61046927SAndroid Build Coastguard Worker },
2162*61046927SAndroid Build Coastguard Worker _ => panic!("Invalid instruction form"),
2163*61046927SAndroid Build Coastguard Worker };
2164*61046927SAndroid Build Coastguard Worker
2165*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2166*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.in_bounds);
2167*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.src);
2168*61046927SAndroid Build Coastguard Worker e.set_field(
2169*61046927SAndroid Build Coastguard Worker 58..60,
2170*61046927SAndroid Build Coastguard Worker match self.op {
2171*61046927SAndroid Build Coastguard Worker ShflOp::Idx => 0_u8,
2172*61046927SAndroid Build Coastguard Worker ShflOp::Up => 1_u8,
2173*61046927SAndroid Build Coastguard Worker ShflOp::Down => 2_u8,
2174*61046927SAndroid Build Coastguard Worker ShflOp::Bfly => 3_u8,
2175*61046927SAndroid Build Coastguard Worker },
2176*61046927SAndroid Build Coastguard Worker );
2177*61046927SAndroid Build Coastguard Worker }
2178*61046927SAndroid Build Coastguard Worker }
2179*61046927SAndroid Build Coastguard Worker
2180*61046927SAndroid Build Coastguard Worker impl SM70Op for OpPLop3 {
legalize(&mut self, b: &mut LegalizeBuilder)2181*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2182*61046927SAndroid Build Coastguard Worker // Fold constants and modifiers if we can
2183*61046927SAndroid Build Coastguard Worker for lop in &mut self.ops {
2184*61046927SAndroid Build Coastguard Worker *lop = LogicOp3::new_lut(&|mut x, mut y, mut z| {
2185*61046927SAndroid Build Coastguard Worker fold_lop_src(&self.srcs[0], &mut x);
2186*61046927SAndroid Build Coastguard Worker fold_lop_src(&self.srcs[1], &mut y);
2187*61046927SAndroid Build Coastguard Worker fold_lop_src(&self.srcs[2], &mut z);
2188*61046927SAndroid Build Coastguard Worker lop.eval(x, y, z)
2189*61046927SAndroid Build Coastguard Worker });
2190*61046927SAndroid Build Coastguard Worker }
2191*61046927SAndroid Build Coastguard Worker for src in &mut self.srcs {
2192*61046927SAndroid Build Coastguard Worker src.src_mod = SrcMod::None;
2193*61046927SAndroid Build Coastguard Worker if src_as_lop_imm(src).is_some() {
2194*61046927SAndroid Build Coastguard Worker src.src_ref = SrcRef::True;
2195*61046927SAndroid Build Coastguard Worker }
2196*61046927SAndroid Build Coastguard Worker }
2197*61046927SAndroid Build Coastguard Worker
2198*61046927SAndroid Build Coastguard Worker if !self.is_uniform() {
2199*61046927SAndroid Build Coastguard Worker // The warp form of plop3 allows a single uniform predicate in
2200*61046927SAndroid Build Coastguard Worker // src2. If we have a uniform predicate anywhere, try to move it
2201*61046927SAndroid Build Coastguard Worker // there.
2202*61046927SAndroid Build Coastguard Worker let [src0, src1, src2] = &mut self.srcs;
2203*61046927SAndroid Build Coastguard Worker if src_is_upred_reg(src0) && !src_is_upred_reg(src2) {
2204*61046927SAndroid Build Coastguard Worker std::mem::swap(src0, src2);
2205*61046927SAndroid Build Coastguard Worker for lop in &mut self.ops {
2206*61046927SAndroid Build Coastguard Worker *lop = LogicOp3::new_lut(&|x, y, z| lop.eval(z, y, x))
2207*61046927SAndroid Build Coastguard Worker }
2208*61046927SAndroid Build Coastguard Worker }
2209*61046927SAndroid Build Coastguard Worker if src_is_upred_reg(src1) && !src_is_upred_reg(src2) {
2210*61046927SAndroid Build Coastguard Worker std::mem::swap(src1, src2);
2211*61046927SAndroid Build Coastguard Worker for lop in &mut self.ops {
2212*61046927SAndroid Build Coastguard Worker *lop = LogicOp3::new_lut(&|x, y, z| lop.eval(x, z, y))
2213*61046927SAndroid Build Coastguard Worker }
2214*61046927SAndroid Build Coastguard Worker }
2215*61046927SAndroid Build Coastguard Worker b.copy_src_if_upred(src0);
2216*61046927SAndroid Build Coastguard Worker b.copy_src_if_upred(src1);
2217*61046927SAndroid Build Coastguard Worker }
2218*61046927SAndroid Build Coastguard Worker }
2219*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2220*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2221*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
2222*61046927SAndroid Build Coastguard Worker e.set_opcode(0x89c);
2223*61046927SAndroid Build Coastguard Worker
2224*61046927SAndroid Build Coastguard Worker e.set_upred_src(68..71, 71, self.srcs[2]);
2225*61046927SAndroid Build Coastguard Worker e.set_upred_src(77..80, 80, self.srcs[1]);
2226*61046927SAndroid Build Coastguard Worker e.set_upred_src(87..90, 90, self.srcs[0]);
2227*61046927SAndroid Build Coastguard Worker } else {
2228*61046927SAndroid Build Coastguard Worker e.set_opcode(0x81c);
2229*61046927SAndroid Build Coastguard Worker
2230*61046927SAndroid Build Coastguard Worker if self.srcs[2]
2231*61046927SAndroid Build Coastguard Worker .src_ref
2232*61046927SAndroid Build Coastguard Worker .as_reg()
2233*61046927SAndroid Build Coastguard Worker .is_some_and(|r| r.is_uniform())
2234*61046927SAndroid Build Coastguard Worker {
2235*61046927SAndroid Build Coastguard Worker e.set_upred_src(68..71, 71, self.srcs[2]);
2236*61046927SAndroid Build Coastguard Worker e.set_bit(67, true);
2237*61046927SAndroid Build Coastguard Worker } else {
2238*61046927SAndroid Build Coastguard Worker e.set_pred_src(68..71, 71, self.srcs[2]);
2239*61046927SAndroid Build Coastguard Worker }
2240*61046927SAndroid Build Coastguard Worker e.set_pred_src(77..80, 80, self.srcs[1]);
2241*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.srcs[0]);
2242*61046927SAndroid Build Coastguard Worker }
2243*61046927SAndroid Build Coastguard Worker e.set_field(16..24, self.ops[1].lut);
2244*61046927SAndroid Build Coastguard Worker e.set_field(64..67, self.ops[0].lut & 0x7);
2245*61046927SAndroid Build Coastguard Worker e.set_field(72..77, self.ops[0].lut >> 3);
2246*61046927SAndroid Build Coastguard Worker
2247*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.dsts[0]);
2248*61046927SAndroid Build Coastguard Worker e.set_pred_dst(84..87, self.dsts[1]);
2249*61046927SAndroid Build Coastguard Worker }
2250*61046927SAndroid Build Coastguard Worker }
2251*61046927SAndroid Build Coastguard Worker
2252*61046927SAndroid Build Coastguard Worker impl SM70Op for OpR2UR {
legalize(&mut self, _b: &mut LegalizeBuilder)2253*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2254*61046927SAndroid Build Coastguard Worker // Nothing to do
2255*61046927SAndroid Build Coastguard Worker }
2256*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2257*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2258*61046927SAndroid Build Coastguard Worker e.set_opcode(0x3c2);
2259*61046927SAndroid Build Coastguard Worker e.set_udst(self.dst);
2260*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.src);
2261*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, Dst::None);
2262*61046927SAndroid Build Coastguard Worker }
2263*61046927SAndroid Build Coastguard Worker }
2264*61046927SAndroid Build Coastguard Worker
2265*61046927SAndroid Build Coastguard Worker impl SM70Encoder<'_> {
set_tex_dim(&mut self, range: Range<usize>, dim: TexDim)2266*61046927SAndroid Build Coastguard Worker fn set_tex_dim(&mut self, range: Range<usize>, dim: TexDim) {
2267*61046927SAndroid Build Coastguard Worker assert!(range.len() == 3);
2268*61046927SAndroid Build Coastguard Worker self.set_field(
2269*61046927SAndroid Build Coastguard Worker range,
2270*61046927SAndroid Build Coastguard Worker match dim {
2271*61046927SAndroid Build Coastguard Worker TexDim::_1D => 0_u8,
2272*61046927SAndroid Build Coastguard Worker TexDim::Array1D => 4_u8,
2273*61046927SAndroid Build Coastguard Worker TexDim::_2D => 1_u8,
2274*61046927SAndroid Build Coastguard Worker TexDim::Array2D => 5_u8,
2275*61046927SAndroid Build Coastguard Worker TexDim::_3D => 2_u8,
2276*61046927SAndroid Build Coastguard Worker TexDim::Cube => 3_u8,
2277*61046927SAndroid Build Coastguard Worker TexDim::ArrayCube => 7_u8,
2278*61046927SAndroid Build Coastguard Worker },
2279*61046927SAndroid Build Coastguard Worker );
2280*61046927SAndroid Build Coastguard Worker }
2281*61046927SAndroid Build Coastguard Worker
set_tex_lod_mode(&mut self, range: Range<usize>, lod_mode: TexLodMode)2282*61046927SAndroid Build Coastguard Worker fn set_tex_lod_mode(&mut self, range: Range<usize>, lod_mode: TexLodMode) {
2283*61046927SAndroid Build Coastguard Worker assert!(range.len() == 3);
2284*61046927SAndroid Build Coastguard Worker self.set_field(
2285*61046927SAndroid Build Coastguard Worker range,
2286*61046927SAndroid Build Coastguard Worker match lod_mode {
2287*61046927SAndroid Build Coastguard Worker TexLodMode::Auto => 0_u8,
2288*61046927SAndroid Build Coastguard Worker TexLodMode::Zero => 1_u8,
2289*61046927SAndroid Build Coastguard Worker TexLodMode::Bias => 2_u8,
2290*61046927SAndroid Build Coastguard Worker TexLodMode::Lod => 3_u8,
2291*61046927SAndroid Build Coastguard Worker TexLodMode::Clamp => 4_u8,
2292*61046927SAndroid Build Coastguard Worker TexLodMode::BiasClamp => 5_u8,
2293*61046927SAndroid Build Coastguard Worker },
2294*61046927SAndroid Build Coastguard Worker );
2295*61046927SAndroid Build Coastguard Worker }
2296*61046927SAndroid Build Coastguard Worker
set_image_dim(&mut self, range: Range<usize>, dim: ImageDim)2297*61046927SAndroid Build Coastguard Worker fn set_image_dim(&mut self, range: Range<usize>, dim: ImageDim) {
2298*61046927SAndroid Build Coastguard Worker assert!(range.len() == 3);
2299*61046927SAndroid Build Coastguard Worker self.set_field(
2300*61046927SAndroid Build Coastguard Worker range,
2301*61046927SAndroid Build Coastguard Worker match dim {
2302*61046927SAndroid Build Coastguard Worker ImageDim::_1D => 0_u8,
2303*61046927SAndroid Build Coastguard Worker ImageDim::_1DBuffer => 1_u8,
2304*61046927SAndroid Build Coastguard Worker ImageDim::_1DArray => 2_u8,
2305*61046927SAndroid Build Coastguard Worker ImageDim::_2D => 3_u8,
2306*61046927SAndroid Build Coastguard Worker ImageDim::_2DArray => 4_u8,
2307*61046927SAndroid Build Coastguard Worker ImageDim::_3D => 5_u8,
2308*61046927SAndroid Build Coastguard Worker },
2309*61046927SAndroid Build Coastguard Worker );
2310*61046927SAndroid Build Coastguard Worker }
2311*61046927SAndroid Build Coastguard Worker }
2312*61046927SAndroid Build Coastguard Worker
2313*61046927SAndroid Build Coastguard Worker impl SM70Op for OpTex {
legalize(&mut self, b: &mut LegalizeBuilder)2314*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2315*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2316*61046927SAndroid Build Coastguard Worker }
2317*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2318*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2319*61046927SAndroid Build Coastguard Worker e.set_opcode(0x361);
2320*61046927SAndroid Build Coastguard Worker e.set_bit(59, true); // .B
2321*61046927SAndroid Build Coastguard Worker
2322*61046927SAndroid Build Coastguard Worker e.set_dst(self.dsts[0]);
2323*61046927SAndroid Build Coastguard Worker if let Dst::Reg(reg) = self.dsts[1] {
2324*61046927SAndroid Build Coastguard Worker e.set_reg(64..72, reg);
2325*61046927SAndroid Build Coastguard Worker } else {
2326*61046927SAndroid Build Coastguard Worker e.set_field(64..72, 255_u8);
2327*61046927SAndroid Build Coastguard Worker }
2328*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.fault);
2329*61046927SAndroid Build Coastguard Worker
2330*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.srcs[0]);
2331*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.srcs[1]);
2332*61046927SAndroid Build Coastguard Worker
2333*61046927SAndroid Build Coastguard Worker e.set_tex_dim(61..64, self.dim);
2334*61046927SAndroid Build Coastguard Worker e.set_field(72..76, self.mask);
2335*61046927SAndroid Build Coastguard Worker e.set_bit(76, self.offset);
2336*61046927SAndroid Build Coastguard Worker e.set_bit(77, false); // ToDo: NDV
2337*61046927SAndroid Build Coastguard Worker e.set_bit(78, self.z_cmpr);
2338*61046927SAndroid Build Coastguard Worker e.set_field(84..87, 1);
2339*61046927SAndroid Build Coastguard Worker e.set_tex_lod_mode(87..90, self.lod_mode);
2340*61046927SAndroid Build Coastguard Worker e.set_bit(90, false); // TODO: .NODEP
2341*61046927SAndroid Build Coastguard Worker }
2342*61046927SAndroid Build Coastguard Worker }
2343*61046927SAndroid Build Coastguard Worker
2344*61046927SAndroid Build Coastguard Worker impl SM70Op for OpTld {
legalize(&mut self, b: &mut LegalizeBuilder)2345*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2346*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2347*61046927SAndroid Build Coastguard Worker }
2348*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2349*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2350*61046927SAndroid Build Coastguard Worker e.set_opcode(0x367);
2351*61046927SAndroid Build Coastguard Worker e.set_bit(59, true); // .B
2352*61046927SAndroid Build Coastguard Worker
2353*61046927SAndroid Build Coastguard Worker e.set_dst(self.dsts[0]);
2354*61046927SAndroid Build Coastguard Worker if let Dst::Reg(reg) = self.dsts[1] {
2355*61046927SAndroid Build Coastguard Worker e.set_reg(64..72, reg);
2356*61046927SAndroid Build Coastguard Worker } else {
2357*61046927SAndroid Build Coastguard Worker e.set_field(64..72, 255_u8);
2358*61046927SAndroid Build Coastguard Worker }
2359*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.fault);
2360*61046927SAndroid Build Coastguard Worker
2361*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.srcs[0]);
2362*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.srcs[1]);
2363*61046927SAndroid Build Coastguard Worker
2364*61046927SAndroid Build Coastguard Worker e.set_tex_dim(61..64, self.dim);
2365*61046927SAndroid Build Coastguard Worker e.set_field(72..76, self.mask);
2366*61046927SAndroid Build Coastguard Worker e.set_bit(76, self.offset);
2367*61046927SAndroid Build Coastguard Worker // bit 77: .CL
2368*61046927SAndroid Build Coastguard Worker e.set_bit(78, self.is_ms);
2369*61046927SAndroid Build Coastguard Worker // bits 79..81: .F16
2370*61046927SAndroid Build Coastguard Worker assert!(
2371*61046927SAndroid Build Coastguard Worker self.lod_mode == TexLodMode::Zero
2372*61046927SAndroid Build Coastguard Worker || self.lod_mode == TexLodMode::Lod
2373*61046927SAndroid Build Coastguard Worker );
2374*61046927SAndroid Build Coastguard Worker e.set_tex_lod_mode(87..90, self.lod_mode);
2375*61046927SAndroid Build Coastguard Worker e.set_bit(90, false); // TODO: .NODEP
2376*61046927SAndroid Build Coastguard Worker }
2377*61046927SAndroid Build Coastguard Worker }
2378*61046927SAndroid Build Coastguard Worker
2379*61046927SAndroid Build Coastguard Worker impl SM70Op for OpTld4 {
legalize(&mut self, b: &mut LegalizeBuilder)2380*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2381*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2382*61046927SAndroid Build Coastguard Worker }
2383*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2384*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2385*61046927SAndroid Build Coastguard Worker e.set_opcode(0x364);
2386*61046927SAndroid Build Coastguard Worker e.set_bit(59, true); // .B
2387*61046927SAndroid Build Coastguard Worker
2388*61046927SAndroid Build Coastguard Worker e.set_dst(self.dsts[0]);
2389*61046927SAndroid Build Coastguard Worker if let Dst::Reg(reg) = self.dsts[1] {
2390*61046927SAndroid Build Coastguard Worker e.set_reg(64..72, reg);
2391*61046927SAndroid Build Coastguard Worker } else {
2392*61046927SAndroid Build Coastguard Worker e.set_field(64..72, 255_u8);
2393*61046927SAndroid Build Coastguard Worker }
2394*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.fault);
2395*61046927SAndroid Build Coastguard Worker
2396*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.srcs[0]);
2397*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.srcs[1]);
2398*61046927SAndroid Build Coastguard Worker
2399*61046927SAndroid Build Coastguard Worker e.set_tex_dim(61..64, self.dim);
2400*61046927SAndroid Build Coastguard Worker e.set_field(72..76, self.mask);
2401*61046927SAndroid Build Coastguard Worker e.set_field(
2402*61046927SAndroid Build Coastguard Worker 76..78,
2403*61046927SAndroid Build Coastguard Worker match self.offset_mode {
2404*61046927SAndroid Build Coastguard Worker Tld4OffsetMode::None => 0_u8,
2405*61046927SAndroid Build Coastguard Worker Tld4OffsetMode::AddOffI => 1_u8,
2406*61046927SAndroid Build Coastguard Worker Tld4OffsetMode::PerPx => 2_u8,
2407*61046927SAndroid Build Coastguard Worker },
2408*61046927SAndroid Build Coastguard Worker );
2409*61046927SAndroid Build Coastguard Worker // bit 77: .CL
2410*61046927SAndroid Build Coastguard Worker e.set_bit(78, self.z_cmpr);
2411*61046927SAndroid Build Coastguard Worker e.set_bit(84, true); // !.EF
2412*61046927SAndroid Build Coastguard Worker e.set_field(87..89, self.comp);
2413*61046927SAndroid Build Coastguard Worker e.set_bit(90, false); // TODO: .NODEP
2414*61046927SAndroid Build Coastguard Worker }
2415*61046927SAndroid Build Coastguard Worker }
2416*61046927SAndroid Build Coastguard Worker
2417*61046927SAndroid Build Coastguard Worker impl SM70Op for OpTmml {
legalize(&mut self, b: &mut LegalizeBuilder)2418*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2419*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2420*61046927SAndroid Build Coastguard Worker }
2421*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2422*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2423*61046927SAndroid Build Coastguard Worker e.set_opcode(0x36a);
2424*61046927SAndroid Build Coastguard Worker e.set_bit(59, true); // .B
2425*61046927SAndroid Build Coastguard Worker
2426*61046927SAndroid Build Coastguard Worker e.set_dst(self.dsts[0]);
2427*61046927SAndroid Build Coastguard Worker if let Dst::Reg(reg) = self.dsts[1] {
2428*61046927SAndroid Build Coastguard Worker e.set_reg(64..72, reg);
2429*61046927SAndroid Build Coastguard Worker } else {
2430*61046927SAndroid Build Coastguard Worker e.set_field(64..72, 255_u8);
2431*61046927SAndroid Build Coastguard Worker }
2432*61046927SAndroid Build Coastguard Worker
2433*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.srcs[0]);
2434*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.srcs[1]);
2435*61046927SAndroid Build Coastguard Worker
2436*61046927SAndroid Build Coastguard Worker e.set_tex_dim(61..64, self.dim);
2437*61046927SAndroid Build Coastguard Worker e.set_field(72..76, self.mask);
2438*61046927SAndroid Build Coastguard Worker e.set_bit(77, false); // ToDo: NDV
2439*61046927SAndroid Build Coastguard Worker e.set_bit(90, false); // TODO: .NODEP
2440*61046927SAndroid Build Coastguard Worker }
2441*61046927SAndroid Build Coastguard Worker }
2442*61046927SAndroid Build Coastguard Worker
2443*61046927SAndroid Build Coastguard Worker impl SM70Op for OpTxd {
legalize(&mut self, b: &mut LegalizeBuilder)2444*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2445*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2446*61046927SAndroid Build Coastguard Worker }
2447*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2448*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2449*61046927SAndroid Build Coastguard Worker e.set_opcode(0x36d);
2450*61046927SAndroid Build Coastguard Worker e.set_bit(59, true); // .B
2451*61046927SAndroid Build Coastguard Worker
2452*61046927SAndroid Build Coastguard Worker e.set_dst(self.dsts[0]);
2453*61046927SAndroid Build Coastguard Worker if let Dst::Reg(reg) = self.dsts[1] {
2454*61046927SAndroid Build Coastguard Worker e.set_reg(64..72, reg);
2455*61046927SAndroid Build Coastguard Worker } else {
2456*61046927SAndroid Build Coastguard Worker e.set_field(64..72, 255_u8);
2457*61046927SAndroid Build Coastguard Worker }
2458*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.fault);
2459*61046927SAndroid Build Coastguard Worker
2460*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.srcs[0]);
2461*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.srcs[1]);
2462*61046927SAndroid Build Coastguard Worker
2463*61046927SAndroid Build Coastguard Worker e.set_tex_dim(61..64, self.dim);
2464*61046927SAndroid Build Coastguard Worker e.set_field(72..76, self.mask);
2465*61046927SAndroid Build Coastguard Worker e.set_bit(76, self.offset);
2466*61046927SAndroid Build Coastguard Worker e.set_bit(77, false); // ToDo: NDV
2467*61046927SAndroid Build Coastguard Worker e.set_bit(90, false); // TODO: .NODEP
2468*61046927SAndroid Build Coastguard Worker }
2469*61046927SAndroid Build Coastguard Worker }
2470*61046927SAndroid Build Coastguard Worker
2471*61046927SAndroid Build Coastguard Worker impl SM70Op for OpTxq {
legalize(&mut self, b: &mut LegalizeBuilder)2472*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2473*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2474*61046927SAndroid Build Coastguard Worker }
2475*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2476*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2477*61046927SAndroid Build Coastguard Worker e.set_opcode(0x370);
2478*61046927SAndroid Build Coastguard Worker e.set_bit(59, true); // .B
2479*61046927SAndroid Build Coastguard Worker
2480*61046927SAndroid Build Coastguard Worker e.set_dst(self.dsts[0]);
2481*61046927SAndroid Build Coastguard Worker if let Dst::Reg(reg) = self.dsts[1] {
2482*61046927SAndroid Build Coastguard Worker e.set_reg(64..72, reg);
2483*61046927SAndroid Build Coastguard Worker } else {
2484*61046927SAndroid Build Coastguard Worker e.set_field(64..72, 255_u8);
2485*61046927SAndroid Build Coastguard Worker }
2486*61046927SAndroid Build Coastguard Worker
2487*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.src);
2488*61046927SAndroid Build Coastguard Worker e.set_field(
2489*61046927SAndroid Build Coastguard Worker 62..64,
2490*61046927SAndroid Build Coastguard Worker match self.query {
2491*61046927SAndroid Build Coastguard Worker TexQuery::Dimension => 0_u8,
2492*61046927SAndroid Build Coastguard Worker TexQuery::TextureType => 1_u8,
2493*61046927SAndroid Build Coastguard Worker TexQuery::SamplerPos => 2_u8,
2494*61046927SAndroid Build Coastguard Worker },
2495*61046927SAndroid Build Coastguard Worker );
2496*61046927SAndroid Build Coastguard Worker e.set_field(72..76, self.mask);
2497*61046927SAndroid Build Coastguard Worker }
2498*61046927SAndroid Build Coastguard Worker }
2499*61046927SAndroid Build Coastguard Worker
2500*61046927SAndroid Build Coastguard Worker impl SM70Encoder<'_> {
set_mem_order(&mut self, order: &MemOrder)2501*61046927SAndroid Build Coastguard Worker fn set_mem_order(&mut self, order: &MemOrder) {
2502*61046927SAndroid Build Coastguard Worker if self.sm.sm < 80 {
2503*61046927SAndroid Build Coastguard Worker let scope = match order {
2504*61046927SAndroid Build Coastguard Worker MemOrder::Constant => MemScope::System,
2505*61046927SAndroid Build Coastguard Worker MemOrder::Weak => MemScope::CTA,
2506*61046927SAndroid Build Coastguard Worker MemOrder::Strong(s) => *s,
2507*61046927SAndroid Build Coastguard Worker };
2508*61046927SAndroid Build Coastguard Worker self.set_field(
2509*61046927SAndroid Build Coastguard Worker 77..79,
2510*61046927SAndroid Build Coastguard Worker match scope {
2511*61046927SAndroid Build Coastguard Worker MemScope::CTA => 0_u8,
2512*61046927SAndroid Build Coastguard Worker // SM => 1_u8,
2513*61046927SAndroid Build Coastguard Worker MemScope::GPU => 2_u8,
2514*61046927SAndroid Build Coastguard Worker MemScope::System => 3_u8,
2515*61046927SAndroid Build Coastguard Worker },
2516*61046927SAndroid Build Coastguard Worker );
2517*61046927SAndroid Build Coastguard Worker self.set_field(
2518*61046927SAndroid Build Coastguard Worker 79..81,
2519*61046927SAndroid Build Coastguard Worker match order {
2520*61046927SAndroid Build Coastguard Worker MemOrder::Constant => 0_u8,
2521*61046927SAndroid Build Coastguard Worker MemOrder::Weak => 1_u8,
2522*61046927SAndroid Build Coastguard Worker MemOrder::Strong(_) => 2_u8,
2523*61046927SAndroid Build Coastguard Worker // MMIO => 3_u8,
2524*61046927SAndroid Build Coastguard Worker },
2525*61046927SAndroid Build Coastguard Worker );
2526*61046927SAndroid Build Coastguard Worker } else {
2527*61046927SAndroid Build Coastguard Worker self.set_field(
2528*61046927SAndroid Build Coastguard Worker 77..81,
2529*61046927SAndroid Build Coastguard Worker match order {
2530*61046927SAndroid Build Coastguard Worker MemOrder::Constant => 0x4_u8,
2531*61046927SAndroid Build Coastguard Worker MemOrder::Weak => 0x0_u8,
2532*61046927SAndroid Build Coastguard Worker MemOrder::Strong(MemScope::CTA) => 0x5_u8,
2533*61046927SAndroid Build Coastguard Worker MemOrder::Strong(MemScope::GPU) => 0x7_u8,
2534*61046927SAndroid Build Coastguard Worker MemOrder::Strong(MemScope::System) => 0xa_u8,
2535*61046927SAndroid Build Coastguard Worker },
2536*61046927SAndroid Build Coastguard Worker );
2537*61046927SAndroid Build Coastguard Worker }
2538*61046927SAndroid Build Coastguard Worker }
2539*61046927SAndroid Build Coastguard Worker
set_eviction_priority(&mut self, pri: &MemEvictionPriority)2540*61046927SAndroid Build Coastguard Worker fn set_eviction_priority(&mut self, pri: &MemEvictionPriority) {
2541*61046927SAndroid Build Coastguard Worker self.set_field(
2542*61046927SAndroid Build Coastguard Worker 84..86,
2543*61046927SAndroid Build Coastguard Worker match pri {
2544*61046927SAndroid Build Coastguard Worker MemEvictionPriority::First => 0_u8,
2545*61046927SAndroid Build Coastguard Worker MemEvictionPriority::Normal => 1_u8,
2546*61046927SAndroid Build Coastguard Worker MemEvictionPriority::Last => 2_u8,
2547*61046927SAndroid Build Coastguard Worker MemEvictionPriority::Unchanged => 3_u8,
2548*61046927SAndroid Build Coastguard Worker },
2549*61046927SAndroid Build Coastguard Worker );
2550*61046927SAndroid Build Coastguard Worker }
2551*61046927SAndroid Build Coastguard Worker
set_mem_type(&mut self, range: Range<usize>, mem_type: MemType)2552*61046927SAndroid Build Coastguard Worker fn set_mem_type(&mut self, range: Range<usize>, mem_type: MemType) {
2553*61046927SAndroid Build Coastguard Worker assert!(range.len() == 3);
2554*61046927SAndroid Build Coastguard Worker self.set_field(
2555*61046927SAndroid Build Coastguard Worker range,
2556*61046927SAndroid Build Coastguard Worker match mem_type {
2557*61046927SAndroid Build Coastguard Worker MemType::U8 => 0_u8,
2558*61046927SAndroid Build Coastguard Worker MemType::I8 => 1_u8,
2559*61046927SAndroid Build Coastguard Worker MemType::U16 => 2_u8,
2560*61046927SAndroid Build Coastguard Worker MemType::I16 => 3_u8,
2561*61046927SAndroid Build Coastguard Worker MemType::B32 => 4_u8,
2562*61046927SAndroid Build Coastguard Worker MemType::B64 => 5_u8,
2563*61046927SAndroid Build Coastguard Worker MemType::B128 => 6_u8,
2564*61046927SAndroid Build Coastguard Worker },
2565*61046927SAndroid Build Coastguard Worker );
2566*61046927SAndroid Build Coastguard Worker }
2567*61046927SAndroid Build Coastguard Worker
set_mem_access(&mut self, access: &MemAccess)2568*61046927SAndroid Build Coastguard Worker fn set_mem_access(&mut self, access: &MemAccess) {
2569*61046927SAndroid Build Coastguard Worker self.set_field(
2570*61046927SAndroid Build Coastguard Worker 72..73,
2571*61046927SAndroid Build Coastguard Worker match access.space.addr_type() {
2572*61046927SAndroid Build Coastguard Worker MemAddrType::A32 => 0_u8,
2573*61046927SAndroid Build Coastguard Worker MemAddrType::A64 => 1_u8,
2574*61046927SAndroid Build Coastguard Worker },
2575*61046927SAndroid Build Coastguard Worker );
2576*61046927SAndroid Build Coastguard Worker self.set_mem_type(73..76, access.mem_type);
2577*61046927SAndroid Build Coastguard Worker self.set_mem_order(&access.order);
2578*61046927SAndroid Build Coastguard Worker self.set_eviction_priority(&access.eviction_priority);
2579*61046927SAndroid Build Coastguard Worker }
2580*61046927SAndroid Build Coastguard Worker }
2581*61046927SAndroid Build Coastguard Worker
2582*61046927SAndroid Build Coastguard Worker impl SM70Op for OpSuLd {
legalize(&mut self, b: &mut LegalizeBuilder)2583*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2584*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2585*61046927SAndroid Build Coastguard Worker }
2586*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2587*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2588*61046927SAndroid Build Coastguard Worker e.set_opcode(0x998);
2589*61046927SAndroid Build Coastguard Worker
2590*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2591*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.coord);
2592*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.handle);
2593*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.fault);
2594*61046927SAndroid Build Coastguard Worker
2595*61046927SAndroid Build Coastguard Worker e.set_image_dim(61..64, self.image_dim);
2596*61046927SAndroid Build Coastguard Worker e.set_mem_order(&self.mem_order);
2597*61046927SAndroid Build Coastguard Worker e.set_eviction_priority(&self.mem_eviction_priority);
2598*61046927SAndroid Build Coastguard Worker
2599*61046927SAndroid Build Coastguard Worker assert!(self.mask == 0x1 || self.mask == 0x3 || self.mask == 0xf);
2600*61046927SAndroid Build Coastguard Worker e.set_field(72..76, self.mask);
2601*61046927SAndroid Build Coastguard Worker }
2602*61046927SAndroid Build Coastguard Worker }
2603*61046927SAndroid Build Coastguard Worker
2604*61046927SAndroid Build Coastguard Worker impl SM70Op for OpSuSt {
legalize(&mut self, b: &mut LegalizeBuilder)2605*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2606*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2607*61046927SAndroid Build Coastguard Worker }
2608*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2609*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2610*61046927SAndroid Build Coastguard Worker e.set_opcode(0x99c);
2611*61046927SAndroid Build Coastguard Worker
2612*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.coord);
2613*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.data);
2614*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.handle);
2615*61046927SAndroid Build Coastguard Worker
2616*61046927SAndroid Build Coastguard Worker e.set_image_dim(61..64, self.image_dim);
2617*61046927SAndroid Build Coastguard Worker e.set_mem_order(&self.mem_order);
2618*61046927SAndroid Build Coastguard Worker e.set_eviction_priority(&self.mem_eviction_priority);
2619*61046927SAndroid Build Coastguard Worker
2620*61046927SAndroid Build Coastguard Worker assert!(self.mask == 0x1 || self.mask == 0x3 || self.mask == 0xf);
2621*61046927SAndroid Build Coastguard Worker e.set_field(72..76, self.mask);
2622*61046927SAndroid Build Coastguard Worker }
2623*61046927SAndroid Build Coastguard Worker }
2624*61046927SAndroid Build Coastguard Worker
2625*61046927SAndroid Build Coastguard Worker impl SM70Op for OpSuAtom {
legalize(&mut self, b: &mut LegalizeBuilder)2626*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2627*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2628*61046927SAndroid Build Coastguard Worker }
2629*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2630*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2631*61046927SAndroid Build Coastguard Worker if self.dst.is_none() {
2632*61046927SAndroid Build Coastguard Worker e.set_opcode(0x3a0);
2633*61046927SAndroid Build Coastguard Worker e.set_atom_op(87..90, self.atom_op);
2634*61046927SAndroid Build Coastguard Worker } else if let AtomOp::CmpExch(cmp_src) = self.atom_op {
2635*61046927SAndroid Build Coastguard Worker e.set_opcode(0x396);
2636*61046927SAndroid Build Coastguard Worker assert!(cmp_src == AtomCmpSrc::Packed);
2637*61046927SAndroid Build Coastguard Worker } else {
2638*61046927SAndroid Build Coastguard Worker e.set_opcode(0x394);
2639*61046927SAndroid Build Coastguard Worker e.set_atom_op(87..91, self.atom_op);
2640*61046927SAndroid Build Coastguard Worker };
2641*61046927SAndroid Build Coastguard Worker
2642*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2643*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.coord);
2644*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.data);
2645*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.handle);
2646*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.fault);
2647*61046927SAndroid Build Coastguard Worker
2648*61046927SAndroid Build Coastguard Worker e.set_image_dim(61..64, self.image_dim);
2649*61046927SAndroid Build Coastguard Worker e.set_mem_order(&self.mem_order);
2650*61046927SAndroid Build Coastguard Worker e.set_eviction_priority(&self.mem_eviction_priority);
2651*61046927SAndroid Build Coastguard Worker
2652*61046927SAndroid Build Coastguard Worker e.set_bit(72, false); // .BA
2653*61046927SAndroid Build Coastguard Worker e.set_atom_type(73..76, self.atom_type);
2654*61046927SAndroid Build Coastguard Worker }
2655*61046927SAndroid Build Coastguard Worker }
2656*61046927SAndroid Build Coastguard Worker
2657*61046927SAndroid Build Coastguard Worker impl SM70Op for OpLd {
legalize(&mut self, b: &mut LegalizeBuilder)2658*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2659*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2660*61046927SAndroid Build Coastguard Worker }
2661*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2662*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2663*61046927SAndroid Build Coastguard Worker match self.access.space {
2664*61046927SAndroid Build Coastguard Worker MemSpace::Global(_) => {
2665*61046927SAndroid Build Coastguard Worker e.set_opcode(0x381);
2666*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, Dst::None);
2667*61046927SAndroid Build Coastguard Worker e.set_mem_access(&self.access);
2668*61046927SAndroid Build Coastguard Worker }
2669*61046927SAndroid Build Coastguard Worker MemSpace::Local => {
2670*61046927SAndroid Build Coastguard Worker e.set_opcode(0x983);
2671*61046927SAndroid Build Coastguard Worker e.set_field(84..87, 1_u8);
2672*61046927SAndroid Build Coastguard Worker
2673*61046927SAndroid Build Coastguard Worker e.set_mem_type(73..76, self.access.mem_type);
2674*61046927SAndroid Build Coastguard Worker assert!(self.access.order == MemOrder::Strong(MemScope::CTA));
2675*61046927SAndroid Build Coastguard Worker assert!(
2676*61046927SAndroid Build Coastguard Worker self.access.eviction_priority
2677*61046927SAndroid Build Coastguard Worker == MemEvictionPriority::Normal
2678*61046927SAndroid Build Coastguard Worker );
2679*61046927SAndroid Build Coastguard Worker }
2680*61046927SAndroid Build Coastguard Worker MemSpace::Shared => {
2681*61046927SAndroid Build Coastguard Worker e.set_opcode(0x984);
2682*61046927SAndroid Build Coastguard Worker
2683*61046927SAndroid Build Coastguard Worker e.set_mem_type(73..76, self.access.mem_type);
2684*61046927SAndroid Build Coastguard Worker assert!(self.access.order == MemOrder::Strong(MemScope::CTA));
2685*61046927SAndroid Build Coastguard Worker assert!(
2686*61046927SAndroid Build Coastguard Worker self.access.eviction_priority
2687*61046927SAndroid Build Coastguard Worker == MemEvictionPriority::Normal
2688*61046927SAndroid Build Coastguard Worker );
2689*61046927SAndroid Build Coastguard Worker
2690*61046927SAndroid Build Coastguard Worker e.set_bit(87, false); // !.ZD - Returns a predicate?
2691*61046927SAndroid Build Coastguard Worker }
2692*61046927SAndroid Build Coastguard Worker }
2693*61046927SAndroid Build Coastguard Worker
2694*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2695*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.addr);
2696*61046927SAndroid Build Coastguard Worker e.set_field(40..64, self.offset);
2697*61046927SAndroid Build Coastguard Worker }
2698*61046927SAndroid Build Coastguard Worker }
2699*61046927SAndroid Build Coastguard Worker
2700*61046927SAndroid Build Coastguard Worker impl SM70Op for OpLdc {
legalize(&mut self, b: &mut LegalizeBuilder)2701*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2702*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
2703*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(&mut self.offset, gpr, SrcType::GPR);
2704*61046927SAndroid Build Coastguard Worker }
2705*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2706*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2707*61046927SAndroid Build Coastguard Worker let SrcRef::CBuf(cb) = &self.cb.src_ref else {
2708*61046927SAndroid Build Coastguard Worker panic!("LDC must take a cbuf source");
2709*61046927SAndroid Build Coastguard Worker };
2710*61046927SAndroid Build Coastguard Worker
2711*61046927SAndroid Build Coastguard Worker match cb.buf {
2712*61046927SAndroid Build Coastguard Worker CBuf::Binding(idx) => {
2713*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
2714*61046927SAndroid Build Coastguard Worker e.set_opcode(0xab9);
2715*61046927SAndroid Build Coastguard Worker e.set_udst(self.dst);
2716*61046927SAndroid Build Coastguard Worker
2717*61046927SAndroid Build Coastguard Worker assert!(self.offset.is_zero());
2718*61046927SAndroid Build Coastguard Worker assert!(self.mode == LdcMode::Indexed);
2719*61046927SAndroid Build Coastguard Worker } else {
2720*61046927SAndroid Build Coastguard Worker e.set_opcode(0xb82);
2721*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2722*61046927SAndroid Build Coastguard Worker
2723*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.offset);
2724*61046927SAndroid Build Coastguard Worker e.set_field(
2725*61046927SAndroid Build Coastguard Worker 78..80,
2726*61046927SAndroid Build Coastguard Worker match self.mode {
2727*61046927SAndroid Build Coastguard Worker LdcMode::Indexed => 0_u8,
2728*61046927SAndroid Build Coastguard Worker LdcMode::IndexedLinear => 1_u8,
2729*61046927SAndroid Build Coastguard Worker LdcMode::IndexedSegmented => 2_u8,
2730*61046927SAndroid Build Coastguard Worker LdcMode::IndexedSegmentedLinear => 3_u8,
2731*61046927SAndroid Build Coastguard Worker },
2732*61046927SAndroid Build Coastguard Worker );
2733*61046927SAndroid Build Coastguard Worker }
2734*61046927SAndroid Build Coastguard Worker e.set_field(54..59, idx);
2735*61046927SAndroid Build Coastguard Worker e.set_bit(91, false); // Bound
2736*61046927SAndroid Build Coastguard Worker }
2737*61046927SAndroid Build Coastguard Worker CBuf::BindlessUGPR(handle) => {
2738*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
2739*61046927SAndroid Build Coastguard Worker e.set_opcode(0xab9);
2740*61046927SAndroid Build Coastguard Worker e.set_udst(self.dst);
2741*61046927SAndroid Build Coastguard Worker
2742*61046927SAndroid Build Coastguard Worker assert!(self.offset.is_zero());
2743*61046927SAndroid Build Coastguard Worker } else {
2744*61046927SAndroid Build Coastguard Worker e.set_opcode(0x582);
2745*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2746*61046927SAndroid Build Coastguard Worker
2747*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.offset);
2748*61046927SAndroid Build Coastguard Worker }
2749*61046927SAndroid Build Coastguard Worker
2750*61046927SAndroid Build Coastguard Worker e.set_ureg(24..32, handle);
2751*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.offset);
2752*61046927SAndroid Build Coastguard Worker assert!(self.mode == LdcMode::Indexed);
2753*61046927SAndroid Build Coastguard Worker e.set_bit(91, true); // Bindless
2754*61046927SAndroid Build Coastguard Worker }
2755*61046927SAndroid Build Coastguard Worker CBuf::BindlessSSA(_) => panic!("SSA values must be lowered"),
2756*61046927SAndroid Build Coastguard Worker }
2757*61046927SAndroid Build Coastguard Worker
2758*61046927SAndroid Build Coastguard Worker e.set_field(38..54, cb.offset);
2759*61046927SAndroid Build Coastguard Worker e.set_mem_type(73..76, self.mem_type);
2760*61046927SAndroid Build Coastguard Worker }
2761*61046927SAndroid Build Coastguard Worker }
2762*61046927SAndroid Build Coastguard Worker
2763*61046927SAndroid Build Coastguard Worker impl SM70Op for OpSt {
legalize(&mut self, b: &mut LegalizeBuilder)2764*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2765*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2766*61046927SAndroid Build Coastguard Worker }
2767*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2768*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2769*61046927SAndroid Build Coastguard Worker match self.access.space {
2770*61046927SAndroid Build Coastguard Worker MemSpace::Global(_) => {
2771*61046927SAndroid Build Coastguard Worker e.set_opcode(0x386);
2772*61046927SAndroid Build Coastguard Worker e.set_mem_access(&self.access);
2773*61046927SAndroid Build Coastguard Worker }
2774*61046927SAndroid Build Coastguard Worker MemSpace::Local => {
2775*61046927SAndroid Build Coastguard Worker e.set_opcode(0x387);
2776*61046927SAndroid Build Coastguard Worker e.set_field(84..87, 1_u8);
2777*61046927SAndroid Build Coastguard Worker
2778*61046927SAndroid Build Coastguard Worker e.set_mem_type(73..76, self.access.mem_type);
2779*61046927SAndroid Build Coastguard Worker assert!(self.access.order == MemOrder::Strong(MemScope::CTA));
2780*61046927SAndroid Build Coastguard Worker assert!(
2781*61046927SAndroid Build Coastguard Worker self.access.eviction_priority
2782*61046927SAndroid Build Coastguard Worker == MemEvictionPriority::Normal
2783*61046927SAndroid Build Coastguard Worker );
2784*61046927SAndroid Build Coastguard Worker }
2785*61046927SAndroid Build Coastguard Worker MemSpace::Shared => {
2786*61046927SAndroid Build Coastguard Worker e.set_opcode(0x388);
2787*61046927SAndroid Build Coastguard Worker
2788*61046927SAndroid Build Coastguard Worker e.set_mem_type(73..76, self.access.mem_type);
2789*61046927SAndroid Build Coastguard Worker assert!(self.access.order == MemOrder::Strong(MemScope::CTA));
2790*61046927SAndroid Build Coastguard Worker assert!(
2791*61046927SAndroid Build Coastguard Worker self.access.eviction_priority
2792*61046927SAndroid Build Coastguard Worker == MemEvictionPriority::Normal
2793*61046927SAndroid Build Coastguard Worker );
2794*61046927SAndroid Build Coastguard Worker }
2795*61046927SAndroid Build Coastguard Worker }
2796*61046927SAndroid Build Coastguard Worker
2797*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.addr);
2798*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.data);
2799*61046927SAndroid Build Coastguard Worker e.set_field(40..64, self.offset);
2800*61046927SAndroid Build Coastguard Worker }
2801*61046927SAndroid Build Coastguard Worker }
2802*61046927SAndroid Build Coastguard Worker
2803*61046927SAndroid Build Coastguard Worker impl SM70Encoder<'_> {
set_atom_op(&mut self, range: Range<usize>, atom_op: AtomOp)2804*61046927SAndroid Build Coastguard Worker fn set_atom_op(&mut self, range: Range<usize>, atom_op: AtomOp) {
2805*61046927SAndroid Build Coastguard Worker self.set_field(
2806*61046927SAndroid Build Coastguard Worker range,
2807*61046927SAndroid Build Coastguard Worker match atom_op {
2808*61046927SAndroid Build Coastguard Worker AtomOp::Add => 0_u8,
2809*61046927SAndroid Build Coastguard Worker AtomOp::Min => 1_u8,
2810*61046927SAndroid Build Coastguard Worker AtomOp::Max => 2_u8,
2811*61046927SAndroid Build Coastguard Worker AtomOp::Inc => 3_u8,
2812*61046927SAndroid Build Coastguard Worker AtomOp::Dec => 4_u8,
2813*61046927SAndroid Build Coastguard Worker AtomOp::And => 5_u8,
2814*61046927SAndroid Build Coastguard Worker AtomOp::Or => 6_u8,
2815*61046927SAndroid Build Coastguard Worker AtomOp::Xor => 7_u8,
2816*61046927SAndroid Build Coastguard Worker AtomOp::Exch => 8_u8,
2817*61046927SAndroid Build Coastguard Worker AtomOp::CmpExch(_) => panic!("CmpExch is a separate opcode"),
2818*61046927SAndroid Build Coastguard Worker },
2819*61046927SAndroid Build Coastguard Worker );
2820*61046927SAndroid Build Coastguard Worker }
2821*61046927SAndroid Build Coastguard Worker
set_atom_type(&mut self, range: Range<usize>, atom_type: AtomType)2822*61046927SAndroid Build Coastguard Worker fn set_atom_type(&mut self, range: Range<usize>, atom_type: AtomType) {
2823*61046927SAndroid Build Coastguard Worker assert!(range.len() == 3);
2824*61046927SAndroid Build Coastguard Worker self.set_field(
2825*61046927SAndroid Build Coastguard Worker range,
2826*61046927SAndroid Build Coastguard Worker match atom_type {
2827*61046927SAndroid Build Coastguard Worker AtomType::U32 => 0_u8,
2828*61046927SAndroid Build Coastguard Worker AtomType::I32 => 1_u8,
2829*61046927SAndroid Build Coastguard Worker AtomType::U64 => 2_u8,
2830*61046927SAndroid Build Coastguard Worker AtomType::F32 => 3_u8,
2831*61046927SAndroid Build Coastguard Worker AtomType::F16x2 => 4_u8,
2832*61046927SAndroid Build Coastguard Worker AtomType::I64 => 5_u8,
2833*61046927SAndroid Build Coastguard Worker AtomType::F64 => 6_u8,
2834*61046927SAndroid Build Coastguard Worker },
2835*61046927SAndroid Build Coastguard Worker );
2836*61046927SAndroid Build Coastguard Worker }
2837*61046927SAndroid Build Coastguard Worker }
2838*61046927SAndroid Build Coastguard Worker
2839*61046927SAndroid Build Coastguard Worker impl SM70Op for OpAtom {
legalize(&mut self, b: &mut LegalizeBuilder)2840*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2841*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2842*61046927SAndroid Build Coastguard Worker }
2843*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2844*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2845*61046927SAndroid Build Coastguard Worker match self.mem_space {
2846*61046927SAndroid Build Coastguard Worker MemSpace::Global(_) => {
2847*61046927SAndroid Build Coastguard Worker if self.dst.is_none() {
2848*61046927SAndroid Build Coastguard Worker e.set_opcode(0x98e);
2849*61046927SAndroid Build Coastguard Worker
2850*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.data);
2851*61046927SAndroid Build Coastguard Worker e.set_atom_op(87..90, self.atom_op);
2852*61046927SAndroid Build Coastguard Worker } else if let AtomOp::CmpExch(cmp_src) = self.atom_op {
2853*61046927SAndroid Build Coastguard Worker e.set_opcode(0x3a9);
2854*61046927SAndroid Build Coastguard Worker
2855*61046927SAndroid Build Coastguard Worker assert!(cmp_src == AtomCmpSrc::Separate);
2856*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.cmpr);
2857*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.data);
2858*61046927SAndroid Build Coastguard Worker } else {
2859*61046927SAndroid Build Coastguard Worker e.set_opcode(0x3a8);
2860*61046927SAndroid Build Coastguard Worker
2861*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.data);
2862*61046927SAndroid Build Coastguard Worker e.set_atom_op(87..91, self.atom_op);
2863*61046927SAndroid Build Coastguard Worker }
2864*61046927SAndroid Build Coastguard Worker
2865*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, Dst::None);
2866*61046927SAndroid Build Coastguard Worker
2867*61046927SAndroid Build Coastguard Worker e.set_field(
2868*61046927SAndroid Build Coastguard Worker 72..73,
2869*61046927SAndroid Build Coastguard Worker match self.mem_space.addr_type() {
2870*61046927SAndroid Build Coastguard Worker MemAddrType::A32 => 0_u8,
2871*61046927SAndroid Build Coastguard Worker MemAddrType::A64 => 1_u8,
2872*61046927SAndroid Build Coastguard Worker },
2873*61046927SAndroid Build Coastguard Worker );
2874*61046927SAndroid Build Coastguard Worker
2875*61046927SAndroid Build Coastguard Worker e.set_mem_order(&self.mem_order);
2876*61046927SAndroid Build Coastguard Worker e.set_eviction_priority(&self.mem_eviction_priority);
2877*61046927SAndroid Build Coastguard Worker }
2878*61046927SAndroid Build Coastguard Worker MemSpace::Local => panic!("Atomics do not support local"),
2879*61046927SAndroid Build Coastguard Worker MemSpace::Shared => {
2880*61046927SAndroid Build Coastguard Worker if let AtomOp::CmpExch(cmp_src) = self.atom_op {
2881*61046927SAndroid Build Coastguard Worker e.set_opcode(0x38d);
2882*61046927SAndroid Build Coastguard Worker
2883*61046927SAndroid Build Coastguard Worker assert!(cmp_src == AtomCmpSrc::Separate);
2884*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.cmpr);
2885*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.data);
2886*61046927SAndroid Build Coastguard Worker } else {
2887*61046927SAndroid Build Coastguard Worker e.set_opcode(0x38c);
2888*61046927SAndroid Build Coastguard Worker
2889*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.data);
2890*61046927SAndroid Build Coastguard Worker e.set_atom_op(87..91, self.atom_op);
2891*61046927SAndroid Build Coastguard Worker }
2892*61046927SAndroid Build Coastguard Worker
2893*61046927SAndroid Build Coastguard Worker assert!(self.mem_order == MemOrder::Strong(MemScope::CTA));
2894*61046927SAndroid Build Coastguard Worker assert!(
2895*61046927SAndroid Build Coastguard Worker self.mem_eviction_priority == MemEvictionPriority::Normal
2896*61046927SAndroid Build Coastguard Worker );
2897*61046927SAndroid Build Coastguard Worker }
2898*61046927SAndroid Build Coastguard Worker }
2899*61046927SAndroid Build Coastguard Worker
2900*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2901*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.addr);
2902*61046927SAndroid Build Coastguard Worker e.set_field(40..64, self.addr_offset);
2903*61046927SAndroid Build Coastguard Worker e.set_atom_type(73..76, self.atom_type);
2904*61046927SAndroid Build Coastguard Worker }
2905*61046927SAndroid Build Coastguard Worker }
2906*61046927SAndroid Build Coastguard Worker
2907*61046927SAndroid Build Coastguard Worker impl SM70Op for OpAL2P {
legalize(&mut self, b: &mut LegalizeBuilder)2908*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2909*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2910*61046927SAndroid Build Coastguard Worker }
2911*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2912*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2913*61046927SAndroid Build Coastguard Worker e.set_opcode(0x920);
2914*61046927SAndroid Build Coastguard Worker
2915*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2916*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.offset);
2917*61046927SAndroid Build Coastguard Worker
2918*61046927SAndroid Build Coastguard Worker e.set_field(40..50, self.access.addr);
2919*61046927SAndroid Build Coastguard Worker e.set_field(74..76, 0_u8); // comps
2920*61046927SAndroid Build Coastguard Worker assert!(!self.access.patch);
2921*61046927SAndroid Build Coastguard Worker e.set_bit(79, self.access.output);
2922*61046927SAndroid Build Coastguard Worker }
2923*61046927SAndroid Build Coastguard Worker }
2924*61046927SAndroid Build Coastguard Worker
2925*61046927SAndroid Build Coastguard Worker impl SM70Op for OpALd {
legalize(&mut self, b: &mut LegalizeBuilder)2926*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2927*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2928*61046927SAndroid Build Coastguard Worker }
2929*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2930*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2931*61046927SAndroid Build Coastguard Worker e.set_opcode(0x321);
2932*61046927SAndroid Build Coastguard Worker
2933*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2934*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.vtx);
2935*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.offset);
2936*61046927SAndroid Build Coastguard Worker
2937*61046927SAndroid Build Coastguard Worker e.set_field(40..50, self.access.addr);
2938*61046927SAndroid Build Coastguard Worker e.set_field(74..76, self.access.comps - 1);
2939*61046927SAndroid Build Coastguard Worker e.set_field(76..77, self.access.patch);
2940*61046927SAndroid Build Coastguard Worker e.set_field(77..78, self.access.phys);
2941*61046927SAndroid Build Coastguard Worker e.set_field(79..80, self.access.output);
2942*61046927SAndroid Build Coastguard Worker }
2943*61046927SAndroid Build Coastguard Worker }
2944*61046927SAndroid Build Coastguard Worker
2945*61046927SAndroid Build Coastguard Worker impl SM70Op for OpASt {
legalize(&mut self, b: &mut LegalizeBuilder)2946*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2947*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2948*61046927SAndroid Build Coastguard Worker }
2949*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2950*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2951*61046927SAndroid Build Coastguard Worker e.set_opcode(0x322);
2952*61046927SAndroid Build Coastguard Worker
2953*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.data);
2954*61046927SAndroid Build Coastguard Worker e.set_reg_src(64..72, self.vtx);
2955*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.offset);
2956*61046927SAndroid Build Coastguard Worker
2957*61046927SAndroid Build Coastguard Worker e.set_field(40..50, self.access.addr);
2958*61046927SAndroid Build Coastguard Worker e.set_field(74..76, self.access.comps - 1);
2959*61046927SAndroid Build Coastguard Worker e.set_field(76..77, self.access.patch);
2960*61046927SAndroid Build Coastguard Worker e.set_field(77..78, self.access.phys);
2961*61046927SAndroid Build Coastguard Worker assert!(self.access.output);
2962*61046927SAndroid Build Coastguard Worker }
2963*61046927SAndroid Build Coastguard Worker }
2964*61046927SAndroid Build Coastguard Worker
2965*61046927SAndroid Build Coastguard Worker impl SM70Op for OpIpa {
legalize(&mut self, b: &mut LegalizeBuilder)2966*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
2967*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
2968*61046927SAndroid Build Coastguard Worker }
2969*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)2970*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
2971*61046927SAndroid Build Coastguard Worker e.set_opcode(0x326);
2972*61046927SAndroid Build Coastguard Worker
2973*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
2974*61046927SAndroid Build Coastguard Worker
2975*61046927SAndroid Build Coastguard Worker assert!(self.addr % 4 == 0);
2976*61046927SAndroid Build Coastguard Worker e.set_field(64..72, self.addr >> 2);
2977*61046927SAndroid Build Coastguard Worker
2978*61046927SAndroid Build Coastguard Worker e.set_field(
2979*61046927SAndroid Build Coastguard Worker 76..78,
2980*61046927SAndroid Build Coastguard Worker match self.loc {
2981*61046927SAndroid Build Coastguard Worker InterpLoc::Default => 0_u8,
2982*61046927SAndroid Build Coastguard Worker InterpLoc::Centroid => 1_u8,
2983*61046927SAndroid Build Coastguard Worker InterpLoc::Offset => 2_u8,
2984*61046927SAndroid Build Coastguard Worker },
2985*61046927SAndroid Build Coastguard Worker );
2986*61046927SAndroid Build Coastguard Worker e.set_field(
2987*61046927SAndroid Build Coastguard Worker 78..80,
2988*61046927SAndroid Build Coastguard Worker match self.freq {
2989*61046927SAndroid Build Coastguard Worker InterpFreq::Pass => 0_u8,
2990*61046927SAndroid Build Coastguard Worker InterpFreq::Constant => 1_u8,
2991*61046927SAndroid Build Coastguard Worker InterpFreq::State => 2_u8,
2992*61046927SAndroid Build Coastguard Worker InterpFreq::PassMulW => {
2993*61046927SAndroid Build Coastguard Worker panic!("InterpFreq::PassMulW is invalid on SM70+");
2994*61046927SAndroid Build Coastguard Worker }
2995*61046927SAndroid Build Coastguard Worker },
2996*61046927SAndroid Build Coastguard Worker );
2997*61046927SAndroid Build Coastguard Worker
2998*61046927SAndroid Build Coastguard Worker assert!(self.inv_w.is_zero());
2999*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.offset);
3000*61046927SAndroid Build Coastguard Worker
3001*61046927SAndroid Build Coastguard Worker // TODO: What is this for?
3002*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, Dst::None);
3003*61046927SAndroid Build Coastguard Worker }
3004*61046927SAndroid Build Coastguard Worker }
3005*61046927SAndroid Build Coastguard Worker
3006*61046927SAndroid Build Coastguard Worker impl SM70Op for OpLdTram {
legalize(&mut self, b: &mut LegalizeBuilder)3007*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
3008*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
3009*61046927SAndroid Build Coastguard Worker }
3010*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3011*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3012*61046927SAndroid Build Coastguard Worker e.set_opcode(0x3ad);
3013*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
3014*61046927SAndroid Build Coastguard Worker e.set_ureg(24..32, RegRef::zero(RegFile::UGPR, 1));
3015*61046927SAndroid Build Coastguard Worker
3016*61046927SAndroid Build Coastguard Worker assert!(self.addr % 4 == 0);
3017*61046927SAndroid Build Coastguard Worker e.set_field(64..72, self.addr >> 2);
3018*61046927SAndroid Build Coastguard Worker
3019*61046927SAndroid Build Coastguard Worker e.set_bit(72, self.use_c);
3020*61046927SAndroid Build Coastguard Worker
3021*61046927SAndroid Build Coastguard Worker // Unknown but required
3022*61046927SAndroid Build Coastguard Worker e.set_bit(91, true);
3023*61046927SAndroid Build Coastguard Worker }
3024*61046927SAndroid Build Coastguard Worker }
3025*61046927SAndroid Build Coastguard Worker
3026*61046927SAndroid Build Coastguard Worker impl SM70Op for OpCCtl {
legalize(&mut self, b: &mut LegalizeBuilder)3027*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
3028*61046927SAndroid Build Coastguard Worker legalize_ext_instr(self, b);
3029*61046927SAndroid Build Coastguard Worker }
3030*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3031*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3032*61046927SAndroid Build Coastguard Worker assert!(matches!(self.mem_space, MemSpace::Global(_)));
3033*61046927SAndroid Build Coastguard Worker e.set_opcode(0x98f);
3034*61046927SAndroid Build Coastguard Worker
3035*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.addr);
3036*61046927SAndroid Build Coastguard Worker e.set_field(32..64, self.addr_offset);
3037*61046927SAndroid Build Coastguard Worker
3038*61046927SAndroid Build Coastguard Worker e.set_field(
3039*61046927SAndroid Build Coastguard Worker 87..91,
3040*61046927SAndroid Build Coastguard Worker match self.op {
3041*61046927SAndroid Build Coastguard Worker CCtlOp::PF1 => 0_u8,
3042*61046927SAndroid Build Coastguard Worker CCtlOp::PF2 => 1_u8,
3043*61046927SAndroid Build Coastguard Worker CCtlOp::WB => 2_u8,
3044*61046927SAndroid Build Coastguard Worker CCtlOp::IV => 3_u8,
3045*61046927SAndroid Build Coastguard Worker CCtlOp::IVAll => 4_u8,
3046*61046927SAndroid Build Coastguard Worker CCtlOp::RS => 5_u8,
3047*61046927SAndroid Build Coastguard Worker CCtlOp::IVAllP => 6_u8,
3048*61046927SAndroid Build Coastguard Worker CCtlOp::WBAll => 7_u8,
3049*61046927SAndroid Build Coastguard Worker CCtlOp::WBAllP => 8_u8,
3050*61046927SAndroid Build Coastguard Worker op => panic!("Unsupported cache control {op:?}"),
3051*61046927SAndroid Build Coastguard Worker },
3052*61046927SAndroid Build Coastguard Worker );
3053*61046927SAndroid Build Coastguard Worker }
3054*61046927SAndroid Build Coastguard Worker }
3055*61046927SAndroid Build Coastguard Worker
3056*61046927SAndroid Build Coastguard Worker impl SM70Op for OpMemBar {
legalize(&mut self, _b: &mut LegalizeBuilder)3057*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3058*61046927SAndroid Build Coastguard Worker // Nothing to do
3059*61046927SAndroid Build Coastguard Worker }
3060*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3061*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3062*61046927SAndroid Build Coastguard Worker e.set_opcode(0x992);
3063*61046927SAndroid Build Coastguard Worker
3064*61046927SAndroid Build Coastguard Worker e.set_bit(72, false); // !.MMIO
3065*61046927SAndroid Build Coastguard Worker e.set_field(
3066*61046927SAndroid Build Coastguard Worker 76..79,
3067*61046927SAndroid Build Coastguard Worker match self.scope {
3068*61046927SAndroid Build Coastguard Worker MemScope::CTA => 0_u8,
3069*61046927SAndroid Build Coastguard Worker // SM => 1_u8,
3070*61046927SAndroid Build Coastguard Worker MemScope::GPU => 2_u8,
3071*61046927SAndroid Build Coastguard Worker MemScope::System => 3_u8,
3072*61046927SAndroid Build Coastguard Worker },
3073*61046927SAndroid Build Coastguard Worker );
3074*61046927SAndroid Build Coastguard Worker e.set_bit(80, false); // .SC
3075*61046927SAndroid Build Coastguard Worker }
3076*61046927SAndroid Build Coastguard Worker }
3077*61046927SAndroid Build Coastguard Worker
3078*61046927SAndroid Build Coastguard Worker impl SM70Encoder<'_> {
set_rel_offset(&mut self, range: Range<usize>, label: &Label)3079*61046927SAndroid Build Coastguard Worker fn set_rel_offset(&mut self, range: Range<usize>, label: &Label) {
3080*61046927SAndroid Build Coastguard Worker let ip = u64::try_from(self.ip).unwrap();
3081*61046927SAndroid Build Coastguard Worker let ip = i64::try_from(ip).unwrap();
3082*61046927SAndroid Build Coastguard Worker
3083*61046927SAndroid Build Coastguard Worker let target_ip = *self.labels.get(label).unwrap();
3084*61046927SAndroid Build Coastguard Worker let target_ip = u64::try_from(target_ip).unwrap();
3085*61046927SAndroid Build Coastguard Worker let target_ip = i64::try_from(target_ip).unwrap();
3086*61046927SAndroid Build Coastguard Worker
3087*61046927SAndroid Build Coastguard Worker let rel_offset = target_ip - ip - 4;
3088*61046927SAndroid Build Coastguard Worker
3089*61046927SAndroid Build Coastguard Worker self.set_field(range, rel_offset);
3090*61046927SAndroid Build Coastguard Worker }
3091*61046927SAndroid Build Coastguard Worker }
3092*61046927SAndroid Build Coastguard Worker
3093*61046927SAndroid Build Coastguard Worker impl SM70Op for OpBClear {
legalize(&mut self, _b: &mut LegalizeBuilder)3094*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3095*61046927SAndroid Build Coastguard Worker // Nothing to do
3096*61046927SAndroid Build Coastguard Worker }
3097*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3098*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3099*61046927SAndroid Build Coastguard Worker e.set_opcode(0x355);
3100*61046927SAndroid Build Coastguard Worker
3101*61046927SAndroid Build Coastguard Worker e.set_dst(Dst::None);
3102*61046927SAndroid Build Coastguard Worker e.set_bar_dst(24..28, self.dst);
3103*61046927SAndroid Build Coastguard Worker
3104*61046927SAndroid Build Coastguard Worker e.set_bit(84, true); // .CLEAR
3105*61046927SAndroid Build Coastguard Worker }
3106*61046927SAndroid Build Coastguard Worker }
3107*61046927SAndroid Build Coastguard Worker
3108*61046927SAndroid Build Coastguard Worker impl SM70Op for OpBMov {
legalize(&mut self, _b: &mut LegalizeBuilder)3109*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3110*61046927SAndroid Build Coastguard Worker // Nothing to do
3111*61046927SAndroid Build Coastguard Worker }
3112*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3113*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3114*61046927SAndroid Build Coastguard Worker if dst_is_bar(self.dst) {
3115*61046927SAndroid Build Coastguard Worker e.set_opcode(0x356);
3116*61046927SAndroid Build Coastguard Worker
3117*61046927SAndroid Build Coastguard Worker e.set_bar_dst(24..28, self.dst);
3118*61046927SAndroid Build Coastguard Worker e.set_reg_src(32..40, self.src);
3119*61046927SAndroid Build Coastguard Worker
3120*61046927SAndroid Build Coastguard Worker e.set_bit(84, self.clear);
3121*61046927SAndroid Build Coastguard Worker } else {
3122*61046927SAndroid Build Coastguard Worker e.set_opcode(0x355);
3123*61046927SAndroid Build Coastguard Worker
3124*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
3125*61046927SAndroid Build Coastguard Worker e.set_bar_src(24..28, self.src);
3126*61046927SAndroid Build Coastguard Worker
3127*61046927SAndroid Build Coastguard Worker e.set_bit(84, self.clear);
3128*61046927SAndroid Build Coastguard Worker }
3129*61046927SAndroid Build Coastguard Worker }
3130*61046927SAndroid Build Coastguard Worker }
3131*61046927SAndroid Build Coastguard Worker
3132*61046927SAndroid Build Coastguard Worker impl SM70Op for OpBreak {
legalize(&mut self, _b: &mut LegalizeBuilder)3133*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3134*61046927SAndroid Build Coastguard Worker // Nothing to do
3135*61046927SAndroid Build Coastguard Worker }
3136*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3137*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3138*61046927SAndroid Build Coastguard Worker e.set_opcode(0x942);
3139*61046927SAndroid Build Coastguard Worker assert!(self.bar_in.src_ref.as_reg() == self.bar_out.as_reg());
3140*61046927SAndroid Build Coastguard Worker e.set_bar_dst(16..20, self.bar_out);
3141*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.cond);
3142*61046927SAndroid Build Coastguard Worker }
3143*61046927SAndroid Build Coastguard Worker }
3144*61046927SAndroid Build Coastguard Worker
3145*61046927SAndroid Build Coastguard Worker impl SM70Op for OpBSSy {
legalize(&mut self, _b: &mut LegalizeBuilder)3146*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3147*61046927SAndroid Build Coastguard Worker // Nothing to do
3148*61046927SAndroid Build Coastguard Worker }
3149*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3150*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3151*61046927SAndroid Build Coastguard Worker e.set_opcode(0x945);
3152*61046927SAndroid Build Coastguard Worker assert!(self.bar_in.src_ref.as_reg() == self.bar_out.as_reg());
3153*61046927SAndroid Build Coastguard Worker e.set_bar_dst(16..20, self.bar_out);
3154*61046927SAndroid Build Coastguard Worker e.set_rel_offset(34..64, &self.target);
3155*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.cond);
3156*61046927SAndroid Build Coastguard Worker }
3157*61046927SAndroid Build Coastguard Worker }
3158*61046927SAndroid Build Coastguard Worker
3159*61046927SAndroid Build Coastguard Worker impl SM70Op for OpBSync {
legalize(&mut self, _b: &mut LegalizeBuilder)3160*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3161*61046927SAndroid Build Coastguard Worker // Nothing to do
3162*61046927SAndroid Build Coastguard Worker }
3163*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3164*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3165*61046927SAndroid Build Coastguard Worker e.set_opcode(0x941);
3166*61046927SAndroid Build Coastguard Worker e.set_bar_src(16..20, self.bar);
3167*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.cond);
3168*61046927SAndroid Build Coastguard Worker }
3169*61046927SAndroid Build Coastguard Worker }
3170*61046927SAndroid Build Coastguard Worker
3171*61046927SAndroid Build Coastguard Worker impl SM70Op for OpBra {
legalize(&mut self, _b: &mut LegalizeBuilder)3172*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3173*61046927SAndroid Build Coastguard Worker // Nothing to do
3174*61046927SAndroid Build Coastguard Worker }
3175*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3176*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3177*61046927SAndroid Build Coastguard Worker e.set_opcode(0x947);
3178*61046927SAndroid Build Coastguard Worker e.set_rel_offset(34..82, &self.target);
3179*61046927SAndroid Build Coastguard Worker e.set_field(87..90, 0x7_u8); // TODO: Pred?
3180*61046927SAndroid Build Coastguard Worker }
3181*61046927SAndroid Build Coastguard Worker }
3182*61046927SAndroid Build Coastguard Worker
3183*61046927SAndroid Build Coastguard Worker impl SM70Op for OpExit {
legalize(&mut self, _b: &mut LegalizeBuilder)3184*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3185*61046927SAndroid Build Coastguard Worker // Nothing to do
3186*61046927SAndroid Build Coastguard Worker }
3187*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3188*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3189*61046927SAndroid Build Coastguard Worker e.set_opcode(0x94d);
3190*61046927SAndroid Build Coastguard Worker
3191*61046927SAndroid Build Coastguard Worker // ./.KEEPREFCOUNT/.PREEMPTED/.INVALID3
3192*61046927SAndroid Build Coastguard Worker e.set_field(84..85, false);
3193*61046927SAndroid Build Coastguard Worker e.set_field(85..86, false); // .NO_ATEXIT
3194*61046927SAndroid Build Coastguard Worker e.set_field(87..90, 0x7_u8); // TODO: Predicate
3195*61046927SAndroid Build Coastguard Worker e.set_field(90..91, false); // NOT
3196*61046927SAndroid Build Coastguard Worker }
3197*61046927SAndroid Build Coastguard Worker }
3198*61046927SAndroid Build Coastguard Worker
3199*61046927SAndroid Build Coastguard Worker impl SM70Op for OpWarpSync {
legalize(&mut self, _b: &mut LegalizeBuilder)3200*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3201*61046927SAndroid Build Coastguard Worker // Nothing to do
3202*61046927SAndroid Build Coastguard Worker }
3203*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3204*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3205*61046927SAndroid Build Coastguard Worker e.encode_alu(0x148, None, None, Some(&Src::from(self.mask)), None);
3206*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, SrcRef::True.into());
3207*61046927SAndroid Build Coastguard Worker }
3208*61046927SAndroid Build Coastguard Worker }
3209*61046927SAndroid Build Coastguard Worker
3210*61046927SAndroid Build Coastguard Worker impl SM70Op for OpBar {
legalize(&mut self, _b: &mut LegalizeBuilder)3211*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3212*61046927SAndroid Build Coastguard Worker // Nothing to do
3213*61046927SAndroid Build Coastguard Worker }
3214*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3215*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3216*61046927SAndroid Build Coastguard Worker e.set_opcode(0xb1d);
3217*61046927SAndroid Build Coastguard Worker
3218*61046927SAndroid Build Coastguard Worker // e.set_opcode(0x31d);
3219*61046927SAndroid Build Coastguard Worker
3220*61046927SAndroid Build Coastguard Worker // // src0 == src1
3221*61046927SAndroid Build Coastguard Worker // e.set_reg_src(32..40, SrcRef::Zero.into());
3222*61046927SAndroid Build Coastguard Worker
3223*61046927SAndroid Build Coastguard Worker // // 00: RED.POPC
3224*61046927SAndroid Build Coastguard Worker // // 01: RED.AND
3225*61046927SAndroid Build Coastguard Worker // // 02: RED.OR
3226*61046927SAndroid Build Coastguard Worker // e.set_field(74..76, 0_u8);
3227*61046927SAndroid Build Coastguard Worker
3228*61046927SAndroid Build Coastguard Worker // // 00: SYNC
3229*61046927SAndroid Build Coastguard Worker // // 01: ARV
3230*61046927SAndroid Build Coastguard Worker // // 02: RED
3231*61046927SAndroid Build Coastguard Worker // // 03: SCAN
3232*61046927SAndroid Build Coastguard Worker // e.set_field(77..79, 0_u8);
3233*61046927SAndroid Build Coastguard Worker
3234*61046927SAndroid Build Coastguard Worker // e.set_pred_src(87..90, 90, SrcRef::True.into());
3235*61046927SAndroid Build Coastguard Worker }
3236*61046927SAndroid Build Coastguard Worker }
3237*61046927SAndroid Build Coastguard Worker
3238*61046927SAndroid Build Coastguard Worker impl SM70Op for OpCS2R {
legalize(&mut self, _b: &mut LegalizeBuilder)3239*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3240*61046927SAndroid Build Coastguard Worker // Nothing to do
3241*61046927SAndroid Build Coastguard Worker }
3242*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3243*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3244*61046927SAndroid Build Coastguard Worker e.set_opcode(0x805);
3245*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
3246*61046927SAndroid Build Coastguard Worker e.set_field(72..80, self.idx);
3247*61046927SAndroid Build Coastguard Worker e.set_bit(80, self.dst.as_reg().unwrap().comps() == 2); // .64
3248*61046927SAndroid Build Coastguard Worker }
3249*61046927SAndroid Build Coastguard Worker }
3250*61046927SAndroid Build Coastguard Worker
3251*61046927SAndroid Build Coastguard Worker impl SM70Op for OpIsberd {
legalize(&mut self, _b: &mut LegalizeBuilder)3252*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3253*61046927SAndroid Build Coastguard Worker // Nothing to do
3254*61046927SAndroid Build Coastguard Worker }
3255*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3256*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3257*61046927SAndroid Build Coastguard Worker e.set_opcode(0x923);
3258*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
3259*61046927SAndroid Build Coastguard Worker e.set_reg_src(24..32, self.idx);
3260*61046927SAndroid Build Coastguard Worker }
3261*61046927SAndroid Build Coastguard Worker }
3262*61046927SAndroid Build Coastguard Worker
3263*61046927SAndroid Build Coastguard Worker impl SM70Op for OpKill {
legalize(&mut self, _b: &mut LegalizeBuilder)3264*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3265*61046927SAndroid Build Coastguard Worker // Nothing to do
3266*61046927SAndroid Build Coastguard Worker }
3267*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3268*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3269*61046927SAndroid Build Coastguard Worker e.set_opcode(0x95b);
3270*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, SrcRef::True.into());
3271*61046927SAndroid Build Coastguard Worker }
3272*61046927SAndroid Build Coastguard Worker }
3273*61046927SAndroid Build Coastguard Worker
3274*61046927SAndroid Build Coastguard Worker impl SM70Op for OpNop {
legalize(&mut self, _b: &mut LegalizeBuilder)3275*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3276*61046927SAndroid Build Coastguard Worker // Nothing to do
3277*61046927SAndroid Build Coastguard Worker }
3278*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3279*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3280*61046927SAndroid Build Coastguard Worker e.set_opcode(0x918);
3281*61046927SAndroid Build Coastguard Worker }
3282*61046927SAndroid Build Coastguard Worker }
3283*61046927SAndroid Build Coastguard Worker
3284*61046927SAndroid Build Coastguard Worker impl SM70Op for OpPixLd {
legalize(&mut self, _b: &mut LegalizeBuilder)3285*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3286*61046927SAndroid Build Coastguard Worker // Nothing to do
3287*61046927SAndroid Build Coastguard Worker }
3288*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3289*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3290*61046927SAndroid Build Coastguard Worker e.set_opcode(0x925);
3291*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
3292*61046927SAndroid Build Coastguard Worker e.set_field(
3293*61046927SAndroid Build Coastguard Worker 78..81,
3294*61046927SAndroid Build Coastguard Worker match &self.val {
3295*61046927SAndroid Build Coastguard Worker PixVal::MsCount => 0_u8,
3296*61046927SAndroid Build Coastguard Worker PixVal::CovMask => 1_u8,
3297*61046927SAndroid Build Coastguard Worker PixVal::CentroidOffset => 2_u8,
3298*61046927SAndroid Build Coastguard Worker PixVal::MyIndex => 3_u8,
3299*61046927SAndroid Build Coastguard Worker PixVal::InnerCoverage => 4_u8,
3300*61046927SAndroid Build Coastguard Worker other => panic!("Unsupported PixVal: {other}"),
3301*61046927SAndroid Build Coastguard Worker },
3302*61046927SAndroid Build Coastguard Worker );
3303*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, Dst::None);
3304*61046927SAndroid Build Coastguard Worker }
3305*61046927SAndroid Build Coastguard Worker }
3306*61046927SAndroid Build Coastguard Worker
3307*61046927SAndroid Build Coastguard Worker impl SM70Op for OpS2R {
legalize(&mut self, _b: &mut LegalizeBuilder)3308*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, _b: &mut LegalizeBuilder) {
3309*61046927SAndroid Build Coastguard Worker // Nothing to do
3310*61046927SAndroid Build Coastguard Worker }
3311*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3312*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3313*61046927SAndroid Build Coastguard Worker assert!(!self.is_uniform());
3314*61046927SAndroid Build Coastguard Worker e.set_opcode(if self.is_uniform() { 0x9c3 } else { 0x919 });
3315*61046927SAndroid Build Coastguard Worker e.set_dst(self.dst);
3316*61046927SAndroid Build Coastguard Worker e.set_field(72..80, self.idx);
3317*61046927SAndroid Build Coastguard Worker }
3318*61046927SAndroid Build Coastguard Worker }
3319*61046927SAndroid Build Coastguard Worker
3320*61046927SAndroid Build Coastguard Worker impl SM70Op for OpOut {
legalize(&mut self, b: &mut LegalizeBuilder)3321*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
3322*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
3323*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(&mut self.handle, gpr, SrcType::GPR);
3324*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg_or_imm(&mut self.stream, gpr, SrcType::ALU);
3325*61046927SAndroid Build Coastguard Worker }
3326*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3327*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3328*61046927SAndroid Build Coastguard Worker e.encode_alu(
3329*61046927SAndroid Build Coastguard Worker 0x124,
3330*61046927SAndroid Build Coastguard Worker Some(&self.dst),
3331*61046927SAndroid Build Coastguard Worker Some(&self.handle),
3332*61046927SAndroid Build Coastguard Worker Some(&self.stream),
3333*61046927SAndroid Build Coastguard Worker None,
3334*61046927SAndroid Build Coastguard Worker );
3335*61046927SAndroid Build Coastguard Worker
3336*61046927SAndroid Build Coastguard Worker e.set_field(
3337*61046927SAndroid Build Coastguard Worker 78..80,
3338*61046927SAndroid Build Coastguard Worker match self.out_type {
3339*61046927SAndroid Build Coastguard Worker OutType::Emit => 1_u8,
3340*61046927SAndroid Build Coastguard Worker OutType::Cut => 2_u8,
3341*61046927SAndroid Build Coastguard Worker OutType::EmitThenCut => 3_u8,
3342*61046927SAndroid Build Coastguard Worker },
3343*61046927SAndroid Build Coastguard Worker );
3344*61046927SAndroid Build Coastguard Worker }
3345*61046927SAndroid Build Coastguard Worker }
3346*61046927SAndroid Build Coastguard Worker
3347*61046927SAndroid Build Coastguard Worker impl SM70Op for OpOutFinal {
legalize(&mut self, b: &mut LegalizeBuilder)3348*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
3349*61046927SAndroid Build Coastguard Worker let gpr = op_gpr(self);
3350*61046927SAndroid Build Coastguard Worker b.copy_alu_src_if_not_reg(&mut self.handle, gpr, SrcType::GPR);
3351*61046927SAndroid Build Coastguard Worker }
3352*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3353*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3354*61046927SAndroid Build Coastguard Worker e.encode_alu(
3355*61046927SAndroid Build Coastguard Worker 0x124,
3356*61046927SAndroid Build Coastguard Worker Some(&Dst::None),
3357*61046927SAndroid Build Coastguard Worker Some(&self.handle),
3358*61046927SAndroid Build Coastguard Worker Some(&Src::new_zero()),
3359*61046927SAndroid Build Coastguard Worker None,
3360*61046927SAndroid Build Coastguard Worker );
3361*61046927SAndroid Build Coastguard Worker }
3362*61046927SAndroid Build Coastguard Worker }
3363*61046927SAndroid Build Coastguard Worker
3364*61046927SAndroid Build Coastguard Worker impl SM70Op for OpVote {
legalize(&mut self, b: &mut LegalizeBuilder)3365*61046927SAndroid Build Coastguard Worker fn legalize(&mut self, b: &mut LegalizeBuilder) {
3366*61046927SAndroid Build Coastguard Worker b.copy_src_if_upred(&mut self.pred);
3367*61046927SAndroid Build Coastguard Worker }
3368*61046927SAndroid Build Coastguard Worker
encode(&self, e: &mut SM70Encoder<'_>)3369*61046927SAndroid Build Coastguard Worker fn encode(&self, e: &mut SM70Encoder<'_>) {
3370*61046927SAndroid Build Coastguard Worker if self.is_uniform() {
3371*61046927SAndroid Build Coastguard Worker e.set_opcode(0x886);
3372*61046927SAndroid Build Coastguard Worker e.set_udst(self.ballot);
3373*61046927SAndroid Build Coastguard Worker } else {
3374*61046927SAndroid Build Coastguard Worker e.set_opcode(0x806);
3375*61046927SAndroid Build Coastguard Worker e.set_dst(self.ballot);
3376*61046927SAndroid Build Coastguard Worker }
3377*61046927SAndroid Build Coastguard Worker
3378*61046927SAndroid Build Coastguard Worker e.set_field(
3379*61046927SAndroid Build Coastguard Worker 72..74,
3380*61046927SAndroid Build Coastguard Worker match self.op {
3381*61046927SAndroid Build Coastguard Worker VoteOp::All => 0_u8,
3382*61046927SAndroid Build Coastguard Worker VoteOp::Any => 1_u8,
3383*61046927SAndroid Build Coastguard Worker VoteOp::Eq => 2_u8,
3384*61046927SAndroid Build Coastguard Worker },
3385*61046927SAndroid Build Coastguard Worker );
3386*61046927SAndroid Build Coastguard Worker
3387*61046927SAndroid Build Coastguard Worker e.set_pred_dst(81..84, self.vote);
3388*61046927SAndroid Build Coastguard Worker e.set_pred_src(87..90, 90, self.pred);
3389*61046927SAndroid Build Coastguard Worker }
3390*61046927SAndroid Build Coastguard Worker }
3391*61046927SAndroid Build Coastguard Worker
3392*61046927SAndroid Build Coastguard Worker macro_rules! as_sm70_op_match {
3393*61046927SAndroid Build Coastguard Worker ($op: expr) => {
3394*61046927SAndroid Build Coastguard Worker match $op {
3395*61046927SAndroid Build Coastguard Worker Op::FAdd(op) => op,
3396*61046927SAndroid Build Coastguard Worker Op::FFma(op) => op,
3397*61046927SAndroid Build Coastguard Worker Op::FMnMx(op) => op,
3398*61046927SAndroid Build Coastguard Worker Op::FMul(op) => op,
3399*61046927SAndroid Build Coastguard Worker Op::FSet(op) => op,
3400*61046927SAndroid Build Coastguard Worker Op::FSetP(op) => op,
3401*61046927SAndroid Build Coastguard Worker Op::FSwzAdd(op) => op,
3402*61046927SAndroid Build Coastguard Worker Op::DAdd(op) => op,
3403*61046927SAndroid Build Coastguard Worker Op::DFma(op) => op,
3404*61046927SAndroid Build Coastguard Worker Op::DMul(op) => op,
3405*61046927SAndroid Build Coastguard Worker Op::DSetP(op) => op,
3406*61046927SAndroid Build Coastguard Worker Op::HAdd2(op) => op,
3407*61046927SAndroid Build Coastguard Worker Op::HFma2(op) => op,
3408*61046927SAndroid Build Coastguard Worker Op::HMul2(op) => op,
3409*61046927SAndroid Build Coastguard Worker Op::HSet2(op) => op,
3410*61046927SAndroid Build Coastguard Worker Op::HSetP2(op) => op,
3411*61046927SAndroid Build Coastguard Worker Op::HMnMx2(op) => op,
3412*61046927SAndroid Build Coastguard Worker Op::MuFu(op) => op,
3413*61046927SAndroid Build Coastguard Worker Op::BMsk(op) => op,
3414*61046927SAndroid Build Coastguard Worker Op::BRev(op) => op,
3415*61046927SAndroid Build Coastguard Worker Op::Flo(op) => op,
3416*61046927SAndroid Build Coastguard Worker Op::IAbs(op) => op,
3417*61046927SAndroid Build Coastguard Worker Op::IAdd3(op) => op,
3418*61046927SAndroid Build Coastguard Worker Op::IAdd3X(op) => op,
3419*61046927SAndroid Build Coastguard Worker Op::IDp4(op) => op,
3420*61046927SAndroid Build Coastguard Worker Op::IMad(op) => op,
3421*61046927SAndroid Build Coastguard Worker Op::IMad64(op) => op,
3422*61046927SAndroid Build Coastguard Worker Op::IMnMx(op) => op,
3423*61046927SAndroid Build Coastguard Worker Op::ISetP(op) => op,
3424*61046927SAndroid Build Coastguard Worker Op::Lop3(op) => op,
3425*61046927SAndroid Build Coastguard Worker Op::PopC(op) => op,
3426*61046927SAndroid Build Coastguard Worker Op::Shf(op) => op,
3427*61046927SAndroid Build Coastguard Worker Op::F2F(op) => op,
3428*61046927SAndroid Build Coastguard Worker Op::F2FP(op) => op,
3429*61046927SAndroid Build Coastguard Worker Op::F2I(op) => op,
3430*61046927SAndroid Build Coastguard Worker Op::I2F(op) => op,
3431*61046927SAndroid Build Coastguard Worker Op::FRnd(op) => op,
3432*61046927SAndroid Build Coastguard Worker Op::Mov(op) => op,
3433*61046927SAndroid Build Coastguard Worker Op::Prmt(op) => op,
3434*61046927SAndroid Build Coastguard Worker Op::Sel(op) => op,
3435*61046927SAndroid Build Coastguard Worker Op::Shfl(op) => op,
3436*61046927SAndroid Build Coastguard Worker Op::PLop3(op) => op,
3437*61046927SAndroid Build Coastguard Worker Op::R2UR(op) => op,
3438*61046927SAndroid Build Coastguard Worker Op::Tex(op) => op,
3439*61046927SAndroid Build Coastguard Worker Op::Tld(op) => op,
3440*61046927SAndroid Build Coastguard Worker Op::Tld4(op) => op,
3441*61046927SAndroid Build Coastguard Worker Op::Tmml(op) => op,
3442*61046927SAndroid Build Coastguard Worker Op::Txd(op) => op,
3443*61046927SAndroid Build Coastguard Worker Op::Txq(op) => op,
3444*61046927SAndroid Build Coastguard Worker Op::SuLd(op) => op,
3445*61046927SAndroid Build Coastguard Worker Op::SuSt(op) => op,
3446*61046927SAndroid Build Coastguard Worker Op::SuAtom(op) => op,
3447*61046927SAndroid Build Coastguard Worker Op::Ld(op) => op,
3448*61046927SAndroid Build Coastguard Worker Op::Ldc(op) => op,
3449*61046927SAndroid Build Coastguard Worker Op::St(op) => op,
3450*61046927SAndroid Build Coastguard Worker Op::Atom(op) => op,
3451*61046927SAndroid Build Coastguard Worker Op::AL2P(op) => op,
3452*61046927SAndroid Build Coastguard Worker Op::ALd(op) => op,
3453*61046927SAndroid Build Coastguard Worker Op::ASt(op) => op,
3454*61046927SAndroid Build Coastguard Worker Op::Ipa(op) => op,
3455*61046927SAndroid Build Coastguard Worker Op::LdTram(op) => op,
3456*61046927SAndroid Build Coastguard Worker Op::CCtl(op) => op,
3457*61046927SAndroid Build Coastguard Worker Op::MemBar(op) => op,
3458*61046927SAndroid Build Coastguard Worker Op::BClear(op) => op,
3459*61046927SAndroid Build Coastguard Worker Op::BMov(op) => op,
3460*61046927SAndroid Build Coastguard Worker Op::Break(op) => op,
3461*61046927SAndroid Build Coastguard Worker Op::BSSy(op) => op,
3462*61046927SAndroid Build Coastguard Worker Op::BSync(op) => op,
3463*61046927SAndroid Build Coastguard Worker Op::Bra(op) => op,
3464*61046927SAndroid Build Coastguard Worker Op::Exit(op) => op,
3465*61046927SAndroid Build Coastguard Worker Op::WarpSync(op) => op,
3466*61046927SAndroid Build Coastguard Worker Op::Bar(op) => op,
3467*61046927SAndroid Build Coastguard Worker Op::CS2R(op) => op,
3468*61046927SAndroid Build Coastguard Worker Op::Isberd(op) => op,
3469*61046927SAndroid Build Coastguard Worker Op::Kill(op) => op,
3470*61046927SAndroid Build Coastguard Worker Op::Nop(op) => op,
3471*61046927SAndroid Build Coastguard Worker Op::PixLd(op) => op,
3472*61046927SAndroid Build Coastguard Worker Op::S2R(op) => op,
3473*61046927SAndroid Build Coastguard Worker Op::Out(op) => op,
3474*61046927SAndroid Build Coastguard Worker Op::OutFinal(op) => op,
3475*61046927SAndroid Build Coastguard Worker Op::Vote(op) => op,
3476*61046927SAndroid Build Coastguard Worker _ => panic!("Unsupported op: {}", $op),
3477*61046927SAndroid Build Coastguard Worker }
3478*61046927SAndroid Build Coastguard Worker };
3479*61046927SAndroid Build Coastguard Worker }
3480*61046927SAndroid Build Coastguard Worker
as_sm70_op(op: &Op) -> &dyn SM70Op3481*61046927SAndroid Build Coastguard Worker fn as_sm70_op(op: &Op) -> &dyn SM70Op {
3482*61046927SAndroid Build Coastguard Worker as_sm70_op_match!(op)
3483*61046927SAndroid Build Coastguard Worker }
3484*61046927SAndroid Build Coastguard Worker
as_sm70_op_mut(op: &mut Op) -> &mut dyn SM70Op3485*61046927SAndroid Build Coastguard Worker fn as_sm70_op_mut(op: &mut Op) -> &mut dyn SM70Op {
3486*61046927SAndroid Build Coastguard Worker as_sm70_op_match!(op)
3487*61046927SAndroid Build Coastguard Worker }
3488*61046927SAndroid Build Coastguard Worker
encode_sm70_shader(sm: &ShaderModel70, s: &Shader<'_>) -> Vec<u32>3489*61046927SAndroid Build Coastguard Worker fn encode_sm70_shader(sm: &ShaderModel70, s: &Shader<'_>) -> Vec<u32> {
3490*61046927SAndroid Build Coastguard Worker assert!(s.functions.len() == 1);
3491*61046927SAndroid Build Coastguard Worker let func = &s.functions[0];
3492*61046927SAndroid Build Coastguard Worker
3493*61046927SAndroid Build Coastguard Worker let mut ip = 0_usize;
3494*61046927SAndroid Build Coastguard Worker let mut labels = HashMap::new();
3495*61046927SAndroid Build Coastguard Worker for b in &func.blocks {
3496*61046927SAndroid Build Coastguard Worker labels.insert(b.label, ip);
3497*61046927SAndroid Build Coastguard Worker for instr in &b.instrs {
3498*61046927SAndroid Build Coastguard Worker if let Op::Nop(op) = &instr.op {
3499*61046927SAndroid Build Coastguard Worker if let Some(label) = op.label {
3500*61046927SAndroid Build Coastguard Worker labels.insert(label, ip);
3501*61046927SAndroid Build Coastguard Worker }
3502*61046927SAndroid Build Coastguard Worker }
3503*61046927SAndroid Build Coastguard Worker ip += 4;
3504*61046927SAndroid Build Coastguard Worker }
3505*61046927SAndroid Build Coastguard Worker }
3506*61046927SAndroid Build Coastguard Worker
3507*61046927SAndroid Build Coastguard Worker let mut encoded = Vec::new();
3508*61046927SAndroid Build Coastguard Worker for b in &func.blocks {
3509*61046927SAndroid Build Coastguard Worker for instr in &b.instrs {
3510*61046927SAndroid Build Coastguard Worker let mut e = SM70Encoder {
3511*61046927SAndroid Build Coastguard Worker sm,
3512*61046927SAndroid Build Coastguard Worker ip: encoded.len(),
3513*61046927SAndroid Build Coastguard Worker labels: &labels,
3514*61046927SAndroid Build Coastguard Worker inst: [0_u32; 4],
3515*61046927SAndroid Build Coastguard Worker };
3516*61046927SAndroid Build Coastguard Worker as_sm70_op(&instr.op).encode(&mut e);
3517*61046927SAndroid Build Coastguard Worker e.set_pred(&instr.pred);
3518*61046927SAndroid Build Coastguard Worker e.set_instr_deps(&instr.deps);
3519*61046927SAndroid Build Coastguard Worker encoded.extend_from_slice(&e.inst[..]);
3520*61046927SAndroid Build Coastguard Worker }
3521*61046927SAndroid Build Coastguard Worker }
3522*61046927SAndroid Build Coastguard Worker encoded
3523*61046927SAndroid Build Coastguard Worker }
3524