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