Editor for papermario-dx mods
1// SPDX-FileCopyrightText: 2024 gopher64 contributors
2// SPDX-FileCopyrightText: 2026 Alex Bates <alex@bates64.com>
3//
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6#[cfg(target_arch = "x86_64")]
7use std::arch::x86_64::*;
8
9use crate::su_instructions::{get_vpr16, modify_vpr16};
10
11fn vt(opcode: u32) -> u32 {
12 (opcode >> 16) & 0x1F
13}
14
15fn ve(opcode: u32) -> u32 {
16 (opcode >> 21) & 0xF
17}
18
19fn vs(opcode: u32) -> u32 {
20 (opcode >> 11) & 0x1F
21}
22
23fn vd(opcode: u32) -> u32 {
24 (opcode >> 6) & 0x1F
25}
26
27fn de(opcode: u32) -> u32 {
28 (opcode >> 11) & 0x7
29}
30
31fn clamp_signed_32(value: i32) -> i16 {
32 value.clamp(-32768, 32767) as i16
33}
34
35fn clamp_signed_64(value: i64) -> i16 {
36 value.clamp(-32768, 32767) as i16
37}
38
39fn s_clip(x: i64, bits: u32) -> i64 {
40 let mask = (1i64 << bits) - 1;
41 let value = x & mask;
42 (value << (64 - bits)) >> (64 - bits)
43}
44
45fn compute_reciprocal(input: i32, reciprocals: &[u16]) -> u32 {
46 let mask = input >> 31;
47 let mut data = input ^ mask;
48 if input > -32768 {
49 data -= mask
50 }
51 if data == 0 {
52 0x7fffffff
53 } else if input == -32768 {
54 0xffff0000
55 } else {
56 let shift = (data as u32).leading_zeros();
57 let index = (((data as u64) << shift) & 0x7fc00000) >> 22;
58 let mut result = reciprocals[index as usize] as u32;
59 result = (0x10000 | result) << 14;
60 (result >> (31 - shift)) ^ mask as u32
61 }
62}
63
64fn compute_inverse_sqrt(input: i32, inverse_square_roots: &[u16]) -> u32 {
65 let mask = input >> 31;
66 let mut data = input ^ mask;
67 if input > -32768 {
68 data -= mask
69 }
70 if data == 0 {
71 0x7fffffff
72 } else if input == -32768 {
73 0xffff0000
74 } else {
75 let shift = (data as u32).leading_zeros();
76 let index = (((data as u64) << shift) & 0x7fc00000) as u32 >> 22;
77 let mut result = inverse_square_roots[((index & 0x1fe) | (shift & 1)) as usize] as u32;
78 result = (0x10000 | result) << 14;
79 (result >> ((31 - shift) >> 1)) ^ mask as u32
80 }
81}
82
83fn vte(device: &crate::Device, vt: u32, index: usize) -> __m128i {
84 unsafe {
85 _mm_shuffle_epi8(
86 device.rsp.cpu.vpr[vt as usize],
87 device.rsp.cpu.shuffle[index],
88 )
89 }
90}
91
92pub fn vmulf(device: &mut crate::Device, opcode: u32) {
93 let vte = vte(device, vt(opcode), ve(opcode) as usize);
94 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
95 unsafe {
96 let lo = _mm_mullo_epi16(vs_reg, vte);
97 let hi = _mm_mulhi_epi16(vs_reg, vte);
98
99 let sign1 = _mm_srli_epi16(lo, 15);
100 let lo_doubled = _mm_add_epi16(lo, lo);
101 let sign2 = _mm_srli_epi16(lo_doubled, 15);
102
103 device.rsp.cpu.accl = _mm_add_epi16(_mm_set1_epi16(-32768_i16), lo_doubled); // round + lo
104 device.rsp.cpu.accm = _mm_add_epi16(_mm_slli_epi16(hi, 1), _mm_add_epi16(sign1, sign2));
105 let neg = _mm_srai_epi16(device.rsp.cpu.accm, 15);
106
107 let neq = _mm_cmpeq_epi16(vs_reg, vte);
108 let eq = _mm_and_si128(neq, neg);
109
110 device.rsp.cpu.acch = _mm_andnot_si128(neq, neg);
111 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_add_epi16(device.rsp.cpu.accm, eq);
112 }
113}
114
115pub fn vmulu(device: &mut crate::Device, opcode: u32) {
116 let vte = vte(device, vt(opcode), ve(opcode) as usize);
117 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
118 unsafe {
119 let lo = _mm_mullo_epi16(vs_reg, vte);
120 let hi = _mm_mulhi_epi16(vs_reg, vte);
121
122 let sign1 = _mm_srli_epi16(lo, 15);
123 let lo_doubled = _mm_add_epi16(lo, lo);
124 let sign2 = _mm_srli_epi16(lo_doubled, 15);
125
126 device.rsp.cpu.accl = _mm_add_epi16(_mm_set1_epi16(-32768_i16), lo_doubled); // round + lo
127 device.rsp.cpu.accm = _mm_add_epi16(_mm_slli_epi16(hi, 1), _mm_add_epi16(sign1, sign2));
128 let neg = _mm_srai_epi16(device.rsp.cpu.accm, 15);
129
130 let neq = _mm_cmpeq_epi16(vs_reg, vte);
131
132 device.rsp.cpu.acch = _mm_andnot_si128(neq, neg);
133 let result = _mm_or_si128(device.rsp.cpu.accm, neg);
134 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_andnot_si128(device.rsp.cpu.acch, result);
135 }
136}
137
138pub fn vrndp(device: &mut crate::Device, opcode: u32) {
139 let vte = vte(device, vt(opcode), ve(opcode) as usize);
140 let acch: &mut __m128i = &mut device.rsp.cpu.acch;
141 let accm: &mut __m128i = &mut device.rsp.cpu.accm;
142 let accl: &mut __m128i = &mut device.rsp.cpu.accl;
143 let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize];
144 let shift_amount = vs(opcode) & 1;
145
146 for n in 0..8 {
147 let mut product = get_vpr16(vte, n) as i16 as i32;
148 if shift_amount != 0 {
149 product <<= 16
150 }
151 let mut acc = 0;
152 acc |= get_vpr16(*acch, n) as i64;
153 acc <<= 16;
154 acc |= get_vpr16(*accm, n) as i64;
155 acc <<= 16;
156 acc |= get_vpr16(*accl, n) as i64;
157 acc <<= 16;
158 acc >>= 16;
159 if acc >= 0 {
160 acc = s_clip(acc + (product as i64), 48)
161 }
162 modify_vpr16(acch, n, (acc >> 32) as u16);
163 modify_vpr16(accm, n, (acc >> 16) as u16);
164 modify_vpr16(accl, n, acc as u16);
165 modify_vpr16(vd_reg, n, clamp_signed_64(acc >> 16) as u16);
166 }
167}
168
169pub fn vmulq(device: &mut crate::Device, opcode: u32) {
170 let vte = vte(device, vt(opcode), ve(opcode) as usize);
171 let acch: &mut __m128i = &mut device.rsp.cpu.acch;
172 let accm: &mut __m128i = &mut device.rsp.cpu.accm;
173 let accl: &mut __m128i = &mut device.rsp.cpu.accl;
174 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
175 let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize];
176
177 for n in 0..8 {
178 let mut product =
179 (get_vpr16(vs_reg, n) as i16 as i32).wrapping_mul(get_vpr16(vte, n) as i16 as i32);
180 if product < 0 {
181 product += 31;
182 }
183 modify_vpr16(acch, n, (product >> 16) as u16);
184 modify_vpr16(accm, n, product as u16);
185 modify_vpr16(accl, n, 0);
186 modify_vpr16(vd_reg, n, (clamp_signed_32(product >> 1) & !15) as u16);
187 }
188}
189
190pub fn vmudl(device: &mut crate::Device, opcode: u32) {
191 let vte = vte(device, vt(opcode), ve(opcode) as usize);
192 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
193 unsafe {
194 device.rsp.cpu.accl = _mm_mulhi_epu16(vs_reg, vte);
195 device.rsp.cpu.accm = _mm_setzero_si128();
196 device.rsp.cpu.acch = _mm_setzero_si128();
197 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
198 }
199}
200
201pub fn vmudm(device: &mut crate::Device, opcode: u32) {
202 let vte = vte(device, vt(opcode), ve(opcode) as usize);
203 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
204 unsafe {
205 device.rsp.cpu.accl = _mm_mullo_epi16(vs_reg, vte);
206 device.rsp.cpu.accm = _mm_mulhi_epu16(vs_reg, vte);
207 let sign = _mm_srai_epi16(vs_reg, 15);
208 let vta = _mm_and_si128(vte, sign);
209 device.rsp.cpu.accm = _mm_sub_epi16(device.rsp.cpu.accm, vta);
210 device.rsp.cpu.acch = _mm_srai_epi16(device.rsp.cpu.accm, 15);
211 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accm;
212 }
213}
214
215pub fn vmudn(device: &mut crate::Device, opcode: u32) {
216 let vte = vte(device, vt(opcode), ve(opcode) as usize);
217 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
218 unsafe {
219 device.rsp.cpu.accl = _mm_mullo_epi16(vs_reg, vte);
220 device.rsp.cpu.accm = _mm_mulhi_epu16(vs_reg, vte);
221 let sign = _mm_srai_epi16(vte, 15);
222 let vsa = _mm_and_si128(vs_reg, sign);
223 device.rsp.cpu.accm = _mm_sub_epi16(device.rsp.cpu.accm, vsa);
224 device.rsp.cpu.acch = _mm_srai_epi16(device.rsp.cpu.accm, 15);
225 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
226 }
227}
228
229pub fn vmudh(device: &mut crate::Device, opcode: u32) {
230 let vte = vte(device, vt(opcode), ve(opcode) as usize);
231 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
232 unsafe {
233 device.rsp.cpu.accl = _mm_setzero_si128();
234 device.rsp.cpu.accm = _mm_mullo_epi16(vs_reg, vte);
235 device.rsp.cpu.acch = _mm_mulhi_epi16(vs_reg, vte);
236 let lo = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch);
237 let hi = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch);
238 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo, hi);
239 }
240}
241
242pub fn vmacf(device: &mut crate::Device, opcode: u32) {
243 let vte = vte(device, vt(opcode), ve(opcode) as usize);
244 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
245 unsafe {
246 let lo = _mm_mullo_epi16(vs_reg, vte);
247 let hi = _mm_mulhi_epi16(vs_reg, vte);
248
249 let carry = _mm_srli_epi16(lo, 15);
250 let md = _mm_or_si128(_mm_slli_epi16(hi, 1), carry);
251 let lo_doubled = _mm_slli_epi16(lo, 1);
252 let hi_sign = _mm_srai_epi16(hi, 15);
253
254 let accl_old = device.rsp.cpu.accl;
255 device.rsp.cpu.accl = _mm_add_epi16(accl_old, lo_doubled);
256 let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, lo_doubled), device.rsp.cpu.accl);
257 let borrow_from_l = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128());
258
259 let md_adjusted = _mm_sub_epi16(md, borrow_from_l);
260 let zero_md = _mm_cmpeq_epi16(md_adjusted, _mm_setzero_si128());
261 let borrow_to_h = _mm_and_si128(zero_md, borrow_from_l);
262 let hi_adjusted = _mm_sub_epi16(hi_sign, borrow_to_h);
263
264 let accm_old = device.rsp.cpu.accm;
265 device.rsp.cpu.accm = _mm_add_epi16(accm_old, md_adjusted);
266 let overflow_m =
267 _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, md_adjusted), device.rsp.cpu.accm);
268 let borrow_from_m = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128());
269
270 device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi_adjusted);
271 device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_from_m);
272
273 let lo_packed = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch);
274 let hi_packed = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch);
275 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo_packed, hi_packed);
276 }
277}
278
279pub fn vmacu(device: &mut crate::Device, opcode: u32) {
280 let vte = vte(device, vt(opcode), ve(opcode) as usize);
281 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
282 unsafe {
283 let lo = _mm_mullo_epi16(vs_reg, vte);
284 let hi = _mm_mulhi_epi16(vs_reg, vte);
285
286 let carry = _mm_srli_epi16(lo, 15);
287 let md = _mm_or_si128(_mm_slli_epi16(hi, 1), carry);
288 let lo_doubled = _mm_slli_epi16(lo, 1);
289 let hi_sign = _mm_srai_epi16(hi, 15);
290
291 let accl_old = device.rsp.cpu.accl;
292 device.rsp.cpu.accl = _mm_add_epi16(accl_old, lo_doubled);
293 let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, lo_doubled), device.rsp.cpu.accl);
294 let borrow_from_l = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128());
295
296 let md_adjusted = _mm_sub_epi16(md, borrow_from_l);
297 let zero_md = _mm_cmpeq_epi16(md_adjusted, _mm_setzero_si128());
298 let borrow_to_h = _mm_and_si128(zero_md, borrow_from_l);
299 let hi_adjusted = _mm_sub_epi16(hi_sign, borrow_to_h);
300
301 let accm_old = device.rsp.cpu.accm;
302 device.rsp.cpu.accm = _mm_add_epi16(accm_old, md_adjusted);
303 let overflow_m =
304 _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, md_adjusted), device.rsp.cpu.accm);
305 let borrow_from_m = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128());
306
307 device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi_adjusted);
308 device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_from_m);
309
310 let mmask = _mm_srai_epi16(device.rsp.cpu.accm, 15);
311 let hmask = _mm_srai_epi16(device.rsp.cpu.acch, 15);
312 let md_result = _mm_or_si128(mmask, device.rsp.cpu.accm);
313 let positive = _mm_cmpgt_epi16(device.rsp.cpu.acch, _mm_setzero_si128());
314 let final_result = _mm_andnot_si128(hmask, md_result);
315 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_or_si128(positive, final_result);
316 }
317}
318
319pub fn vrndn(device: &mut crate::Device, opcode: u32) {
320 let vte = vte(device, vt(opcode), ve(opcode) as usize);
321 let acch: &mut __m128i = &mut device.rsp.cpu.acch;
322 let accm: &mut __m128i = &mut device.rsp.cpu.accm;
323 let accl: &mut __m128i = &mut device.rsp.cpu.accl;
324 let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize];
325 let shift_amount = vs(opcode) & 1;
326
327 for n in 0..8 {
328 let mut product = get_vpr16(vte, n) as i16 as i32;
329 if shift_amount != 0 {
330 product <<= 16
331 }
332 let mut acc = 0;
333 acc |= get_vpr16(*acch, n) as i64;
334 acc <<= 16;
335 acc |= get_vpr16(*accm, n) as i64;
336 acc <<= 16;
337 acc |= get_vpr16(*accl, n) as i64;
338 acc <<= 16;
339 acc >>= 16;
340 if acc < 0 {
341 acc = s_clip(acc + (product as i64), 48)
342 }
343 modify_vpr16(acch, n, (acc >> 32) as u16);
344 modify_vpr16(accm, n, (acc >> 16) as u16);
345 modify_vpr16(accl, n, acc as u16);
346 modify_vpr16(vd_reg, n, clamp_signed_64(acc >> 16) as u16);
347 }
348}
349
350pub fn vmacq(device: &mut crate::Device, opcode: u32) {
351 let acch: &mut __m128i = &mut device.rsp.cpu.acch;
352 let accm: &mut __m128i = &mut device.rsp.cpu.accm;
353 let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize];
354
355 for n in 0..8 {
356 let mut product = ((get_vpr16(*acch, n) as i32) << 16) | (get_vpr16(*accm, n) as i32);
357 if product < 0 && (product & (1 << 5)) == 0 {
358 product += 32
359 } else if product >= 32 && (product & (1 << 5)) == 0 {
360 product -= 32
361 }
362 modify_vpr16(acch, n, (product >> 16) as u16);
363 modify_vpr16(accm, n, product as u16);
364 modify_vpr16(vd_reg, n, (clamp_signed_32(product >> 1) & !15) as u16);
365 }
366}
367
368pub fn vmadl(device: &mut crate::Device, opcode: u32) {
369 let vte = vte(device, vt(opcode), ve(opcode) as usize);
370 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
371 unsafe {
372 let hi = _mm_mulhi_epu16(vs_reg, vte);
373
374 let accl_old = device.rsp.cpu.accl;
375 device.rsp.cpu.accl = _mm_add_epi16(accl_old, hi);
376 let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, hi), device.rsp.cpu.accl);
377 let borrow = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128());
378
379 let accm_old = device.rsp.cpu.accm;
380 device.rsp.cpu.accm = _mm_sub_epi16(accm_old, borrow);
381 let overflow_m = _mm_cmpeq_epi16(
382 _mm_adds_epu16(accm_old, _mm_sub_epi16(_mm_setzero_si128(), borrow)),
383 device.rsp.cpu.accm,
384 );
385 let borrow_h = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128());
386
387 device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_h);
388
389 let nhi = _mm_srai_epi16(device.rsp.cpu.acch, 15);
390 let nmd = _mm_srai_epi16(device.rsp.cpu.accm, 15);
391 let shi = _mm_cmpeq_epi16(nhi, device.rsp.cpu.acch);
392 let smd = _mm_cmpeq_epi16(nhi, nmd);
393 let cmask = _mm_and_si128(smd, shi);
394 let cval = _mm_cmpeq_epi16(nhi, _mm_setzero_si128());
395
396 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_blendv_epi8(cval, device.rsp.cpu.accl, cmask);
397 }
398}
399
400pub fn vmadm(device: &mut crate::Device, opcode: u32) {
401 let vte = vte(device, vt(opcode), ve(opcode) as usize);
402 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
403 unsafe {
404 let lo = _mm_mullo_epi16(vs_reg, vte);
405 let mut hi = _mm_mulhi_epu16(vs_reg, vte);
406 let sign = _mm_srai_epi16(vs_reg, 15);
407 let vta = _mm_and_si128(vte, sign);
408 hi = _mm_sub_epi16(hi, vta);
409
410 let accl_old = device.rsp.cpu.accl;
411 device.rsp.cpu.accl = _mm_add_epi16(accl_old, lo);
412 let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, lo), device.rsp.cpu.accl);
413 let borrow = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128());
414
415 hi = _mm_sub_epi16(hi, borrow);
416
417 let accm_old = device.rsp.cpu.accm;
418 device.rsp.cpu.accm = _mm_add_epi16(accm_old, hi);
419 let overflow_m = _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, hi), device.rsp.cpu.accm);
420 let borrow_h = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128());
421
422 let hi_sign = _mm_srai_epi16(hi, 15);
423 device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi_sign);
424 device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_h);
425
426 let lo_packed = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch);
427 let hi_packed = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch);
428 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo_packed, hi_packed);
429 }
430}
431
432pub fn vmadn(device: &mut crate::Device, opcode: u32) {
433 let vte = vte(device, vt(opcode), ve(opcode) as usize);
434 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
435 unsafe {
436 let lo = _mm_mullo_epi16(vs_reg, vte);
437 let mut hi = _mm_mulhi_epu16(vs_reg, vte);
438 let sign = _mm_srai_epi16(vte, 15);
439 let vsa = _mm_and_si128(vs_reg, sign);
440 hi = _mm_sub_epi16(hi, vsa);
441
442 let accl_old = device.rsp.cpu.accl;
443 device.rsp.cpu.accl = _mm_add_epi16(accl_old, lo);
444 let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, lo), device.rsp.cpu.accl);
445 let borrow = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128());
446
447 hi = _mm_sub_epi16(hi, borrow);
448
449 let accm_old = device.rsp.cpu.accm;
450 device.rsp.cpu.accm = _mm_add_epi16(accm_old, hi);
451 let overflow_m = _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, hi), device.rsp.cpu.accm);
452 let borrow_h = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128());
453
454 let hi_sign = _mm_srai_epi16(hi, 15);
455 device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi_sign);
456 device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_h);
457
458 let nhi = _mm_srai_epi16(device.rsp.cpu.acch, 15);
459 let nmd = _mm_srai_epi16(device.rsp.cpu.accm, 15);
460 let shi = _mm_cmpeq_epi16(nhi, device.rsp.cpu.acch);
461 let smd = _mm_cmpeq_epi16(nhi, nmd);
462 let cmask = _mm_and_si128(smd, shi);
463 let cval = _mm_cmpeq_epi16(nhi, _mm_setzero_si128());
464
465 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_blendv_epi8(cval, device.rsp.cpu.accl, cmask);
466 }
467}
468
469pub fn vmadh(device: &mut crate::Device, opcode: u32) {
470 let vte = vte(device, vt(opcode), ve(opcode) as usize);
471 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
472 unsafe {
473 let lo = _mm_mullo_epi16(vs_reg, vte);
474 let mut hi = _mm_mulhi_epi16(vs_reg, vte);
475
476 let accm_old = device.rsp.cpu.accm;
477 device.rsp.cpu.accm = _mm_add_epi16(accm_old, lo);
478 let overflow = _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, lo), device.rsp.cpu.accm);
479 let borrow = _mm_cmpeq_epi16(overflow, _mm_setzero_si128());
480
481 hi = _mm_sub_epi16(hi, borrow);
482 device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi);
483
484 let lo_packed = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch);
485 let hi_packed = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch);
486 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo_packed, hi_packed);
487 }
488}
489
490pub fn vadd(device: &mut crate::Device, opcode: u32) {
491 let vte = vte(device, vt(opcode), ve(opcode) as usize);
492 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
493 unsafe {
494 let sum = _mm_add_epi16(vs_reg, vte);
495 device.rsp.cpu.accl = _mm_sub_epi16(sum, device.rsp.cpu.vcol);
496
497 let min = _mm_min_epi16(vs_reg, vte);
498 let max = _mm_max_epi16(vs_reg, vte);
499 let min_adjusted = _mm_subs_epi16(min, device.rsp.cpu.vcol);
500 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_adds_epi16(min_adjusted, max);
501
502 device.rsp.cpu.vcol = _mm_setzero_si128();
503 device.rsp.cpu.vcoh = _mm_setzero_si128();
504 }
505}
506
507pub fn vsub(device: &mut crate::Device, opcode: u32) {
508 let vte = vte(device, vt(opcode), ve(opcode) as usize);
509 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
510 unsafe {
511 let udiff = _mm_sub_epi16(vte, device.rsp.cpu.vcol);
512 let sdiff = _mm_subs_epi16(vte, device.rsp.cpu.vcol);
513 device.rsp.cpu.accl = _mm_sub_epi16(vs_reg, udiff);
514
515 let ov = _mm_cmpgt_epi16(sdiff, udiff);
516 let sub_result = _mm_subs_epi16(vs_reg, sdiff);
517 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_adds_epi16(sub_result, ov);
518
519 device.rsp.cpu.vcol = _mm_setzero_si128();
520 device.rsp.cpu.vcoh = _mm_setzero_si128();
521 }
522}
523
524pub fn vzero(device: &mut crate::Device, opcode: u32) {
525 let vte = vte(device, vt(opcode), ve(opcode) as usize);
526 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
527 unsafe {
528 device.rsp.cpu.accl = _mm_add_epi16(vs_reg, vte);
529 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_setzero_si128();
530 }
531}
532
533pub fn vabs(device: &mut crate::Device, opcode: u32) {
534 let vte = vte(device, vt(opcode), ve(opcode) as usize);
535 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
536 unsafe {
537 let vs0 = _mm_cmpeq_epi16(vs_reg, _mm_setzero_si128());
538 let slt = _mm_srai_epi16(vs_reg, 15);
539
540 let mut result = _mm_andnot_si128(vs0, vte);
541 result = _mm_xor_si128(result, slt);
542 device.rsp.cpu.accl = _mm_sub_epi16(result, slt);
543 device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_subs_epi16(result, slt);
544 }
545}
546
547pub fn vaddc(device: &mut crate::Device, opcode: u32) {
548 let vte = vte(device, vt(opcode), ve(opcode) as usize);
549 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
550 unsafe {
551 let sum = _mm_adds_epu16(vs_reg, vte);
552 device.rsp.cpu.accl = _mm_add_epi16(vs_reg, vte);
553 device.rsp.cpu.vcol = _mm_cmpeq_epi16(
554 _mm_cmpeq_epi16(sum, device.rsp.cpu.accl),
555 _mm_setzero_si128(),
556 );
557 device.rsp.cpu.vcoh = _mm_setzero_si128();
558 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
559 }
560}
561
562pub fn vsubc(device: &mut crate::Device, opcode: u32) {
563 let vte = vte(device, vt(opcode), ve(opcode) as usize);
564 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
565 unsafe {
566 let udiff = _mm_subs_epu16(vs_reg, vte);
567 let equal = _mm_cmpeq_epi16(vs_reg, vte);
568 let diff0 = _mm_cmpeq_epi16(udiff, _mm_setzero_si128());
569
570 device.rsp.cpu.vcoh = _mm_cmpeq_epi16(equal, _mm_setzero_si128());
571 device.rsp.cpu.vcol = _mm_andnot_si128(equal, diff0);
572 device.rsp.cpu.accl = _mm_sub_epi16(vs_reg, vte);
573 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
574 }
575}
576
577pub fn vsar(device: &mut crate::Device, opcode: u32) {
578 let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize];
579 match ve(opcode) {
580 0x8 => {
581 *vd_reg = device.rsp.cpu.acch;
582 }
583 0x9 => {
584 *vd_reg = device.rsp.cpu.accm;
585 }
586 0xa => {
587 *vd_reg = device.rsp.cpu.accl;
588 }
589 _ => {
590 *vd_reg = unsafe { _mm_setzero_si128() };
591 }
592 }
593}
594
595pub fn vlt(device: &mut crate::Device, opcode: u32) {
596 let vte = vte(device, vt(opcode), ve(opcode) as usize);
597 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
598 unsafe {
599 let eq = _mm_cmpeq_epi16(vs_reg, vte);
600 let lt = _mm_cmplt_epi16(vs_reg, vte);
601 let eq_and_carry =
602 _mm_and_si128(_mm_and_si128(device.rsp.cpu.vcoh, eq), device.rsp.cpu.vcol);
603
604 device.rsp.cpu.vccl = _mm_or_si128(lt, eq_and_carry);
605 device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl);
606
607 device.rsp.cpu.vcch = _mm_setzero_si128();
608 device.rsp.cpu.vcoh = _mm_setzero_si128();
609 device.rsp.cpu.vcol = _mm_setzero_si128();
610 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
611 }
612}
613
614pub fn veq(device: &mut crate::Device, opcode: u32) {
615 let vte = vte(device, vt(opcode), ve(opcode) as usize);
616 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
617 unsafe {
618 let eq = _mm_cmpeq_epi16(vs_reg, vte);
619 device.rsp.cpu.vccl = _mm_andnot_si128(device.rsp.cpu.vcoh, eq);
620 device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl);
621
622 device.rsp.cpu.vcch = _mm_setzero_si128();
623 device.rsp.cpu.vcoh = _mm_setzero_si128();
624 device.rsp.cpu.vcol = _mm_setzero_si128();
625 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
626 }
627}
628
629pub fn vne(device: &mut crate::Device, opcode: u32) {
630 let vte = vte(device, vt(opcode), ve(opcode) as usize);
631 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
632 unsafe {
633 let eq = _mm_cmpeq_epi16(vs_reg, vte);
634 let ne = _mm_cmpeq_epi16(eq, _mm_setzero_si128());
635 device.rsp.cpu.vccl = _mm_or_si128(_mm_and_si128(device.rsp.cpu.vcoh, eq), ne);
636 device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl);
637
638 device.rsp.cpu.vcch = _mm_setzero_si128();
639 device.rsp.cpu.vcoh = _mm_setzero_si128();
640 device.rsp.cpu.vcol = _mm_setzero_si128();
641 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
642 }
643}
644
645pub fn vge(device: &mut crate::Device, opcode: u32) {
646 let vte = vte(device, vt(opcode), ve(opcode) as usize);
647 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
648 unsafe {
649 let eq = _mm_cmpeq_epi16(vs_reg, vte);
650 let gt = _mm_cmpgt_epi16(vs_reg, vte);
651 let es = _mm_and_si128(device.rsp.cpu.vcoh, device.rsp.cpu.vcol);
652 let eq_filtered = _mm_andnot_si128(es, eq);
653
654 device.rsp.cpu.vccl = _mm_or_si128(gt, eq_filtered);
655 device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl);
656
657 device.rsp.cpu.vcch = _mm_setzero_si128();
658 device.rsp.cpu.vcoh = _mm_setzero_si128();
659 device.rsp.cpu.vcol = _mm_setzero_si128();
660 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
661 }
662}
663
664pub fn vcl(device: &mut crate::Device, opcode: u32) {
665 let vte = vte(device, vt(opcode), ve(opcode) as usize);
666 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
667 unsafe {
668 let mut nvt = _mm_xor_si128(vte, device.rsp.cpu.vcol);
669 nvt = _mm_sub_epi16(nvt, device.rsp.cpu.vcol);
670 let diff = _mm_sub_epi16(vs_reg, nvt);
671
672 let ncarry = _mm_cmpeq_epi16(diff, _mm_adds_epu16(vs_reg, vte));
673 let nvce = _mm_cmpeq_epi16(device.rsp.cpu.vce, _mm_setzero_si128());
674 let diff0 = _mm_cmpeq_epi16(diff, _mm_setzero_si128());
675
676 let lec1 = _mm_and_si128(_mm_and_si128(diff0, ncarry), nvce);
677 let lec2 = _mm_and_si128(_mm_or_si128(diff0, ncarry), device.rsp.cpu.vce);
678 let leeq = _mm_or_si128(lec1, lec2);
679
680 let geeq = _mm_cmpeq_epi16(_mm_subs_epu16(vte, vs_reg), _mm_setzero_si128());
681
682 let le_sel = _mm_andnot_si128(device.rsp.cpu.vcoh, device.rsp.cpu.vcol);
683 let le = _mm_blendv_epi8(device.rsp.cpu.vccl, leeq, le_sel);
684
685 let ge_sel = _mm_or_si128(device.rsp.cpu.vcol, device.rsp.cpu.vcoh);
686 let ge = _mm_blendv_epi8(geeq, device.rsp.cpu.vcch, ge_sel);
687
688 let mask = _mm_blendv_epi8(ge, le, device.rsp.cpu.vcol);
689 device.rsp.cpu.accl = _mm_blendv_epi8(vs_reg, nvt, mask);
690
691 device.rsp.cpu.vcch = ge;
692 device.rsp.cpu.vccl = le;
693 device.rsp.cpu.vcoh = _mm_setzero_si128();
694 device.rsp.cpu.vcol = _mm_setzero_si128();
695 device.rsp.cpu.vce = _mm_setzero_si128();
696 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
697 }
698}
699
700pub fn vch(device: &mut crate::Device, opcode: u32) {
701 let vte = vte(device, vt(opcode), ve(opcode) as usize);
702 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
703 unsafe {
704 device.rsp.cpu.vcol = _mm_cmplt_epi16(_mm_xor_si128(vs_reg, vte), _mm_setzero_si128());
705
706 let mut nvt = _mm_xor_si128(vte, device.rsp.cpu.vcol);
707 nvt = _mm_sub_epi16(nvt, device.rsp.cpu.vcol);
708 let diff = _mm_sub_epi16(vs_reg, nvt);
709 let diff0 = _mm_cmpeq_epi16(diff, _mm_setzero_si128());
710 let vtn = _mm_cmplt_epi16(vte, _mm_setzero_si128());
711
712 let dlez = _mm_cmpeq_epi16(
713 _mm_setzero_si128(),
714 _mm_cmpgt_epi16(diff, _mm_setzero_si128()),
715 );
716 let dgez = _mm_or_si128(_mm_cmpgt_epi16(diff, _mm_setzero_si128()), diff0);
717
718 device.rsp.cpu.vcch = _mm_blendv_epi8(dgez, vtn, device.rsp.cpu.vcol);
719 device.rsp.cpu.vccl = _mm_blendv_epi8(vtn, dlez, device.rsp.cpu.vcol);
720 device.rsp.cpu.vce = _mm_and_si128(
721 _mm_cmpeq_epi16(diff, device.rsp.cpu.vcol),
722 device.rsp.cpu.vcol,
723 );
724 device.rsp.cpu.vcoh =
725 _mm_cmpeq_epi16(_mm_or_si128(diff0, device.rsp.cpu.vce), _mm_setzero_si128());
726
727 let mask = _mm_blendv_epi8(
728 device.rsp.cpu.vcch,
729 device.rsp.cpu.vccl,
730 device.rsp.cpu.vcol,
731 );
732 device.rsp.cpu.accl = _mm_blendv_epi8(vs_reg, nvt, mask);
733 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
734 }
735}
736
737pub fn vcr(device: &mut crate::Device, opcode: u32) {
738 let vte = vte(device, vt(opcode), ve(opcode) as usize);
739 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
740 unsafe {
741 let sign = _mm_srai_epi16(_mm_xor_si128(vs_reg, vte), 15);
742 let dlez = _mm_add_epi16(_mm_and_si128(vs_reg, sign), vte);
743 device.rsp.cpu.vccl = _mm_srai_epi16(dlez, 15);
744
745 let dgez = _mm_min_epi16(_mm_or_si128(vs_reg, sign), vte);
746 device.rsp.cpu.vcch = _mm_cmpeq_epi16(dgez, vte);
747
748 let nvt = _mm_xor_si128(vte, sign);
749 let mask = _mm_blendv_epi8(device.rsp.cpu.vcch, device.rsp.cpu.vccl, sign);
750 device.rsp.cpu.accl = _mm_blendv_epi8(vs_reg, nvt, mask);
751 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
752
753 device.rsp.cpu.vcol = _mm_setzero_si128();
754 device.rsp.cpu.vcoh = _mm_setzero_si128();
755 device.rsp.cpu.vce = _mm_setzero_si128();
756 }
757}
758
759pub fn vmrg(device: &mut crate::Device, opcode: u32) {
760 let vte = vte(device, vt(opcode), ve(opcode) as usize);
761 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
762 unsafe {
763 device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl);
764 device.rsp.cpu.vcoh = _mm_setzero_si128();
765 device.rsp.cpu.vcol = _mm_setzero_si128();
766 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
767 }
768}
769
770pub fn vand(device: &mut crate::Device, opcode: u32) {
771 let vte = vte(device, vt(opcode), ve(opcode) as usize);
772 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
773 unsafe {
774 device.rsp.cpu.accl = _mm_and_si128(vs_reg, vte);
775 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
776 }
777}
778
779pub fn vnand(device: &mut crate::Device, opcode: u32) {
780 let vte = vte(device, vt(opcode), ve(opcode) as usize);
781 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
782 unsafe {
783 let and_result = _mm_and_si128(vs_reg, vte);
784 device.rsp.cpu.accl = _mm_xor_si128(and_result, _mm_set1_epi32(-1));
785 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
786 }
787}
788
789pub fn vor(device: &mut crate::Device, opcode: u32) {
790 let vte = vte(device, vt(opcode), ve(opcode) as usize);
791 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
792 unsafe {
793 device.rsp.cpu.accl = _mm_or_si128(vs_reg, vte);
794 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
795 }
796}
797
798pub fn vnor(device: &mut crate::Device, opcode: u32) {
799 let vte = vte(device, vt(opcode), ve(opcode) as usize);
800 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
801 unsafe {
802 let or_result = _mm_or_si128(vs_reg, vte);
803 device.rsp.cpu.accl = _mm_xor_si128(or_result, _mm_set1_epi32(-1));
804 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
805 }
806}
807
808pub fn vxor(device: &mut crate::Device, opcode: u32) {
809 let vte = vte(device, vt(opcode), ve(opcode) as usize);
810 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
811 unsafe {
812 device.rsp.cpu.accl = _mm_xor_si128(vs_reg, vte);
813 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
814 }
815}
816
817pub fn vnxor(device: &mut crate::Device, opcode: u32) {
818 let vte = vte(device, vt(opcode), ve(opcode) as usize);
819 let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize];
820 unsafe {
821 let xor_result = _mm_xor_si128(vs_reg, vte);
822 device.rsp.cpu.accl = _mm_xor_si128(xor_result, _mm_set1_epi32(-1));
823 device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl;
824 }
825}
826
827pub fn vrcp(device: &mut crate::Device, opcode: u32) {
828 let vte = vte(device, vt(opcode), ve(opcode) as usize);
829 let input = get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16 as i32;
830 let result = compute_reciprocal(input, &device.rsp.cpu.reciprocals);
831
832 device.rsp.cpu.divdp = false;
833 device.rsp.cpu.divout = (result >> 16) as i16;
834 device.rsp.cpu.accl = vte;
835 modify_vpr16(
836 &mut device.rsp.cpu.vpr[vd(opcode) as usize],
837 de(opcode) as u8,
838 result as u16,
839 );
840}
841
842pub fn vrcpl(device: &mut crate::Device, opcode: u32) {
843 let vte = vte(device, vt(opcode), ve(opcode) as usize);
844 let input = if device.rsp.cpu.divdp {
845 ((device.rsp.cpu.divin as i32) << 16)
846 | get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as u16 as i32
847 } else {
848 get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16 as i32
849 };
850 let result = compute_reciprocal(input, &device.rsp.cpu.reciprocals);
851
852 device.rsp.cpu.divdp = false;
853 device.rsp.cpu.divout = (result >> 16) as i16;
854 device.rsp.cpu.accl = vte;
855 modify_vpr16(
856 &mut device.rsp.cpu.vpr[vd(opcode) as usize],
857 de(opcode) as u8,
858 result as u16,
859 );
860}
861
862pub fn vrcph(device: &mut crate::Device, opcode: u32) {
863 let vte = vte(device, vt(opcode), ve(opcode) as usize);
864 let vt_reg = device.rsp.cpu.vpr[vt(opcode) as usize];
865 let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize];
866
867 device.rsp.cpu.accl = vte;
868 device.rsp.cpu.divdp = true;
869 device.rsp.cpu.divin = get_vpr16(vt_reg, ve(opcode) as u8) as i16;
870
871 modify_vpr16(vd_reg, de(opcode) as u8, device.rsp.cpu.divout as u16);
872}
873
874pub fn vmov(device: &mut crate::Device, opcode: u32) {
875 let vte = vte(device, vt(opcode), ve(opcode) as usize);
876 let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize];
877 let de_index = de(opcode) as u8;
878
879 let value = get_vpr16(vte, de_index);
880 modify_vpr16(vd_reg, de_index, value);
881 device.rsp.cpu.accl = vte;
882}
883
884pub fn vrsq(device: &mut crate::Device, opcode: u32) {
885 let vte = vte(device, vt(opcode), ve(opcode) as usize);
886 let input = get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16 as i32;
887 let result = compute_inverse_sqrt(input, &device.rsp.cpu.inverse_square_roots);
888
889 device.rsp.cpu.divdp = false;
890 device.rsp.cpu.divout = (result >> 16) as i16;
891 device.rsp.cpu.accl = vte;
892 modify_vpr16(
893 &mut device.rsp.cpu.vpr[vd(opcode) as usize],
894 de(opcode) as u8,
895 result as u16,
896 );
897}
898
899pub fn vrsql(device: &mut crate::Device, opcode: u32) {
900 let vte = vte(device, vt(opcode), ve(opcode) as usize);
901 let input = if device.rsp.cpu.divdp {
902 ((device.rsp.cpu.divin as i32) << 16)
903 | get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as u16 as i32
904 } else {
905 get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16 as i32
906 };
907 let result = compute_inverse_sqrt(input, &device.rsp.cpu.inverse_square_roots);
908
909 device.rsp.cpu.divdp = false;
910 device.rsp.cpu.divout = (result >> 16) as i16;
911 device.rsp.cpu.accl = vte;
912 modify_vpr16(
913 &mut device.rsp.cpu.vpr[vd(opcode) as usize],
914 de(opcode) as u8,
915 result as u16,
916 );
917}
918
919pub fn vrsqh(device: &mut crate::Device, opcode: u32) {
920 let vte = vte(device, vt(opcode), ve(opcode) as usize);
921 let vt_reg = device.rsp.cpu.vpr[vt(opcode) as usize];
922 let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize];
923
924 device.rsp.cpu.accl = vte;
925 device.rsp.cpu.divdp = true;
926 device.rsp.cpu.divin = get_vpr16(vt_reg, ve(opcode) as u8) as i16;
927
928 modify_vpr16(vd_reg, de(opcode) as u8, device.rsp.cpu.divout as u16);
929}
930
931pub fn vnop(_device: &mut crate::Device, _opcode: u32) {}
932
933pub fn execute_vec(device: &mut crate::Device, opcode: u32) {
934 device.rsp.cpu.instruction_type = crate::cpu::InstructionType::Vu;
935 device.rsp.cpu.vec_instrs[(opcode & 0x3F) as usize](device, opcode)
936}
937
938pub fn reserved(_device: &mut crate::Device, _opcode: u32) {
939 panic!("rsp vu reserved")
940}