xref: /aosp_15_r20/external/mesa3d/src/nouveau/compiler/nak/sm70.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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