xref: /aosp_15_r20/external/mesa3d/src/nouveau/compiler/nak/sm50.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker // Copyright © 2023 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, swap_srcs_if_not_reg, LegalizeBuildHelpers, LegalizeBuilder,
7*61046927SAndroid Build Coastguard Worker };
8*61046927SAndroid Build Coastguard Worker use bitview::*;
9*61046927SAndroid Build Coastguard Worker 
10*61046927SAndroid Build Coastguard Worker use std::collections::HashMap;
11*61046927SAndroid Build Coastguard Worker use std::ops::Range;
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker pub struct ShaderModel50 {
14*61046927SAndroid Build Coastguard Worker     sm: u8,
15*61046927SAndroid Build Coastguard Worker }
16*61046927SAndroid Build Coastguard Worker 
17*61046927SAndroid Build Coastguard Worker impl ShaderModel50 {
new(sm: u8) -> Self18*61046927SAndroid Build Coastguard Worker     pub fn new(sm: u8) -> Self {
19*61046927SAndroid Build Coastguard Worker         assert!(sm >= 50 && sm < 70);
20*61046927SAndroid Build Coastguard Worker         Self { sm }
21*61046927SAndroid Build Coastguard Worker     }
22*61046927SAndroid Build Coastguard Worker }
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker impl ShaderModel for ShaderModel50 {
sm(&self) -> u825*61046927SAndroid Build Coastguard Worker     fn sm(&self) -> u8 {
26*61046927SAndroid Build Coastguard Worker         self.sm
27*61046927SAndroid Build Coastguard Worker     }
28*61046927SAndroid Build Coastguard Worker 
num_regs(&self, file: RegFile) -> u3229*61046927SAndroid Build Coastguard Worker     fn num_regs(&self, file: RegFile) -> u32 {
30*61046927SAndroid Build Coastguard Worker         match file {
31*61046927SAndroid Build Coastguard Worker             RegFile::GPR => 255,
32*61046927SAndroid Build Coastguard Worker             RegFile::UGPR => 0,
33*61046927SAndroid Build Coastguard Worker             RegFile::Pred => 7,
34*61046927SAndroid Build Coastguard Worker             RegFile::UPred => 0,
35*61046927SAndroid Build Coastguard Worker             RegFile::Carry => 1,
36*61046927SAndroid Build Coastguard Worker             RegFile::Bar => 0,
37*61046927SAndroid Build Coastguard Worker             RegFile::Mem => RegRef::MAX_IDX + 1,
38*61046927SAndroid Build Coastguard Worker         }
39*61046927SAndroid Build Coastguard Worker     }
40*61046927SAndroid Build Coastguard Worker 
crs_size(&self, max_crs_depth: u32) -> u3241*61046927SAndroid Build Coastguard Worker     fn crs_size(&self, max_crs_depth: u32) -> u32 {
42*61046927SAndroid Build Coastguard Worker         if max_crs_depth <= 16 {
43*61046927SAndroid Build Coastguard Worker             0
44*61046927SAndroid Build Coastguard Worker         } else if max_crs_depth <= 32 {
45*61046927SAndroid Build Coastguard Worker             1024
46*61046927SAndroid Build Coastguard Worker         } else {
47*61046927SAndroid Build Coastguard Worker             ((max_crs_depth + 32) * 16).next_multiple_of(512)
48*61046927SAndroid Build Coastguard Worker         }
49*61046927SAndroid Build Coastguard Worker     }
50*61046927SAndroid Build Coastguard Worker 
op_can_be_uniform(&self, _op: &Op) -> bool51*61046927SAndroid Build Coastguard Worker     fn op_can_be_uniform(&self, _op: &Op) -> bool {
52*61046927SAndroid Build Coastguard Worker         false
53*61046927SAndroid Build Coastguard Worker     }
54*61046927SAndroid Build Coastguard Worker 
legalize_op(&self, b: &mut LegalizeBuilder, op: &mut Op)55*61046927SAndroid Build Coastguard Worker     fn legalize_op(&self, b: &mut LegalizeBuilder, op: &mut Op) {
56*61046927SAndroid Build Coastguard Worker         as_sm50_op_mut(op).legalize(b);
57*61046927SAndroid Build Coastguard Worker     }
58*61046927SAndroid Build Coastguard Worker 
encode_shader(&self, s: &Shader<'_>) -> Vec<u32>59*61046927SAndroid Build Coastguard Worker     fn encode_shader(&self, s: &Shader<'_>) -> Vec<u32> {
60*61046927SAndroid Build Coastguard Worker         encode_sm50_shader(self, s)
61*61046927SAndroid Build Coastguard Worker     }
62*61046927SAndroid Build Coastguard Worker }
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker trait SM50Op {
legalize(&mut self, b: &mut LegalizeBuilder)65*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder);
encode(&self, e: &mut SM50Encoder<'_>)66*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>);
67*61046927SAndroid Build Coastguard Worker }
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker struct SM50Encoder<'a> {
70*61046927SAndroid Build Coastguard Worker     sm: &'a ShaderModel50,
71*61046927SAndroid Build Coastguard Worker     ip: usize,
72*61046927SAndroid Build Coastguard Worker     labels: &'a HashMap<Label, usize>,
73*61046927SAndroid Build Coastguard Worker     inst: [u32; 2],
74*61046927SAndroid Build Coastguard Worker     sched: u32,
75*61046927SAndroid Build Coastguard Worker }
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker impl BitViewable for SM50Encoder<'_> {
bits(&self) -> usize78*61046927SAndroid Build Coastguard Worker     fn bits(&self) -> usize {
79*61046927SAndroid Build Coastguard Worker         BitView::new(&self.inst).bits()
80*61046927SAndroid Build Coastguard Worker     }
81*61046927SAndroid Build Coastguard Worker 
get_bit_range_u64(&self, range: Range<usize>) -> u6482*61046927SAndroid Build Coastguard Worker     fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
83*61046927SAndroid Build Coastguard Worker         BitView::new(&self.inst).get_bit_range_u64(range)
84*61046927SAndroid Build Coastguard Worker     }
85*61046927SAndroid Build Coastguard Worker }
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker impl BitMutViewable for SM50Encoder<'_> {
set_bit_range_u64(&mut self, range: Range<usize>, val: u64)88*61046927SAndroid Build Coastguard Worker     fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
89*61046927SAndroid Build Coastguard Worker         BitMutView::new(&mut self.inst).set_bit_range_u64(range, val);
90*61046927SAndroid Build Coastguard Worker     }
91*61046927SAndroid Build Coastguard Worker }
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker impl SetFieldU64 for SM50Encoder<'_> {
set_field_u64(&mut self, range: Range<usize>, val: u64)94*61046927SAndroid Build Coastguard Worker     fn set_field_u64(&mut self, range: Range<usize>, val: u64) {
95*61046927SAndroid Build Coastguard Worker         BitMutView::new(&mut self.inst).set_field_u64(range, val);
96*61046927SAndroid Build Coastguard Worker     }
97*61046927SAndroid Build Coastguard Worker }
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker impl SM50Encoder<'_> {
set_opcode(&mut self, opcode: u16)100*61046927SAndroid Build Coastguard Worker     fn set_opcode(&mut self, opcode: u16) {
101*61046927SAndroid Build Coastguard Worker         self.set_field(48..64, opcode);
102*61046927SAndroid Build Coastguard Worker     }
103*61046927SAndroid Build Coastguard Worker 
set_pred_reg(&mut self, range: Range<usize>, reg: RegRef)104*61046927SAndroid Build Coastguard Worker     fn set_pred_reg(&mut self, range: Range<usize>, reg: RegRef) {
105*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 3);
106*61046927SAndroid Build Coastguard Worker         assert!(reg.file() == RegFile::Pred);
107*61046927SAndroid Build Coastguard Worker         assert!(reg.base_idx() <= 7);
108*61046927SAndroid Build Coastguard Worker         assert!(reg.comps() == 1);
109*61046927SAndroid Build Coastguard Worker         self.set_field(range, reg.base_idx());
110*61046927SAndroid Build Coastguard Worker     }
111*61046927SAndroid Build Coastguard Worker 
set_pred(&mut self, pred: &Pred)112*61046927SAndroid Build Coastguard Worker     fn set_pred(&mut self, pred: &Pred) {
113*61046927SAndroid Build Coastguard Worker         assert!(!pred.is_false());
114*61046927SAndroid Build Coastguard Worker         self.set_pred_reg(
115*61046927SAndroid Build Coastguard Worker             16..19,
116*61046927SAndroid Build Coastguard Worker             match pred.pred_ref {
117*61046927SAndroid Build Coastguard Worker                 PredRef::None => RegRef::zero(RegFile::Pred, 1),
118*61046927SAndroid Build Coastguard Worker                 PredRef::Reg(reg) => reg,
119*61046927SAndroid Build Coastguard Worker                 PredRef::SSA(_) => panic!("SSA values must be lowered"),
120*61046927SAndroid Build Coastguard Worker             },
121*61046927SAndroid Build Coastguard Worker         );
122*61046927SAndroid Build Coastguard Worker         self.set_bit(19, pred.pred_inv);
123*61046927SAndroid Build Coastguard Worker     }
124*61046927SAndroid Build Coastguard Worker 
set_instr_deps(&mut self, deps: &InstrDeps)125*61046927SAndroid Build Coastguard Worker     fn set_instr_deps(&mut self, deps: &InstrDeps) {
126*61046927SAndroid Build Coastguard Worker         let mut sched = BitMutView::new(&mut self.sched);
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker         sched.set_field(0..4, deps.delay);
129*61046927SAndroid Build Coastguard Worker         sched.set_bit(4, deps.yld);
130*61046927SAndroid Build Coastguard Worker         sched.set_field(5..8, deps.wr_bar().unwrap_or(7));
131*61046927SAndroid Build Coastguard Worker         sched.set_field(8..11, deps.rd_bar().unwrap_or(7));
132*61046927SAndroid Build Coastguard Worker         sched.set_field(11..17, deps.wt_bar_mask);
133*61046927SAndroid Build Coastguard Worker         sched.set_field(17..21, deps.reuse_mask);
134*61046927SAndroid Build Coastguard Worker     }
135*61046927SAndroid Build Coastguard Worker 
set_reg(&mut self, range: Range<usize>, reg: RegRef)136*61046927SAndroid Build Coastguard Worker     fn set_reg(&mut self, range: Range<usize>, reg: RegRef) {
137*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 8);
138*61046927SAndroid Build Coastguard Worker         assert!(reg.file() == RegFile::GPR);
139*61046927SAndroid Build Coastguard Worker         self.set_field(range, reg.base_idx());
140*61046927SAndroid Build Coastguard Worker     }
141*61046927SAndroid Build Coastguard Worker 
set_reg_src_ref(&mut self, range: Range<usize>, src_ref: SrcRef)142*61046927SAndroid Build Coastguard Worker     fn set_reg_src_ref(&mut self, range: Range<usize>, src_ref: SrcRef) {
143*61046927SAndroid Build Coastguard Worker         match src_ref {
144*61046927SAndroid Build Coastguard Worker             SrcRef::Zero => self.set_reg(range, RegRef::zero(RegFile::GPR, 1)),
145*61046927SAndroid Build Coastguard Worker             SrcRef::Reg(reg) => self.set_reg(range, reg),
146*61046927SAndroid Build Coastguard Worker             _ => panic!("Not a register"),
147*61046927SAndroid Build Coastguard Worker         }
148*61046927SAndroid Build Coastguard Worker     }
149*61046927SAndroid Build Coastguard Worker 
set_reg_src(&mut self, range: Range<usize>, src: Src)150*61046927SAndroid Build Coastguard Worker     fn set_reg_src(&mut self, range: Range<usize>, src: Src) {
151*61046927SAndroid Build Coastguard Worker         assert!(src.src_mod.is_none());
152*61046927SAndroid Build Coastguard Worker         self.set_reg_src_ref(range, src.src_ref);
153*61046927SAndroid Build Coastguard Worker     }
154*61046927SAndroid Build Coastguard Worker 
set_reg_fmod_src( &mut self, range: Range<usize>, abs_bit: usize, neg_bit: usize, src: Src, )155*61046927SAndroid Build Coastguard Worker     fn set_reg_fmod_src(
156*61046927SAndroid Build Coastguard Worker         &mut self,
157*61046927SAndroid Build Coastguard Worker         range: Range<usize>,
158*61046927SAndroid Build Coastguard Worker         abs_bit: usize,
159*61046927SAndroid Build Coastguard Worker         neg_bit: usize,
160*61046927SAndroid Build Coastguard Worker         src: Src,
161*61046927SAndroid Build Coastguard Worker     ) {
162*61046927SAndroid Build Coastguard Worker         self.set_reg_src_ref(range, src.src_ref);
163*61046927SAndroid Build Coastguard Worker         self.set_bit(abs_bit, src.src_mod.has_fabs());
164*61046927SAndroid Build Coastguard Worker         self.set_bit(neg_bit, src.src_mod.has_fneg());
165*61046927SAndroid Build Coastguard Worker     }
166*61046927SAndroid Build Coastguard Worker 
set_reg_ineg_src( &mut self, range: Range<usize>, neg_bit: usize, src: Src, )167*61046927SAndroid Build Coastguard Worker     fn set_reg_ineg_src(
168*61046927SAndroid Build Coastguard Worker         &mut self,
169*61046927SAndroid Build Coastguard Worker         range: Range<usize>,
170*61046927SAndroid Build Coastguard Worker         neg_bit: usize,
171*61046927SAndroid Build Coastguard Worker         src: Src,
172*61046927SAndroid Build Coastguard Worker     ) {
173*61046927SAndroid Build Coastguard Worker         self.set_reg_src_ref(range, src.src_ref);
174*61046927SAndroid Build Coastguard Worker         self.set_bit(neg_bit, src.src_mod.is_ineg());
175*61046927SAndroid Build Coastguard Worker     }
176*61046927SAndroid Build Coastguard Worker 
set_reg_bnot_src( &mut self, range: Range<usize>, not_bit: usize, src: Src, )177*61046927SAndroid Build Coastguard Worker     fn set_reg_bnot_src(
178*61046927SAndroid Build Coastguard Worker         &mut self,
179*61046927SAndroid Build Coastguard Worker         range: Range<usize>,
180*61046927SAndroid Build Coastguard Worker         not_bit: usize,
181*61046927SAndroid Build Coastguard Worker         src: Src,
182*61046927SAndroid Build Coastguard Worker     ) {
183*61046927SAndroid Build Coastguard Worker         self.set_reg_src_ref(range, src.src_ref);
184*61046927SAndroid Build Coastguard Worker         self.set_bit(not_bit, src.src_mod.is_bnot());
185*61046927SAndroid Build Coastguard Worker     }
186*61046927SAndroid Build Coastguard Worker 
set_pred_dst(&mut self, range: Range<usize>, dst: Dst)187*61046927SAndroid Build Coastguard Worker     fn set_pred_dst(&mut self, range: Range<usize>, dst: Dst) {
188*61046927SAndroid Build Coastguard Worker         match dst {
189*61046927SAndroid Build Coastguard Worker             Dst::None => {
190*61046927SAndroid Build Coastguard Worker                 self.set_pred_reg(range, RegRef::zero(RegFile::Pred, 1));
191*61046927SAndroid Build Coastguard Worker             }
192*61046927SAndroid Build Coastguard Worker             Dst::Reg(reg) => self.set_pred_reg(range, reg),
193*61046927SAndroid Build Coastguard Worker             _ => panic!("Not a register"),
194*61046927SAndroid Build Coastguard Worker         }
195*61046927SAndroid Build Coastguard Worker     }
196*61046927SAndroid Build Coastguard Worker 
set_pred_src(&mut self, range: Range<usize>, not_bit: usize, src: Src)197*61046927SAndroid Build Coastguard Worker     fn set_pred_src(&mut self, range: Range<usize>, not_bit: usize, src: Src) {
198*61046927SAndroid Build Coastguard Worker         // The default for predicates is true
199*61046927SAndroid Build Coastguard Worker         let true_reg = RegRef::new(RegFile::Pred, 7, 1);
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker         let (not, reg) = match src.src_ref {
202*61046927SAndroid Build Coastguard Worker             SrcRef::True => (false, true_reg),
203*61046927SAndroid Build Coastguard Worker             SrcRef::False => (true, true_reg),
204*61046927SAndroid Build Coastguard Worker             SrcRef::Reg(reg) => (false, reg),
205*61046927SAndroid Build Coastguard Worker             _ => panic!("Not a register"),
206*61046927SAndroid Build Coastguard Worker         };
207*61046927SAndroid Build Coastguard Worker         self.set_pred_reg(range, reg);
208*61046927SAndroid Build Coastguard Worker         self.set_bit(not_bit, not ^ src.src_mod.is_bnot());
209*61046927SAndroid Build Coastguard Worker     }
210*61046927SAndroid Build Coastguard Worker 
set_dst(&mut self, dst: Dst)211*61046927SAndroid Build Coastguard Worker     fn set_dst(&mut self, dst: Dst) {
212*61046927SAndroid Build Coastguard Worker         let reg = match dst {
213*61046927SAndroid Build Coastguard Worker             Dst::None => RegRef::zero(RegFile::GPR, 1),
214*61046927SAndroid Build Coastguard Worker             Dst::Reg(reg) => reg,
215*61046927SAndroid Build Coastguard Worker             _ => panic!("invalid dst {dst}"),
216*61046927SAndroid Build Coastguard Worker         };
217*61046927SAndroid Build Coastguard Worker         self.set_reg(0..8, reg);
218*61046927SAndroid Build Coastguard Worker     }
219*61046927SAndroid Build Coastguard Worker 
set_src_imm32(&mut self, range: Range<usize>, u: u32)220*61046927SAndroid Build Coastguard Worker     fn set_src_imm32(&mut self, range: Range<usize>, u: u32) {
221*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 32);
222*61046927SAndroid Build Coastguard Worker         self.set_field(range, u);
223*61046927SAndroid Build Coastguard Worker     }
224*61046927SAndroid Build Coastguard Worker 
set_src_imm_i20( &mut self, range: Range<usize>, sign_bit: usize, i: u32, )225*61046927SAndroid Build Coastguard Worker     fn set_src_imm_i20(
226*61046927SAndroid Build Coastguard Worker         &mut self,
227*61046927SAndroid Build Coastguard Worker         range: Range<usize>,
228*61046927SAndroid Build Coastguard Worker         sign_bit: usize,
229*61046927SAndroid Build Coastguard Worker         i: u32,
230*61046927SAndroid Build Coastguard Worker     ) {
231*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 19);
232*61046927SAndroid Build Coastguard Worker         assert!((i & 0xfff80000) == 0 || (i & 0xfff80000) == 0xfff80000);
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker         self.set_field(range, i & 0x7ffff);
235*61046927SAndroid Build Coastguard Worker         self.set_field(sign_bit..sign_bit + 1, (i & 0x80000) >> 19);
236*61046927SAndroid Build Coastguard Worker     }
237*61046927SAndroid Build Coastguard Worker 
set_src_imm_f20( &mut self, range: Range<usize>, sign_bit: usize, f: u32, )238*61046927SAndroid Build Coastguard Worker     fn set_src_imm_f20(
239*61046927SAndroid Build Coastguard Worker         &mut self,
240*61046927SAndroid Build Coastguard Worker         range: Range<usize>,
241*61046927SAndroid Build Coastguard Worker         sign_bit: usize,
242*61046927SAndroid Build Coastguard Worker         f: u32,
243*61046927SAndroid Build Coastguard Worker     ) {
244*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 19);
245*61046927SAndroid Build Coastguard Worker         assert!((f & 0x00000fff) == 0);
246*61046927SAndroid Build Coastguard Worker 
247*61046927SAndroid Build Coastguard Worker         self.set_field(range, (f >> 12) & 0x7ffff);
248*61046927SAndroid Build Coastguard Worker         self.set_field(sign_bit..sign_bit + 1, f >> 31);
249*61046927SAndroid Build Coastguard Worker     }
250*61046927SAndroid Build Coastguard Worker 
set_src_cb(&mut self, range: Range<usize>, cb: &CBufRef)251*61046927SAndroid Build Coastguard Worker     fn set_src_cb(&mut self, range: Range<usize>, cb: &CBufRef) {
252*61046927SAndroid Build Coastguard Worker         let mut v = BitMutView::new_subset(self, range);
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker         assert!(cb.offset % 4 == 0);
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker         v.set_field(0..14, cb.offset >> 2);
257*61046927SAndroid Build Coastguard Worker         if let CBuf::Binding(idx) = cb.buf {
258*61046927SAndroid Build Coastguard Worker             v.set_field(14..19, idx);
259*61046927SAndroid Build Coastguard Worker         } else {
260*61046927SAndroid Build Coastguard Worker             panic!("Must be a bound constant buffer");
261*61046927SAndroid Build Coastguard Worker         }
262*61046927SAndroid Build Coastguard Worker     }
263*61046927SAndroid Build Coastguard Worker 
set_cb_fmod_src( &mut self, range: Range<usize>, abs_bit: usize, neg_bit: usize, src: Src, )264*61046927SAndroid Build Coastguard Worker     fn set_cb_fmod_src(
265*61046927SAndroid Build Coastguard Worker         &mut self,
266*61046927SAndroid Build Coastguard Worker         range: Range<usize>,
267*61046927SAndroid Build Coastguard Worker         abs_bit: usize,
268*61046927SAndroid Build Coastguard Worker         neg_bit: usize,
269*61046927SAndroid Build Coastguard Worker         src: Src,
270*61046927SAndroid Build Coastguard Worker     ) {
271*61046927SAndroid Build Coastguard Worker         if let SrcRef::CBuf(cb) = &src.src_ref {
272*61046927SAndroid Build Coastguard Worker             self.set_src_cb(range, cb);
273*61046927SAndroid Build Coastguard Worker         } else {
274*61046927SAndroid Build Coastguard Worker             panic!("Not a CBuf source");
275*61046927SAndroid Build Coastguard Worker         }
276*61046927SAndroid Build Coastguard Worker 
277*61046927SAndroid Build Coastguard Worker         self.set_bit(abs_bit, src.src_mod.has_fabs());
278*61046927SAndroid Build Coastguard Worker         self.set_bit(neg_bit, src.src_mod.has_fneg());
279*61046927SAndroid Build Coastguard Worker     }
280*61046927SAndroid Build Coastguard Worker 
set_cb_ineg_src( &mut self, range: Range<usize>, neg_bit: usize, src: Src, )281*61046927SAndroid Build Coastguard Worker     fn set_cb_ineg_src(
282*61046927SAndroid Build Coastguard Worker         &mut self,
283*61046927SAndroid Build Coastguard Worker         range: Range<usize>,
284*61046927SAndroid Build Coastguard Worker         neg_bit: usize,
285*61046927SAndroid Build Coastguard Worker         src: Src,
286*61046927SAndroid Build Coastguard Worker     ) {
287*61046927SAndroid Build Coastguard Worker         if let SrcRef::CBuf(cb) = &src.src_ref {
288*61046927SAndroid Build Coastguard Worker             self.set_src_cb(range, cb);
289*61046927SAndroid Build Coastguard Worker         } else {
290*61046927SAndroid Build Coastguard Worker             panic!("Not a CBuf source");
291*61046927SAndroid Build Coastguard Worker         }
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker         self.set_bit(neg_bit, src.src_mod.is_ineg());
294*61046927SAndroid Build Coastguard Worker     }
295*61046927SAndroid Build Coastguard Worker 
set_cb_bnot_src( &mut self, range: Range<usize>, not_bit: usize, src: Src, )296*61046927SAndroid Build Coastguard Worker     fn set_cb_bnot_src(
297*61046927SAndroid Build Coastguard Worker         &mut self,
298*61046927SAndroid Build Coastguard Worker         range: Range<usize>,
299*61046927SAndroid Build Coastguard Worker         not_bit: usize,
300*61046927SAndroid Build Coastguard Worker         src: Src,
301*61046927SAndroid Build Coastguard Worker     ) {
302*61046927SAndroid Build Coastguard Worker         if let SrcRef::CBuf(cb) = &src.src_ref {
303*61046927SAndroid Build Coastguard Worker             self.set_src_cb(range, cb);
304*61046927SAndroid Build Coastguard Worker         } else {
305*61046927SAndroid Build Coastguard Worker             panic!("Not a CBuf source");
306*61046927SAndroid Build Coastguard Worker         }
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker         self.set_bit(not_bit, src.src_mod.is_bnot());
309*61046927SAndroid Build Coastguard Worker     }
310*61046927SAndroid Build Coastguard Worker }
311*61046927SAndroid Build Coastguard Worker 
312*61046927SAndroid Build Coastguard Worker //
313*61046927SAndroid Build Coastguard Worker // Legalization helpers
314*61046927SAndroid Build Coastguard Worker //
315*61046927SAndroid Build Coastguard Worker 
316*61046927SAndroid Build Coastguard Worker pub trait SM50LegalizeBuildHelpers: LegalizeBuildHelpers {
copy_alu_src_if_fabs(&mut self, src: &mut Src, src_type: SrcType)317*61046927SAndroid Build Coastguard Worker     fn copy_alu_src_if_fabs(&mut self, src: &mut Src, src_type: SrcType) {
318*61046927SAndroid Build Coastguard Worker         if src.src_mod.has_fabs() {
319*61046927SAndroid Build Coastguard Worker             self.copy_alu_src_and_lower_fmod(src, src_type);
320*61046927SAndroid Build Coastguard Worker         }
321*61046927SAndroid Build Coastguard Worker     }
322*61046927SAndroid Build Coastguard Worker 
copy_alu_src_if_i20_overflow( &mut self, src: &mut Src, reg_file: RegFile, src_type: SrcType, )323*61046927SAndroid Build Coastguard Worker     fn copy_alu_src_if_i20_overflow(
324*61046927SAndroid Build Coastguard Worker         &mut self,
325*61046927SAndroid Build Coastguard Worker         src: &mut Src,
326*61046927SAndroid Build Coastguard Worker         reg_file: RegFile,
327*61046927SAndroid Build Coastguard Worker         src_type: SrcType,
328*61046927SAndroid Build Coastguard Worker     ) {
329*61046927SAndroid Build Coastguard Worker         if src.as_imm_not_i20().is_some() {
330*61046927SAndroid Build Coastguard Worker             self.copy_alu_src(src, reg_file, src_type);
331*61046927SAndroid Build Coastguard Worker         }
332*61046927SAndroid Build Coastguard Worker     }
333*61046927SAndroid Build Coastguard Worker 
copy_alu_src_if_f20_overflow( &mut self, src: &mut Src, reg_file: RegFile, src_type: SrcType, )334*61046927SAndroid Build Coastguard Worker     fn copy_alu_src_if_f20_overflow(
335*61046927SAndroid Build Coastguard Worker         &mut self,
336*61046927SAndroid Build Coastguard Worker         src: &mut Src,
337*61046927SAndroid Build Coastguard Worker         reg_file: RegFile,
338*61046927SAndroid Build Coastguard Worker         src_type: SrcType,
339*61046927SAndroid Build Coastguard Worker     ) {
340*61046927SAndroid Build Coastguard Worker         if src.as_imm_not_f20().is_some() {
341*61046927SAndroid Build Coastguard Worker             self.copy_alu_src(src, reg_file, src_type);
342*61046927SAndroid Build Coastguard Worker         }
343*61046927SAndroid Build Coastguard Worker     }
344*61046927SAndroid Build Coastguard Worker }
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker impl SM50LegalizeBuildHelpers for LegalizeBuilder<'_> {}
347*61046927SAndroid Build Coastguard Worker 
348*61046927SAndroid Build Coastguard Worker /// Helper to legalize extended or external instructions
349*61046927SAndroid Build Coastguard Worker ///
350*61046927SAndroid Build Coastguard Worker /// These are instructions which reach out external units such as load/store
351*61046927SAndroid Build Coastguard Worker /// and texture ops.  They typically can't take anything but GPRs and are the
352*61046927SAndroid Build Coastguard Worker /// only types of instructions that support vectors.
353*61046927SAndroid Build Coastguard Worker ///
legalize_ext_instr(op: &mut impl SrcsAsSlice, _b: &mut LegalizeBuilder)354*61046927SAndroid Build Coastguard Worker fn legalize_ext_instr(op: &mut impl SrcsAsSlice, _b: &mut LegalizeBuilder) {
355*61046927SAndroid Build Coastguard Worker     let src_types = op.src_types();
356*61046927SAndroid Build Coastguard Worker     for (i, src) in op.srcs_as_mut_slice().iter_mut().enumerate() {
357*61046927SAndroid Build Coastguard Worker         match src_types[i] {
358*61046927SAndroid Build Coastguard Worker             SrcType::SSA => {
359*61046927SAndroid Build Coastguard Worker                 assert!(src.as_ssa().is_some());
360*61046927SAndroid Build Coastguard Worker             }
361*61046927SAndroid Build Coastguard Worker             SrcType::GPR => {
362*61046927SAndroid Build Coastguard Worker                 assert!(src_is_reg(src, RegFile::GPR));
363*61046927SAndroid Build Coastguard Worker             }
364*61046927SAndroid Build Coastguard Worker             SrcType::ALU
365*61046927SAndroid Build Coastguard Worker             | SrcType::F16
366*61046927SAndroid Build Coastguard Worker             | SrcType::F16v2
367*61046927SAndroid Build Coastguard Worker             | SrcType::F32
368*61046927SAndroid Build Coastguard Worker             | SrcType::F64
369*61046927SAndroid Build Coastguard Worker             | SrcType::I32
370*61046927SAndroid Build Coastguard Worker             | SrcType::B32 => {
371*61046927SAndroid Build Coastguard Worker                 panic!("ALU srcs must be legalized explicitly");
372*61046927SAndroid Build Coastguard Worker             }
373*61046927SAndroid Build Coastguard Worker             SrcType::Pred => {
374*61046927SAndroid Build Coastguard Worker                 panic!("Predicates must be legalized explicitly");
375*61046927SAndroid Build Coastguard Worker             }
376*61046927SAndroid Build Coastguard Worker             SrcType::Carry => {
377*61046927SAndroid Build Coastguard Worker                 panic!("Carry values must be legalized explicitly");
378*61046927SAndroid Build Coastguard Worker             }
379*61046927SAndroid Build Coastguard Worker             SrcType::Bar => panic!("Barrier regs are Volta+"),
380*61046927SAndroid Build Coastguard Worker         }
381*61046927SAndroid Build Coastguard Worker     }
382*61046927SAndroid Build Coastguard Worker }
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker //
385*61046927SAndroid Build Coastguard Worker // Implementations of SM50Op for each op we support on Maxwell/Pascal
386*61046927SAndroid Build Coastguard Worker //
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker impl SM50Encoder<'_> {
set_rnd_mode(&mut self, range: Range<usize>, rnd_mode: FRndMode)389*61046927SAndroid Build Coastguard Worker     fn set_rnd_mode(&mut self, range: Range<usize>, rnd_mode: FRndMode) {
390*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 2);
391*61046927SAndroid Build Coastguard Worker         self.set_field(
392*61046927SAndroid Build Coastguard Worker             range,
393*61046927SAndroid Build Coastguard Worker             match rnd_mode {
394*61046927SAndroid Build Coastguard Worker                 FRndMode::NearestEven => 0_u8,
395*61046927SAndroid Build Coastguard Worker                 FRndMode::NegInf => 1_u8,
396*61046927SAndroid Build Coastguard Worker                 FRndMode::PosInf => 2_u8,
397*61046927SAndroid Build Coastguard Worker                 FRndMode::Zero => 3_u8,
398*61046927SAndroid Build Coastguard Worker             },
399*61046927SAndroid Build Coastguard Worker         );
400*61046927SAndroid Build Coastguard Worker     }
401*61046927SAndroid Build Coastguard Worker }
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker impl SM50Op for OpFAdd {
legalize(&mut self, b: &mut LegalizeBuilder)404*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
405*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
406*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
407*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
408*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F32);
409*61046927SAndroid Build Coastguard Worker     }
410*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)411*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
412*61046927SAndroid Build Coastguard Worker         if let Some(imm32) = self.srcs[1].as_imm_not_f20() {
413*61046927SAndroid Build Coastguard Worker             e.set_opcode(0x0800);
414*61046927SAndroid Build Coastguard Worker             e.set_dst(self.dst);
415*61046927SAndroid Build Coastguard Worker             e.set_reg_fmod_src(8..16, 54, 56, self.srcs[0]);
416*61046927SAndroid Build Coastguard Worker             e.set_src_imm32(20..52, imm32);
417*61046927SAndroid Build Coastguard Worker             e.set_bit(55, self.ftz);
418*61046927SAndroid Build Coastguard Worker         } else {
419*61046927SAndroid Build Coastguard Worker             match &self.srcs[1].src_ref {
420*61046927SAndroid Build Coastguard Worker                 SrcRef::Zero | SrcRef::Reg(_) => {
421*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x5c58);
422*61046927SAndroid Build Coastguard Worker                     e.set_reg_fmod_src(20..28, 49, 45, self.srcs[1]);
423*61046927SAndroid Build Coastguard Worker                 }
424*61046927SAndroid Build Coastguard Worker                 SrcRef::Imm32(imm32) => {
425*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x3858);
426*61046927SAndroid Build Coastguard Worker                     e.set_src_imm_f20(20..39, 56, *imm32);
427*61046927SAndroid Build Coastguard Worker                     assert!(self.srcs[1].src_mod.is_none());
428*61046927SAndroid Build Coastguard Worker                 }
429*61046927SAndroid Build Coastguard Worker                 SrcRef::CBuf(_) => {
430*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x4c58);
431*61046927SAndroid Build Coastguard Worker                     e.set_cb_fmod_src(20..39, 49, 45, self.srcs[1]);
432*61046927SAndroid Build Coastguard Worker                 }
433*61046927SAndroid Build Coastguard Worker                 src => panic!("Invalid fadd src1: {src}"),
434*61046927SAndroid Build Coastguard Worker             }
435*61046927SAndroid Build Coastguard Worker 
436*61046927SAndroid Build Coastguard Worker             e.set_dst(self.dst);
437*61046927SAndroid Build Coastguard Worker             e.set_reg_fmod_src(8..16, 46, 48, self.srcs[0]);
438*61046927SAndroid Build Coastguard Worker 
439*61046927SAndroid Build Coastguard Worker             e.set_rnd_mode(39..41, self.rnd_mode);
440*61046927SAndroid Build Coastguard Worker             e.set_bit(44, self.ftz);
441*61046927SAndroid Build Coastguard Worker             e.set_bit(50, self.saturate);
442*61046927SAndroid Build Coastguard Worker         }
443*61046927SAndroid Build Coastguard Worker     }
444*61046927SAndroid Build Coastguard Worker }
445*61046927SAndroid Build Coastguard Worker 
446*61046927SAndroid Build Coastguard Worker impl SM50Op for OpFFma {
legalize(&mut self, b: &mut LegalizeBuilder)447*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
448*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
449*61046927SAndroid Build Coastguard Worker         let [src0, src1, src2] = &mut self.srcs;
450*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src0, SrcType::F32);
451*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src1, SrcType::F32);
452*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src2, SrcType::F32);
453*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
454*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F32);
455*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(src1, GPR, SrcType::F32);
456*61046927SAndroid Build Coastguard Worker         if src_is_reg(src1, GPR) {
457*61046927SAndroid Build Coastguard Worker             b.copy_alu_src_if_imm(src2, GPR, SrcType::F32);
458*61046927SAndroid Build Coastguard Worker         } else {
459*61046927SAndroid Build Coastguard Worker             b.copy_alu_src_if_not_reg(src2, GPR, SrcType::F32);
460*61046927SAndroid Build Coastguard Worker         }
461*61046927SAndroid Build Coastguard Worker     }
462*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)463*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
464*61046927SAndroid Build Coastguard Worker         // ffma doesn't have any abs flags.
465*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[0].src_mod.has_fabs());
466*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[1].src_mod.has_fabs());
467*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[2].src_mod.has_fabs());
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker         // There is one fneg bit shared by the two fmul sources
470*61046927SAndroid Build Coastguard Worker         let fneg_fmul =
471*61046927SAndroid Build Coastguard Worker             self.srcs[0].src_mod.has_fneg() ^ self.srcs[1].src_mod.has_fneg();
472*61046927SAndroid Build Coastguard Worker         let fneg_src2 = self.srcs[2].src_mod.has_fneg();
473*61046927SAndroid Build Coastguard Worker 
474*61046927SAndroid Build Coastguard Worker         match &self.srcs[2].src_ref {
475*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
476*61046927SAndroid Build Coastguard Worker                 match &self.srcs[1].src_ref {
477*61046927SAndroid Build Coastguard Worker                     SrcRef::Zero | SrcRef::Reg(_) => {
478*61046927SAndroid Build Coastguard Worker                         e.set_opcode(0x5980);
479*61046927SAndroid Build Coastguard Worker                         e.set_reg_src_ref(20..28, self.srcs[1].src_ref);
480*61046927SAndroid Build Coastguard Worker                     }
481*61046927SAndroid Build Coastguard Worker                     SrcRef::Imm32(imm32) => {
482*61046927SAndroid Build Coastguard Worker                         e.set_opcode(0x3280);
483*61046927SAndroid Build Coastguard Worker 
484*61046927SAndroid Build Coastguard Worker                         // Technically, ffma also supports a 32-bit immediate,
485*61046927SAndroid Build Coastguard Worker                         // but only in the case where the destination is the
486*61046927SAndroid Build Coastguard Worker                         // same as src2.  We don't support that right now.
487*61046927SAndroid Build Coastguard Worker                         e.set_src_imm_f20(20..39, 56, *imm32);
488*61046927SAndroid Build Coastguard Worker                     }
489*61046927SAndroid Build Coastguard Worker                     SrcRef::CBuf(cb) => {
490*61046927SAndroid Build Coastguard Worker                         e.set_opcode(0x4980);
491*61046927SAndroid Build Coastguard Worker                         e.set_src_cb(20..39, cb);
492*61046927SAndroid Build Coastguard Worker                     }
493*61046927SAndroid Build Coastguard Worker                     src => panic!("Invalid ffma src1: {src}"),
494*61046927SAndroid Build Coastguard Worker                 }
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker                 e.set_reg_src_ref(39..47, self.srcs[2].src_ref);
497*61046927SAndroid Build Coastguard Worker             }
498*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
499*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5180);
500*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
501*61046927SAndroid Build Coastguard Worker                 e.set_reg_src_ref(39..47, self.srcs[1].src_ref);
502*61046927SAndroid Build Coastguard Worker             }
503*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid ffma src2: {src}"),
504*61046927SAndroid Build Coastguard Worker         }
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
507*61046927SAndroid Build Coastguard Worker         e.set_reg_src_ref(8..16, self.srcs[0].src_ref);
508*61046927SAndroid Build Coastguard Worker 
509*61046927SAndroid Build Coastguard Worker         e.set_bit(48, fneg_fmul);
510*61046927SAndroid Build Coastguard Worker         e.set_bit(49, fneg_src2);
511*61046927SAndroid Build Coastguard Worker         e.set_bit(50, self.saturate);
512*61046927SAndroid Build Coastguard Worker         e.set_rnd_mode(51..53, self.rnd_mode);
513*61046927SAndroid Build Coastguard Worker 
514*61046927SAndroid Build Coastguard Worker         e.set_bit(53, self.ftz);
515*61046927SAndroid Build Coastguard Worker         e.set_bit(54, self.dnz);
516*61046927SAndroid Build Coastguard Worker     }
517*61046927SAndroid Build Coastguard Worker }
518*61046927SAndroid Build Coastguard Worker 
519*61046927SAndroid Build Coastguard Worker impl SM50Op for OpFMnMx {
legalize(&mut self, b: &mut LegalizeBuilder)520*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
521*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
522*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
523*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
524*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F32);
525*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(src1, GPR, SrcType::F32);
526*61046927SAndroid Build Coastguard Worker     }
527*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)528*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
529*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
530*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
531*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c60);
532*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..28, 49, 45, self.srcs[1]);
533*61046927SAndroid Build Coastguard Worker             }
534*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
535*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3860);
536*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_f20(20..39, 56, *imm32);
537*61046927SAndroid Build Coastguard Worker                 assert!(self.srcs[1].src_mod.is_none());
538*61046927SAndroid Build Coastguard Worker             }
539*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
540*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c60);
541*61046927SAndroid Build Coastguard Worker                 e.set_cb_fmod_src(20..39, 49, 45, self.srcs[1]);
542*61046927SAndroid Build Coastguard Worker             }
543*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid fmnmx src2: {src}"),
544*61046927SAndroid Build Coastguard Worker         }
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker         e.set_reg_fmod_src(8..16, 46, 48, self.srcs[0]);
547*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
548*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, self.min);
549*61046927SAndroid Build Coastguard Worker         e.set_bit(44, self.ftz);
550*61046927SAndroid Build Coastguard Worker     }
551*61046927SAndroid Build Coastguard Worker }
552*61046927SAndroid Build Coastguard Worker 
553*61046927SAndroid Build Coastguard Worker impl SM50Op for OpFMul {
legalize(&mut self, b: &mut LegalizeBuilder)554*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
555*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
556*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
557*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src0, SrcType::F32);
558*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src1, SrcType::F32);
559*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
560*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F32);
561*61046927SAndroid Build Coastguard Worker     }
562*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)563*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
564*61046927SAndroid Build Coastguard Worker         // fmul doesn't have any abs flags.
565*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[0].src_mod.has_fabs());
566*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[1].src_mod.has_fabs());
567*61046927SAndroid Build Coastguard Worker 
568*61046927SAndroid Build Coastguard Worker         // There is one fneg bit shared by both sources
569*61046927SAndroid Build Coastguard Worker         let fneg =
570*61046927SAndroid Build Coastguard Worker             self.srcs[0].src_mod.has_fneg() ^ self.srcs[1].src_mod.has_fneg();
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker         if let Some(mut imm32) = self.srcs[1].as_imm_not_f20() {
573*61046927SAndroid Build Coastguard Worker             e.set_opcode(0x1e00);
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker             e.set_bit(53, self.ftz);
576*61046927SAndroid Build Coastguard Worker             e.set_bit(54, self.dnz);
577*61046927SAndroid Build Coastguard Worker             e.set_bit(55, self.saturate);
578*61046927SAndroid Build Coastguard Worker 
579*61046927SAndroid Build Coastguard Worker             if fneg {
580*61046927SAndroid Build Coastguard Worker                 // Flip the immediate sign bit
581*61046927SAndroid Build Coastguard Worker                 imm32 ^= 0x80000000;
582*61046927SAndroid Build Coastguard Worker             }
583*61046927SAndroid Build Coastguard Worker             e.set_src_imm32(20..52, imm32);
584*61046927SAndroid Build Coastguard Worker         } else {
585*61046927SAndroid Build Coastguard Worker             match &self.srcs[1].src_ref {
586*61046927SAndroid Build Coastguard Worker                 SrcRef::Zero | SrcRef::Reg(_) => {
587*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x5c68);
588*61046927SAndroid Build Coastguard Worker                     e.set_reg_src(20..28, self.srcs[1]);
589*61046927SAndroid Build Coastguard Worker                 }
590*61046927SAndroid Build Coastguard Worker                 SrcRef::Imm32(imm32) => {
591*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x3868);
592*61046927SAndroid Build Coastguard Worker                     e.set_src_imm_f20(20..39, 56, *imm32);
593*61046927SAndroid Build Coastguard Worker                 }
594*61046927SAndroid Build Coastguard Worker                 SrcRef::CBuf(cbuf) => {
595*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x4c68);
596*61046927SAndroid Build Coastguard Worker                     e.set_src_cb(20..39, cbuf);
597*61046927SAndroid Build Coastguard Worker                 }
598*61046927SAndroid Build Coastguard Worker                 src => panic!("Invalid fmul src1: {src}"),
599*61046927SAndroid Build Coastguard Worker             }
600*61046927SAndroid Build Coastguard Worker 
601*61046927SAndroid Build Coastguard Worker             e.set_rnd_mode(39..41, self.rnd_mode);
602*61046927SAndroid Build Coastguard Worker             e.set_field(41..44, 0x0_u8); // TODO: PDIV
603*61046927SAndroid Build Coastguard Worker             e.set_bit(44, self.ftz);
604*61046927SAndroid Build Coastguard Worker             e.set_bit(45, self.dnz);
605*61046927SAndroid Build Coastguard Worker             e.set_bit(48, fneg);
606*61046927SAndroid Build Coastguard Worker             e.set_bit(50, self.saturate);
607*61046927SAndroid Build Coastguard Worker         }
608*61046927SAndroid Build Coastguard Worker 
609*61046927SAndroid Build Coastguard Worker         e.set_reg_src_ref(8..16, self.srcs[0].src_ref);
610*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
611*61046927SAndroid Build Coastguard Worker     }
612*61046927SAndroid Build Coastguard Worker }
613*61046927SAndroid Build Coastguard Worker 
614*61046927SAndroid Build Coastguard Worker impl SM50Op for OpRro {
legalize(&mut self, b: &mut LegalizeBuilder)615*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
616*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
617*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(&mut self.src, GPR, SrcType::F32);
618*61046927SAndroid Build Coastguard Worker     }
619*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)620*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
621*61046927SAndroid Build Coastguard Worker         match &self.src.src_ref {
622*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
623*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c90);
624*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..28, 49, 45, self.src);
625*61046927SAndroid Build Coastguard Worker             }
626*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
627*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3890);
628*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_f20(20..39, 56, *imm32);
629*61046927SAndroid Build Coastguard Worker                 assert!(self.src.src_mod.is_none());
630*61046927SAndroid Build Coastguard Worker             }
631*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
632*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c90);
633*61046927SAndroid Build Coastguard Worker                 e.set_cb_fmod_src(20..39, 49, 45, self.src);
634*61046927SAndroid Build Coastguard Worker             }
635*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid rro src: {src}"),
636*61046927SAndroid Build Coastguard Worker         }
637*61046927SAndroid Build Coastguard Worker 
638*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
639*61046927SAndroid Build Coastguard Worker         e.set_field(
640*61046927SAndroid Build Coastguard Worker             39..40,
641*61046927SAndroid Build Coastguard Worker             match self.op {
642*61046927SAndroid Build Coastguard Worker                 RroOp::SinCos => 0u8,
643*61046927SAndroid Build Coastguard Worker                 RroOp::Exp2 => 1u8,
644*61046927SAndroid Build Coastguard Worker             },
645*61046927SAndroid Build Coastguard Worker         );
646*61046927SAndroid Build Coastguard Worker     }
647*61046927SAndroid Build Coastguard Worker }
648*61046927SAndroid Build Coastguard Worker 
649*61046927SAndroid Build Coastguard Worker impl SM50Op for OpMuFu {
legalize(&mut self, b: &mut LegalizeBuilder)650*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
651*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.src, RegFile::GPR, SrcType::GPR);
652*61046927SAndroid Build Coastguard Worker     }
653*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)654*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
655*61046927SAndroid Build Coastguard Worker         e.set_opcode(0x5080);
656*61046927SAndroid Build Coastguard Worker 
657*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
658*61046927SAndroid Build Coastguard Worker         e.set_reg_fmod_src(8..16, 46, 48, self.src);
659*61046927SAndroid Build Coastguard Worker 
660*61046927SAndroid Build Coastguard Worker         e.set_field(
661*61046927SAndroid Build Coastguard Worker             20..24,
662*61046927SAndroid Build Coastguard Worker             match self.op {
663*61046927SAndroid Build Coastguard Worker                 MuFuOp::Cos => 0_u8,
664*61046927SAndroid Build Coastguard Worker                 MuFuOp::Sin => 1_u8,
665*61046927SAndroid Build Coastguard Worker                 MuFuOp::Exp2 => 2_u8,
666*61046927SAndroid Build Coastguard Worker                 MuFuOp::Log2 => 3_u8,
667*61046927SAndroid Build Coastguard Worker                 MuFuOp::Rcp => 4_u8,
668*61046927SAndroid Build Coastguard Worker                 MuFuOp::Rsq => 5_u8,
669*61046927SAndroid Build Coastguard Worker                 MuFuOp::Rcp64H => 6_u8,
670*61046927SAndroid Build Coastguard Worker                 MuFuOp::Rsq64H => 7_u8,
671*61046927SAndroid Build Coastguard Worker                 // SQRT is only on SM52 and later
672*61046927SAndroid Build Coastguard Worker                 MuFuOp::Sqrt if e.sm.sm >= 52 => 8_u8,
673*61046927SAndroid Build Coastguard Worker                 MuFuOp::Sqrt => panic!("MUFU.SQRT not supported on SM50"),
674*61046927SAndroid Build Coastguard Worker                 MuFuOp::Tanh => panic!("MUFU.TANH not supported on SM50"),
675*61046927SAndroid Build Coastguard Worker             },
676*61046927SAndroid Build Coastguard Worker         );
677*61046927SAndroid Build Coastguard Worker     }
678*61046927SAndroid Build Coastguard Worker }
679*61046927SAndroid Build Coastguard Worker 
680*61046927SAndroid Build Coastguard Worker impl SM50Encoder<'_> {
set_float_cmp_op(&mut self, range: Range<usize>, op: FloatCmpOp)681*61046927SAndroid Build Coastguard Worker     fn set_float_cmp_op(&mut self, range: Range<usize>, op: FloatCmpOp) {
682*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 4);
683*61046927SAndroid Build Coastguard Worker         self.set_field(
684*61046927SAndroid Build Coastguard Worker             range,
685*61046927SAndroid Build Coastguard Worker             match op {
686*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::OrdLt => 0x01_u8,
687*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::OrdEq => 0x02_u8,
688*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::OrdLe => 0x03_u8,
689*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::OrdGt => 0x04_u8,
690*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::OrdNe => 0x05_u8,
691*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::OrdGe => 0x06_u8,
692*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::UnordLt => 0x09_u8,
693*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::UnordEq => 0x0a_u8,
694*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::UnordLe => 0x0b_u8,
695*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::UnordGt => 0x0c_u8,
696*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::UnordNe => 0x0d_u8,
697*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::UnordGe => 0x0e_u8,
698*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::IsNum => 0x07_u8,
699*61046927SAndroid Build Coastguard Worker                 FloatCmpOp::IsNan => 0x08_u8,
700*61046927SAndroid Build Coastguard Worker             },
701*61046927SAndroid Build Coastguard Worker         );
702*61046927SAndroid Build Coastguard Worker     }
703*61046927SAndroid Build Coastguard Worker 
set_pred_set_op(&mut self, range: Range<usize>, op: PredSetOp)704*61046927SAndroid Build Coastguard Worker     fn set_pred_set_op(&mut self, range: Range<usize>, op: PredSetOp) {
705*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 2);
706*61046927SAndroid Build Coastguard Worker         self.set_field(
707*61046927SAndroid Build Coastguard Worker             range,
708*61046927SAndroid Build Coastguard Worker             match op {
709*61046927SAndroid Build Coastguard Worker                 PredSetOp::And => 0_u8,
710*61046927SAndroid Build Coastguard Worker                 PredSetOp::Or => 1_u8,
711*61046927SAndroid Build Coastguard Worker                 PredSetOp::Xor => 2_u8,
712*61046927SAndroid Build Coastguard Worker             },
713*61046927SAndroid Build Coastguard Worker         );
714*61046927SAndroid Build Coastguard Worker     }
715*61046927SAndroid Build Coastguard Worker 
set_int_cmp_op(&mut self, range: Range<usize>, op: IntCmpOp)716*61046927SAndroid Build Coastguard Worker     fn set_int_cmp_op(&mut self, range: Range<usize>, op: IntCmpOp) {
717*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 3);
718*61046927SAndroid Build Coastguard Worker         self.set_field(
719*61046927SAndroid Build Coastguard Worker             range,
720*61046927SAndroid Build Coastguard Worker             match op {
721*61046927SAndroid Build Coastguard Worker                 IntCmpOp::Eq => 2_u8,
722*61046927SAndroid Build Coastguard Worker                 IntCmpOp::Ne => 5_u8,
723*61046927SAndroid Build Coastguard Worker                 IntCmpOp::Lt => 1_u8,
724*61046927SAndroid Build Coastguard Worker                 IntCmpOp::Le => 3_u8,
725*61046927SAndroid Build Coastguard Worker                 IntCmpOp::Gt => 4_u8,
726*61046927SAndroid Build Coastguard Worker                 IntCmpOp::Ge => 6_u8,
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 impl SM50Op for OpFSet {
legalize(&mut self, b: &mut LegalizeBuilder)733*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
734*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
735*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
736*61046927SAndroid Build Coastguard Worker         if swap_srcs_if_not_reg(src0, src1, GPR) {
737*61046927SAndroid Build Coastguard Worker             self.cmp_op = self.cmp_op.flip();
738*61046927SAndroid Build Coastguard Worker         }
739*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F32);
740*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(src1, GPR, SrcType::F32);
741*61046927SAndroid Build Coastguard Worker     }
742*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)743*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
744*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
745*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
746*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5800);
747*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..28, 44, 53, self.srcs[1]);
748*61046927SAndroid Build Coastguard Worker             }
749*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
750*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3000);
751*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_f20(20..39, 56, *imm32);
752*61046927SAndroid Build Coastguard Worker                 assert!(self.srcs[1].src_mod.is_none());
753*61046927SAndroid Build Coastguard Worker             }
754*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
755*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4800);
756*61046927SAndroid Build Coastguard Worker                 e.set_cb_fmod_src(20..39, 44, 6, self.srcs[1]);
757*61046927SAndroid Build Coastguard Worker             }
758*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid fset src1: {src}"),
759*61046927SAndroid Build Coastguard Worker         }
760*61046927SAndroid Build Coastguard Worker 
761*61046927SAndroid Build Coastguard Worker         e.set_reg_fmod_src(8..16, 54, 43, self.srcs[0]);
762*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, SrcRef::True.into());
763*61046927SAndroid Build Coastguard Worker         e.set_float_cmp_op(48..52, self.cmp_op);
764*61046927SAndroid Build Coastguard Worker         e.set_bit(52, true); // bool float
765*61046927SAndroid Build Coastguard Worker         e.set_bit(55, self.ftz);
766*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
767*61046927SAndroid Build Coastguard Worker     }
768*61046927SAndroid Build Coastguard Worker }
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker impl SM50Op for OpFSetP {
legalize(&mut self, b: &mut LegalizeBuilder)771*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
772*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
773*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
774*61046927SAndroid Build Coastguard Worker         if swap_srcs_if_not_reg(src0, src1, GPR) {
775*61046927SAndroid Build Coastguard Worker             self.cmp_op = self.cmp_op.flip();
776*61046927SAndroid Build Coastguard Worker         }
777*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F32);
778*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(src1, GPR, SrcType::F32);
779*61046927SAndroid Build Coastguard Worker     }
780*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)781*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
782*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
783*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
784*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5bb0);
785*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..28, 44, 6, self.srcs[1]);
786*61046927SAndroid Build Coastguard Worker             }
787*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
788*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x36b0);
789*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_f20(20..39, 56, *imm32);
790*61046927SAndroid Build Coastguard Worker                 assert!(self.srcs[1].src_mod.is_none());
791*61046927SAndroid Build Coastguard Worker             }
792*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
793*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4bb0);
794*61046927SAndroid Build Coastguard Worker                 e.set_cb_fmod_src(20..39, 44, 6, self.srcs[1]);
795*61046927SAndroid Build Coastguard Worker             }
796*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid fsetp src1: {src}"),
797*61046927SAndroid Build Coastguard Worker         }
798*61046927SAndroid Build Coastguard Worker 
799*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(3..6, self.dst);
800*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(0..3, Dst::None); // dst1
801*61046927SAndroid Build Coastguard Worker         e.set_reg_fmod_src(8..16, 7, 43, self.srcs[0]);
802*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, self.accum);
803*61046927SAndroid Build Coastguard Worker         e.set_pred_set_op(45..47, self.set_op);
804*61046927SAndroid Build Coastguard Worker         e.set_bit(47, self.ftz);
805*61046927SAndroid Build Coastguard Worker         e.set_float_cmp_op(48..52, self.cmp_op);
806*61046927SAndroid Build Coastguard Worker     }
807*61046927SAndroid Build Coastguard Worker }
808*61046927SAndroid Build Coastguard Worker 
809*61046927SAndroid Build Coastguard Worker impl SM50Op for OpFSwzAdd {
legalize(&mut self, b: &mut LegalizeBuilder)810*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
811*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
812*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.srcs[0], GPR, SrcType::GPR);
813*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.srcs[1], GPR, SrcType::GPR);
814*61046927SAndroid Build Coastguard Worker     }
815*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)816*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
817*61046927SAndroid Build Coastguard Worker         e.set_opcode(0x50f8);
818*61046927SAndroid Build Coastguard Worker 
819*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
820*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
821*61046927SAndroid Build Coastguard Worker         e.set_reg_src(20..28, self.srcs[1]);
822*61046927SAndroid Build Coastguard Worker 
823*61046927SAndroid Build Coastguard Worker         e.set_field(
824*61046927SAndroid Build Coastguard Worker             39..41,
825*61046927SAndroid Build Coastguard Worker             match self.rnd_mode {
826*61046927SAndroid Build Coastguard Worker                 FRndMode::NearestEven => 0u8,
827*61046927SAndroid Build Coastguard Worker                 FRndMode::NegInf => 1u8,
828*61046927SAndroid Build Coastguard Worker                 FRndMode::PosInf => 2u8,
829*61046927SAndroid Build Coastguard Worker                 FRndMode::Zero => 3u8,
830*61046927SAndroid Build Coastguard Worker             },
831*61046927SAndroid Build Coastguard Worker         );
832*61046927SAndroid Build Coastguard Worker 
833*61046927SAndroid Build Coastguard Worker         for (i, op) in self.ops.iter().enumerate() {
834*61046927SAndroid Build Coastguard Worker             e.set_field(
835*61046927SAndroid Build Coastguard Worker                 28 + i * 2..28 + (i + 1) * 2,
836*61046927SAndroid Build Coastguard Worker                 match op {
837*61046927SAndroid Build Coastguard Worker                     FSwzAddOp::Add => 0u8,
838*61046927SAndroid Build Coastguard Worker                     FSwzAddOp::SubLeft => 1u8,
839*61046927SAndroid Build Coastguard Worker                     FSwzAddOp::SubRight => 2u8,
840*61046927SAndroid Build Coastguard Worker                     FSwzAddOp::MoveLeft => 3u8,
841*61046927SAndroid Build Coastguard Worker                 },
842*61046927SAndroid Build Coastguard Worker             );
843*61046927SAndroid Build Coastguard Worker         }
844*61046927SAndroid Build Coastguard Worker 
845*61046927SAndroid Build Coastguard Worker         e.set_bit(38, false); /* .NDV */
846*61046927SAndroid Build Coastguard Worker         e.set_bit(44, self.ftz);
847*61046927SAndroid Build Coastguard Worker         e.set_bit(47, false); /* dst.CC */
848*61046927SAndroid Build Coastguard Worker     }
849*61046927SAndroid Build Coastguard Worker }
850*61046927SAndroid Build Coastguard Worker 
851*61046927SAndroid Build Coastguard Worker impl SM50Op for OpDAdd {
legalize(&mut self, b: &mut LegalizeBuilder)852*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
853*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
854*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
855*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
856*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F64);
857*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(src1, GPR, SrcType::F64);
858*61046927SAndroid Build Coastguard Worker     }
859*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)860*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
861*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
862*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
863*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c70);
864*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..28, 49, 45, self.srcs[1]);
865*61046927SAndroid Build Coastguard Worker             }
866*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
867*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3870);
868*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_f20(20..39, 56, *imm32);
869*61046927SAndroid Build Coastguard Worker                 assert!(self.srcs[1].src_mod.is_none());
870*61046927SAndroid Build Coastguard Worker             }
871*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
872*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c70);
873*61046927SAndroid Build Coastguard Worker                 e.set_cb_fmod_src(20..39, 49, 45, self.srcs[1]);
874*61046927SAndroid Build Coastguard Worker             }
875*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid dadd src1: {src}"),
876*61046927SAndroid Build Coastguard Worker         }
877*61046927SAndroid Build Coastguard Worker 
878*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
879*61046927SAndroid Build Coastguard Worker         e.set_reg_fmod_src(8..16, 46, 48, self.srcs[0]);
880*61046927SAndroid Build Coastguard Worker         e.set_rnd_mode(39..41, self.rnd_mode);
881*61046927SAndroid Build Coastguard Worker     }
882*61046927SAndroid Build Coastguard Worker }
883*61046927SAndroid Build Coastguard Worker 
884*61046927SAndroid Build Coastguard Worker impl SM50Op for OpDFma {
legalize(&mut self, b: &mut LegalizeBuilder)885*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
886*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
887*61046927SAndroid Build Coastguard Worker         let [src0, src1, src2] = &mut self.srcs;
888*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src0, SrcType::F64);
889*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src1, SrcType::F64);
890*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src2, SrcType::F64);
891*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
892*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F64);
893*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(src1, GPR, SrcType::F64);
894*61046927SAndroid Build Coastguard Worker         if src_is_reg(src1, GPR) {
895*61046927SAndroid Build Coastguard Worker             b.copy_alu_src_if_imm(src2, GPR, SrcType::F64);
896*61046927SAndroid Build Coastguard Worker         } else {
897*61046927SAndroid Build Coastguard Worker             b.copy_alu_src_if_not_reg(src2, GPR, SrcType::F64);
898*61046927SAndroid Build Coastguard Worker         }
899*61046927SAndroid Build Coastguard Worker     }
900*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)901*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
902*61046927SAndroid Build Coastguard Worker         // dfma doesn't have any abs flags.
903*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[0].src_mod.has_fabs());
904*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[1].src_mod.has_fabs());
905*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[2].src_mod.has_fabs());
906*61046927SAndroid Build Coastguard Worker 
907*61046927SAndroid Build Coastguard Worker         // There is one fneg bit shared by the two fmul sources
908*61046927SAndroid Build Coastguard Worker         let fneg_fmul =
909*61046927SAndroid Build Coastguard Worker             self.srcs[0].src_mod.has_fneg() ^ self.srcs[1].src_mod.has_fneg();
910*61046927SAndroid Build Coastguard Worker         let fneg_src2 = self.srcs[2].src_mod.has_fneg();
911*61046927SAndroid Build Coastguard Worker 
912*61046927SAndroid Build Coastguard Worker         match &self.srcs[2].src_ref {
913*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
914*61046927SAndroid Build Coastguard Worker                 match &self.srcs[1].src_ref {
915*61046927SAndroid Build Coastguard Worker                     SrcRef::Zero | SrcRef::Reg(_) => {
916*61046927SAndroid Build Coastguard Worker                         e.set_opcode(0x5b70);
917*61046927SAndroid Build Coastguard Worker                         e.set_reg_src_ref(20..28, self.srcs[1].src_ref);
918*61046927SAndroid Build Coastguard Worker                     }
919*61046927SAndroid Build Coastguard Worker                     SrcRef::Imm32(imm32) => {
920*61046927SAndroid Build Coastguard Worker                         e.set_opcode(0x3670);
921*61046927SAndroid Build Coastguard Worker                         e.set_src_imm_f20(20..39, 56, *imm32);
922*61046927SAndroid Build Coastguard Worker                     }
923*61046927SAndroid Build Coastguard Worker                     SrcRef::CBuf(cb) => {
924*61046927SAndroid Build Coastguard Worker                         e.set_opcode(0x4b70);
925*61046927SAndroid Build Coastguard Worker                         e.set_src_cb(20..39, cb);
926*61046927SAndroid Build Coastguard Worker                     }
927*61046927SAndroid Build Coastguard Worker                     src => panic!("Invalid dfma src1: {src}"),
928*61046927SAndroid Build Coastguard Worker                 }
929*61046927SAndroid Build Coastguard Worker 
930*61046927SAndroid Build Coastguard Worker                 e.set_reg_src_ref(39..47, self.srcs[2].src_ref);
931*61046927SAndroid Build Coastguard Worker             }
932*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
933*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5370);
934*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
935*61046927SAndroid Build Coastguard Worker                 e.set_reg_src_ref(39..47, self.srcs[1].src_ref);
936*61046927SAndroid Build Coastguard Worker             }
937*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid dfma src2: {src}"),
938*61046927SAndroid Build Coastguard Worker         }
939*61046927SAndroid Build Coastguard Worker 
940*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
941*61046927SAndroid Build Coastguard Worker         e.set_reg_src_ref(8..16, self.srcs[0].src_ref);
942*61046927SAndroid Build Coastguard Worker 
943*61046927SAndroid Build Coastguard Worker         e.set_bit(48, fneg_fmul);
944*61046927SAndroid Build Coastguard Worker         e.set_bit(49, fneg_src2);
945*61046927SAndroid Build Coastguard Worker 
946*61046927SAndroid Build Coastguard Worker         e.set_rnd_mode(50..52, self.rnd_mode);
947*61046927SAndroid Build Coastguard Worker     }
948*61046927SAndroid Build Coastguard Worker }
949*61046927SAndroid Build Coastguard Worker 
950*61046927SAndroid Build Coastguard Worker impl SM50Op for OpDMnMx {
legalize(&mut self, b: &mut LegalizeBuilder)951*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
952*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
953*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
954*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
955*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F64);
956*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(src1, GPR, SrcType::F64);
957*61046927SAndroid Build Coastguard Worker     }
958*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)959*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
960*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
961*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
962*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c50);
963*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..28, 49, 45, self.srcs[1]);
964*61046927SAndroid Build Coastguard Worker             }
965*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
966*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3850);
967*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_f20(20..39, 56, *imm32);
968*61046927SAndroid Build Coastguard Worker                 assert!(self.srcs[1].src_mod.is_none());
969*61046927SAndroid Build Coastguard Worker             }
970*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
971*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c50);
972*61046927SAndroid Build Coastguard Worker                 e.set_cb_fmod_src(20..39, 49, 45, self.srcs[1]);
973*61046927SAndroid Build Coastguard Worker             }
974*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid dmnmx src1: {src}"),
975*61046927SAndroid Build Coastguard Worker         }
976*61046927SAndroid Build Coastguard Worker 
977*61046927SAndroid Build Coastguard Worker         e.set_reg_fmod_src(8..16, 46, 48, self.srcs[0]);
978*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
979*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, self.min);
980*61046927SAndroid Build Coastguard Worker     }
981*61046927SAndroid Build Coastguard Worker }
982*61046927SAndroid Build Coastguard Worker 
983*61046927SAndroid Build Coastguard Worker impl SM50Op for OpDMul {
legalize(&mut self, b: &mut LegalizeBuilder)984*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
985*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
986*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
987*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src0, SrcType::F64);
988*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_fabs(src1, SrcType::F64);
989*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
990*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F64);
991*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(src1, GPR, SrcType::F64);
992*61046927SAndroid Build Coastguard Worker     }
993*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)994*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
995*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[0].src_mod.has_fabs());
996*61046927SAndroid Build Coastguard Worker         assert!(!self.srcs[1].src_mod.has_fabs());
997*61046927SAndroid Build Coastguard Worker 
998*61046927SAndroid Build Coastguard Worker         // There is one fneg bit shared by both sources
999*61046927SAndroid Build Coastguard Worker         let fneg =
1000*61046927SAndroid Build Coastguard Worker             self.srcs[0].src_mod.has_fneg() ^ self.srcs[1].src_mod.has_fneg();
1001*61046927SAndroid Build Coastguard Worker 
1002*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
1003*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1004*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c80);
1005*61046927SAndroid Build Coastguard Worker                 e.set_reg_src_ref(20..28, self.srcs[1].src_ref);
1006*61046927SAndroid Build Coastguard Worker             }
1007*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1008*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3880);
1009*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_f20(20..39, 56, *imm32);
1010*61046927SAndroid Build Coastguard Worker             }
1011*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
1012*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c80);
1013*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
1014*61046927SAndroid Build Coastguard Worker             }
1015*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid dmul src1: {src}"),
1016*61046927SAndroid Build Coastguard Worker         }
1017*61046927SAndroid Build Coastguard Worker 
1018*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1019*61046927SAndroid Build Coastguard Worker         e.set_reg_src_ref(8..16, self.srcs[0].src_ref);
1020*61046927SAndroid Build Coastguard Worker 
1021*61046927SAndroid Build Coastguard Worker         e.set_rnd_mode(39..41, self.rnd_mode);
1022*61046927SAndroid Build Coastguard Worker         e.set_bit(48, fneg);
1023*61046927SAndroid Build Coastguard Worker     }
1024*61046927SAndroid Build Coastguard Worker }
1025*61046927SAndroid Build Coastguard Worker 
1026*61046927SAndroid Build Coastguard Worker impl SM50Op for OpDSetP {
legalize(&mut self, b: &mut LegalizeBuilder)1027*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1028*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1029*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
1030*61046927SAndroid Build Coastguard Worker         if swap_srcs_if_not_reg(src0, src1, GPR) {
1031*61046927SAndroid Build Coastguard Worker             self.cmp_op = self.cmp_op.flip();
1032*61046927SAndroid Build Coastguard Worker         }
1033*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::F64);
1034*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(src1, GPR, SrcType::F64);
1035*61046927SAndroid Build Coastguard Worker     }
1036*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1037*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1038*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
1039*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1040*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5b80);
1041*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..28, 44, 6, self.srcs[1]);
1042*61046927SAndroid Build Coastguard Worker             }
1043*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1044*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3680);
1045*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_f20(20..39, 56, *imm32);
1046*61046927SAndroid Build Coastguard Worker                 assert!(self.srcs[1].src_mod.is_none());
1047*61046927SAndroid Build Coastguard Worker             }
1048*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
1049*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4b80);
1050*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..39, 44, 6, self.srcs[1]);
1051*61046927SAndroid Build Coastguard Worker             }
1052*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid dsetp src1: {src}"),
1053*61046927SAndroid Build Coastguard Worker         }
1054*61046927SAndroid Build Coastguard Worker 
1055*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(3..6, self.dst);
1056*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(0..3, Dst::None); // dst1
1057*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, self.accum);
1058*61046927SAndroid Build Coastguard Worker         e.set_pred_set_op(45..47, self.set_op);
1059*61046927SAndroid Build Coastguard Worker         e.set_float_cmp_op(48..52, self.cmp_op);
1060*61046927SAndroid Build Coastguard Worker         e.set_reg_fmod_src(8..16, 7, 43, self.srcs[0]);
1061*61046927SAndroid Build Coastguard Worker     }
1062*61046927SAndroid Build Coastguard Worker }
1063*61046927SAndroid Build Coastguard Worker 
1064*61046927SAndroid Build Coastguard Worker impl SM50Op for OpBfe {
legalize(&mut self, b: &mut LegalizeBuilder)1065*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1066*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1067*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.base, GPR, SrcType::ALU);
1068*61046927SAndroid Build Coastguard Worker     }
1069*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1070*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1071*61046927SAndroid Build Coastguard Worker         match &self.range.src_ref {
1072*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1073*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c00);
1074*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.range);
1075*61046927SAndroid Build Coastguard Worker             }
1076*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1077*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3800);
1078*61046927SAndroid Build Coastguard Worker                 // Only the bottom 16 bits of the immediate matter
1079*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32 & 0xffff);
1080*61046927SAndroid Build Coastguard Worker             }
1081*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cbuf) => {
1082*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c00);
1083*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cbuf);
1084*61046927SAndroid Build Coastguard Worker             }
1085*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid bfe range: {src}"),
1086*61046927SAndroid Build Coastguard Worker         }
1087*61046927SAndroid Build Coastguard Worker 
1088*61046927SAndroid Build Coastguard Worker         if self.signed {
1089*61046927SAndroid Build Coastguard Worker             e.set_bit(48, true);
1090*61046927SAndroid Build Coastguard Worker         }
1091*61046927SAndroid Build Coastguard Worker 
1092*61046927SAndroid Build Coastguard Worker         if self.reverse {
1093*61046927SAndroid Build Coastguard Worker             e.set_bit(40, true);
1094*61046927SAndroid Build Coastguard Worker         }
1095*61046927SAndroid Build Coastguard Worker 
1096*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.base);
1097*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1098*61046927SAndroid Build Coastguard Worker     }
1099*61046927SAndroid Build Coastguard Worker }
1100*61046927SAndroid Build Coastguard Worker 
1101*61046927SAndroid Build Coastguard Worker impl SM50Op for OpFlo {
legalize(&mut self, b: &mut LegalizeBuilder)1102*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1103*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1104*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(&mut self.src, GPR, SrcType::ALU);
1105*61046927SAndroid Build Coastguard Worker     }
1106*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1107*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1108*61046927SAndroid Build Coastguard Worker         match &self.src.src_ref {
1109*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1110*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c30);
1111*61046927SAndroid Build Coastguard Worker                 e.set_reg_src_ref(20..28, self.src.src_ref);
1112*61046927SAndroid Build Coastguard Worker             }
1113*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1114*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3830);
1115*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1116*61046927SAndroid Build Coastguard Worker                 assert!(self.src.src_mod.is_none());
1117*61046927SAndroid Build Coastguard Worker             }
1118*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
1119*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c30);
1120*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
1121*61046927SAndroid Build Coastguard Worker             }
1122*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid flo src: {src}"),
1123*61046927SAndroid Build Coastguard Worker         }
1124*61046927SAndroid Build Coastguard Worker 
1125*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1126*61046927SAndroid Build Coastguard Worker         e.set_bit(40, self.src.src_mod.is_bnot());
1127*61046927SAndroid Build Coastguard Worker         e.set_bit(48, self.signed);
1128*61046927SAndroid Build Coastguard Worker         e.set_bit(41, self.return_shift_amount);
1129*61046927SAndroid Build Coastguard Worker         e.set_bit(47, false); /* dst.CC */
1130*61046927SAndroid Build Coastguard Worker     }
1131*61046927SAndroid Build Coastguard Worker }
1132*61046927SAndroid Build Coastguard Worker 
1133*61046927SAndroid Build Coastguard Worker impl SM50Op for OpIAdd2 {
legalize(&mut self, b: &mut LegalizeBuilder)1134*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1135*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1136*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
1137*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
1138*61046927SAndroid Build Coastguard Worker         if src0.src_mod.is_ineg() && src1.src_mod.is_ineg() {
1139*61046927SAndroid Build Coastguard Worker             assert!(self.carry_out.is_none());
1140*61046927SAndroid Build Coastguard Worker             let val = b.alloc_ssa(GPR, 1);
1141*61046927SAndroid Build Coastguard Worker             b.push_op(OpIAdd2 {
1142*61046927SAndroid Build Coastguard Worker                 dst: val.into(),
1143*61046927SAndroid Build Coastguard Worker                 carry_out: Dst::None,
1144*61046927SAndroid Build Coastguard Worker                 srcs: [Src::new_zero(), *src0],
1145*61046927SAndroid Build Coastguard Worker             });
1146*61046927SAndroid Build Coastguard Worker             *src0 = val.into();
1147*61046927SAndroid Build Coastguard Worker         }
1148*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::I32);
1149*61046927SAndroid Build Coastguard Worker         if !self.carry_out.is_none() {
1150*61046927SAndroid Build Coastguard Worker             b.copy_alu_src_if_ineg_imm(src1, GPR, SrcType::I32);
1151*61046927SAndroid Build Coastguard Worker         }
1152*61046927SAndroid Build Coastguard Worker     }
1153*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1154*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1155*61046927SAndroid Build Coastguard Worker         // Hardware requires at least one of these be unmodified.  Otherwise, it
1156*61046927SAndroid Build Coastguard Worker         // encodes as iadd.po which isn't what we want.
1157*61046927SAndroid Build Coastguard Worker         assert!(
1158*61046927SAndroid Build Coastguard Worker             self.srcs[0].src_mod.is_none() || self.srcs[1].src_mod.is_none()
1159*61046927SAndroid Build Coastguard Worker         );
1160*61046927SAndroid Build Coastguard Worker 
1161*61046927SAndroid Build Coastguard Worker         let carry_out = match self.carry_out {
1162*61046927SAndroid Build Coastguard Worker             Dst::Reg(reg) if reg.file() == RegFile::Carry => true,
1163*61046927SAndroid Build Coastguard Worker             Dst::None => false,
1164*61046927SAndroid Build Coastguard Worker             dst => panic!("Invalid iadd carry_out: {dst}"),
1165*61046927SAndroid Build Coastguard Worker         };
1166*61046927SAndroid Build Coastguard Worker 
1167*61046927SAndroid Build Coastguard Worker         if let Some(imm32) = self.srcs[1].as_imm_not_i20() {
1168*61046927SAndroid Build Coastguard Worker             e.set_opcode(0x1c00);
1169*61046927SAndroid Build Coastguard Worker 
1170*61046927SAndroid Build Coastguard Worker             e.set_dst(self.dst);
1171*61046927SAndroid Build Coastguard Worker             e.set_reg_ineg_src(8..16, 56, self.srcs[0]);
1172*61046927SAndroid Build Coastguard Worker             e.set_src_imm32(20..52, imm32);
1173*61046927SAndroid Build Coastguard Worker 
1174*61046927SAndroid Build Coastguard Worker             e.set_bit(52, carry_out);
1175*61046927SAndroid Build Coastguard Worker             e.set_bit(53, false); // .X
1176*61046927SAndroid Build Coastguard Worker         } else {
1177*61046927SAndroid Build Coastguard Worker             match &self.srcs[1].src_ref {
1178*61046927SAndroid Build Coastguard Worker                 SrcRef::Zero | SrcRef::Reg(_) => {
1179*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x5c10);
1180*61046927SAndroid Build Coastguard Worker                     e.set_reg_ineg_src(20..28, 48, self.srcs[1]);
1181*61046927SAndroid Build Coastguard Worker                 }
1182*61046927SAndroid Build Coastguard Worker                 SrcRef::Imm32(imm32) => {
1183*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x3810);
1184*61046927SAndroid Build Coastguard Worker                     e.set_src_imm_i20(20..39, 56, *imm32);
1185*61046927SAndroid Build Coastguard Worker                     assert!(self.srcs[1].src_mod.is_none());
1186*61046927SAndroid Build Coastguard Worker                 }
1187*61046927SAndroid Build Coastguard Worker                 SrcRef::CBuf(_) => {
1188*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x4c10);
1189*61046927SAndroid Build Coastguard Worker                     e.set_cb_ineg_src(20..39, 48, self.srcs[1]);
1190*61046927SAndroid Build Coastguard Worker                 }
1191*61046927SAndroid Build Coastguard Worker                 src => panic!("Invalid iadd src1: {src}"),
1192*61046927SAndroid Build Coastguard Worker             }
1193*61046927SAndroid Build Coastguard Worker 
1194*61046927SAndroid Build Coastguard Worker             e.set_dst(self.dst);
1195*61046927SAndroid Build Coastguard Worker             e.set_reg_ineg_src(8..16, 49, self.srcs[0]);
1196*61046927SAndroid Build Coastguard Worker 
1197*61046927SAndroid Build Coastguard Worker             e.set_bit(43, false); // .X
1198*61046927SAndroid Build Coastguard Worker             e.set_bit(47, carry_out);
1199*61046927SAndroid Build Coastguard Worker         }
1200*61046927SAndroid Build Coastguard Worker     }
1201*61046927SAndroid Build Coastguard Worker }
1202*61046927SAndroid Build Coastguard Worker 
1203*61046927SAndroid Build Coastguard Worker impl SM50Op for OpIAdd2X {
legalize(&mut self, b: &mut LegalizeBuilder)1204*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1205*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1206*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
1207*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
1208*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::I32);
1209*61046927SAndroid Build Coastguard Worker     }
1210*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1211*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1212*61046927SAndroid Build Coastguard Worker         match self.carry_in.src_ref {
1213*61046927SAndroid Build Coastguard Worker             SrcRef::Reg(reg) if reg.file() == RegFile::Carry => (),
1214*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid iadd.x carry_in: {src}"),
1215*61046927SAndroid Build Coastguard Worker         }
1216*61046927SAndroid Build Coastguard Worker 
1217*61046927SAndroid Build Coastguard Worker         let carry_out = match self.carry_out {
1218*61046927SAndroid Build Coastguard Worker             Dst::Reg(reg) if reg.file() == RegFile::Carry => true,
1219*61046927SAndroid Build Coastguard Worker             Dst::None => false,
1220*61046927SAndroid Build Coastguard Worker             dst => panic!("Invalid iadd.x carry_out: {dst}"),
1221*61046927SAndroid Build Coastguard Worker         };
1222*61046927SAndroid Build Coastguard Worker 
1223*61046927SAndroid Build Coastguard Worker         if let Some(imm32) = self.srcs[1].as_imm_not_i20() {
1224*61046927SAndroid Build Coastguard Worker             e.set_opcode(0x1c00);
1225*61046927SAndroid Build Coastguard Worker 
1226*61046927SAndroid Build Coastguard Worker             e.set_dst(self.dst);
1227*61046927SAndroid Build Coastguard Worker             e.set_reg_bnot_src(8..16, 56, self.srcs[0]);
1228*61046927SAndroid Build Coastguard Worker             e.set_src_imm32(20..52, imm32);
1229*61046927SAndroid Build Coastguard Worker 
1230*61046927SAndroid Build Coastguard Worker             e.set_bit(52, carry_out);
1231*61046927SAndroid Build Coastguard Worker             e.set_bit(53, true); // .X
1232*61046927SAndroid Build Coastguard Worker         } else {
1233*61046927SAndroid Build Coastguard Worker             match &self.srcs[1].src_ref {
1234*61046927SAndroid Build Coastguard Worker                 SrcRef::Zero | SrcRef::Reg(_) => {
1235*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x5c10);
1236*61046927SAndroid Build Coastguard Worker                     e.set_reg_bnot_src(20..28, 48, self.srcs[1]);
1237*61046927SAndroid Build Coastguard Worker                 }
1238*61046927SAndroid Build Coastguard Worker                 SrcRef::Imm32(imm32) => {
1239*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x3810);
1240*61046927SAndroid Build Coastguard Worker                     e.set_src_imm_i20(20..39, 56, *imm32);
1241*61046927SAndroid Build Coastguard Worker                     assert!(self.srcs[1].src_mod.is_none());
1242*61046927SAndroid Build Coastguard Worker                 }
1243*61046927SAndroid Build Coastguard Worker                 SrcRef::CBuf(_) => {
1244*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x4c10);
1245*61046927SAndroid Build Coastguard Worker                     e.set_cb_bnot_src(20..39, 48, self.srcs[1]);
1246*61046927SAndroid Build Coastguard Worker                 }
1247*61046927SAndroid Build Coastguard Worker                 src => panic!("Invalid iadd.x src1: {src}"),
1248*61046927SAndroid Build Coastguard Worker             }
1249*61046927SAndroid Build Coastguard Worker 
1250*61046927SAndroid Build Coastguard Worker             e.set_dst(self.dst);
1251*61046927SAndroid Build Coastguard Worker             e.set_reg_bnot_src(8..16, 49, self.srcs[0]);
1252*61046927SAndroid Build Coastguard Worker 
1253*61046927SAndroid Build Coastguard Worker             e.set_bit(43, true); // .X
1254*61046927SAndroid Build Coastguard Worker             e.set_bit(47, carry_out);
1255*61046927SAndroid Build Coastguard Worker         }
1256*61046927SAndroid Build Coastguard Worker     }
1257*61046927SAndroid Build Coastguard Worker }
1258*61046927SAndroid Build Coastguard Worker 
1259*61046927SAndroid Build Coastguard Worker impl SM50Op for OpIMad {
legalize(&mut self, b: &mut LegalizeBuilder)1260*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1261*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1262*61046927SAndroid Build Coastguard Worker         let [src0, src1, src2] = &mut self.srcs;
1263*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
1264*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::ALU);
1265*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(src1, GPR, SrcType::ALU);
1266*61046927SAndroid Build Coastguard Worker         if src_is_reg(src1, GPR) {
1267*61046927SAndroid Build Coastguard Worker             b.copy_alu_src_if_imm(src2, GPR, SrcType::ALU);
1268*61046927SAndroid Build Coastguard Worker         } else {
1269*61046927SAndroid Build Coastguard Worker             b.copy_alu_src_if_not_reg(src2, GPR, SrcType::ALU);
1270*61046927SAndroid Build Coastguard Worker         }
1271*61046927SAndroid Build Coastguard Worker     }
1272*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1273*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1274*61046927SAndroid Build Coastguard Worker         // There is one ineg bit shared by the two imul sources
1275*61046927SAndroid Build Coastguard Worker         let ineg_imul =
1276*61046927SAndroid Build Coastguard Worker             self.srcs[0].src_mod.is_ineg() ^ self.srcs[1].src_mod.is_ineg();
1277*61046927SAndroid Build Coastguard Worker         let ineg_src2 = self.srcs[2].src_mod.is_ineg();
1278*61046927SAndroid Build Coastguard Worker 
1279*61046927SAndroid Build Coastguard Worker         match &self.srcs[2].src_ref {
1280*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1281*61046927SAndroid Build Coastguard Worker                 match &self.srcs[1].src_ref {
1282*61046927SAndroid Build Coastguard Worker                     SrcRef::Zero | SrcRef::Reg(_) => {
1283*61046927SAndroid Build Coastguard Worker                         e.set_opcode(0x5a00);
1284*61046927SAndroid Build Coastguard Worker                         e.set_reg_src_ref(20..28, self.srcs[1].src_ref);
1285*61046927SAndroid Build Coastguard Worker                     }
1286*61046927SAndroid Build Coastguard Worker                     SrcRef::Imm32(imm32) => {
1287*61046927SAndroid Build Coastguard Worker                         e.set_opcode(0x3400);
1288*61046927SAndroid Build Coastguard Worker                         e.set_src_imm_i20(20..39, 56, *imm32);
1289*61046927SAndroid Build Coastguard Worker                     }
1290*61046927SAndroid Build Coastguard Worker                     SrcRef::CBuf(cb) => {
1291*61046927SAndroid Build Coastguard Worker                         e.set_opcode(0x4a00);
1292*61046927SAndroid Build Coastguard Worker                         e.set_src_cb(20..39, cb);
1293*61046927SAndroid Build Coastguard Worker                     }
1294*61046927SAndroid Build Coastguard Worker                     src => panic!("Invalid imad src1: {src}"),
1295*61046927SAndroid Build Coastguard Worker                 }
1296*61046927SAndroid Build Coastguard Worker 
1297*61046927SAndroid Build Coastguard Worker                 e.set_reg_src_ref(39..47, self.srcs[2].src_ref);
1298*61046927SAndroid Build Coastguard Worker             }
1299*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
1300*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5200);
1301*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
1302*61046927SAndroid Build Coastguard Worker                 e.set_reg_src_ref(39..47, self.srcs[1].src_ref);
1303*61046927SAndroid Build Coastguard Worker             }
1304*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid imad src2: {src}"),
1305*61046927SAndroid Build Coastguard Worker         }
1306*61046927SAndroid Build Coastguard Worker 
1307*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1308*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
1309*61046927SAndroid Build Coastguard Worker 
1310*61046927SAndroid Build Coastguard Worker         e.set_bit(48, self.signed); // src0 signed
1311*61046927SAndroid Build Coastguard Worker         e.set_bit(51, ineg_imul);
1312*61046927SAndroid Build Coastguard Worker         e.set_bit(52, ineg_src2);
1313*61046927SAndroid Build Coastguard Worker         e.set_bit(53, self.signed); // src1 signed
1314*61046927SAndroid Build Coastguard Worker     }
1315*61046927SAndroid Build Coastguard Worker }
1316*61046927SAndroid Build Coastguard Worker 
1317*61046927SAndroid Build Coastguard Worker impl SM50Op for OpIMul {
legalize(&mut self, b: &mut LegalizeBuilder)1318*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1319*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1320*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
1321*61046927SAndroid Build Coastguard Worker         if swap_srcs_if_not_reg(src0, src1, GPR) {
1322*61046927SAndroid Build Coastguard Worker             self.signed.swap(0, 1);
1323*61046927SAndroid Build Coastguard Worker         }
1324*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::ALU);
1325*61046927SAndroid Build Coastguard Worker     }
1326*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1327*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1328*61046927SAndroid Build Coastguard Worker         assert!(self.srcs[0].src_mod.is_none());
1329*61046927SAndroid Build Coastguard Worker         assert!(self.srcs[1].src_mod.is_none());
1330*61046927SAndroid Build Coastguard Worker 
1331*61046927SAndroid Build Coastguard Worker         if let Some(i) = self.srcs[1].as_imm_not_i20() {
1332*61046927SAndroid Build Coastguard Worker             e.set_opcode(0x1fc0);
1333*61046927SAndroid Build Coastguard Worker             e.set_src_imm32(20..52, i);
1334*61046927SAndroid Build Coastguard Worker 
1335*61046927SAndroid Build Coastguard Worker             e.set_bit(53, self.high);
1336*61046927SAndroid Build Coastguard Worker             e.set_bit(54, self.signed[0]);
1337*61046927SAndroid Build Coastguard Worker             e.set_bit(55, self.signed[1]);
1338*61046927SAndroid Build Coastguard Worker         } else {
1339*61046927SAndroid Build Coastguard Worker             match &self.srcs[1].src_ref {
1340*61046927SAndroid Build Coastguard Worker                 SrcRef::Zero | SrcRef::Reg(_) => {
1341*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x5c38);
1342*61046927SAndroid Build Coastguard Worker                     e.set_reg_src(20..28, self.srcs[1]);
1343*61046927SAndroid Build Coastguard Worker                 }
1344*61046927SAndroid Build Coastguard Worker                 SrcRef::Imm32(imm32) => {
1345*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x3838);
1346*61046927SAndroid Build Coastguard Worker                     e.set_src_imm_i20(20..39, 56, *imm32);
1347*61046927SAndroid Build Coastguard Worker                 }
1348*61046927SAndroid Build Coastguard Worker                 SrcRef::CBuf(cb) => {
1349*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x4c38);
1350*61046927SAndroid Build Coastguard Worker                     e.set_src_cb(20..39, cb);
1351*61046927SAndroid Build Coastguard Worker                 }
1352*61046927SAndroid Build Coastguard Worker                 src => panic!("Invalid imul src1: {src}"),
1353*61046927SAndroid Build Coastguard Worker             };
1354*61046927SAndroid Build Coastguard Worker 
1355*61046927SAndroid Build Coastguard Worker             e.set_bit(39, self.high);
1356*61046927SAndroid Build Coastguard Worker             e.set_bit(40, self.signed[0]);
1357*61046927SAndroid Build Coastguard Worker             e.set_bit(41, self.signed[1]);
1358*61046927SAndroid Build Coastguard Worker         }
1359*61046927SAndroid Build Coastguard Worker 
1360*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1361*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
1362*61046927SAndroid Build Coastguard Worker     }
1363*61046927SAndroid Build Coastguard Worker }
1364*61046927SAndroid Build Coastguard Worker 
1365*61046927SAndroid Build Coastguard Worker impl SM50Op for OpIMnMx {
legalize(&mut self, b: &mut LegalizeBuilder)1366*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1367*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1368*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
1369*61046927SAndroid Build Coastguard Worker         swap_srcs_if_not_reg(src0, src1, GPR);
1370*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::ALU);
1371*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(src1, GPR, SrcType::ALU);
1372*61046927SAndroid Build Coastguard Worker     }
1373*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1374*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1375*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
1376*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1377*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c20);
1378*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.srcs[1]);
1379*61046927SAndroid Build Coastguard Worker             }
1380*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1381*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3820);
1382*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1383*61046927SAndroid Build Coastguard Worker                 assert!(self.srcs[1].src_mod.is_none());
1384*61046927SAndroid Build Coastguard Worker             }
1385*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
1386*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c20);
1387*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
1388*61046927SAndroid Build Coastguard Worker             }
1389*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid imnmx src1: {src}"),
1390*61046927SAndroid Build Coastguard Worker         }
1391*61046927SAndroid Build Coastguard Worker 
1392*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1393*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
1394*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, self.min);
1395*61046927SAndroid Build Coastguard Worker         e.set_bit(47, false); // .CC
1396*61046927SAndroid Build Coastguard Worker         e.set_bit(
1397*61046927SAndroid Build Coastguard Worker             48,
1398*61046927SAndroid Build Coastguard Worker             match self.cmp_type {
1399*61046927SAndroid Build Coastguard Worker                 IntCmpType::U32 => false,
1400*61046927SAndroid Build Coastguard Worker                 IntCmpType::I32 => true,
1401*61046927SAndroid Build Coastguard Worker             },
1402*61046927SAndroid Build Coastguard Worker         );
1403*61046927SAndroid Build Coastguard Worker     }
1404*61046927SAndroid Build Coastguard Worker }
1405*61046927SAndroid Build Coastguard Worker 
1406*61046927SAndroid Build Coastguard Worker impl SM50Op for OpISetP {
legalize(&mut self, b: &mut LegalizeBuilder)1407*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1408*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1409*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
1410*61046927SAndroid Build Coastguard Worker         if swap_srcs_if_not_reg(src0, src1, GPR) {
1411*61046927SAndroid Build Coastguard Worker             self.cmp_op = self.cmp_op.flip();
1412*61046927SAndroid Build Coastguard Worker         }
1413*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::ALU);
1414*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(src1, GPR, SrcType::ALU);
1415*61046927SAndroid Build Coastguard Worker     }
1416*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1417*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1418*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
1419*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1420*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5b60);
1421*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.srcs[1]);
1422*61046927SAndroid Build Coastguard Worker             }
1423*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1424*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3660);
1425*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1426*61046927SAndroid Build Coastguard Worker                 assert!(self.srcs[1].src_mod.is_none());
1427*61046927SAndroid Build Coastguard Worker             }
1428*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
1429*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4b60);
1430*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
1431*61046927SAndroid Build Coastguard Worker             }
1432*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid isetp src1: {src}"),
1433*61046927SAndroid Build Coastguard Worker         }
1434*61046927SAndroid Build Coastguard Worker 
1435*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(0..3, Dst::None); // dst1
1436*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(3..6, self.dst);
1437*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
1438*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, self.accum);
1439*61046927SAndroid Build Coastguard Worker 
1440*61046927SAndroid Build Coastguard Worker         // isetp.x seems to take the accumulator into account and we don't fully
1441*61046927SAndroid Build Coastguard Worker         // understand how.  Until we do, disallow it.
1442*61046927SAndroid Build Coastguard Worker         assert!(!self.ex);
1443*61046927SAndroid Build Coastguard Worker         e.set_bit(43, self.ex);
1444*61046927SAndroid Build Coastguard Worker         e.set_pred_set_op(45..47, self.set_op);
1445*61046927SAndroid Build Coastguard Worker 
1446*61046927SAndroid Build Coastguard Worker         e.set_field(
1447*61046927SAndroid Build Coastguard Worker             48..49,
1448*61046927SAndroid Build Coastguard Worker             match self.cmp_type {
1449*61046927SAndroid Build Coastguard Worker                 IntCmpType::U32 => 0_u32,
1450*61046927SAndroid Build Coastguard Worker                 IntCmpType::I32 => 1_u32,
1451*61046927SAndroid Build Coastguard Worker             },
1452*61046927SAndroid Build Coastguard Worker         );
1453*61046927SAndroid Build Coastguard Worker         e.set_int_cmp_op(49..52, self.cmp_op);
1454*61046927SAndroid Build Coastguard Worker     }
1455*61046927SAndroid Build Coastguard Worker }
1456*61046927SAndroid Build Coastguard Worker 
1457*61046927SAndroid Build Coastguard Worker impl SM50Op for OpLop2 {
legalize(&mut self, b: &mut LegalizeBuilder)1458*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1459*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1460*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
1461*61046927SAndroid Build Coastguard Worker         match self.op {
1462*61046927SAndroid Build Coastguard Worker             LogicOp2::PassB => {
1463*61046927SAndroid Build Coastguard Worker                 *src0 = 0.into();
1464*61046927SAndroid Build Coastguard Worker                 b.copy_alu_src_if_i20_overflow(src1, GPR, SrcType::ALU);
1465*61046927SAndroid Build Coastguard Worker             }
1466*61046927SAndroid Build Coastguard Worker             LogicOp2::And | LogicOp2::Or | LogicOp2::Xor => {
1467*61046927SAndroid Build Coastguard Worker                 swap_srcs_if_not_reg(src0, src1, GPR);
1468*61046927SAndroid Build Coastguard Worker                 b.copy_alu_src_if_not_reg(src0, GPR, SrcType::ALU);
1469*61046927SAndroid Build Coastguard Worker             }
1470*61046927SAndroid Build Coastguard Worker         }
1471*61046927SAndroid Build Coastguard Worker     }
1472*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1473*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1474*61046927SAndroid Build Coastguard Worker         if let Some(imm32) = self.srcs[1].as_imm_not_i20() {
1475*61046927SAndroid Build Coastguard Worker             e.set_opcode(0x0400);
1476*61046927SAndroid Build Coastguard Worker 
1477*61046927SAndroid Build Coastguard Worker             e.set_dst(self.dst);
1478*61046927SAndroid Build Coastguard Worker             e.set_reg_bnot_src(8..16, 55, self.srcs[0]);
1479*61046927SAndroid Build Coastguard Worker             e.set_src_imm32(20..52, imm32);
1480*61046927SAndroid Build Coastguard Worker             e.set_field(
1481*61046927SAndroid Build Coastguard Worker                 53..55,
1482*61046927SAndroid Build Coastguard Worker                 match self.op {
1483*61046927SAndroid Build Coastguard Worker                     LogicOp2::And => 0_u8,
1484*61046927SAndroid Build Coastguard Worker                     LogicOp2::Or => 1_u8,
1485*61046927SAndroid Build Coastguard Worker                     LogicOp2::Xor => 2_u8,
1486*61046927SAndroid Build Coastguard Worker                     LogicOp2::PassB => {
1487*61046927SAndroid Build Coastguard Worker                         panic!("PASS_B is not supported for LOP32I");
1488*61046927SAndroid Build Coastguard Worker                     }
1489*61046927SAndroid Build Coastguard Worker                 },
1490*61046927SAndroid Build Coastguard Worker             );
1491*61046927SAndroid Build Coastguard Worker             e.set_bit(56, self.srcs[1].src_mod.is_bnot());
1492*61046927SAndroid Build Coastguard Worker         } else {
1493*61046927SAndroid Build Coastguard Worker             match &self.srcs[1].src_ref {
1494*61046927SAndroid Build Coastguard Worker                 SrcRef::Zero | SrcRef::Reg(_) => {
1495*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x5c40);
1496*61046927SAndroid Build Coastguard Worker                     e.set_reg_bnot_src(20..28, 40, self.srcs[1]);
1497*61046927SAndroid Build Coastguard Worker                 }
1498*61046927SAndroid Build Coastguard Worker                 SrcRef::Imm32(imm32) => {
1499*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x3840);
1500*61046927SAndroid Build Coastguard Worker                     e.set_src_imm_i20(20..39, 56, *imm32);
1501*61046927SAndroid Build Coastguard Worker                     assert!(self.srcs[1].src_mod.is_none());
1502*61046927SAndroid Build Coastguard Worker                 }
1503*61046927SAndroid Build Coastguard Worker                 SrcRef::CBuf(_) => {
1504*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0x4c40);
1505*61046927SAndroid Build Coastguard Worker                     e.set_cb_bnot_src(20..39, 40, self.srcs[1]);
1506*61046927SAndroid Build Coastguard Worker                 }
1507*61046927SAndroid Build Coastguard Worker                 src => panic!("Invalid lop2 src1: {src}"),
1508*61046927SAndroid Build Coastguard Worker             }
1509*61046927SAndroid Build Coastguard Worker 
1510*61046927SAndroid Build Coastguard Worker             e.set_dst(self.dst);
1511*61046927SAndroid Build Coastguard Worker             e.set_reg_bnot_src(8..16, 39, self.srcs[0]);
1512*61046927SAndroid Build Coastguard Worker 
1513*61046927SAndroid Build Coastguard Worker             e.set_field(
1514*61046927SAndroid Build Coastguard Worker                 41..43,
1515*61046927SAndroid Build Coastguard Worker                 match self.op {
1516*61046927SAndroid Build Coastguard Worker                     LogicOp2::And => 0_u8,
1517*61046927SAndroid Build Coastguard Worker                     LogicOp2::Or => 1_u8,
1518*61046927SAndroid Build Coastguard Worker                     LogicOp2::Xor => 2_u8,
1519*61046927SAndroid Build Coastguard Worker                     LogicOp2::PassB => 3_u8,
1520*61046927SAndroid Build Coastguard Worker                 },
1521*61046927SAndroid Build Coastguard Worker             );
1522*61046927SAndroid Build Coastguard Worker 
1523*61046927SAndroid Build Coastguard Worker             e.set_pred_dst(48..51, Dst::None);
1524*61046927SAndroid Build Coastguard Worker         }
1525*61046927SAndroid Build Coastguard Worker     }
1526*61046927SAndroid Build Coastguard Worker }
1527*61046927SAndroid Build Coastguard Worker 
1528*61046927SAndroid Build Coastguard Worker impl SM50Op for OpPopC {
legalize(&mut self, b: &mut LegalizeBuilder)1529*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1530*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1531*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(&mut self.src, GPR, SrcType::ALU);
1532*61046927SAndroid Build Coastguard Worker     }
1533*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1534*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1535*61046927SAndroid Build Coastguard Worker         match &self.src.src_ref {
1536*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1537*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c08);
1538*61046927SAndroid Build Coastguard Worker                 e.set_reg_bnot_src(20..28, 40, self.src);
1539*61046927SAndroid Build Coastguard Worker             }
1540*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1541*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3808);
1542*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1543*61046927SAndroid Build Coastguard Worker                 e.set_bit(40, self.src.src_mod.is_bnot());
1544*61046927SAndroid Build Coastguard Worker             }
1545*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
1546*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c08);
1547*61046927SAndroid Build Coastguard Worker                 e.set_cb_bnot_src(20..39, 40, self.src);
1548*61046927SAndroid Build Coastguard Worker             }
1549*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid popc src1: {src}"),
1550*61046927SAndroid Build Coastguard Worker         }
1551*61046927SAndroid Build Coastguard Worker 
1552*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1553*61046927SAndroid Build Coastguard Worker     }
1554*61046927SAndroid Build Coastguard Worker }
1555*61046927SAndroid Build Coastguard Worker 
1556*61046927SAndroid Build Coastguard Worker impl SM50Op for OpShf {
legalize(&mut self, b: &mut LegalizeBuilder)1557*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1558*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1559*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.high, GPR, SrcType::ALU);
1560*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.low, GPR, SrcType::GPR);
1561*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg_or_imm(&mut self.shift, GPR, SrcType::GPR);
1562*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(&mut self.shift, GPR, SrcType::GPR);
1563*61046927SAndroid Build Coastguard Worker     }
1564*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1565*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1566*61046927SAndroid Build Coastguard Worker         match &self.shift.src_ref {
1567*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1568*61046927SAndroid Build Coastguard Worker                 e.set_opcode(if self.right { 0x5cf8 } else { 0x5bf8 });
1569*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.shift);
1570*61046927SAndroid Build Coastguard Worker             }
1571*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1572*61046927SAndroid Build Coastguard Worker                 e.set_opcode(if self.right { 0x38f8 } else { 0x36f8 });
1573*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1574*61046927SAndroid Build Coastguard Worker                 assert!(self.shift.src_mod.is_none());
1575*61046927SAndroid Build Coastguard Worker             }
1576*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid shf shift: {src}"),
1577*61046927SAndroid Build Coastguard Worker         }
1578*61046927SAndroid Build Coastguard Worker 
1579*61046927SAndroid Build Coastguard Worker         e.set_field(
1580*61046927SAndroid Build Coastguard Worker             37..39,
1581*61046927SAndroid Build Coastguard Worker             match self.data_type {
1582*61046927SAndroid Build Coastguard Worker                 IntType::I32 => 0_u8,
1583*61046927SAndroid Build Coastguard Worker                 IntType::U32 => 0_u8,
1584*61046927SAndroid Build Coastguard Worker                 IntType::U64 => 2_u8,
1585*61046927SAndroid Build Coastguard Worker                 IntType::I64 => 3_u8,
1586*61046927SAndroid Build Coastguard Worker                 _ => panic!("Invalid shift data type"),
1587*61046927SAndroid Build Coastguard Worker             },
1588*61046927SAndroid Build Coastguard Worker         );
1589*61046927SAndroid Build Coastguard Worker 
1590*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1591*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.low);
1592*61046927SAndroid Build Coastguard Worker         e.set_reg_src(39..47, self.high);
1593*61046927SAndroid Build Coastguard Worker 
1594*61046927SAndroid Build Coastguard Worker         e.set_bit(47, false); // .CC
1595*61046927SAndroid Build Coastguard Worker 
1596*61046927SAndroid Build Coastguard Worker         // If we're shifting left, the HW will throw an illegal instrucction
1597*61046927SAndroid Build Coastguard Worker         // encoding error if we set .high and will give us the high part anyway
1598*61046927SAndroid Build Coastguard Worker         // if we don't.  This makes everything a bit more consistent.
1599*61046927SAndroid Build Coastguard Worker         assert!(self.right || self.dst_high);
1600*61046927SAndroid Build Coastguard Worker         e.set_bit(48, self.dst_high && self.right); // .high
1601*61046927SAndroid Build Coastguard Worker 
1602*61046927SAndroid Build Coastguard Worker         e.set_bit(49, false); // .X
1603*61046927SAndroid Build Coastguard Worker         e.set_bit(50, self.wrap);
1604*61046927SAndroid Build Coastguard Worker     }
1605*61046927SAndroid Build Coastguard Worker }
1606*61046927SAndroid Build Coastguard Worker 
1607*61046927SAndroid Build Coastguard Worker impl SM50Op for OpShl {
legalize(&mut self, b: &mut LegalizeBuilder)1608*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1609*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1610*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.src, GPR, SrcType::GPR);
1611*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(&mut self.shift, GPR, SrcType::ALU);
1612*61046927SAndroid Build Coastguard Worker     }
1613*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1614*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1615*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1616*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.src);
1617*61046927SAndroid Build Coastguard Worker         match &self.shift.src_ref {
1618*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1619*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c48);
1620*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.shift);
1621*61046927SAndroid Build Coastguard Worker             }
1622*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1623*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3848);
1624*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1625*61046927SAndroid Build Coastguard Worker             }
1626*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
1627*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c48);
1628*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
1629*61046927SAndroid Build Coastguard Worker             }
1630*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid shl shift: {src}"),
1631*61046927SAndroid Build Coastguard Worker         }
1632*61046927SAndroid Build Coastguard Worker 
1633*61046927SAndroid Build Coastguard Worker         e.set_bit(39, self.wrap);
1634*61046927SAndroid Build Coastguard Worker     }
1635*61046927SAndroid Build Coastguard Worker }
1636*61046927SAndroid Build Coastguard Worker 
1637*61046927SAndroid Build Coastguard Worker impl SM50Op for OpShr {
legalize(&mut self, b: &mut LegalizeBuilder)1638*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1639*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1640*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.src, GPR, SrcType::GPR);
1641*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(&mut self.shift, GPR, SrcType::ALU);
1642*61046927SAndroid Build Coastguard Worker     }
1643*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1644*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1645*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1646*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.src);
1647*61046927SAndroid Build Coastguard Worker         match &self.shift.src_ref {
1648*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1649*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c28);
1650*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.shift);
1651*61046927SAndroid Build Coastguard Worker             }
1652*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1653*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x3828);
1654*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1655*61046927SAndroid Build Coastguard Worker             }
1656*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
1657*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c28);
1658*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
1659*61046927SAndroid Build Coastguard Worker             }
1660*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid shr shift: {src}"),
1661*61046927SAndroid Build Coastguard Worker         }
1662*61046927SAndroid Build Coastguard Worker 
1663*61046927SAndroid Build Coastguard Worker         e.set_bit(39, self.wrap);
1664*61046927SAndroid Build Coastguard Worker         e.set_bit(48, self.signed);
1665*61046927SAndroid Build Coastguard Worker     }
1666*61046927SAndroid Build Coastguard Worker }
1667*61046927SAndroid Build Coastguard Worker 
1668*61046927SAndroid Build Coastguard Worker impl SM50Op for OpF2F {
legalize(&mut self, b: &mut LegalizeBuilder)1669*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1670*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1671*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(&mut self.src, GPR, SrcType::ALU);
1672*61046927SAndroid Build Coastguard Worker     }
1673*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1674*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1675*61046927SAndroid Build Coastguard Worker         match &self.src.src_ref {
1676*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1677*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5ca8);
1678*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..28, 49, 45, self.src);
1679*61046927SAndroid Build Coastguard Worker             }
1680*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1681*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x38a8);
1682*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1683*61046927SAndroid Build Coastguard Worker                 assert!(self.src.src_mod.is_none());
1684*61046927SAndroid Build Coastguard Worker             }
1685*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
1686*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4ca8);
1687*61046927SAndroid Build Coastguard Worker                 e.set_cb_fmod_src(20..39, 49, 45, self.src);
1688*61046927SAndroid Build Coastguard Worker             }
1689*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid f2f src: {src}"),
1690*61046927SAndroid Build Coastguard Worker         }
1691*61046927SAndroid Build Coastguard Worker 
1692*61046927SAndroid Build Coastguard Worker         // We can't span 32 bits
1693*61046927SAndroid Build Coastguard Worker         assert!(
1694*61046927SAndroid Build Coastguard Worker             (self.dst_type.bits() <= 32 && self.src_type.bits() <= 32)
1695*61046927SAndroid Build Coastguard Worker                 || (self.dst_type.bits() >= 32 && self.src_type.bits() >= 32)
1696*61046927SAndroid Build Coastguard Worker         );
1697*61046927SAndroid Build Coastguard Worker         e.set_field(8..10, (self.dst_type.bits() / 8).ilog2());
1698*61046927SAndroid Build Coastguard Worker         e.set_field(10..12, (self.src_type.bits() / 8).ilog2());
1699*61046927SAndroid Build Coastguard Worker 
1700*61046927SAndroid Build Coastguard Worker         e.set_rnd_mode(39..41, self.rnd_mode);
1701*61046927SAndroid Build Coastguard Worker         e.set_bit(41, self.high);
1702*61046927SAndroid Build Coastguard Worker         e.set_bit(42, self.integer_rnd);
1703*61046927SAndroid Build Coastguard Worker         e.set_bit(44, self.ftz);
1704*61046927SAndroid Build Coastguard Worker         e.set_bit(50, false); // saturate
1705*61046927SAndroid Build Coastguard Worker 
1706*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1707*61046927SAndroid Build Coastguard Worker     }
1708*61046927SAndroid Build Coastguard Worker }
1709*61046927SAndroid Build Coastguard Worker 
1710*61046927SAndroid Build Coastguard Worker impl SM50Op for OpF2I {
legalize(&mut self, b: &mut LegalizeBuilder)1711*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1712*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1713*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_f20_overflow(&mut self.src, GPR, SrcType::ALU);
1714*61046927SAndroid Build Coastguard Worker     }
1715*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1716*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1717*61046927SAndroid Build Coastguard Worker         match &self.src.src_ref {
1718*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1719*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5cb0);
1720*61046927SAndroid Build Coastguard Worker                 e.set_reg_fmod_src(20..28, 49, 45, self.src);
1721*61046927SAndroid Build Coastguard Worker             }
1722*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1723*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x38b0);
1724*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_f20(20..39, 56, *imm32);
1725*61046927SAndroid Build Coastguard Worker                 assert!(self.src.src_mod.is_none());
1726*61046927SAndroid Build Coastguard Worker             }
1727*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
1728*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4cb0);
1729*61046927SAndroid Build Coastguard Worker                 e.set_cb_fmod_src(20..39, 49, 45, self.src);
1730*61046927SAndroid Build Coastguard Worker             }
1731*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid f2i src: {src}"),
1732*61046927SAndroid Build Coastguard Worker         }
1733*61046927SAndroid Build Coastguard Worker 
1734*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1735*61046927SAndroid Build Coastguard Worker 
1736*61046927SAndroid Build Coastguard Worker         // We can't span 32 bits
1737*61046927SAndroid Build Coastguard Worker         assert!(
1738*61046927SAndroid Build Coastguard Worker             (self.dst_type.bits() <= 32 && self.src_type.bits() <= 32)
1739*61046927SAndroid Build Coastguard Worker                 || (self.dst_type.bits() >= 32 && self.src_type.bits() >= 32)
1740*61046927SAndroid Build Coastguard Worker         );
1741*61046927SAndroid Build Coastguard Worker         e.set_field(8..10, (self.dst_type.bits() / 8).ilog2());
1742*61046927SAndroid Build Coastguard Worker         e.set_field(10..12, (self.src_type.bits() / 8).ilog2());
1743*61046927SAndroid Build Coastguard Worker         e.set_bit(12, self.dst_type.is_signed());
1744*61046927SAndroid Build Coastguard Worker 
1745*61046927SAndroid Build Coastguard Worker         e.set_rnd_mode(39..41, self.rnd_mode);
1746*61046927SAndroid Build Coastguard Worker         e.set_bit(44, self.ftz);
1747*61046927SAndroid Build Coastguard Worker         e.set_bit(47, false); // .CC
1748*61046927SAndroid Build Coastguard Worker     }
1749*61046927SAndroid Build Coastguard Worker }
1750*61046927SAndroid Build Coastguard Worker 
1751*61046927SAndroid Build Coastguard Worker impl SM50Op for OpI2F {
legalize(&mut self, b: &mut LegalizeBuilder)1752*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1753*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1754*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(&mut self.src, GPR, SrcType::ALU);
1755*61046927SAndroid Build Coastguard Worker     }
1756*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1757*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1758*61046927SAndroid Build Coastguard Worker         match &self.src.src_ref {
1759*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1760*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5cb8);
1761*61046927SAndroid Build Coastguard Worker                 e.set_reg_ineg_src(20..28, 45, self.src);
1762*61046927SAndroid Build Coastguard Worker             }
1763*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1764*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x38b8);
1765*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1766*61046927SAndroid Build Coastguard Worker                 assert!(self.src.src_mod.is_none());
1767*61046927SAndroid Build Coastguard Worker             }
1768*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(_) => {
1769*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4cb8);
1770*61046927SAndroid Build Coastguard Worker                 e.set_cb_ineg_src(20..39, 45, self.src);
1771*61046927SAndroid Build Coastguard Worker             }
1772*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid i2f src: {src}"),
1773*61046927SAndroid Build Coastguard Worker         }
1774*61046927SAndroid Build Coastguard Worker 
1775*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1776*61046927SAndroid Build Coastguard Worker 
1777*61046927SAndroid Build Coastguard Worker         // We can't span 32 bits
1778*61046927SAndroid Build Coastguard Worker         assert!(
1779*61046927SAndroid Build Coastguard Worker             (self.dst_type.bits() <= 32 && self.src_type.bits() <= 32)
1780*61046927SAndroid Build Coastguard Worker                 || (self.dst_type.bits() >= 32 && self.src_type.bits() >= 32)
1781*61046927SAndroid Build Coastguard Worker         );
1782*61046927SAndroid Build Coastguard Worker         e.set_field(8..10, (self.dst_type.bits() / 8).ilog2());
1783*61046927SAndroid Build Coastguard Worker         e.set_field(10..12, (self.src_type.bits() / 8).ilog2());
1784*61046927SAndroid Build Coastguard Worker         e.set_bit(13, self.src_type.is_signed());
1785*61046927SAndroid Build Coastguard Worker 
1786*61046927SAndroid Build Coastguard Worker         e.set_rnd_mode(39..41, self.rnd_mode);
1787*61046927SAndroid Build Coastguard Worker         e.set_field(41..43, 0_u8); // TODO: subop
1788*61046927SAndroid Build Coastguard Worker         e.set_bit(49, false); // iabs
1789*61046927SAndroid Build Coastguard Worker     }
1790*61046927SAndroid Build Coastguard Worker }
1791*61046927SAndroid Build Coastguard Worker 
1792*61046927SAndroid Build Coastguard Worker impl SM50Op for OpI2I {
legalize(&mut self, b: &mut LegalizeBuilder)1793*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1794*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1795*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(&mut self.src, GPR, SrcType::ALU);
1796*61046927SAndroid Build Coastguard Worker     }
1797*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1798*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1799*61046927SAndroid Build Coastguard Worker         match &self.src.src_ref {
1800*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1801*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5ce0);
1802*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.src);
1803*61046927SAndroid Build Coastguard Worker             }
1804*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1805*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x38e0);
1806*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1807*61046927SAndroid Build Coastguard Worker             }
1808*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cbuf) => {
1809*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4ce0);
1810*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cbuf);
1811*61046927SAndroid Build Coastguard Worker             }
1812*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid i2i src: {src}"),
1813*61046927SAndroid Build Coastguard Worker         }
1814*61046927SAndroid Build Coastguard Worker 
1815*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1816*61046927SAndroid Build Coastguard Worker 
1817*61046927SAndroid Build Coastguard Worker         // We can't span 32 bits
1818*61046927SAndroid Build Coastguard Worker         assert!(
1819*61046927SAndroid Build Coastguard Worker             (self.dst_type.bits() <= 32 && self.src_type.bits() <= 32)
1820*61046927SAndroid Build Coastguard Worker                 || (self.dst_type.bits() >= 32 && self.src_type.bits() >= 32)
1821*61046927SAndroid Build Coastguard Worker         );
1822*61046927SAndroid Build Coastguard Worker         e.set_field(8..10, (self.dst_type.bits() / 8).ilog2());
1823*61046927SAndroid Build Coastguard Worker         e.set_field(10..12, (self.src_type.bits() / 8).ilog2());
1824*61046927SAndroid Build Coastguard Worker         e.set_bit(12, self.dst_type.is_signed());
1825*61046927SAndroid Build Coastguard Worker         e.set_bit(13, self.src_type.is_signed());
1826*61046927SAndroid Build Coastguard Worker 
1827*61046927SAndroid Build Coastguard Worker         e.set_field(41..43, 0u8); // src.B1-3
1828*61046927SAndroid Build Coastguard Worker         e.set_bit(45, self.neg);
1829*61046927SAndroid Build Coastguard Worker         e.set_bit(47, false); // dst.CC
1830*61046927SAndroid Build Coastguard Worker         e.set_bit(49, self.abs);
1831*61046927SAndroid Build Coastguard Worker         e.set_bit(50, self.saturate);
1832*61046927SAndroid Build Coastguard Worker     }
1833*61046927SAndroid Build Coastguard Worker }
1834*61046927SAndroid Build Coastguard Worker 
1835*61046927SAndroid Build Coastguard Worker impl SM50Op for OpMov {
legalize(&mut self, _b: &mut LegalizeBuilder)1836*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1837*61046927SAndroid Build Coastguard Worker         // Nothing to do
1838*61046927SAndroid Build Coastguard Worker     }
1839*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1840*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1841*61046927SAndroid Build Coastguard Worker         match &self.src.src_ref {
1842*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1843*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5c98);
1844*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.src);
1845*61046927SAndroid Build Coastguard Worker                 e.set_field(39..43, self.quad_lanes);
1846*61046927SAndroid Build Coastguard Worker             }
1847*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1848*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x0100);
1849*61046927SAndroid Build Coastguard Worker                 e.set_src_imm32(20..52, *imm32);
1850*61046927SAndroid Build Coastguard Worker                 e.set_field(12..16, self.quad_lanes);
1851*61046927SAndroid Build Coastguard Worker             }
1852*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
1853*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4c98);
1854*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
1855*61046927SAndroid Build Coastguard Worker                 e.set_field(39..43, self.quad_lanes);
1856*61046927SAndroid Build Coastguard Worker             }
1857*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid mov src: {src}"),
1858*61046927SAndroid Build Coastguard Worker         }
1859*61046927SAndroid Build Coastguard Worker 
1860*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1861*61046927SAndroid Build Coastguard Worker     }
1862*61046927SAndroid Build Coastguard Worker }
1863*61046927SAndroid Build Coastguard Worker 
1864*61046927SAndroid Build Coastguard Worker impl SM50Op for OpPrmt {
legalize(&mut self, b: &mut LegalizeBuilder)1865*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1866*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1867*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.srcs[0], GPR, SrcType::GPR);
1868*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.srcs[1], GPR, SrcType::GPR);
1869*61046927SAndroid Build Coastguard Worker     }
1870*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1871*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1872*61046927SAndroid Build Coastguard Worker         match &self.sel.src_ref {
1873*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1874*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5bc0);
1875*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.sel);
1876*61046927SAndroid Build Coastguard Worker             }
1877*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1878*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x36c0);
1879*61046927SAndroid Build Coastguard Worker                 // Only the bottom 16 bits matter
1880*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32 & 0xffff);
1881*61046927SAndroid Build Coastguard Worker             }
1882*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cb) => {
1883*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4bc0);
1884*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cb);
1885*61046927SAndroid Build Coastguard Worker             }
1886*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid prmt selector: {src}"),
1887*61046927SAndroid Build Coastguard Worker         }
1888*61046927SAndroid Build Coastguard Worker 
1889*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1890*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
1891*61046927SAndroid Build Coastguard Worker         e.set_reg_src(39..47, self.srcs[1]);
1892*61046927SAndroid Build Coastguard Worker         e.set_field(
1893*61046927SAndroid Build Coastguard Worker             48..51,
1894*61046927SAndroid Build Coastguard Worker             match self.mode {
1895*61046927SAndroid Build Coastguard Worker                 PrmtMode::Index => 0_u8,
1896*61046927SAndroid Build Coastguard Worker                 PrmtMode::Forward4Extract => 1_u8,
1897*61046927SAndroid Build Coastguard Worker                 PrmtMode::Backward4Extract => 2_u8,
1898*61046927SAndroid Build Coastguard Worker                 PrmtMode::Replicate8 => 3_u8,
1899*61046927SAndroid Build Coastguard Worker                 PrmtMode::EdgeClampLeft => 4_u8,
1900*61046927SAndroid Build Coastguard Worker                 PrmtMode::EdgeClampRight => 5_u8,
1901*61046927SAndroid Build Coastguard Worker                 PrmtMode::Replicate16 => 6_u8,
1902*61046927SAndroid Build Coastguard Worker             },
1903*61046927SAndroid Build Coastguard Worker         );
1904*61046927SAndroid Build Coastguard Worker     }
1905*61046927SAndroid Build Coastguard Worker }
1906*61046927SAndroid Build Coastguard Worker 
1907*61046927SAndroid Build Coastguard Worker impl SM50Op for OpSel {
legalize(&mut self, b: &mut LegalizeBuilder)1908*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1909*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1910*61046927SAndroid Build Coastguard Worker         let [src0, src1] = &mut self.srcs;
1911*61046927SAndroid Build Coastguard Worker         if swap_srcs_if_not_reg(src0, src1, GPR) {
1912*61046927SAndroid Build Coastguard Worker             self.cond = self.cond.bnot();
1913*61046927SAndroid Build Coastguard Worker         }
1914*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(src0, GPR, SrcType::ALU);
1915*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(src1, GPR, SrcType::ALU);
1916*61046927SAndroid Build Coastguard Worker     }
1917*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1918*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1919*61046927SAndroid Build Coastguard Worker         match &self.srcs[1].src_ref {
1920*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1921*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x5ca0);
1922*61046927SAndroid Build Coastguard Worker                 e.set_reg_src_ref(20..28, self.srcs[1].src_ref);
1923*61046927SAndroid Build Coastguard Worker             }
1924*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1925*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x38a0);
1926*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
1927*61046927SAndroid Build Coastguard Worker             }
1928*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cbuf) => {
1929*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0x4ca0);
1930*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cbuf);
1931*61046927SAndroid Build Coastguard Worker             }
1932*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid sel src1: {src}"),
1933*61046927SAndroid Build Coastguard Worker         }
1934*61046927SAndroid Build Coastguard Worker 
1935*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1936*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
1937*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, self.cond);
1938*61046927SAndroid Build Coastguard Worker     }
1939*61046927SAndroid Build Coastguard Worker }
1940*61046927SAndroid Build Coastguard Worker 
1941*61046927SAndroid Build Coastguard Worker impl SM50Op for OpShfl {
legalize(&mut self, b: &mut LegalizeBuilder)1942*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
1943*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
1944*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.src, GPR, SrcType::GPR);
1945*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg_or_imm(&mut self.lane, GPR, SrcType::ALU);
1946*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg_or_imm(&mut self.c, GPR, SrcType::ALU);
1947*61046927SAndroid Build Coastguard Worker     }
1948*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1949*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1950*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xef10);
1951*61046927SAndroid Build Coastguard Worker 
1952*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
1953*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(48..51, self.in_bounds);
1954*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.src);
1955*61046927SAndroid Build Coastguard Worker 
1956*61046927SAndroid Build Coastguard Worker         match &self.lane.src_ref {
1957*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1958*61046927SAndroid Build Coastguard Worker                 e.set_bit(28, false);
1959*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.lane);
1960*61046927SAndroid Build Coastguard Worker             }
1961*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1962*61046927SAndroid Build Coastguard Worker                 e.set_bit(28, true);
1963*61046927SAndroid Build Coastguard Worker                 e.set_field(20..25, *imm32 & 0x1f);
1964*61046927SAndroid Build Coastguard Worker             }
1965*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid shfl lane: {src}"),
1966*61046927SAndroid Build Coastguard Worker         }
1967*61046927SAndroid Build Coastguard Worker         match &self.c.src_ref {
1968*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
1969*61046927SAndroid Build Coastguard Worker                 e.set_bit(29, false);
1970*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(39..47, self.c);
1971*61046927SAndroid Build Coastguard Worker             }
1972*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
1973*61046927SAndroid Build Coastguard Worker                 e.set_bit(29, true);
1974*61046927SAndroid Build Coastguard Worker                 e.set_field(34..47, *imm32 & 0x1f1f);
1975*61046927SAndroid Build Coastguard Worker             }
1976*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid shfl c: {src}"),
1977*61046927SAndroid Build Coastguard Worker         }
1978*61046927SAndroid Build Coastguard Worker 
1979*61046927SAndroid Build Coastguard Worker         e.set_field(
1980*61046927SAndroid Build Coastguard Worker             30..32,
1981*61046927SAndroid Build Coastguard Worker             match self.op {
1982*61046927SAndroid Build Coastguard Worker                 ShflOp::Idx => 0u8,
1983*61046927SAndroid Build Coastguard Worker                 ShflOp::Up => 1u8,
1984*61046927SAndroid Build Coastguard Worker                 ShflOp::Down => 2u8,
1985*61046927SAndroid Build Coastguard Worker                 ShflOp::Bfly => 3u8,
1986*61046927SAndroid Build Coastguard Worker             },
1987*61046927SAndroid Build Coastguard Worker         );
1988*61046927SAndroid Build Coastguard Worker     }
1989*61046927SAndroid Build Coastguard Worker }
1990*61046927SAndroid Build Coastguard Worker 
1991*61046927SAndroid Build Coastguard Worker impl SM50Op for OpPSetP {
legalize(&mut self, _b: &mut LegalizeBuilder)1992*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
1993*61046927SAndroid Build Coastguard Worker         // Nothing to do
1994*61046927SAndroid Build Coastguard Worker     }
1995*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)1996*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
1997*61046927SAndroid Build Coastguard Worker         e.set_opcode(0x5090);
1998*61046927SAndroid Build Coastguard Worker 
1999*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(3..6, self.dsts[0]);
2000*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(0..3, self.dsts[1]);
2001*61046927SAndroid Build Coastguard Worker 
2002*61046927SAndroid Build Coastguard Worker         e.set_pred_src(12..15, 15, self.srcs[0]);
2003*61046927SAndroid Build Coastguard Worker         e.set_pred_src(29..32, 32, self.srcs[1]);
2004*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, self.srcs[2]);
2005*61046927SAndroid Build Coastguard Worker 
2006*61046927SAndroid Build Coastguard Worker         e.set_pred_set_op(24..26, self.ops[0]);
2007*61046927SAndroid Build Coastguard Worker         e.set_pred_set_op(45..47, self.ops[1]);
2008*61046927SAndroid Build Coastguard Worker     }
2009*61046927SAndroid Build Coastguard Worker }
2010*61046927SAndroid Build Coastguard Worker 
2011*61046927SAndroid Build Coastguard Worker impl SM50Encoder<'_> {
set_tex_dim(&mut self, range: Range<usize>, dim: TexDim)2012*61046927SAndroid Build Coastguard Worker     fn set_tex_dim(&mut self, range: Range<usize>, dim: TexDim) {
2013*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 3);
2014*61046927SAndroid Build Coastguard Worker         self.set_field(
2015*61046927SAndroid Build Coastguard Worker             range,
2016*61046927SAndroid Build Coastguard Worker             match dim {
2017*61046927SAndroid Build Coastguard Worker                 TexDim::_1D => 0_u8,
2018*61046927SAndroid Build Coastguard Worker                 TexDim::Array1D => 1_u8,
2019*61046927SAndroid Build Coastguard Worker                 TexDim::_2D => 2_u8,
2020*61046927SAndroid Build Coastguard Worker                 TexDim::Array2D => 3_u8,
2021*61046927SAndroid Build Coastguard Worker                 TexDim::_3D => 4_u8,
2022*61046927SAndroid Build Coastguard Worker                 TexDim::Cube => 6_u8,
2023*61046927SAndroid Build Coastguard Worker                 TexDim::ArrayCube => 7_u8,
2024*61046927SAndroid Build Coastguard Worker             },
2025*61046927SAndroid Build Coastguard Worker         );
2026*61046927SAndroid Build Coastguard Worker     }
2027*61046927SAndroid Build Coastguard Worker 
set_tex_lod_mode(&mut self, range: Range<usize>, lod_mode: TexLodMode)2028*61046927SAndroid Build Coastguard Worker     fn set_tex_lod_mode(&mut self, range: Range<usize>, lod_mode: TexLodMode) {
2029*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 2);
2030*61046927SAndroid Build Coastguard Worker         self.set_field(
2031*61046927SAndroid Build Coastguard Worker             range,
2032*61046927SAndroid Build Coastguard Worker             match lod_mode {
2033*61046927SAndroid Build Coastguard Worker                 TexLodMode::Auto => 0_u8,
2034*61046927SAndroid Build Coastguard Worker                 TexLodMode::Zero => 1_u8,
2035*61046927SAndroid Build Coastguard Worker                 TexLodMode::Bias => 2_u8,
2036*61046927SAndroid Build Coastguard Worker                 TexLodMode::Lod => 3_u8,
2037*61046927SAndroid Build Coastguard Worker                 _ => panic!("Unknown LOD mode"),
2038*61046927SAndroid Build Coastguard Worker             },
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 SM50Op for OpTex {
legalize(&mut self, b: &mut LegalizeBuilder)2044*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2045*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2046*61046927SAndroid Build Coastguard Worker     }
2047*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2048*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2049*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xdeb8);
2050*61046927SAndroid Build Coastguard Worker 
2051*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dsts[0]);
2052*61046927SAndroid Build Coastguard Worker         assert!(self.dsts[1].is_none());
2053*61046927SAndroid Build Coastguard Worker         assert!(self.fault.is_none());
2054*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
2055*61046927SAndroid Build Coastguard Worker         e.set_reg_src(20..28, self.srcs[1]);
2056*61046927SAndroid Build Coastguard Worker 
2057*61046927SAndroid Build Coastguard Worker         e.set_tex_dim(28..31, self.dim);
2058*61046927SAndroid Build Coastguard Worker         e.set_field(31..35, self.mask);
2059*61046927SAndroid Build Coastguard Worker         e.set_bit(35, false); // ToDo: NDV
2060*61046927SAndroid Build Coastguard Worker         e.set_bit(36, self.offset);
2061*61046927SAndroid Build Coastguard Worker         e.set_tex_lod_mode(37..39, self.lod_mode);
2062*61046927SAndroid Build Coastguard Worker         e.set_bit(49, false); // TODO: .NODEP
2063*61046927SAndroid Build Coastguard Worker         e.set_bit(50, self.z_cmpr);
2064*61046927SAndroid Build Coastguard Worker     }
2065*61046927SAndroid Build Coastguard Worker }
2066*61046927SAndroid Build Coastguard Worker 
2067*61046927SAndroid Build Coastguard Worker impl SM50Op for OpTld {
legalize(&mut self, b: &mut LegalizeBuilder)2068*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2069*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2070*61046927SAndroid Build Coastguard Worker     }
2071*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2072*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2073*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xdd38);
2074*61046927SAndroid Build Coastguard Worker 
2075*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dsts[0]);
2076*61046927SAndroid Build Coastguard Worker         assert!(self.dsts[1].is_none());
2077*61046927SAndroid Build Coastguard Worker         assert!(self.fault.is_none());
2078*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
2079*61046927SAndroid Build Coastguard Worker         e.set_reg_src(20..28, self.srcs[1]);
2080*61046927SAndroid Build Coastguard Worker 
2081*61046927SAndroid Build Coastguard Worker         e.set_tex_dim(28..31, self.dim);
2082*61046927SAndroid Build Coastguard Worker         e.set_field(31..35, self.mask);
2083*61046927SAndroid Build Coastguard Worker         e.set_bit(35, self.offset);
2084*61046927SAndroid Build Coastguard Worker         e.set_bit(49, false); // TODO: .NODEP
2085*61046927SAndroid Build Coastguard Worker         e.set_bit(50, self.is_ms);
2086*61046927SAndroid Build Coastguard Worker 
2087*61046927SAndroid Build Coastguard Worker         assert!(
2088*61046927SAndroid Build Coastguard Worker             self.lod_mode == TexLodMode::Zero
2089*61046927SAndroid Build Coastguard Worker                 || self.lod_mode == TexLodMode::Lod
2090*61046927SAndroid Build Coastguard Worker         );
2091*61046927SAndroid Build Coastguard Worker         e.set_bit(55, self.lod_mode == TexLodMode::Lod);
2092*61046927SAndroid Build Coastguard Worker     }
2093*61046927SAndroid Build Coastguard Worker }
2094*61046927SAndroid Build Coastguard Worker 
2095*61046927SAndroid Build Coastguard Worker impl SM50Op for OpTld4 {
legalize(&mut self, b: &mut LegalizeBuilder)2096*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2097*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2098*61046927SAndroid Build Coastguard Worker     }
2099*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2100*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2101*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xdef8);
2102*61046927SAndroid Build Coastguard Worker 
2103*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dsts[0]);
2104*61046927SAndroid Build Coastguard Worker         assert!(self.dsts[1].is_none());
2105*61046927SAndroid Build Coastguard Worker         assert!(self.fault.is_none());
2106*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
2107*61046927SAndroid Build Coastguard Worker         e.set_reg_src(20..28, self.srcs[1]);
2108*61046927SAndroid Build Coastguard Worker 
2109*61046927SAndroid Build Coastguard Worker         e.set_tex_dim(28..31, self.dim);
2110*61046927SAndroid Build Coastguard Worker         e.set_field(31..35, self.mask);
2111*61046927SAndroid Build Coastguard Worker         e.set_bit(35, false); // ToDo: NDV
2112*61046927SAndroid Build Coastguard Worker         e.set_field(
2113*61046927SAndroid Build Coastguard Worker             36..38,
2114*61046927SAndroid Build Coastguard Worker             match self.offset_mode {
2115*61046927SAndroid Build Coastguard Worker                 Tld4OffsetMode::None => 0_u8,
2116*61046927SAndroid Build Coastguard Worker                 Tld4OffsetMode::AddOffI => 1_u8,
2117*61046927SAndroid Build Coastguard Worker                 Tld4OffsetMode::PerPx => 2_u8,
2118*61046927SAndroid Build Coastguard Worker             },
2119*61046927SAndroid Build Coastguard Worker         );
2120*61046927SAndroid Build Coastguard Worker         e.set_field(38..40, self.comp);
2121*61046927SAndroid Build Coastguard Worker         e.set_bit(49, false); // TODO: .NODEP
2122*61046927SAndroid Build Coastguard Worker         e.set_bit(50, self.z_cmpr);
2123*61046927SAndroid Build Coastguard Worker     }
2124*61046927SAndroid Build Coastguard Worker }
2125*61046927SAndroid Build Coastguard Worker 
2126*61046927SAndroid Build Coastguard Worker impl SM50Op for OpTmml {
legalize(&mut self, b: &mut LegalizeBuilder)2127*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2128*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2129*61046927SAndroid Build Coastguard Worker     }
2130*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2131*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2132*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xdf60);
2133*61046927SAndroid Build Coastguard Worker 
2134*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dsts[0]);
2135*61046927SAndroid Build Coastguard Worker         assert!(self.dsts[1].is_none());
2136*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
2137*61046927SAndroid Build Coastguard Worker         e.set_reg_src(20..28, self.srcs[1]);
2138*61046927SAndroid Build Coastguard Worker 
2139*61046927SAndroid Build Coastguard Worker         e.set_tex_dim(28..31, self.dim);
2140*61046927SAndroid Build Coastguard Worker         e.set_field(31..35, self.mask);
2141*61046927SAndroid Build Coastguard Worker         e.set_bit(35, false); // ToDo: NDV
2142*61046927SAndroid Build Coastguard Worker         e.set_bit(49, false); // TODO: .NODEP
2143*61046927SAndroid Build Coastguard Worker     }
2144*61046927SAndroid Build Coastguard Worker }
2145*61046927SAndroid Build Coastguard Worker 
2146*61046927SAndroid Build Coastguard Worker impl SM50Op for OpTxd {
legalize(&mut self, b: &mut LegalizeBuilder)2147*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2148*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2149*61046927SAndroid Build Coastguard Worker     }
2150*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2151*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2152*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xde78);
2153*61046927SAndroid Build Coastguard Worker 
2154*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dsts[0]);
2155*61046927SAndroid Build Coastguard Worker         assert!(self.dsts[1].is_none());
2156*61046927SAndroid Build Coastguard Worker         assert!(self.fault.is_none());
2157*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.srcs[0]);
2158*61046927SAndroid Build Coastguard Worker         e.set_reg_src(20..28, self.srcs[1]);
2159*61046927SAndroid Build Coastguard Worker 
2160*61046927SAndroid Build Coastguard Worker         e.set_tex_dim(28..31, self.dim);
2161*61046927SAndroid Build Coastguard Worker         e.set_field(31..35, self.mask);
2162*61046927SAndroid Build Coastguard Worker         e.set_bit(35, self.offset);
2163*61046927SAndroid Build Coastguard Worker         e.set_bit(49, false); // TODO: .NODEP
2164*61046927SAndroid Build Coastguard Worker     }
2165*61046927SAndroid Build Coastguard Worker }
2166*61046927SAndroid Build Coastguard Worker 
2167*61046927SAndroid Build Coastguard Worker impl SM50Op for OpTxq {
legalize(&mut self, b: &mut LegalizeBuilder)2168*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2169*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2170*61046927SAndroid Build Coastguard Worker     }
2171*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2172*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2173*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xdf50);
2174*61046927SAndroid Build Coastguard Worker 
2175*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dsts[0]);
2176*61046927SAndroid Build Coastguard Worker         assert!(self.dsts[1].is_none());
2177*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.src);
2178*61046927SAndroid Build Coastguard Worker 
2179*61046927SAndroid Build Coastguard Worker         e.set_field(
2180*61046927SAndroid Build Coastguard Worker             22..28,
2181*61046927SAndroid Build Coastguard Worker             match self.query {
2182*61046927SAndroid Build Coastguard Worker                 TexQuery::Dimension => 1_u8,
2183*61046927SAndroid Build Coastguard Worker                 TexQuery::TextureType => 2_u8,
2184*61046927SAndroid Build Coastguard Worker                 TexQuery::SamplerPos => 5_u8,
2185*61046927SAndroid Build Coastguard Worker                 // TexQuery::Filter => 0x10_u8,
2186*61046927SAndroid Build Coastguard Worker                 // TexQuery::Lod => 0x12_u8,
2187*61046927SAndroid Build Coastguard Worker                 // TexQuery::Wrap => 0x14_u8,
2188*61046927SAndroid Build Coastguard Worker                 // TexQuery::BorderColour => 0x16,
2189*61046927SAndroid Build Coastguard Worker             },
2190*61046927SAndroid Build Coastguard Worker         );
2191*61046927SAndroid Build Coastguard Worker         e.set_field(31..35, self.mask);
2192*61046927SAndroid Build Coastguard Worker         e.set_bit(49, false); // TODO: .NODEP
2193*61046927SAndroid Build Coastguard Worker     }
2194*61046927SAndroid Build Coastguard Worker }
2195*61046927SAndroid Build Coastguard Worker 
2196*61046927SAndroid Build Coastguard Worker impl SM50Encoder<'_> {
set_mem_type(&mut self, range: Range<usize>, mem_type: MemType)2197*61046927SAndroid Build Coastguard Worker     fn set_mem_type(&mut self, range: Range<usize>, mem_type: MemType) {
2198*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 3);
2199*61046927SAndroid Build Coastguard Worker         self.set_field(
2200*61046927SAndroid Build Coastguard Worker             range,
2201*61046927SAndroid Build Coastguard Worker             match mem_type {
2202*61046927SAndroid Build Coastguard Worker                 MemType::U8 => 0_u8,
2203*61046927SAndroid Build Coastguard Worker                 MemType::I8 => 1_u8,
2204*61046927SAndroid Build Coastguard Worker                 MemType::U16 => 2_u8,
2205*61046927SAndroid Build Coastguard Worker                 MemType::I16 => 3_u8,
2206*61046927SAndroid Build Coastguard Worker                 MemType::B32 => 4_u8,
2207*61046927SAndroid Build Coastguard Worker                 MemType::B64 => 5_u8,
2208*61046927SAndroid Build Coastguard Worker                 MemType::B128 => 6_u8,
2209*61046927SAndroid Build Coastguard Worker             },
2210*61046927SAndroid Build Coastguard Worker         );
2211*61046927SAndroid Build Coastguard Worker     }
2212*61046927SAndroid Build Coastguard Worker 
set_mem_order(&mut self, _order: &MemOrder)2213*61046927SAndroid Build Coastguard Worker     fn set_mem_order(&mut self, _order: &MemOrder) {
2214*61046927SAndroid Build Coastguard Worker         // TODO: order and scope aren't present before SM70, what should we do?
2215*61046927SAndroid Build Coastguard Worker     }
2216*61046927SAndroid Build Coastguard Worker 
set_mem_access(&mut self, access: &MemAccess)2217*61046927SAndroid Build Coastguard Worker     fn set_mem_access(&mut self, access: &MemAccess) {
2218*61046927SAndroid Build Coastguard Worker         self.set_field(
2219*61046927SAndroid Build Coastguard Worker             45..46,
2220*61046927SAndroid Build Coastguard Worker             match access.space.addr_type() {
2221*61046927SAndroid Build Coastguard Worker                 MemAddrType::A32 => 0_u8,
2222*61046927SAndroid Build Coastguard Worker                 MemAddrType::A64 => 1_u8,
2223*61046927SAndroid Build Coastguard Worker             },
2224*61046927SAndroid Build Coastguard Worker         );
2225*61046927SAndroid Build Coastguard Worker         self.set_mem_type(48..51, access.mem_type);
2226*61046927SAndroid Build Coastguard Worker         self.set_mem_order(&access.order);
2227*61046927SAndroid Build Coastguard Worker     }
2228*61046927SAndroid Build Coastguard Worker 
set_image_dim(&mut self, range: Range<usize>, dim: ImageDim)2229*61046927SAndroid Build Coastguard Worker     fn set_image_dim(&mut self, range: Range<usize>, dim: ImageDim) {
2230*61046927SAndroid Build Coastguard Worker         assert!(range.len() == 3);
2231*61046927SAndroid Build Coastguard Worker         self.set_field(
2232*61046927SAndroid Build Coastguard Worker             range,
2233*61046927SAndroid Build Coastguard Worker             match dim {
2234*61046927SAndroid Build Coastguard Worker                 ImageDim::_1D => 0_u8,
2235*61046927SAndroid Build Coastguard Worker                 ImageDim::_1DBuffer => 1_u8,
2236*61046927SAndroid Build Coastguard Worker                 ImageDim::_1DArray => 2_u8,
2237*61046927SAndroid Build Coastguard Worker                 ImageDim::_2D => 3_u8,
2238*61046927SAndroid Build Coastguard Worker                 ImageDim::_2DArray => 4_u8,
2239*61046927SAndroid Build Coastguard Worker                 ImageDim::_3D => 5_u8,
2240*61046927SAndroid Build Coastguard Worker             },
2241*61046927SAndroid Build Coastguard Worker         );
2242*61046927SAndroid Build Coastguard Worker     }
2243*61046927SAndroid Build Coastguard Worker }
2244*61046927SAndroid Build Coastguard Worker 
2245*61046927SAndroid Build Coastguard Worker impl SM50Op for OpSuLd {
legalize(&mut self, b: &mut LegalizeBuilder)2246*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2247*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2248*61046927SAndroid Build Coastguard Worker     }
2249*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2250*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2251*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xeb00);
2252*61046927SAndroid Build Coastguard Worker 
2253*61046927SAndroid Build Coastguard Worker         assert!(self.mask == 0x1 || self.mask == 0x3 || self.mask == 0xf);
2254*61046927SAndroid Build Coastguard Worker         e.set_field(20..24, self.mask);
2255*61046927SAndroid Build Coastguard Worker         e.set_image_dim(33..36, self.image_dim);
2256*61046927SAndroid Build Coastguard Worker 
2257*61046927SAndroid Build Coastguard Worker         // mem_eviction_policy not a thing for sm < 70
2258*61046927SAndroid Build Coastguard Worker 
2259*61046927SAndroid Build Coastguard Worker         let scope = match self.mem_order {
2260*61046927SAndroid Build Coastguard Worker             MemOrder::Constant => MemScope::System,
2261*61046927SAndroid Build Coastguard Worker             MemOrder::Weak => MemScope::CTA,
2262*61046927SAndroid Build Coastguard Worker             MemOrder::Strong(s) => s,
2263*61046927SAndroid Build Coastguard Worker         };
2264*61046927SAndroid Build Coastguard Worker 
2265*61046927SAndroid Build Coastguard Worker         e.set_field(
2266*61046927SAndroid Build Coastguard Worker             24..26,
2267*61046927SAndroid Build Coastguard Worker             match scope {
2268*61046927SAndroid Build Coastguard Worker                 MemScope::CTA => 0_u8,
2269*61046927SAndroid Build Coastguard Worker                 /* SM => 1_u8, */
2270*61046927SAndroid Build Coastguard Worker                 MemScope::GPU => 2_u8,
2271*61046927SAndroid Build Coastguard Worker                 MemScope::System => 3_u8,
2272*61046927SAndroid Build Coastguard Worker             },
2273*61046927SAndroid Build Coastguard Worker         );
2274*61046927SAndroid Build Coastguard Worker 
2275*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2276*61046927SAndroid Build Coastguard Worker 
2277*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.coord);
2278*61046927SAndroid Build Coastguard Worker         e.set_reg_src(39..47, self.handle);
2279*61046927SAndroid Build Coastguard Worker     }
2280*61046927SAndroid Build Coastguard Worker }
2281*61046927SAndroid Build Coastguard Worker 
2282*61046927SAndroid Build Coastguard Worker impl SM50Op for OpSuSt {
legalize(&mut self, b: &mut LegalizeBuilder)2283*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2284*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2285*61046927SAndroid Build Coastguard Worker     }
2286*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2287*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2288*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xeb20);
2289*61046927SAndroid Build Coastguard Worker 
2290*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.coord);
2291*61046927SAndroid Build Coastguard Worker         e.set_reg_src(0..8, self.data);
2292*61046927SAndroid Build Coastguard Worker         e.set_reg_src(39..47, self.handle);
2293*61046927SAndroid Build Coastguard Worker 
2294*61046927SAndroid Build Coastguard Worker         e.set_image_dim(33..36, self.image_dim);
2295*61046927SAndroid Build Coastguard Worker         e.set_mem_order(&self.mem_order);
2296*61046927SAndroid Build Coastguard Worker 
2297*61046927SAndroid Build Coastguard Worker         assert!(self.mask == 0x1 || self.mask == 0x3 || self.mask == 0xf);
2298*61046927SAndroid Build Coastguard Worker         e.set_field(20..24, self.mask);
2299*61046927SAndroid Build Coastguard Worker     }
2300*61046927SAndroid Build Coastguard Worker }
2301*61046927SAndroid Build Coastguard Worker 
2302*61046927SAndroid Build Coastguard Worker impl SM50Encoder<'_> {
set_atom_op(&mut self, range: Range<usize>, atom_op: AtomOp)2303*61046927SAndroid Build Coastguard Worker     fn set_atom_op(&mut self, range: Range<usize>, atom_op: AtomOp) {
2304*61046927SAndroid Build Coastguard Worker         self.set_field(
2305*61046927SAndroid Build Coastguard Worker             range,
2306*61046927SAndroid Build Coastguard Worker             match atom_op {
2307*61046927SAndroid Build Coastguard Worker                 AtomOp::Add => 0_u8,
2308*61046927SAndroid Build Coastguard Worker                 AtomOp::Min => 1_u8,
2309*61046927SAndroid Build Coastguard Worker                 AtomOp::Max => 2_u8,
2310*61046927SAndroid Build Coastguard Worker                 AtomOp::Inc => 3_u8,
2311*61046927SAndroid Build Coastguard Worker                 AtomOp::Dec => 4_u8,
2312*61046927SAndroid Build Coastguard Worker                 AtomOp::And => 5_u8,
2313*61046927SAndroid Build Coastguard Worker                 AtomOp::Or => 6_u8,
2314*61046927SAndroid Build Coastguard Worker                 AtomOp::Xor => 7_u8,
2315*61046927SAndroid Build Coastguard Worker                 AtomOp::Exch => 8_u8,
2316*61046927SAndroid Build Coastguard Worker                 AtomOp::CmpExch(_) => panic!("CmpExch is a separate opcode"),
2317*61046927SAndroid Build Coastguard Worker             },
2318*61046927SAndroid Build Coastguard Worker         );
2319*61046927SAndroid Build Coastguard Worker     }
2320*61046927SAndroid Build Coastguard Worker }
2321*61046927SAndroid Build Coastguard Worker 
2322*61046927SAndroid Build Coastguard Worker impl SM50Op for OpSuAtom {
legalize(&mut self, b: &mut LegalizeBuilder)2323*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2324*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2325*61046927SAndroid Build Coastguard Worker     }
2326*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2327*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2328*61046927SAndroid Build Coastguard Worker         if let AtomOp::CmpExch(cmp_src) = self.atom_op {
2329*61046927SAndroid Build Coastguard Worker             e.set_opcode(0xeac0);
2330*61046927SAndroid Build Coastguard Worker             assert!(cmp_src == AtomCmpSrc::Packed);
2331*61046927SAndroid Build Coastguard Worker         } else {
2332*61046927SAndroid Build Coastguard Worker             e.set_opcode(0xea60);
2333*61046927SAndroid Build Coastguard Worker             e.set_atom_op(29..33, self.atom_op);
2334*61046927SAndroid Build Coastguard Worker         }
2335*61046927SAndroid Build Coastguard Worker 
2336*61046927SAndroid Build Coastguard Worker         let atom_type: u8 = match self.atom_type {
2337*61046927SAndroid Build Coastguard Worker             AtomType::U32 => 0,
2338*61046927SAndroid Build Coastguard Worker             AtomType::I32 => 1,
2339*61046927SAndroid Build Coastguard Worker             AtomType::F32 => 3,
2340*61046927SAndroid Build Coastguard Worker             AtomType::U64 => 2,
2341*61046927SAndroid Build Coastguard Worker             AtomType::I64 => 5,
2342*61046927SAndroid Build Coastguard Worker             _ => panic!("Unsupported atom type {}", self.atom_type),
2343*61046927SAndroid Build Coastguard Worker         };
2344*61046927SAndroid Build Coastguard Worker 
2345*61046927SAndroid Build Coastguard Worker         e.set_image_dim(33..36, self.image_dim);
2346*61046927SAndroid Build Coastguard Worker         e.set_field(36..39, atom_type);
2347*61046927SAndroid Build Coastguard Worker 
2348*61046927SAndroid Build Coastguard Worker         // The hardware requires that we set .D on atomics.  This is safe to do
2349*61046927SAndroid Build Coastguard Worker         // in in the emit code because it only affects format conversion, not
2350*61046927SAndroid Build Coastguard Worker         // surface coordinates and atomics are required to be performed with
2351*61046927SAndroid Build Coastguard Worker         // image formats that that exactly match the shader data type.  So, for
2352*61046927SAndroid Build Coastguard Worker         // instance, a uint32_t atomic has to happen on an R32_UINT or R32_SINT
2353*61046927SAndroid Build Coastguard Worker         // image.
2354*61046927SAndroid Build Coastguard Worker         e.set_bit(52, true); // .D
2355*61046927SAndroid Build Coastguard Worker 
2356*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2357*61046927SAndroid Build Coastguard Worker 
2358*61046927SAndroid Build Coastguard Worker         e.set_reg_src(20..28, self.data);
2359*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.coord);
2360*61046927SAndroid Build Coastguard Worker         e.set_reg_src(39..47, self.handle);
2361*61046927SAndroid Build Coastguard Worker     }
2362*61046927SAndroid Build Coastguard Worker }
2363*61046927SAndroid Build Coastguard Worker 
2364*61046927SAndroid Build Coastguard Worker impl SM50Op for OpLd {
legalize(&mut self, b: &mut LegalizeBuilder)2365*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2366*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2367*61046927SAndroid Build Coastguard Worker     }
2368*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2369*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2370*61046927SAndroid Build Coastguard Worker         e.set_opcode(match self.access.space {
2371*61046927SAndroid Build Coastguard Worker             MemSpace::Global(_) => 0xeed0,
2372*61046927SAndroid Build Coastguard Worker             MemSpace::Local => 0xef40,
2373*61046927SAndroid Build Coastguard Worker             MemSpace::Shared => 0xef48,
2374*61046927SAndroid Build Coastguard Worker         });
2375*61046927SAndroid Build Coastguard Worker 
2376*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2377*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.addr);
2378*61046927SAndroid Build Coastguard Worker         e.set_field(20..44, self.offset);
2379*61046927SAndroid Build Coastguard Worker 
2380*61046927SAndroid Build Coastguard Worker         e.set_mem_access(&self.access);
2381*61046927SAndroid Build Coastguard Worker     }
2382*61046927SAndroid Build Coastguard Worker }
2383*61046927SAndroid Build Coastguard Worker 
2384*61046927SAndroid Build Coastguard Worker impl SM50Op for OpLdc {
legalize(&mut self, b: &mut LegalizeBuilder)2385*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2386*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
2387*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.offset, GPR, SrcType::GPR);
2388*61046927SAndroid Build Coastguard Worker     }
2389*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2390*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2391*61046927SAndroid Build Coastguard Worker         assert!(self.cb.src_mod.is_none());
2392*61046927SAndroid Build Coastguard Worker         let SrcRef::CBuf(cb) = &self.cb.src_ref else {
2393*61046927SAndroid Build Coastguard Worker             panic!("Not a CBuf source");
2394*61046927SAndroid Build Coastguard Worker         };
2395*61046927SAndroid Build Coastguard Worker         let CBuf::Binding(cb_idx) = cb.buf else {
2396*61046927SAndroid Build Coastguard Worker             panic!("Must be a bound constant buffer");
2397*61046927SAndroid Build Coastguard Worker         };
2398*61046927SAndroid Build Coastguard Worker 
2399*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xef90);
2400*61046927SAndroid Build Coastguard Worker 
2401*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2402*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.offset);
2403*61046927SAndroid Build Coastguard Worker         e.set_field(20..36, cb.offset);
2404*61046927SAndroid Build Coastguard Worker         e.set_field(36..41, cb_idx);
2405*61046927SAndroid Build Coastguard Worker         e.set_field(
2406*61046927SAndroid Build Coastguard Worker             44..46,
2407*61046927SAndroid Build Coastguard Worker             match self.mode {
2408*61046927SAndroid Build Coastguard Worker                 LdcMode::Indexed => 0_u8,
2409*61046927SAndroid Build Coastguard Worker                 LdcMode::IndexedLinear => 1_u8,
2410*61046927SAndroid Build Coastguard Worker                 LdcMode::IndexedSegmented => 2_u8,
2411*61046927SAndroid Build Coastguard Worker                 LdcMode::IndexedSegmentedLinear => 3_u8,
2412*61046927SAndroid Build Coastguard Worker             },
2413*61046927SAndroid Build Coastguard Worker         );
2414*61046927SAndroid Build Coastguard Worker         e.set_mem_type(48..51, self.mem_type);
2415*61046927SAndroid Build Coastguard Worker     }
2416*61046927SAndroid Build Coastguard Worker }
2417*61046927SAndroid Build Coastguard Worker 
2418*61046927SAndroid Build Coastguard Worker impl SM50Op for OpSt {
legalize(&mut self, b: &mut LegalizeBuilder)2419*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2420*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2421*61046927SAndroid Build Coastguard Worker     }
2422*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2423*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2424*61046927SAndroid Build Coastguard Worker         e.set_opcode(match self.access.space {
2425*61046927SAndroid Build Coastguard Worker             MemSpace::Global(_) => 0xeed8,
2426*61046927SAndroid Build Coastguard Worker             MemSpace::Local => 0xef50,
2427*61046927SAndroid Build Coastguard Worker             MemSpace::Shared => 0xef58,
2428*61046927SAndroid Build Coastguard Worker         });
2429*61046927SAndroid Build Coastguard Worker 
2430*61046927SAndroid Build Coastguard Worker         e.set_reg_src(0..8, self.data);
2431*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.addr);
2432*61046927SAndroid Build Coastguard Worker         e.set_field(20..44, self.offset);
2433*61046927SAndroid Build Coastguard Worker         e.set_mem_access(&self.access);
2434*61046927SAndroid Build Coastguard Worker     }
2435*61046927SAndroid Build Coastguard Worker }
2436*61046927SAndroid Build Coastguard Worker 
atom_src_as_ssa( b: &mut LegalizeBuilder, src: Src, atom_type: AtomType, ) -> SSARef2437*61046927SAndroid Build Coastguard Worker fn atom_src_as_ssa(
2438*61046927SAndroid Build Coastguard Worker     b: &mut LegalizeBuilder,
2439*61046927SAndroid Build Coastguard Worker     src: Src,
2440*61046927SAndroid Build Coastguard Worker     atom_type: AtomType,
2441*61046927SAndroid Build Coastguard Worker ) -> SSARef {
2442*61046927SAndroid Build Coastguard Worker     if let Some(ssa) = src.as_ssa() {
2443*61046927SAndroid Build Coastguard Worker         return *ssa;
2444*61046927SAndroid Build Coastguard Worker     }
2445*61046927SAndroid Build Coastguard Worker 
2446*61046927SAndroid Build Coastguard Worker     let tmp;
2447*61046927SAndroid Build Coastguard Worker     if atom_type.bits() == 32 {
2448*61046927SAndroid Build Coastguard Worker         tmp = b.alloc_ssa(RegFile::GPR, 1);
2449*61046927SAndroid Build Coastguard Worker         b.copy_to(tmp.into(), 0.into());
2450*61046927SAndroid Build Coastguard Worker     } else {
2451*61046927SAndroid Build Coastguard Worker         debug_assert!(atom_type.bits() == 64);
2452*61046927SAndroid Build Coastguard Worker         tmp = b.alloc_ssa(RegFile::GPR, 2);
2453*61046927SAndroid Build Coastguard Worker         b.copy_to(tmp[0].into(), 0.into());
2454*61046927SAndroid Build Coastguard Worker         b.copy_to(tmp[1].into(), 0.into());
2455*61046927SAndroid Build Coastguard Worker     }
2456*61046927SAndroid Build Coastguard Worker     tmp
2457*61046927SAndroid Build Coastguard Worker }
2458*61046927SAndroid Build Coastguard Worker 
2459*61046927SAndroid Build Coastguard Worker impl SM50Op for OpAtom {
legalize(&mut self, b: &mut LegalizeBuilder)2460*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2461*61046927SAndroid Build Coastguard Worker         if self.atom_op == AtomOp::CmpExch(AtomCmpSrc::Separate) {
2462*61046927SAndroid Build Coastguard Worker             let cmpr = atom_src_as_ssa(b, self.cmpr, self.atom_type);
2463*61046927SAndroid Build Coastguard Worker             let data = atom_src_as_ssa(b, self.data, self.atom_type);
2464*61046927SAndroid Build Coastguard Worker 
2465*61046927SAndroid Build Coastguard Worker             let mut cmpr_data = Vec::new();
2466*61046927SAndroid Build Coastguard Worker             cmpr_data.extend_from_slice(&cmpr);
2467*61046927SAndroid Build Coastguard Worker             cmpr_data.extend_from_slice(&data);
2468*61046927SAndroid Build Coastguard Worker             let cmpr_data = SSARef::try_from(cmpr_data).unwrap();
2469*61046927SAndroid Build Coastguard Worker 
2470*61046927SAndroid Build Coastguard Worker             self.cmpr = 0.into();
2471*61046927SAndroid Build Coastguard Worker             self.data = cmpr_data.into();
2472*61046927SAndroid Build Coastguard Worker             self.atom_op = AtomOp::CmpExch(AtomCmpSrc::Packed);
2473*61046927SAndroid Build Coastguard Worker         }
2474*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2475*61046927SAndroid Build Coastguard Worker     }
2476*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2477*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2478*61046927SAndroid Build Coastguard Worker         match self.mem_space {
2479*61046927SAndroid Build Coastguard Worker             MemSpace::Global(addr_type) => {
2480*61046927SAndroid Build Coastguard Worker                 if self.dst.is_none() {
2481*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0xebf8);
2482*61046927SAndroid Build Coastguard Worker 
2483*61046927SAndroid Build Coastguard Worker                     e.set_reg_src(0..8, self.data);
2484*61046927SAndroid Build Coastguard Worker 
2485*61046927SAndroid Build Coastguard Worker                     let data_type = match self.atom_type {
2486*61046927SAndroid Build Coastguard Worker                         AtomType::U32 => 0_u8,
2487*61046927SAndroid Build Coastguard Worker                         AtomType::I32 => 1_u8,
2488*61046927SAndroid Build Coastguard Worker                         AtomType::U64 => 2_u8,
2489*61046927SAndroid Build Coastguard Worker                         AtomType::F32 => 3_u8,
2490*61046927SAndroid Build Coastguard Worker                         // NOTE: U128 => 4_u8,
2491*61046927SAndroid Build Coastguard Worker                         AtomType::I64 => 5_u8,
2492*61046927SAndroid Build Coastguard Worker                         _ => panic!("Unsupported data type"),
2493*61046927SAndroid Build Coastguard Worker                     };
2494*61046927SAndroid Build Coastguard Worker                     e.set_field(20..23, data_type);
2495*61046927SAndroid Build Coastguard Worker                     e.set_atom_op(23..26, self.atom_op);
2496*61046927SAndroid Build Coastguard Worker                 } else if let AtomOp::CmpExch(cmp_src) = self.atom_op {
2497*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0xee00);
2498*61046927SAndroid Build Coastguard Worker 
2499*61046927SAndroid Build Coastguard Worker                     e.set_dst(self.dst);
2500*61046927SAndroid Build Coastguard Worker 
2501*61046927SAndroid Build Coastguard Worker                     // TODO: These are all supported by the disassembler but
2502*61046927SAndroid Build Coastguard Worker                     // only the packed layout appears to be supported by real
2503*61046927SAndroid Build Coastguard Worker                     // hardware
2504*61046927SAndroid Build Coastguard Worker                     let (data_src, data_layout) = match cmp_src {
2505*61046927SAndroid Build Coastguard Worker                         AtomCmpSrc::Separate => {
2506*61046927SAndroid Build Coastguard Worker                             if self.data.is_zero() {
2507*61046927SAndroid Build Coastguard Worker                                 (self.cmpr, 1_u8)
2508*61046927SAndroid Build Coastguard Worker                             } else {
2509*61046927SAndroid Build Coastguard Worker                                 assert!(self.cmpr.is_zero());
2510*61046927SAndroid Build Coastguard Worker                                 (self.data, 2_u8)
2511*61046927SAndroid Build Coastguard Worker                             }
2512*61046927SAndroid Build Coastguard Worker                         }
2513*61046927SAndroid Build Coastguard Worker                         AtomCmpSrc::Packed => (self.data, 0_u8),
2514*61046927SAndroid Build Coastguard Worker                     };
2515*61046927SAndroid Build Coastguard Worker                     e.set_reg_src(20..28, data_src);
2516*61046927SAndroid Build Coastguard Worker 
2517*61046927SAndroid Build Coastguard Worker                     let data_type = match self.atom_type {
2518*61046927SAndroid Build Coastguard Worker                         AtomType::U32 => 0_u8,
2519*61046927SAndroid Build Coastguard Worker                         AtomType::U64 => 1_u8,
2520*61046927SAndroid Build Coastguard Worker                         _ => panic!("Unsupported data type"),
2521*61046927SAndroid Build Coastguard Worker                     };
2522*61046927SAndroid Build Coastguard Worker                     e.set_field(49..50, data_type);
2523*61046927SAndroid Build Coastguard Worker                     e.set_field(50..52, data_layout);
2524*61046927SAndroid Build Coastguard Worker                     e.set_field(52..56, 15_u8); // subOp
2525*61046927SAndroid Build Coastguard Worker                 } else {
2526*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0xed00);
2527*61046927SAndroid Build Coastguard Worker 
2528*61046927SAndroid Build Coastguard Worker                     e.set_dst(self.dst);
2529*61046927SAndroid Build Coastguard Worker                     e.set_reg_src(20..28, self.data);
2530*61046927SAndroid Build Coastguard Worker 
2531*61046927SAndroid Build Coastguard Worker                     let data_type = match self.atom_type {
2532*61046927SAndroid Build Coastguard Worker                         AtomType::U32 => 0_u8,
2533*61046927SAndroid Build Coastguard Worker                         AtomType::I32 => 1_u8,
2534*61046927SAndroid Build Coastguard Worker                         AtomType::U64 => 2_u8,
2535*61046927SAndroid Build Coastguard Worker                         AtomType::F32 => 3_u8,
2536*61046927SAndroid Build Coastguard Worker                         // NOTE: U128 => 4_u8,
2537*61046927SAndroid Build Coastguard Worker                         AtomType::I64 => 5_u8,
2538*61046927SAndroid Build Coastguard Worker                         _ => panic!("Unsupported data type"),
2539*61046927SAndroid Build Coastguard Worker                     };
2540*61046927SAndroid Build Coastguard Worker                     e.set_field(49..52, data_type);
2541*61046927SAndroid Build Coastguard Worker                     e.set_atom_op(52..56, self.atom_op);
2542*61046927SAndroid Build Coastguard Worker                 }
2543*61046927SAndroid Build Coastguard Worker 
2544*61046927SAndroid Build Coastguard Worker                 e.set_mem_order(&self.mem_order);
2545*61046927SAndroid Build Coastguard Worker 
2546*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(8..16, self.addr);
2547*61046927SAndroid Build Coastguard Worker                 e.set_field(28..48, self.addr_offset);
2548*61046927SAndroid Build Coastguard Worker                 e.set_field(
2549*61046927SAndroid Build Coastguard Worker                     48..49,
2550*61046927SAndroid Build Coastguard Worker                     match addr_type {
2551*61046927SAndroid Build Coastguard Worker                         MemAddrType::A32 => 0_u8,
2552*61046927SAndroid Build Coastguard Worker                         MemAddrType::A64 => 1_u8,
2553*61046927SAndroid Build Coastguard Worker                     },
2554*61046927SAndroid Build Coastguard Worker                 );
2555*61046927SAndroid Build Coastguard Worker             }
2556*61046927SAndroid Build Coastguard Worker             MemSpace::Local => panic!("Atomics do not support local"),
2557*61046927SAndroid Build Coastguard Worker             MemSpace::Shared => {
2558*61046927SAndroid Build Coastguard Worker                 if let AtomOp::CmpExch(cmp_src) = self.atom_op {
2559*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0xee00);
2560*61046927SAndroid Build Coastguard Worker 
2561*61046927SAndroid Build Coastguard Worker                     assert!(cmp_src == AtomCmpSrc::Packed);
2562*61046927SAndroid Build Coastguard Worker                     assert!(self.cmpr.is_zero());
2563*61046927SAndroid Build Coastguard Worker                     e.set_reg_src(20..28, self.data);
2564*61046927SAndroid Build Coastguard Worker 
2565*61046927SAndroid Build Coastguard Worker                     let subop = match self.atom_type {
2566*61046927SAndroid Build Coastguard Worker                         AtomType::U32 => 4_u8,
2567*61046927SAndroid Build Coastguard Worker                         AtomType::U64 => 5_u8,
2568*61046927SAndroid Build Coastguard Worker                         _ => panic!("Unsupported data type"),
2569*61046927SAndroid Build Coastguard Worker                     };
2570*61046927SAndroid Build Coastguard Worker                     e.set_field(52..56, subop);
2571*61046927SAndroid Build Coastguard Worker                 } else {
2572*61046927SAndroid Build Coastguard Worker                     e.set_opcode(0xec00);
2573*61046927SAndroid Build Coastguard Worker 
2574*61046927SAndroid Build Coastguard Worker                     e.set_reg_src(20..28, self.data);
2575*61046927SAndroid Build Coastguard Worker 
2576*61046927SAndroid Build Coastguard Worker                     let data_type = match self.atom_type {
2577*61046927SAndroid Build Coastguard Worker                         AtomType::U32 => 0_u8,
2578*61046927SAndroid Build Coastguard Worker                         AtomType::I32 => 1_u8,
2579*61046927SAndroid Build Coastguard Worker                         AtomType::U64 => 2_u8,
2580*61046927SAndroid Build Coastguard Worker                         AtomType::I64 => 3_u8,
2581*61046927SAndroid Build Coastguard Worker                         _ => panic!("Unsupported data type"),
2582*61046927SAndroid Build Coastguard Worker                     };
2583*61046927SAndroid Build Coastguard Worker                     e.set_field(28..30, data_type);
2584*61046927SAndroid Build Coastguard Worker                     e.set_atom_op(52..56, self.atom_op);
2585*61046927SAndroid Build Coastguard Worker                 }
2586*61046927SAndroid Build Coastguard Worker 
2587*61046927SAndroid Build Coastguard Worker                 e.set_dst(self.dst);
2588*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(8..16, self.addr);
2589*61046927SAndroid Build Coastguard Worker                 assert_eq!(self.addr_offset % 4, 0);
2590*61046927SAndroid Build Coastguard Worker                 e.set_field(30..52, self.addr_offset / 4);
2591*61046927SAndroid Build Coastguard Worker             }
2592*61046927SAndroid Build Coastguard Worker         }
2593*61046927SAndroid Build Coastguard Worker     }
2594*61046927SAndroid Build Coastguard Worker }
2595*61046927SAndroid Build Coastguard Worker 
2596*61046927SAndroid Build Coastguard Worker impl SM50Op for OpAL2P {
legalize(&mut self, b: &mut LegalizeBuilder)2597*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2598*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2599*61046927SAndroid Build Coastguard Worker     }
2600*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2601*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2602*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xefa0);
2603*61046927SAndroid Build Coastguard Worker 
2604*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2605*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.offset);
2606*61046927SAndroid Build Coastguard Worker 
2607*61046927SAndroid Build Coastguard Worker         e.set_field(20..31, self.access.addr);
2608*61046927SAndroid Build Coastguard Worker         assert!(!self.access.patch);
2609*61046927SAndroid Build Coastguard Worker         e.set_bit(32, self.access.output);
2610*61046927SAndroid Build Coastguard Worker 
2611*61046927SAndroid Build Coastguard Worker         e.set_field(47..49, 0_u8); // comps
2612*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(44..47, Dst::None);
2613*61046927SAndroid Build Coastguard Worker     }
2614*61046927SAndroid Build Coastguard Worker }
2615*61046927SAndroid Build Coastguard Worker 
2616*61046927SAndroid Build Coastguard Worker impl SM50Op for OpALd {
legalize(&mut self, b: &mut LegalizeBuilder)2617*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2618*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2619*61046927SAndroid Build Coastguard Worker     }
2620*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2621*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2622*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xefd8);
2623*61046927SAndroid Build Coastguard Worker 
2624*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2625*61046927SAndroid Build Coastguard Worker         if self.access.phys {
2626*61046927SAndroid Build Coastguard Worker             assert!(!self.access.patch);
2627*61046927SAndroid Build Coastguard Worker             assert!(self.offset.src_ref.as_reg().is_some());
2628*61046927SAndroid Build Coastguard Worker         } else if !self.access.patch {
2629*61046927SAndroid Build Coastguard Worker             assert!(self.offset.is_zero());
2630*61046927SAndroid Build Coastguard Worker         }
2631*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.offset);
2632*61046927SAndroid Build Coastguard Worker         e.set_reg_src(39..47, self.vtx);
2633*61046927SAndroid Build Coastguard Worker 
2634*61046927SAndroid Build Coastguard Worker         e.set_field(20..30, self.access.addr);
2635*61046927SAndroid Build Coastguard Worker         e.set_bit(31, self.access.patch);
2636*61046927SAndroid Build Coastguard Worker         e.set_bit(32, self.access.output);
2637*61046927SAndroid Build Coastguard Worker         e.set_field(47..49, self.access.comps - 1);
2638*61046927SAndroid Build Coastguard Worker     }
2639*61046927SAndroid Build Coastguard Worker }
2640*61046927SAndroid Build Coastguard Worker 
2641*61046927SAndroid Build Coastguard Worker impl SM50Op for OpASt {
legalize(&mut self, b: &mut LegalizeBuilder)2642*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2643*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2644*61046927SAndroid Build Coastguard Worker     }
2645*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2646*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2647*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xeff0);
2648*61046927SAndroid Build Coastguard Worker 
2649*61046927SAndroid Build Coastguard Worker         e.set_reg_src(0..8, self.data);
2650*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.offset);
2651*61046927SAndroid Build Coastguard Worker         e.set_reg_src(39..47, self.vtx);
2652*61046927SAndroid Build Coastguard Worker 
2653*61046927SAndroid Build Coastguard Worker         assert!(!self.access.phys);
2654*61046927SAndroid Build Coastguard Worker         assert!(self.access.output);
2655*61046927SAndroid Build Coastguard Worker         e.set_field(20..30, self.access.addr);
2656*61046927SAndroid Build Coastguard Worker         e.set_bit(31, self.access.patch);
2657*61046927SAndroid Build Coastguard Worker         e.set_bit(32, self.access.output);
2658*61046927SAndroid Build Coastguard Worker         e.set_field(47..49, self.access.comps - 1);
2659*61046927SAndroid Build Coastguard Worker     }
2660*61046927SAndroid Build Coastguard Worker }
2661*61046927SAndroid Build Coastguard Worker 
2662*61046927SAndroid Build Coastguard Worker impl SM50Op for OpIpa {
legalize(&mut self, b: &mut LegalizeBuilder)2663*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2664*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2665*61046927SAndroid Build Coastguard Worker     }
2666*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2667*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2668*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xe000);
2669*61046927SAndroid Build Coastguard Worker 
2670*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2671*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, 0.into()); // addr
2672*61046927SAndroid Build Coastguard Worker         e.set_reg_src(20..28, self.inv_w);
2673*61046927SAndroid Build Coastguard Worker         e.set_reg_src(39..47, self.offset);
2674*61046927SAndroid Build Coastguard Worker 
2675*61046927SAndroid Build Coastguard Worker         assert!(self.addr % 4 == 0);
2676*61046927SAndroid Build Coastguard Worker         e.set_field(28..38, self.addr);
2677*61046927SAndroid Build Coastguard Worker         e.set_bit(38, false); // .IDX
2678*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(47..50, Dst::None); // TODO: What is this for?
2679*61046927SAndroid Build Coastguard Worker         e.set_bit(51, false); // .SAT
2680*61046927SAndroid Build Coastguard Worker         e.set_field(
2681*61046927SAndroid Build Coastguard Worker             52..54,
2682*61046927SAndroid Build Coastguard Worker             match self.loc {
2683*61046927SAndroid Build Coastguard Worker                 InterpLoc::Default => 0_u8,
2684*61046927SAndroid Build Coastguard Worker                 InterpLoc::Centroid => 1_u8,
2685*61046927SAndroid Build Coastguard Worker                 InterpLoc::Offset => 2_u8,
2686*61046927SAndroid Build Coastguard Worker             },
2687*61046927SAndroid Build Coastguard Worker         );
2688*61046927SAndroid Build Coastguard Worker         e.set_field(
2689*61046927SAndroid Build Coastguard Worker             54..56,
2690*61046927SAndroid Build Coastguard Worker             match self.freq {
2691*61046927SAndroid Build Coastguard Worker                 InterpFreq::Pass => 0_u8,
2692*61046927SAndroid Build Coastguard Worker                 InterpFreq::PassMulW => 1_u8,
2693*61046927SAndroid Build Coastguard Worker                 InterpFreq::Constant => 2_u8,
2694*61046927SAndroid Build Coastguard Worker                 InterpFreq::State => 3_u8,
2695*61046927SAndroid Build Coastguard Worker             },
2696*61046927SAndroid Build Coastguard Worker         );
2697*61046927SAndroid Build Coastguard Worker     }
2698*61046927SAndroid Build Coastguard Worker }
2699*61046927SAndroid Build Coastguard Worker 
2700*61046927SAndroid Build Coastguard Worker impl SM50Op for OpCCtl {
legalize(&mut self, b: &mut LegalizeBuilder)2701*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
2702*61046927SAndroid Build Coastguard Worker         legalize_ext_instr(self, b);
2703*61046927SAndroid Build Coastguard Worker     }
2704*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2705*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2706*61046927SAndroid Build Coastguard Worker         match self.mem_space {
2707*61046927SAndroid Build Coastguard Worker             MemSpace::Global(addr_type) => {
2708*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0xef60);
2709*61046927SAndroid Build Coastguard Worker 
2710*61046927SAndroid Build Coastguard Worker                 assert!(self.addr_offset % 4 == 0);
2711*61046927SAndroid Build Coastguard Worker                 e.set_field(22..52, self.addr_offset / 4);
2712*61046927SAndroid Build Coastguard Worker                 e.set_field(
2713*61046927SAndroid Build Coastguard Worker                     52..53,
2714*61046927SAndroid Build Coastguard Worker                     match addr_type {
2715*61046927SAndroid Build Coastguard Worker                         MemAddrType::A32 => 0_u8,
2716*61046927SAndroid Build Coastguard Worker                         MemAddrType::A64 => 1_u8,
2717*61046927SAndroid Build Coastguard Worker                     },
2718*61046927SAndroid Build Coastguard Worker                 );
2719*61046927SAndroid Build Coastguard Worker             }
2720*61046927SAndroid Build Coastguard Worker             MemSpace::Local => panic!("cctl does not support local"),
2721*61046927SAndroid Build Coastguard Worker             MemSpace::Shared => {
2722*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0xef80);
2723*61046927SAndroid Build Coastguard Worker 
2724*61046927SAndroid Build Coastguard Worker                 assert!(self.addr_offset % 4 == 0);
2725*61046927SAndroid Build Coastguard Worker                 e.set_field(22..44, self.addr_offset / 4);
2726*61046927SAndroid Build Coastguard Worker             }
2727*61046927SAndroid Build Coastguard Worker         }
2728*61046927SAndroid Build Coastguard Worker 
2729*61046927SAndroid Build Coastguard Worker         e.set_field(
2730*61046927SAndroid Build Coastguard Worker             0..4,
2731*61046927SAndroid Build Coastguard Worker             match self.op {
2732*61046927SAndroid Build Coastguard Worker                 CCtlOp::Qry1 => 0_u8,
2733*61046927SAndroid Build Coastguard Worker                 CCtlOp::PF1 => 1_u8,
2734*61046927SAndroid Build Coastguard Worker                 CCtlOp::PF1_5 => 2_u8,
2735*61046927SAndroid Build Coastguard Worker                 CCtlOp::PF2 => 3_u8,
2736*61046927SAndroid Build Coastguard Worker                 CCtlOp::WB => 4_u8,
2737*61046927SAndroid Build Coastguard Worker                 CCtlOp::IV => 5_u8,
2738*61046927SAndroid Build Coastguard Worker                 CCtlOp::IVAll => 6_u8,
2739*61046927SAndroid Build Coastguard Worker                 CCtlOp::RS => 7_u8,
2740*61046927SAndroid Build Coastguard Worker                 CCtlOp::RSLB => 7_u8,
2741*61046927SAndroid Build Coastguard Worker                 op => panic!("Unsupported cache control {op:?}"),
2742*61046927SAndroid Build Coastguard Worker             },
2743*61046927SAndroid Build Coastguard Worker         );
2744*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.addr);
2745*61046927SAndroid Build Coastguard Worker     }
2746*61046927SAndroid Build Coastguard Worker }
2747*61046927SAndroid Build Coastguard Worker 
2748*61046927SAndroid Build Coastguard Worker impl SM50Op for OpMemBar {
legalize(&mut self, _b: &mut LegalizeBuilder)2749*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2750*61046927SAndroid Build Coastguard Worker         // Nothing to do
2751*61046927SAndroid Build Coastguard Worker     }
2752*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2753*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2754*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xef98);
2755*61046927SAndroid Build Coastguard Worker 
2756*61046927SAndroid Build Coastguard Worker         e.set_field(
2757*61046927SAndroid Build Coastguard Worker             8..10,
2758*61046927SAndroid Build Coastguard Worker             match self.scope {
2759*61046927SAndroid Build Coastguard Worker                 MemScope::CTA => 0_u8,
2760*61046927SAndroid Build Coastguard Worker                 MemScope::GPU => 1_u8,
2761*61046927SAndroid Build Coastguard Worker                 MemScope::System => 2_u8,
2762*61046927SAndroid Build Coastguard Worker             },
2763*61046927SAndroid Build Coastguard Worker         );
2764*61046927SAndroid Build Coastguard Worker     }
2765*61046927SAndroid Build Coastguard Worker }
2766*61046927SAndroid Build Coastguard Worker 
2767*61046927SAndroid Build Coastguard Worker impl SM50Encoder<'_> {
set_rel_offset(&mut self, range: Range<usize>, label: &Label)2768*61046927SAndroid Build Coastguard Worker     fn set_rel_offset(&mut self, range: Range<usize>, label: &Label) {
2769*61046927SAndroid Build Coastguard Worker         let ip = u32::try_from(self.ip).unwrap();
2770*61046927SAndroid Build Coastguard Worker         let ip = i32::try_from(ip).unwrap();
2771*61046927SAndroid Build Coastguard Worker 
2772*61046927SAndroid Build Coastguard Worker         let target_ip = *self.labels.get(label).unwrap();
2773*61046927SAndroid Build Coastguard Worker         let target_ip = u32::try_from(target_ip).unwrap();
2774*61046927SAndroid Build Coastguard Worker         let target_ip = i32::try_from(target_ip).unwrap();
2775*61046927SAndroid Build Coastguard Worker 
2776*61046927SAndroid Build Coastguard Worker         let rel_offset = target_ip - ip - 8;
2777*61046927SAndroid Build Coastguard Worker 
2778*61046927SAndroid Build Coastguard Worker         self.set_field(range, rel_offset);
2779*61046927SAndroid Build Coastguard Worker     }
2780*61046927SAndroid Build Coastguard Worker }
2781*61046927SAndroid Build Coastguard Worker 
2782*61046927SAndroid Build Coastguard Worker impl SM50Op for OpBra {
legalize(&mut self, _b: &mut LegalizeBuilder)2783*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2784*61046927SAndroid Build Coastguard Worker         // Nothing to do
2785*61046927SAndroid Build Coastguard Worker     }
2786*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2787*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2788*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xe240);
2789*61046927SAndroid Build Coastguard Worker         e.set_rel_offset(20..44, &self.target);
2790*61046927SAndroid Build Coastguard Worker         e.set_field(0..5, 0xF_u8); // TODO: Pred?
2791*61046927SAndroid Build Coastguard Worker     }
2792*61046927SAndroid Build Coastguard Worker }
2793*61046927SAndroid Build Coastguard Worker 
2794*61046927SAndroid Build Coastguard Worker impl SM50Op for OpSSy {
legalize(&mut self, _b: &mut LegalizeBuilder)2795*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2796*61046927SAndroid Build Coastguard Worker         // Nothing to do
2797*61046927SAndroid Build Coastguard Worker     }
2798*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2799*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2800*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xe290);
2801*61046927SAndroid Build Coastguard Worker         e.set_rel_offset(20..44, &self.target);
2802*61046927SAndroid Build Coastguard Worker         e.set_field(0..5, 0xF_u8); // TODO: Pred?
2803*61046927SAndroid Build Coastguard Worker     }
2804*61046927SAndroid Build Coastguard Worker }
2805*61046927SAndroid Build Coastguard Worker 
2806*61046927SAndroid Build Coastguard Worker impl SM50Op for OpSync {
legalize(&mut self, _b: &mut LegalizeBuilder)2807*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2808*61046927SAndroid Build Coastguard Worker         // Nothing to do
2809*61046927SAndroid Build Coastguard Worker     }
2810*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2811*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2812*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xf0f8);
2813*61046927SAndroid Build Coastguard Worker         e.set_field(0..5, 0xF_u8); // TODO: Pred?
2814*61046927SAndroid Build Coastguard Worker     }
2815*61046927SAndroid Build Coastguard Worker }
2816*61046927SAndroid Build Coastguard Worker 
2817*61046927SAndroid Build Coastguard Worker impl SM50Op for OpBrk {
legalize(&mut self, _b: &mut LegalizeBuilder)2818*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2819*61046927SAndroid Build Coastguard Worker         // Nothing to do
2820*61046927SAndroid Build Coastguard Worker     }
2821*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2822*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2823*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xe340);
2824*61046927SAndroid Build Coastguard Worker         e.set_field(0..5, 0xF_u8); // TODO: Pred?
2825*61046927SAndroid Build Coastguard Worker     }
2826*61046927SAndroid Build Coastguard Worker }
2827*61046927SAndroid Build Coastguard Worker 
2828*61046927SAndroid Build Coastguard Worker impl SM50Op for OpPBk {
legalize(&mut self, _b: &mut LegalizeBuilder)2829*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2830*61046927SAndroid Build Coastguard Worker         // Nothing to do
2831*61046927SAndroid Build Coastguard Worker     }
2832*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2833*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2834*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xe2a0);
2835*61046927SAndroid Build Coastguard Worker         e.set_rel_offset(20..44, &self.target);
2836*61046927SAndroid Build Coastguard Worker         e.set_field(0..5, 0xF_u8); // TODO: Pred?
2837*61046927SAndroid Build Coastguard Worker     }
2838*61046927SAndroid Build Coastguard Worker }
2839*61046927SAndroid Build Coastguard Worker 
2840*61046927SAndroid Build Coastguard Worker impl SM50Op for OpCont {
legalize(&mut self, _b: &mut LegalizeBuilder)2841*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2842*61046927SAndroid Build Coastguard Worker         // Nothing to do
2843*61046927SAndroid Build Coastguard Worker     }
2844*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2845*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2846*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xe350);
2847*61046927SAndroid Build Coastguard Worker         e.set_field(0..5, 0xF_u8); // TODO: Pred?
2848*61046927SAndroid Build Coastguard Worker     }
2849*61046927SAndroid Build Coastguard Worker }
2850*61046927SAndroid Build Coastguard Worker 
2851*61046927SAndroid Build Coastguard Worker impl SM50Op for OpPCnt {
legalize(&mut self, _b: &mut LegalizeBuilder)2852*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2853*61046927SAndroid Build Coastguard Worker         // Nothing to do
2854*61046927SAndroid Build Coastguard Worker     }
2855*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2856*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2857*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xe2b0);
2858*61046927SAndroid Build Coastguard Worker         e.set_rel_offset(20..44, &self.target);
2859*61046927SAndroid Build Coastguard Worker         e.set_field(0..5, 0xF_u8); // TODO: Pred?
2860*61046927SAndroid Build Coastguard Worker     }
2861*61046927SAndroid Build Coastguard Worker }
2862*61046927SAndroid Build Coastguard Worker 
2863*61046927SAndroid Build Coastguard Worker impl SM50Op for OpExit {
legalize(&mut self, _b: &mut LegalizeBuilder)2864*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2865*61046927SAndroid Build Coastguard Worker         // Nothing to do
2866*61046927SAndroid Build Coastguard Worker     }
2867*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2868*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2869*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xe300);
2870*61046927SAndroid Build Coastguard Worker 
2871*61046927SAndroid Build Coastguard Worker         // TODO: CC flags
2872*61046927SAndroid Build Coastguard Worker         e.set_field(0..4, 0xf_u8); // CC.T
2873*61046927SAndroid Build Coastguard Worker     }
2874*61046927SAndroid Build Coastguard Worker }
2875*61046927SAndroid Build Coastguard Worker 
2876*61046927SAndroid Build Coastguard Worker impl SM50Op for OpBar {
legalize(&mut self, _b: &mut LegalizeBuilder)2877*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2878*61046927SAndroid Build Coastguard Worker         // Nothing to do
2879*61046927SAndroid Build Coastguard Worker     }
2880*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2881*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2882*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xf0a8);
2883*61046927SAndroid Build Coastguard Worker 
2884*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, SrcRef::Zero.into());
2885*61046927SAndroid Build Coastguard Worker 
2886*61046927SAndroid Build Coastguard Worker         // 00: RED.POPC
2887*61046927SAndroid Build Coastguard Worker         // 01: RED.AND
2888*61046927SAndroid Build Coastguard Worker         // 02: RED.OR
2889*61046927SAndroid Build Coastguard Worker         e.set_field(35..37, 0_u8);
2890*61046927SAndroid Build Coastguard Worker 
2891*61046927SAndroid Build Coastguard Worker         // 00: SYNC
2892*61046927SAndroid Build Coastguard Worker         // 01: ARV
2893*61046927SAndroid Build Coastguard Worker         // 02: RED
2894*61046927SAndroid Build Coastguard Worker         // 03: SCAN
2895*61046927SAndroid Build Coastguard Worker         e.set_field(32..35, 0_u8);
2896*61046927SAndroid Build Coastguard Worker 
2897*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, SrcRef::True.into());
2898*61046927SAndroid Build Coastguard Worker     }
2899*61046927SAndroid Build Coastguard Worker }
2900*61046927SAndroid Build Coastguard Worker 
2901*61046927SAndroid Build Coastguard Worker impl SM50Op for OpCS2R {
legalize(&mut self, _b: &mut LegalizeBuilder)2902*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2903*61046927SAndroid Build Coastguard Worker         // Nothing to do
2904*61046927SAndroid Build Coastguard Worker     }
2905*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2906*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2907*61046927SAndroid Build Coastguard Worker         e.set_opcode(0x50c8);
2908*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2909*61046927SAndroid Build Coastguard Worker         e.set_field(20..28, self.idx);
2910*61046927SAndroid Build Coastguard Worker     }
2911*61046927SAndroid Build Coastguard Worker }
2912*61046927SAndroid Build Coastguard Worker 
2913*61046927SAndroid Build Coastguard Worker impl SM50Op for OpIsberd {
legalize(&mut self, _b: &mut LegalizeBuilder)2914*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2915*61046927SAndroid Build Coastguard Worker         // Nothing to do
2916*61046927SAndroid Build Coastguard Worker     }
2917*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2918*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2919*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xefd0);
2920*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2921*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.idx);
2922*61046927SAndroid Build Coastguard Worker     }
2923*61046927SAndroid Build Coastguard Worker }
2924*61046927SAndroid Build Coastguard Worker 
2925*61046927SAndroid Build Coastguard Worker impl SM50Op for OpKill {
legalize(&mut self, _b: &mut LegalizeBuilder)2926*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2927*61046927SAndroid Build Coastguard Worker         // Nothing to do
2928*61046927SAndroid Build Coastguard Worker     }
2929*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2930*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2931*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xe330);
2932*61046927SAndroid Build Coastguard Worker         e.set_field(0..5, 0x0f_u8);
2933*61046927SAndroid Build Coastguard Worker     }
2934*61046927SAndroid Build Coastguard Worker }
2935*61046927SAndroid Build Coastguard Worker 
2936*61046927SAndroid Build Coastguard Worker impl SM50Op for OpNop {
legalize(&mut self, _b: &mut LegalizeBuilder)2937*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2938*61046927SAndroid Build Coastguard Worker         // Nothing to do
2939*61046927SAndroid Build Coastguard Worker     }
2940*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2941*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2942*61046927SAndroid Build Coastguard Worker         e.set_opcode(0x50b0);
2943*61046927SAndroid Build Coastguard Worker 
2944*61046927SAndroid Build Coastguard Worker         // TODO: CC flags
2945*61046927SAndroid Build Coastguard Worker         e.set_field(8..12, 0xf_u8); // CC.T
2946*61046927SAndroid Build Coastguard Worker     }
2947*61046927SAndroid Build Coastguard Worker }
2948*61046927SAndroid Build Coastguard Worker 
2949*61046927SAndroid Build Coastguard Worker impl SM50Op for OpPixLd {
legalize(&mut self, _b: &mut LegalizeBuilder)2950*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2951*61046927SAndroid Build Coastguard Worker         // Nothing to do
2952*61046927SAndroid Build Coastguard Worker     }
2953*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2954*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2955*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xefe8);
2956*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2957*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, 0.into());
2958*61046927SAndroid Build Coastguard Worker         e.set_field(
2959*61046927SAndroid Build Coastguard Worker             31..34,
2960*61046927SAndroid Build Coastguard Worker             match &self.val {
2961*61046927SAndroid Build Coastguard Worker                 PixVal::CovMask => 1_u8,
2962*61046927SAndroid Build Coastguard Worker                 PixVal::Covered => 2_u8,
2963*61046927SAndroid Build Coastguard Worker                 PixVal::Offset => 3_u8,
2964*61046927SAndroid Build Coastguard Worker                 PixVal::CentroidOffset => 4_u8,
2965*61046927SAndroid Build Coastguard Worker                 PixVal::MyIndex => 5_u8,
2966*61046927SAndroid Build Coastguard Worker                 other => panic!("Unsupported PixVal: {other}"),
2967*61046927SAndroid Build Coastguard Worker             },
2968*61046927SAndroid Build Coastguard Worker         );
2969*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(45..48, Dst::None);
2970*61046927SAndroid Build Coastguard Worker     }
2971*61046927SAndroid Build Coastguard Worker }
2972*61046927SAndroid Build Coastguard Worker 
2973*61046927SAndroid Build Coastguard Worker impl SM50Op for OpS2R {
legalize(&mut self, _b: &mut LegalizeBuilder)2974*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2975*61046927SAndroid Build Coastguard Worker         // Nothing to do
2976*61046927SAndroid Build Coastguard Worker     }
2977*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2978*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2979*61046927SAndroid Build Coastguard Worker         e.set_opcode(0xf0c8);
2980*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
2981*61046927SAndroid Build Coastguard Worker         e.set_field(20..28, self.idx);
2982*61046927SAndroid Build Coastguard Worker     }
2983*61046927SAndroid Build Coastguard Worker }
2984*61046927SAndroid Build Coastguard Worker 
2985*61046927SAndroid Build Coastguard Worker impl SM50Op for OpVote {
legalize(&mut self, _b: &mut LegalizeBuilder)2986*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, _b: &mut LegalizeBuilder) {
2987*61046927SAndroid Build Coastguard Worker         // Nothing to do
2988*61046927SAndroid Build Coastguard Worker     }
2989*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)2990*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
2991*61046927SAndroid Build Coastguard Worker         e.set_opcode(0x50d8);
2992*61046927SAndroid Build Coastguard Worker 
2993*61046927SAndroid Build Coastguard Worker         e.set_dst(self.ballot);
2994*61046927SAndroid Build Coastguard Worker         e.set_pred_dst(45..48, self.vote);
2995*61046927SAndroid Build Coastguard Worker         e.set_pred_src(39..42, 42, self.pred);
2996*61046927SAndroid Build Coastguard Worker 
2997*61046927SAndroid Build Coastguard Worker         e.set_field(
2998*61046927SAndroid Build Coastguard Worker             48..50,
2999*61046927SAndroid Build Coastguard Worker             match self.op {
3000*61046927SAndroid Build Coastguard Worker                 VoteOp::All => 0u8,
3001*61046927SAndroid Build Coastguard Worker                 VoteOp::Any => 1u8,
3002*61046927SAndroid Build Coastguard Worker                 VoteOp::Eq => 2u8,
3003*61046927SAndroid Build Coastguard Worker             },
3004*61046927SAndroid Build Coastguard Worker         );
3005*61046927SAndroid Build Coastguard Worker     }
3006*61046927SAndroid Build Coastguard Worker }
3007*61046927SAndroid Build Coastguard Worker 
3008*61046927SAndroid Build Coastguard Worker impl SM50Op for OpOut {
legalize(&mut self, b: &mut LegalizeBuilder)3009*61046927SAndroid Build Coastguard Worker     fn legalize(&mut self, b: &mut LegalizeBuilder) {
3010*61046927SAndroid Build Coastguard Worker         use RegFile::GPR;
3011*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_not_reg(&mut self.handle, GPR, SrcType::GPR);
3012*61046927SAndroid Build Coastguard Worker         b.copy_alu_src_if_i20_overflow(&mut self.stream, GPR, SrcType::ALU);
3013*61046927SAndroid Build Coastguard Worker     }
3014*61046927SAndroid Build Coastguard Worker 
encode(&self, e: &mut SM50Encoder<'_>)3015*61046927SAndroid Build Coastguard Worker     fn encode(&self, e: &mut SM50Encoder<'_>) {
3016*61046927SAndroid Build Coastguard Worker         match &self.stream.src_ref {
3017*61046927SAndroid Build Coastguard Worker             SrcRef::Zero | SrcRef::Reg(_) => {
3018*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0xfbe0);
3019*61046927SAndroid Build Coastguard Worker                 e.set_reg_src(20..28, self.stream);
3020*61046927SAndroid Build Coastguard Worker             }
3021*61046927SAndroid Build Coastguard Worker             SrcRef::Imm32(imm32) => {
3022*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0xf6e0);
3023*61046927SAndroid Build Coastguard Worker                 e.set_src_imm_i20(20..39, 56, *imm32);
3024*61046927SAndroid Build Coastguard Worker             }
3025*61046927SAndroid Build Coastguard Worker             SrcRef::CBuf(cbuf) => {
3026*61046927SAndroid Build Coastguard Worker                 e.set_opcode(0xebe0);
3027*61046927SAndroid Build Coastguard Worker                 e.set_src_cb(20..39, cbuf);
3028*61046927SAndroid Build Coastguard Worker             }
3029*61046927SAndroid Build Coastguard Worker             src => panic!("Invalid out stream: {src}"),
3030*61046927SAndroid Build Coastguard Worker         }
3031*61046927SAndroid Build Coastguard Worker 
3032*61046927SAndroid Build Coastguard Worker         e.set_field(
3033*61046927SAndroid Build Coastguard Worker             39..41,
3034*61046927SAndroid Build Coastguard Worker             match self.out_type {
3035*61046927SAndroid Build Coastguard Worker                 OutType::Emit => 1_u8,
3036*61046927SAndroid Build Coastguard Worker                 OutType::Cut => 2_u8,
3037*61046927SAndroid Build Coastguard Worker                 OutType::EmitThenCut => 3_u8,
3038*61046927SAndroid Build Coastguard Worker             },
3039*61046927SAndroid Build Coastguard Worker         );
3040*61046927SAndroid Build Coastguard Worker 
3041*61046927SAndroid Build Coastguard Worker         e.set_reg_src(8..16, self.handle);
3042*61046927SAndroid Build Coastguard Worker         e.set_dst(self.dst);
3043*61046927SAndroid Build Coastguard Worker     }
3044*61046927SAndroid Build Coastguard Worker }
3045*61046927SAndroid Build Coastguard Worker 
3046*61046927SAndroid Build Coastguard Worker macro_rules! as_sm50_op_match {
3047*61046927SAndroid Build Coastguard Worker     ($op: expr) => {
3048*61046927SAndroid Build Coastguard Worker         match $op {
3049*61046927SAndroid Build Coastguard Worker             Op::FAdd(op) => op,
3050*61046927SAndroid Build Coastguard Worker             Op::FMnMx(op) => op,
3051*61046927SAndroid Build Coastguard Worker             Op::FMul(op) => op,
3052*61046927SAndroid Build Coastguard Worker             Op::FFma(op) => op,
3053*61046927SAndroid Build Coastguard Worker             Op::FSet(op) => op,
3054*61046927SAndroid Build Coastguard Worker             Op::FSetP(op) => op,
3055*61046927SAndroid Build Coastguard Worker             Op::FSwzAdd(op) => op,
3056*61046927SAndroid Build Coastguard Worker             Op::Rro(op) => op,
3057*61046927SAndroid Build Coastguard Worker             Op::MuFu(op) => op,
3058*61046927SAndroid Build Coastguard Worker             Op::Flo(op) => op,
3059*61046927SAndroid Build Coastguard Worker             Op::DAdd(op) => op,
3060*61046927SAndroid Build Coastguard Worker             Op::DFma(op) => op,
3061*61046927SAndroid Build Coastguard Worker             Op::DMnMx(op) => op,
3062*61046927SAndroid Build Coastguard Worker             Op::DMul(op) => op,
3063*61046927SAndroid Build Coastguard Worker             Op::DSetP(op) => op,
3064*61046927SAndroid Build Coastguard Worker             Op::IAdd2(op) => op,
3065*61046927SAndroid Build Coastguard Worker             Op::IAdd2X(op) => op,
3066*61046927SAndroid Build Coastguard Worker             Op::Mov(op) => op,
3067*61046927SAndroid Build Coastguard Worker             Op::Sel(op) => op,
3068*61046927SAndroid Build Coastguard Worker             Op::Shfl(op) => op,
3069*61046927SAndroid Build Coastguard Worker             Op::Vote(op) => op,
3070*61046927SAndroid Build Coastguard Worker             Op::PSetP(op) => op,
3071*61046927SAndroid Build Coastguard Worker             Op::SuSt(op) => op,
3072*61046927SAndroid Build Coastguard Worker             Op::S2R(op) => op,
3073*61046927SAndroid Build Coastguard Worker             Op::PopC(op) => op,
3074*61046927SAndroid Build Coastguard Worker             Op::Prmt(op) => op,
3075*61046927SAndroid Build Coastguard Worker             Op::Ld(op) => op,
3076*61046927SAndroid Build Coastguard Worker             Op::Ldc(op) => op,
3077*61046927SAndroid Build Coastguard Worker             Op::St(op) => op,
3078*61046927SAndroid Build Coastguard Worker             Op::Lop2(op) => op,
3079*61046927SAndroid Build Coastguard Worker             Op::Shf(op) => op,
3080*61046927SAndroid Build Coastguard Worker             Op::Shl(op) => op,
3081*61046927SAndroid Build Coastguard Worker             Op::Shr(op) => op,
3082*61046927SAndroid Build Coastguard Worker             Op::F2F(op) => op,
3083*61046927SAndroid Build Coastguard Worker             Op::F2I(op) => op,
3084*61046927SAndroid Build Coastguard Worker             Op::I2F(op) => op,
3085*61046927SAndroid Build Coastguard Worker             Op::I2I(op) => op,
3086*61046927SAndroid Build Coastguard Worker             Op::IMad(op) => op,
3087*61046927SAndroid Build Coastguard Worker             Op::IMul(op) => op,
3088*61046927SAndroid Build Coastguard Worker             Op::IMnMx(op) => op,
3089*61046927SAndroid Build Coastguard Worker             Op::ISetP(op) => op,
3090*61046927SAndroid Build Coastguard Worker             Op::Tex(op) => op,
3091*61046927SAndroid Build Coastguard Worker             Op::Tld(op) => op,
3092*61046927SAndroid Build Coastguard Worker             Op::Tld4(op) => op,
3093*61046927SAndroid Build Coastguard Worker             Op::Tmml(op) => op,
3094*61046927SAndroid Build Coastguard Worker             Op::Txd(op) => op,
3095*61046927SAndroid Build Coastguard Worker             Op::Txq(op) => op,
3096*61046927SAndroid Build Coastguard Worker             Op::Ipa(op) => op,
3097*61046927SAndroid Build Coastguard Worker             Op::AL2P(op) => op,
3098*61046927SAndroid Build Coastguard Worker             Op::ALd(op) => op,
3099*61046927SAndroid Build Coastguard Worker             Op::ASt(op) => op,
3100*61046927SAndroid Build Coastguard Worker             Op::CCtl(op) => op,
3101*61046927SAndroid Build Coastguard Worker             Op::MemBar(op) => op,
3102*61046927SAndroid Build Coastguard Worker             Op::Atom(op) => op,
3103*61046927SAndroid Build Coastguard Worker             Op::Bra(op) => op,
3104*61046927SAndroid Build Coastguard Worker             Op::SSy(op) => op,
3105*61046927SAndroid Build Coastguard Worker             Op::Sync(op) => op,
3106*61046927SAndroid Build Coastguard Worker             Op::Brk(op) => op,
3107*61046927SAndroid Build Coastguard Worker             Op::PBk(op) => op,
3108*61046927SAndroid Build Coastguard Worker             Op::Cont(op) => op,
3109*61046927SAndroid Build Coastguard Worker             Op::PCnt(op) => op,
3110*61046927SAndroid Build Coastguard Worker             Op::Exit(op) => op,
3111*61046927SAndroid Build Coastguard Worker             Op::Bar(op) => op,
3112*61046927SAndroid Build Coastguard Worker             Op::SuLd(op) => op,
3113*61046927SAndroid Build Coastguard Worker             Op::SuAtom(op) => op,
3114*61046927SAndroid Build Coastguard Worker             Op::Kill(op) => op,
3115*61046927SAndroid Build Coastguard Worker             Op::CS2R(op) => op,
3116*61046927SAndroid Build Coastguard Worker             Op::Nop(op) => op,
3117*61046927SAndroid Build Coastguard Worker             Op::PixLd(op) => op,
3118*61046927SAndroid Build Coastguard Worker             Op::Isberd(op) => op,
3119*61046927SAndroid Build Coastguard Worker             Op::Out(op) => op,
3120*61046927SAndroid Build Coastguard Worker             Op::Bfe(op) => op,
3121*61046927SAndroid Build Coastguard Worker             _ => panic!("Unhandled instruction {}", $op),
3122*61046927SAndroid Build Coastguard Worker         }
3123*61046927SAndroid Build Coastguard Worker     };
3124*61046927SAndroid Build Coastguard Worker }
3125*61046927SAndroid Build Coastguard Worker 
as_sm50_op(op: &Op) -> &dyn SM50Op3126*61046927SAndroid Build Coastguard Worker fn as_sm50_op(op: &Op) -> &dyn SM50Op {
3127*61046927SAndroid Build Coastguard Worker     as_sm50_op_match!(op)
3128*61046927SAndroid Build Coastguard Worker }
3129*61046927SAndroid Build Coastguard Worker 
as_sm50_op_mut(op: &mut Op) -> &mut dyn SM50Op3130*61046927SAndroid Build Coastguard Worker fn as_sm50_op_mut(op: &mut Op) -> &mut dyn SM50Op {
3131*61046927SAndroid Build Coastguard Worker     as_sm50_op_match!(op)
3132*61046927SAndroid Build Coastguard Worker }
3133*61046927SAndroid Build Coastguard Worker 
encode_instr( instr_index: usize, instr: Option<&Box<Instr>>, sm: &ShaderModel50, labels: &HashMap<Label, usize>, ip: &mut usize, sched_instr: &mut [u32; 2], ) -> [u32; 2]3134*61046927SAndroid Build Coastguard Worker fn encode_instr(
3135*61046927SAndroid Build Coastguard Worker     instr_index: usize,
3136*61046927SAndroid Build Coastguard Worker     instr: Option<&Box<Instr>>,
3137*61046927SAndroid Build Coastguard Worker     sm: &ShaderModel50,
3138*61046927SAndroid Build Coastguard Worker     labels: &HashMap<Label, usize>,
3139*61046927SAndroid Build Coastguard Worker     ip: &mut usize,
3140*61046927SAndroid Build Coastguard Worker     sched_instr: &mut [u32; 2],
3141*61046927SAndroid Build Coastguard Worker ) -> [u32; 2] {
3142*61046927SAndroid Build Coastguard Worker     let mut e = SM50Encoder {
3143*61046927SAndroid Build Coastguard Worker         sm,
3144*61046927SAndroid Build Coastguard Worker         ip: *ip,
3145*61046927SAndroid Build Coastguard Worker         labels,
3146*61046927SAndroid Build Coastguard Worker         inst: [0_u32; 2],
3147*61046927SAndroid Build Coastguard Worker         sched: 0,
3148*61046927SAndroid Build Coastguard Worker     };
3149*61046927SAndroid Build Coastguard Worker 
3150*61046927SAndroid Build Coastguard Worker     if let Some(instr) = instr {
3151*61046927SAndroid Build Coastguard Worker         as_sm50_op(&instr.op).encode(&mut e);
3152*61046927SAndroid Build Coastguard Worker         e.set_pred(&instr.pred);
3153*61046927SAndroid Build Coastguard Worker         e.set_instr_deps(&instr.deps);
3154*61046927SAndroid Build Coastguard Worker     } else {
3155*61046927SAndroid Build Coastguard Worker         let nop = OpNop { label: None };
3156*61046927SAndroid Build Coastguard Worker         nop.encode(&mut e);
3157*61046927SAndroid Build Coastguard Worker         e.set_pred(&true.into());
3158*61046927SAndroid Build Coastguard Worker         e.set_instr_deps(&InstrDeps::new());
3159*61046927SAndroid Build Coastguard Worker     }
3160*61046927SAndroid Build Coastguard Worker 
3161*61046927SAndroid Build Coastguard Worker     *ip += 8;
3162*61046927SAndroid Build Coastguard Worker 
3163*61046927SAndroid Build Coastguard Worker     BitMutView::new(sched_instr)
3164*61046927SAndroid Build Coastguard Worker         .set_field(21 * instr_index..21 * (instr_index + 1), e.sched);
3165*61046927SAndroid Build Coastguard Worker 
3166*61046927SAndroid Build Coastguard Worker     e.inst
3167*61046927SAndroid Build Coastguard Worker }
3168*61046927SAndroid Build Coastguard Worker 
encode_sm50_shader(sm: &ShaderModel50, s: &Shader<'_>) -> Vec<u32>3169*61046927SAndroid Build Coastguard Worker fn encode_sm50_shader(sm: &ShaderModel50, s: &Shader<'_>) -> Vec<u32> {
3170*61046927SAndroid Build Coastguard Worker     assert!(s.functions.len() == 1);
3171*61046927SAndroid Build Coastguard Worker     let func = &s.functions[0];
3172*61046927SAndroid Build Coastguard Worker 
3173*61046927SAndroid Build Coastguard Worker     let mut num_instrs = 0_usize;
3174*61046927SAndroid Build Coastguard Worker     let mut labels = HashMap::new();
3175*61046927SAndroid Build Coastguard Worker     for b in &func.blocks {
3176*61046927SAndroid Build Coastguard Worker         // We ensure blocks will have groups of 3 instructions with a
3177*61046927SAndroid Build Coastguard Worker         // schedule instruction before each groups.  As we should never jump
3178*61046927SAndroid Build Coastguard Worker         // to a schedule instruction, we account for that here.
3179*61046927SAndroid Build Coastguard Worker         labels.insert(b.label, num_instrs + 8);
3180*61046927SAndroid Build Coastguard Worker 
3181*61046927SAndroid Build Coastguard Worker         let block_num_instrs = b.instrs.len().next_multiple_of(3);
3182*61046927SAndroid Build Coastguard Worker 
3183*61046927SAndroid Build Coastguard Worker         // Every 3 instructions, we have a new schedule instruction so we
3184*61046927SAndroid Build Coastguard Worker         // need to account for that.
3185*61046927SAndroid Build Coastguard Worker         num_instrs += (block_num_instrs + (block_num_instrs / 3)) * 8;
3186*61046927SAndroid Build Coastguard Worker     }
3187*61046927SAndroid Build Coastguard Worker 
3188*61046927SAndroid Build Coastguard Worker     let mut encoded = Vec::new();
3189*61046927SAndroid Build Coastguard Worker     for b in &func.blocks {
3190*61046927SAndroid Build Coastguard Worker         // A block is composed of groups of 3 instructions.
3191*61046927SAndroid Build Coastguard Worker         let block_num_instrs = b.instrs.len().next_multiple_of(3);
3192*61046927SAndroid Build Coastguard Worker 
3193*61046927SAndroid Build Coastguard Worker         let mut instrs_iter = b.instrs.iter();
3194*61046927SAndroid Build Coastguard Worker 
3195*61046927SAndroid Build Coastguard Worker         for _ in 0..(block_num_instrs / 3) {
3196*61046927SAndroid Build Coastguard Worker             let mut ip = ((encoded.len() / 2) + 1) * 8;
3197*61046927SAndroid Build Coastguard Worker 
3198*61046927SAndroid Build Coastguard Worker             let mut sched_instr = [0x0; 2];
3199*61046927SAndroid Build Coastguard Worker 
3200*61046927SAndroid Build Coastguard Worker             let instr0 = encode_instr(
3201*61046927SAndroid Build Coastguard Worker                 0,
3202*61046927SAndroid Build Coastguard Worker                 instrs_iter.next(),
3203*61046927SAndroid Build Coastguard Worker                 sm,
3204*61046927SAndroid Build Coastguard Worker                 &labels,
3205*61046927SAndroid Build Coastguard Worker                 &mut ip,
3206*61046927SAndroid Build Coastguard Worker                 &mut sched_instr,
3207*61046927SAndroid Build Coastguard Worker             );
3208*61046927SAndroid Build Coastguard Worker             let instr1 = encode_instr(
3209*61046927SAndroid Build Coastguard Worker                 1,
3210*61046927SAndroid Build Coastguard Worker                 instrs_iter.next(),
3211*61046927SAndroid Build Coastguard Worker                 sm,
3212*61046927SAndroid Build Coastguard Worker                 &labels,
3213*61046927SAndroid Build Coastguard Worker                 &mut ip,
3214*61046927SAndroid Build Coastguard Worker                 &mut sched_instr,
3215*61046927SAndroid Build Coastguard Worker             );
3216*61046927SAndroid Build Coastguard Worker             let instr2 = encode_instr(
3217*61046927SAndroid Build Coastguard Worker                 2,
3218*61046927SAndroid Build Coastguard Worker                 instrs_iter.next(),
3219*61046927SAndroid Build Coastguard Worker                 sm,
3220*61046927SAndroid Build Coastguard Worker                 &labels,
3221*61046927SAndroid Build Coastguard Worker                 &mut ip,
3222*61046927SAndroid Build Coastguard Worker                 &mut sched_instr,
3223*61046927SAndroid Build Coastguard Worker             );
3224*61046927SAndroid Build Coastguard Worker 
3225*61046927SAndroid Build Coastguard Worker             encoded.extend_from_slice(&sched_instr[..]);
3226*61046927SAndroid Build Coastguard Worker             encoded.extend_from_slice(&instr0[..]);
3227*61046927SAndroid Build Coastguard Worker             encoded.extend_from_slice(&instr1[..]);
3228*61046927SAndroid Build Coastguard Worker             encoded.extend_from_slice(&instr2[..]);
3229*61046927SAndroid Build Coastguard Worker         }
3230*61046927SAndroid Build Coastguard Worker     }
3231*61046927SAndroid Build Coastguard Worker 
3232*61046927SAndroid Build Coastguard Worker     encoded
3233*61046927SAndroid Build Coastguard Worker }
3234