1235eb015SJia Liu /* 2235eb015SJia Liu * MIPS ASE DSP Instruction emulation helpers for QEMU. 3235eb015SJia Liu * 4235eb015SJia Liu * Copyright (c) 2012 Jia Liu <proljc@gmail.com> 5235eb015SJia Liu * Dongxue Zhang <elat.era@gmail.com> 6235eb015SJia Liu * This library is free software; you can redistribute it and/or 7235eb015SJia Liu * modify it under the terms of the GNU Lesser General Public 8235eb015SJia Liu * License as published by the Free Software Foundation; either 9235eb015SJia Liu * version 2 of the License, or (at your option) any later version. 10235eb015SJia Liu * 11235eb015SJia Liu * This library is distributed in the hope that it will be useful, 12235eb015SJia Liu * but WITHOUT ANY WARRANTY; without even the implied warranty of 13235eb015SJia Liu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14235eb015SJia Liu * Lesser General Public License for more details. 15235eb015SJia Liu * 16235eb015SJia Liu * You should have received a copy of the GNU Lesser General Public 17235eb015SJia Liu * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18235eb015SJia Liu */ 19235eb015SJia Liu 20235eb015SJia Liu #include "cpu.h" 21235eb015SJia Liu #include "helper.h" 22235eb015SJia Liu 23235eb015SJia Liu /*** MIPS DSP internal functions begin ***/ 24235eb015SJia Liu #define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x) 25235eb015SJia Liu #define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d))) 26235eb015SJia Liu 27235eb015SJia Liu static inline void set_DSPControl_overflow_flag(uint32_t flag, int position, 28235eb015SJia Liu CPUMIPSState *env) 29235eb015SJia Liu { 30235eb015SJia Liu env->active_tc.DSPControl |= (target_ulong)flag << position; 31235eb015SJia Liu } 32235eb015SJia Liu 33235eb015SJia Liu static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env) 34235eb015SJia Liu { 35235eb015SJia Liu env->active_tc.DSPControl |= (target_ulong)flag << 13; 36235eb015SJia Liu } 37235eb015SJia Liu 38235eb015SJia Liu static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env) 39235eb015SJia Liu { 40235eb015SJia Liu return (env->active_tc.DSPControl >> 13) & 0x01; 41235eb015SJia Liu } 42235eb015SJia Liu 43235eb015SJia Liu static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env) 44235eb015SJia Liu { 45235eb015SJia Liu uint32_t filter; 46235eb015SJia Liu 47235eb015SJia Liu filter = ((0x01 << len) - 1) << 24; 48235eb015SJia Liu filter = ~filter; 49235eb015SJia Liu 50235eb015SJia Liu env->active_tc.DSPControl &= filter; 51235eb015SJia Liu env->active_tc.DSPControl |= (target_ulong)flag << 24; 52235eb015SJia Liu } 53235eb015SJia Liu 54235eb015SJia Liu static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env) 55235eb015SJia Liu { 56235eb015SJia Liu uint32_t filter; 57235eb015SJia Liu 58235eb015SJia Liu filter = (0x01 << len) - 1; 59235eb015SJia Liu 60235eb015SJia Liu return (env->active_tc.DSPControl >> 24) & filter; 61235eb015SJia Liu } 62235eb015SJia Liu 63235eb015SJia Liu static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env) 64235eb015SJia Liu { 65235eb015SJia Liu target_ulong dspc; 66235eb015SJia Liu 67235eb015SJia Liu dspc = env->active_tc.DSPControl; 68235eb015SJia Liu #ifndef TARGET_MIPS64 69235eb015SJia Liu dspc = dspc & 0xFFFFFFC0; 70235eb015SJia Liu dspc |= pos; 71235eb015SJia Liu #else 72235eb015SJia Liu dspc = dspc & 0xFFFFFF80; 73235eb015SJia Liu dspc |= pos; 74235eb015SJia Liu #endif 75235eb015SJia Liu env->active_tc.DSPControl = dspc; 76235eb015SJia Liu } 77235eb015SJia Liu 78235eb015SJia Liu static inline uint32_t get_DSPControl_pos(CPUMIPSState *env) 79235eb015SJia Liu { 80235eb015SJia Liu target_ulong dspc; 81235eb015SJia Liu uint32_t pos; 82235eb015SJia Liu 83235eb015SJia Liu dspc = env->active_tc.DSPControl; 84235eb015SJia Liu 85235eb015SJia Liu #ifndef TARGET_MIPS64 86235eb015SJia Liu pos = dspc & 0x3F; 87235eb015SJia Liu #else 88235eb015SJia Liu pos = dspc & 0x7F; 89235eb015SJia Liu #endif 90235eb015SJia Liu 91235eb015SJia Liu return pos; 92235eb015SJia Liu } 93235eb015SJia Liu 94235eb015SJia Liu static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env) 95235eb015SJia Liu { 96235eb015SJia Liu env->active_tc.DSPControl &= 0xFFFFBFFF; 97235eb015SJia Liu env->active_tc.DSPControl |= (target_ulong)flag << 14; 98235eb015SJia Liu } 99235eb015SJia Liu 100235eb015SJia Liu #define DO_MIPS_SAT_ABS(size) \ 101235eb015SJia Liu static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a, \ 102235eb015SJia Liu CPUMIPSState *env) \ 103235eb015SJia Liu { \ 104235eb015SJia Liu if (a == INT##size##_MIN) { \ 105235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); \ 106235eb015SJia Liu return INT##size##_MAX; \ 107235eb015SJia Liu } else { \ 108235eb015SJia Liu return MIPSDSP_ABS(a); \ 109235eb015SJia Liu } \ 110235eb015SJia Liu } 111235eb015SJia Liu DO_MIPS_SAT_ABS(8) 112235eb015SJia Liu DO_MIPS_SAT_ABS(16) 113235eb015SJia Liu DO_MIPS_SAT_ABS(32) 114235eb015SJia Liu #undef DO_MIPS_SAT_ABS 115235eb015SJia Liu 116235eb015SJia Liu /* get sum value */ 117235eb015SJia Liu static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env) 118235eb015SJia Liu { 119235eb015SJia Liu int16_t tempI; 120235eb015SJia Liu 121235eb015SJia Liu tempI = a + b; 122235eb015SJia Liu 123235eb015SJia Liu if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) { 124235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 125235eb015SJia Liu } 126235eb015SJia Liu 127235eb015SJia Liu return tempI; 128235eb015SJia Liu } 129235eb015SJia Liu 130235eb015SJia Liu static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b, 131235eb015SJia Liu CPUMIPSState *env) 132235eb015SJia Liu { 133235eb015SJia Liu int16_t tempS; 134235eb015SJia Liu 135235eb015SJia Liu tempS = a + b; 136235eb015SJia Liu 137235eb015SJia Liu if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) { 138235eb015SJia Liu if (a > 0) { 139235eb015SJia Liu tempS = 0x7FFF; 140235eb015SJia Liu } else { 141235eb015SJia Liu tempS = 0x8000; 142235eb015SJia Liu } 143235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 144235eb015SJia Liu } 145235eb015SJia Liu 146235eb015SJia Liu return tempS; 147235eb015SJia Liu } 148235eb015SJia Liu 149235eb015SJia Liu static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b, 150235eb015SJia Liu CPUMIPSState *env) 151235eb015SJia Liu { 152235eb015SJia Liu int32_t tempI; 153235eb015SJia Liu 154235eb015SJia Liu tempI = a + b; 155235eb015SJia Liu 156235eb015SJia Liu if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) { 157235eb015SJia Liu if (a > 0) { 158235eb015SJia Liu tempI = 0x7FFFFFFF; 159235eb015SJia Liu } else { 160235eb015SJia Liu tempI = 0x80000000; 161235eb015SJia Liu } 162235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 163235eb015SJia Liu } 164235eb015SJia Liu 165235eb015SJia Liu return tempI; 166235eb015SJia Liu } 167235eb015SJia Liu 168235eb015SJia Liu static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env) 169235eb015SJia Liu { 170235eb015SJia Liu uint16_t temp; 171235eb015SJia Liu 172235eb015SJia Liu temp = (uint16_t)a + (uint16_t)b; 173235eb015SJia Liu 174235eb015SJia Liu if (temp & 0x0100) { 175235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 176235eb015SJia Liu } 177235eb015SJia Liu 178235eb015SJia Liu return temp & 0xFF; 179235eb015SJia Liu } 180235eb015SJia Liu 181235eb015SJia Liu static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b, 182235eb015SJia Liu CPUMIPSState *env) 183235eb015SJia Liu { 184235eb015SJia Liu uint32_t temp; 185235eb015SJia Liu 186235eb015SJia Liu temp = (uint32_t)a + (uint32_t)b; 187235eb015SJia Liu 188235eb015SJia Liu if (temp & 0x00010000) { 189235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 190235eb015SJia Liu } 191235eb015SJia Liu 192235eb015SJia Liu return temp & 0xFFFF; 193235eb015SJia Liu } 194235eb015SJia Liu 195235eb015SJia Liu static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b, 196235eb015SJia Liu CPUMIPSState *env) 197235eb015SJia Liu { 198235eb015SJia Liu uint8_t result; 199235eb015SJia Liu uint16_t temp; 200235eb015SJia Liu 201235eb015SJia Liu temp = (uint16_t)a + (uint16_t)b; 202235eb015SJia Liu result = temp & 0xFF; 203235eb015SJia Liu 204235eb015SJia Liu if (0x0100 & temp) { 205235eb015SJia Liu result = 0xFF; 206235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 207235eb015SJia Liu } 208235eb015SJia Liu 209235eb015SJia Liu return result; 210235eb015SJia Liu } 211235eb015SJia Liu 212235eb015SJia Liu static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b, 213235eb015SJia Liu CPUMIPSState *env) 214235eb015SJia Liu { 215235eb015SJia Liu uint16_t result; 216235eb015SJia Liu uint32_t temp; 217235eb015SJia Liu 218235eb015SJia Liu temp = (uint32_t)a + (uint32_t)b; 219235eb015SJia Liu result = temp & 0xFFFF; 220235eb015SJia Liu 221235eb015SJia Liu if (0x00010000 & temp) { 222235eb015SJia Liu result = 0xFFFF; 223235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 224235eb015SJia Liu } 225235eb015SJia Liu 226235eb015SJia Liu return result; 227235eb015SJia Liu } 228235eb015SJia Liu 229235eb015SJia Liu static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a, 230235eb015SJia Liu CPUMIPSState *env) 231235eb015SJia Liu { 232235eb015SJia Liu int64_t temp; 233235eb015SJia Liu int32_t temp32, temp31, result; 234235eb015SJia Liu int64_t temp_sum; 235235eb015SJia Liu 236235eb015SJia Liu #ifndef TARGET_MIPS64 237235eb015SJia Liu temp = ((uint64_t)env->active_tc.HI[acc] << 32) | 238235eb015SJia Liu (uint64_t)env->active_tc.LO[acc]; 239235eb015SJia Liu #else 240235eb015SJia Liu temp = (uint64_t)env->active_tc.LO[acc]; 241235eb015SJia Liu #endif 242235eb015SJia Liu 243235eb015SJia Liu temp_sum = (int64_t)a + temp; 244235eb015SJia Liu 245235eb015SJia Liu temp32 = (temp_sum >> 32) & 0x01; 246235eb015SJia Liu temp31 = (temp_sum >> 31) & 0x01; 247235eb015SJia Liu result = temp_sum & 0xFFFFFFFF; 248235eb015SJia Liu 249235eb015SJia Liu /* FIXME 250235eb015SJia Liu This sat function may wrong, because user manual wrote: 251235eb015SJia Liu temp127..0 ← temp + ( (signA) || a31..0 252235eb015SJia Liu if ( temp32 ≠ temp31 ) then 253235eb015SJia Liu if ( temp32 = 0 ) then 254235eb015SJia Liu temp31..0 ← 0x80000000 255235eb015SJia Liu else 256235eb015SJia Liu temp31..0 ← 0x7FFFFFFF 257235eb015SJia Liu endif 258235eb015SJia Liu DSPControlouflag:16+acc ← 1 259235eb015SJia Liu endif 260235eb015SJia Liu */ 261235eb015SJia Liu if (temp32 != temp31) { 262235eb015SJia Liu if (temp32 == 0) { 263235eb015SJia Liu result = 0x7FFFFFFF; 264235eb015SJia Liu } else { 265235eb015SJia Liu result = 0x80000000; 266235eb015SJia Liu } 267235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + acc, env); 268235eb015SJia Liu } 269235eb015SJia Liu 270235eb015SJia Liu return result; 271235eb015SJia Liu } 272235eb015SJia Liu 273235eb015SJia Liu /* a[0] is LO, a[1] is HI. */ 274235eb015SJia Liu static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret, 275235eb015SJia Liu int32_t ac, 276235eb015SJia Liu int64_t *a, 277235eb015SJia Liu CPUMIPSState *env) 278235eb015SJia Liu { 279235eb015SJia Liu bool temp64; 280235eb015SJia Liu 281235eb015SJia Liu ret[0] = env->active_tc.LO[ac] + a[0]; 282235eb015SJia Liu ret[1] = env->active_tc.HI[ac] + a[1]; 283235eb015SJia Liu 284235eb015SJia Liu if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) && 285235eb015SJia Liu ((uint64_t)ret[0] < (uint64_t)a[0])) { 286235eb015SJia Liu ret[1] += 1; 287235eb015SJia Liu } 288235eb015SJia Liu temp64 = ret[1] & 1; 289235eb015SJia Liu if (temp64 != ((ret[0] >> 63) & 0x01)) { 290235eb015SJia Liu if (temp64) { 291235eb015SJia Liu ret[0] = (0x01ull << 63); 292235eb015SJia Liu ret[1] = ~0ull; 293235eb015SJia Liu } else { 294235eb015SJia Liu ret[0] = (0x01ull << 63) - 1; 295235eb015SJia Liu ret[1] = 0x00; 296235eb015SJia Liu } 297235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); 298235eb015SJia Liu } 299235eb015SJia Liu } 300235eb015SJia Liu 301235eb015SJia Liu static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret, 302235eb015SJia Liu int32_t ac, 303235eb015SJia Liu int64_t *a, 304235eb015SJia Liu CPUMIPSState *env) 305235eb015SJia Liu { 306235eb015SJia Liu bool temp64; 307235eb015SJia Liu 308235eb015SJia Liu ret[0] = env->active_tc.LO[ac] - a[0]; 309235eb015SJia Liu ret[1] = env->active_tc.HI[ac] - a[1]; 310235eb015SJia Liu 311235eb015SJia Liu if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) { 312235eb015SJia Liu ret[1] -= 1; 313235eb015SJia Liu } 314235eb015SJia Liu temp64 = ret[1] & 1; 315235eb015SJia Liu if (temp64 != ((ret[0] >> 63) & 0x01)) { 316235eb015SJia Liu if (temp64) { 317235eb015SJia Liu ret[0] = (0x01ull << 63); 318235eb015SJia Liu ret[1] = ~0ull; 319235eb015SJia Liu } else { 320235eb015SJia Liu ret[0] = (0x01ull << 63) - 1; 321235eb015SJia Liu ret[1] = 0x00; 322235eb015SJia Liu } 323235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); 324235eb015SJia Liu } 325235eb015SJia Liu } 326235eb015SJia Liu 327235eb015SJia Liu static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b, 328235eb015SJia Liu CPUMIPSState *env) 329235eb015SJia Liu { 330235eb015SJia Liu int32_t temp; 331235eb015SJia Liu 332235eb015SJia Liu temp = (int32_t)a * (int32_t)b; 333235eb015SJia Liu 334235eb015SJia Liu if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) { 335235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 336235eb015SJia Liu } 337235eb015SJia Liu temp &= 0x0000FFFF; 338235eb015SJia Liu 339235eb015SJia Liu return temp; 340235eb015SJia Liu } 341235eb015SJia Liu 342235eb015SJia Liu static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b) 343235eb015SJia Liu { 344235eb015SJia Liu return a * b; 345235eb015SJia Liu } 346235eb015SJia Liu 347235eb015SJia Liu static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b) 348235eb015SJia Liu { 349235eb015SJia Liu return a * b; 350235eb015SJia Liu } 351235eb015SJia Liu 352235eb015SJia Liu static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b, 353235eb015SJia Liu CPUMIPSState *env) 354235eb015SJia Liu { 355235eb015SJia Liu int32_t temp; 356235eb015SJia Liu 357235eb015SJia Liu temp = (int32_t)a * (int32_t)b; 358235eb015SJia Liu 359235eb015SJia Liu if (temp > (int)0x7FFF) { 360235eb015SJia Liu temp = 0x00007FFF; 361235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 362235eb015SJia Liu } else if (temp < (int)0xffff8000) { 363235eb015SJia Liu temp = 0xFFFF8000; 364235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 365235eb015SJia Liu } 366235eb015SJia Liu temp &= 0x0000FFFF; 367235eb015SJia Liu 368235eb015SJia Liu return temp; 369235eb015SJia Liu } 370235eb015SJia Liu 371235eb015SJia Liu static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b, 372235eb015SJia Liu CPUMIPSState *env) 373235eb015SJia Liu { 374235eb015SJia Liu int32_t temp; 375235eb015SJia Liu 376235eb015SJia Liu if ((a == 0x8000) && (b == 0x8000)) { 377235eb015SJia Liu temp = 0x7FFFFFFF; 378235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 379235eb015SJia Liu } else { 380235eb015SJia Liu temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1; 381235eb015SJia Liu } 382235eb015SJia Liu 383235eb015SJia Liu return temp; 384235eb015SJia Liu } 385235eb015SJia Liu 386235eb015SJia Liu /* right shift */ 387235eb015SJia Liu static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov) 388235eb015SJia Liu { 389235eb015SJia Liu return a >> mov; 390235eb015SJia Liu } 391235eb015SJia Liu 392235eb015SJia Liu static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov) 393235eb015SJia Liu { 394235eb015SJia Liu return a >> mov; 395235eb015SJia Liu } 396235eb015SJia Liu 397235eb015SJia Liu static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov) 398235eb015SJia Liu { 399235eb015SJia Liu return a >> mov; 400235eb015SJia Liu } 401235eb015SJia Liu 402235eb015SJia Liu static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov) 403235eb015SJia Liu { 404235eb015SJia Liu return a >> mov; 405235eb015SJia Liu } 406235eb015SJia Liu 407235eb015SJia Liu static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov) 408235eb015SJia Liu { 409235eb015SJia Liu return a >> mov; 410235eb015SJia Liu } 411235eb015SJia Liu 412235eb015SJia Liu static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b) 413235eb015SJia Liu { 414235eb015SJia Liu int32_t temp; 415235eb015SJia Liu 416235eb015SJia Liu temp = (int32_t)a + (int32_t)b; 417235eb015SJia Liu 418235eb015SJia Liu return (temp >> 1) & 0xFFFF; 419235eb015SJia Liu } 420235eb015SJia Liu 421235eb015SJia Liu /* round right shift */ 422235eb015SJia Liu static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b) 423235eb015SJia Liu { 424235eb015SJia Liu int32_t temp; 425235eb015SJia Liu 426235eb015SJia Liu temp = (int32_t)a + (int32_t)b; 427235eb015SJia Liu temp += 1; 428235eb015SJia Liu 429235eb015SJia Liu return (temp >> 1) & 0xFFFF; 430235eb015SJia Liu } 431235eb015SJia Liu 432235eb015SJia Liu static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b) 433235eb015SJia Liu { 434235eb015SJia Liu int64_t temp; 435235eb015SJia Liu 436235eb015SJia Liu temp = (int64_t)a + (int64_t)b; 437235eb015SJia Liu 438235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFF; 439235eb015SJia Liu } 440235eb015SJia Liu 441235eb015SJia Liu static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b) 442235eb015SJia Liu { 443235eb015SJia Liu int64_t temp; 444235eb015SJia Liu 445235eb015SJia Liu temp = (int64_t)a + (int64_t)b; 446235eb015SJia Liu temp += 1; 447235eb015SJia Liu 448235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFF; 449235eb015SJia Liu } 450235eb015SJia Liu 451235eb015SJia Liu static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b) 452235eb015SJia Liu { 453235eb015SJia Liu uint16_t temp; 454235eb015SJia Liu 455235eb015SJia Liu temp = (uint16_t)a + (uint16_t)b; 456235eb015SJia Liu 457235eb015SJia Liu return (temp >> 1) & 0x00FF; 458235eb015SJia Liu } 459235eb015SJia Liu 460235eb015SJia Liu static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b) 461235eb015SJia Liu { 462235eb015SJia Liu uint16_t temp; 463235eb015SJia Liu 464235eb015SJia Liu temp = (uint16_t)a + (uint16_t)b + 1; 465235eb015SJia Liu 466235eb015SJia Liu return (temp >> 1) & 0x00FF; 467235eb015SJia Liu } 468235eb015SJia Liu 469235eb015SJia Liu static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b) 470235eb015SJia Liu { 471235eb015SJia Liu uint16_t temp; 472235eb015SJia Liu 473235eb015SJia Liu temp = (uint16_t)a - (uint16_t)b; 474235eb015SJia Liu 475235eb015SJia Liu return (temp >> 1) & 0x00FF; 476235eb015SJia Liu } 477235eb015SJia Liu 478235eb015SJia Liu static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b) 479235eb015SJia Liu { 480235eb015SJia Liu uint16_t temp; 481235eb015SJia Liu 482235eb015SJia Liu temp = (uint16_t)a - (uint16_t)b + 1; 483235eb015SJia Liu 484235eb015SJia Liu return (temp >> 1) & 0x00FF; 485235eb015SJia Liu } 486235eb015SJia Liu 487235eb015SJia Liu static inline int64_t mipsdsp_rashift_short_acc(int32_t ac, 488235eb015SJia Liu int32_t shift, 489235eb015SJia Liu CPUMIPSState *env) 490235eb015SJia Liu { 491235eb015SJia Liu int32_t sign, temp31; 492235eb015SJia Liu int64_t temp, acc; 493235eb015SJia Liu 494235eb015SJia Liu sign = (env->active_tc.HI[ac] >> 31) & 0x01; 495235eb015SJia Liu acc = ((int64_t)env->active_tc.HI[ac] << 32) | 496235eb015SJia Liu ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); 497235eb015SJia Liu if (shift == 0) { 498235eb015SJia Liu temp = acc; 499235eb015SJia Liu } else { 500235eb015SJia Liu if (sign == 0) { 501235eb015SJia Liu temp = (((int64_t)0x01 << (32 - shift + 1)) - 1) & (acc >> shift); 502235eb015SJia Liu } else { 503235eb015SJia Liu temp = ((((int64_t)0x01 << (shift + 1)) - 1) << (32 - shift)) | 504235eb015SJia Liu (acc >> shift); 505235eb015SJia Liu } 506235eb015SJia Liu } 507235eb015SJia Liu 508235eb015SJia Liu temp31 = (temp >> 31) & 0x01; 509235eb015SJia Liu if (sign != temp31) { 510235eb015SJia Liu set_DSPControl_overflow_flag(1, 23, env); 511235eb015SJia Liu } 512235eb015SJia Liu 513235eb015SJia Liu return temp; 514235eb015SJia Liu } 515235eb015SJia Liu 516235eb015SJia Liu /* 128 bits long. p[0] is LO, p[1] is HI. */ 517235eb015SJia Liu static inline void mipsdsp_rndrashift_short_acc(int64_t *p, 518235eb015SJia Liu int32_t ac, 519235eb015SJia Liu int32_t shift, 520235eb015SJia Liu CPUMIPSState *env) 521235eb015SJia Liu { 522235eb015SJia Liu int64_t acc; 523235eb015SJia Liu 524235eb015SJia Liu acc = ((int64_t)env->active_tc.HI[ac] << 32) | 525235eb015SJia Liu ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); 526235eb015SJia Liu if (shift == 0) { 527235eb015SJia Liu p[0] = acc << 1; 528235eb015SJia Liu p[1] = (acc >> 63) & 0x01; 529235eb015SJia Liu } else { 530235eb015SJia Liu p[0] = acc >> (shift - 1); 531235eb015SJia Liu p[1] = 0; 532235eb015SJia Liu } 533235eb015SJia Liu } 534235eb015SJia Liu 535235eb015SJia Liu /* 128 bits long. p[0] is LO, p[1] is HI */ 536235eb015SJia Liu static inline void mipsdsp_rashift_acc(uint64_t *p, 537235eb015SJia Liu uint32_t ac, 538235eb015SJia Liu uint32_t shift, 539235eb015SJia Liu CPUMIPSState *env) 540235eb015SJia Liu { 541235eb015SJia Liu uint64_t tempB, tempA; 542235eb015SJia Liu 543235eb015SJia Liu tempB = env->active_tc.HI[ac]; 544235eb015SJia Liu tempA = env->active_tc.LO[ac]; 545235eb015SJia Liu shift = shift & 0x1F; 546235eb015SJia Liu 547235eb015SJia Liu if (shift == 0) { 548235eb015SJia Liu p[1] = tempB; 549235eb015SJia Liu p[0] = tempA; 550235eb015SJia Liu } else { 551235eb015SJia Liu p[0] = (tempB << (64 - shift)) | (tempA >> shift); 552235eb015SJia Liu p[1] = (int64_t)tempB >> shift; 553235eb015SJia Liu } 554235eb015SJia Liu } 555235eb015SJia Liu 556235eb015SJia Liu /* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/ 557235eb015SJia Liu static inline void mipsdsp_rndrashift_acc(uint64_t *p, 558235eb015SJia Liu uint32_t ac, 559235eb015SJia Liu uint32_t shift, 560235eb015SJia Liu CPUMIPSState *env) 561235eb015SJia Liu { 562235eb015SJia Liu int64_t tempB, tempA; 563235eb015SJia Liu 564235eb015SJia Liu tempB = env->active_tc.HI[ac]; 565235eb015SJia Liu tempA = env->active_tc.LO[ac]; 566235eb015SJia Liu shift = shift & 0x3F; 567235eb015SJia Liu 568235eb015SJia Liu if (shift == 0) { 569235eb015SJia Liu p[2] = tempB >> 63; 570235eb015SJia Liu p[1] = (tempB << 1) | (tempA >> 63); 571235eb015SJia Liu p[0] = tempA << 1; 572235eb015SJia Liu } else { 573235eb015SJia Liu p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1)); 574235eb015SJia Liu p[1] = (int64_t)tempB >> (shift - 1); 575235eb015SJia Liu if (tempB >= 0) { 576235eb015SJia Liu p[2] = 0x0; 577235eb015SJia Liu } else { 578235eb015SJia Liu p[2] = ~0ull; 579235eb015SJia Liu } 580235eb015SJia Liu } 581235eb015SJia Liu } 582235eb015SJia Liu 583235eb015SJia Liu static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b, 584235eb015SJia Liu CPUMIPSState *env) 585235eb015SJia Liu { 586235eb015SJia Liu int32_t temp; 587235eb015SJia Liu 588235eb015SJia Liu if ((a == 0x8000) && (b == 0x8000)) { 589235eb015SJia Liu temp = 0x7FFFFFFF; 590235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); 591235eb015SJia Liu } else { 592235eb015SJia Liu temp = ((uint32_t)a * (uint32_t)b) << 1; 593235eb015SJia Liu } 594235eb015SJia Liu 595235eb015SJia Liu return temp; 596235eb015SJia Liu } 597235eb015SJia Liu 598235eb015SJia Liu static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b, 599235eb015SJia Liu CPUMIPSState *env) 600235eb015SJia Liu { 601235eb015SJia Liu uint64_t temp; 602235eb015SJia Liu 603235eb015SJia Liu if ((a == 0x80000000) && (b == 0x80000000)) { 604235eb015SJia Liu temp = (0x01ull << 63) - 1; 605235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); 606235eb015SJia Liu } else { 607235eb015SJia Liu temp = ((uint64_t)a * (uint64_t)b) << 1; 608235eb015SJia Liu } 609235eb015SJia Liu 610235eb015SJia Liu return temp; 611235eb015SJia Liu } 612235eb015SJia Liu 613235eb015SJia Liu static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b) 614235eb015SJia Liu { 615235eb015SJia Liu return (uint16_t)a * (uint16_t)b; 616235eb015SJia Liu } 617235eb015SJia Liu 618235eb015SJia Liu static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b, 619235eb015SJia Liu CPUMIPSState *env) 620235eb015SJia Liu { 621235eb015SJia Liu uint32_t tempI; 622235eb015SJia Liu 623235eb015SJia Liu tempI = (uint32_t)a * (uint32_t)b; 624235eb015SJia Liu if (tempI > 0x0000FFFF) { 625235eb015SJia Liu tempI = 0x0000FFFF; 626235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 627235eb015SJia Liu } 628235eb015SJia Liu 629235eb015SJia Liu return tempI & 0x0000FFFF; 630235eb015SJia Liu } 631235eb015SJia Liu 632235eb015SJia Liu static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b) 633235eb015SJia Liu { 634235eb015SJia Liu return (uint64_t)a * (uint64_t)b; 635235eb015SJia Liu } 636235eb015SJia Liu 637235eb015SJia Liu static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b, 638235eb015SJia Liu CPUMIPSState *env) 639235eb015SJia Liu { 640235eb015SJia Liu uint32_t temp; 641235eb015SJia Liu 642235eb015SJia Liu if ((a == 0x8000) && (b == 0x8000)) { 643235eb015SJia Liu temp = 0x7FFF0000; 644235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 645235eb015SJia Liu } else { 646235eb015SJia Liu temp = (a * b) << 1; 647235eb015SJia Liu temp = temp + 0x00008000; 648235eb015SJia Liu } 649235eb015SJia Liu 650235eb015SJia Liu return (temp & 0xFFFF0000) >> 16; 651235eb015SJia Liu } 652235eb015SJia Liu 653235eb015SJia Liu static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b, 654235eb015SJia Liu CPUMIPSState *env) 655235eb015SJia Liu { 656235eb015SJia Liu int32_t temp; 657235eb015SJia Liu 658235eb015SJia Liu if ((a == 0x8000) && (b == 0x8000)) { 659235eb015SJia Liu temp = 0x7FFF0000; 660235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 661235eb015SJia Liu } else { 662235eb015SJia Liu temp = ((uint32_t)a * (uint32_t)b); 663235eb015SJia Liu temp = temp << 1; 664235eb015SJia Liu } 665235eb015SJia Liu 666235eb015SJia Liu return (temp >> 16) & 0x0000FFFF; 667235eb015SJia Liu } 668235eb015SJia Liu 669235eb015SJia Liu static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a, 670235eb015SJia Liu CPUMIPSState *env) 671235eb015SJia Liu { 672235eb015SJia Liu int64_t temp; 673235eb015SJia Liu 674235eb015SJia Liu temp = (int32_t)a + 0x00008000; 675235eb015SJia Liu 676235eb015SJia Liu if (a > (int)0x7fff8000) { 677235eb015SJia Liu temp = 0x7FFFFFFF; 678235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 679235eb015SJia Liu } 680235eb015SJia Liu 681235eb015SJia Liu return (temp >> 16) & 0xFFFF; 682235eb015SJia Liu } 683235eb015SJia Liu 684235eb015SJia Liu static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a, 685235eb015SJia Liu CPUMIPSState *env) 686235eb015SJia Liu { 687235eb015SJia Liu uint16_t mag; 688235eb015SJia Liu uint32_t sign; 689235eb015SJia Liu 690235eb015SJia Liu sign = (a >> 15) & 0x01; 691235eb015SJia Liu mag = a & 0x7FFF; 692235eb015SJia Liu 693235eb015SJia Liu if (sign == 0) { 694235eb015SJia Liu if (mag > 0x7F80) { 695235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 696235eb015SJia Liu return 0xFF; 697235eb015SJia Liu } else { 698235eb015SJia Liu return (mag >> 7) & 0xFFFF; 699235eb015SJia Liu } 700235eb015SJia Liu } else { 701235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 702235eb015SJia Liu return 0x00; 703235eb015SJia Liu } 704235eb015SJia Liu } 705235eb015SJia Liu 706235eb015SJia Liu static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env) 707235eb015SJia Liu { 708235eb015SJia Liu uint8_t sign; 709235eb015SJia Liu uint8_t discard; 710235eb015SJia Liu 711235eb015SJia Liu if (s == 0) { 712235eb015SJia Liu return a; 713235eb015SJia Liu } else { 714235eb015SJia Liu sign = (a >> 7) & 0x01; 715235eb015SJia Liu if (sign != 0) { 716235eb015SJia Liu discard = (((0x01 << (8 - s)) - 1) << s) | 717235eb015SJia Liu ((a >> (6 - (s - 1))) & ((0x01 << s) - 1)); 718235eb015SJia Liu } else { 719235eb015SJia Liu discard = a >> (6 - (s - 1)); 720235eb015SJia Liu } 721235eb015SJia Liu 722235eb015SJia Liu if (discard != 0x00) { 723235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 724235eb015SJia Liu } 725235eb015SJia Liu return a << s; 726235eb015SJia Liu } 727235eb015SJia Liu } 728235eb015SJia Liu 729235eb015SJia Liu static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s, 730235eb015SJia Liu CPUMIPSState *env) 731235eb015SJia Liu { 732235eb015SJia Liu uint8_t sign; 733235eb015SJia Liu uint16_t discard; 734235eb015SJia Liu 735235eb015SJia Liu if (s == 0) { 736235eb015SJia Liu return a; 737235eb015SJia Liu } else { 738235eb015SJia Liu sign = (a >> 15) & 0x01; 739235eb015SJia Liu if (sign != 0) { 740235eb015SJia Liu discard = (((0x01 << (16 - s)) - 1) << s) | 741235eb015SJia Liu ((a >> (14 - (s - 1))) & ((0x01 << s) - 1)); 742235eb015SJia Liu } else { 743235eb015SJia Liu discard = a >> (14 - (s - 1)); 744235eb015SJia Liu } 745235eb015SJia Liu 746235eb015SJia Liu if ((discard != 0x0000) && (discard != 0xFFFF)) { 747235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 748235eb015SJia Liu } 749235eb015SJia Liu return a << s; 750235eb015SJia Liu } 751235eb015SJia Liu } 752235eb015SJia Liu 753235eb015SJia Liu 754235eb015SJia Liu static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s, 755235eb015SJia Liu CPUMIPSState *env) 756235eb015SJia Liu { 757235eb015SJia Liu uint32_t discard; 758235eb015SJia Liu 759235eb015SJia Liu if (s == 0) { 760235eb015SJia Liu return a; 761235eb015SJia Liu } else { 762235eb015SJia Liu discard = (int32_t)a >> (31 - (s - 1)); 763235eb015SJia Liu 764235eb015SJia Liu if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) { 765235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 766235eb015SJia Liu } 767235eb015SJia Liu return a << s; 768235eb015SJia Liu } 769235eb015SJia Liu } 770235eb015SJia Liu 771235eb015SJia Liu static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s, 772235eb015SJia Liu CPUMIPSState *env) 773235eb015SJia Liu { 774235eb015SJia Liu uint8_t sign; 775235eb015SJia Liu uint16_t discard; 776235eb015SJia Liu 777235eb015SJia Liu if (s == 0) { 778235eb015SJia Liu return a; 779235eb015SJia Liu } else { 780235eb015SJia Liu sign = (a >> 15) & 0x01; 781235eb015SJia Liu if (sign != 0) { 782235eb015SJia Liu discard = (((0x01 << (16 - s)) - 1) << s) | 783235eb015SJia Liu ((a >> (14 - (s - 1))) & ((0x01 << s) - 1)); 784235eb015SJia Liu } else { 785235eb015SJia Liu discard = a >> (14 - (s - 1)); 786235eb015SJia Liu } 787235eb015SJia Liu 788235eb015SJia Liu if ((discard != 0x0000) && (discard != 0xFFFF)) { 789235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 790235eb015SJia Liu return (sign == 0) ? 0x7FFF : 0x8000; 791235eb015SJia Liu } else { 792235eb015SJia Liu return a << s; 793235eb015SJia Liu } 794235eb015SJia Liu } 795235eb015SJia Liu } 796235eb015SJia Liu 797235eb015SJia Liu static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s, 798235eb015SJia Liu CPUMIPSState *env) 799235eb015SJia Liu { 800235eb015SJia Liu uint8_t sign; 801235eb015SJia Liu uint32_t discard; 802235eb015SJia Liu 803235eb015SJia Liu if (s == 0) { 804235eb015SJia Liu return a; 805235eb015SJia Liu } else { 806235eb015SJia Liu sign = (a >> 31) & 0x01; 807235eb015SJia Liu if (sign != 0) { 808235eb015SJia Liu discard = (((0x01 << (32 - s)) - 1) << s) | 809235eb015SJia Liu ((a >> (30 - (s - 1))) & ((0x01 << s) - 1)); 810235eb015SJia Liu } else { 811235eb015SJia Liu discard = a >> (30 - (s - 1)); 812235eb015SJia Liu } 813235eb015SJia Liu 814235eb015SJia Liu if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) { 815235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 816235eb015SJia Liu return (sign == 0) ? 0x7FFFFFFF : 0x80000000; 817235eb015SJia Liu } else { 818235eb015SJia Liu return a << s; 819235eb015SJia Liu } 820235eb015SJia Liu } 821235eb015SJia Liu } 822235eb015SJia Liu 823235eb015SJia Liu static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s) 824235eb015SJia Liu { 825235eb015SJia Liu uint32_t temp; 826235eb015SJia Liu 827235eb015SJia Liu if (s == 0) { 828235eb015SJia Liu temp = (uint32_t)a << 1; 829235eb015SJia Liu } else { 830235eb015SJia Liu temp = (int32_t)(int8_t)a >> (s - 1); 831235eb015SJia Liu } 832235eb015SJia Liu 833235eb015SJia Liu return (temp + 1) >> 1; 834235eb015SJia Liu } 835235eb015SJia Liu 836235eb015SJia Liu static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s) 837235eb015SJia Liu { 838235eb015SJia Liu uint32_t temp; 839235eb015SJia Liu 840235eb015SJia Liu if (s == 0) { 841235eb015SJia Liu temp = (uint32_t)a << 1; 842235eb015SJia Liu } else { 843235eb015SJia Liu temp = (int32_t)(int16_t)a >> (s - 1); 844235eb015SJia Liu } 845235eb015SJia Liu 846235eb015SJia Liu return (temp + 1) >> 1; 847235eb015SJia Liu } 848235eb015SJia Liu 849235eb015SJia Liu static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s) 850235eb015SJia Liu { 851235eb015SJia Liu int64_t temp; 852235eb015SJia Liu 853235eb015SJia Liu if (s == 0) { 854235eb015SJia Liu temp = (uint64_t)a << 1; 855235eb015SJia Liu } else { 856235eb015SJia Liu temp = (int64_t)(int32_t)a >> (s - 1); 857235eb015SJia Liu } 858235eb015SJia Liu temp += 1; 859235eb015SJia Liu 860235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFFull; 861235eb015SJia Liu } 862235eb015SJia Liu 863235eb015SJia Liu static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env) 864235eb015SJia Liu { 865235eb015SJia Liu int16_t temp; 866235eb015SJia Liu 867235eb015SJia Liu temp = a - b; 868235eb015SJia Liu if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) { 869235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 870235eb015SJia Liu } 871235eb015SJia Liu 872235eb015SJia Liu return temp; 873235eb015SJia Liu } 874235eb015SJia Liu 875235eb015SJia Liu static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b, 876235eb015SJia Liu CPUMIPSState *env) 877235eb015SJia Liu { 878235eb015SJia Liu int16_t temp; 879235eb015SJia Liu 880235eb015SJia Liu temp = a - b; 881235eb015SJia Liu if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) { 882235eb015SJia Liu if (a > 0) { 883235eb015SJia Liu temp = 0x7FFF; 884235eb015SJia Liu } else { 885235eb015SJia Liu temp = 0x8000; 886235eb015SJia Liu } 887235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 888235eb015SJia Liu } 889235eb015SJia Liu 890235eb015SJia Liu return temp; 891235eb015SJia Liu } 892235eb015SJia Liu 893235eb015SJia Liu static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b, 894235eb015SJia Liu CPUMIPSState *env) 895235eb015SJia Liu { 896235eb015SJia Liu int32_t temp; 897235eb015SJia Liu 898235eb015SJia Liu temp = a - b; 899235eb015SJia Liu if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) { 900235eb015SJia Liu if (a > 0) { 901235eb015SJia Liu temp = 0x7FFFFFFF; 902235eb015SJia Liu } else { 903235eb015SJia Liu temp = 0x80000000; 904235eb015SJia Liu } 905235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 906235eb015SJia Liu } 907235eb015SJia Liu 908235eb015SJia Liu return temp & 0xFFFFFFFFull; 909235eb015SJia Liu } 910235eb015SJia Liu 911235eb015SJia Liu static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b) 912235eb015SJia Liu { 913235eb015SJia Liu int32_t temp; 914235eb015SJia Liu 915235eb015SJia Liu temp = (int32_t)a - (int32_t)b; 916235eb015SJia Liu 917235eb015SJia Liu return (temp >> 1) & 0x0000FFFF; 918235eb015SJia Liu } 919235eb015SJia Liu 920235eb015SJia Liu static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b) 921235eb015SJia Liu { 922235eb015SJia Liu int32_t temp; 923235eb015SJia Liu 924235eb015SJia Liu temp = (int32_t)a - (int32_t)b; 925235eb015SJia Liu temp += 1; 926235eb015SJia Liu 927235eb015SJia Liu return (temp >> 1) & 0x0000FFFF; 928235eb015SJia Liu } 929235eb015SJia Liu 930235eb015SJia Liu static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b) 931235eb015SJia Liu { 932235eb015SJia Liu int64_t temp; 933235eb015SJia Liu 934235eb015SJia Liu temp = (int64_t)a - (int64_t)b; 935235eb015SJia Liu 936235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFFull; 937235eb015SJia Liu } 938235eb015SJia Liu 939235eb015SJia Liu static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b) 940235eb015SJia Liu { 941235eb015SJia Liu int64_t temp; 942235eb015SJia Liu 943235eb015SJia Liu temp = (int64_t)a - (int64_t)b; 944235eb015SJia Liu temp += 1; 945235eb015SJia Liu 946235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFFull; 947235eb015SJia Liu } 948235eb015SJia Liu 949235eb015SJia Liu static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b, 950235eb015SJia Liu CPUMIPSState *env) 951235eb015SJia Liu { 952235eb015SJia Liu uint8_t temp16; 953235eb015SJia Liu uint32_t temp; 954235eb015SJia Liu 955235eb015SJia Liu temp = (uint32_t)a - (uint32_t)b; 956235eb015SJia Liu temp16 = (temp >> 16) & 0x01; 957235eb015SJia Liu if (temp16 == 1) { 958235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 959235eb015SJia Liu } 960235eb015SJia Liu return temp & 0x0000FFFF; 961235eb015SJia Liu } 962235eb015SJia Liu 963235eb015SJia Liu static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b, 964235eb015SJia Liu CPUMIPSState *env) 965235eb015SJia Liu { 966235eb015SJia Liu uint8_t temp16; 967235eb015SJia Liu uint32_t temp; 968235eb015SJia Liu 969235eb015SJia Liu temp = (uint32_t)a - (uint32_t)b; 970235eb015SJia Liu temp16 = (temp >> 16) & 0x01; 971235eb015SJia Liu 972235eb015SJia Liu if (temp16 == 1) { 973235eb015SJia Liu temp = 0x0000; 974235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 975235eb015SJia Liu } 976235eb015SJia Liu 977235eb015SJia Liu return temp & 0x0000FFFF; 978235eb015SJia Liu } 979235eb015SJia Liu 980235eb015SJia Liu static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env) 981235eb015SJia Liu { 982235eb015SJia Liu uint8_t temp8; 983235eb015SJia Liu uint16_t temp; 984235eb015SJia Liu 985235eb015SJia Liu temp = (uint16_t)a - (uint16_t)b; 986235eb015SJia Liu temp8 = (temp >> 8) & 0x01; 987235eb015SJia Liu if (temp8 == 1) { 988235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 989235eb015SJia Liu } 990235eb015SJia Liu 991235eb015SJia Liu return temp & 0x00FF; 992235eb015SJia Liu } 993235eb015SJia Liu 994235eb015SJia Liu static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env) 995235eb015SJia Liu { 996235eb015SJia Liu uint8_t temp8; 997235eb015SJia Liu uint16_t temp; 998235eb015SJia Liu 999235eb015SJia Liu temp = (uint16_t)a - (uint16_t)b; 1000235eb015SJia Liu temp8 = (temp >> 8) & 0x01; 1001235eb015SJia Liu if (temp8 == 1) { 1002235eb015SJia Liu temp = 0x00; 1003235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 1004235eb015SJia Liu } 1005235eb015SJia Liu 1006235eb015SJia Liu return temp & 0x00FF; 1007235eb015SJia Liu } 1008235eb015SJia Liu 1009235eb015SJia Liu static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env) 1010235eb015SJia Liu { 1011235eb015SJia Liu int32_t temp; 1012235eb015SJia Liu 1013235eb015SJia Liu temp = a - b; 1014235eb015SJia Liu if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) { 1015235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 1016235eb015SJia Liu } 1017235eb015SJia Liu 1018235eb015SJia Liu return temp; 1019235eb015SJia Liu } 1020235eb015SJia Liu 1021235eb015SJia Liu static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env) 1022235eb015SJia Liu { 1023235eb015SJia Liu int32_t temp; 1024235eb015SJia Liu 1025235eb015SJia Liu temp = a + b; 1026235eb015SJia Liu 1027235eb015SJia Liu if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) { 1028235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 1029235eb015SJia Liu } 1030235eb015SJia Liu 1031235eb015SJia Liu return temp; 1032235eb015SJia Liu } 1033235eb015SJia Liu 1034235eb015SJia Liu static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b) 1035235eb015SJia Liu { 1036235eb015SJia Liu return a == b; 1037235eb015SJia Liu } 1038235eb015SJia Liu 1039235eb015SJia Liu static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b) 1040235eb015SJia Liu { 1041235eb015SJia Liu return a <= b; 1042235eb015SJia Liu } 1043235eb015SJia Liu 1044235eb015SJia Liu static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b) 1045235eb015SJia Liu { 1046235eb015SJia Liu return a < b; 1047235eb015SJia Liu } 1048235eb015SJia Liu 1049235eb015SJia Liu static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b) 1050235eb015SJia Liu { 1051235eb015SJia Liu return a == b; 1052235eb015SJia Liu } 1053235eb015SJia Liu 1054235eb015SJia Liu static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b) 1055235eb015SJia Liu { 1056235eb015SJia Liu return a <= b; 1057235eb015SJia Liu } 1058235eb015SJia Liu 1059235eb015SJia Liu static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b) 1060235eb015SJia Liu { 1061235eb015SJia Liu return a < b; 1062235eb015SJia Liu } 1063235eb015SJia Liu /*** MIPS DSP internal functions end ***/ 1064461c08dfSJia Liu 1065461c08dfSJia Liu #define MIPSDSP_LHI 0xFFFFFFFF00000000ull 1066461c08dfSJia Liu #define MIPSDSP_LLO 0x00000000FFFFFFFFull 1067461c08dfSJia Liu #define MIPSDSP_HI 0xFFFF0000 1068461c08dfSJia Liu #define MIPSDSP_LO 0x0000FFFF 1069461c08dfSJia Liu #define MIPSDSP_Q3 0xFF000000 1070461c08dfSJia Liu #define MIPSDSP_Q2 0x00FF0000 1071461c08dfSJia Liu #define MIPSDSP_Q1 0x0000FF00 1072461c08dfSJia Liu #define MIPSDSP_Q0 0x000000FF 1073461c08dfSJia Liu 1074461c08dfSJia Liu #define MIPSDSP_SPLIT32_8(num, a, b, c, d) \ 1075461c08dfSJia Liu do { \ 1076461c08dfSJia Liu a = (num >> 24) & MIPSDSP_Q0; \ 1077461c08dfSJia Liu b = (num >> 16) & MIPSDSP_Q0; \ 1078461c08dfSJia Liu c = (num >> 8) & MIPSDSP_Q0; \ 1079461c08dfSJia Liu d = num & MIPSDSP_Q0; \ 1080461c08dfSJia Liu } while (0) 1081461c08dfSJia Liu 1082461c08dfSJia Liu #define MIPSDSP_SPLIT32_16(num, a, b) \ 1083461c08dfSJia Liu do { \ 1084461c08dfSJia Liu a = (num >> 16) & MIPSDSP_LO; \ 1085461c08dfSJia Liu b = num & MIPSDSP_LO; \ 1086461c08dfSJia Liu } while (0) 1087461c08dfSJia Liu 1088461c08dfSJia Liu #define MIPSDSP_RETURN32(a) ((target_long)(int32_t)a) 1089461c08dfSJia Liu #define MIPSDSP_RETURN32_8(a, b, c, d) ((target_long)(int32_t) \ 1090461c08dfSJia Liu (((uint32_t)a << 24) | \ 1091461c08dfSJia Liu (((uint32_t)b << 16) | \ 1092461c08dfSJia Liu (((uint32_t)c << 8) | \ 1093461c08dfSJia Liu ((uint32_t)d & 0xFF))))) 1094461c08dfSJia Liu #define MIPSDSP_RETURN32_16(a, b) ((target_long)(int32_t) \ 1095461c08dfSJia Liu (((uint32_t)a << 16) | \ 1096461c08dfSJia Liu ((uint32_t)b & 0xFFFF))) 1097461c08dfSJia Liu 1098461c08dfSJia Liu #ifdef TARGET_MIPS64 1099461c08dfSJia Liu #define MIPSDSP_SPLIT64_16(num, a, b, c, d) \ 1100461c08dfSJia Liu do { \ 1101461c08dfSJia Liu a = (num >> 48) & MIPSDSP_LO; \ 1102461c08dfSJia Liu b = (num >> 32) & MIPSDSP_LO; \ 1103461c08dfSJia Liu c = (num >> 16) & MIPSDSP_LO; \ 1104461c08dfSJia Liu d = num & MIPSDSP_LO; \ 1105461c08dfSJia Liu } while (0) 1106461c08dfSJia Liu 1107461c08dfSJia Liu #define MIPSDSP_SPLIT64_32(num, a, b) \ 1108461c08dfSJia Liu do { \ 1109461c08dfSJia Liu a = (num >> 32) & MIPSDSP_LLO; \ 1110461c08dfSJia Liu b = num & MIPSDSP_LLO; \ 1111461c08dfSJia Liu } while (0) 1112461c08dfSJia Liu 1113461c08dfSJia Liu #define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \ 1114461c08dfSJia Liu ((uint64_t)b << 32) | \ 1115461c08dfSJia Liu ((uint64_t)c << 16) | \ 1116461c08dfSJia Liu (uint64_t)d) 1117461c08dfSJia Liu #define MIPSDSP_RETURN64_32(a, b) (((uint64_t)a << 32) | (uint64_t)b) 1118461c08dfSJia Liu #endif 1119461c08dfSJia Liu 1120461c08dfSJia Liu /** DSP Arithmetic Sub-class insns **/ 1121461c08dfSJia Liu #define ARITH_PH(name, func) \ 1122461c08dfSJia Liu target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt) \ 1123461c08dfSJia Liu { \ 1124461c08dfSJia Liu uint16_t rsh, rsl, rth, rtl, temph, templ; \ 1125461c08dfSJia Liu \ 1126461c08dfSJia Liu MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ 1127461c08dfSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 1128461c08dfSJia Liu \ 1129461c08dfSJia Liu temph = mipsdsp_##func(rsh, rth); \ 1130461c08dfSJia Liu templ = mipsdsp_##func(rsl, rtl); \ 1131461c08dfSJia Liu \ 1132461c08dfSJia Liu return MIPSDSP_RETURN32_16(temph, templ); \ 1133461c08dfSJia Liu } 1134461c08dfSJia Liu 1135461c08dfSJia Liu #define ARITH_PH_ENV(name, func) \ 1136461c08dfSJia Liu target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt, \ 1137461c08dfSJia Liu CPUMIPSState *env) \ 1138461c08dfSJia Liu { \ 1139461c08dfSJia Liu uint16_t rsh, rsl, rth, rtl, temph, templ; \ 1140461c08dfSJia Liu \ 1141461c08dfSJia Liu MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ 1142461c08dfSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 1143461c08dfSJia Liu \ 1144461c08dfSJia Liu temph = mipsdsp_##func(rsh, rth, env); \ 1145461c08dfSJia Liu templ = mipsdsp_##func(rsl, rtl, env); \ 1146461c08dfSJia Liu \ 1147461c08dfSJia Liu return MIPSDSP_RETURN32_16(temph, templ); \ 1148461c08dfSJia Liu } 1149461c08dfSJia Liu 1150461c08dfSJia Liu 1151461c08dfSJia Liu ARITH_PH_ENV(addq, add_i16); 1152461c08dfSJia Liu ARITH_PH_ENV(addq_s, sat_add_i16); 1153461c08dfSJia Liu ARITH_PH_ENV(addu, add_u16); 1154461c08dfSJia Liu ARITH_PH_ENV(addu_s, sat_add_u16); 1155461c08dfSJia Liu 1156461c08dfSJia Liu ARITH_PH(addqh, rshift1_add_q16); 1157461c08dfSJia Liu ARITH_PH(addqh_r, rrshift1_add_q16); 1158461c08dfSJia Liu 1159461c08dfSJia Liu ARITH_PH_ENV(subq, sub_i16); 1160461c08dfSJia Liu ARITH_PH_ENV(subq_s, sat16_sub); 1161461c08dfSJia Liu ARITH_PH_ENV(subu, sub_u16_u16); 1162461c08dfSJia Liu ARITH_PH_ENV(subu_s, satu16_sub_u16_u16); 1163461c08dfSJia Liu 1164461c08dfSJia Liu ARITH_PH(subqh, rshift1_sub_q16); 1165461c08dfSJia Liu ARITH_PH(subqh_r, rrshift1_sub_q16); 1166461c08dfSJia Liu 1167461c08dfSJia Liu #undef ARITH_PH 1168461c08dfSJia Liu #undef ARITH_PH_ENV 1169461c08dfSJia Liu 1170461c08dfSJia Liu #ifdef TARGET_MIPS64 1171461c08dfSJia Liu #define ARITH_QH_ENV(name, func) \ 1172461c08dfSJia Liu target_ulong helper_##name##_qh(target_ulong rs, target_ulong rt, \ 1173461c08dfSJia Liu CPUMIPSState *env) \ 1174461c08dfSJia Liu { \ 1175461c08dfSJia Liu uint16_t rs3, rs2, rs1, rs0; \ 1176461c08dfSJia Liu uint16_t rt3, rt2, rt1, rt0; \ 1177461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 1178461c08dfSJia Liu \ 1179461c08dfSJia Liu MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ 1180461c08dfSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 1181461c08dfSJia Liu \ 1182461c08dfSJia Liu tempD = mipsdsp_##func(rs3, rt3, env); \ 1183461c08dfSJia Liu tempC = mipsdsp_##func(rs2, rt2, env); \ 1184461c08dfSJia Liu tempB = mipsdsp_##func(rs1, rt1, env); \ 1185461c08dfSJia Liu tempA = mipsdsp_##func(rs0, rt0, env); \ 1186461c08dfSJia Liu \ 1187461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1188461c08dfSJia Liu } 1189461c08dfSJia Liu 1190461c08dfSJia Liu ARITH_QH_ENV(addq, add_i16); 1191461c08dfSJia Liu ARITH_QH_ENV(addq_s, sat_add_i16); 1192461c08dfSJia Liu ARITH_QH_ENV(addu, add_u16); 1193461c08dfSJia Liu ARITH_QH_ENV(addu_s, sat_add_u16); 1194461c08dfSJia Liu 1195461c08dfSJia Liu ARITH_QH_ENV(subq, sub_i16); 1196461c08dfSJia Liu ARITH_QH_ENV(subq_s, sat16_sub); 1197461c08dfSJia Liu ARITH_QH_ENV(subu, sub_u16_u16); 1198461c08dfSJia Liu ARITH_QH_ENV(subu_s, satu16_sub_u16_u16); 1199461c08dfSJia Liu 1200461c08dfSJia Liu #undef ARITH_QH_ENV 1201461c08dfSJia Liu 1202461c08dfSJia Liu #endif 1203461c08dfSJia Liu 1204461c08dfSJia Liu #define ARITH_W(name, func) \ 1205461c08dfSJia Liu target_ulong helper_##name##_w(target_ulong rs, target_ulong rt) \ 1206461c08dfSJia Liu { \ 1207461c08dfSJia Liu uint32_t rd; \ 1208461c08dfSJia Liu rd = mipsdsp_##func(rs, rt); \ 1209461c08dfSJia Liu return MIPSDSP_RETURN32(rd); \ 1210461c08dfSJia Liu } 1211461c08dfSJia Liu 1212461c08dfSJia Liu #define ARITH_W_ENV(name, func) \ 1213461c08dfSJia Liu target_ulong helper_##name##_w(target_ulong rs, target_ulong rt, \ 1214461c08dfSJia Liu CPUMIPSState *env) \ 1215461c08dfSJia Liu { \ 1216461c08dfSJia Liu uint32_t rd; \ 1217461c08dfSJia Liu rd = mipsdsp_##func(rs, rt, env); \ 1218461c08dfSJia Liu return MIPSDSP_RETURN32(rd); \ 1219461c08dfSJia Liu } 1220461c08dfSJia Liu 1221461c08dfSJia Liu ARITH_W_ENV(addq_s, sat_add_i32); 1222461c08dfSJia Liu 1223461c08dfSJia Liu ARITH_W(addqh, rshift1_add_q32); 1224461c08dfSJia Liu ARITH_W(addqh_r, rrshift1_add_q32); 1225461c08dfSJia Liu 1226461c08dfSJia Liu ARITH_W_ENV(subq_s, sat32_sub); 1227461c08dfSJia Liu 1228461c08dfSJia Liu ARITH_W(subqh, rshift1_sub_q32); 1229461c08dfSJia Liu ARITH_W(subqh_r, rrshift1_sub_q32); 1230461c08dfSJia Liu 1231461c08dfSJia Liu #undef ARITH_W 1232461c08dfSJia Liu #undef ARITH_W_ENV 1233461c08dfSJia Liu 1234461c08dfSJia Liu target_ulong helper_absq_s_w(target_ulong rt, CPUMIPSState *env) 1235461c08dfSJia Liu { 1236461c08dfSJia Liu uint32_t rd; 1237461c08dfSJia Liu 1238461c08dfSJia Liu rd = mipsdsp_sat_abs32(rt, env); 1239461c08dfSJia Liu 1240461c08dfSJia Liu return (target_ulong)rd; 1241461c08dfSJia Liu } 1242461c08dfSJia Liu 1243461c08dfSJia Liu 1244461c08dfSJia Liu #if defined(TARGET_MIPS64) 1245461c08dfSJia Liu 1246461c08dfSJia Liu #define ARITH_PW_ENV(name, func) \ 1247461c08dfSJia Liu target_ulong helper_##name##_pw(target_ulong rs, target_ulong rt, \ 1248461c08dfSJia Liu CPUMIPSState *env) \ 1249461c08dfSJia Liu { \ 1250461c08dfSJia Liu uint32_t rs1, rs0; \ 1251461c08dfSJia Liu uint32_t rt1, rt0; \ 1252461c08dfSJia Liu uint32_t tempB, tempA; \ 1253461c08dfSJia Liu \ 1254461c08dfSJia Liu MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ 1255461c08dfSJia Liu MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 1256461c08dfSJia Liu \ 1257461c08dfSJia Liu tempB = mipsdsp_##func(rs1, rt1, env); \ 1258461c08dfSJia Liu tempA = mipsdsp_##func(rs0, rt0, env); \ 1259461c08dfSJia Liu \ 1260461c08dfSJia Liu return MIPSDSP_RETURN64_32(tempB, tempA); \ 1261461c08dfSJia Liu } 1262461c08dfSJia Liu 1263461c08dfSJia Liu ARITH_PW_ENV(addq, add_i32); 1264461c08dfSJia Liu ARITH_PW_ENV(addq_s, sat_add_i32); 1265461c08dfSJia Liu ARITH_PW_ENV(subq, sub32); 1266461c08dfSJia Liu ARITH_PW_ENV(subq_s, sat32_sub); 1267461c08dfSJia Liu 1268461c08dfSJia Liu #undef ARITH_PW_ENV 1269461c08dfSJia Liu 1270461c08dfSJia Liu #endif 1271461c08dfSJia Liu 1272461c08dfSJia Liu #define ARITH_QB(name, func) \ 1273461c08dfSJia Liu target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \ 1274461c08dfSJia Liu { \ 1275461c08dfSJia Liu uint8_t rs0, rs1, rs2, rs3; \ 1276461c08dfSJia Liu uint8_t rt0, rt1, rt2, rt3; \ 1277461c08dfSJia Liu uint8_t temp0, temp1, temp2, temp3; \ 1278461c08dfSJia Liu \ 1279461c08dfSJia Liu MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ 1280461c08dfSJia Liu MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 1281461c08dfSJia Liu \ 1282461c08dfSJia Liu temp0 = mipsdsp_##func(rs0, rt0); \ 1283461c08dfSJia Liu temp1 = mipsdsp_##func(rs1, rt1); \ 1284461c08dfSJia Liu temp2 = mipsdsp_##func(rs2, rt2); \ 1285461c08dfSJia Liu temp3 = mipsdsp_##func(rs3, rt3); \ 1286461c08dfSJia Liu \ 1287461c08dfSJia Liu return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0); \ 1288461c08dfSJia Liu } 1289461c08dfSJia Liu 1290461c08dfSJia Liu #define ARITH_QB_ENV(name, func) \ 1291461c08dfSJia Liu target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt, \ 1292461c08dfSJia Liu CPUMIPSState *env) \ 1293461c08dfSJia Liu { \ 1294461c08dfSJia Liu uint8_t rs0, rs1, rs2, rs3; \ 1295461c08dfSJia Liu uint8_t rt0, rt1, rt2, rt3; \ 1296461c08dfSJia Liu uint8_t temp0, temp1, temp2, temp3; \ 1297461c08dfSJia Liu \ 1298461c08dfSJia Liu MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ 1299461c08dfSJia Liu MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 1300461c08dfSJia Liu \ 1301461c08dfSJia Liu temp0 = mipsdsp_##func(rs0, rt0, env); \ 1302461c08dfSJia Liu temp1 = mipsdsp_##func(rs1, rt1, env); \ 1303461c08dfSJia Liu temp2 = mipsdsp_##func(rs2, rt2, env); \ 1304461c08dfSJia Liu temp3 = mipsdsp_##func(rs3, rt3, env); \ 1305461c08dfSJia Liu \ 1306461c08dfSJia Liu return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0); \ 1307461c08dfSJia Liu } 1308461c08dfSJia Liu 1309461c08dfSJia Liu ARITH_QB(adduh, rshift1_add_u8); 1310461c08dfSJia Liu ARITH_QB(adduh_r, rrshift1_add_u8); 1311461c08dfSJia Liu 1312461c08dfSJia Liu ARITH_QB_ENV(addu, add_u8); 1313461c08dfSJia Liu ARITH_QB_ENV(addu_s, sat_add_u8); 1314461c08dfSJia Liu 1315461c08dfSJia Liu #undef ADDU_QB 1316461c08dfSJia Liu #undef ADDU_QB_ENV 1317461c08dfSJia Liu 1318461c08dfSJia Liu #if defined(TARGET_MIPS64) 1319461c08dfSJia Liu #define ARITH_OB(name, func) \ 1320461c08dfSJia Liu target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt) \ 1321461c08dfSJia Liu { \ 1322461c08dfSJia Liu int i; \ 1323461c08dfSJia Liu uint8_t rs_t[8], rt_t[8]; \ 1324461c08dfSJia Liu uint8_t temp[8]; \ 1325461c08dfSJia Liu uint64_t result; \ 1326461c08dfSJia Liu \ 1327461c08dfSJia Liu result = 0; \ 1328461c08dfSJia Liu \ 1329461c08dfSJia Liu for (i = 0; i < 8; i++) { \ 1330461c08dfSJia Liu rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0; \ 1331461c08dfSJia Liu rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ 1332461c08dfSJia Liu temp[i] = mipsdsp_##func(rs_t[i], rt_t[i]); \ 1333461c08dfSJia Liu result |= (uint64_t)temp[i] << (8 * i); \ 1334461c08dfSJia Liu } \ 1335461c08dfSJia Liu \ 1336461c08dfSJia Liu return result; \ 1337461c08dfSJia Liu } 1338461c08dfSJia Liu 1339461c08dfSJia Liu #define ARITH_OB_ENV(name, func) \ 1340461c08dfSJia Liu target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt, \ 1341461c08dfSJia Liu CPUMIPSState *env) \ 1342461c08dfSJia Liu { \ 1343461c08dfSJia Liu int i; \ 1344461c08dfSJia Liu uint8_t rs_t[8], rt_t[8]; \ 1345461c08dfSJia Liu uint8_t temp[8]; \ 1346461c08dfSJia Liu uint64_t result; \ 1347461c08dfSJia Liu \ 1348461c08dfSJia Liu result = 0; \ 1349461c08dfSJia Liu \ 1350461c08dfSJia Liu for (i = 0; i < 8; i++) { \ 1351461c08dfSJia Liu rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0; \ 1352461c08dfSJia Liu rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ 1353461c08dfSJia Liu temp[i] = mipsdsp_##func(rs_t[i], rt_t[i], env); \ 1354461c08dfSJia Liu result |= (uint64_t)temp[i] << (8 * i); \ 1355461c08dfSJia Liu } \ 1356461c08dfSJia Liu \ 1357461c08dfSJia Liu return result; \ 1358461c08dfSJia Liu } 1359461c08dfSJia Liu 1360461c08dfSJia Liu ARITH_OB_ENV(addu, add_u8); 1361461c08dfSJia Liu ARITH_OB_ENV(addu_s, sat_add_u8); 1362461c08dfSJia Liu 1363461c08dfSJia Liu ARITH_OB(adduh, rshift1_add_u8); 1364461c08dfSJia Liu ARITH_OB(adduh_r, rrshift1_add_u8); 1365461c08dfSJia Liu 1366461c08dfSJia Liu ARITH_OB_ENV(subu, sub_u8); 1367461c08dfSJia Liu ARITH_OB_ENV(subu_s, satu8_sub); 1368461c08dfSJia Liu 1369461c08dfSJia Liu ARITH_OB(subuh, rshift1_sub_u8); 1370461c08dfSJia Liu ARITH_OB(subuh_r, rrshift1_sub_u8); 1371461c08dfSJia Liu 1372461c08dfSJia Liu #undef ARITH_OB 1373461c08dfSJia Liu #undef ARITH_OB_ENV 1374461c08dfSJia Liu 1375461c08dfSJia Liu #endif 1376461c08dfSJia Liu 1377461c08dfSJia Liu #define SUBU_QB(name, func) \ 1378461c08dfSJia Liu target_ulong helper_##name##_qb(target_ulong rs, \ 1379461c08dfSJia Liu target_ulong rt, \ 1380461c08dfSJia Liu CPUMIPSState *env) \ 1381461c08dfSJia Liu { \ 1382461c08dfSJia Liu uint8_t rs3, rs2, rs1, rs0; \ 1383461c08dfSJia Liu uint8_t rt3, rt2, rt1, rt0; \ 1384461c08dfSJia Liu uint8_t tempD, tempC, tempB, tempA; \ 1385461c08dfSJia Liu \ 1386461c08dfSJia Liu MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ 1387461c08dfSJia Liu MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 1388461c08dfSJia Liu \ 1389461c08dfSJia Liu tempD = mipsdsp_##func(rs3, rt3, env); \ 1390461c08dfSJia Liu tempC = mipsdsp_##func(rs2, rt2, env); \ 1391461c08dfSJia Liu tempB = mipsdsp_##func(rs1, rt1, env); \ 1392461c08dfSJia Liu tempA = mipsdsp_##func(rs0, rt0, env); \ 1393461c08dfSJia Liu \ 1394461c08dfSJia Liu return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); \ 1395461c08dfSJia Liu } 1396461c08dfSJia Liu 1397461c08dfSJia Liu SUBU_QB(subu, sub_u8); 1398461c08dfSJia Liu SUBU_QB(subu_s, satu8_sub); 1399461c08dfSJia Liu 1400461c08dfSJia Liu #undef SUBU_QB 1401461c08dfSJia Liu 1402461c08dfSJia Liu #define SUBUH_QB(name, var) \ 1403461c08dfSJia Liu target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \ 1404461c08dfSJia Liu { \ 1405461c08dfSJia Liu uint8_t rs3, rs2, rs1, rs0; \ 1406461c08dfSJia Liu uint8_t rt3, rt2, rt1, rt0; \ 1407461c08dfSJia Liu uint8_t tempD, tempC, tempB, tempA; \ 1408461c08dfSJia Liu \ 1409461c08dfSJia Liu MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ 1410461c08dfSJia Liu MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 1411461c08dfSJia Liu \ 1412461c08dfSJia Liu tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1; \ 1413461c08dfSJia Liu tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1; \ 1414461c08dfSJia Liu tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1; \ 1415461c08dfSJia Liu tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1; \ 1416461c08dfSJia Liu \ 1417461c08dfSJia Liu return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \ 1418461c08dfSJia Liu ((uint32_t)tempB << 8) | ((uint32_t)tempA); \ 1419461c08dfSJia Liu } 1420461c08dfSJia Liu 1421461c08dfSJia Liu SUBUH_QB(subuh, 0); 1422461c08dfSJia Liu SUBUH_QB(subuh_r, 1); 1423461c08dfSJia Liu 1424461c08dfSJia Liu #undef SUBUH_QB 1425461c08dfSJia Liu 1426461c08dfSJia Liu target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env) 1427461c08dfSJia Liu { 1428461c08dfSJia Liu uint64_t temp, tempRs, tempRt; 1429461c08dfSJia Liu int32_t flag; 1430461c08dfSJia Liu 1431461c08dfSJia Liu tempRs = (uint64_t)rs & MIPSDSP_LLO; 1432461c08dfSJia Liu tempRt = (uint64_t)rt & MIPSDSP_LLO; 1433461c08dfSJia Liu 1434461c08dfSJia Liu temp = tempRs + tempRt; 1435461c08dfSJia Liu flag = (temp & 0x0100000000ull) >> 32; 1436461c08dfSJia Liu set_DSPControl_carryflag(flag, env); 1437461c08dfSJia Liu 1438461c08dfSJia Liu return (target_long)(int32_t)(temp & MIPSDSP_LLO); 1439461c08dfSJia Liu } 1440461c08dfSJia Liu 1441461c08dfSJia Liu target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env) 1442461c08dfSJia Liu { 1443461c08dfSJia Liu uint32_t rd; 1444461c08dfSJia Liu int32_t temp32, temp31; 1445461c08dfSJia Liu int64_t tempL; 1446461c08dfSJia Liu 1447461c08dfSJia Liu tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt + 1448461c08dfSJia Liu get_DSPControl_carryflag(env); 1449461c08dfSJia Liu temp31 = (tempL >> 31) & 0x01; 1450461c08dfSJia Liu temp32 = (tempL >> 32) & 0x01; 1451461c08dfSJia Liu 1452461c08dfSJia Liu if (temp31 != temp32) { 1453461c08dfSJia Liu set_DSPControl_overflow_flag(1, 20, env); 1454461c08dfSJia Liu } 1455461c08dfSJia Liu 1456461c08dfSJia Liu rd = tempL & MIPSDSP_LLO; 1457461c08dfSJia Liu 1458461c08dfSJia Liu return (target_long)(int32_t)rd; 1459461c08dfSJia Liu } 1460461c08dfSJia Liu 1461461c08dfSJia Liu target_ulong helper_modsub(target_ulong rs, target_ulong rt) 1462461c08dfSJia Liu { 1463461c08dfSJia Liu int32_t decr; 1464461c08dfSJia Liu uint16_t lastindex; 1465461c08dfSJia Liu target_ulong rd; 1466461c08dfSJia Liu 1467461c08dfSJia Liu decr = rt & MIPSDSP_Q0; 1468461c08dfSJia Liu lastindex = (rt >> 8) & MIPSDSP_LO; 1469461c08dfSJia Liu 1470461c08dfSJia Liu if ((rs & MIPSDSP_LLO) == 0x00000000) { 1471461c08dfSJia Liu rd = (target_ulong)lastindex; 1472461c08dfSJia Liu } else { 1473461c08dfSJia Liu rd = rs - decr; 1474461c08dfSJia Liu } 1475461c08dfSJia Liu 1476461c08dfSJia Liu return rd; 1477461c08dfSJia Liu } 1478461c08dfSJia Liu 1479461c08dfSJia Liu target_ulong helper_raddu_w_qb(target_ulong rs) 1480461c08dfSJia Liu { 1481461c08dfSJia Liu uint8_t rs3, rs2, rs1, rs0; 1482461c08dfSJia Liu uint16_t temp; 1483461c08dfSJia Liu 1484461c08dfSJia Liu MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); 1485461c08dfSJia Liu 1486461c08dfSJia Liu temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0; 1487461c08dfSJia Liu 1488461c08dfSJia Liu return (target_ulong)temp; 1489461c08dfSJia Liu } 1490461c08dfSJia Liu 1491461c08dfSJia Liu #if defined(TARGET_MIPS64) 1492461c08dfSJia Liu target_ulong helper_raddu_l_ob(target_ulong rs) 1493461c08dfSJia Liu { 1494461c08dfSJia Liu int i; 1495461c08dfSJia Liu uint16_t rs_t[8]; 1496461c08dfSJia Liu uint64_t temp; 1497461c08dfSJia Liu 1498461c08dfSJia Liu temp = 0; 1499461c08dfSJia Liu 1500461c08dfSJia Liu for (i = 0; i < 8; i++) { 1501461c08dfSJia Liu rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0; 1502461c08dfSJia Liu temp += (uint64_t)rs_t[i]; 1503461c08dfSJia Liu } 1504461c08dfSJia Liu 1505461c08dfSJia Liu return temp; 1506461c08dfSJia Liu } 1507461c08dfSJia Liu #endif 1508461c08dfSJia Liu 1509461c08dfSJia Liu target_ulong helper_absq_s_qb(target_ulong rt, CPUMIPSState *env) 1510461c08dfSJia Liu { 1511461c08dfSJia Liu uint8_t tempD, tempC, tempB, tempA; 1512461c08dfSJia Liu 1513461c08dfSJia Liu MIPSDSP_SPLIT32_8(rt, tempD, tempC, tempB, tempA); 1514461c08dfSJia Liu 1515461c08dfSJia Liu tempD = mipsdsp_sat_abs8(tempD, env); 1516461c08dfSJia Liu tempC = mipsdsp_sat_abs8(tempC, env); 1517461c08dfSJia Liu tempB = mipsdsp_sat_abs8(tempB, env); 1518461c08dfSJia Liu tempA = mipsdsp_sat_abs8(tempA, env); 1519461c08dfSJia Liu 1520461c08dfSJia Liu return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); 1521461c08dfSJia Liu } 1522461c08dfSJia Liu 1523461c08dfSJia Liu target_ulong helper_absq_s_ph(target_ulong rt, CPUMIPSState *env) 1524461c08dfSJia Liu { 1525461c08dfSJia Liu uint16_t tempB, tempA; 1526461c08dfSJia Liu 1527461c08dfSJia Liu MIPSDSP_SPLIT32_16(rt, tempB, tempA); 1528461c08dfSJia Liu 1529461c08dfSJia Liu tempB = mipsdsp_sat_abs16 (tempB, env); 1530461c08dfSJia Liu tempA = mipsdsp_sat_abs16 (tempA, env); 1531461c08dfSJia Liu 1532461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); 1533461c08dfSJia Liu } 1534461c08dfSJia Liu 1535461c08dfSJia Liu #if defined(TARGET_MIPS64) 1536461c08dfSJia Liu target_ulong helper_absq_s_ob(target_ulong rt, CPUMIPSState *env) 1537461c08dfSJia Liu { 1538461c08dfSJia Liu int i; 1539461c08dfSJia Liu int8_t temp[8]; 1540461c08dfSJia Liu uint64_t result; 1541461c08dfSJia Liu 1542461c08dfSJia Liu for (i = 0; i < 8; i++) { 1543461c08dfSJia Liu temp[i] = (rt >> (8 * i)) & MIPSDSP_Q0; 1544461c08dfSJia Liu temp[i] = mipsdsp_sat_abs8(temp[i], env); 1545461c08dfSJia Liu } 1546461c08dfSJia Liu 1547461c08dfSJia Liu for (i = 0; i < 8; i++) { 1548461c08dfSJia Liu result = (uint64_t)(uint8_t)temp[i] << (8 * i); 1549461c08dfSJia Liu } 1550461c08dfSJia Liu 1551461c08dfSJia Liu return result; 1552461c08dfSJia Liu } 1553461c08dfSJia Liu 1554461c08dfSJia Liu target_ulong helper_absq_s_qh(target_ulong rt, CPUMIPSState *env) 1555461c08dfSJia Liu { 1556461c08dfSJia Liu int16_t tempD, tempC, tempB, tempA; 1557461c08dfSJia Liu 1558461c08dfSJia Liu MIPSDSP_SPLIT64_16(rt, tempD, tempC, tempB, tempA); 1559461c08dfSJia Liu 1560461c08dfSJia Liu tempD = mipsdsp_sat_abs16(tempD, env); 1561461c08dfSJia Liu tempC = mipsdsp_sat_abs16(tempC, env); 1562461c08dfSJia Liu tempB = mipsdsp_sat_abs16(tempB, env); 1563461c08dfSJia Liu tempA = mipsdsp_sat_abs16(tempA, env); 1564461c08dfSJia Liu 1565461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); 1566461c08dfSJia Liu } 1567461c08dfSJia Liu 1568461c08dfSJia Liu target_ulong helper_absq_s_pw(target_ulong rt, CPUMIPSState *env) 1569461c08dfSJia Liu { 1570461c08dfSJia Liu int32_t tempB, tempA; 1571461c08dfSJia Liu 1572461c08dfSJia Liu MIPSDSP_SPLIT64_32(rt, tempB, tempA); 1573461c08dfSJia Liu 1574461c08dfSJia Liu tempB = mipsdsp_sat_abs32(tempB, env); 1575461c08dfSJia Liu tempA = mipsdsp_sat_abs32(tempA, env); 1576461c08dfSJia Liu 1577461c08dfSJia Liu return MIPSDSP_RETURN64_32(tempB, tempA); 1578461c08dfSJia Liu } 1579461c08dfSJia Liu #endif 1580461c08dfSJia Liu 1581461c08dfSJia Liu #define PRECR_QB_PH(name, a, b)\ 1582461c08dfSJia Liu target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \ 1583461c08dfSJia Liu { \ 1584461c08dfSJia Liu uint8_t tempD, tempC, tempB, tempA; \ 1585461c08dfSJia Liu \ 1586461c08dfSJia Liu tempD = (rs >> a) & MIPSDSP_Q0; \ 1587461c08dfSJia Liu tempC = (rs >> b) & MIPSDSP_Q0; \ 1588461c08dfSJia Liu tempB = (rt >> a) & MIPSDSP_Q0; \ 1589461c08dfSJia Liu tempA = (rt >> b) & MIPSDSP_Q0; \ 1590461c08dfSJia Liu \ 1591461c08dfSJia Liu return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); \ 1592461c08dfSJia Liu } 1593461c08dfSJia Liu 1594461c08dfSJia Liu PRECR_QB_PH(precr, 16, 0); 1595461c08dfSJia Liu PRECR_QB_PH(precrq, 24, 8); 1596461c08dfSJia Liu 1597461c08dfSJia Liu #undef PRECR_QB_OH 1598461c08dfSJia Liu 1599461c08dfSJia Liu target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs, 1600461c08dfSJia Liu target_ulong rt) 1601461c08dfSJia Liu { 1602461c08dfSJia Liu uint16_t tempB, tempA; 1603461c08dfSJia Liu 1604461c08dfSJia Liu tempB = ((int32_t)rt >> sa) & MIPSDSP_LO; 1605461c08dfSJia Liu tempA = ((int32_t)rs >> sa) & MIPSDSP_LO; 1606461c08dfSJia Liu 1607461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); 1608461c08dfSJia Liu } 1609461c08dfSJia Liu 1610461c08dfSJia Liu target_ulong helper_precr_sra_r_ph_w(uint32_t sa, 1611461c08dfSJia Liu target_ulong rs, target_ulong rt) 1612461c08dfSJia Liu { 1613461c08dfSJia Liu uint64_t tempB, tempA; 1614461c08dfSJia Liu 1615461c08dfSJia Liu /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */ 1616461c08dfSJia Liu if (sa == 0) { 1617461c08dfSJia Liu tempB = (rt & MIPSDSP_LO) << 1; 1618461c08dfSJia Liu tempA = (rs & MIPSDSP_LO) << 1; 1619461c08dfSJia Liu } else { 1620461c08dfSJia Liu tempB = ((int32_t)rt >> (sa - 1)) + 1; 1621461c08dfSJia Liu tempA = ((int32_t)rs >> (sa - 1)) + 1; 1622461c08dfSJia Liu } 1623461c08dfSJia Liu rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO); 1624461c08dfSJia Liu 1625461c08dfSJia Liu return (target_long)(int32_t)rt; 1626461c08dfSJia Liu } 1627461c08dfSJia Liu 1628461c08dfSJia Liu target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt) 1629461c08dfSJia Liu { 1630461c08dfSJia Liu uint16_t tempB, tempA; 1631461c08dfSJia Liu 1632461c08dfSJia Liu tempB = (rs & MIPSDSP_HI) >> 16; 1633461c08dfSJia Liu tempA = (rt & MIPSDSP_HI) >> 16; 1634461c08dfSJia Liu 1635461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); 1636461c08dfSJia Liu } 1637461c08dfSJia Liu 1638461c08dfSJia Liu target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt, 1639461c08dfSJia Liu CPUMIPSState *env) 1640461c08dfSJia Liu { 1641461c08dfSJia Liu uint16_t tempB, tempA; 1642461c08dfSJia Liu 1643461c08dfSJia Liu tempB = mipsdsp_trunc16_sat16_round(rs, env); 1644461c08dfSJia Liu tempA = mipsdsp_trunc16_sat16_round(rt, env); 1645461c08dfSJia Liu 1646461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); 1647461c08dfSJia Liu } 1648461c08dfSJia Liu 1649461c08dfSJia Liu #if defined(TARGET_MIPS64) 1650461c08dfSJia Liu target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt) 1651461c08dfSJia Liu { 1652461c08dfSJia Liu uint8_t rs6, rs4, rs2, rs0; 1653461c08dfSJia Liu uint8_t rt6, rt4, rt2, rt0; 1654461c08dfSJia Liu uint64_t temp; 1655461c08dfSJia Liu 1656461c08dfSJia Liu rs6 = (rs >> 48) & MIPSDSP_Q0; 1657461c08dfSJia Liu rs4 = (rs >> 32) & MIPSDSP_Q0; 1658461c08dfSJia Liu rs2 = (rs >> 16) & MIPSDSP_Q0; 1659461c08dfSJia Liu rs0 = rs & MIPSDSP_Q0; 1660461c08dfSJia Liu rt6 = (rt >> 48) & MIPSDSP_Q0; 1661461c08dfSJia Liu rt4 = (rt >> 32) & MIPSDSP_Q0; 1662461c08dfSJia Liu rt2 = (rt >> 16) & MIPSDSP_Q0; 1663461c08dfSJia Liu rt0 = rt & MIPSDSP_Q0; 1664461c08dfSJia Liu 1665461c08dfSJia Liu temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) | 1666461c08dfSJia Liu ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) | 1667461c08dfSJia Liu ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) | 1668461c08dfSJia Liu ((uint64_t)rt2 << 8) | (uint64_t)rt0; 1669461c08dfSJia Liu 1670461c08dfSJia Liu return temp; 1671461c08dfSJia Liu } 1672461c08dfSJia Liu 1673461c08dfSJia Liu #define PRECR_QH_PW(name, var) \ 1674461c08dfSJia Liu target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \ 1675461c08dfSJia Liu uint32_t sa) \ 1676461c08dfSJia Liu { \ 1677461c08dfSJia Liu uint16_t rs3, rs2, rs1, rs0; \ 1678461c08dfSJia Liu uint16_t rt3, rt2, rt1, rt0; \ 1679461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 1680461c08dfSJia Liu \ 1681461c08dfSJia Liu MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ 1682461c08dfSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 1683461c08dfSJia Liu \ 1684461c08dfSJia Liu /* When sa = 0, we use rt2, rt0, rs2, rs0; \ 1685461c08dfSJia Liu * when sa != 0, we use rt3, rt1, rs3, rs1. */ \ 1686461c08dfSJia Liu if (sa == 0) { \ 1687461c08dfSJia Liu tempD = rt2 << var; \ 1688461c08dfSJia Liu tempC = rt0 << var; \ 1689461c08dfSJia Liu tempB = rs2 << var; \ 1690461c08dfSJia Liu tempA = rs0 << var; \ 1691461c08dfSJia Liu } else { \ 1692461c08dfSJia Liu tempD = (((int16_t)rt3 >> sa) + var) >> var; \ 1693461c08dfSJia Liu tempC = (((int16_t)rt1 >> sa) + var) >> var; \ 1694461c08dfSJia Liu tempB = (((int16_t)rs3 >> sa) + var) >> var; \ 1695461c08dfSJia Liu tempA = (((int16_t)rs1 >> sa) + var) >> var; \ 1696461c08dfSJia Liu } \ 1697461c08dfSJia Liu \ 1698461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1699461c08dfSJia Liu } 1700461c08dfSJia Liu 1701461c08dfSJia Liu PRECR_QH_PW(sra, 0); 1702461c08dfSJia Liu PRECR_QH_PW(sra_r, 1); 1703461c08dfSJia Liu 1704461c08dfSJia Liu #undef PRECR_QH_PW 1705461c08dfSJia Liu 1706461c08dfSJia Liu target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt) 1707461c08dfSJia Liu { 1708461c08dfSJia Liu uint8_t rs6, rs4, rs2, rs0; 1709461c08dfSJia Liu uint8_t rt6, rt4, rt2, rt0; 1710461c08dfSJia Liu uint64_t temp; 1711461c08dfSJia Liu 1712461c08dfSJia Liu rs6 = (rs >> 56) & MIPSDSP_Q0; 1713461c08dfSJia Liu rs4 = (rs >> 40) & MIPSDSP_Q0; 1714461c08dfSJia Liu rs2 = (rs >> 24) & MIPSDSP_Q0; 1715461c08dfSJia Liu rs0 = (rs >> 8) & MIPSDSP_Q0; 1716461c08dfSJia Liu rt6 = (rt >> 56) & MIPSDSP_Q0; 1717461c08dfSJia Liu rt4 = (rt >> 40) & MIPSDSP_Q0; 1718461c08dfSJia Liu rt2 = (rt >> 24) & MIPSDSP_Q0; 1719461c08dfSJia Liu rt0 = (rt >> 8) & MIPSDSP_Q0; 1720461c08dfSJia Liu 1721461c08dfSJia Liu temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) | 1722461c08dfSJia Liu ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) | 1723461c08dfSJia Liu ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) | 1724461c08dfSJia Liu ((uint64_t)rt2 << 8) | (uint64_t)rt0; 1725461c08dfSJia Liu 1726461c08dfSJia Liu return temp; 1727461c08dfSJia Liu } 1728461c08dfSJia Liu 1729461c08dfSJia Liu target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt) 1730461c08dfSJia Liu { 1731461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; 1732461c08dfSJia Liu 1733461c08dfSJia Liu tempD = (rs >> 48) & MIPSDSP_LO; 1734461c08dfSJia Liu tempC = (rs >> 16) & MIPSDSP_LO; 1735461c08dfSJia Liu tempB = (rt >> 48) & MIPSDSP_LO; 1736461c08dfSJia Liu tempA = (rt >> 16) & MIPSDSP_LO; 1737461c08dfSJia Liu 1738461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); 1739461c08dfSJia Liu } 1740461c08dfSJia Liu 1741461c08dfSJia Liu target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt, 1742461c08dfSJia Liu CPUMIPSState *env) 1743461c08dfSJia Liu { 1744461c08dfSJia Liu uint32_t rs2, rs0; 1745461c08dfSJia Liu uint32_t rt2, rt0; 1746461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; 1747461c08dfSJia Liu 1748461c08dfSJia Liu rs2 = (rs >> 32) & MIPSDSP_LLO; 1749461c08dfSJia Liu rs0 = rs & MIPSDSP_LLO; 1750461c08dfSJia Liu rt2 = (rt >> 32) & MIPSDSP_LLO; 1751461c08dfSJia Liu rt0 = rt & MIPSDSP_LLO; 1752461c08dfSJia Liu 1753461c08dfSJia Liu tempD = mipsdsp_trunc16_sat16_round(rs2, env); 1754461c08dfSJia Liu tempC = mipsdsp_trunc16_sat16_round(rs0, env); 1755461c08dfSJia Liu tempB = mipsdsp_trunc16_sat16_round(rt2, env); 1756461c08dfSJia Liu tempA = mipsdsp_trunc16_sat16_round(rt0, env); 1757461c08dfSJia Liu 1758461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); 1759461c08dfSJia Liu } 1760461c08dfSJia Liu 1761461c08dfSJia Liu target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt) 1762461c08dfSJia Liu { 1763461c08dfSJia Liu uint32_t tempB, tempA; 1764461c08dfSJia Liu 1765461c08dfSJia Liu tempB = (rs >> 32) & MIPSDSP_LLO; 1766461c08dfSJia Liu tempA = (rt >> 32) & MIPSDSP_LLO; 1767461c08dfSJia Liu 1768461c08dfSJia Liu return MIPSDSP_RETURN64_32(tempB, tempA); 1769461c08dfSJia Liu } 1770461c08dfSJia Liu #endif 1771461c08dfSJia Liu 1772461c08dfSJia Liu target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt, 1773461c08dfSJia Liu CPUMIPSState *env) 1774461c08dfSJia Liu { 1775461c08dfSJia Liu uint8_t tempD, tempC, tempB, tempA; 1776461c08dfSJia Liu uint16_t rsh, rsl, rth, rtl; 1777461c08dfSJia Liu 1778461c08dfSJia Liu rsh = (rs & MIPSDSP_HI) >> 16; 1779461c08dfSJia Liu rsl = rs & MIPSDSP_LO; 1780461c08dfSJia Liu rth = (rt & MIPSDSP_HI) >> 16; 1781461c08dfSJia Liu rtl = rt & MIPSDSP_LO; 1782461c08dfSJia Liu 1783461c08dfSJia Liu tempD = mipsdsp_sat8_reduce_precision(rsh, env); 1784461c08dfSJia Liu tempC = mipsdsp_sat8_reduce_precision(rsl, env); 1785461c08dfSJia Liu tempB = mipsdsp_sat8_reduce_precision(rth, env); 1786461c08dfSJia Liu tempA = mipsdsp_sat8_reduce_precision(rtl, env); 1787461c08dfSJia Liu 1788461c08dfSJia Liu return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); 1789461c08dfSJia Liu } 1790461c08dfSJia Liu 1791461c08dfSJia Liu #if defined(TARGET_MIPS64) 1792461c08dfSJia Liu target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt, 1793461c08dfSJia Liu CPUMIPSState *env) 1794461c08dfSJia Liu { 1795461c08dfSJia Liu int i; 1796461c08dfSJia Liu uint16_t rs3, rs2, rs1, rs0; 1797461c08dfSJia Liu uint16_t rt3, rt2, rt1, rt0; 1798461c08dfSJia Liu uint8_t temp[8]; 1799461c08dfSJia Liu uint64_t result; 1800461c08dfSJia Liu 1801461c08dfSJia Liu result = 0; 1802461c08dfSJia Liu 1803461c08dfSJia Liu MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); 1804461c08dfSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); 1805461c08dfSJia Liu 1806461c08dfSJia Liu temp[7] = mipsdsp_sat8_reduce_precision(rs3, env); 1807461c08dfSJia Liu temp[6] = mipsdsp_sat8_reduce_precision(rs2, env); 1808461c08dfSJia Liu temp[5] = mipsdsp_sat8_reduce_precision(rs1, env); 1809461c08dfSJia Liu temp[4] = mipsdsp_sat8_reduce_precision(rs0, env); 1810461c08dfSJia Liu temp[3] = mipsdsp_sat8_reduce_precision(rt3, env); 1811461c08dfSJia Liu temp[2] = mipsdsp_sat8_reduce_precision(rt2, env); 1812461c08dfSJia Liu temp[1] = mipsdsp_sat8_reduce_precision(rt1, env); 1813461c08dfSJia Liu temp[0] = mipsdsp_sat8_reduce_precision(rt0, env); 1814461c08dfSJia Liu 1815461c08dfSJia Liu for (i = 0; i < 8; i++) { 1816461c08dfSJia Liu result |= (uint64_t)temp[i] << (8 * i); 1817461c08dfSJia Liu } 1818461c08dfSJia Liu 1819461c08dfSJia Liu return result; 1820461c08dfSJia Liu } 1821461c08dfSJia Liu 1822461c08dfSJia Liu #define PRECEQ_PW(name, a, b) \ 1823461c08dfSJia Liu target_ulong helper_preceq_pw_##name(target_ulong rt) \ 1824461c08dfSJia Liu { \ 1825461c08dfSJia Liu uint16_t tempB, tempA; \ 1826461c08dfSJia Liu uint32_t tempBI, tempAI; \ 1827461c08dfSJia Liu \ 1828461c08dfSJia Liu tempB = (rt >> a) & MIPSDSP_LO; \ 1829461c08dfSJia Liu tempA = (rt >> b) & MIPSDSP_LO; \ 1830461c08dfSJia Liu \ 1831461c08dfSJia Liu tempBI = (uint32_t)tempB << 16; \ 1832461c08dfSJia Liu tempAI = (uint32_t)tempA << 16; \ 1833461c08dfSJia Liu \ 1834461c08dfSJia Liu return MIPSDSP_RETURN64_32(tempBI, tempAI); \ 1835461c08dfSJia Liu } 1836461c08dfSJia Liu 1837461c08dfSJia Liu PRECEQ_PW(qhl, 48, 32); 1838461c08dfSJia Liu PRECEQ_PW(qhr, 16, 0); 1839461c08dfSJia Liu PRECEQ_PW(qhla, 48, 16); 1840461c08dfSJia Liu PRECEQ_PW(qhra, 32, 0); 1841461c08dfSJia Liu 1842461c08dfSJia Liu #undef PRECEQ_PW 1843461c08dfSJia Liu 1844461c08dfSJia Liu #endif 1845461c08dfSJia Liu 1846461c08dfSJia Liu #define PRECEQU_PH(name, a, b) \ 1847461c08dfSJia Liu target_ulong helper_precequ_ph_##name(target_ulong rt) \ 1848461c08dfSJia Liu { \ 1849461c08dfSJia Liu uint16_t tempB, tempA; \ 1850461c08dfSJia Liu \ 1851461c08dfSJia Liu tempB = (rt >> a) & MIPSDSP_Q0; \ 1852461c08dfSJia Liu tempA = (rt >> b) & MIPSDSP_Q0; \ 1853461c08dfSJia Liu \ 1854461c08dfSJia Liu tempB = tempB << 7; \ 1855461c08dfSJia Liu tempA = tempA << 7; \ 1856461c08dfSJia Liu \ 1857461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); \ 1858461c08dfSJia Liu } 1859461c08dfSJia Liu 1860461c08dfSJia Liu PRECEQU_PH(qbl, 24, 16); 1861461c08dfSJia Liu PRECEQU_PH(qbr, 8, 0); 1862461c08dfSJia Liu PRECEQU_PH(qbla, 24, 8); 1863461c08dfSJia Liu PRECEQU_PH(qbra, 16, 0); 1864461c08dfSJia Liu 1865461c08dfSJia Liu #undef PRECEQU_PH 1866461c08dfSJia Liu 1867461c08dfSJia Liu #if defined(TARGET_MIPS64) 1868461c08dfSJia Liu #define PRECEQU_QH(name, a, b, c, d) \ 1869461c08dfSJia Liu target_ulong helper_precequ_qh_##name(target_ulong rt) \ 1870461c08dfSJia Liu { \ 1871461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 1872461c08dfSJia Liu \ 1873461c08dfSJia Liu tempD = (rt >> a) & MIPSDSP_Q0; \ 1874461c08dfSJia Liu tempC = (rt >> b) & MIPSDSP_Q0; \ 1875461c08dfSJia Liu tempB = (rt >> c) & MIPSDSP_Q0; \ 1876461c08dfSJia Liu tempA = (rt >> d) & MIPSDSP_Q0; \ 1877461c08dfSJia Liu \ 1878461c08dfSJia Liu tempD = tempD << 7; \ 1879461c08dfSJia Liu tempC = tempC << 7; \ 1880461c08dfSJia Liu tempB = tempB << 7; \ 1881461c08dfSJia Liu tempA = tempA << 7; \ 1882461c08dfSJia Liu \ 1883461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1884461c08dfSJia Liu } 1885461c08dfSJia Liu 1886461c08dfSJia Liu PRECEQU_QH(obl, 56, 48, 40, 32); 1887461c08dfSJia Liu PRECEQU_QH(obr, 24, 16, 8, 0); 1888461c08dfSJia Liu PRECEQU_QH(obla, 56, 40, 24, 8); 1889461c08dfSJia Liu PRECEQU_QH(obra, 48, 32, 16, 0); 1890461c08dfSJia Liu 1891461c08dfSJia Liu #undef PRECEQU_QH 1892461c08dfSJia Liu 1893461c08dfSJia Liu #endif 1894461c08dfSJia Liu 1895461c08dfSJia Liu #define PRECEU_PH(name, a, b) \ 1896461c08dfSJia Liu target_ulong helper_preceu_ph_##name(target_ulong rt) \ 1897461c08dfSJia Liu { \ 1898461c08dfSJia Liu uint16_t tempB, tempA; \ 1899461c08dfSJia Liu \ 1900461c08dfSJia Liu tempB = (rt >> a) & MIPSDSP_Q0; \ 1901461c08dfSJia Liu tempA = (rt >> b) & MIPSDSP_Q0; \ 1902461c08dfSJia Liu \ 1903461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); \ 1904461c08dfSJia Liu } 1905461c08dfSJia Liu 1906461c08dfSJia Liu PRECEU_PH(qbl, 24, 16); 1907461c08dfSJia Liu PRECEU_PH(qbr, 8, 0); 1908461c08dfSJia Liu PRECEU_PH(qbla, 24, 8); 1909461c08dfSJia Liu PRECEU_PH(qbra, 16, 0); 1910461c08dfSJia Liu 1911461c08dfSJia Liu #undef PRECEU_PH 1912461c08dfSJia Liu 1913461c08dfSJia Liu #if defined(TARGET_MIPS64) 1914461c08dfSJia Liu #define PRECEU_QH(name, a, b, c, d) \ 1915461c08dfSJia Liu target_ulong helper_preceu_qh_##name(target_ulong rt) \ 1916461c08dfSJia Liu { \ 1917461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 1918461c08dfSJia Liu \ 1919461c08dfSJia Liu tempD = (rt >> a) & MIPSDSP_Q0; \ 1920461c08dfSJia Liu tempC = (rt >> b) & MIPSDSP_Q0; \ 1921461c08dfSJia Liu tempB = (rt >> c) & MIPSDSP_Q0; \ 1922461c08dfSJia Liu tempA = (rt >> d) & MIPSDSP_Q0; \ 1923461c08dfSJia Liu \ 1924461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1925461c08dfSJia Liu } 1926461c08dfSJia Liu 1927461c08dfSJia Liu PRECEU_QH(obl, 56, 48, 40, 32); 1928461c08dfSJia Liu PRECEU_QH(obr, 24, 16, 8, 0); 1929461c08dfSJia Liu PRECEU_QH(obla, 56, 40, 24, 8); 1930461c08dfSJia Liu PRECEU_QH(obra, 48, 32, 16, 0); 1931461c08dfSJia Liu 1932461c08dfSJia Liu #undef PRECEU_QH 1933461c08dfSJia Liu 1934461c08dfSJia Liu #endif 1935461c08dfSJia Liu 193677c5fa8bSJia Liu /** DSP GPR-Based Shift Sub-class insns **/ 193777c5fa8bSJia Liu #define SHIFT_QB(name, func) \ 193877c5fa8bSJia Liu target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \ 193977c5fa8bSJia Liu { \ 194077c5fa8bSJia Liu uint8_t rt3, rt2, rt1, rt0; \ 194177c5fa8bSJia Liu \ 194277c5fa8bSJia Liu sa = sa & 0x07; \ 194377c5fa8bSJia Liu \ 194477c5fa8bSJia Liu MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 194577c5fa8bSJia Liu \ 194677c5fa8bSJia Liu rt3 = mipsdsp_##func(rt3, sa); \ 194777c5fa8bSJia Liu rt2 = mipsdsp_##func(rt2, sa); \ 194877c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa); \ 194977c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa); \ 195077c5fa8bSJia Liu \ 195177c5fa8bSJia Liu return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \ 195277c5fa8bSJia Liu } 195377c5fa8bSJia Liu 195477c5fa8bSJia Liu #define SHIFT_QB_ENV(name, func) \ 195577c5fa8bSJia Liu target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\ 195677c5fa8bSJia Liu CPUMIPSState *env) \ 195777c5fa8bSJia Liu { \ 195877c5fa8bSJia Liu uint8_t rt3, rt2, rt1, rt0; \ 195977c5fa8bSJia Liu \ 196077c5fa8bSJia Liu sa = sa & 0x07; \ 196177c5fa8bSJia Liu \ 196277c5fa8bSJia Liu MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 196377c5fa8bSJia Liu \ 196477c5fa8bSJia Liu rt3 = mipsdsp_##func(rt3, sa, env); \ 196577c5fa8bSJia Liu rt2 = mipsdsp_##func(rt2, sa, env); \ 196677c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa, env); \ 196777c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa, env); \ 196877c5fa8bSJia Liu \ 196977c5fa8bSJia Liu return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \ 197077c5fa8bSJia Liu } 197177c5fa8bSJia Liu 197277c5fa8bSJia Liu SHIFT_QB_ENV(shll, lshift8); 197377c5fa8bSJia Liu SHIFT_QB(shrl, rshift_u8); 197477c5fa8bSJia Liu 197577c5fa8bSJia Liu SHIFT_QB(shra, rashift8); 197677c5fa8bSJia Liu SHIFT_QB(shra_r, rnd8_rashift); 197777c5fa8bSJia Liu 197877c5fa8bSJia Liu #undef SHIFT_QB 197977c5fa8bSJia Liu #undef SHIFT_QB_ENV 198077c5fa8bSJia Liu 198177c5fa8bSJia Liu #if defined(TARGET_MIPS64) 198277c5fa8bSJia Liu #define SHIFT_OB(name, func) \ 198377c5fa8bSJia Liu target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \ 198477c5fa8bSJia Liu { \ 198577c5fa8bSJia Liu int i; \ 198677c5fa8bSJia Liu uint8_t rt_t[8]; \ 198777c5fa8bSJia Liu uint64_t temp; \ 198877c5fa8bSJia Liu \ 198977c5fa8bSJia Liu sa = sa & 0x07; \ 199077c5fa8bSJia Liu temp = 0; \ 199177c5fa8bSJia Liu \ 199277c5fa8bSJia Liu for (i = 0; i < 8; i++) { \ 199377c5fa8bSJia Liu rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ 199477c5fa8bSJia Liu rt_t[i] = mipsdsp_##func(rt_t[i], sa); \ 199577c5fa8bSJia Liu temp |= (uint64_t)rt_t[i] << (8 * i); \ 199677c5fa8bSJia Liu } \ 199777c5fa8bSJia Liu \ 199877c5fa8bSJia Liu return temp; \ 199977c5fa8bSJia Liu } 200077c5fa8bSJia Liu 200177c5fa8bSJia Liu #define SHIFT_OB_ENV(name, func) \ 200277c5fa8bSJia Liu target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \ 200377c5fa8bSJia Liu CPUMIPSState *env) \ 200477c5fa8bSJia Liu { \ 200577c5fa8bSJia Liu int i; \ 200677c5fa8bSJia Liu uint8_t rt_t[8]; \ 200777c5fa8bSJia Liu uint64_t temp; \ 200877c5fa8bSJia Liu \ 200977c5fa8bSJia Liu sa = sa & 0x07; \ 201077c5fa8bSJia Liu temp = 0; \ 201177c5fa8bSJia Liu \ 201277c5fa8bSJia Liu for (i = 0; i < 8; i++) { \ 201377c5fa8bSJia Liu rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ 201477c5fa8bSJia Liu rt_t[i] = mipsdsp_##func(rt_t[i], sa, env); \ 201577c5fa8bSJia Liu temp |= (uint64_t)rt_t[i] << (8 * i); \ 201677c5fa8bSJia Liu } \ 201777c5fa8bSJia Liu \ 201877c5fa8bSJia Liu return temp; \ 201977c5fa8bSJia Liu } 202077c5fa8bSJia Liu 202177c5fa8bSJia Liu SHIFT_OB_ENV(shll, lshift8); 202277c5fa8bSJia Liu SHIFT_OB(shrl, rshift_u8); 202377c5fa8bSJia Liu 202477c5fa8bSJia Liu SHIFT_OB(shra, rashift8); 202577c5fa8bSJia Liu SHIFT_OB(shra_r, rnd8_rashift); 202677c5fa8bSJia Liu 202777c5fa8bSJia Liu #undef SHIFT_OB 202877c5fa8bSJia Liu #undef SHIFT_OB_ENV 202977c5fa8bSJia Liu 203077c5fa8bSJia Liu #endif 203177c5fa8bSJia Liu 203277c5fa8bSJia Liu #define SHIFT_PH(name, func) \ 203377c5fa8bSJia Liu target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \ 203477c5fa8bSJia Liu CPUMIPSState *env) \ 203577c5fa8bSJia Liu { \ 203677c5fa8bSJia Liu uint16_t rth, rtl; \ 203777c5fa8bSJia Liu \ 203877c5fa8bSJia Liu sa = sa & 0x0F; \ 203977c5fa8bSJia Liu \ 204077c5fa8bSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 204177c5fa8bSJia Liu \ 204277c5fa8bSJia Liu rth = mipsdsp_##func(rth, sa, env); \ 204377c5fa8bSJia Liu rtl = mipsdsp_##func(rtl, sa, env); \ 204477c5fa8bSJia Liu \ 204577c5fa8bSJia Liu return MIPSDSP_RETURN32_16(rth, rtl); \ 204677c5fa8bSJia Liu } 204777c5fa8bSJia Liu 204877c5fa8bSJia Liu SHIFT_PH(shll, lshift16); 204977c5fa8bSJia Liu SHIFT_PH(shll_s, sat16_lshift); 205077c5fa8bSJia Liu 205177c5fa8bSJia Liu #undef SHIFT_PH 205277c5fa8bSJia Liu 205377c5fa8bSJia Liu #if defined(TARGET_MIPS64) 205477c5fa8bSJia Liu #define SHIFT_QH(name, func) \ 205577c5fa8bSJia Liu target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \ 205677c5fa8bSJia Liu { \ 205777c5fa8bSJia Liu uint16_t rt3, rt2, rt1, rt0; \ 205877c5fa8bSJia Liu \ 205977c5fa8bSJia Liu sa = sa & 0x0F; \ 206077c5fa8bSJia Liu \ 206177c5fa8bSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 206277c5fa8bSJia Liu \ 206377c5fa8bSJia Liu rt3 = mipsdsp_##func(rt3, sa); \ 206477c5fa8bSJia Liu rt2 = mipsdsp_##func(rt2, sa); \ 206577c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa); \ 206677c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa); \ 206777c5fa8bSJia Liu \ 206877c5fa8bSJia Liu return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \ 206977c5fa8bSJia Liu } 207077c5fa8bSJia Liu 207177c5fa8bSJia Liu #define SHIFT_QH_ENV(name, func) \ 207277c5fa8bSJia Liu target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \ 207377c5fa8bSJia Liu CPUMIPSState *env) \ 207477c5fa8bSJia Liu { \ 207577c5fa8bSJia Liu uint16_t rt3, rt2, rt1, rt0; \ 207677c5fa8bSJia Liu \ 207777c5fa8bSJia Liu sa = sa & 0x0F; \ 207877c5fa8bSJia Liu \ 207977c5fa8bSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 208077c5fa8bSJia Liu \ 208177c5fa8bSJia Liu rt3 = mipsdsp_##func(rt3, sa, env); \ 208277c5fa8bSJia Liu rt2 = mipsdsp_##func(rt2, sa, env); \ 208377c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa, env); \ 208477c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa, env); \ 208577c5fa8bSJia Liu \ 208677c5fa8bSJia Liu return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \ 208777c5fa8bSJia Liu } 208877c5fa8bSJia Liu 208977c5fa8bSJia Liu SHIFT_QH_ENV(shll, lshift16); 209077c5fa8bSJia Liu SHIFT_QH_ENV(shll_s, sat16_lshift); 209177c5fa8bSJia Liu 209277c5fa8bSJia Liu SHIFT_QH(shrl, rshift_u16); 209377c5fa8bSJia Liu SHIFT_QH(shra, rashift16); 209477c5fa8bSJia Liu SHIFT_QH(shra_r, rnd16_rashift); 209577c5fa8bSJia Liu 209677c5fa8bSJia Liu #undef SHIFT_QH 209777c5fa8bSJia Liu #undef SHIFT_QH_ENV 209877c5fa8bSJia Liu 209977c5fa8bSJia Liu #endif 210077c5fa8bSJia Liu 210177c5fa8bSJia Liu #define SHIFT_W(name, func) \ 210277c5fa8bSJia Liu target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \ 210377c5fa8bSJia Liu { \ 210477c5fa8bSJia Liu uint32_t temp; \ 210577c5fa8bSJia Liu \ 210677c5fa8bSJia Liu sa = sa & 0x1F; \ 210777c5fa8bSJia Liu temp = mipsdsp_##func(rt, sa); \ 210877c5fa8bSJia Liu \ 210977c5fa8bSJia Liu return (target_long)(int32_t)temp; \ 211077c5fa8bSJia Liu } 211177c5fa8bSJia Liu 211277c5fa8bSJia Liu #define SHIFT_W_ENV(name, func) \ 211377c5fa8bSJia Liu target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \ 211477c5fa8bSJia Liu CPUMIPSState *env) \ 211577c5fa8bSJia Liu { \ 211677c5fa8bSJia Liu uint32_t temp; \ 211777c5fa8bSJia Liu \ 211877c5fa8bSJia Liu sa = sa & 0x1F; \ 211977c5fa8bSJia Liu temp = mipsdsp_##func(rt, sa, env); \ 212077c5fa8bSJia Liu \ 212177c5fa8bSJia Liu return (target_long)(int32_t)temp; \ 212277c5fa8bSJia Liu } 212377c5fa8bSJia Liu 212477c5fa8bSJia Liu SHIFT_W_ENV(shll_s, sat32_lshift); 212577c5fa8bSJia Liu SHIFT_W(shra_r, rnd32_rashift); 212677c5fa8bSJia Liu 212777c5fa8bSJia Liu #undef SHIFT_W 212877c5fa8bSJia Liu #undef SHIFT_W_ENV 212977c5fa8bSJia Liu 213077c5fa8bSJia Liu #if defined(TARGET_MIPS64) 213177c5fa8bSJia Liu #define SHIFT_PW(name, func) \ 213277c5fa8bSJia Liu target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \ 213377c5fa8bSJia Liu { \ 213477c5fa8bSJia Liu uint32_t rt1, rt0; \ 213577c5fa8bSJia Liu \ 213677c5fa8bSJia Liu sa = sa & 0x1F; \ 213777c5fa8bSJia Liu MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 213877c5fa8bSJia Liu \ 213977c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa); \ 214077c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa); \ 214177c5fa8bSJia Liu \ 214277c5fa8bSJia Liu return MIPSDSP_RETURN64_32(rt1, rt0); \ 214377c5fa8bSJia Liu } 214477c5fa8bSJia Liu 214577c5fa8bSJia Liu #define SHIFT_PW_ENV(name, func) \ 214677c5fa8bSJia Liu target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \ 214777c5fa8bSJia Liu CPUMIPSState *env) \ 214877c5fa8bSJia Liu { \ 214977c5fa8bSJia Liu uint32_t rt1, rt0; \ 215077c5fa8bSJia Liu \ 215177c5fa8bSJia Liu sa = sa & 0x1F; \ 215277c5fa8bSJia Liu MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 215377c5fa8bSJia Liu \ 215477c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa, env); \ 215577c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa, env); \ 215677c5fa8bSJia Liu \ 215777c5fa8bSJia Liu return MIPSDSP_RETURN64_32(rt1, rt0); \ 215877c5fa8bSJia Liu } 215977c5fa8bSJia Liu 216077c5fa8bSJia Liu SHIFT_PW_ENV(shll, lshift32); 216177c5fa8bSJia Liu SHIFT_PW_ENV(shll_s, sat32_lshift); 216277c5fa8bSJia Liu 216377c5fa8bSJia Liu SHIFT_PW(shra, rashift32); 216477c5fa8bSJia Liu SHIFT_PW(shra_r, rnd32_rashift); 216577c5fa8bSJia Liu 216677c5fa8bSJia Liu #undef SHIFT_PW 216777c5fa8bSJia Liu #undef SHIFT_PW_ENV 216877c5fa8bSJia Liu 216977c5fa8bSJia Liu #endif 217077c5fa8bSJia Liu 217177c5fa8bSJia Liu #define SHIFT_PH(name, func) \ 217277c5fa8bSJia Liu target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \ 217377c5fa8bSJia Liu { \ 217477c5fa8bSJia Liu uint16_t rth, rtl; \ 217577c5fa8bSJia Liu \ 217677c5fa8bSJia Liu sa = sa & 0x0F; \ 217777c5fa8bSJia Liu \ 217877c5fa8bSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 217977c5fa8bSJia Liu \ 218077c5fa8bSJia Liu rth = mipsdsp_##func(rth, sa); \ 218177c5fa8bSJia Liu rtl = mipsdsp_##func(rtl, sa); \ 218277c5fa8bSJia Liu \ 218377c5fa8bSJia Liu return MIPSDSP_RETURN32_16(rth, rtl); \ 218477c5fa8bSJia Liu } 218577c5fa8bSJia Liu 218677c5fa8bSJia Liu SHIFT_PH(shrl, rshift_u16); 218777c5fa8bSJia Liu SHIFT_PH(shra, rashift16); 218877c5fa8bSJia Liu SHIFT_PH(shra_r, rnd16_rashift); 218977c5fa8bSJia Liu 219077c5fa8bSJia Liu #undef SHIFT_PH 219177c5fa8bSJia Liu 2192a22260aeSJia Liu /** DSP Multiply Sub-class insns **/ 2193a22260aeSJia Liu /* Return value made up by two 16bits value. 2194a22260aeSJia Liu * FIXME give the macro a better name. 2195a22260aeSJia Liu */ 2196a22260aeSJia Liu #define MUL_RETURN32_16_PH(name, func, \ 2197a22260aeSJia Liu rsmov1, rsmov2, rsfilter, \ 2198a22260aeSJia Liu rtmov1, rtmov2, rtfilter) \ 2199a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2200a22260aeSJia Liu CPUMIPSState *env) \ 2201a22260aeSJia Liu { \ 2202a22260aeSJia Liu uint16_t rsB, rsA, rtB, rtA; \ 2203a22260aeSJia Liu \ 2204a22260aeSJia Liu rsB = (rs >> rsmov1) & rsfilter; \ 2205a22260aeSJia Liu rsA = (rs >> rsmov2) & rsfilter; \ 2206a22260aeSJia Liu rtB = (rt >> rtmov1) & rtfilter; \ 2207a22260aeSJia Liu rtA = (rt >> rtmov2) & rtfilter; \ 2208a22260aeSJia Liu \ 2209a22260aeSJia Liu rsB = mipsdsp_##func(rsB, rtB, env); \ 2210a22260aeSJia Liu rsA = mipsdsp_##func(rsA, rtA, env); \ 2211a22260aeSJia Liu \ 2212a22260aeSJia Liu return MIPSDSP_RETURN32_16(rsB, rsA); \ 2213a22260aeSJia Liu } 2214a22260aeSJia Liu 2215a22260aeSJia Liu MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \ 2216a22260aeSJia Liu 24, 16, MIPSDSP_Q0, \ 2217a22260aeSJia Liu 16, 0, MIPSDSP_LO); 2218a22260aeSJia Liu MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \ 2219a22260aeSJia Liu 8, 0, MIPSDSP_Q0, \ 2220a22260aeSJia Liu 16, 0, MIPSDSP_LO); 2221a22260aeSJia Liu MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \ 2222a22260aeSJia Liu 16, 0, MIPSDSP_LO, \ 2223a22260aeSJia Liu 16, 0, MIPSDSP_LO); 2224a22260aeSJia Liu MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \ 2225a22260aeSJia Liu 16, 0, MIPSDSP_LO, \ 2226a22260aeSJia Liu 16, 0, MIPSDSP_LO); 2227a22260aeSJia Liu MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \ 2228a22260aeSJia Liu 16, 0, MIPSDSP_LO, \ 2229a22260aeSJia Liu 16, 0, MIPSDSP_LO); 2230a22260aeSJia Liu MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \ 2231a22260aeSJia Liu 16, 0, MIPSDSP_LO, \ 2232a22260aeSJia Liu 16, 0, MIPSDSP_LO); 2233a22260aeSJia Liu 2234a22260aeSJia Liu #undef MUL_RETURN32_16_PH 2235a22260aeSJia Liu 2236a22260aeSJia Liu #define MUL_RETURN32_32_ph(name, func, movbits) \ 2237a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2238a22260aeSJia Liu CPUMIPSState *env) \ 2239a22260aeSJia Liu { \ 2240a22260aeSJia Liu int16_t rsh, rth; \ 2241a22260aeSJia Liu int32_t temp; \ 2242a22260aeSJia Liu \ 2243a22260aeSJia Liu rsh = (rs >> movbits) & MIPSDSP_LO; \ 2244a22260aeSJia Liu rth = (rt >> movbits) & MIPSDSP_LO; \ 2245a22260aeSJia Liu temp = mipsdsp_##func(rsh, rth, env); \ 2246a22260aeSJia Liu \ 2247a22260aeSJia Liu return (target_long)(int32_t)temp; \ 2248a22260aeSJia Liu } 2249a22260aeSJia Liu 2250a22260aeSJia Liu MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16); 2251a22260aeSJia Liu MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0); 2252a22260aeSJia Liu 2253a22260aeSJia Liu #undef MUL_RETURN32_32_ph 2254a22260aeSJia Liu 2255a22260aeSJia Liu #define MUL_VOID_PH(name, use_ac_env) \ 2256a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2257a22260aeSJia Liu CPUMIPSState *env) \ 2258a22260aeSJia Liu { \ 2259a22260aeSJia Liu int16_t rsh, rsl, rth, rtl; \ 2260a22260aeSJia Liu int32_t tempB, tempA; \ 2261a22260aeSJia Liu int64_t acc, dotp; \ 2262a22260aeSJia Liu \ 2263a22260aeSJia Liu MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ 2264a22260aeSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 2265a22260aeSJia Liu \ 2266a22260aeSJia Liu if (use_ac_env == 1) { \ 2267a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ 2268a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env); \ 2269a22260aeSJia Liu } else { \ 2270a22260aeSJia Liu tempB = mipsdsp_mul_u16_u16(rsh, rth); \ 2271a22260aeSJia Liu tempA = mipsdsp_mul_u16_u16(rsl, rtl); \ 2272a22260aeSJia Liu } \ 2273a22260aeSJia Liu \ 2274a22260aeSJia Liu dotp = (int64_t)tempB - (int64_t)tempA; \ 2275a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2276a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2277a22260aeSJia Liu dotp = dotp + acc; \ 2278a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2279a22260aeSJia Liu ((dotp & MIPSDSP_LHI) >> 32); \ 2280a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO); \ 2281a22260aeSJia Liu } 2282a22260aeSJia Liu 2283a22260aeSJia Liu MUL_VOID_PH(mulsaq_s_w_ph, 1); 2284a22260aeSJia Liu MUL_VOID_PH(mulsa_w_ph, 0); 2285a22260aeSJia Liu 2286a22260aeSJia Liu #undef MUL_VOID_PH 2287a22260aeSJia Liu 2288a22260aeSJia Liu #if defined(TARGET_MIPS64) 2289a22260aeSJia Liu #define MUL_RETURN64_16_QH(name, func, \ 2290a22260aeSJia Liu rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \ 2291a22260aeSJia Liu rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \ 2292a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2293a22260aeSJia Liu CPUMIPSState *env) \ 2294a22260aeSJia Liu { \ 2295a22260aeSJia Liu uint16_t rs3, rs2, rs1, rs0; \ 2296a22260aeSJia Liu uint16_t rt3, rt2, rt1, rt0; \ 2297a22260aeSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 2298a22260aeSJia Liu \ 2299a22260aeSJia Liu rs3 = (rs >> rsmov1) & rsfilter; \ 2300a22260aeSJia Liu rs2 = (rs >> rsmov2) & rsfilter; \ 2301a22260aeSJia Liu rs1 = (rs >> rsmov3) & rsfilter; \ 2302a22260aeSJia Liu rs0 = (rs >> rsmov4) & rsfilter; \ 2303a22260aeSJia Liu rt3 = (rt >> rtmov1) & rtfilter; \ 2304a22260aeSJia Liu rt2 = (rt >> rtmov2) & rtfilter; \ 2305a22260aeSJia Liu rt1 = (rt >> rtmov3) & rtfilter; \ 2306a22260aeSJia Liu rt0 = (rt >> rtmov4) & rtfilter; \ 2307a22260aeSJia Liu \ 2308a22260aeSJia Liu tempD = mipsdsp_##func(rs3, rt3, env); \ 2309a22260aeSJia Liu tempC = mipsdsp_##func(rs2, rt2, env); \ 2310a22260aeSJia Liu tempB = mipsdsp_##func(rs1, rt1, env); \ 2311a22260aeSJia Liu tempA = mipsdsp_##func(rs0, rt0, env); \ 2312a22260aeSJia Liu \ 2313a22260aeSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 2314a22260aeSJia Liu } 2315a22260aeSJia Liu 2316a22260aeSJia Liu MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \ 2317a22260aeSJia Liu 56, 48, 40, 32, MIPSDSP_Q0, \ 2318a22260aeSJia Liu 48, 32, 16, 0, MIPSDSP_LO); 2319a22260aeSJia Liu MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \ 2320a22260aeSJia Liu 24, 16, 8, 0, MIPSDSP_Q0, \ 2321a22260aeSJia Liu 48, 32, 16, 0, MIPSDSP_LO); 2322a22260aeSJia Liu MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \ 2323a22260aeSJia Liu 48, 32, 16, 0, MIPSDSP_LO, \ 2324a22260aeSJia Liu 48, 32, 16, 0, MIPSDSP_LO); 2325a22260aeSJia Liu 2326a22260aeSJia Liu #undef MUL_RETURN64_16_QH 2327a22260aeSJia Liu 2328a22260aeSJia Liu #define MUL_RETURN64_32_QH(name, \ 2329a22260aeSJia Liu rsmov1, rsmov2, \ 2330a22260aeSJia Liu rtmov1, rtmov2) \ 2331a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2332a22260aeSJia Liu CPUMIPSState *env) \ 2333a22260aeSJia Liu { \ 2334a22260aeSJia Liu uint16_t rsB, rsA; \ 2335a22260aeSJia Liu uint16_t rtB, rtA; \ 2336a22260aeSJia Liu uint32_t tempB, tempA; \ 2337a22260aeSJia Liu \ 2338a22260aeSJia Liu rsB = (rs >> rsmov1) & MIPSDSP_LO; \ 2339a22260aeSJia Liu rsA = (rs >> rsmov2) & MIPSDSP_LO; \ 2340a22260aeSJia Liu rtB = (rt >> rtmov1) & MIPSDSP_LO; \ 2341a22260aeSJia Liu rtA = (rt >> rtmov2) & MIPSDSP_LO; \ 2342a22260aeSJia Liu \ 2343a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env); \ 2344a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env); \ 2345a22260aeSJia Liu \ 2346a22260aeSJia Liu return ((uint64_t)tempB << 32) | (uint64_t)tempA; \ 2347a22260aeSJia Liu } 2348a22260aeSJia Liu 2349a22260aeSJia Liu MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32); 2350a22260aeSJia Liu MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0); 2351a22260aeSJia Liu 2352a22260aeSJia Liu #undef MUL_RETURN64_32_QH 2353a22260aeSJia Liu 2354a22260aeSJia Liu void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac, 2355a22260aeSJia Liu CPUMIPSState *env) 2356a22260aeSJia Liu { 2357a22260aeSJia Liu int16_t rs3, rs2, rs1, rs0; 2358a22260aeSJia Liu int16_t rt3, rt2, rt1, rt0; 2359a22260aeSJia Liu int32_t tempD, tempC, tempB, tempA; 2360a22260aeSJia Liu int64_t acc[2]; 2361a22260aeSJia Liu int64_t temp[2]; 2362a22260aeSJia Liu int64_t temp_sum; 2363a22260aeSJia Liu 2364a22260aeSJia Liu MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); 2365a22260aeSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); 2366a22260aeSJia Liu 2367a22260aeSJia Liu tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); 2368a22260aeSJia Liu tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); 2369a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); 2370a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); 2371a22260aeSJia Liu 2372a22260aeSJia Liu temp[0] = ((int32_t)tempD - (int32_t)tempC) + 2373a22260aeSJia Liu ((int32_t)tempB - (int32_t)tempA); 2374a22260aeSJia Liu temp[0] = (int64_t)(temp[0] << 30) >> 30; 2375a22260aeSJia Liu if (((temp[0] >> 33) & 0x01) == 0) { 2376a22260aeSJia Liu temp[1] = 0x00; 2377a22260aeSJia Liu } else { 2378a22260aeSJia Liu temp[1] = ~0ull; 2379a22260aeSJia Liu } 2380a22260aeSJia Liu 2381a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; 2382a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; 2383a22260aeSJia Liu 2384a22260aeSJia Liu temp_sum = acc[0] + temp[0]; 2385a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && 2386a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { 2387a22260aeSJia Liu acc[1] += 1; 2388a22260aeSJia Liu } 2389a22260aeSJia Liu acc[0] = temp_sum; 2390a22260aeSJia Liu acc[1] += temp[1]; 2391a22260aeSJia Liu 2392a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; 2393a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; 2394a22260aeSJia Liu } 2395a22260aeSJia Liu #endif 2396a22260aeSJia Liu 2397a22260aeSJia Liu #define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ 2398a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2399a22260aeSJia Liu CPUMIPSState *env) \ 2400a22260aeSJia Liu { \ 2401a22260aeSJia Liu uint8_t rs3, rs2; \ 2402a22260aeSJia Liu uint8_t rt3, rt2; \ 2403a22260aeSJia Liu uint16_t tempB, tempA; \ 2404a22260aeSJia Liu uint64_t tempC, dotp; \ 2405a22260aeSJia Liu \ 2406a22260aeSJia Liu rs3 = (rs >> rsmov1) & MIPSDSP_Q0; \ 2407a22260aeSJia Liu rs2 = (rs >> rsmov2) & MIPSDSP_Q0; \ 2408a22260aeSJia Liu rt3 = (rt >> rtmov1) & MIPSDSP_Q0; \ 2409a22260aeSJia Liu rt2 = (rt >> rtmov2) & MIPSDSP_Q0; \ 2410a22260aeSJia Liu tempB = mipsdsp_##func(rs3, rt3); \ 2411a22260aeSJia Liu tempA = mipsdsp_##func(rs2, rt2); \ 2412a22260aeSJia Liu dotp = (int64_t)tempB + (int64_t)tempA; \ 2413a22260aeSJia Liu if (is_add) { \ 2414a22260aeSJia Liu tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \ 2415a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \ 2416a22260aeSJia Liu + dotp; \ 2417a22260aeSJia Liu } else { \ 2418a22260aeSJia Liu tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \ 2419a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \ 2420a22260aeSJia Liu - dotp; \ 2421a22260aeSJia Liu } \ 2422a22260aeSJia Liu \ 2423a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2424a22260aeSJia Liu ((tempC & MIPSDSP_LHI) >> 32); \ 2425a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \ 2426a22260aeSJia Liu } 2427a22260aeSJia Liu 2428a22260aeSJia Liu DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16); 2429a22260aeSJia Liu DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0); 2430a22260aeSJia Liu DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16); 2431a22260aeSJia Liu DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0); 2432a22260aeSJia Liu 2433a22260aeSJia Liu #undef DP_QB 2434a22260aeSJia Liu 2435a22260aeSJia Liu #if defined(TARGET_MIPS64) 2436a22260aeSJia Liu #define DP_OB(name, add_sub, \ 2437a22260aeSJia Liu rsmov1, rsmov2, rsmov3, rsmov4, \ 2438a22260aeSJia Liu rtmov1, rtmov2, rtmov3, rtmov4) \ 2439a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2440a22260aeSJia Liu CPUMIPSState *env) \ 2441a22260aeSJia Liu { \ 2442a22260aeSJia Liu uint8_t rsD, rsC, rsB, rsA; \ 2443a22260aeSJia Liu uint8_t rtD, rtC, rtB, rtA; \ 2444a22260aeSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 2445a22260aeSJia Liu uint64_t temp[2]; \ 2446a22260aeSJia Liu uint64_t acc[2]; \ 2447a22260aeSJia Liu uint64_t temp_sum; \ 2448a22260aeSJia Liu \ 2449a22260aeSJia Liu temp[0] = 0; \ 2450a22260aeSJia Liu temp[1] = 0; \ 2451a22260aeSJia Liu \ 2452a22260aeSJia Liu rsD = (rs >> rsmov1) & MIPSDSP_Q0; \ 2453a22260aeSJia Liu rsC = (rs >> rsmov2) & MIPSDSP_Q0; \ 2454a22260aeSJia Liu rsB = (rs >> rsmov3) & MIPSDSP_Q0; \ 2455a22260aeSJia Liu rsA = (rs >> rsmov4) & MIPSDSP_Q0; \ 2456a22260aeSJia Liu rtD = (rt >> rtmov1) & MIPSDSP_Q0; \ 2457a22260aeSJia Liu rtC = (rt >> rtmov2) & MIPSDSP_Q0; \ 2458a22260aeSJia Liu rtB = (rt >> rtmov3) & MIPSDSP_Q0; \ 2459a22260aeSJia Liu rtA = (rt >> rtmov4) & MIPSDSP_Q0; \ 2460a22260aeSJia Liu \ 2461a22260aeSJia Liu tempD = mipsdsp_mul_u8_u8(rsD, rtD); \ 2462a22260aeSJia Liu tempC = mipsdsp_mul_u8_u8(rsC, rtC); \ 2463a22260aeSJia Liu tempB = mipsdsp_mul_u8_u8(rsB, rtB); \ 2464a22260aeSJia Liu tempA = mipsdsp_mul_u8_u8(rsA, rtA); \ 2465a22260aeSJia Liu \ 2466a22260aeSJia Liu temp[0] = (uint64_t)tempD + (uint64_t)tempC + \ 2467a22260aeSJia Liu (uint64_t)tempB + (uint64_t)tempA; \ 2468a22260aeSJia Liu \ 2469a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 2470a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 2471a22260aeSJia Liu \ 2472a22260aeSJia Liu if (add_sub) { \ 2473a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 2474a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2475a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2476a22260aeSJia Liu acc[1] += 1; \ 2477a22260aeSJia Liu } \ 2478a22260aeSJia Liu temp[0] = temp_sum; \ 2479a22260aeSJia Liu temp[1] = acc[1] + temp[1]; \ 2480a22260aeSJia Liu } else { \ 2481a22260aeSJia Liu temp_sum = acc[0] - temp[0]; \ 2482a22260aeSJia Liu if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ 2483a22260aeSJia Liu acc[1] -= 1; \ 2484a22260aeSJia Liu } \ 2485a22260aeSJia Liu temp[0] = temp_sum; \ 2486a22260aeSJia Liu temp[1] = acc[1] - temp[1]; \ 2487a22260aeSJia Liu } \ 2488a22260aeSJia Liu \ 2489a22260aeSJia Liu env->active_tc.HI[ac] = temp[1]; \ 2490a22260aeSJia Liu env->active_tc.LO[ac] = temp[0]; \ 2491a22260aeSJia Liu } 2492a22260aeSJia Liu 2493a22260aeSJia Liu DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32); 2494a22260aeSJia Liu DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0); 2495a22260aeSJia Liu DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32); 2496a22260aeSJia Liu DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0); 2497a22260aeSJia Liu 2498a22260aeSJia Liu #undef DP_OB 2499a22260aeSJia Liu #endif 2500a22260aeSJia Liu 2501a22260aeSJia Liu #define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ 2502a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2503a22260aeSJia Liu CPUMIPSState *env) \ 2504a22260aeSJia Liu { \ 2505a22260aeSJia Liu uint16_t rsB, rsA, rtB, rtA; \ 2506a22260aeSJia Liu int32_t tempA, tempB; \ 2507a22260aeSJia Liu int64_t acc; \ 2508a22260aeSJia Liu \ 2509a22260aeSJia Liu rsB = (rs >> rsmov1) & MIPSDSP_LO; \ 2510a22260aeSJia Liu rsA = (rs >> rsmov2) & MIPSDSP_LO; \ 2511a22260aeSJia Liu rtB = (rt >> rtmov1) & MIPSDSP_LO; \ 2512a22260aeSJia Liu rtA = (rt >> rtmov2) & MIPSDSP_LO; \ 2513a22260aeSJia Liu \ 2514a22260aeSJia Liu tempB = (int32_t)rsB * (int32_t)rtB; \ 2515a22260aeSJia Liu tempA = (int32_t)rsA * (int32_t)rtA; \ 2516a22260aeSJia Liu \ 2517a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2518a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2519a22260aeSJia Liu \ 2520a22260aeSJia Liu if (is_add) { \ 2521a22260aeSJia Liu acc = acc + ((int64_t)tempB + (int64_t)tempA); \ 2522a22260aeSJia Liu } else { \ 2523a22260aeSJia Liu acc = acc - ((int64_t)tempB + (int64_t)tempA); \ 2524a22260aeSJia Liu } \ 2525a22260aeSJia Liu \ 2526a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \ 2527a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO); \ 2528a22260aeSJia Liu } 2529a22260aeSJia Liu 2530a22260aeSJia Liu DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0); 2531a22260aeSJia Liu DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16); 2532a22260aeSJia Liu DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0); 2533a22260aeSJia Liu DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16); 2534a22260aeSJia Liu #undef DP_NOFUNC_PH 2535a22260aeSJia Liu 2536a22260aeSJia Liu #define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ 2537a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2538a22260aeSJia Liu CPUMIPSState *env) \ 2539a22260aeSJia Liu { \ 2540a22260aeSJia Liu int16_t rsB, rsA, rtB, rtA; \ 2541a22260aeSJia Liu int32_t tempB, tempA; \ 2542a22260aeSJia Liu int64_t acc, dotp; \ 2543a22260aeSJia Liu \ 2544a22260aeSJia Liu rsB = (rs >> rsmov1) & MIPSDSP_LO; \ 2545a22260aeSJia Liu rsA = (rs >> rsmov2) & MIPSDSP_LO; \ 2546a22260aeSJia Liu rtB = (rt >> rtmov1) & MIPSDSP_LO; \ 2547a22260aeSJia Liu rtA = (rt >> rtmov2) & MIPSDSP_LO; \ 2548a22260aeSJia Liu \ 2549a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env); \ 2550a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env); \ 2551a22260aeSJia Liu \ 2552a22260aeSJia Liu dotp = (int64_t)tempB + (int64_t)tempA; \ 2553a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2554a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2555a22260aeSJia Liu \ 2556a22260aeSJia Liu if (is_add) { \ 2557a22260aeSJia Liu acc = acc + dotp; \ 2558a22260aeSJia Liu } else { \ 2559a22260aeSJia Liu acc = acc - dotp; \ 2560a22260aeSJia Liu } \ 2561a22260aeSJia Liu \ 2562a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2563a22260aeSJia Liu ((acc & MIPSDSP_LHI) >> 32); \ 2564a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t) \ 2565a22260aeSJia Liu (acc & MIPSDSP_LLO); \ 2566a22260aeSJia Liu } 2567a22260aeSJia Liu 2568a22260aeSJia Liu DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0); 2569a22260aeSJia Liu DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16); 2570a22260aeSJia Liu DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0); 2571a22260aeSJia Liu DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16); 2572a22260aeSJia Liu 2573a22260aeSJia Liu #undef DP_HASFUNC_PH 2574a22260aeSJia Liu 2575a22260aeSJia Liu #define DP_128OPERATION_PH(name, is_add) \ 2576a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2577a22260aeSJia Liu CPUMIPSState *env) \ 2578a22260aeSJia Liu { \ 2579a22260aeSJia Liu int16_t rsh, rsl, rth, rtl; \ 2580a22260aeSJia Liu int32_t tempB, tempA, tempC62_31, tempC63; \ 2581a22260aeSJia Liu int64_t acc, dotp, tempC; \ 2582a22260aeSJia Liu \ 2583a22260aeSJia Liu MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ 2584a22260aeSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 2585a22260aeSJia Liu \ 2586a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env); \ 2587a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env); \ 2588a22260aeSJia Liu \ 2589a22260aeSJia Liu dotp = (int64_t)tempB + (int64_t)tempA; \ 2590a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2591a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2592a22260aeSJia Liu if (is_add) { \ 2593a22260aeSJia Liu tempC = acc + dotp; \ 2594a22260aeSJia Liu } else { \ 2595a22260aeSJia Liu tempC = acc - dotp; \ 2596a22260aeSJia Liu } \ 2597a22260aeSJia Liu tempC63 = (tempC >> 63) & 0x01; \ 2598a22260aeSJia Liu tempC62_31 = (tempC >> 31) & 0xFFFFFFFF; \ 2599a22260aeSJia Liu \ 2600a22260aeSJia Liu if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) { \ 2601a22260aeSJia Liu tempC = 0x7FFFFFFF; \ 2602a22260aeSJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); \ 2603a22260aeSJia Liu } \ 2604a22260aeSJia Liu \ 2605a22260aeSJia Liu if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) { \ 2606a22260aeSJia Liu tempC = (int64_t)(int32_t)0x80000000; \ 2607a22260aeSJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); \ 2608a22260aeSJia Liu } \ 2609a22260aeSJia Liu \ 2610a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2611a22260aeSJia Liu ((tempC & MIPSDSP_LHI) >> 32); \ 2612a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t) \ 2613a22260aeSJia Liu (tempC & MIPSDSP_LLO); \ 2614a22260aeSJia Liu } 2615a22260aeSJia Liu 2616a22260aeSJia Liu DP_128OPERATION_PH(dpaqx_sa_w_ph, 1); 2617a22260aeSJia Liu DP_128OPERATION_PH(dpsqx_sa_w_ph, 0); 2618a22260aeSJia Liu 2619a22260aeSJia Liu #undef DP_128OPERATION_HP 2620a22260aeSJia Liu 2621a22260aeSJia Liu #if defined(TARGET_MIPS64) 2622a22260aeSJia Liu #define DP_QH(name, is_add, use_ac_env) \ 2623a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2624a22260aeSJia Liu CPUMIPSState *env) \ 2625a22260aeSJia Liu { \ 2626a22260aeSJia Liu int32_t rs3, rs2, rs1, rs0; \ 2627a22260aeSJia Liu int32_t rt3, rt2, rt1, rt0; \ 2628a22260aeSJia Liu int32_t tempD, tempC, tempB, tempA; \ 2629a22260aeSJia Liu int64_t acc[2]; \ 2630a22260aeSJia Liu int64_t temp[2]; \ 2631a22260aeSJia Liu int64_t temp_sum; \ 2632a22260aeSJia Liu \ 2633a22260aeSJia Liu MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ 2634a22260aeSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 2635a22260aeSJia Liu \ 2636a22260aeSJia Liu if (use_ac_env) { \ 2637a22260aeSJia Liu tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); \ 2638a22260aeSJia Liu tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); \ 2639a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); \ 2640a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); \ 2641a22260aeSJia Liu } else { \ 2642a22260aeSJia Liu tempD = mipsdsp_mul_u16_u16(rs3, rt3); \ 2643a22260aeSJia Liu tempC = mipsdsp_mul_u16_u16(rs2, rt2); \ 2644a22260aeSJia Liu tempB = mipsdsp_mul_u16_u16(rs1, rt1); \ 2645a22260aeSJia Liu tempA = mipsdsp_mul_u16_u16(rs0, rt0); \ 2646a22260aeSJia Liu } \ 2647a22260aeSJia Liu \ 2648a22260aeSJia Liu temp[0] = (int64_t)tempD + (int64_t)tempC + \ 2649a22260aeSJia Liu (int64_t)tempB + (int64_t)tempA; \ 2650a22260aeSJia Liu \ 2651a22260aeSJia Liu if (temp[0] >= 0) { \ 2652a22260aeSJia Liu temp[1] = 0; \ 2653a22260aeSJia Liu } else { \ 2654a22260aeSJia Liu temp[1] = ~0ull; \ 2655a22260aeSJia Liu } \ 2656a22260aeSJia Liu \ 2657a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 2658a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 2659a22260aeSJia Liu \ 2660a22260aeSJia Liu if (is_add) { \ 2661a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 2662a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2663a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2664a22260aeSJia Liu acc[1] = acc[1] + 1; \ 2665a22260aeSJia Liu } \ 2666a22260aeSJia Liu temp[0] = temp_sum; \ 2667a22260aeSJia Liu temp[1] = acc[1] + temp[1]; \ 2668a22260aeSJia Liu } else { \ 2669a22260aeSJia Liu temp_sum = acc[0] - temp[0]; \ 2670a22260aeSJia Liu if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ 2671a22260aeSJia Liu acc[1] = acc[1] - 1; \ 2672a22260aeSJia Liu } \ 2673a22260aeSJia Liu temp[0] = temp_sum; \ 2674a22260aeSJia Liu temp[1] = acc[1] - temp[1]; \ 2675a22260aeSJia Liu } \ 2676a22260aeSJia Liu \ 2677a22260aeSJia Liu env->active_tc.HI[ac] = temp[1]; \ 2678a22260aeSJia Liu env->active_tc.LO[ac] = temp[0]; \ 2679a22260aeSJia Liu } 2680a22260aeSJia Liu 2681a22260aeSJia Liu DP_QH(dpa_w_qh, 1, 0); 2682a22260aeSJia Liu DP_QH(dpaq_s_w_qh, 1, 1); 2683a22260aeSJia Liu DP_QH(dps_w_qh, 0, 0); 2684a22260aeSJia Liu DP_QH(dpsq_s_w_qh, 0, 1); 2685a22260aeSJia Liu 2686a22260aeSJia Liu #undef DP_QH 2687a22260aeSJia Liu 2688a22260aeSJia Liu #endif 2689a22260aeSJia Liu 2690a22260aeSJia Liu #define DP_L_W(name, is_add) \ 2691a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2692a22260aeSJia Liu CPUMIPSState *env) \ 2693a22260aeSJia Liu { \ 2694a22260aeSJia Liu int32_t temp63; \ 2695a22260aeSJia Liu int64_t dotp, acc; \ 2696a22260aeSJia Liu uint64_t temp; \ 2697a22260aeSJia Liu \ 2698a22260aeSJia Liu dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \ 2699a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2700a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2701a22260aeSJia Liu if (!is_add) { \ 2702a22260aeSJia Liu dotp = -dotp; \ 2703a22260aeSJia Liu } \ 2704a22260aeSJia Liu \ 2705a22260aeSJia Liu temp = acc + dotp; \ 2706a22260aeSJia Liu if (MIPSDSP_OVERFLOW((uint64_t)acc, (uint64_t)dotp, temp, \ 2707a22260aeSJia Liu (0x01ull << 63))) { \ 2708a22260aeSJia Liu temp63 = (temp >> 63) & 0x01; \ 2709a22260aeSJia Liu if (temp63 == 1) { \ 2710a22260aeSJia Liu temp = (0x01ull << 63) - 1; \ 2711a22260aeSJia Liu } else { \ 2712a22260aeSJia Liu temp = 0x01ull << 63; \ 2713a22260aeSJia Liu } \ 2714a22260aeSJia Liu \ 2715a22260aeSJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); \ 2716a22260aeSJia Liu } \ 2717a22260aeSJia Liu \ 2718a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2719a22260aeSJia Liu ((temp & MIPSDSP_LHI) >> 32); \ 2720a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t) \ 2721a22260aeSJia Liu (temp & MIPSDSP_LLO); \ 2722a22260aeSJia Liu } 2723a22260aeSJia Liu 2724a22260aeSJia Liu DP_L_W(dpaq_sa_l_w, 1); 2725a22260aeSJia Liu DP_L_W(dpsq_sa_l_w, 0); 2726a22260aeSJia Liu 2727a22260aeSJia Liu #undef DP_L_W 2728a22260aeSJia Liu 2729a22260aeSJia Liu #if defined(TARGET_MIPS64) 2730a22260aeSJia Liu #define DP_L_PW(name, func) \ 2731a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2732a22260aeSJia Liu CPUMIPSState *env) \ 2733a22260aeSJia Liu { \ 2734a22260aeSJia Liu int32_t rs1, rs0; \ 2735a22260aeSJia Liu int32_t rt1, rt0; \ 2736a22260aeSJia Liu int64_t tempB[2], tempA[2]; \ 2737a22260aeSJia Liu int64_t temp[2]; \ 2738a22260aeSJia Liu int64_t acc[2]; \ 2739a22260aeSJia Liu int64_t temp_sum; \ 2740a22260aeSJia Liu \ 2741a22260aeSJia Liu temp[0] = 0; \ 2742a22260aeSJia Liu temp[1] = 0; \ 2743a22260aeSJia Liu \ 2744a22260aeSJia Liu MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ 2745a22260aeSJia Liu MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 2746a22260aeSJia Liu \ 2747a22260aeSJia Liu tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); \ 2748a22260aeSJia Liu tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); \ 2749a22260aeSJia Liu \ 2750a22260aeSJia Liu if (tempB[0] >= 0) { \ 2751a22260aeSJia Liu tempB[1] = 0x00; \ 2752a22260aeSJia Liu } else { \ 2753a22260aeSJia Liu tempB[1] = ~0ull; \ 2754a22260aeSJia Liu } \ 2755a22260aeSJia Liu \ 2756a22260aeSJia Liu if (tempA[0] >= 0) { \ 2757a22260aeSJia Liu tempA[1] = 0x00; \ 2758a22260aeSJia Liu } else { \ 2759a22260aeSJia Liu tempA[1] = ~0ull; \ 2760a22260aeSJia Liu } \ 2761a22260aeSJia Liu \ 2762a22260aeSJia Liu temp_sum = tempB[0] + tempA[0]; \ 2763a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)tempB[0]) && \ 2764a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)tempA[0])) { \ 2765a22260aeSJia Liu temp[1] += 1; \ 2766a22260aeSJia Liu } \ 2767a22260aeSJia Liu temp[0] = temp_sum; \ 2768a22260aeSJia Liu temp[1] += tempB[1] + tempA[1]; \ 2769a22260aeSJia Liu \ 2770a22260aeSJia Liu mipsdsp_##func(acc, ac, temp, env); \ 2771a22260aeSJia Liu \ 2772a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; \ 2773a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; \ 2774a22260aeSJia Liu } 2775a22260aeSJia Liu 2776a22260aeSJia Liu DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63); 2777a22260aeSJia Liu DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63); 2778a22260aeSJia Liu 2779a22260aeSJia Liu #undef DP_L_PW 2780a22260aeSJia Liu 2781a22260aeSJia Liu void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac, 2782a22260aeSJia Liu CPUMIPSState *env) 2783a22260aeSJia Liu { 2784a22260aeSJia Liu int32_t rs1, rs0; 2785a22260aeSJia Liu int32_t rt1, rt0; 2786a22260aeSJia Liu int64_t tempB[2], tempA[2]; 2787a22260aeSJia Liu int64_t temp[2]; 2788a22260aeSJia Liu int64_t acc[2]; 2789a22260aeSJia Liu int64_t temp_sum; 2790a22260aeSJia Liu 2791a22260aeSJia Liu rs1 = (rs >> 32) & MIPSDSP_LLO; 2792a22260aeSJia Liu rs0 = rs & MIPSDSP_LLO; 2793a22260aeSJia Liu rt1 = (rt >> 32) & MIPSDSP_LLO; 2794a22260aeSJia Liu rt0 = rt & MIPSDSP_LLO; 2795a22260aeSJia Liu 2796a22260aeSJia Liu tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); 2797a22260aeSJia Liu tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); 2798a22260aeSJia Liu 2799a22260aeSJia Liu if (tempB[0] >= 0) { 2800a22260aeSJia Liu tempB[1] = 0x00; 2801a22260aeSJia Liu } else { 2802a22260aeSJia Liu tempB[1] = ~0ull; 2803a22260aeSJia Liu } 2804a22260aeSJia Liu 2805a22260aeSJia Liu if (tempA[0] >= 0) { 2806a22260aeSJia Liu tempA[1] = 0x00; 2807a22260aeSJia Liu } else { 2808a22260aeSJia Liu tempA[1] = ~0ull; 2809a22260aeSJia Liu } 2810a22260aeSJia Liu 2811a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; 2812a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; 2813a22260aeSJia Liu 2814a22260aeSJia Liu temp_sum = tempB[0] - tempA[0]; 2815a22260aeSJia Liu if ((uint64_t)temp_sum > (uint64_t)tempB[0]) { 2816a22260aeSJia Liu tempB[1] -= 1; 2817a22260aeSJia Liu } 2818a22260aeSJia Liu temp[0] = temp_sum; 2819a22260aeSJia Liu temp[1] = tempB[1] - tempA[1]; 2820a22260aeSJia Liu 2821a22260aeSJia Liu if ((temp[1] & 0x01) == 0) { 2822a22260aeSJia Liu temp[1] = 0x00; 2823a22260aeSJia Liu } else { 2824a22260aeSJia Liu temp[1] = ~0ull; 2825a22260aeSJia Liu } 2826a22260aeSJia Liu 2827a22260aeSJia Liu temp_sum = acc[0] + temp[0]; 2828a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && 2829a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { 2830a22260aeSJia Liu acc[1] += 1; 2831a22260aeSJia Liu } 2832a22260aeSJia Liu acc[0] = temp_sum; 2833a22260aeSJia Liu acc[1] += temp[1]; 2834a22260aeSJia Liu 2835a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; 2836a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; 2837a22260aeSJia Liu } 2838a22260aeSJia Liu #endif 2839a22260aeSJia Liu 2840a22260aeSJia Liu #define MAQ_S_W(name, mov) \ 2841a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2842a22260aeSJia Liu CPUMIPSState *env) \ 2843a22260aeSJia Liu { \ 2844a22260aeSJia Liu int16_t rsh, rth; \ 2845a22260aeSJia Liu int32_t tempA; \ 2846a22260aeSJia Liu int64_t tempL, acc; \ 2847a22260aeSJia Liu \ 2848a22260aeSJia Liu rsh = (rs >> mov) & MIPSDSP_LO; \ 2849a22260aeSJia Liu rth = (rt >> mov) & MIPSDSP_LO; \ 2850a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ 2851a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2852a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2853a22260aeSJia Liu tempL = (int64_t)tempA + acc; \ 2854a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2855a22260aeSJia Liu ((tempL & MIPSDSP_LHI) >> 32); \ 2856a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t) \ 2857a22260aeSJia Liu (tempL & MIPSDSP_LLO); \ 2858a22260aeSJia Liu } 2859a22260aeSJia Liu 2860a22260aeSJia Liu MAQ_S_W(maq_s_w_phl, 16); 2861a22260aeSJia Liu MAQ_S_W(maq_s_w_phr, 0); 2862a22260aeSJia Liu 2863a22260aeSJia Liu #undef MAQ_S_W 2864a22260aeSJia Liu 2865a22260aeSJia Liu #define MAQ_SA_W(name, mov) \ 2866a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2867a22260aeSJia Liu CPUMIPSState *env) \ 2868a22260aeSJia Liu { \ 2869a22260aeSJia Liu int16_t rsh, rth; \ 2870a22260aeSJia Liu int32_t tempA; \ 2871a22260aeSJia Liu \ 2872a22260aeSJia Liu rsh = (rs >> mov) & MIPSDSP_LO; \ 2873a22260aeSJia Liu rth = (rt >> mov) & MIPSDSP_LO; \ 2874a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ 2875a22260aeSJia Liu tempA = mipsdsp_sat32_acc_q31(ac, tempA, env); \ 2876a22260aeSJia Liu \ 2877a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA & \ 2878a22260aeSJia Liu MIPSDSP_LHI) >> 32); \ 2879a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA & \ 2880a22260aeSJia Liu MIPSDSP_LLO); \ 2881a22260aeSJia Liu } 2882a22260aeSJia Liu 2883a22260aeSJia Liu MAQ_SA_W(maq_sa_w_phl, 16); 2884a22260aeSJia Liu MAQ_SA_W(maq_sa_w_phr, 0); 2885a22260aeSJia Liu 2886a22260aeSJia Liu #undef MAQ_SA_W 2887a22260aeSJia Liu 2888a22260aeSJia Liu #define MULQ_W(name, addvar) \ 2889a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2890a22260aeSJia Liu CPUMIPSState *env) \ 2891a22260aeSJia Liu { \ 2892a22260aeSJia Liu uint32_t rs_t, rt_t; \ 2893a22260aeSJia Liu int32_t tempI; \ 2894a22260aeSJia Liu int64_t tempL; \ 2895a22260aeSJia Liu \ 2896a22260aeSJia Liu rs_t = rs & MIPSDSP_LLO; \ 2897a22260aeSJia Liu rt_t = rt & MIPSDSP_LLO; \ 2898a22260aeSJia Liu \ 2899a22260aeSJia Liu if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) { \ 2900a22260aeSJia Liu tempL = 0x7FFFFFFF00000000ull; \ 2901a22260aeSJia Liu set_DSPControl_overflow_flag(1, 21, env); \ 2902a22260aeSJia Liu } else { \ 2903a22260aeSJia Liu tempL = ((int64_t)rs_t * (int64_t)rt_t) << 1; \ 2904a22260aeSJia Liu tempL += addvar; \ 2905a22260aeSJia Liu } \ 2906a22260aeSJia Liu tempI = (tempL & MIPSDSP_LHI) >> 32; \ 2907a22260aeSJia Liu \ 2908a22260aeSJia Liu return (target_long)(int32_t)tempI; \ 2909a22260aeSJia Liu } 2910a22260aeSJia Liu 2911a22260aeSJia Liu MULQ_W(mulq_s_w, 0); 2912a22260aeSJia Liu MULQ_W(mulq_rs_w, 0x80000000ull); 2913a22260aeSJia Liu 2914a22260aeSJia Liu #undef MULQ_W 2915a22260aeSJia Liu 2916a22260aeSJia Liu #if defined(TARGET_MIPS64) 2917a22260aeSJia Liu 2918a22260aeSJia Liu #define MAQ_S_W_QH(name, mov) \ 2919a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2920a22260aeSJia Liu CPUMIPSState *env) \ 2921a22260aeSJia Liu { \ 2922a22260aeSJia Liu int16_t rs_t, rt_t; \ 2923a22260aeSJia Liu int32_t temp_mul; \ 2924a22260aeSJia Liu int64_t temp[2]; \ 2925a22260aeSJia Liu int64_t acc[2]; \ 2926a22260aeSJia Liu int64_t temp_sum; \ 2927a22260aeSJia Liu \ 2928a22260aeSJia Liu temp[0] = 0; \ 2929a22260aeSJia Liu temp[1] = 0; \ 2930a22260aeSJia Liu \ 2931a22260aeSJia Liu rs_t = (rs >> mov) & MIPSDSP_LO; \ 2932a22260aeSJia Liu rt_t = (rt >> mov) & MIPSDSP_LO; \ 2933a22260aeSJia Liu temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \ 2934a22260aeSJia Liu \ 2935a22260aeSJia Liu temp[0] = (int64_t)temp_mul; \ 2936a22260aeSJia Liu if (temp[0] >= 0) { \ 2937a22260aeSJia Liu temp[1] = 0x00; \ 2938a22260aeSJia Liu } else { \ 2939a22260aeSJia Liu temp[1] = ~0ull; \ 2940a22260aeSJia Liu } \ 2941a22260aeSJia Liu \ 2942a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 2943a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 2944a22260aeSJia Liu \ 2945a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 2946a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2947a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2948a22260aeSJia Liu acc[1] += 1; \ 2949a22260aeSJia Liu } \ 2950a22260aeSJia Liu acc[0] = temp_sum; \ 2951a22260aeSJia Liu acc[1] += temp[1]; \ 2952a22260aeSJia Liu \ 2953a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; \ 2954a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; \ 2955a22260aeSJia Liu } 2956a22260aeSJia Liu 2957a22260aeSJia Liu MAQ_S_W_QH(maq_s_w_qhll, 48); 2958a22260aeSJia Liu MAQ_S_W_QH(maq_s_w_qhlr, 32); 2959a22260aeSJia Liu MAQ_S_W_QH(maq_s_w_qhrl, 16); 2960a22260aeSJia Liu MAQ_S_W_QH(maq_s_w_qhrr, 0); 2961a22260aeSJia Liu 2962a22260aeSJia Liu #undef MAQ_S_W_QH 2963a22260aeSJia Liu 2964a22260aeSJia Liu #define MAQ_SA_W(name, mov) \ 2965a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2966a22260aeSJia Liu CPUMIPSState *env) \ 2967a22260aeSJia Liu { \ 2968a22260aeSJia Liu int16_t rs_t, rt_t; \ 2969a22260aeSJia Liu int32_t temp; \ 2970a22260aeSJia Liu int64_t acc[2]; \ 2971a22260aeSJia Liu \ 2972a22260aeSJia Liu rs_t = (rs >> mov) & MIPSDSP_LO; \ 2973a22260aeSJia Liu rt_t = (rt >> mov) & MIPSDSP_LO; \ 2974a22260aeSJia Liu temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \ 2975a22260aeSJia Liu temp = mipsdsp_sat32_acc_q31(ac, temp, env); \ 2976a22260aeSJia Liu \ 2977a22260aeSJia Liu acc[0] = (int64_t)(int32_t)temp; \ 2978a22260aeSJia Liu if (acc[0] >= 0) { \ 2979a22260aeSJia Liu acc[1] = 0x00; \ 2980a22260aeSJia Liu } else { \ 2981a22260aeSJia Liu acc[1] = ~0ull; \ 2982a22260aeSJia Liu } \ 2983a22260aeSJia Liu \ 2984a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; \ 2985a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; \ 2986a22260aeSJia Liu } 2987a22260aeSJia Liu 2988a22260aeSJia Liu MAQ_SA_W(maq_sa_w_qhll, 48); 2989a22260aeSJia Liu MAQ_SA_W(maq_sa_w_qhlr, 32); 2990a22260aeSJia Liu MAQ_SA_W(maq_sa_w_qhrl, 16); 2991a22260aeSJia Liu MAQ_SA_W(maq_sa_w_qhrr, 0); 2992a22260aeSJia Liu 2993a22260aeSJia Liu #undef MAQ_SA_W 2994a22260aeSJia Liu 2995a22260aeSJia Liu #define MAQ_S_L_PW(name, mov) \ 2996a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2997a22260aeSJia Liu CPUMIPSState *env) \ 2998a22260aeSJia Liu { \ 2999a22260aeSJia Liu int32_t rs_t, rt_t; \ 3000a22260aeSJia Liu int64_t temp[2]; \ 3001a22260aeSJia Liu int64_t acc[2]; \ 3002a22260aeSJia Liu int64_t temp_sum; \ 3003a22260aeSJia Liu \ 3004a22260aeSJia Liu temp[0] = 0; \ 3005a22260aeSJia Liu temp[1] = 0; \ 3006a22260aeSJia Liu \ 3007a22260aeSJia Liu rs_t = (rs >> mov) & MIPSDSP_LLO; \ 3008a22260aeSJia Liu rt_t = (rt >> mov) & MIPSDSP_LLO; \ 3009a22260aeSJia Liu \ 3010a22260aeSJia Liu temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env); \ 3011a22260aeSJia Liu if (temp[0] >= 0) { \ 3012a22260aeSJia Liu temp[1] = 0x00; \ 3013a22260aeSJia Liu } else { \ 3014a22260aeSJia Liu temp[1] = ~0ull; \ 3015a22260aeSJia Liu } \ 3016a22260aeSJia Liu \ 3017a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 3018a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 3019a22260aeSJia Liu \ 3020a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 3021a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 3022a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 3023a22260aeSJia Liu acc[1] += 1; \ 3024a22260aeSJia Liu } \ 3025a22260aeSJia Liu acc[0] = temp_sum; \ 3026a22260aeSJia Liu acc[1] += temp[1]; \ 3027a22260aeSJia Liu \ 3028a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; \ 3029a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; \ 3030a22260aeSJia Liu } 3031a22260aeSJia Liu 3032a22260aeSJia Liu MAQ_S_L_PW(maq_s_l_pwl, 32); 3033a22260aeSJia Liu MAQ_S_L_PW(maq_s_l_pwr, 0); 3034a22260aeSJia Liu 3035a22260aeSJia Liu #undef MAQ_S_L_PW 3036a22260aeSJia Liu 3037a22260aeSJia Liu #define DM_OPERATE(name, func, is_add, sigext) \ 3038a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 3039a22260aeSJia Liu CPUMIPSState *env) \ 3040a22260aeSJia Liu { \ 3041a22260aeSJia Liu int32_t rs1, rs0; \ 3042a22260aeSJia Liu int32_t rt1, rt0; \ 3043a22260aeSJia Liu int64_t tempBL[2], tempAL[2]; \ 3044a22260aeSJia Liu int64_t acc[2]; \ 3045a22260aeSJia Liu int64_t temp[2]; \ 3046a22260aeSJia Liu int64_t temp_sum; \ 3047a22260aeSJia Liu \ 3048a22260aeSJia Liu temp[0] = 0x00; \ 3049a22260aeSJia Liu temp[1] = 0x00; \ 3050a22260aeSJia Liu \ 3051a22260aeSJia Liu MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ 3052a22260aeSJia Liu MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 3053a22260aeSJia Liu \ 3054a22260aeSJia Liu if (sigext) { \ 3055a22260aeSJia Liu tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1); \ 3056a22260aeSJia Liu tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0); \ 3057a22260aeSJia Liu \ 3058a22260aeSJia Liu if (tempBL[0] >= 0) { \ 3059a22260aeSJia Liu tempBL[1] = 0x0; \ 3060a22260aeSJia Liu } else { \ 3061a22260aeSJia Liu tempBL[1] = ~0ull; \ 3062a22260aeSJia Liu } \ 3063a22260aeSJia Liu \ 3064a22260aeSJia Liu if (tempAL[0] >= 0) { \ 3065a22260aeSJia Liu tempAL[1] = 0x0; \ 3066a22260aeSJia Liu } else { \ 3067a22260aeSJia Liu tempAL[1] = ~0ull; \ 3068a22260aeSJia Liu } \ 3069a22260aeSJia Liu } else { \ 3070a22260aeSJia Liu tempBL[0] = mipsdsp_##func(rs1, rt1); \ 3071a22260aeSJia Liu tempAL[0] = mipsdsp_##func(rs0, rt0); \ 3072a22260aeSJia Liu tempBL[1] = 0; \ 3073a22260aeSJia Liu tempAL[1] = 0; \ 3074a22260aeSJia Liu } \ 3075a22260aeSJia Liu \ 3076a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 3077a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 3078a22260aeSJia Liu \ 3079a22260aeSJia Liu temp_sum = tempBL[0] + tempAL[0]; \ 3080a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) && \ 3081a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)tempAL[0])) { \ 3082a22260aeSJia Liu temp[1] += 1; \ 3083a22260aeSJia Liu } \ 3084a22260aeSJia Liu temp[0] = temp_sum; \ 3085a22260aeSJia Liu temp[1] += tempBL[1] + tempAL[1]; \ 3086a22260aeSJia Liu \ 3087a22260aeSJia Liu if (is_add) { \ 3088a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 3089a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 3090a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 3091a22260aeSJia Liu acc[1] += 1; \ 3092a22260aeSJia Liu } \ 3093a22260aeSJia Liu temp[0] = temp_sum; \ 3094a22260aeSJia Liu temp[1] = acc[1] + temp[1]; \ 3095a22260aeSJia Liu } else { \ 3096a22260aeSJia Liu temp_sum = acc[0] - temp[0]; \ 3097a22260aeSJia Liu if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ 3098a22260aeSJia Liu acc[1] -= 1; \ 3099a22260aeSJia Liu } \ 3100a22260aeSJia Liu temp[0] = temp_sum; \ 3101a22260aeSJia Liu temp[1] = acc[1] - temp[1]; \ 3102a22260aeSJia Liu } \ 3103a22260aeSJia Liu \ 3104a22260aeSJia Liu env->active_tc.HI[ac] = temp[1]; \ 3105a22260aeSJia Liu env->active_tc.LO[ac] = temp[0]; \ 3106a22260aeSJia Liu } 3107a22260aeSJia Liu 3108a22260aeSJia Liu DM_OPERATE(dmadd, mul_i32_i32, 1, 1); 3109a22260aeSJia Liu DM_OPERATE(dmaddu, mul_u32_u32, 1, 0); 3110a22260aeSJia Liu DM_OPERATE(dmsub, mul_i32_i32, 0, 1); 3111a22260aeSJia Liu DM_OPERATE(dmsubu, mul_u32_u32, 0, 0); 3112a22260aeSJia Liu #undef DM_OPERATE 3113a22260aeSJia Liu #endif 3114a22260aeSJia Liu 31151cb6686cSJia Liu /** DSP Bit/Manipulation Sub-class insns **/ 31161cb6686cSJia Liu target_ulong helper_bitrev(target_ulong rt) 31171cb6686cSJia Liu { 31181cb6686cSJia Liu int32_t temp; 31191cb6686cSJia Liu uint32_t rd; 31201cb6686cSJia Liu int i; 31211cb6686cSJia Liu 31221cb6686cSJia Liu temp = rt & MIPSDSP_LO; 31231cb6686cSJia Liu rd = 0; 31241cb6686cSJia Liu for (i = 0; i < 16; i++) { 31251cb6686cSJia Liu rd = (rd << 1) | (temp & 1); 31261cb6686cSJia Liu temp = temp >> 1; 31271cb6686cSJia Liu } 31281cb6686cSJia Liu 31291cb6686cSJia Liu return (target_ulong)rd; 31301cb6686cSJia Liu } 31311cb6686cSJia Liu 31321cb6686cSJia Liu #define BIT_INSV(name, posfilter, sizefilter, ret_type) \ 31331cb6686cSJia Liu target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \ 31341cb6686cSJia Liu target_ulong rt) \ 31351cb6686cSJia Liu { \ 31361cb6686cSJia Liu uint32_t pos, size, msb, lsb; \ 31371cb6686cSJia Liu target_ulong filter; \ 31381cb6686cSJia Liu target_ulong temp, temprs, temprt; \ 31391cb6686cSJia Liu target_ulong dspc; \ 31401cb6686cSJia Liu \ 31411cb6686cSJia Liu dspc = env->active_tc.DSPControl; \ 31421cb6686cSJia Liu \ 31431cb6686cSJia Liu pos = dspc & posfilter; \ 31441cb6686cSJia Liu size = (dspc >> 7) & sizefilter; \ 31451cb6686cSJia Liu \ 31461cb6686cSJia Liu msb = pos + size - 1; \ 31471cb6686cSJia Liu lsb = pos; \ 31481cb6686cSJia Liu \ 31491cb6686cSJia Liu if (lsb > msb || (msb > TARGET_LONG_BITS)) { \ 31501cb6686cSJia Liu return rt; \ 31511cb6686cSJia Liu } \ 31521cb6686cSJia Liu \ 31531cb6686cSJia Liu filter = ((int32_t)0x01 << size) - 1; \ 31541cb6686cSJia Liu filter = filter << pos; \ 31551cb6686cSJia Liu temprs = rs & filter; \ 31561cb6686cSJia Liu temprt = rt & ~filter; \ 31571cb6686cSJia Liu temp = temprs | temprt; \ 31581cb6686cSJia Liu \ 31591cb6686cSJia Liu return (target_long)(ret_type)temp; \ 31601cb6686cSJia Liu } 31611cb6686cSJia Liu 31621cb6686cSJia Liu BIT_INSV(insv, 0x1F, 0x1F, int32_t); 31631cb6686cSJia Liu #ifdef TARGET_MIPS64 31641cb6686cSJia Liu BIT_INSV(dinsv, 0x7F, 0x3F, target_long); 31651cb6686cSJia Liu #endif 31661cb6686cSJia Liu 31671cb6686cSJia Liu #undef BIT_INSV 31681cb6686cSJia Liu 31691cb6686cSJia Liu 317026690560SJia Liu /** DSP Compare-Pick Sub-class insns **/ 317126690560SJia Liu #define CMP_HAS_RET(name, func, split_num, filter, bit_size) \ 317226690560SJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt) \ 317326690560SJia Liu { \ 317426690560SJia Liu uint32_t rs_t, rt_t; \ 317526690560SJia Liu uint8_t cc; \ 317626690560SJia Liu uint32_t temp = 0; \ 317726690560SJia Liu int i; \ 317826690560SJia Liu \ 317926690560SJia Liu for (i = 0; i < split_num; i++) { \ 318026690560SJia Liu rs_t = (rs >> (bit_size * i)) & filter; \ 318126690560SJia Liu rt_t = (rt >> (bit_size * i)) & filter; \ 318226690560SJia Liu cc = mipsdsp_##func(rs_t, rt_t); \ 318326690560SJia Liu temp |= cc << i; \ 318426690560SJia Liu } \ 318526690560SJia Liu \ 318626690560SJia Liu return (target_ulong)temp; \ 318726690560SJia Liu } 318826690560SJia Liu 318926690560SJia Liu CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); 319026690560SJia Liu CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); 319126690560SJia Liu CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); 319226690560SJia Liu 319326690560SJia Liu #ifdef TARGET_MIPS64 319426690560SJia Liu CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); 319526690560SJia Liu CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); 319626690560SJia Liu CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8); 319726690560SJia Liu #endif 319826690560SJia Liu 319926690560SJia Liu #undef CMP_HAS_RET 320026690560SJia Liu 320126690560SJia Liu 320226690560SJia Liu #define CMP_NO_RET(name, func, split_num, filter, bit_size) \ 320326690560SJia Liu void helper_##name(target_ulong rs, target_ulong rt, \ 320426690560SJia Liu CPUMIPSState *env) \ 320526690560SJia Liu { \ 320626690560SJia Liu int##bit_size##_t rs_t, rt_t; \ 320726690560SJia Liu int##bit_size##_t flag = 0; \ 320826690560SJia Liu int##bit_size##_t cc; \ 320926690560SJia Liu int i; \ 321026690560SJia Liu \ 321126690560SJia Liu for (i = 0; i < split_num; i++) { \ 321226690560SJia Liu rs_t = (rs >> (bit_size * i)) & filter; \ 321326690560SJia Liu rt_t = (rt >> (bit_size * i)) & filter; \ 321426690560SJia Liu \ 321526690560SJia Liu cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t); \ 321626690560SJia Liu flag |= cc << i; \ 321726690560SJia Liu } \ 321826690560SJia Liu \ 321926690560SJia Liu set_DSPControl_24(flag, split_num, env); \ 322026690560SJia Liu } 322126690560SJia Liu 322226690560SJia Liu CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); 322326690560SJia Liu CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); 322426690560SJia Liu CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); 322526690560SJia Liu 322626690560SJia Liu CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16); 322726690560SJia Liu CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16); 322826690560SJia Liu CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16); 322926690560SJia Liu 323026690560SJia Liu #ifdef TARGET_MIPS64 323126690560SJia Liu CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); 323226690560SJia Liu CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); 323326690560SJia Liu CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8); 323426690560SJia Liu 323526690560SJia Liu CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16); 323626690560SJia Liu CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16); 323726690560SJia Liu CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16); 323826690560SJia Liu 323926690560SJia Liu CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32); 324026690560SJia Liu CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32); 324126690560SJia Liu CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32); 324226690560SJia Liu #endif 324326690560SJia Liu #undef CMP_NO_RET 324426690560SJia Liu 324526690560SJia Liu #if defined(TARGET_MIPS64) 324626690560SJia Liu 324726690560SJia Liu #define CMPGDU_OB(name) \ 324826690560SJia Liu target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \ 324926690560SJia Liu CPUMIPSState *env) \ 325026690560SJia Liu { \ 325126690560SJia Liu int i; \ 325226690560SJia Liu uint8_t rs_t, rt_t; \ 325326690560SJia Liu uint32_t cond; \ 325426690560SJia Liu \ 325526690560SJia Liu cond = 0; \ 325626690560SJia Liu \ 325726690560SJia Liu for (i = 0; i < 8; i++) { \ 325826690560SJia Liu rs_t = (rs >> (8 * i)) & MIPSDSP_Q0; \ 325926690560SJia Liu rt_t = (rt >> (8 * i)) & MIPSDSP_Q0; \ 326026690560SJia Liu \ 326126690560SJia Liu if (mipsdsp_cmpu_##name(rs_t, rt_t)) { \ 326226690560SJia Liu cond |= 0x01 << i; \ 326326690560SJia Liu } \ 326426690560SJia Liu } \ 326526690560SJia Liu \ 326626690560SJia Liu set_DSPControl_24(cond, 8, env); \ 326726690560SJia Liu \ 326826690560SJia Liu return (uint64_t)cond; \ 326926690560SJia Liu } 327026690560SJia Liu 327126690560SJia Liu CMPGDU_OB(eq) 327226690560SJia Liu CMPGDU_OB(lt) 327326690560SJia Liu CMPGDU_OB(le) 327426690560SJia Liu #undef CMPGDU_OB 327526690560SJia Liu #endif 327626690560SJia Liu 327726690560SJia Liu #define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \ 327826690560SJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 327926690560SJia Liu CPUMIPSState *env) \ 328026690560SJia Liu { \ 328126690560SJia Liu uint32_t rs_t, rt_t; \ 328226690560SJia Liu uint32_t cc; \ 328326690560SJia Liu target_ulong dsp; \ 328426690560SJia Liu int i; \ 328526690560SJia Liu target_ulong result = 0; \ 328626690560SJia Liu \ 328726690560SJia Liu dsp = env->active_tc.DSPControl; \ 328826690560SJia Liu for (i = 0; i < split_num; i++) { \ 328926690560SJia Liu rs_t = (rs >> (bit_size * i)) & filter; \ 329026690560SJia Liu rt_t = (rt >> (bit_size * i)) & filter; \ 329126690560SJia Liu cc = (dsp >> (24 + i)) & 0x01; \ 329226690560SJia Liu cc = cc == 1 ? rs_t : rt_t; \ 329326690560SJia Liu \ 329426690560SJia Liu result |= (target_ulong)cc << (bit_size * i); \ 329526690560SJia Liu } \ 329626690560SJia Liu \ 329726690560SJia Liu if (ret32bit) { \ 329826690560SJia Liu result = (target_long)(int32_t)(result & MIPSDSP_LLO); \ 329926690560SJia Liu } \ 330026690560SJia Liu \ 330126690560SJia Liu return result; \ 330226690560SJia Liu } 330326690560SJia Liu 330426690560SJia Liu PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1); 330526690560SJia Liu PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1); 330626690560SJia Liu 330726690560SJia Liu #ifdef TARGET_MIPS64 330826690560SJia Liu PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0); 330926690560SJia Liu PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0); 331026690560SJia Liu PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0); 331126690560SJia Liu #endif 331226690560SJia Liu #undef PICK_INSN 331326690560SJia Liu 331426690560SJia Liu #define APPEND_INSN(name, ret_32) \ 331526690560SJia Liu target_ulong helper_##name(target_ulong rt, target_ulong rs, uint32_t sa) \ 331626690560SJia Liu { \ 331726690560SJia Liu target_ulong temp; \ 331826690560SJia Liu \ 331926690560SJia Liu if (ret_32) { \ 332026690560SJia Liu temp = ((rt & MIPSDSP_LLO) << sa) | \ 332126690560SJia Liu ((rs & MIPSDSP_LLO) & ((0x01 << sa) - 1)); \ 332226690560SJia Liu temp = (target_long)(int32_t)(temp & MIPSDSP_LLO); \ 332326690560SJia Liu } else { \ 332426690560SJia Liu temp = (rt << sa) | (rs & ((0x01 << sa) - 1)); \ 332526690560SJia Liu } \ 332626690560SJia Liu \ 332726690560SJia Liu return temp; \ 332826690560SJia Liu } 332926690560SJia Liu 333026690560SJia Liu APPEND_INSN(append, 1); 333126690560SJia Liu #ifdef TARGET_MIPS64 333226690560SJia Liu APPEND_INSN(dappend, 0); 333326690560SJia Liu #endif 333426690560SJia Liu #undef APPEND_INSN 333526690560SJia Liu 333626690560SJia Liu #define PREPEND_INSN(name, or_val, ret_32) \ 333726690560SJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 333826690560SJia Liu uint32_t sa) \ 333926690560SJia Liu { \ 334026690560SJia Liu sa |= or_val; \ 334126690560SJia Liu \ 334226690560SJia Liu if (1) { \ 334326690560SJia Liu return (target_long)(int32_t)(uint32_t) \ 334426690560SJia Liu (((rs & MIPSDSP_LLO) << (32 - sa)) | \ 334526690560SJia Liu ((rt & MIPSDSP_LLO) >> sa)); \ 334626690560SJia Liu } else { \ 334726690560SJia Liu return (rs << (64 - sa)) | (rt >> sa); \ 334826690560SJia Liu } \ 334926690560SJia Liu } 335026690560SJia Liu 335126690560SJia Liu PREPEND_INSN(prepend, 0, 1); 335226690560SJia Liu #ifdef TARGET_MIPS64 335326690560SJia Liu PREPEND_INSN(prependw, 0, 0); 335426690560SJia Liu PREPEND_INSN(prependd, 0x20, 0); 335526690560SJia Liu #endif 335626690560SJia Liu #undef PREPEND_INSN 335726690560SJia Liu 335826690560SJia Liu #define BALIGN_INSN(name, filter, ret32) \ 335926690560SJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, uint32_t bp) \ 336026690560SJia Liu { \ 336126690560SJia Liu bp = bp & 0x03; \ 336226690560SJia Liu \ 336326690560SJia Liu if ((bp & 1) == 0) { \ 336426690560SJia Liu return rt; \ 336526690560SJia Liu } else { \ 336626690560SJia Liu if (ret32) { \ 336726690560SJia Liu return (target_long)(int32_t)((rt << (8 * bp)) | \ 336826690560SJia Liu (rs >> (8 * (4 - bp)))); \ 336926690560SJia Liu } else { \ 337026690560SJia Liu return (rt << (8 * bp)) | (rs >> (8 * (8 - bp))); \ 337126690560SJia Liu } \ 337226690560SJia Liu } \ 337326690560SJia Liu } 337426690560SJia Liu 337526690560SJia Liu BALIGN_INSN(balign, 0x03, 1); 337626690560SJia Liu #if defined(TARGET_MIPS64) 337726690560SJia Liu BALIGN_INSN(dbalign, 0x07, 0); 337826690560SJia Liu #endif 337926690560SJia Liu #undef BALIGN_INSN 338026690560SJia Liu 338126690560SJia Liu target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt) 338226690560SJia Liu { 338326690560SJia Liu uint32_t rsl, rth; 338426690560SJia Liu 338526690560SJia Liu rsl = rs & MIPSDSP_LO; 338626690560SJia Liu rth = (rt & MIPSDSP_HI) >> 16; 338726690560SJia Liu 338826690560SJia Liu return (target_long)(int32_t)((rsl << 16) | rth); 338926690560SJia Liu } 339026690560SJia Liu 339126690560SJia Liu #if defined(TARGET_MIPS64) 339226690560SJia Liu target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt) 339326690560SJia Liu { 339426690560SJia Liu uint32_t rs0, rt1; 339526690560SJia Liu 339626690560SJia Liu rs0 = rs & MIPSDSP_LLO; 339726690560SJia Liu rt1 = (rt >> 32) & MIPSDSP_LLO; 339826690560SJia Liu 339926690560SJia Liu return ((uint64_t)rs0 << 32) | (uint64_t)rt1; 340026690560SJia Liu } 340126690560SJia Liu #endif 340226690560SJia Liu 3403b53371edSJia Liu /** DSP Accumulator and DSPControl Access Sub-class insns **/ 3404b53371edSJia Liu target_ulong helper_extr_w(target_ulong ac, target_ulong shift, 3405b53371edSJia Liu CPUMIPSState *env) 3406b53371edSJia Liu { 3407b53371edSJia Liu int32_t tempI; 3408b53371edSJia Liu int64_t tempDL[2]; 3409b53371edSJia Liu 3410b53371edSJia Liu shift = shift & 0x0F; 3411b53371edSJia Liu 3412b53371edSJia Liu mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); 3413b53371edSJia Liu if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3414b53371edSJia Liu (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3415b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3416b53371edSJia Liu } 3417b53371edSJia Liu 3418b53371edSJia Liu tempI = (tempDL[0] >> 1) & MIPSDSP_LLO; 3419b53371edSJia Liu 3420b53371edSJia Liu tempDL[0] += 1; 3421b53371edSJia Liu if (tempDL[0] == 0) { 3422b53371edSJia Liu tempDL[1] += 1; 3423b53371edSJia Liu } 3424b53371edSJia Liu 3425b53371edSJia Liu if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) && 3426b53371edSJia Liu (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) { 3427b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3428b53371edSJia Liu } 3429b53371edSJia Liu 3430b53371edSJia Liu return (target_long)tempI; 3431b53371edSJia Liu } 3432b53371edSJia Liu 3433b53371edSJia Liu target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift, 3434b53371edSJia Liu CPUMIPSState *env) 3435b53371edSJia Liu { 3436b53371edSJia Liu int64_t tempDL[2]; 3437b53371edSJia Liu 3438b53371edSJia Liu shift = shift & 0x0F; 3439b53371edSJia Liu 3440b53371edSJia Liu mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); 3441b53371edSJia Liu if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3442b53371edSJia Liu (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3443b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3444b53371edSJia Liu } 3445b53371edSJia Liu 3446b53371edSJia Liu tempDL[0] += 1; 3447b53371edSJia Liu if (tempDL[0] == 0) { 3448b53371edSJia Liu tempDL[1] += 1; 3449b53371edSJia Liu } 3450b53371edSJia Liu 3451b53371edSJia Liu if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3452b53371edSJia Liu (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3453b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3454b53371edSJia Liu } 3455b53371edSJia Liu 3456b53371edSJia Liu return (target_long)(int32_t)(tempDL[0] >> 1); 3457b53371edSJia Liu } 3458b53371edSJia Liu 3459b53371edSJia Liu target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift, 3460b53371edSJia Liu CPUMIPSState *env) 3461b53371edSJia Liu { 3462b53371edSJia Liu int32_t tempI, temp64; 3463b53371edSJia Liu int64_t tempDL[2]; 3464b53371edSJia Liu 3465b53371edSJia Liu shift = shift & 0x0F; 3466b53371edSJia Liu 3467b53371edSJia Liu mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); 3468b53371edSJia Liu if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3469b53371edSJia Liu (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3470b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3471b53371edSJia Liu } 3472b53371edSJia Liu tempDL[0] += 1; 3473b53371edSJia Liu if (tempDL[0] == 0) { 3474b53371edSJia Liu tempDL[1] += 1; 3475b53371edSJia Liu } 3476b53371edSJia Liu tempI = tempDL[0] >> 1; 3477b53371edSJia Liu 3478b53371edSJia Liu if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3479b53371edSJia Liu (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3480b53371edSJia Liu temp64 = tempDL[1]; 3481b53371edSJia Liu if (temp64 == 0) { 3482b53371edSJia Liu tempI = 0x7FFFFFFF; 3483b53371edSJia Liu } else { 3484b53371edSJia Liu tempI = 0x80000000; 3485b53371edSJia Liu } 3486b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3487b53371edSJia Liu } 3488b53371edSJia Liu 3489b53371edSJia Liu return (target_long)tempI; 3490b53371edSJia Liu } 3491b53371edSJia Liu 3492b53371edSJia Liu #if defined(TARGET_MIPS64) 3493b53371edSJia Liu target_ulong helper_dextr_w(target_ulong ac, target_ulong shift, 3494b53371edSJia Liu CPUMIPSState *env) 3495b53371edSJia Liu { 3496b53371edSJia Liu uint64_t temp[3]; 3497b53371edSJia Liu 3498b53371edSJia Liu shift = shift & 0x3F; 3499b53371edSJia Liu 3500b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3501b53371edSJia Liu 3502b53371edSJia Liu return (int64_t)(int32_t)(temp[0] >> 1); 3503b53371edSJia Liu } 3504b53371edSJia Liu 3505b53371edSJia Liu target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift, 3506b53371edSJia Liu CPUMIPSState *env) 3507b53371edSJia Liu { 3508b53371edSJia Liu uint64_t temp[3]; 3509b53371edSJia Liu uint32_t temp128; 3510b53371edSJia Liu 3511b53371edSJia Liu shift = shift & 0x3F; 3512b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3513b53371edSJia Liu 3514b53371edSJia Liu temp[0] += 1; 3515b53371edSJia Liu if (temp[0] == 0) { 3516b53371edSJia Liu temp[1] += 1; 3517b53371edSJia Liu if (temp[1] == 0) { 3518b53371edSJia Liu temp[2] += 1; 3519b53371edSJia Liu } 3520b53371edSJia Liu } 3521b53371edSJia Liu 3522b53371edSJia Liu temp128 = temp[2] & 0x01; 3523b53371edSJia Liu 3524b53371edSJia Liu if ((temp128 != 0 || temp[1] != 0) && 3525b53371edSJia Liu (temp128 != 1 || temp[1] != ~0ull)) { 3526b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3527b53371edSJia Liu } 3528b53371edSJia Liu 3529b53371edSJia Liu return (int64_t)(int32_t)(temp[0] >> 1); 3530b53371edSJia Liu } 3531b53371edSJia Liu 3532b53371edSJia Liu target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift, 3533b53371edSJia Liu CPUMIPSState *env) 3534b53371edSJia Liu { 3535b53371edSJia Liu uint64_t temp[3]; 3536b53371edSJia Liu uint32_t temp128; 3537b53371edSJia Liu 3538b53371edSJia Liu shift = shift & 0x3F; 3539b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3540b53371edSJia Liu 3541b53371edSJia Liu temp[0] += 1; 3542b53371edSJia Liu if (temp[0] == 0) { 3543b53371edSJia Liu temp[1] += 1; 3544b53371edSJia Liu if (temp[1] == 0) { 3545b53371edSJia Liu temp[2] += 1; 3546b53371edSJia Liu } 3547b53371edSJia Liu } 3548b53371edSJia Liu 3549b53371edSJia Liu temp128 = temp[2] & 0x01; 3550b53371edSJia Liu 3551b53371edSJia Liu if ((temp128 != 0 || temp[1] != 0) && 3552b53371edSJia Liu (temp128 != 1 || temp[1] != ~0ull)) { 3553b53371edSJia Liu if (temp128 == 0) { 3554b53371edSJia Liu temp[0] = 0x0FFFFFFFF; 3555b53371edSJia Liu } else { 35561cfd981fSBlue Swirl temp[0] = 0x0100000000ULL; 3557b53371edSJia Liu } 3558b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3559b53371edSJia Liu } 3560b53371edSJia Liu 3561b53371edSJia Liu return (int64_t)(int32_t)(temp[0] >> 1); 3562b53371edSJia Liu } 3563b53371edSJia Liu 3564b53371edSJia Liu target_ulong helper_dextr_l(target_ulong ac, target_ulong shift, 3565b53371edSJia Liu CPUMIPSState *env) 3566b53371edSJia Liu { 3567b53371edSJia Liu uint64_t temp[3]; 3568b53371edSJia Liu target_ulong result; 3569b53371edSJia Liu 3570b53371edSJia Liu shift = shift & 0x3F; 3571b53371edSJia Liu 3572b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3573b53371edSJia Liu result = (temp[1] << 63) | (temp[0] >> 1); 3574b53371edSJia Liu 3575b53371edSJia Liu return result; 3576b53371edSJia Liu } 3577b53371edSJia Liu 3578b53371edSJia Liu target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, 3579b53371edSJia Liu CPUMIPSState *env) 3580b53371edSJia Liu { 3581b53371edSJia Liu uint64_t temp[3]; 3582b53371edSJia Liu uint32_t temp128; 3583b53371edSJia Liu target_ulong result; 3584b53371edSJia Liu 3585b53371edSJia Liu shift = shift & 0x3F; 3586b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3587b53371edSJia Liu 3588b53371edSJia Liu temp[0] += 1; 3589b53371edSJia Liu if (temp[0] == 0) { 3590b53371edSJia Liu temp[1] += 1; 3591b53371edSJia Liu if (temp[1] == 0) { 3592b53371edSJia Liu temp[2] += 1; 3593b53371edSJia Liu } 3594b53371edSJia Liu } 3595b53371edSJia Liu 3596b53371edSJia Liu temp128 = temp[2] & 0x01; 3597b53371edSJia Liu 3598b53371edSJia Liu if ((temp128 != 0 || temp[1] != 0) && 3599b53371edSJia Liu (temp128 != 1 || temp[1] != ~0ull)) { 3600b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3601b53371edSJia Liu } 3602b53371edSJia Liu 3603b53371edSJia Liu result = (temp[1] << 63) | (temp[0] >> 1); 3604b53371edSJia Liu 3605b53371edSJia Liu return result; 3606b53371edSJia Liu } 3607b53371edSJia Liu 3608b53371edSJia Liu target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, 3609b53371edSJia Liu CPUMIPSState *env) 3610b53371edSJia Liu { 3611b53371edSJia Liu uint64_t temp[3]; 3612b53371edSJia Liu uint32_t temp128; 3613b53371edSJia Liu target_ulong result; 3614b53371edSJia Liu 3615b53371edSJia Liu shift = shift & 0x3F; 3616b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3617b53371edSJia Liu 3618b53371edSJia Liu temp[0] += 1; 3619b53371edSJia Liu if (temp[0] == 0) { 3620b53371edSJia Liu temp[1] += 1; 3621b53371edSJia Liu if (temp[1] == 0) { 3622b53371edSJia Liu temp[2] += 1; 3623b53371edSJia Liu } 3624b53371edSJia Liu } 3625b53371edSJia Liu 3626b53371edSJia Liu temp128 = temp[2] & 0x01; 3627b53371edSJia Liu 3628b53371edSJia Liu if ((temp128 != 0 || temp[1] != 0) && 3629b53371edSJia Liu (temp128 != 1 || temp[1] != ~0ull)) { 3630b53371edSJia Liu if (temp128 == 0) { 3631b53371edSJia Liu temp[1] &= ~0x00ull - 1; 3632b53371edSJia Liu temp[0] |= ~0x00ull - 1; 3633b53371edSJia Liu } else { 3634b53371edSJia Liu temp[1] |= 0x01; 3635b53371edSJia Liu temp[0] &= 0x01; 3636b53371edSJia Liu } 3637b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3638b53371edSJia Liu } 3639b53371edSJia Liu result = (temp[1] << 63) | (temp[0] >> 1); 3640b53371edSJia Liu 3641b53371edSJia Liu return result; 3642b53371edSJia Liu } 3643b53371edSJia Liu #endif 3644b53371edSJia Liu 3645b53371edSJia Liu target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift, 3646b53371edSJia Liu CPUMIPSState *env) 3647b53371edSJia Liu { 3648b53371edSJia Liu int64_t temp; 3649b53371edSJia Liu 3650b53371edSJia Liu shift = shift & 0x0F; 3651b53371edSJia Liu 3652b53371edSJia Liu temp = mipsdsp_rashift_short_acc(ac, shift, env); 3653b53371edSJia Liu if (temp > (int64_t)0x7FFF) { 3654b53371edSJia Liu temp = 0x00007FFF; 3655b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 36561cfd981fSBlue Swirl } else if (temp < (int64_t)0xFFFFFFFFFFFF8000ULL) { 3657b53371edSJia Liu temp = 0xFFFF8000; 3658b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3659b53371edSJia Liu } 3660b53371edSJia Liu 3661b53371edSJia Liu return (target_long)(int32_t)(temp & 0xFFFFFFFF); 3662b53371edSJia Liu } 3663b53371edSJia Liu 3664b53371edSJia Liu 3665b53371edSJia Liu #if defined(TARGET_MIPS64) 3666b53371edSJia Liu target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift, 3667b53371edSJia Liu CPUMIPSState *env) 3668b53371edSJia Liu { 3669b53371edSJia Liu int64_t temp[2]; 3670b53371edSJia Liu uint32_t temp127; 3671b53371edSJia Liu 3672b53371edSJia Liu shift = shift & 0x1F; 3673b53371edSJia Liu 3674b53371edSJia Liu mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env); 3675b53371edSJia Liu 3676b53371edSJia Liu temp127 = (temp[1] >> 63) & 0x01; 3677b53371edSJia Liu 3678b53371edSJia Liu if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) { 3679b53371edSJia Liu temp[0] &= 0xFFFF0000; 3680b53371edSJia Liu temp[0] |= 0x00007FFF; 3681b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3682b53371edSJia Liu } else if ((temp127 == 1) && 3683b53371edSJia Liu (temp[1] < 0xFFFFFFFFFFFFFFFFll 3684b53371edSJia Liu || temp[0] < 0xFFFFFFFFFFFF1000ll)) { 3685b53371edSJia Liu temp[0] &= 0xFFFF0000; 3686b53371edSJia Liu temp[0] |= 0x00008000; 3687b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3688b53371edSJia Liu } 3689b53371edSJia Liu 3690b53371edSJia Liu return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO); 3691b53371edSJia Liu } 3692b53371edSJia Liu 3693b53371edSJia Liu #endif 3694b53371edSJia Liu 3695b53371edSJia Liu target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env) 3696b53371edSJia Liu { 3697b53371edSJia Liu int32_t start_pos; 3698b53371edSJia Liu int sub; 3699b53371edSJia Liu uint32_t temp; 3700b53371edSJia Liu uint64_t acc; 3701b53371edSJia Liu 3702b53371edSJia Liu size = size & 0x1F; 3703b53371edSJia Liu 3704b53371edSJia Liu temp = 0; 3705b53371edSJia Liu start_pos = get_DSPControl_pos(env); 3706b53371edSJia Liu sub = start_pos - (size + 1); 3707b53371edSJia Liu if (sub >= -1) { 3708b53371edSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | 3709b53371edSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); 3710b53371edSJia Liu temp = (acc >> (start_pos - size)) & 3711b53371edSJia Liu (((uint32_t)0x01 << (size + 1)) - 1); 3712b53371edSJia Liu set_DSPControl_efi(0, env); 3713b53371edSJia Liu } else { 3714b53371edSJia Liu set_DSPControl_efi(1, env); 3715b53371edSJia Liu } 3716b53371edSJia Liu 3717b53371edSJia Liu return (target_ulong)temp; 3718b53371edSJia Liu } 3719b53371edSJia Liu 3720b53371edSJia Liu target_ulong helper_extpdp(target_ulong ac, target_ulong size, 3721b53371edSJia Liu CPUMIPSState *env) 3722b53371edSJia Liu { 3723b53371edSJia Liu int32_t start_pos; 3724b53371edSJia Liu int sub; 3725b53371edSJia Liu uint32_t temp; 3726b53371edSJia Liu uint64_t acc; 3727b53371edSJia Liu 3728b53371edSJia Liu size = size & 0x1F; 3729b53371edSJia Liu temp = 0; 3730b53371edSJia Liu start_pos = get_DSPControl_pos(env); 3731b53371edSJia Liu sub = start_pos - (size + 1); 3732b53371edSJia Liu if (sub >= -1) { 3733b53371edSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | 3734b53371edSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); 3735b53371edSJia Liu temp = (acc >> (start_pos - size)) & 3736b53371edSJia Liu (((uint32_t)0x01 << (size + 1)) - 1); 3737b53371edSJia Liu 3738b53371edSJia Liu set_DSPControl_pos(start_pos - (size + 1), env); 3739b53371edSJia Liu set_DSPControl_efi(0, env); 3740b53371edSJia Liu } else { 3741b53371edSJia Liu set_DSPControl_efi(1, env); 3742b53371edSJia Liu } 3743b53371edSJia Liu 3744b53371edSJia Liu return (target_ulong)temp; 3745b53371edSJia Liu } 3746b53371edSJia Liu 3747b53371edSJia Liu 3748b53371edSJia Liu #if defined(TARGET_MIPS64) 3749b53371edSJia Liu target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env) 3750b53371edSJia Liu { 3751b53371edSJia Liu int start_pos; 3752b53371edSJia Liu int len; 3753b53371edSJia Liu int sub; 3754b53371edSJia Liu uint64_t tempB, tempA; 3755b53371edSJia Liu uint64_t temp; 3756b53371edSJia Liu 3757b53371edSJia Liu temp = 0; 3758b53371edSJia Liu 3759b53371edSJia Liu size = size & 0x3F; 3760b53371edSJia Liu start_pos = get_DSPControl_pos(env); 3761b53371edSJia Liu len = start_pos - size; 3762b53371edSJia Liu tempB = env->active_tc.HI[ac]; 3763b53371edSJia Liu tempA = env->active_tc.LO[ac]; 3764b53371edSJia Liu 3765b53371edSJia Liu sub = start_pos - (size + 1); 3766b53371edSJia Liu 3767b53371edSJia Liu if (sub >= -1) { 3768b53371edSJia Liu temp = (tempB << (64 - len)) | (tempA >> len); 3769b53371edSJia Liu temp = temp & ((0x01 << (size + 1)) - 1); 3770b53371edSJia Liu set_DSPControl_efi(0, env); 3771b53371edSJia Liu } else { 3772b53371edSJia Liu set_DSPControl_efi(1, env); 3773b53371edSJia Liu } 3774b53371edSJia Liu 3775b53371edSJia Liu return temp; 3776b53371edSJia Liu } 3777b53371edSJia Liu 3778b53371edSJia Liu target_ulong helper_dextpdp(target_ulong ac, target_ulong size, 3779b53371edSJia Liu CPUMIPSState *env) 3780b53371edSJia Liu { 3781b53371edSJia Liu int start_pos; 3782b53371edSJia Liu int len; 3783b53371edSJia Liu int sub; 3784b53371edSJia Liu uint64_t tempB, tempA; 3785b53371edSJia Liu uint64_t temp; 3786b53371edSJia Liu 3787b53371edSJia Liu temp = 0; 3788b53371edSJia Liu size = size & 0x3F; 3789b53371edSJia Liu start_pos = get_DSPControl_pos(env); 3790b53371edSJia Liu len = start_pos - size; 3791b53371edSJia Liu tempB = env->active_tc.HI[ac]; 3792b53371edSJia Liu tempA = env->active_tc.LO[ac]; 3793b53371edSJia Liu 3794b53371edSJia Liu sub = start_pos - (size + 1); 3795b53371edSJia Liu 3796b53371edSJia Liu if (sub >= -1) { 3797b53371edSJia Liu temp = (tempB << (64 - len)) | (tempA >> len); 3798b53371edSJia Liu temp = temp & ((0x01 << (size + 1)) - 1); 3799b53371edSJia Liu set_DSPControl_pos(sub, env); 3800b53371edSJia Liu set_DSPControl_efi(0, env); 3801b53371edSJia Liu } else { 3802b53371edSJia Liu set_DSPControl_efi(1, env); 3803b53371edSJia Liu } 3804b53371edSJia Liu 3805b53371edSJia Liu return temp; 3806b53371edSJia Liu } 3807b53371edSJia Liu 3808b53371edSJia Liu #endif 3809b53371edSJia Liu 3810b53371edSJia Liu void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env) 3811b53371edSJia Liu { 3812b53371edSJia Liu int8_t rs5_0; 3813b53371edSJia Liu uint64_t temp, acc; 3814b53371edSJia Liu 3815b53371edSJia Liu rs5_0 = rs & 0x3F; 3816b53371edSJia Liu rs5_0 = (int8_t)(rs5_0 << 2) >> 2; 3817b53371edSJia Liu rs5_0 = MIPSDSP_ABS(rs5_0); 3818b53371edSJia Liu acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) | 3819b53371edSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); 3820b53371edSJia Liu if (rs5_0 == 0) { 3821b53371edSJia Liu temp = acc; 3822b53371edSJia Liu } else { 3823b53371edSJia Liu if (rs5_0 > 0) { 3824b53371edSJia Liu temp = acc >> rs5_0; 3825b53371edSJia Liu } else { 3826b53371edSJia Liu temp = acc << rs5_0; 3827b53371edSJia Liu } 3828b53371edSJia Liu } 3829b53371edSJia Liu 3830b53371edSJia Liu env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32); 3831b53371edSJia Liu env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO); 3832b53371edSJia Liu } 3833b53371edSJia Liu 3834b53371edSJia Liu #if defined(TARGET_MIPS64) 3835b53371edSJia Liu void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env) 3836b53371edSJia Liu { 3837b53371edSJia Liu int8_t shift_t; 3838b53371edSJia Liu uint64_t tempB, tempA; 3839b53371edSJia Liu 3840b53371edSJia Liu shift_t = (int8_t)(shift << 1) >> 1; 3841b53371edSJia Liu 3842b53371edSJia Liu tempB = env->active_tc.HI[ac]; 3843b53371edSJia Liu tempA = env->active_tc.LO[ac]; 3844b53371edSJia Liu 3845b53371edSJia Liu if (shift_t != 0) { 3846b53371edSJia Liu if (shift_t >= 0) { 3847b53371edSJia Liu tempA = (tempB << (64 - shift_t)) | (tempA >> shift_t); 3848b53371edSJia Liu tempB = tempB >> shift_t; 3849b53371edSJia Liu } else { 3850b53371edSJia Liu shift_t = -shift_t; 3851b53371edSJia Liu tempB = (tempB << shift_t) | (tempA >> (64 - shift_t)); 3852b53371edSJia Liu tempA = tempA << shift_t; 3853b53371edSJia Liu } 3854b53371edSJia Liu } 3855b53371edSJia Liu 3856b53371edSJia Liu env->active_tc.HI[ac] = tempB; 3857b53371edSJia Liu env->active_tc.LO[ac] = tempA; 3858b53371edSJia Liu } 3859b53371edSJia Liu 3860b53371edSJia Liu #endif 3861b53371edSJia Liu void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env) 3862b53371edSJia Liu { 3863b53371edSJia Liu int32_t tempA, tempB, pos; 3864b53371edSJia Liu 3865b53371edSJia Liu tempA = rs; 3866b53371edSJia Liu tempB = env->active_tc.LO[ac]; 3867b53371edSJia Liu env->active_tc.HI[ac] = (target_long)tempB; 3868b53371edSJia Liu env->active_tc.LO[ac] = (target_long)tempA; 3869b53371edSJia Liu pos = get_DSPControl_pos(env); 3870b53371edSJia Liu 3871b53371edSJia Liu if (pos > 32) { 3872b53371edSJia Liu return; 3873b53371edSJia Liu } else { 3874b53371edSJia Liu set_DSPControl_pos(pos + 32, env); 3875b53371edSJia Liu } 3876b53371edSJia Liu } 3877b53371edSJia Liu 3878b53371edSJia Liu #if defined(TARGET_MIPS64) 3879b53371edSJia Liu void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env) 3880b53371edSJia Liu { 3881b53371edSJia Liu uint8_t ac_t; 3882b53371edSJia Liu uint8_t pos; 3883b53371edSJia Liu uint64_t tempB, tempA; 3884b53371edSJia Liu 3885b53371edSJia Liu ac_t = ac & 0x3; 3886b53371edSJia Liu 3887b53371edSJia Liu tempA = rs; 3888b53371edSJia Liu tempB = env->active_tc.LO[ac_t]; 3889b53371edSJia Liu 3890b53371edSJia Liu env->active_tc.HI[ac_t] = tempB; 3891b53371edSJia Liu env->active_tc.LO[ac_t] = tempA; 3892b53371edSJia Liu 3893b53371edSJia Liu pos = get_DSPControl_pos(env); 3894b53371edSJia Liu 3895b53371edSJia Liu if (pos <= 64) { 3896b53371edSJia Liu pos = pos + 64; 3897b53371edSJia Liu set_DSPControl_pos(pos, env); 3898b53371edSJia Liu } 3899b53371edSJia Liu } 3900b53371edSJia Liu #endif 3901b53371edSJia Liu 3902b53371edSJia Liu void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env) 3903b53371edSJia Liu { 3904b53371edSJia Liu uint8_t mask[6]; 3905b53371edSJia Liu uint8_t i; 3906b53371edSJia Liu uint32_t newbits, overwrite; 3907b53371edSJia Liu target_ulong dsp; 3908b53371edSJia Liu 3909b53371edSJia Liu newbits = 0x00; 3910b53371edSJia Liu overwrite = 0xFFFFFFFF; 3911b53371edSJia Liu dsp = env->active_tc.DSPControl; 3912b53371edSJia Liu 3913b53371edSJia Liu for (i = 0; i < 6; i++) { 3914b53371edSJia Liu mask[i] = (mask_num >> i) & 0x01; 3915b53371edSJia Liu } 3916b53371edSJia Liu 3917b53371edSJia Liu if (mask[0] == 1) { 3918b53371edSJia Liu #if defined(TARGET_MIPS64) 3919b53371edSJia Liu overwrite &= 0xFFFFFF80; 3920b53371edSJia Liu newbits &= 0xFFFFFF80; 3921b53371edSJia Liu newbits |= 0x0000007F & rs; 3922b53371edSJia Liu #else 3923b53371edSJia Liu overwrite &= 0xFFFFFFC0; 3924b53371edSJia Liu newbits &= 0xFFFFFFC0; 3925b53371edSJia Liu newbits |= 0x0000003F & rs; 3926b53371edSJia Liu #endif 3927b53371edSJia Liu } 3928b53371edSJia Liu 3929b53371edSJia Liu if (mask[1] == 1) { 3930b53371edSJia Liu overwrite &= 0xFFFFE07F; 3931b53371edSJia Liu newbits &= 0xFFFFE07F; 3932b53371edSJia Liu newbits |= 0x00001F80 & rs; 3933b53371edSJia Liu } 3934b53371edSJia Liu 3935b53371edSJia Liu if (mask[2] == 1) { 3936b53371edSJia Liu overwrite &= 0xFFFFDFFF; 3937b53371edSJia Liu newbits &= 0xFFFFDFFF; 3938b53371edSJia Liu newbits |= 0x00002000 & rs; 3939b53371edSJia Liu } 3940b53371edSJia Liu 3941b53371edSJia Liu if (mask[3] == 1) { 3942b53371edSJia Liu overwrite &= 0xFF00FFFF; 3943b53371edSJia Liu newbits &= 0xFF00FFFF; 3944b53371edSJia Liu newbits |= 0x00FF0000 & rs; 3945b53371edSJia Liu } 3946b53371edSJia Liu 3947b53371edSJia Liu if (mask[4] == 1) { 3948b53371edSJia Liu overwrite &= 0x00FFFFFF; 3949b53371edSJia Liu newbits &= 0x00FFFFFF; 3950b53371edSJia Liu newbits |= 0xFF000000 & rs; 3951b53371edSJia Liu } 3952b53371edSJia Liu 3953b53371edSJia Liu if (mask[5] == 1) { 3954b53371edSJia Liu overwrite &= 0xFFFFBFFF; 3955b53371edSJia Liu newbits &= 0xFFFFBFFF; 3956b53371edSJia Liu newbits |= 0x00004000 & rs; 3957b53371edSJia Liu } 3958b53371edSJia Liu 3959b53371edSJia Liu dsp = dsp & overwrite; 3960b53371edSJia Liu dsp = dsp | newbits; 3961b53371edSJia Liu env->active_tc.DSPControl = dsp; 3962b53371edSJia Liu } 3963b53371edSJia Liu 3964b53371edSJia Liu target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env) 3965b53371edSJia Liu { 3966b53371edSJia Liu uint8_t mask[6]; 3967b53371edSJia Liu uint32_t ruler, i; 3968b53371edSJia Liu target_ulong temp; 3969b53371edSJia Liu target_ulong dsp; 3970b53371edSJia Liu 3971b53371edSJia Liu ruler = 0x01; 3972b53371edSJia Liu for (i = 0; i < 6; i++) { 3973b53371edSJia Liu mask[i] = (masknum & ruler) >> i ; 3974b53371edSJia Liu ruler = ruler << 1; 3975b53371edSJia Liu } 3976b53371edSJia Liu 3977b53371edSJia Liu temp = 0x00; 3978b53371edSJia Liu dsp = env->active_tc.DSPControl; 3979b53371edSJia Liu 3980b53371edSJia Liu if (mask[0] == 1) { 3981b53371edSJia Liu #if defined(TARGET_MIPS64) 3982b53371edSJia Liu temp |= dsp & 0x7F; 3983b53371edSJia Liu #else 3984b53371edSJia Liu temp |= dsp & 0x3F; 3985b53371edSJia Liu #endif 3986b53371edSJia Liu } 3987b53371edSJia Liu 3988b53371edSJia Liu if (mask[1] == 1) { 3989b53371edSJia Liu temp |= dsp & 0x1F80; 3990b53371edSJia Liu } 3991b53371edSJia Liu 3992b53371edSJia Liu if (mask[2] == 1) { 3993b53371edSJia Liu temp |= dsp & 0x2000; 3994b53371edSJia Liu } 3995b53371edSJia Liu 3996b53371edSJia Liu if (mask[3] == 1) { 3997b53371edSJia Liu temp |= dsp & 0x00FF0000; 3998b53371edSJia Liu } 3999b53371edSJia Liu 4000b53371edSJia Liu if (mask[4] == 1) { 4001b53371edSJia Liu temp |= dsp & 0xFF000000; 4002b53371edSJia Liu } 4003b53371edSJia Liu 4004b53371edSJia Liu if (mask[5] == 1) { 4005b53371edSJia Liu temp |= dsp & 0x4000; 4006b53371edSJia Liu } 4007b53371edSJia Liu 4008b53371edSJia Liu return temp; 4009b53371edSJia Liu } 4010b53371edSJia Liu 4011b53371edSJia Liu 4012461c08dfSJia Liu #undef MIPSDSP_LHI 4013461c08dfSJia Liu #undef MIPSDSP_LLO 4014461c08dfSJia Liu #undef MIPSDSP_HI 4015461c08dfSJia Liu #undef MIPSDSP_LO 4016461c08dfSJia Liu #undef MIPSDSP_Q3 4017461c08dfSJia Liu #undef MIPSDSP_Q2 4018461c08dfSJia Liu #undef MIPSDSP_Q1 4019461c08dfSJia Liu #undef MIPSDSP_Q0 4020461c08dfSJia Liu 4021461c08dfSJia Liu #undef MIPSDSP_SPLIT32_8 4022461c08dfSJia Liu #undef MIPSDSP_SPLIT32_16 4023461c08dfSJia Liu 4024461c08dfSJia Liu #undef MIPSDSP_RETURN32 4025461c08dfSJia Liu #undef MIPSDSP_RETURN32_8 4026461c08dfSJia Liu #undef MIPSDSP_RETURN32_16 4027461c08dfSJia Liu 4028461c08dfSJia Liu #ifdef TARGET_MIPS64 4029461c08dfSJia Liu #undef MIPSDSP_SPLIT64_16 4030461c08dfSJia Liu #undef MIPSDSP_SPLIT64_32 4031461c08dfSJia Liu #undef MIPSDSP_RETURN64_16 4032461c08dfSJia Liu #undef MIPSDSP_RETURN64_32 4033461c08dfSJia Liu #endif 4034