diff --git a/build.rs b/build.rs index d23c4ffe..399adf9c 100644 --- a/build.rs +++ b/build.rs @@ -164,6 +164,7 @@ fn main() { .allowlist_function("_mm_cmplt_epi16") .allowlist_function("_mm_subs_epu16") .allowlist_function("_mm_set1_epi32") + .allowlist_function("_mm_set1_epi16") .blocklist_type("__m128i") .blocklist_type("int64x2_t") .wrap_static_fns(true) diff --git a/src/device/rsp_vu_instructions.rs b/src/device/rsp_vu_instructions.rs index 15de7e4b..5d961a9c 100644 --- a/src/device/rsp_vu_instructions.rs +++ b/src/device/rsp_vu_instructions.rs @@ -38,9 +38,47 @@ fn clamp_signed_64(value: i64) -> i16 { } fn s_clip(x: i64, bits: u32) -> i64 { - let b = 1_u64 << (bits - 1); - let m = b * 2 - 1; - ((((x as u64) & m) ^ b).wrapping_sub(b)) as i64 + let mask = (1i64 << bits) - 1; + let value = x & mask; + (value << (64 - bits)) >> (64 - bits) +} + +fn compute_reciprocal(input: i32, reciprocals: &[u16]) -> u32 { + let mask = input >> 31; + let mut data = input ^ mask; + if input > -32768 { + data -= mask + } + if data == 0 { + 0x7fffffff + } else if input == -32768 { + 0xffff0000 + } else { + let shift = (data as u32).leading_zeros(); + let index = (((data as u64) << shift) & 0x7fc00000) >> 22; + let mut result = reciprocals[index as usize] as u32; + result = (0x10000 | result) << 14; + (result >> (31 - shift)) ^ mask as u32 + } +} + +fn compute_inverse_sqrt(input: i32, inverse_square_roots: &[u16]) -> u32 { + let mask = input >> 31; + let mut data = input ^ mask; + if input > -32768 { + data -= mask + } + if data == 0 { + 0x7fffffff + } else if input == -32768 { + 0xffff0000 + } else { + let shift = (data as u32).leading_zeros(); + let index = (((data as u64) << shift) & 0x7fc00000) as u32 >> 22; + let mut result = inverse_square_roots[((index & 0x1fe) | (shift & 1)) as usize] as u32; + result = (0x10000 | result) << 14; + (result >> ((31 - shift) >> 1)) ^ mask as u32 + } } fn vte(device: &device::Device, vt: u32, index: usize) -> __m128i { @@ -54,23 +92,22 @@ fn vte(device: &device::Device, vt: u32, index: usize) -> __m128i { pub fn vmulf(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut lo, mut hi, mut round, mut sign1, sign2, neq, eq, neg); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - lo = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - round = _mm_cmpeq_epi16(_mm_setzero_si128(), _mm_setzero_si128()); - sign1 = _mm_srli_epi16(lo, 15); - lo = _mm_add_epi16(lo, lo); - round = _mm_slli_epi16(round, 15); - hi = _mm_mulhi_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - sign2 = _mm_srli_epi16(lo, 15); - device.rsp.cpu.accl = _mm_add_epi16(round, lo); - sign1 = _mm_add_epi16(sign1, sign2); - hi = _mm_slli_epi16(hi, 1); - neq = _mm_cmpeq_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.accm = _mm_add_epi16(hi, sign1); - neg = _mm_srai_epi16(device.rsp.cpu.accm, 15); + let lo = _mm_mullo_epi16(vs_reg, vte); + let hi = _mm_mulhi_epi16(vs_reg, vte); + + let sign1 = _mm_srli_epi16(lo, 15); + let lo_doubled = _mm_add_epi16(lo, lo); + let sign2 = _mm_srli_epi16(lo_doubled, 15); + + device.rsp.cpu.accl = _mm_add_epi16(_mm_set1_epi16(-32768_i16), lo_doubled); // round + lo + device.rsp.cpu.accm = _mm_add_epi16(_mm_slli_epi16(hi, 1), _mm_add_epi16(sign1, sign2)); + let neg = _mm_srai_epi16(device.rsp.cpu.accm, 15); + + let neq = _mm_cmpeq_epi16(vs_reg, vte); + let eq = _mm_and_si128(neq, neg); - eq = _mm_and_si128(neq, neg); device.rsp.cpu.acch = _mm_andnot_si128(neq, neg); device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_add_epi16(device.rsp.cpu.accm, eq); } @@ -78,25 +115,24 @@ pub fn vmulf(device: &mut device::Device, opcode: u32) { pub fn vmulu(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut lo, mut hi, mut round, mut sign1, sign2, neq, neg); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - lo = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - round = _mm_cmpeq_epi16(_mm_setzero_si128(), _mm_setzero_si128()); - sign1 = _mm_srli_epi16(lo, 15); - lo = _mm_add_epi16(lo, lo); - round = _mm_slli_epi16(round, 15); - hi = _mm_mulhi_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - sign2 = _mm_srli_epi16(lo, 15); - device.rsp.cpu.accl = _mm_add_epi16(round, lo); - sign1 = _mm_add_epi16(sign1, sign2); - hi = _mm_slli_epi16(hi, 1); - neq = _mm_cmpeq_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.accm = _mm_add_epi16(hi, sign1); - neg = _mm_srai_epi16(device.rsp.cpu.accm, 15); + let lo = _mm_mullo_epi16(vs_reg, vte); + let hi = _mm_mulhi_epi16(vs_reg, vte); + + let sign1 = _mm_srli_epi16(lo, 15); + let lo_doubled = _mm_add_epi16(lo, lo); + let sign2 = _mm_srli_epi16(lo_doubled, 15); + + device.rsp.cpu.accl = _mm_add_epi16(_mm_set1_epi16(-32768_i16), lo_doubled); // round + lo + device.rsp.cpu.accm = _mm_add_epi16(_mm_slli_epi16(hi, 1), _mm_add_epi16(sign1, sign2)); + let neg = _mm_srai_epi16(device.rsp.cpu.accm, 15); + + let neq = _mm_cmpeq_epi16(vs_reg, vte); device.rsp.cpu.acch = _mm_andnot_si128(neq, neg); - hi = _mm_or_si128(device.rsp.cpu.accm, neg); - device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_andnot_si128(device.rsp.cpu.acch, hi); + let result = _mm_or_si128(device.rsp.cpu.accm, neg); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_andnot_si128(device.rsp.cpu.acch, result); } } @@ -105,10 +141,12 @@ pub fn vrndp(device: &mut device::Device, opcode: u32) { let acch: &mut __m128i = &mut device.rsp.cpu.acch; let accm: &mut __m128i = &mut device.rsp.cpu.accm; let accl: &mut __m128i = &mut device.rsp.cpu.accl; + let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize]; + let shift_amount = vs(opcode) & 1; for n in 0..8 { let mut product = get_vpr16(vte, n) as i16 as i32; - if vs(opcode) & 1 != 0 { + if shift_amount != 0 { product <<= 16 } let mut acc = 0; @@ -125,11 +163,7 @@ pub fn vrndp(device: &mut device::Device, opcode: u32) { modify_vpr16(acch, n, (acc >> 32) as u16); modify_vpr16(accm, n, (acc >> 16) as u16); modify_vpr16(accl, n, acc as u16); - modify_vpr16( - &mut device.rsp.cpu.vpr[vd(opcode) as usize], - n, - clamp_signed_64(acc >> 16) as u16, - ); + modify_vpr16(vd_reg, n, clamp_signed_64(acc >> 16) as u16); } } @@ -138,28 +172,27 @@ pub fn vmulq(device: &mut device::Device, opcode: u32) { let acch: &mut __m128i = &mut device.rsp.cpu.acch; let accm: &mut __m128i = &mut device.rsp.cpu.accm; let accl: &mut __m128i = &mut device.rsp.cpu.accl; + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; + let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize]; for n in 0..8 { - let mut product = (get_vpr16(device.rsp.cpu.vpr[vs(opcode) as usize], n) as i16 as i32) - .wrapping_mul(get_vpr16(vte, n) as i16 as i32); + let mut product = + (get_vpr16(vs_reg, n) as i16 as i32).wrapping_mul(get_vpr16(vte, n) as i16 as i32); if product < 0 { product += 31; } modify_vpr16(acch, n, (product >> 16) as u16); - modify_vpr16(accm, n, (product) as u16); + modify_vpr16(accm, n, product as u16); modify_vpr16(accl, n, 0); - modify_vpr16( - &mut device.rsp.cpu.vpr[vd(opcode) as usize], - n, - (clamp_signed_32(product >> 1) & !15) as u16, - ); + modify_vpr16(vd_reg, n, (clamp_signed_32(product >> 1) & !15) as u16); } } pub fn vmudl(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_mulhi_epu16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); + device.rsp.cpu.accl = _mm_mulhi_epu16(vs_reg, vte); device.rsp.cpu.accm = _mm_setzero_si128(); device.rsp.cpu.acch = _mm_setzero_si128(); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; @@ -168,12 +201,12 @@ pub fn vmudl(device: &mut device::Device, opcode: u32) { pub fn vmudm(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (sign, vta); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.accm = _mm_mulhi_epu16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - sign = _mm_srai_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], 15); - vta = _mm_and_si128(vte, sign); + device.rsp.cpu.accl = _mm_mullo_epi16(vs_reg, vte); + device.rsp.cpu.accm = _mm_mulhi_epu16(vs_reg, vte); + let sign = _mm_srai_epi16(vs_reg, 15); + let vta = _mm_and_si128(vte, sign); device.rsp.cpu.accm = _mm_sub_epi16(device.rsp.cpu.accm, vta); device.rsp.cpu.acch = _mm_srai_epi16(device.rsp.cpu.accm, 15); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accm; @@ -182,12 +215,12 @@ pub fn vmudm(device: &mut device::Device, opcode: u32) { pub fn vmudn(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (sign, vsa); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.accm = _mm_mulhi_epu16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - sign = _mm_srai_epi16(vte, 15); - vsa = _mm_and_si128(device.rsp.cpu.vpr[vs(opcode) as usize], sign); + device.rsp.cpu.accl = _mm_mullo_epi16(vs_reg, vte); + device.rsp.cpu.accm = _mm_mulhi_epu16(vs_reg, vte); + let sign = _mm_srai_epi16(vte, 15); + let vsa = _mm_and_si128(vs_reg, sign); device.rsp.cpu.accm = _mm_sub_epi16(device.rsp.cpu.accm, vsa); device.rsp.cpu.acch = _mm_srai_epi16(device.rsp.cpu.accm, 15); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; @@ -196,81 +229,91 @@ pub fn vmudn(device: &mut device::Device, opcode: u32) { pub fn vmudh(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (lo, hi); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { device.rsp.cpu.accl = _mm_setzero_si128(); - device.rsp.cpu.accm = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.acch = _mm_mulhi_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - lo = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); - hi = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); + device.rsp.cpu.accm = _mm_mullo_epi16(vs_reg, vte); + device.rsp.cpu.acch = _mm_mulhi_epi16(vs_reg, vte); + let lo = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); + let hi = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo, hi); } } pub fn vmacf(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut lo, mut md, mut hi, mut carry, mut omask); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - lo = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - hi = _mm_mulhi_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - md = _mm_slli_epi16(hi, 1); - carry = _mm_srli_epi16(lo, 15); - hi = _mm_srai_epi16(hi, 15); - md = _mm_or_si128(md, carry); - lo = _mm_slli_epi16(lo, 1); - omask = _mm_adds_epu16(device.rsp.cpu.accl, lo); - device.rsp.cpu.accl = _mm_add_epi16(device.rsp.cpu.accl, lo); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accl, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - md = _mm_sub_epi16(md, omask); - carry = _mm_cmpeq_epi16(md, _mm_setzero_si128()); - carry = _mm_and_si128(carry, omask); - hi = _mm_sub_epi16(hi, carry); - omask = _mm_adds_epu16(device.rsp.cpu.accm, md); - device.rsp.cpu.accm = _mm_add_epi16(device.rsp.cpu.accm, md); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accm, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi); - device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, omask); + let lo = _mm_mullo_epi16(vs_reg, vte); + let hi = _mm_mulhi_epi16(vs_reg, vte); - lo = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); - hi = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); - device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo, hi); + let carry = _mm_srli_epi16(lo, 15); + let md = _mm_or_si128(_mm_slli_epi16(hi, 1), carry); + let lo_doubled = _mm_slli_epi16(lo, 1); + let hi_sign = _mm_srai_epi16(hi, 15); + + let accl_old = device.rsp.cpu.accl; + device.rsp.cpu.accl = _mm_add_epi16(accl_old, lo_doubled); + let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, lo_doubled), device.rsp.cpu.accl); + let borrow_from_l = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128()); + + let md_adjusted = _mm_sub_epi16(md, borrow_from_l); + let zero_md = _mm_cmpeq_epi16(md_adjusted, _mm_setzero_si128()); + let borrow_to_h = _mm_and_si128(zero_md, borrow_from_l); + let hi_adjusted = _mm_sub_epi16(hi_sign, borrow_to_h); + + let accm_old = device.rsp.cpu.accm; + device.rsp.cpu.accm = _mm_add_epi16(accm_old, md_adjusted); + let overflow_m = + _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, md_adjusted), device.rsp.cpu.accm); + let borrow_from_m = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128()); + + device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi_adjusted); + device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_from_m); + + let lo_packed = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); + let hi_packed = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo_packed, hi_packed); } } pub fn vmacu(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut lo, mut md, mut hi, mut carry, mut omask, mmask, hmask); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - lo = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - hi = _mm_mulhi_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - md = _mm_slli_epi16(hi, 1); - carry = _mm_srli_epi16(lo, 15); - hi = _mm_srai_epi16(hi, 15); - md = _mm_or_si128(md, carry); - lo = _mm_slli_epi16(lo, 1); - omask = _mm_adds_epu16(device.rsp.cpu.accl, lo); - device.rsp.cpu.accl = _mm_add_epi16(device.rsp.cpu.accl, lo); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accl, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - md = _mm_sub_epi16(md, omask); - carry = _mm_cmpeq_epi16(md, _mm_setzero_si128()); - carry = _mm_and_si128(carry, omask); - hi = _mm_sub_epi16(hi, carry); - omask = _mm_adds_epu16(device.rsp.cpu.accm, md); - device.rsp.cpu.accm = _mm_add_epi16(device.rsp.cpu.accm, md); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accm, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi); - device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, omask); + let lo = _mm_mullo_epi16(vs_reg, vte); + let hi = _mm_mulhi_epi16(vs_reg, vte); - mmask = _mm_srai_epi16(device.rsp.cpu.accm, 15); - hmask = _mm_srai_epi16(device.rsp.cpu.acch, 15); - md = _mm_or_si128(mmask, device.rsp.cpu.accm); - omask = _mm_cmpgt_epi16(device.rsp.cpu.acch, _mm_setzero_si128()); - md = _mm_andnot_si128(hmask, md); - device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_or_si128(omask, md); + let carry = _mm_srli_epi16(lo, 15); + let md = _mm_or_si128(_mm_slli_epi16(hi, 1), carry); + let lo_doubled = _mm_slli_epi16(lo, 1); + let hi_sign = _mm_srai_epi16(hi, 15); + + let accl_old = device.rsp.cpu.accl; + device.rsp.cpu.accl = _mm_add_epi16(accl_old, lo_doubled); + let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, lo_doubled), device.rsp.cpu.accl); + let borrow_from_l = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128()); + + let md_adjusted = _mm_sub_epi16(md, borrow_from_l); + let zero_md = _mm_cmpeq_epi16(md_adjusted, _mm_setzero_si128()); + let borrow_to_h = _mm_and_si128(zero_md, borrow_from_l); + let hi_adjusted = _mm_sub_epi16(hi_sign, borrow_to_h); + + let accm_old = device.rsp.cpu.accm; + device.rsp.cpu.accm = _mm_add_epi16(accm_old, md_adjusted); + let overflow_m = + _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, md_adjusted), device.rsp.cpu.accm); + let borrow_from_m = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128()); + + device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi_adjusted); + device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_from_m); + + let mmask = _mm_srai_epi16(device.rsp.cpu.accm, 15); + let hmask = _mm_srai_epi16(device.rsp.cpu.acch, 15); + let md_result = _mm_or_si128(mmask, device.rsp.cpu.accm); + let positive = _mm_cmpgt_epi16(device.rsp.cpu.acch, _mm_setzero_si128()); + let final_result = _mm_andnot_si128(hmask, md_result); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_or_si128(positive, final_result); } } @@ -279,10 +322,12 @@ pub fn vrndn(device: &mut device::Device, opcode: u32) { let acch: &mut __m128i = &mut device.rsp.cpu.acch; let accm: &mut __m128i = &mut device.rsp.cpu.accm; let accl: &mut __m128i = &mut device.rsp.cpu.accl; + let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize]; + let shift_amount = vs(opcode) & 1; for n in 0..8 { let mut product = get_vpr16(vte, n) as i16 as i32; - if vs(opcode) & 1 != 0 { + if shift_amount != 0 { product <<= 16 } let mut acc = 0; @@ -299,17 +344,14 @@ pub fn vrndn(device: &mut device::Device, opcode: u32) { modify_vpr16(acch, n, (acc >> 32) as u16); modify_vpr16(accm, n, (acc >> 16) as u16); modify_vpr16(accl, n, acc as u16); - modify_vpr16( - &mut device.rsp.cpu.vpr[vd(opcode) as usize], - n, - clamp_signed_64(acc >> 16) as u16, - ); + modify_vpr16(vd_reg, n, clamp_signed_64(acc >> 16) as u16); } } pub fn vmacq(device: &mut device::Device, opcode: u32) { let acch: &mut __m128i = &mut device.rsp.cpu.acch; let accm: &mut __m128i = &mut device.rsp.cpu.accm; + let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize]; for n in 0..8 { let mut product = ((get_vpr16(*acch, n) as i32) << 16) | (get_vpr16(*accm, n) as i32); @@ -319,126 +361,145 @@ pub fn vmacq(device: &mut device::Device, opcode: u32) { product -= 32 } modify_vpr16(acch, n, (product >> 16) as u16); - modify_vpr16(accm, n, (product) as u16); - modify_vpr16( - &mut device.rsp.cpu.vpr[vd(opcode) as usize], - n, - (clamp_signed_32(product >> 1) & !15) as u16, - ); + modify_vpr16(accm, n, product as u16); + modify_vpr16(vd_reg, n, (clamp_signed_32(product >> 1) & !15) as u16); } } pub fn vmadl(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut hi, mut omask, nhi, nmd, shi, smd, cmask, cval); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - hi = _mm_mulhi_epu16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - omask = _mm_adds_epu16(device.rsp.cpu.accl, hi); - device.rsp.cpu.accl = _mm_add_epi16(device.rsp.cpu.accl, hi); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accl, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - hi = _mm_sub_epi16(_mm_setzero_si128(), omask); - omask = _mm_adds_epu16(device.rsp.cpu.accm, hi); - device.rsp.cpu.accm = _mm_add_epi16(device.rsp.cpu.accm, hi); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accm, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, omask); - nhi = _mm_srai_epi16(device.rsp.cpu.acch, 15); - nmd = _mm_srai_epi16(device.rsp.cpu.accm, 15); - shi = _mm_cmpeq_epi16(nhi, device.rsp.cpu.acch); - smd = _mm_cmpeq_epi16(nhi, nmd); - cmask = _mm_and_si128(smd, shi); - cval = _mm_cmpeq_epi16(nhi, _mm_setzero_si128()); + let hi = _mm_mulhi_epu16(vs_reg, vte); + + let accl_old = device.rsp.cpu.accl; + device.rsp.cpu.accl = _mm_add_epi16(accl_old, hi); + let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, hi), device.rsp.cpu.accl); + let borrow = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128()); + + let accm_old = device.rsp.cpu.accm; + device.rsp.cpu.accm = _mm_sub_epi16(accm_old, borrow); + let overflow_m = _mm_cmpeq_epi16( + _mm_adds_epu16(accm_old, _mm_sub_epi16(_mm_setzero_si128(), borrow)), + device.rsp.cpu.accm, + ); + let borrow_h = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128()); + + device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_h); + + let nhi = _mm_srai_epi16(device.rsp.cpu.acch, 15); + let nmd = _mm_srai_epi16(device.rsp.cpu.accm, 15); + let shi = _mm_cmpeq_epi16(nhi, device.rsp.cpu.acch); + let smd = _mm_cmpeq_epi16(nhi, nmd); + let cmask = _mm_and_si128(smd, shi); + let cval = _mm_cmpeq_epi16(nhi, _mm_setzero_si128()); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_blendv_epi8(cval, device.rsp.cpu.accl, cmask); } } pub fn vmadm(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut lo, mut hi, sign, vta, mut omask); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - lo = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - hi = _mm_mulhi_epu16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - sign = _mm_srai_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], 15); - vta = _mm_and_si128(vte, sign); + let lo = _mm_mullo_epi16(vs_reg, vte); + let mut hi = _mm_mulhi_epu16(vs_reg, vte); + let sign = _mm_srai_epi16(vs_reg, 15); + let vta = _mm_and_si128(vte, sign); hi = _mm_sub_epi16(hi, vta); - omask = _mm_adds_epu16(device.rsp.cpu.accl, lo); - device.rsp.cpu.accl = _mm_add_epi16(device.rsp.cpu.accl, lo); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accl, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - hi = _mm_sub_epi16(hi, omask); - omask = _mm_adds_epu16(device.rsp.cpu.accm, hi); - device.rsp.cpu.accm = _mm_add_epi16(device.rsp.cpu.accm, hi); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accm, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - hi = _mm_srai_epi16(hi, 15); - device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi); - device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, omask); - lo = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); - hi = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); - device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo, hi); + + let accl_old = device.rsp.cpu.accl; + device.rsp.cpu.accl = _mm_add_epi16(accl_old, lo); + let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, lo), device.rsp.cpu.accl); + let borrow = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128()); + + hi = _mm_sub_epi16(hi, borrow); + + let accm_old = device.rsp.cpu.accm; + device.rsp.cpu.accm = _mm_add_epi16(accm_old, hi); + let overflow_m = _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, hi), device.rsp.cpu.accm); + let borrow_h = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128()); + + let hi_sign = _mm_srai_epi16(hi, 15); + device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi_sign); + device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_h); + + let lo_packed = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); + let hi_packed = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo_packed, hi_packed); } } pub fn vmadn(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (lo, mut hi, sign, vsa, mut omask, nhi, nmd, shi, smd, cmask, cval); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - lo = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - hi = _mm_mulhi_epu16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - sign = _mm_srai_epi16(vte, 15); - vsa = _mm_and_si128(device.rsp.cpu.vpr[vs(opcode) as usize], sign); + let lo = _mm_mullo_epi16(vs_reg, vte); + let mut hi = _mm_mulhi_epu16(vs_reg, vte); + let sign = _mm_srai_epi16(vte, 15); + let vsa = _mm_and_si128(vs_reg, sign); hi = _mm_sub_epi16(hi, vsa); - omask = _mm_adds_epu16(device.rsp.cpu.accl, lo); - device.rsp.cpu.accl = _mm_add_epi16(device.rsp.cpu.accl, lo); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accl, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - hi = _mm_sub_epi16(hi, omask); - omask = _mm_adds_epu16(device.rsp.cpu.accm, hi); - device.rsp.cpu.accm = _mm_add_epi16(device.rsp.cpu.accm, hi); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accm, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - hi = _mm_srai_epi16(hi, 15); - device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi); - device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, omask); - nhi = _mm_srai_epi16(device.rsp.cpu.acch, 15); - nmd = _mm_srai_epi16(device.rsp.cpu.accm, 15); - shi = _mm_cmpeq_epi16(nhi, device.rsp.cpu.acch); - smd = _mm_cmpeq_epi16(nhi, nmd); - cmask = _mm_and_si128(smd, shi); - cval = _mm_cmpeq_epi16(nhi, _mm_setzero_si128()); + + let accl_old = device.rsp.cpu.accl; + device.rsp.cpu.accl = _mm_add_epi16(accl_old, lo); + let overflow_l = _mm_cmpeq_epi16(_mm_adds_epu16(accl_old, lo), device.rsp.cpu.accl); + let borrow = _mm_cmpeq_epi16(overflow_l, _mm_setzero_si128()); + + hi = _mm_sub_epi16(hi, borrow); + + let accm_old = device.rsp.cpu.accm; + device.rsp.cpu.accm = _mm_add_epi16(accm_old, hi); + let overflow_m = _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, hi), device.rsp.cpu.accm); + let borrow_h = _mm_cmpeq_epi16(overflow_m, _mm_setzero_si128()); + + let hi_sign = _mm_srai_epi16(hi, 15); + device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi_sign); + device.rsp.cpu.acch = _mm_sub_epi16(device.rsp.cpu.acch, borrow_h); + + let nhi = _mm_srai_epi16(device.rsp.cpu.acch, 15); + let nmd = _mm_srai_epi16(device.rsp.cpu.accm, 15); + let shi = _mm_cmpeq_epi16(nhi, device.rsp.cpu.acch); + let smd = _mm_cmpeq_epi16(nhi, nmd); + let cmask = _mm_and_si128(smd, shi); + let cval = _mm_cmpeq_epi16(nhi, _mm_setzero_si128()); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_blendv_epi8(cval, device.rsp.cpu.accl, cmask); } } pub fn vmadh(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut lo, mut hi, mut omask); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - lo = _mm_mullo_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - hi = _mm_mulhi_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - omask = _mm_adds_epu16(device.rsp.cpu.accm, lo); - device.rsp.cpu.accm = _mm_add_epi16(device.rsp.cpu.accm, lo); - omask = _mm_cmpeq_epi16(device.rsp.cpu.accm, omask); - omask = _mm_cmpeq_epi16(omask, _mm_setzero_si128()); - hi = _mm_sub_epi16(hi, omask); + let lo = _mm_mullo_epi16(vs_reg, vte); + let mut hi = _mm_mulhi_epi16(vs_reg, vte); + + let accm_old = device.rsp.cpu.accm; + device.rsp.cpu.accm = _mm_add_epi16(accm_old, lo); + let overflow = _mm_cmpeq_epi16(_mm_adds_epu16(accm_old, lo), device.rsp.cpu.accm); + let borrow = _mm_cmpeq_epi16(overflow, _mm_setzero_si128()); + + hi = _mm_sub_epi16(hi, borrow); device.rsp.cpu.acch = _mm_add_epi16(device.rsp.cpu.acch, hi); - lo = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); - hi = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); - device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo, hi); + + let lo_packed = _mm_unpacklo_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); + let hi_packed = _mm_unpackhi_epi16(device.rsp.cpu.accm, device.rsp.cpu.acch); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_packs_epi32(lo_packed, hi_packed); } } pub fn vadd(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (sum, mut min, max); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - sum = _mm_add_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); + let sum = _mm_add_epi16(vs_reg, vte); device.rsp.cpu.accl = _mm_sub_epi16(sum, device.rsp.cpu.vcol); - min = _mm_min_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - max = _mm_max_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - min = _mm_subs_epi16(min, device.rsp.cpu.vcol); - device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_adds_epi16(min, max); + + let min = _mm_min_epi16(vs_reg, vte); + let max = _mm_max_epi16(vs_reg, vte); + let min_adjusted = _mm_subs_epi16(min, device.rsp.cpu.vcol); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_adds_epi16(min_adjusted, max); + device.rsp.cpu.vcol = _mm_setzero_si128(); device.rsp.cpu.vcoh = _mm_setzero_si128(); } @@ -446,16 +507,16 @@ pub fn vadd(device: &mut device::Device, opcode: u32) { pub fn vsub(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (udiff, sdiff, ov); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - udiff = _mm_sub_epi16(vte, device.rsp.cpu.vcol); - sdiff = _mm_subs_epi16(vte, device.rsp.cpu.vcol); - device.rsp.cpu.accl = _mm_sub_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], udiff); - ov = _mm_cmpgt_epi16(sdiff, udiff); - device.rsp.cpu.vpr[vd(opcode) as usize] = - _mm_subs_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], sdiff); - device.rsp.cpu.vpr[vd(opcode) as usize] = - _mm_adds_epi16(device.rsp.cpu.vpr[vd(opcode) as usize], ov); + let udiff = _mm_sub_epi16(vte, device.rsp.cpu.vcol); + let sdiff = _mm_subs_epi16(vte, device.rsp.cpu.vcol); + device.rsp.cpu.accl = _mm_sub_epi16(vs_reg, udiff); + + let ov = _mm_cmpgt_epi16(sdiff, udiff); + let sub_result = _mm_subs_epi16(vs_reg, sdiff); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_adds_epi16(sub_result, ov); + device.rsp.cpu.vcol = _mm_setzero_si128(); device.rsp.cpu.vcoh = _mm_setzero_si128(); } @@ -463,38 +524,37 @@ pub fn vsub(device: &mut device::Device, opcode: u32) { pub fn vzero(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_add_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_xor_si128( - device.rsp.cpu.vpr[vd(opcode) as usize], - device.rsp.cpu.vpr[vd(opcode) as usize], - ); + device.rsp.cpu.accl = _mm_add_epi16(vs_reg, vte); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_setzero_si128(); } } pub fn vabs(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (vs0, slt); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - vs0 = _mm_cmpeq_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], _mm_setzero_si128()); - slt = _mm_srai_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], 15); - device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_andnot_si128(vs0, vte); - device.rsp.cpu.vpr[vd(opcode) as usize] = - _mm_xor_si128(device.rsp.cpu.vpr[vd(opcode) as usize], slt); - device.rsp.cpu.accl = _mm_sub_epi16(device.rsp.cpu.vpr[vd(opcode) as usize], slt); - device.rsp.cpu.vpr[vd(opcode) as usize] = - _mm_subs_epi16(device.rsp.cpu.vpr[vd(opcode) as usize], slt); + let vs0 = _mm_cmpeq_epi16(vs_reg, _mm_setzero_si128()); + let slt = _mm_srai_epi16(vs_reg, 15); + + let mut result = _mm_andnot_si128(vs0, vte); + result = _mm_xor_si128(result, slt); + device.rsp.cpu.accl = _mm_sub_epi16(result, slt); + device.rsp.cpu.vpr[vd(opcode) as usize] = _mm_subs_epi16(result, slt); } } pub fn vaddc(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let sum; + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - sum = _mm_adds_epu16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.accl = _mm_add_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.vcol = _mm_cmpeq_epi16(sum, device.rsp.cpu.accl); - device.rsp.cpu.vcol = _mm_cmpeq_epi16(device.rsp.cpu.vcol, _mm_setzero_si128()); + let sum = _mm_adds_epu16(vs_reg, vte); + device.rsp.cpu.accl = _mm_add_epi16(vs_reg, vte); + device.rsp.cpu.vcol = _mm_cmpeq_epi16( + _mm_cmpeq_epi16(sum, device.rsp.cpu.accl), + _mm_setzero_si128(), + ); device.rsp.cpu.vcoh = _mm_setzero_si128(); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; } @@ -502,49 +562,49 @@ pub fn vaddc(device: &mut device::Device, opcode: u32) { pub fn vsubc(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (equal, udiff, diff0); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - udiff = _mm_subs_epu16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - equal = _mm_cmpeq_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - diff0 = _mm_cmpeq_epi16(udiff, _mm_setzero_si128()); + let udiff = _mm_subs_epu16(vs_reg, vte); + let equal = _mm_cmpeq_epi16(vs_reg, vte); + let diff0 = _mm_cmpeq_epi16(udiff, _mm_setzero_si128()); + device.rsp.cpu.vcoh = _mm_cmpeq_epi16(equal, _mm_setzero_si128()); device.rsp.cpu.vcol = _mm_andnot_si128(equal, diff0); - device.rsp.cpu.accl = _mm_sub_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); + device.rsp.cpu.accl = _mm_sub_epi16(vs_reg, vte); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; } } pub fn vsar(device: &mut device::Device, opcode: u32) { + let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize]; match ve(opcode) { 0x8 => { - device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.acch; + *vd_reg = device.rsp.cpu.acch; } 0x9 => { - device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accm; + *vd_reg = device.rsp.cpu.accm; } 0xa => { - device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; + *vd_reg = device.rsp.cpu.accl; } _ => { - device.rsp.cpu.vpr[vd(opcode) as usize] = unsafe { _mm_setzero_si128() }; + *vd_reg = unsafe { _mm_setzero_si128() }; } } } pub fn vlt(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut eq, lt); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - eq = _mm_cmpeq_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - lt = _mm_cmplt_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - eq = _mm_and_si128(device.rsp.cpu.vcoh, eq); - eq = _mm_and_si128(device.rsp.cpu.vcol, eq); - device.rsp.cpu.vccl = _mm_or_si128(lt, eq); - device.rsp.cpu.accl = _mm_blendv_epi8( - vte, - device.rsp.cpu.vpr[vs(opcode) as usize], - device.rsp.cpu.vccl, - ); + let eq = _mm_cmpeq_epi16(vs_reg, vte); + let lt = _mm_cmplt_epi16(vs_reg, vte); + let eq_and_carry = + _mm_and_si128(_mm_and_si128(device.rsp.cpu.vcoh, eq), device.rsp.cpu.vcol); + + device.rsp.cpu.vccl = _mm_or_si128(lt, eq_and_carry); + device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl); + device.rsp.cpu.vcch = _mm_setzero_si128(); device.rsp.cpu.vcoh = _mm_setzero_si128(); device.rsp.cpu.vcol = _mm_setzero_si128(); @@ -554,16 +614,13 @@ pub fn vlt(device: &mut device::Device, opcode: u32) { pub fn veq(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let eq; + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - eq = _mm_cmpeq_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); + let eq = _mm_cmpeq_epi16(vs_reg, vte); device.rsp.cpu.vccl = _mm_andnot_si128(device.rsp.cpu.vcoh, eq); - device.rsp.cpu.accl = _mm_blendv_epi8( - vte, - device.rsp.cpu.vpr[vs(opcode) as usize], - device.rsp.cpu.vccl, - ); - device.rsp.cpu.vcch = _mm_setzero_si128(); //unverified + device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl); + + device.rsp.cpu.vcch = _mm_setzero_si128(); device.rsp.cpu.vcoh = _mm_setzero_si128(); device.rsp.cpu.vcol = _mm_setzero_si128(); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; @@ -572,17 +629,13 @@ pub fn veq(device: &mut device::Device, opcode: u32) { pub fn vne(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (eq, ne); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - eq = _mm_cmpeq_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - ne = _mm_cmpeq_epi16(eq, _mm_setzero_si128()); - device.rsp.cpu.vccl = _mm_and_si128(device.rsp.cpu.vcoh, eq); - device.rsp.cpu.vccl = _mm_or_si128(device.rsp.cpu.vccl, ne); - device.rsp.cpu.accl = _mm_blendv_epi8( - vte, - device.rsp.cpu.vpr[vs(opcode) as usize], - device.rsp.cpu.vccl, - ); + let eq = _mm_cmpeq_epi16(vs_reg, vte); + let ne = _mm_cmpeq_epi16(eq, _mm_setzero_si128()); + device.rsp.cpu.vccl = _mm_or_si128(_mm_and_si128(device.rsp.cpu.vcoh, eq), ne); + device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl); + device.rsp.cpu.vcch = _mm_setzero_si128(); device.rsp.cpu.vcoh = _mm_setzero_si128(); device.rsp.cpu.vcol = _mm_setzero_si128(); @@ -592,18 +645,16 @@ pub fn vne(device: &mut device::Device, opcode: u32) { pub fn vge(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut eq, gt, es); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - eq = _mm_cmpeq_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - gt = _mm_cmpgt_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - es = _mm_and_si128(device.rsp.cpu.vcoh, device.rsp.cpu.vcol); - eq = _mm_andnot_si128(es, eq); - device.rsp.cpu.vccl = _mm_or_si128(gt, eq); - device.rsp.cpu.accl = _mm_blendv_epi8( - vte, - device.rsp.cpu.vpr[vs(opcode) as usize], - device.rsp.cpu.vccl, - ); + let eq = _mm_cmpeq_epi16(vs_reg, vte); + let gt = _mm_cmpgt_epi16(vs_reg, vte); + let es = _mm_and_si128(device.rsp.cpu.vcoh, device.rsp.cpu.vcol); + let eq_filtered = _mm_andnot_si128(es, eq); + + device.rsp.cpu.vccl = _mm_or_si128(gt, eq_filtered); + device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl); + device.rsp.cpu.vcch = _mm_setzero_si128(); device.rsp.cpu.vcoh = _mm_setzero_si128(); device.rsp.cpu.vcol = _mm_setzero_si128(); @@ -613,41 +664,31 @@ pub fn vge(device: &mut device::Device, opcode: u32) { pub fn vcl(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let ( - mut nvt, - diff, - mut ncarry, - nvce, - diff0, - mut lec1, - mut lec2, - leeq, - mut geeq, - mut le, - mut ge, - mask, - ); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - nvt = _mm_xor_si128(vte, device.rsp.cpu.vcol); + let mut nvt = _mm_xor_si128(vte, device.rsp.cpu.vcol); nvt = _mm_sub_epi16(nvt, device.rsp.cpu.vcol); - diff = _mm_sub_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], nvt); - ncarry = _mm_adds_epu16(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - ncarry = _mm_cmpeq_epi16(diff, ncarry); - nvce = _mm_cmpeq_epi16(device.rsp.cpu.vce, _mm_setzero_si128()); - diff0 = _mm_cmpeq_epi16(diff, _mm_setzero_si128()); - lec1 = _mm_and_si128(diff0, ncarry); - lec1 = _mm_and_si128(nvce, lec1); - lec2 = _mm_or_si128(diff0, ncarry); - lec2 = _mm_and_si128(device.rsp.cpu.vce, lec2); - leeq = _mm_or_si128(lec1, lec2); - geeq = _mm_subs_epu16(vte, device.rsp.cpu.vpr[vs(opcode) as usize]); - geeq = _mm_cmpeq_epi16(geeq, _mm_setzero_si128()); - le = _mm_andnot_si128(device.rsp.cpu.vcoh, device.rsp.cpu.vcol); - le = _mm_blendv_epi8(device.rsp.cpu.vccl, leeq, le); - ge = _mm_or_si128(device.rsp.cpu.vcol, device.rsp.cpu.vcoh); - ge = _mm_blendv_epi8(geeq, device.rsp.cpu.vcch, ge); - mask = _mm_blendv_epi8(ge, le, device.rsp.cpu.vcol); - device.rsp.cpu.accl = _mm_blendv_epi8(device.rsp.cpu.vpr[vs(opcode) as usize], nvt, mask); + let diff = _mm_sub_epi16(vs_reg, nvt); + + let ncarry = _mm_cmpeq_epi16(diff, _mm_adds_epu16(vs_reg, vte)); + let nvce = _mm_cmpeq_epi16(device.rsp.cpu.vce, _mm_setzero_si128()); + let diff0 = _mm_cmpeq_epi16(diff, _mm_setzero_si128()); + + let lec1 = _mm_and_si128(_mm_and_si128(diff0, ncarry), nvce); + let lec2 = _mm_and_si128(_mm_or_si128(diff0, ncarry), device.rsp.cpu.vce); + let leeq = _mm_or_si128(lec1, lec2); + + let geeq = _mm_cmpeq_epi16(_mm_subs_epu16(vte, vs_reg), _mm_setzero_si128()); + + let le_sel = _mm_andnot_si128(device.rsp.cpu.vcoh, device.rsp.cpu.vcol); + let le = _mm_blendv_epi8(device.rsp.cpu.vccl, leeq, le_sel); + + let ge_sel = _mm_or_si128(device.rsp.cpu.vcol, device.rsp.cpu.vcoh); + let ge = _mm_blendv_epi8(geeq, device.rsp.cpu.vcch, ge_sel); + + let mask = _mm_blendv_epi8(ge, le, device.rsp.cpu.vcol); + device.rsp.cpu.accl = _mm_blendv_epi8(vs_reg, nvt, mask); + device.rsp.cpu.vcch = ge; device.rsp.cpu.vccl = le; device.rsp.cpu.vcoh = _mm_setzero_si128(); @@ -659,50 +700,57 @@ pub fn vcl(device: &mut device::Device, opcode: u32) { pub fn vch(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut nvt, diff, diff0, vtn, mut dlez, dgez, mask); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.vcol = _mm_xor_si128(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.vcol = _mm_cmplt_epi16(device.rsp.cpu.vcol, _mm_setzero_si128()); - nvt = _mm_xor_si128(vte, device.rsp.cpu.vcol); + device.rsp.cpu.vcol = _mm_cmplt_epi16(_mm_xor_si128(vs_reg, vte), _mm_setzero_si128()); + + let mut nvt = _mm_xor_si128(vte, device.rsp.cpu.vcol); nvt = _mm_sub_epi16(nvt, device.rsp.cpu.vcol); - diff = _mm_sub_epi16(device.rsp.cpu.vpr[vs(opcode) as usize], nvt); - diff0 = _mm_cmpeq_epi16(diff, _mm_setzero_si128()); - vtn = _mm_cmplt_epi16(vte, _mm_setzero_si128()); - dlez = _mm_cmpgt_epi16(diff, _mm_setzero_si128()); - dgez = _mm_or_si128(dlez, diff0); - dlez = _mm_cmpeq_epi16(_mm_setzero_si128(), dlez); + let diff = _mm_sub_epi16(vs_reg, nvt); + let diff0 = _mm_cmpeq_epi16(diff, _mm_setzero_si128()); + let vtn = _mm_cmplt_epi16(vte, _mm_setzero_si128()); + + let dlez = _mm_cmpeq_epi16( + _mm_setzero_si128(), + _mm_cmpgt_epi16(diff, _mm_setzero_si128()), + ); + let dgez = _mm_or_si128(_mm_cmpgt_epi16(diff, _mm_setzero_si128()), diff0); + device.rsp.cpu.vcch = _mm_blendv_epi8(dgez, vtn, device.rsp.cpu.vcol); device.rsp.cpu.vccl = _mm_blendv_epi8(vtn, dlez, device.rsp.cpu.vcol); - device.rsp.cpu.vce = _mm_cmpeq_epi16(diff, device.rsp.cpu.vcol); - device.rsp.cpu.vce = _mm_and_si128(device.rsp.cpu.vce, device.rsp.cpu.vcol); - device.rsp.cpu.vcoh = _mm_or_si128(diff0, device.rsp.cpu.vce); - device.rsp.cpu.vcoh = _mm_cmpeq_epi16(device.rsp.cpu.vcoh, _mm_setzero_si128()); - mask = _mm_blendv_epi8( + device.rsp.cpu.vce = _mm_and_si128( + _mm_cmpeq_epi16(diff, device.rsp.cpu.vcol), + device.rsp.cpu.vcol, + ); + device.rsp.cpu.vcoh = + _mm_cmpeq_epi16(_mm_or_si128(diff0, device.rsp.cpu.vce), _mm_setzero_si128()); + + let mask = _mm_blendv_epi8( device.rsp.cpu.vcch, device.rsp.cpu.vccl, device.rsp.cpu.vcol, ); - device.rsp.cpu.accl = _mm_blendv_epi8(device.rsp.cpu.vpr[vs(opcode) as usize], nvt, mask); + device.rsp.cpu.accl = _mm_blendv_epi8(vs_reg, nvt, mask); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; } } pub fn vcr(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let (mut sign, mut dlez, mut dgez, nvt, mask); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - sign = _mm_xor_si128(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - sign = _mm_srai_epi16(sign, 15); - dlez = _mm_and_si128(device.rsp.cpu.vpr[vs(opcode) as usize], sign); - dlez = _mm_add_epi16(dlez, vte); + let sign = _mm_srai_epi16(_mm_xor_si128(vs_reg, vte), 15); + let dlez = _mm_add_epi16(_mm_and_si128(vs_reg, sign), vte); device.rsp.cpu.vccl = _mm_srai_epi16(dlez, 15); - dgez = _mm_or_si128(device.rsp.cpu.vpr[vs(opcode) as usize], sign); - dgez = _mm_min_epi16(dgez, vte); + + let dgez = _mm_min_epi16(_mm_or_si128(vs_reg, sign), vte); device.rsp.cpu.vcch = _mm_cmpeq_epi16(dgez, vte); - nvt = _mm_xor_si128(vte, sign); - mask = _mm_blendv_epi8(device.rsp.cpu.vcch, device.rsp.cpu.vccl, sign); - device.rsp.cpu.accl = _mm_blendv_epi8(device.rsp.cpu.vpr[vs(opcode) as usize], nvt, mask); + + let nvt = _mm_xor_si128(vte, sign); + let mask = _mm_blendv_epi8(device.rsp.cpu.vcch, device.rsp.cpu.vccl, sign); + device.rsp.cpu.accl = _mm_blendv_epi8(vs_reg, nvt, mask); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; + device.rsp.cpu.vcol = _mm_setzero_si128(); device.rsp.cpu.vcoh = _mm_setzero_si128(); device.rsp.cpu.vce = _mm_setzero_si128(); @@ -711,12 +759,9 @@ pub fn vcr(device: &mut device::Device, opcode: u32) { pub fn vmrg(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_blendv_epi8( - vte, - device.rsp.cpu.vpr[vs(opcode) as usize], - device.rsp.cpu.vccl, - ); + device.rsp.cpu.accl = _mm_blendv_epi8(vte, vs_reg, device.rsp.cpu.vccl); device.rsp.cpu.vcoh = _mm_setzero_si128(); device.rsp.cpu.vcol = _mm_setzero_si128(); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; @@ -725,75 +770,66 @@ pub fn vmrg(device: &mut device::Device, opcode: u32) { pub fn vand(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_and_si128(device.rsp.cpu.vpr[vs(opcode) as usize], vte); + device.rsp.cpu.accl = _mm_and_si128(vs_reg, vte); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; } } pub fn vnand(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_and_si128(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.accl = _mm_xor_si128(device.rsp.cpu.accl, _mm_set1_epi32(-1)); + let and_result = _mm_and_si128(vs_reg, vte); + device.rsp.cpu.accl = _mm_xor_si128(and_result, _mm_set1_epi32(-1)); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; } } pub fn vor(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_or_si128(device.rsp.cpu.vpr[vs(opcode) as usize], vte); + device.rsp.cpu.accl = _mm_or_si128(vs_reg, vte); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; } } pub fn vnor(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_or_si128(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.accl = _mm_xor_si128(device.rsp.cpu.accl, _mm_set1_epi32(-1)); + let or_result = _mm_or_si128(vs_reg, vte); + device.rsp.cpu.accl = _mm_xor_si128(or_result, _mm_set1_epi32(-1)); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; } } pub fn vxor(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_xor_si128(device.rsp.cpu.vpr[vs(opcode) as usize], vte); + device.rsp.cpu.accl = _mm_xor_si128(vs_reg, vte); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; } } pub fn vnxor(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vs_reg = device.rsp.cpu.vpr[vs(opcode) as usize]; unsafe { - device.rsp.cpu.accl = _mm_xor_si128(device.rsp.cpu.vpr[vs(opcode) as usize], vte); - device.rsp.cpu.accl = _mm_xor_si128(device.rsp.cpu.accl, _mm_set1_epi32(-1)); + let xor_result = _mm_xor_si128(vs_reg, vte); + device.rsp.cpu.accl = _mm_xor_si128(xor_result, _mm_set1_epi32(-1)); device.rsp.cpu.vpr[vd(opcode) as usize] = device.rsp.cpu.accl; } } pub fn vrcp(device: &mut device::Device, opcode: u32) { - let mut result; let vte = vte(device, vt(opcode), ve(opcode) as usize); let input = get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16 as i32; - let mask = input >> 31; - let mut data = input ^ mask; - if input > -32768 { - data -= mask - } - if data == 0 { - result = 0x7fffffff - } else if input == -32768 { - result = 0xffff0000 - } else { - let shift = (data as u32).leading_zeros(); - let index = (((data as u64) << shift) & 0x7fc00000) >> 22; - result = device.rsp.cpu.reciprocals[index as usize] as u32; - result = (0x10000 | result) << 14; - result = (result >> (31 - shift)) ^ mask as u32 - } + let result = compute_reciprocal(input, &device.rsp.cpu.reciprocals); + device.rsp.cpu.divdp = false; device.rsp.cpu.divout = (result >> 16) as i16; device.rsp.cpu.accl = vte; @@ -805,7 +841,6 @@ pub fn vrcp(device: &mut device::Device, opcode: u32) { } pub fn vrcpl(device: &mut device::Device, opcode: u32) { - let mut result; let vte = vte(device, vt(opcode), ve(opcode) as usize); let input = if device.rsp.cpu.divdp { ((device.rsp.cpu.divin as i32) << 16) @@ -813,22 +848,8 @@ pub fn vrcpl(device: &mut device::Device, opcode: u32) { } else { get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16 as i32 }; - let mask = input >> 31; - let mut data = input ^ mask; - if input > -32768 { - data -= mask - } - if data == 0 { - result = 0x7fffffff - } else if input == -32768 { - result = 0xffff0000 - } else { - let shift = (data as u32).leading_zeros(); - let index = (((data as u64) << shift) & 0x7fc00000) >> 22; - result = device.rsp.cpu.reciprocals[index as usize] as u32; - result = (0x10000 | result) << 14; - result = (result >> (31 - shift)) ^ mask as u32 - } + let result = compute_reciprocal(input, &device.rsp.cpu.reciprocals); + device.rsp.cpu.divdp = false; device.rsp.cpu.divout = (result >> 16) as i16; device.rsp.cpu.accl = vte; @@ -841,50 +862,31 @@ pub fn vrcpl(device: &mut device::Device, opcode: u32) { pub fn vrcph(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vt_reg = device.rsp.cpu.vpr[vt(opcode) as usize]; + let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize]; + device.rsp.cpu.accl = vte; device.rsp.cpu.divdp = true; + device.rsp.cpu.divin = get_vpr16(vt_reg, ve(opcode) as u8) as i16; - device.rsp.cpu.divin = - get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16; - modify_vpr16( - &mut device.rsp.cpu.vpr[vd(opcode) as usize], - de(opcode) as u8, - device.rsp.cpu.divout as u16, - ); + modify_vpr16(vd_reg, de(opcode) as u8, device.rsp.cpu.divout as u16); } pub fn vmov(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); - let value = get_vpr16(vte, de(opcode) as u8); - modify_vpr16( - &mut device.rsp.cpu.vpr[vd(opcode) as usize], - de(opcode) as u8, - value, - ); + let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize]; + let de_index = de(opcode) as u8; + + let value = get_vpr16(vte, de_index); + modify_vpr16(vd_reg, de_index, value); device.rsp.cpu.accl = vte; } pub fn vrsq(device: &mut device::Device, opcode: u32) { - let mut result; let vte = vte(device, vt(opcode), ve(opcode) as usize); let input = get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16 as i32; - let mask = input >> 31; - let mut data = input ^ mask; - if input > -32768 { - data -= mask - } - if data == 0 { - result = 0x7fffffff - } else if input == -32768 { - result = 0xffff0000 - } else { - let shift = (data as u32).leading_zeros(); - let index = (((data as u64) << shift) & 0x7fc00000) as u32 >> 22; - result = - (device.rsp.cpu.inverse_square_roots[((index & 0x1fe) | (shift & 1)) as usize]) as u32; - result = (0x10000 | result) << 14; - result = (result >> ((31 - shift) >> 1)) ^ mask as u32 - } + let result = compute_inverse_sqrt(input, &device.rsp.cpu.inverse_square_roots); + device.rsp.cpu.divdp = false; device.rsp.cpu.divout = (result >> 16) as i16; device.rsp.cpu.accl = vte; @@ -896,7 +898,6 @@ pub fn vrsq(device: &mut device::Device, opcode: u32) { } pub fn vrsql(device: &mut device::Device, opcode: u32) { - let mut result; let vte = vte(device, vt(opcode), ve(opcode) as usize); let input = if device.rsp.cpu.divdp { ((device.rsp.cpu.divin as i32) << 16) @@ -904,23 +905,8 @@ pub fn vrsql(device: &mut device::Device, opcode: u32) { } else { get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16 as i32 }; - let mask = input >> 31; - let mut data = input ^ mask; - if input > -32768 { - data -= mask - } - if data == 0 { - result = 0x7fffffff - } else if input == -32768 { - result = 0xffff0000 - } else { - let shift = (data as u32).leading_zeros(); - let index = (((data as u64) << shift) & 0x7fc00000) as u32 >> 22; - result = - (device.rsp.cpu.inverse_square_roots[((index & 0x1fe) | (shift & 1)) as usize]) as u32; - result = (0x10000 | result) << 14; - result = (result >> ((31 - shift) >> 1)) ^ mask as u32 - } + let result = compute_inverse_sqrt(input, &device.rsp.cpu.inverse_square_roots); + device.rsp.cpu.divdp = false; device.rsp.cpu.divout = (result >> 16) as i16; device.rsp.cpu.accl = vte; @@ -933,16 +919,14 @@ pub fn vrsql(device: &mut device::Device, opcode: u32) { pub fn vrsqh(device: &mut device::Device, opcode: u32) { let vte = vte(device, vt(opcode), ve(opcode) as usize); + let vt_reg = device.rsp.cpu.vpr[vt(opcode) as usize]; + let vd_reg = &mut device.rsp.cpu.vpr[vd(opcode) as usize]; + device.rsp.cpu.accl = vte; device.rsp.cpu.divdp = true; + device.rsp.cpu.divin = get_vpr16(vt_reg, ve(opcode) as u8) as i16; - device.rsp.cpu.divin = - get_vpr16(device.rsp.cpu.vpr[vt(opcode) as usize], ve(opcode) as u8) as i16; - modify_vpr16( - &mut device.rsp.cpu.vpr[vd(opcode) as usize], - de(opcode) as u8, - device.rsp.cpu.divout as u16, - ); + modify_vpr16(vd_reg, de(opcode) as u8, device.rsp.cpu.divout as u16); } pub fn vnop(_device: &mut device::Device, _opcode: u32) {}