1235eb015SJia Liu /* 2235eb015SJia Liu * MIPS ASE DSP Instruction emulation helpers for QEMU. 3235eb015SJia Liu * 4235eb015SJia Liu * Copyright (c) 2012 Jia Liu <proljc@gmail.com> 5fe65a1faSDongxue Zhang * Dongxue Zhang <elta.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 20c684822aSPeter Maydell #include "qemu/osdep.h" 21235eb015SJia Liu #include "cpu.h" 222ef6175aSRichard Henderson #include "exec/helper-proto.h" 230ba365f4SPetar Jovanovic #include "qemu/bitops.h" 24235eb015SJia Liu 25652613abSAurelien Jarno /* As the byte ordering doesn't matter, i.e. all columns are treated 26652613abSAurelien Jarno identically, these unions can be used directly. */ 27652613abSAurelien Jarno typedef union { 28652613abSAurelien Jarno uint8_t ub[4]; 29652613abSAurelien Jarno int8_t sb[4]; 30652613abSAurelien Jarno uint16_t uh[2]; 31652613abSAurelien Jarno int16_t sh[2]; 32652613abSAurelien Jarno uint32_t uw[1]; 33652613abSAurelien Jarno int32_t sw[1]; 34652613abSAurelien Jarno } DSP32Value; 35652613abSAurelien Jarno 36652613abSAurelien Jarno typedef union { 37652613abSAurelien Jarno uint8_t ub[8]; 38652613abSAurelien Jarno int8_t sb[8]; 39652613abSAurelien Jarno uint16_t uh[4]; 40652613abSAurelien Jarno int16_t sh[4]; 41652613abSAurelien Jarno uint32_t uw[2]; 42652613abSAurelien Jarno int32_t sw[2]; 43652613abSAurelien Jarno uint64_t ul[1]; 44652613abSAurelien Jarno int64_t sl[1]; 45652613abSAurelien Jarno } DSP64Value; 46652613abSAurelien Jarno 47235eb015SJia Liu /*** MIPS DSP internal functions begin ***/ 48*2a2be359SEric Blake #define MIPSDSP_ABS(x) (((x) >= 0) ? (x) : -(x)) 49*2a2be359SEric Blake #define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~((a) ^ (b)) & ((a) ^ (c)) & (d)) 50*2a2be359SEric Blake #define MIPSDSP_OVERFLOW_SUB(a, b, c, d) (((a) ^ (b)) & ((a) ^ (c)) & (d)) 51235eb015SJia Liu 52235eb015SJia Liu static inline void set_DSPControl_overflow_flag(uint32_t flag, int position, 53235eb015SJia Liu CPUMIPSState *env) 54235eb015SJia Liu { 55235eb015SJia Liu env->active_tc.DSPControl |= (target_ulong)flag << position; 56235eb015SJia Liu } 57235eb015SJia Liu 58118d1e4fSPetar Jovanovic static inline void set_DSPControl_carryflag(bool flag, CPUMIPSState *env) 59235eb015SJia Liu { 60118d1e4fSPetar Jovanovic env->active_tc.DSPControl &= ~(1 << 13); 61118d1e4fSPetar Jovanovic env->active_tc.DSPControl |= flag << 13; 62235eb015SJia Liu } 63235eb015SJia Liu 64235eb015SJia Liu static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env) 65235eb015SJia Liu { 66235eb015SJia Liu return (env->active_tc.DSPControl >> 13) & 0x01; 67235eb015SJia Liu } 68235eb015SJia Liu 69235eb015SJia Liu static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env) 70235eb015SJia Liu { 71235eb015SJia Liu uint32_t filter; 72235eb015SJia Liu 73235eb015SJia Liu filter = ((0x01 << len) - 1) << 24; 74235eb015SJia Liu filter = ~filter; 75235eb015SJia Liu 76235eb015SJia Liu env->active_tc.DSPControl &= filter; 77235eb015SJia Liu env->active_tc.DSPControl |= (target_ulong)flag << 24; 78235eb015SJia Liu } 79235eb015SJia Liu 80235eb015SJia Liu static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env) 81235eb015SJia Liu { 82235eb015SJia Liu target_ulong dspc; 83235eb015SJia Liu 84235eb015SJia Liu dspc = env->active_tc.DSPControl; 85235eb015SJia Liu #ifndef TARGET_MIPS64 86235eb015SJia Liu dspc = dspc & 0xFFFFFFC0; 870ba365f4SPetar Jovanovic dspc |= (pos & 0x3F); 88235eb015SJia Liu #else 89235eb015SJia Liu dspc = dspc & 0xFFFFFF80; 900ba365f4SPetar Jovanovic dspc |= (pos & 0x7F); 91235eb015SJia Liu #endif 92235eb015SJia Liu env->active_tc.DSPControl = dspc; 93235eb015SJia Liu } 94235eb015SJia Liu 95235eb015SJia Liu static inline uint32_t get_DSPControl_pos(CPUMIPSState *env) 96235eb015SJia Liu { 97235eb015SJia Liu target_ulong dspc; 98235eb015SJia Liu uint32_t pos; 99235eb015SJia Liu 100235eb015SJia Liu dspc = env->active_tc.DSPControl; 101235eb015SJia Liu 102235eb015SJia Liu #ifndef TARGET_MIPS64 103235eb015SJia Liu pos = dspc & 0x3F; 104235eb015SJia Liu #else 105235eb015SJia Liu pos = dspc & 0x7F; 106235eb015SJia Liu #endif 107235eb015SJia Liu 108235eb015SJia Liu return pos; 109235eb015SJia Liu } 110235eb015SJia Liu 111235eb015SJia Liu static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env) 112235eb015SJia Liu { 113235eb015SJia Liu env->active_tc.DSPControl &= 0xFFFFBFFF; 114235eb015SJia Liu env->active_tc.DSPControl |= (target_ulong)flag << 14; 115235eb015SJia Liu } 116235eb015SJia Liu 117235eb015SJia Liu #define DO_MIPS_SAT_ABS(size) \ 118235eb015SJia Liu static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a, \ 119235eb015SJia Liu CPUMIPSState *env) \ 120235eb015SJia Liu { \ 121235eb015SJia Liu if (a == INT##size##_MIN) { \ 122235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); \ 123235eb015SJia Liu return INT##size##_MAX; \ 124235eb015SJia Liu } else { \ 125235eb015SJia Liu return MIPSDSP_ABS(a); \ 126235eb015SJia Liu } \ 127235eb015SJia Liu } 128235eb015SJia Liu DO_MIPS_SAT_ABS(8) 129235eb015SJia Liu DO_MIPS_SAT_ABS(16) 130235eb015SJia Liu DO_MIPS_SAT_ABS(32) 131235eb015SJia Liu #undef DO_MIPS_SAT_ABS 132235eb015SJia Liu 133235eb015SJia Liu /* get sum value */ 134235eb015SJia Liu static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env) 135235eb015SJia Liu { 136235eb015SJia Liu int16_t tempI; 137235eb015SJia Liu 138235eb015SJia Liu tempI = a + b; 139235eb015SJia Liu 14020c334a7SPetar Jovanovic if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x8000)) { 141235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 142235eb015SJia Liu } 143235eb015SJia Liu 144235eb015SJia Liu return tempI; 145235eb015SJia Liu } 146235eb015SJia Liu 147235eb015SJia Liu static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b, 148235eb015SJia Liu CPUMIPSState *env) 149235eb015SJia Liu { 150235eb015SJia Liu int16_t tempS; 151235eb015SJia Liu 152235eb015SJia Liu tempS = a + b; 153235eb015SJia Liu 15420c334a7SPetar Jovanovic if (MIPSDSP_OVERFLOW_ADD(a, b, tempS, 0x8000)) { 155235eb015SJia Liu if (a > 0) { 156235eb015SJia Liu tempS = 0x7FFF; 157235eb015SJia Liu } else { 158235eb015SJia Liu tempS = 0x8000; 159235eb015SJia Liu } 160235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 161235eb015SJia Liu } 162235eb015SJia Liu 163235eb015SJia Liu return tempS; 164235eb015SJia Liu } 165235eb015SJia Liu 166235eb015SJia Liu static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b, 167235eb015SJia Liu CPUMIPSState *env) 168235eb015SJia Liu { 169235eb015SJia Liu int32_t tempI; 170235eb015SJia Liu 171235eb015SJia Liu tempI = a + b; 172235eb015SJia Liu 17320c334a7SPetar Jovanovic if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x80000000)) { 174235eb015SJia Liu if (a > 0) { 175235eb015SJia Liu tempI = 0x7FFFFFFF; 176235eb015SJia Liu } else { 177235eb015SJia Liu tempI = 0x80000000; 178235eb015SJia Liu } 179235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 180235eb015SJia Liu } 181235eb015SJia Liu 182235eb015SJia Liu return tempI; 183235eb015SJia Liu } 184235eb015SJia Liu 185235eb015SJia Liu static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env) 186235eb015SJia Liu { 187235eb015SJia Liu uint16_t temp; 188235eb015SJia Liu 189235eb015SJia Liu temp = (uint16_t)a + (uint16_t)b; 190235eb015SJia Liu 191235eb015SJia Liu if (temp & 0x0100) { 192235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 193235eb015SJia Liu } 194235eb015SJia Liu 195235eb015SJia Liu return temp & 0xFF; 196235eb015SJia Liu } 197235eb015SJia Liu 198235eb015SJia Liu static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b, 199235eb015SJia Liu CPUMIPSState *env) 200235eb015SJia Liu { 201235eb015SJia Liu uint32_t temp; 202235eb015SJia Liu 203235eb015SJia Liu temp = (uint32_t)a + (uint32_t)b; 204235eb015SJia Liu 205235eb015SJia Liu if (temp & 0x00010000) { 206235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 207235eb015SJia Liu } 208235eb015SJia Liu 209235eb015SJia Liu return temp & 0xFFFF; 210235eb015SJia Liu } 211235eb015SJia Liu 212235eb015SJia Liu static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b, 213235eb015SJia Liu CPUMIPSState *env) 214235eb015SJia Liu { 215235eb015SJia Liu uint8_t result; 216235eb015SJia Liu uint16_t temp; 217235eb015SJia Liu 218235eb015SJia Liu temp = (uint16_t)a + (uint16_t)b; 219235eb015SJia Liu result = temp & 0xFF; 220235eb015SJia Liu 221235eb015SJia Liu if (0x0100 & temp) { 222235eb015SJia Liu result = 0xFF; 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 uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b, 230235eb015SJia Liu CPUMIPSState *env) 231235eb015SJia Liu { 232235eb015SJia Liu uint16_t result; 233235eb015SJia Liu uint32_t temp; 234235eb015SJia Liu 235235eb015SJia Liu temp = (uint32_t)a + (uint32_t)b; 236235eb015SJia Liu result = temp & 0xFFFF; 237235eb015SJia Liu 238235eb015SJia Liu if (0x00010000 & temp) { 239235eb015SJia Liu result = 0xFFFF; 240235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 241235eb015SJia Liu } 242235eb015SJia Liu 243235eb015SJia Liu return result; 244235eb015SJia Liu } 245235eb015SJia Liu 246235eb015SJia Liu static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a, 247235eb015SJia Liu CPUMIPSState *env) 248235eb015SJia Liu { 249235eb015SJia Liu int64_t temp; 250235eb015SJia Liu int32_t temp32, temp31, result; 251235eb015SJia Liu int64_t temp_sum; 252235eb015SJia Liu 253235eb015SJia Liu #ifndef TARGET_MIPS64 254235eb015SJia Liu temp = ((uint64_t)env->active_tc.HI[acc] << 32) | 255235eb015SJia Liu (uint64_t)env->active_tc.LO[acc]; 256235eb015SJia Liu #else 257235eb015SJia Liu temp = (uint64_t)env->active_tc.LO[acc]; 258235eb015SJia Liu #endif 259235eb015SJia Liu 260235eb015SJia Liu temp_sum = (int64_t)a + temp; 261235eb015SJia Liu 262235eb015SJia Liu temp32 = (temp_sum >> 32) & 0x01; 263235eb015SJia Liu temp31 = (temp_sum >> 31) & 0x01; 264235eb015SJia Liu result = temp_sum & 0xFFFFFFFF; 265235eb015SJia Liu 266235eb015SJia Liu if (temp32 != temp31) { 267235eb015SJia Liu if (temp32 == 0) { 268235eb015SJia Liu result = 0x7FFFFFFF; 269235eb015SJia Liu } else { 270235eb015SJia Liu result = 0x80000000; 271235eb015SJia Liu } 272235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + acc, env); 273235eb015SJia Liu } 274235eb015SJia Liu 275235eb015SJia Liu return result; 276235eb015SJia Liu } 277235eb015SJia Liu 27831efecccSPeter Maydell #ifdef TARGET_MIPS64 279235eb015SJia Liu /* a[0] is LO, a[1] is HI. */ 280235eb015SJia Liu static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret, 281235eb015SJia Liu int32_t ac, 282235eb015SJia Liu int64_t *a, 283235eb015SJia Liu CPUMIPSState *env) 284235eb015SJia Liu { 285235eb015SJia Liu bool temp64; 286235eb015SJia Liu 287235eb015SJia Liu ret[0] = env->active_tc.LO[ac] + a[0]; 288235eb015SJia Liu ret[1] = env->active_tc.HI[ac] + a[1]; 289235eb015SJia Liu 290235eb015SJia Liu if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) && 291235eb015SJia Liu ((uint64_t)ret[0] < (uint64_t)a[0])) { 292235eb015SJia Liu ret[1] += 1; 293235eb015SJia Liu } 294235eb015SJia Liu temp64 = ret[1] & 1; 295235eb015SJia Liu if (temp64 != ((ret[0] >> 63) & 0x01)) { 296235eb015SJia Liu if (temp64) { 297235eb015SJia Liu ret[0] = (0x01ull << 63); 298235eb015SJia Liu ret[1] = ~0ull; 299235eb015SJia Liu } else { 300235eb015SJia Liu ret[0] = (0x01ull << 63) - 1; 301235eb015SJia Liu ret[1] = 0x00; 302235eb015SJia Liu } 303235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); 304235eb015SJia Liu } 305235eb015SJia Liu } 306235eb015SJia Liu 307235eb015SJia Liu static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret, 308235eb015SJia Liu int32_t ac, 309235eb015SJia Liu int64_t *a, 310235eb015SJia Liu CPUMIPSState *env) 311235eb015SJia Liu { 312235eb015SJia Liu bool temp64; 313235eb015SJia Liu 314235eb015SJia Liu ret[0] = env->active_tc.LO[ac] - a[0]; 315235eb015SJia Liu ret[1] = env->active_tc.HI[ac] - a[1]; 316235eb015SJia Liu 317235eb015SJia Liu if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) { 318235eb015SJia Liu ret[1] -= 1; 319235eb015SJia Liu } 320235eb015SJia Liu temp64 = ret[1] & 1; 321235eb015SJia Liu if (temp64 != ((ret[0] >> 63) & 0x01)) { 322235eb015SJia Liu if (temp64) { 323235eb015SJia Liu ret[0] = (0x01ull << 63); 324235eb015SJia Liu ret[1] = ~0ull; 325235eb015SJia Liu } else { 326235eb015SJia Liu ret[0] = (0x01ull << 63) - 1; 327235eb015SJia Liu ret[1] = 0x00; 328235eb015SJia Liu } 329235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); 330235eb015SJia Liu } 331235eb015SJia Liu } 33231efecccSPeter Maydell #endif 333235eb015SJia Liu 334235eb015SJia Liu static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b, 335235eb015SJia Liu CPUMIPSState *env) 336235eb015SJia Liu { 337235eb015SJia Liu int32_t temp; 338235eb015SJia Liu 339235eb015SJia Liu temp = (int32_t)a * (int32_t)b; 340235eb015SJia Liu 341235eb015SJia Liu if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) { 342235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 343235eb015SJia Liu } 344235eb015SJia Liu temp &= 0x0000FFFF; 345235eb015SJia Liu 346235eb015SJia Liu return temp; 347235eb015SJia Liu } 348235eb015SJia Liu 349235eb015SJia Liu static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b) 350235eb015SJia Liu { 351235eb015SJia Liu return a * b; 352235eb015SJia Liu } 353235eb015SJia Liu 35431efecccSPeter Maydell #ifdef TARGET_MIPS64 355235eb015SJia Liu static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b) 356235eb015SJia Liu { 357235eb015SJia Liu return a * b; 358235eb015SJia Liu } 35931efecccSPeter Maydell #endif 360235eb015SJia Liu 361235eb015SJia Liu static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b, 362235eb015SJia Liu CPUMIPSState *env) 363235eb015SJia Liu { 364235eb015SJia Liu int32_t temp; 365235eb015SJia Liu 366235eb015SJia Liu temp = (int32_t)a * (int32_t)b; 367235eb015SJia Liu 368235eb015SJia Liu if (temp > (int)0x7FFF) { 369235eb015SJia Liu temp = 0x00007FFF; 370235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 371235eb015SJia Liu } else if (temp < (int)0xffff8000) { 372235eb015SJia Liu temp = 0xFFFF8000; 373235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 374235eb015SJia Liu } 375235eb015SJia Liu temp &= 0x0000FFFF; 376235eb015SJia Liu 377235eb015SJia Liu return temp; 378235eb015SJia Liu } 379235eb015SJia Liu 380235eb015SJia Liu static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b, 381235eb015SJia Liu CPUMIPSState *env) 382235eb015SJia Liu { 383235eb015SJia Liu int32_t temp; 384235eb015SJia Liu 385235eb015SJia Liu if ((a == 0x8000) && (b == 0x8000)) { 386235eb015SJia Liu temp = 0x7FFFFFFF; 387235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 388235eb015SJia Liu } else { 3894877866eSPetar Jovanovic temp = ((int16_t)a * (int16_t)b) << 1; 390235eb015SJia Liu } 391235eb015SJia Liu 392235eb015SJia Liu return temp; 393235eb015SJia Liu } 394235eb015SJia Liu 395235eb015SJia Liu /* right shift */ 396235eb015SJia Liu static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov) 397235eb015SJia Liu { 398235eb015SJia Liu return a >> mov; 399235eb015SJia Liu } 400235eb015SJia Liu 401235eb015SJia Liu static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov) 402235eb015SJia Liu { 403235eb015SJia Liu return a >> mov; 404235eb015SJia Liu } 405235eb015SJia Liu 406235eb015SJia Liu static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov) 407235eb015SJia Liu { 408235eb015SJia Liu return a >> mov; 409235eb015SJia Liu } 410235eb015SJia Liu 411235eb015SJia Liu static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov) 412235eb015SJia Liu { 413235eb015SJia Liu return a >> mov; 414235eb015SJia Liu } 415235eb015SJia Liu 41631efecccSPeter Maydell #ifdef TARGET_MIPS64 417235eb015SJia Liu static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov) 418235eb015SJia Liu { 419235eb015SJia Liu return a >> mov; 420235eb015SJia Liu } 42131efecccSPeter Maydell #endif 422235eb015SJia Liu 423235eb015SJia Liu static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b) 424235eb015SJia Liu { 425235eb015SJia Liu int32_t temp; 426235eb015SJia Liu 427235eb015SJia Liu temp = (int32_t)a + (int32_t)b; 428235eb015SJia Liu 429235eb015SJia Liu return (temp >> 1) & 0xFFFF; 430235eb015SJia Liu } 431235eb015SJia Liu 432235eb015SJia Liu /* round right shift */ 433235eb015SJia Liu static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b) 434235eb015SJia Liu { 435235eb015SJia Liu int32_t temp; 436235eb015SJia Liu 437235eb015SJia Liu temp = (int32_t)a + (int32_t)b; 438235eb015SJia Liu temp += 1; 439235eb015SJia Liu 440235eb015SJia Liu return (temp >> 1) & 0xFFFF; 441235eb015SJia Liu } 442235eb015SJia Liu 443235eb015SJia Liu static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b) 444235eb015SJia Liu { 445235eb015SJia Liu int64_t temp; 446235eb015SJia Liu 447235eb015SJia Liu temp = (int64_t)a + (int64_t)b; 448235eb015SJia Liu 449235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFF; 450235eb015SJia Liu } 451235eb015SJia Liu 452235eb015SJia Liu static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b) 453235eb015SJia Liu { 454235eb015SJia Liu int64_t temp; 455235eb015SJia Liu 456235eb015SJia Liu temp = (int64_t)a + (int64_t)b; 457235eb015SJia Liu temp += 1; 458235eb015SJia Liu 459235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFF; 460235eb015SJia Liu } 461235eb015SJia Liu 462235eb015SJia Liu static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b) 463235eb015SJia Liu { 464235eb015SJia Liu uint16_t temp; 465235eb015SJia Liu 466235eb015SJia Liu temp = (uint16_t)a + (uint16_t)b; 467235eb015SJia Liu 468235eb015SJia Liu return (temp >> 1) & 0x00FF; 469235eb015SJia Liu } 470235eb015SJia Liu 471235eb015SJia Liu static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b) 472235eb015SJia Liu { 473235eb015SJia Liu uint16_t temp; 474235eb015SJia Liu 475235eb015SJia Liu temp = (uint16_t)a + (uint16_t)b + 1; 476235eb015SJia Liu 477235eb015SJia Liu return (temp >> 1) & 0x00FF; 478235eb015SJia Liu } 479235eb015SJia Liu 48031efecccSPeter Maydell #ifdef TARGET_MIPS64 481235eb015SJia Liu static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b) 482235eb015SJia Liu { 483235eb015SJia Liu uint16_t temp; 484235eb015SJia Liu 485235eb015SJia Liu temp = (uint16_t)a - (uint16_t)b; 486235eb015SJia Liu 487235eb015SJia Liu return (temp >> 1) & 0x00FF; 488235eb015SJia Liu } 489235eb015SJia Liu 490235eb015SJia Liu static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b) 491235eb015SJia Liu { 492235eb015SJia Liu uint16_t temp; 493235eb015SJia Liu 494235eb015SJia Liu temp = (uint16_t)a - (uint16_t)b + 1; 495235eb015SJia Liu 496235eb015SJia Liu return (temp >> 1) & 0x00FF; 497235eb015SJia Liu } 49831efecccSPeter Maydell #endif 499235eb015SJia Liu 500235eb015SJia Liu /* 128 bits long. p[0] is LO, p[1] is HI. */ 501235eb015SJia Liu static inline void mipsdsp_rndrashift_short_acc(int64_t *p, 502235eb015SJia Liu int32_t ac, 503235eb015SJia Liu int32_t shift, 504235eb015SJia Liu CPUMIPSState *env) 505235eb015SJia Liu { 506235eb015SJia Liu int64_t acc; 507235eb015SJia Liu 508235eb015SJia Liu acc = ((int64_t)env->active_tc.HI[ac] << 32) | 509235eb015SJia Liu ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); 5108b758d05SPetar Jovanovic p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1)); 511235eb015SJia Liu p[1] = (acc >> 63) & 0x01; 512235eb015SJia Liu } 513235eb015SJia Liu 51431efecccSPeter Maydell #ifdef TARGET_MIPS64 515235eb015SJia Liu /* 128 bits long. p[0] is LO, p[1] is HI */ 516235eb015SJia Liu static inline void mipsdsp_rashift_acc(uint64_t *p, 517235eb015SJia Liu uint32_t ac, 518235eb015SJia Liu uint32_t shift, 519235eb015SJia Liu CPUMIPSState *env) 520235eb015SJia Liu { 521235eb015SJia Liu uint64_t tempB, tempA; 522235eb015SJia Liu 523235eb015SJia Liu tempB = env->active_tc.HI[ac]; 524235eb015SJia Liu tempA = env->active_tc.LO[ac]; 525235eb015SJia Liu shift = shift & 0x1F; 526235eb015SJia Liu 527235eb015SJia Liu if (shift == 0) { 528235eb015SJia Liu p[1] = tempB; 529235eb015SJia Liu p[0] = tempA; 530235eb015SJia Liu } else { 531235eb015SJia Liu p[0] = (tempB << (64 - shift)) | (tempA >> shift); 532235eb015SJia Liu p[1] = (int64_t)tempB >> shift; 533235eb015SJia Liu } 534235eb015SJia Liu } 535235eb015SJia Liu 536235eb015SJia Liu /* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/ 537235eb015SJia Liu static inline void mipsdsp_rndrashift_acc(uint64_t *p, 538235eb015SJia Liu uint32_t ac, 539235eb015SJia Liu uint32_t shift, 540235eb015SJia Liu CPUMIPSState *env) 541235eb015SJia Liu { 542235eb015SJia Liu int64_t tempB, tempA; 543235eb015SJia Liu 544235eb015SJia Liu tempB = env->active_tc.HI[ac]; 545235eb015SJia Liu tempA = env->active_tc.LO[ac]; 546235eb015SJia Liu shift = shift & 0x3F; 547235eb015SJia Liu 548235eb015SJia Liu if (shift == 0) { 549235eb015SJia Liu p[2] = tempB >> 63; 550235eb015SJia Liu p[1] = (tempB << 1) | (tempA >> 63); 551235eb015SJia Liu p[0] = tempA << 1; 552235eb015SJia Liu } else { 553235eb015SJia Liu p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1)); 554235eb015SJia Liu p[1] = (int64_t)tempB >> (shift - 1); 555235eb015SJia Liu if (tempB >= 0) { 556235eb015SJia Liu p[2] = 0x0; 557235eb015SJia Liu } else { 558235eb015SJia Liu p[2] = ~0ull; 559235eb015SJia Liu } 560235eb015SJia Liu } 561235eb015SJia Liu } 56231efecccSPeter Maydell #endif 563235eb015SJia Liu 564235eb015SJia Liu static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b, 565235eb015SJia Liu CPUMIPSState *env) 566235eb015SJia Liu { 567235eb015SJia Liu int32_t temp; 568235eb015SJia Liu 569235eb015SJia Liu if ((a == 0x8000) && (b == 0x8000)) { 570235eb015SJia Liu temp = 0x7FFFFFFF; 571235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); 572235eb015SJia Liu } else { 573b1ca31d7SPetar Jovanovic temp = ((int16_t)a * (int16_t)b) << 1; 574235eb015SJia Liu } 575235eb015SJia Liu 576235eb015SJia Liu return temp; 577235eb015SJia Liu } 578235eb015SJia Liu 579235eb015SJia Liu static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b, 580235eb015SJia Liu CPUMIPSState *env) 581235eb015SJia Liu { 582235eb015SJia Liu uint64_t temp; 583235eb015SJia Liu 584235eb015SJia Liu if ((a == 0x80000000) && (b == 0x80000000)) { 585235eb015SJia Liu temp = (0x01ull << 63) - 1; 586235eb015SJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); 587235eb015SJia Liu } else { 588b6a9f468SPetar Jovanovic temp = ((int64_t)(int32_t)a * (int32_t)b) << 1; 589235eb015SJia Liu } 590235eb015SJia Liu 591235eb015SJia Liu return temp; 592235eb015SJia Liu } 593235eb015SJia Liu 594235eb015SJia Liu static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b) 595235eb015SJia Liu { 596235eb015SJia Liu return (uint16_t)a * (uint16_t)b; 597235eb015SJia Liu } 598235eb015SJia Liu 599235eb015SJia Liu static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b, 600235eb015SJia Liu CPUMIPSState *env) 601235eb015SJia Liu { 602235eb015SJia Liu uint32_t tempI; 603235eb015SJia Liu 604235eb015SJia Liu tempI = (uint32_t)a * (uint32_t)b; 605235eb015SJia Liu if (tempI > 0x0000FFFF) { 606235eb015SJia Liu tempI = 0x0000FFFF; 607235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 608235eb015SJia Liu } 609235eb015SJia Liu 610235eb015SJia Liu return tempI & 0x0000FFFF; 611235eb015SJia Liu } 612235eb015SJia Liu 61331efecccSPeter Maydell #ifdef TARGET_MIPS64 614235eb015SJia Liu static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b) 615235eb015SJia Liu { 616235eb015SJia Liu return (uint64_t)a * (uint64_t)b; 617235eb015SJia Liu } 61831efecccSPeter Maydell #endif 619235eb015SJia Liu 620235eb015SJia Liu static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b, 621235eb015SJia Liu CPUMIPSState *env) 622235eb015SJia Liu { 623235eb015SJia Liu uint32_t temp; 624235eb015SJia Liu 625235eb015SJia Liu if ((a == 0x8000) && (b == 0x8000)) { 626235eb015SJia Liu temp = 0x7FFF0000; 627235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 628235eb015SJia Liu } else { 6294877866eSPetar Jovanovic temp = ((int16_t)a * (int16_t)b) << 1; 630235eb015SJia Liu temp = temp + 0x00008000; 631235eb015SJia Liu } 632235eb015SJia Liu 633235eb015SJia Liu return (temp & 0xFFFF0000) >> 16; 634235eb015SJia Liu } 635235eb015SJia Liu 636235eb015SJia Liu static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b, 637235eb015SJia Liu CPUMIPSState *env) 638235eb015SJia Liu { 639235eb015SJia Liu int32_t temp; 640235eb015SJia Liu 641235eb015SJia Liu if ((a == 0x8000) && (b == 0x8000)) { 642235eb015SJia Liu temp = 0x7FFF0000; 643235eb015SJia Liu set_DSPControl_overflow_flag(1, 21, env); 644235eb015SJia Liu } else { 6459c19eb1eSPetar Jovanovic temp = (int16_t)a * (int16_t)b; 646235eb015SJia Liu temp = temp << 1; 647235eb015SJia Liu } 648235eb015SJia Liu 649235eb015SJia Liu return (temp >> 16) & 0x0000FFFF; 650235eb015SJia Liu } 651235eb015SJia Liu 652235eb015SJia Liu static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a, 653235eb015SJia Liu CPUMIPSState *env) 654235eb015SJia Liu { 655d36c231fSPetar Jovanovic uint16_t temp; 656235eb015SJia Liu 657235eb015SJia Liu 658d36c231fSPetar Jovanovic /* 659d36c231fSPetar Jovanovic * The value 0x00008000 will be added to the input Q31 value, and the code 660d36c231fSPetar Jovanovic * needs to check if the addition causes an overflow. Since a positive value 661d36c231fSPetar Jovanovic * is added, overflow can happen in one direction only. 662d36c231fSPetar Jovanovic */ 663d36c231fSPetar Jovanovic if (a > 0x7FFF7FFF) { 664d36c231fSPetar Jovanovic temp = 0x7FFF; 665235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 666d36c231fSPetar Jovanovic } else { 667d36c231fSPetar Jovanovic temp = ((a + 0x8000) >> 16) & 0xFFFF; 668235eb015SJia Liu } 669235eb015SJia Liu 670d36c231fSPetar Jovanovic return temp; 671235eb015SJia Liu } 672235eb015SJia Liu 673235eb015SJia Liu static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a, 674235eb015SJia Liu CPUMIPSState *env) 675235eb015SJia Liu { 676235eb015SJia Liu uint16_t mag; 677235eb015SJia Liu uint32_t sign; 678235eb015SJia Liu 679235eb015SJia Liu sign = (a >> 15) & 0x01; 680235eb015SJia Liu mag = a & 0x7FFF; 681235eb015SJia Liu 682235eb015SJia Liu if (sign == 0) { 683235eb015SJia Liu if (mag > 0x7F80) { 684235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 685235eb015SJia Liu return 0xFF; 686235eb015SJia Liu } else { 687235eb015SJia Liu return (mag >> 7) & 0xFFFF; 688235eb015SJia Liu } 689235eb015SJia Liu } else { 690235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 691235eb015SJia Liu return 0x00; 692235eb015SJia Liu } 693235eb015SJia Liu } 694235eb015SJia Liu 695235eb015SJia Liu static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env) 696235eb015SJia Liu { 697235eb015SJia Liu uint8_t discard; 698235eb015SJia Liu 69929851ee7SPetar Jovanovic if (s != 0) { 70029851ee7SPetar Jovanovic discard = a >> (8 - s); 701235eb015SJia Liu 702235eb015SJia Liu if (discard != 0x00) { 703235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 704235eb015SJia Liu } 705235eb015SJia Liu } 70629851ee7SPetar Jovanovic return a << s; 707235eb015SJia Liu } 708235eb015SJia Liu 709235eb015SJia Liu static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s, 710235eb015SJia Liu CPUMIPSState *env) 711235eb015SJia Liu { 712235eb015SJia Liu uint16_t discard; 713235eb015SJia Liu 71429851ee7SPetar Jovanovic if (s != 0) { 71529851ee7SPetar Jovanovic discard = (int16_t)a >> (15 - s); 716235eb015SJia Liu 717235eb015SJia Liu if ((discard != 0x0000) && (discard != 0xFFFF)) { 718235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 719235eb015SJia Liu } 720235eb015SJia Liu } 72129851ee7SPetar Jovanovic return a << s; 722235eb015SJia Liu } 723235eb015SJia Liu 72431efecccSPeter Maydell #ifdef TARGET_MIPS64 725235eb015SJia Liu static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s, 726235eb015SJia Liu CPUMIPSState *env) 727235eb015SJia Liu { 728235eb015SJia Liu uint32_t discard; 729235eb015SJia Liu 730235eb015SJia Liu if (s == 0) { 731235eb015SJia Liu return a; 732235eb015SJia Liu } else { 733235eb015SJia Liu discard = (int32_t)a >> (31 - (s - 1)); 734235eb015SJia Liu 735235eb015SJia Liu if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) { 736235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 737235eb015SJia Liu } 738235eb015SJia Liu return a << s; 739235eb015SJia Liu } 740235eb015SJia Liu } 74131efecccSPeter Maydell #endif 742235eb015SJia Liu 743235eb015SJia Liu static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s, 744235eb015SJia Liu CPUMIPSState *env) 745235eb015SJia Liu { 746235eb015SJia Liu uint8_t sign; 747235eb015SJia Liu uint16_t discard; 748235eb015SJia Liu 749235eb015SJia Liu if (s == 0) { 750235eb015SJia Liu return a; 751235eb015SJia Liu } else { 752235eb015SJia Liu sign = (a >> 15) & 0x01; 753235eb015SJia Liu if (sign != 0) { 754235eb015SJia Liu discard = (((0x01 << (16 - s)) - 1) << s) | 755235eb015SJia Liu ((a >> (14 - (s - 1))) & ((0x01 << s) - 1)); 756235eb015SJia Liu } else { 757235eb015SJia Liu discard = a >> (14 - (s - 1)); 758235eb015SJia Liu } 759235eb015SJia Liu 760235eb015SJia Liu if ((discard != 0x0000) && (discard != 0xFFFF)) { 761235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 762235eb015SJia Liu return (sign == 0) ? 0x7FFF : 0x8000; 763235eb015SJia Liu } else { 764235eb015SJia Liu return a << s; 765235eb015SJia Liu } 766235eb015SJia Liu } 767235eb015SJia Liu } 768235eb015SJia Liu 769235eb015SJia Liu static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s, 770235eb015SJia Liu CPUMIPSState *env) 771235eb015SJia Liu { 772235eb015SJia Liu uint8_t sign; 773235eb015SJia Liu uint32_t discard; 774235eb015SJia Liu 775235eb015SJia Liu if (s == 0) { 776235eb015SJia Liu return a; 777235eb015SJia Liu } else { 778235eb015SJia Liu sign = (a >> 31) & 0x01; 779235eb015SJia Liu if (sign != 0) { 780235eb015SJia Liu discard = (((0x01 << (32 - s)) - 1) << s) | 781235eb015SJia Liu ((a >> (30 - (s - 1))) & ((0x01 << s) - 1)); 782235eb015SJia Liu } else { 783235eb015SJia Liu discard = a >> (30 - (s - 1)); 784235eb015SJia Liu } 785235eb015SJia Liu 786235eb015SJia Liu if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) { 787235eb015SJia Liu set_DSPControl_overflow_flag(1, 22, env); 788235eb015SJia Liu return (sign == 0) ? 0x7FFFFFFF : 0x80000000; 789235eb015SJia Liu } else { 790235eb015SJia Liu return a << s; 791235eb015SJia Liu } 792235eb015SJia Liu } 793235eb015SJia Liu } 794235eb015SJia Liu 795235eb015SJia Liu static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s) 796235eb015SJia Liu { 797235eb015SJia Liu uint32_t temp; 798235eb015SJia Liu 799235eb015SJia Liu if (s == 0) { 800235eb015SJia Liu temp = (uint32_t)a << 1; 801235eb015SJia Liu } else { 802235eb015SJia Liu temp = (int32_t)(int8_t)a >> (s - 1); 803235eb015SJia Liu } 804235eb015SJia Liu 805235eb015SJia Liu return (temp + 1) >> 1; 806235eb015SJia Liu } 807235eb015SJia Liu 808235eb015SJia Liu static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s) 809235eb015SJia Liu { 810235eb015SJia Liu uint32_t temp; 811235eb015SJia Liu 812235eb015SJia Liu if (s == 0) { 813235eb015SJia Liu temp = (uint32_t)a << 1; 814235eb015SJia Liu } else { 815235eb015SJia Liu temp = (int32_t)(int16_t)a >> (s - 1); 816235eb015SJia Liu } 817235eb015SJia Liu 818235eb015SJia Liu return (temp + 1) >> 1; 819235eb015SJia Liu } 820235eb015SJia Liu 821235eb015SJia Liu static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s) 822235eb015SJia Liu { 823235eb015SJia Liu int64_t temp; 824235eb015SJia Liu 825235eb015SJia Liu if (s == 0) { 826235eb015SJia Liu temp = (uint64_t)a << 1; 827235eb015SJia Liu } else { 828235eb015SJia Liu temp = (int64_t)(int32_t)a >> (s - 1); 829235eb015SJia Liu } 830235eb015SJia Liu temp += 1; 831235eb015SJia Liu 832235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFFull; 833235eb015SJia Liu } 834235eb015SJia Liu 835235eb015SJia Liu static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env) 836235eb015SJia Liu { 837235eb015SJia Liu int16_t temp; 838235eb015SJia Liu 839235eb015SJia Liu temp = a - b; 84020c334a7SPetar Jovanovic if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) { 841235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 842235eb015SJia Liu } 843235eb015SJia Liu 844235eb015SJia Liu return temp; 845235eb015SJia Liu } 846235eb015SJia Liu 847235eb015SJia Liu static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b, 848235eb015SJia Liu CPUMIPSState *env) 849235eb015SJia Liu { 850235eb015SJia Liu int16_t temp; 851235eb015SJia Liu 852235eb015SJia Liu temp = a - b; 85320c334a7SPetar Jovanovic if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) { 85420c334a7SPetar Jovanovic if (a >= 0) { 855235eb015SJia Liu temp = 0x7FFF; 856235eb015SJia Liu } else { 857235eb015SJia Liu temp = 0x8000; 858235eb015SJia Liu } 859235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 860235eb015SJia Liu } 861235eb015SJia Liu 862235eb015SJia Liu return temp; 863235eb015SJia Liu } 864235eb015SJia Liu 865235eb015SJia Liu static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b, 866235eb015SJia Liu CPUMIPSState *env) 867235eb015SJia Liu { 868235eb015SJia Liu int32_t temp; 869235eb015SJia Liu 870235eb015SJia Liu temp = a - b; 87120c334a7SPetar Jovanovic if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) { 87220c334a7SPetar Jovanovic if (a >= 0) { 873235eb015SJia Liu temp = 0x7FFFFFFF; 874235eb015SJia Liu } else { 875235eb015SJia Liu temp = 0x80000000; 876235eb015SJia Liu } 877235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 878235eb015SJia Liu } 879235eb015SJia Liu 880235eb015SJia Liu return temp & 0xFFFFFFFFull; 881235eb015SJia Liu } 882235eb015SJia Liu 883235eb015SJia Liu static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b) 884235eb015SJia Liu { 885235eb015SJia Liu int32_t temp; 886235eb015SJia Liu 887235eb015SJia Liu temp = (int32_t)a - (int32_t)b; 888235eb015SJia Liu 889235eb015SJia Liu return (temp >> 1) & 0x0000FFFF; 890235eb015SJia Liu } 891235eb015SJia Liu 892235eb015SJia Liu static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b) 893235eb015SJia Liu { 894235eb015SJia Liu int32_t temp; 895235eb015SJia Liu 896235eb015SJia Liu temp = (int32_t)a - (int32_t)b; 897235eb015SJia Liu temp += 1; 898235eb015SJia Liu 899235eb015SJia Liu return (temp >> 1) & 0x0000FFFF; 900235eb015SJia Liu } 901235eb015SJia Liu 902235eb015SJia Liu static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b) 903235eb015SJia Liu { 904235eb015SJia Liu int64_t temp; 905235eb015SJia Liu 906235eb015SJia Liu temp = (int64_t)a - (int64_t)b; 907235eb015SJia Liu 908235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFFull; 909235eb015SJia Liu } 910235eb015SJia Liu 911235eb015SJia Liu static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b) 912235eb015SJia Liu { 913235eb015SJia Liu int64_t temp; 914235eb015SJia Liu 915235eb015SJia Liu temp = (int64_t)a - (int64_t)b; 916235eb015SJia Liu temp += 1; 917235eb015SJia Liu 918235eb015SJia Liu return (temp >> 1) & 0xFFFFFFFFull; 919235eb015SJia Liu } 920235eb015SJia Liu 921235eb015SJia Liu static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b, 922235eb015SJia Liu CPUMIPSState *env) 923235eb015SJia Liu { 924235eb015SJia Liu uint8_t temp16; 925235eb015SJia Liu uint32_t temp; 926235eb015SJia Liu 927235eb015SJia Liu temp = (uint32_t)a - (uint32_t)b; 928235eb015SJia Liu temp16 = (temp >> 16) & 0x01; 929235eb015SJia Liu if (temp16 == 1) { 930235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 931235eb015SJia Liu } 932235eb015SJia Liu return temp & 0x0000FFFF; 933235eb015SJia Liu } 934235eb015SJia Liu 935235eb015SJia Liu static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b, 936235eb015SJia Liu CPUMIPSState *env) 937235eb015SJia Liu { 938235eb015SJia Liu uint8_t temp16; 939235eb015SJia Liu uint32_t temp; 940235eb015SJia Liu 941235eb015SJia Liu temp = (uint32_t)a - (uint32_t)b; 942235eb015SJia Liu temp16 = (temp >> 16) & 0x01; 943235eb015SJia Liu 944235eb015SJia Liu if (temp16 == 1) { 945235eb015SJia Liu temp = 0x0000; 946235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 947235eb015SJia Liu } 948235eb015SJia Liu 949235eb015SJia Liu return temp & 0x0000FFFF; 950235eb015SJia Liu } 951235eb015SJia Liu 952235eb015SJia Liu static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env) 953235eb015SJia Liu { 954235eb015SJia Liu uint8_t temp8; 955235eb015SJia Liu uint16_t temp; 956235eb015SJia Liu 957235eb015SJia Liu temp = (uint16_t)a - (uint16_t)b; 958235eb015SJia Liu temp8 = (temp >> 8) & 0x01; 959235eb015SJia Liu if (temp8 == 1) { 960235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 961235eb015SJia Liu } 962235eb015SJia Liu 963235eb015SJia Liu return temp & 0x00FF; 964235eb015SJia Liu } 965235eb015SJia Liu 966235eb015SJia Liu static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env) 967235eb015SJia Liu { 968235eb015SJia Liu uint8_t temp8; 969235eb015SJia Liu uint16_t temp; 970235eb015SJia Liu 971235eb015SJia Liu temp = (uint16_t)a - (uint16_t)b; 972235eb015SJia Liu temp8 = (temp >> 8) & 0x01; 973235eb015SJia Liu if (temp8 == 1) { 974235eb015SJia Liu temp = 0x00; 975235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 976235eb015SJia Liu } 977235eb015SJia Liu 978235eb015SJia Liu return temp & 0x00FF; 979235eb015SJia Liu } 980235eb015SJia Liu 98131efecccSPeter Maydell #ifdef TARGET_MIPS64 982235eb015SJia Liu static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env) 983235eb015SJia Liu { 984235eb015SJia Liu int32_t temp; 985235eb015SJia Liu 986235eb015SJia Liu temp = a - b; 98720c334a7SPetar Jovanovic if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) { 988235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 989235eb015SJia Liu } 990235eb015SJia Liu 991235eb015SJia Liu return temp; 992235eb015SJia Liu } 993235eb015SJia Liu 994235eb015SJia Liu static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env) 995235eb015SJia Liu { 996235eb015SJia Liu int32_t temp; 997235eb015SJia Liu 998235eb015SJia Liu temp = a + b; 999235eb015SJia Liu 100020c334a7SPetar Jovanovic if (MIPSDSP_OVERFLOW_ADD(a, b, temp, 0x80000000)) { 1001235eb015SJia Liu set_DSPControl_overflow_flag(1, 20, env); 1002235eb015SJia Liu } 1003235eb015SJia Liu 1004235eb015SJia Liu return temp; 1005235eb015SJia Liu } 100631efecccSPeter Maydell #endif 1007235eb015SJia Liu 1008235eb015SJia Liu static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b) 1009235eb015SJia Liu { 1010235eb015SJia Liu return a == b; 1011235eb015SJia Liu } 1012235eb015SJia Liu 1013235eb015SJia Liu static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b) 1014235eb015SJia Liu { 1015235eb015SJia Liu return a <= b; 1016235eb015SJia Liu } 1017235eb015SJia Liu 1018235eb015SJia Liu static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b) 1019235eb015SJia Liu { 1020235eb015SJia Liu return a < b; 1021235eb015SJia Liu } 1022235eb015SJia Liu 1023235eb015SJia Liu static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b) 1024235eb015SJia Liu { 1025235eb015SJia Liu return a == b; 1026235eb015SJia Liu } 1027235eb015SJia Liu 1028235eb015SJia Liu static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b) 1029235eb015SJia Liu { 1030235eb015SJia Liu return a <= b; 1031235eb015SJia Liu } 1032235eb015SJia Liu 1033235eb015SJia Liu static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b) 1034235eb015SJia Liu { 1035235eb015SJia Liu return a < b; 1036235eb015SJia Liu } 1037235eb015SJia Liu /*** MIPS DSP internal functions end ***/ 1038461c08dfSJia Liu 1039461c08dfSJia Liu #define MIPSDSP_LHI 0xFFFFFFFF00000000ull 1040461c08dfSJia Liu #define MIPSDSP_LLO 0x00000000FFFFFFFFull 1041461c08dfSJia Liu #define MIPSDSP_HI 0xFFFF0000 1042461c08dfSJia Liu #define MIPSDSP_LO 0x0000FFFF 1043461c08dfSJia Liu #define MIPSDSP_Q3 0xFF000000 1044461c08dfSJia Liu #define MIPSDSP_Q2 0x00FF0000 1045461c08dfSJia Liu #define MIPSDSP_Q1 0x0000FF00 1046461c08dfSJia Liu #define MIPSDSP_Q0 0x000000FF 1047461c08dfSJia Liu 1048461c08dfSJia Liu #define MIPSDSP_SPLIT32_8(num, a, b, c, d) \ 1049461c08dfSJia Liu do { \ 1050*2a2be359SEric Blake a = ((num) >> 24) & MIPSDSP_Q0; \ 1051*2a2be359SEric Blake b = ((num) >> 16) & MIPSDSP_Q0; \ 1052*2a2be359SEric Blake c = ((num) >> 8) & MIPSDSP_Q0; \ 1053*2a2be359SEric Blake d = (num) & MIPSDSP_Q0; \ 1054461c08dfSJia Liu } while (0) 1055461c08dfSJia Liu 1056461c08dfSJia Liu #define MIPSDSP_SPLIT32_16(num, a, b) \ 1057461c08dfSJia Liu do { \ 1058*2a2be359SEric Blake a = ((num) >> 16) & MIPSDSP_LO; \ 1059*2a2be359SEric Blake b = (num) & MIPSDSP_LO; \ 1060461c08dfSJia Liu } while (0) 1061461c08dfSJia Liu 1062461c08dfSJia Liu #define MIPSDSP_RETURN32_8(a, b, c, d) ((target_long)(int32_t) \ 1063*2a2be359SEric Blake (((uint32_t)(a) << 24) | \ 1064*2a2be359SEric Blake ((uint32_t)(b) << 16) | \ 1065*2a2be359SEric Blake ((uint32_t)(c) << 8) | \ 1066*2a2be359SEric Blake ((uint32_t)(d) & 0xFF))) 1067461c08dfSJia Liu #define MIPSDSP_RETURN32_16(a, b) ((target_long)(int32_t) \ 1068*2a2be359SEric Blake (((uint32_t)(a) << 16) | \ 1069*2a2be359SEric Blake ((uint32_t)(b) & 0xFFFF))) 1070461c08dfSJia Liu 1071461c08dfSJia Liu #ifdef TARGET_MIPS64 1072461c08dfSJia Liu #define MIPSDSP_SPLIT64_16(num, a, b, c, d) \ 1073461c08dfSJia Liu do { \ 1074*2a2be359SEric Blake a = ((num) >> 48) & MIPSDSP_LO; \ 1075*2a2be359SEric Blake b = ((num) >> 32) & MIPSDSP_LO; \ 1076*2a2be359SEric Blake c = ((num) >> 16) & MIPSDSP_LO; \ 1077*2a2be359SEric Blake d = (num) & MIPSDSP_LO; \ 1078461c08dfSJia Liu } while (0) 1079461c08dfSJia Liu 1080461c08dfSJia Liu #define MIPSDSP_SPLIT64_32(num, a, b) \ 1081461c08dfSJia Liu do { \ 1082*2a2be359SEric Blake a = ((num) >> 32) & MIPSDSP_LLO; \ 1083*2a2be359SEric Blake b = (num) & MIPSDSP_LLO; \ 1084461c08dfSJia Liu } while (0) 1085461c08dfSJia Liu 1086*2a2be359SEric Blake #define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)(a) << 48) | \ 1087*2a2be359SEric Blake ((uint64_t)(b) << 32) | \ 1088*2a2be359SEric Blake ((uint64_t)(c) << 16) | \ 1089*2a2be359SEric Blake (uint64_t)(d)) 1090*2a2be359SEric Blake #define MIPSDSP_RETURN64_32(a, b) (((uint64_t)(a) << 32) | (uint64_t)(b)) 1091461c08dfSJia Liu #endif 1092461c08dfSJia Liu 1093461c08dfSJia Liu /** DSP Arithmetic Sub-class insns **/ 109475d012acSAurelien Jarno #define MIPSDSP32_UNOP_ENV(name, func, element) \ 109575d012acSAurelien Jarno target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \ 109675d012acSAurelien Jarno { \ 109775d012acSAurelien Jarno DSP32Value dt; \ 10988f84271dSStefan Weil unsigned int i; \ 109975d012acSAurelien Jarno \ 110075d012acSAurelien Jarno dt.sw[0] = rt; \ 110175d012acSAurelien Jarno \ 11028f84271dSStefan Weil for (i = 0; i < ARRAY_SIZE(dt.element); i++) { \ 110375d012acSAurelien Jarno dt.element[i] = mipsdsp_##func(dt.element[i], env); \ 110475d012acSAurelien Jarno } \ 110575d012acSAurelien Jarno \ 110675d012acSAurelien Jarno return (target_long)dt.sw[0]; \ 110775d012acSAurelien Jarno } 110875d012acSAurelien Jarno MIPSDSP32_UNOP_ENV(absq_s_ph, sat_abs16, sh) 110975d012acSAurelien Jarno MIPSDSP32_UNOP_ENV(absq_s_qb, sat_abs8, sb) 111075d012acSAurelien Jarno MIPSDSP32_UNOP_ENV(absq_s_w, sat_abs32, sw) 111175d012acSAurelien Jarno #undef MIPSDSP32_UNOP_ENV 111275d012acSAurelien Jarno 111375d012acSAurelien Jarno #if defined(TARGET_MIPS64) 111475d012acSAurelien Jarno #define MIPSDSP64_UNOP_ENV(name, func, element) \ 111575d012acSAurelien Jarno target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \ 111675d012acSAurelien Jarno { \ 111775d012acSAurelien Jarno DSP64Value dt; \ 11188f84271dSStefan Weil unsigned int i; \ 111975d012acSAurelien Jarno \ 112075d012acSAurelien Jarno dt.sl[0] = rt; \ 112175d012acSAurelien Jarno \ 11228f84271dSStefan Weil for (i = 0; i < ARRAY_SIZE(dt.element); i++) { \ 112375d012acSAurelien Jarno dt.element[i] = mipsdsp_##func(dt.element[i], env); \ 112475d012acSAurelien Jarno } \ 112575d012acSAurelien Jarno \ 112675d012acSAurelien Jarno return dt.sl[0]; \ 112775d012acSAurelien Jarno } 112875d012acSAurelien Jarno MIPSDSP64_UNOP_ENV(absq_s_ob, sat_abs8, sb) 112975d012acSAurelien Jarno MIPSDSP64_UNOP_ENV(absq_s_qh, sat_abs16, sh) 113075d012acSAurelien Jarno MIPSDSP64_UNOP_ENV(absq_s_pw, sat_abs32, sw) 113175d012acSAurelien Jarno #undef MIPSDSP64_UNOP_ENV 113275d012acSAurelien Jarno #endif 113375d012acSAurelien Jarno 11346de0e6c1SAurelien Jarno #define MIPSDSP32_BINOP(name, func, element) \ 11356de0e6c1SAurelien Jarno target_ulong helper_##name(target_ulong rs, target_ulong rt) \ 1136461c08dfSJia Liu { \ 11376de0e6c1SAurelien Jarno DSP32Value ds, dt; \ 11388f84271dSStefan Weil unsigned int i; \ 1139461c08dfSJia Liu \ 11406de0e6c1SAurelien Jarno ds.sw[0] = rs; \ 11416de0e6c1SAurelien Jarno dt.sw[0] = rt; \ 1142461c08dfSJia Liu \ 11438f84271dSStefan Weil for (i = 0; i < ARRAY_SIZE(ds.element); i++) { \ 11446de0e6c1SAurelien Jarno ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \ 11456de0e6c1SAurelien Jarno } \ 1146461c08dfSJia Liu \ 11476de0e6c1SAurelien Jarno return (target_long)ds.sw[0]; \ 1148461c08dfSJia Liu } 11496de0e6c1SAurelien Jarno MIPSDSP32_BINOP(addqh_ph, rshift1_add_q16, sh); 11506de0e6c1SAurelien Jarno MIPSDSP32_BINOP(addqh_r_ph, rrshift1_add_q16, sh); 11516de0e6c1SAurelien Jarno MIPSDSP32_BINOP(addqh_r_w, rrshift1_add_q32, sw); 11526de0e6c1SAurelien Jarno MIPSDSP32_BINOP(addqh_w, rshift1_add_q32, sw); 11536de0e6c1SAurelien Jarno MIPSDSP32_BINOP(adduh_qb, rshift1_add_u8, ub); 11546de0e6c1SAurelien Jarno MIPSDSP32_BINOP(adduh_r_qb, rrshift1_add_u8, ub); 11556de0e6c1SAurelien Jarno MIPSDSP32_BINOP(subqh_ph, rshift1_sub_q16, sh); 11566de0e6c1SAurelien Jarno MIPSDSP32_BINOP(subqh_r_ph, rrshift1_sub_q16, sh); 11576de0e6c1SAurelien Jarno MIPSDSP32_BINOP(subqh_r_w, rrshift1_sub_q32, sw); 11586de0e6c1SAurelien Jarno MIPSDSP32_BINOP(subqh_w, rshift1_sub_q32, sw); 11596de0e6c1SAurelien Jarno #undef MIPSDSP32_BINOP 1160461c08dfSJia Liu 11616de0e6c1SAurelien Jarno #define MIPSDSP32_BINOP_ENV(name, func, element) \ 11626de0e6c1SAurelien Jarno target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 1163461c08dfSJia Liu CPUMIPSState *env) \ 1164461c08dfSJia Liu { \ 11656de0e6c1SAurelien Jarno DSP32Value ds, dt; \ 11668f84271dSStefan Weil unsigned int i; \ 1167461c08dfSJia Liu \ 11686de0e6c1SAurelien Jarno ds.sw[0] = rs; \ 11696de0e6c1SAurelien Jarno dt.sw[0] = rt; \ 1170461c08dfSJia Liu \ 11718f84271dSStefan Weil for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) { \ 11726de0e6c1SAurelien Jarno ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \ 11736de0e6c1SAurelien Jarno } \ 1174461c08dfSJia Liu \ 11756de0e6c1SAurelien Jarno return (target_long)ds.sw[0]; \ 1176461c08dfSJia Liu } 11776de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(addq_ph, add_i16, sh) 11786de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(addq_s_ph, sat_add_i16, sh) 11796de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(addq_s_w, sat_add_i32, sw); 11806de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(addu_ph, add_u16, sh) 11816de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(addu_qb, add_u8, ub); 11826de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(addu_s_ph, sat_add_u16, sh) 11836de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(addu_s_qb, sat_add_u8, ub); 11846de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(subq_ph, sub_i16, sh); 11856de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(subq_s_ph, sat16_sub, sh); 11866de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(subq_s_w, sat32_sub, sw); 11876de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(subu_ph, sub_u16_u16, sh); 11886de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(subu_qb, sub_u8, ub); 11896de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(subu_s_ph, satu16_sub_u16_u16, sh); 11906de0e6c1SAurelien Jarno MIPSDSP32_BINOP_ENV(subu_s_qb, satu8_sub, ub); 11916de0e6c1SAurelien Jarno #undef MIPSDSP32_BINOP_ENV 1192461c08dfSJia Liu 1193461c08dfSJia Liu #ifdef TARGET_MIPS64 11946de0e6c1SAurelien Jarno #define MIPSDSP64_BINOP(name, func, element) \ 11956de0e6c1SAurelien Jarno target_ulong helper_##name(target_ulong rs, target_ulong rt) \ 11966de0e6c1SAurelien Jarno { \ 11976de0e6c1SAurelien Jarno DSP64Value ds, dt; \ 11988f84271dSStefan Weil unsigned int i; \ 11996de0e6c1SAurelien Jarno \ 12006de0e6c1SAurelien Jarno ds.sl[0] = rs; \ 12016de0e6c1SAurelien Jarno dt.sl[0] = rt; \ 12026de0e6c1SAurelien Jarno \ 12038f84271dSStefan Weil for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) { \ 12046de0e6c1SAurelien Jarno ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \ 12056de0e6c1SAurelien Jarno } \ 12066de0e6c1SAurelien Jarno \ 12076de0e6c1SAurelien Jarno return ds.sl[0]; \ 12086de0e6c1SAurelien Jarno } 12096de0e6c1SAurelien Jarno MIPSDSP64_BINOP(adduh_ob, rshift1_add_u8, ub); 12106de0e6c1SAurelien Jarno MIPSDSP64_BINOP(adduh_r_ob, rrshift1_add_u8, ub); 12116de0e6c1SAurelien Jarno MIPSDSP64_BINOP(subuh_ob, rshift1_sub_u8, ub); 12126de0e6c1SAurelien Jarno MIPSDSP64_BINOP(subuh_r_ob, rrshift1_sub_u8, ub); 12136de0e6c1SAurelien Jarno #undef MIPSDSP64_BINOP 12146de0e6c1SAurelien Jarno 12156de0e6c1SAurelien Jarno #define MIPSDSP64_BINOP_ENV(name, func, element) \ 12166de0e6c1SAurelien Jarno target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 1217461c08dfSJia Liu CPUMIPSState *env) \ 1218461c08dfSJia Liu { \ 12196de0e6c1SAurelien Jarno DSP64Value ds, dt; \ 12208f84271dSStefan Weil unsigned int i; \ 1221461c08dfSJia Liu \ 12226de0e6c1SAurelien Jarno ds.sl[0] = rs; \ 12236de0e6c1SAurelien Jarno dt.sl[0] = rt; \ 1224461c08dfSJia Liu \ 12258f84271dSStefan Weil for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) { \ 12266de0e6c1SAurelien Jarno ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \ 12276de0e6c1SAurelien Jarno } \ 1228461c08dfSJia Liu \ 12296de0e6c1SAurelien Jarno return ds.sl[0]; \ 1230461c08dfSJia Liu } 12316de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(addq_pw, add_i32, sw); 12326de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(addq_qh, add_i16, sh); 12336de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(addq_s_pw, sat_add_i32, sw); 12346de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(addq_s_qh, sat_add_i16, sh); 12356de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(addu_ob, add_u8, uh); 12366de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(addu_qh, add_u16, uh); 12376de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(addu_s_ob, sat_add_u8, uh); 12386de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(addu_s_qh, sat_add_u16, uh); 12396de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(subq_pw, sub32, sw); 12406de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(subq_qh, sub_i16, sh); 12416de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(subq_s_pw, sat32_sub, sw); 12426de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(subq_s_qh, sat16_sub, sh); 12436de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(subu_ob, sub_u8, uh); 12446de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(subu_qh, sub_u16_u16, uh); 12456de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(subu_s_ob, satu8_sub, uh); 12466de0e6c1SAurelien Jarno MIPSDSP64_BINOP_ENV(subu_s_qh, satu16_sub_u16_u16, uh); 12476de0e6c1SAurelien Jarno #undef MIPSDSP64_BINOP_ENV 1248461c08dfSJia Liu 1249461c08dfSJia Liu #endif 1250461c08dfSJia Liu 1251461c08dfSJia Liu #define SUBUH_QB(name, var) \ 1252461c08dfSJia Liu target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \ 1253461c08dfSJia Liu { \ 1254461c08dfSJia Liu uint8_t rs3, rs2, rs1, rs0; \ 1255461c08dfSJia Liu uint8_t rt3, rt2, rt1, rt0; \ 1256461c08dfSJia Liu uint8_t tempD, tempC, tempB, tempA; \ 1257461c08dfSJia Liu \ 1258461c08dfSJia Liu MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ 1259461c08dfSJia Liu MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 1260461c08dfSJia Liu \ 1261461c08dfSJia Liu tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1; \ 1262461c08dfSJia Liu tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1; \ 1263461c08dfSJia Liu tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1; \ 1264461c08dfSJia Liu tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1; \ 1265461c08dfSJia Liu \ 1266461c08dfSJia Liu return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \ 1267461c08dfSJia Liu ((uint32_t)tempB << 8) | ((uint32_t)tempA); \ 1268461c08dfSJia Liu } 1269461c08dfSJia Liu 1270461c08dfSJia Liu SUBUH_QB(subuh, 0); 1271461c08dfSJia Liu SUBUH_QB(subuh_r, 1); 1272461c08dfSJia Liu 1273461c08dfSJia Liu #undef SUBUH_QB 1274461c08dfSJia Liu 1275461c08dfSJia Liu target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env) 1276461c08dfSJia Liu { 1277461c08dfSJia Liu uint64_t temp, tempRs, tempRt; 1278118d1e4fSPetar Jovanovic bool flag; 1279461c08dfSJia Liu 1280461c08dfSJia Liu tempRs = (uint64_t)rs & MIPSDSP_LLO; 1281461c08dfSJia Liu tempRt = (uint64_t)rt & MIPSDSP_LLO; 1282461c08dfSJia Liu 1283461c08dfSJia Liu temp = tempRs + tempRt; 1284461c08dfSJia Liu flag = (temp & 0x0100000000ull) >> 32; 1285461c08dfSJia Liu set_DSPControl_carryflag(flag, env); 1286461c08dfSJia Liu 1287461c08dfSJia Liu return (target_long)(int32_t)(temp & MIPSDSP_LLO); 1288461c08dfSJia Liu } 1289461c08dfSJia Liu 1290461c08dfSJia Liu target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env) 1291461c08dfSJia Liu { 1292461c08dfSJia Liu uint32_t rd; 1293461c08dfSJia Liu int32_t temp32, temp31; 1294461c08dfSJia Liu int64_t tempL; 1295461c08dfSJia Liu 1296461c08dfSJia Liu tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt + 1297461c08dfSJia Liu get_DSPControl_carryflag(env); 1298461c08dfSJia Liu temp31 = (tempL >> 31) & 0x01; 1299461c08dfSJia Liu temp32 = (tempL >> 32) & 0x01; 1300461c08dfSJia Liu 1301461c08dfSJia Liu if (temp31 != temp32) { 1302461c08dfSJia Liu set_DSPControl_overflow_flag(1, 20, env); 1303461c08dfSJia Liu } 1304461c08dfSJia Liu 1305461c08dfSJia Liu rd = tempL & MIPSDSP_LLO; 1306461c08dfSJia Liu 1307461c08dfSJia Liu return (target_long)(int32_t)rd; 1308461c08dfSJia Liu } 1309461c08dfSJia Liu 1310461c08dfSJia Liu target_ulong helper_modsub(target_ulong rs, target_ulong rt) 1311461c08dfSJia Liu { 1312461c08dfSJia Liu int32_t decr; 1313461c08dfSJia Liu uint16_t lastindex; 1314461c08dfSJia Liu target_ulong rd; 1315461c08dfSJia Liu 1316461c08dfSJia Liu decr = rt & MIPSDSP_Q0; 1317461c08dfSJia Liu lastindex = (rt >> 8) & MIPSDSP_LO; 1318461c08dfSJia Liu 1319461c08dfSJia Liu if ((rs & MIPSDSP_LLO) == 0x00000000) { 1320461c08dfSJia Liu rd = (target_ulong)lastindex; 1321461c08dfSJia Liu } else { 1322461c08dfSJia Liu rd = rs - decr; 1323461c08dfSJia Liu } 1324461c08dfSJia Liu 1325461c08dfSJia Liu return rd; 1326461c08dfSJia Liu } 1327461c08dfSJia Liu 1328461c08dfSJia Liu target_ulong helper_raddu_w_qb(target_ulong rs) 1329461c08dfSJia Liu { 13300a16c79cSAurelien Jarno target_ulong ret = 0; 13310a16c79cSAurelien Jarno DSP32Value ds; 13320a16c79cSAurelien Jarno unsigned int i; 1333461c08dfSJia Liu 13340a16c79cSAurelien Jarno ds.uw[0] = rs; 13350a16c79cSAurelien Jarno for (i = 0; i < 4; i++) { 13360a16c79cSAurelien Jarno ret += ds.ub[i]; 13370a16c79cSAurelien Jarno } 13380a16c79cSAurelien Jarno return ret; 1339461c08dfSJia Liu } 1340461c08dfSJia Liu 1341461c08dfSJia Liu #if defined(TARGET_MIPS64) 1342461c08dfSJia Liu target_ulong helper_raddu_l_ob(target_ulong rs) 1343461c08dfSJia Liu { 13440a16c79cSAurelien Jarno target_ulong ret = 0; 13450a16c79cSAurelien Jarno DSP64Value ds; 13460a16c79cSAurelien Jarno unsigned int i; 1347461c08dfSJia Liu 13480a16c79cSAurelien Jarno ds.ul[0] = rs; 1349461c08dfSJia Liu for (i = 0; i < 8; i++) { 13500a16c79cSAurelien Jarno ret += ds.ub[i]; 1351461c08dfSJia Liu } 13520a16c79cSAurelien Jarno return ret; 1353461c08dfSJia Liu } 1354461c08dfSJia Liu #endif 1355461c08dfSJia Liu 1356461c08dfSJia Liu #define PRECR_QB_PH(name, a, b)\ 1357461c08dfSJia Liu target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \ 1358461c08dfSJia Liu { \ 1359461c08dfSJia Liu uint8_t tempD, tempC, tempB, tempA; \ 1360461c08dfSJia Liu \ 1361461c08dfSJia Liu tempD = (rs >> a) & MIPSDSP_Q0; \ 1362461c08dfSJia Liu tempC = (rs >> b) & MIPSDSP_Q0; \ 1363461c08dfSJia Liu tempB = (rt >> a) & MIPSDSP_Q0; \ 1364461c08dfSJia Liu tempA = (rt >> b) & MIPSDSP_Q0; \ 1365461c08dfSJia Liu \ 1366461c08dfSJia Liu return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); \ 1367461c08dfSJia Liu } 1368461c08dfSJia Liu 1369461c08dfSJia Liu PRECR_QB_PH(precr, 16, 0); 1370461c08dfSJia Liu PRECR_QB_PH(precrq, 24, 8); 1371461c08dfSJia Liu 1372461c08dfSJia Liu #undef PRECR_QB_OH 1373461c08dfSJia Liu 1374461c08dfSJia Liu target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs, 1375461c08dfSJia Liu target_ulong rt) 1376461c08dfSJia Liu { 1377461c08dfSJia Liu uint16_t tempB, tempA; 1378461c08dfSJia Liu 1379461c08dfSJia Liu tempB = ((int32_t)rt >> sa) & MIPSDSP_LO; 1380461c08dfSJia Liu tempA = ((int32_t)rs >> sa) & MIPSDSP_LO; 1381461c08dfSJia Liu 1382461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); 1383461c08dfSJia Liu } 1384461c08dfSJia Liu 1385461c08dfSJia Liu target_ulong helper_precr_sra_r_ph_w(uint32_t sa, 1386461c08dfSJia Liu target_ulong rs, target_ulong rt) 1387461c08dfSJia Liu { 1388461c08dfSJia Liu uint64_t tempB, tempA; 1389461c08dfSJia Liu 1390461c08dfSJia Liu /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */ 1391461c08dfSJia Liu if (sa == 0) { 1392461c08dfSJia Liu tempB = (rt & MIPSDSP_LO) << 1; 1393461c08dfSJia Liu tempA = (rs & MIPSDSP_LO) << 1; 1394461c08dfSJia Liu } else { 1395461c08dfSJia Liu tempB = ((int32_t)rt >> (sa - 1)) + 1; 1396461c08dfSJia Liu tempA = ((int32_t)rs >> (sa - 1)) + 1; 1397461c08dfSJia Liu } 1398461c08dfSJia Liu rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO); 1399461c08dfSJia Liu 1400461c08dfSJia Liu return (target_long)(int32_t)rt; 1401461c08dfSJia Liu } 1402461c08dfSJia Liu 1403461c08dfSJia Liu target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt) 1404461c08dfSJia Liu { 1405461c08dfSJia Liu uint16_t tempB, tempA; 1406461c08dfSJia Liu 1407461c08dfSJia Liu tempB = (rs & MIPSDSP_HI) >> 16; 1408461c08dfSJia Liu tempA = (rt & MIPSDSP_HI) >> 16; 1409461c08dfSJia Liu 1410461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); 1411461c08dfSJia Liu } 1412461c08dfSJia Liu 1413461c08dfSJia Liu target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt, 1414461c08dfSJia Liu CPUMIPSState *env) 1415461c08dfSJia Liu { 1416461c08dfSJia Liu uint16_t tempB, tempA; 1417461c08dfSJia Liu 1418461c08dfSJia Liu tempB = mipsdsp_trunc16_sat16_round(rs, env); 1419461c08dfSJia Liu tempA = mipsdsp_trunc16_sat16_round(rt, env); 1420461c08dfSJia Liu 1421461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); 1422461c08dfSJia Liu } 1423461c08dfSJia Liu 1424461c08dfSJia Liu #if defined(TARGET_MIPS64) 1425461c08dfSJia Liu target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt) 1426461c08dfSJia Liu { 1427461c08dfSJia Liu uint8_t rs6, rs4, rs2, rs0; 1428461c08dfSJia Liu uint8_t rt6, rt4, rt2, rt0; 1429461c08dfSJia Liu uint64_t temp; 1430461c08dfSJia Liu 1431461c08dfSJia Liu rs6 = (rs >> 48) & MIPSDSP_Q0; 1432461c08dfSJia Liu rs4 = (rs >> 32) & MIPSDSP_Q0; 1433461c08dfSJia Liu rs2 = (rs >> 16) & MIPSDSP_Q0; 1434461c08dfSJia Liu rs0 = rs & MIPSDSP_Q0; 1435461c08dfSJia Liu rt6 = (rt >> 48) & MIPSDSP_Q0; 1436461c08dfSJia Liu rt4 = (rt >> 32) & MIPSDSP_Q0; 1437461c08dfSJia Liu rt2 = (rt >> 16) & MIPSDSP_Q0; 1438461c08dfSJia Liu rt0 = rt & MIPSDSP_Q0; 1439461c08dfSJia Liu 1440461c08dfSJia Liu temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) | 1441461c08dfSJia Liu ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) | 1442461c08dfSJia Liu ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) | 1443461c08dfSJia Liu ((uint64_t)rt2 << 8) | (uint64_t)rt0; 1444461c08dfSJia Liu 1445461c08dfSJia Liu return temp; 1446461c08dfSJia Liu } 1447461c08dfSJia Liu 1448461c08dfSJia Liu #define PRECR_QH_PW(name, var) \ 1449461c08dfSJia Liu target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \ 1450461c08dfSJia Liu uint32_t sa) \ 1451461c08dfSJia Liu { \ 1452461c08dfSJia Liu uint16_t rs3, rs2, rs1, rs0; \ 1453461c08dfSJia Liu uint16_t rt3, rt2, rt1, rt0; \ 1454461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 1455461c08dfSJia Liu \ 1456461c08dfSJia Liu MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ 1457461c08dfSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 1458461c08dfSJia Liu \ 1459461c08dfSJia Liu /* When sa = 0, we use rt2, rt0, rs2, rs0; \ 1460461c08dfSJia Liu * when sa != 0, we use rt3, rt1, rs3, rs1. */ \ 1461461c08dfSJia Liu if (sa == 0) { \ 1462461c08dfSJia Liu tempD = rt2 << var; \ 1463461c08dfSJia Liu tempC = rt0 << var; \ 1464461c08dfSJia Liu tempB = rs2 << var; \ 1465461c08dfSJia Liu tempA = rs0 << var; \ 1466461c08dfSJia Liu } else { \ 1467461c08dfSJia Liu tempD = (((int16_t)rt3 >> sa) + var) >> var; \ 1468461c08dfSJia Liu tempC = (((int16_t)rt1 >> sa) + var) >> var; \ 1469461c08dfSJia Liu tempB = (((int16_t)rs3 >> sa) + var) >> var; \ 1470461c08dfSJia Liu tempA = (((int16_t)rs1 >> sa) + var) >> var; \ 1471461c08dfSJia Liu } \ 1472461c08dfSJia Liu \ 1473461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1474461c08dfSJia Liu } 1475461c08dfSJia Liu 1476461c08dfSJia Liu PRECR_QH_PW(sra, 0); 1477461c08dfSJia Liu PRECR_QH_PW(sra_r, 1); 1478461c08dfSJia Liu 1479461c08dfSJia Liu #undef PRECR_QH_PW 1480461c08dfSJia Liu 1481461c08dfSJia Liu target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt) 1482461c08dfSJia Liu { 1483461c08dfSJia Liu uint8_t rs6, rs4, rs2, rs0; 1484461c08dfSJia Liu uint8_t rt6, rt4, rt2, rt0; 1485461c08dfSJia Liu uint64_t temp; 1486461c08dfSJia Liu 1487461c08dfSJia Liu rs6 = (rs >> 56) & MIPSDSP_Q0; 1488461c08dfSJia Liu rs4 = (rs >> 40) & MIPSDSP_Q0; 1489461c08dfSJia Liu rs2 = (rs >> 24) & MIPSDSP_Q0; 1490461c08dfSJia Liu rs0 = (rs >> 8) & MIPSDSP_Q0; 1491461c08dfSJia Liu rt6 = (rt >> 56) & MIPSDSP_Q0; 1492461c08dfSJia Liu rt4 = (rt >> 40) & MIPSDSP_Q0; 1493461c08dfSJia Liu rt2 = (rt >> 24) & MIPSDSP_Q0; 1494461c08dfSJia Liu rt0 = (rt >> 8) & MIPSDSP_Q0; 1495461c08dfSJia Liu 1496461c08dfSJia Liu temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) | 1497461c08dfSJia Liu ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) | 1498461c08dfSJia Liu ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) | 1499461c08dfSJia Liu ((uint64_t)rt2 << 8) | (uint64_t)rt0; 1500461c08dfSJia Liu 1501461c08dfSJia Liu return temp; 1502461c08dfSJia Liu } 1503461c08dfSJia Liu 1504461c08dfSJia Liu target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt) 1505461c08dfSJia Liu { 1506461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; 1507461c08dfSJia Liu 1508461c08dfSJia Liu tempD = (rs >> 48) & MIPSDSP_LO; 1509461c08dfSJia Liu tempC = (rs >> 16) & MIPSDSP_LO; 1510461c08dfSJia Liu tempB = (rt >> 48) & MIPSDSP_LO; 1511461c08dfSJia Liu tempA = (rt >> 16) & MIPSDSP_LO; 1512461c08dfSJia Liu 1513461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); 1514461c08dfSJia Liu } 1515461c08dfSJia Liu 1516461c08dfSJia Liu target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt, 1517461c08dfSJia Liu CPUMIPSState *env) 1518461c08dfSJia Liu { 1519461c08dfSJia Liu uint32_t rs2, rs0; 1520461c08dfSJia Liu uint32_t rt2, rt0; 1521461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; 1522461c08dfSJia Liu 1523461c08dfSJia Liu rs2 = (rs >> 32) & MIPSDSP_LLO; 1524461c08dfSJia Liu rs0 = rs & MIPSDSP_LLO; 1525461c08dfSJia Liu rt2 = (rt >> 32) & MIPSDSP_LLO; 1526461c08dfSJia Liu rt0 = rt & MIPSDSP_LLO; 1527461c08dfSJia Liu 1528461c08dfSJia Liu tempD = mipsdsp_trunc16_sat16_round(rs2, env); 1529461c08dfSJia Liu tempC = mipsdsp_trunc16_sat16_round(rs0, env); 1530461c08dfSJia Liu tempB = mipsdsp_trunc16_sat16_round(rt2, env); 1531461c08dfSJia Liu tempA = mipsdsp_trunc16_sat16_round(rt0, env); 1532461c08dfSJia Liu 1533461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); 1534461c08dfSJia Liu } 1535461c08dfSJia Liu 1536461c08dfSJia Liu target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt) 1537461c08dfSJia Liu { 1538461c08dfSJia Liu uint32_t tempB, tempA; 1539461c08dfSJia Liu 1540461c08dfSJia Liu tempB = (rs >> 32) & MIPSDSP_LLO; 1541461c08dfSJia Liu tempA = (rt >> 32) & MIPSDSP_LLO; 1542461c08dfSJia Liu 1543461c08dfSJia Liu return MIPSDSP_RETURN64_32(tempB, tempA); 1544461c08dfSJia Liu } 1545461c08dfSJia Liu #endif 1546461c08dfSJia Liu 1547461c08dfSJia Liu target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt, 1548461c08dfSJia Liu CPUMIPSState *env) 1549461c08dfSJia Liu { 1550461c08dfSJia Liu uint8_t tempD, tempC, tempB, tempA; 1551461c08dfSJia Liu uint16_t rsh, rsl, rth, rtl; 1552461c08dfSJia Liu 1553461c08dfSJia Liu rsh = (rs & MIPSDSP_HI) >> 16; 1554461c08dfSJia Liu rsl = rs & MIPSDSP_LO; 1555461c08dfSJia Liu rth = (rt & MIPSDSP_HI) >> 16; 1556461c08dfSJia Liu rtl = rt & MIPSDSP_LO; 1557461c08dfSJia Liu 1558461c08dfSJia Liu tempD = mipsdsp_sat8_reduce_precision(rsh, env); 1559461c08dfSJia Liu tempC = mipsdsp_sat8_reduce_precision(rsl, env); 1560461c08dfSJia Liu tempB = mipsdsp_sat8_reduce_precision(rth, env); 1561461c08dfSJia Liu tempA = mipsdsp_sat8_reduce_precision(rtl, env); 1562461c08dfSJia Liu 1563461c08dfSJia Liu return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); 1564461c08dfSJia Liu } 1565461c08dfSJia Liu 1566461c08dfSJia Liu #if defined(TARGET_MIPS64) 1567461c08dfSJia Liu target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt, 1568461c08dfSJia Liu CPUMIPSState *env) 1569461c08dfSJia Liu { 1570461c08dfSJia Liu int i; 1571461c08dfSJia Liu uint16_t rs3, rs2, rs1, rs0; 1572461c08dfSJia Liu uint16_t rt3, rt2, rt1, rt0; 1573461c08dfSJia Liu uint8_t temp[8]; 1574461c08dfSJia Liu uint64_t result; 1575461c08dfSJia Liu 1576461c08dfSJia Liu result = 0; 1577461c08dfSJia Liu 1578461c08dfSJia Liu MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); 1579461c08dfSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); 1580461c08dfSJia Liu 1581461c08dfSJia Liu temp[7] = mipsdsp_sat8_reduce_precision(rs3, env); 1582461c08dfSJia Liu temp[6] = mipsdsp_sat8_reduce_precision(rs2, env); 1583461c08dfSJia Liu temp[5] = mipsdsp_sat8_reduce_precision(rs1, env); 1584461c08dfSJia Liu temp[4] = mipsdsp_sat8_reduce_precision(rs0, env); 1585461c08dfSJia Liu temp[3] = mipsdsp_sat8_reduce_precision(rt3, env); 1586461c08dfSJia Liu temp[2] = mipsdsp_sat8_reduce_precision(rt2, env); 1587461c08dfSJia Liu temp[1] = mipsdsp_sat8_reduce_precision(rt1, env); 1588461c08dfSJia Liu temp[0] = mipsdsp_sat8_reduce_precision(rt0, env); 1589461c08dfSJia Liu 1590461c08dfSJia Liu for (i = 0; i < 8; i++) { 1591461c08dfSJia Liu result |= (uint64_t)temp[i] << (8 * i); 1592461c08dfSJia Liu } 1593461c08dfSJia Liu 1594461c08dfSJia Liu return result; 1595461c08dfSJia Liu } 1596461c08dfSJia Liu 1597461c08dfSJia Liu #define PRECEQ_PW(name, a, b) \ 1598461c08dfSJia Liu target_ulong helper_preceq_pw_##name(target_ulong rt) \ 1599461c08dfSJia Liu { \ 1600461c08dfSJia Liu uint16_t tempB, tempA; \ 1601461c08dfSJia Liu uint32_t tempBI, tempAI; \ 1602461c08dfSJia Liu \ 1603461c08dfSJia Liu tempB = (rt >> a) & MIPSDSP_LO; \ 1604461c08dfSJia Liu tempA = (rt >> b) & MIPSDSP_LO; \ 1605461c08dfSJia Liu \ 1606461c08dfSJia Liu tempBI = (uint32_t)tempB << 16; \ 1607461c08dfSJia Liu tempAI = (uint32_t)tempA << 16; \ 1608461c08dfSJia Liu \ 1609461c08dfSJia Liu return MIPSDSP_RETURN64_32(tempBI, tempAI); \ 1610461c08dfSJia Liu } 1611461c08dfSJia Liu 1612461c08dfSJia Liu PRECEQ_PW(qhl, 48, 32); 1613461c08dfSJia Liu PRECEQ_PW(qhr, 16, 0); 1614461c08dfSJia Liu PRECEQ_PW(qhla, 48, 16); 1615461c08dfSJia Liu PRECEQ_PW(qhra, 32, 0); 1616461c08dfSJia Liu 1617461c08dfSJia Liu #undef PRECEQ_PW 1618461c08dfSJia Liu 1619461c08dfSJia Liu #endif 1620461c08dfSJia Liu 1621461c08dfSJia Liu #define PRECEQU_PH(name, a, b) \ 1622461c08dfSJia Liu target_ulong helper_precequ_ph_##name(target_ulong rt) \ 1623461c08dfSJia Liu { \ 1624461c08dfSJia Liu uint16_t tempB, tempA; \ 1625461c08dfSJia Liu \ 1626461c08dfSJia Liu tempB = (rt >> a) & MIPSDSP_Q0; \ 1627461c08dfSJia Liu tempA = (rt >> b) & MIPSDSP_Q0; \ 1628461c08dfSJia Liu \ 1629461c08dfSJia Liu tempB = tempB << 7; \ 1630461c08dfSJia Liu tempA = tempA << 7; \ 1631461c08dfSJia Liu \ 1632461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); \ 1633461c08dfSJia Liu } 1634461c08dfSJia Liu 1635461c08dfSJia Liu PRECEQU_PH(qbl, 24, 16); 1636461c08dfSJia Liu PRECEQU_PH(qbr, 8, 0); 1637461c08dfSJia Liu PRECEQU_PH(qbla, 24, 8); 1638461c08dfSJia Liu PRECEQU_PH(qbra, 16, 0); 1639461c08dfSJia Liu 1640461c08dfSJia Liu #undef PRECEQU_PH 1641461c08dfSJia Liu 1642461c08dfSJia Liu #if defined(TARGET_MIPS64) 1643461c08dfSJia Liu #define PRECEQU_QH(name, a, b, c, d) \ 1644461c08dfSJia Liu target_ulong helper_precequ_qh_##name(target_ulong rt) \ 1645461c08dfSJia Liu { \ 1646461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 1647461c08dfSJia Liu \ 1648461c08dfSJia Liu tempD = (rt >> a) & MIPSDSP_Q0; \ 1649461c08dfSJia Liu tempC = (rt >> b) & MIPSDSP_Q0; \ 1650461c08dfSJia Liu tempB = (rt >> c) & MIPSDSP_Q0; \ 1651461c08dfSJia Liu tempA = (rt >> d) & MIPSDSP_Q0; \ 1652461c08dfSJia Liu \ 1653461c08dfSJia Liu tempD = tempD << 7; \ 1654461c08dfSJia Liu tempC = tempC << 7; \ 1655461c08dfSJia Liu tempB = tempB << 7; \ 1656461c08dfSJia Liu tempA = tempA << 7; \ 1657461c08dfSJia Liu \ 1658461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1659461c08dfSJia Liu } 1660461c08dfSJia Liu 1661461c08dfSJia Liu PRECEQU_QH(obl, 56, 48, 40, 32); 1662461c08dfSJia Liu PRECEQU_QH(obr, 24, 16, 8, 0); 1663461c08dfSJia Liu PRECEQU_QH(obla, 56, 40, 24, 8); 1664461c08dfSJia Liu PRECEQU_QH(obra, 48, 32, 16, 0); 1665461c08dfSJia Liu 1666461c08dfSJia Liu #undef PRECEQU_QH 1667461c08dfSJia Liu 1668461c08dfSJia Liu #endif 1669461c08dfSJia Liu 1670461c08dfSJia Liu #define PRECEU_PH(name, a, b) \ 1671461c08dfSJia Liu target_ulong helper_preceu_ph_##name(target_ulong rt) \ 1672461c08dfSJia Liu { \ 1673461c08dfSJia Liu uint16_t tempB, tempA; \ 1674461c08dfSJia Liu \ 1675461c08dfSJia Liu tempB = (rt >> a) & MIPSDSP_Q0; \ 1676461c08dfSJia Liu tempA = (rt >> b) & MIPSDSP_Q0; \ 1677461c08dfSJia Liu \ 1678461c08dfSJia Liu return MIPSDSP_RETURN32_16(tempB, tempA); \ 1679461c08dfSJia Liu } 1680461c08dfSJia Liu 1681461c08dfSJia Liu PRECEU_PH(qbl, 24, 16); 1682461c08dfSJia Liu PRECEU_PH(qbr, 8, 0); 1683461c08dfSJia Liu PRECEU_PH(qbla, 24, 8); 1684461c08dfSJia Liu PRECEU_PH(qbra, 16, 0); 1685461c08dfSJia Liu 1686461c08dfSJia Liu #undef PRECEU_PH 1687461c08dfSJia Liu 1688461c08dfSJia Liu #if defined(TARGET_MIPS64) 1689461c08dfSJia Liu #define PRECEU_QH(name, a, b, c, d) \ 1690461c08dfSJia Liu target_ulong helper_preceu_qh_##name(target_ulong rt) \ 1691461c08dfSJia Liu { \ 1692461c08dfSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 1693461c08dfSJia Liu \ 1694461c08dfSJia Liu tempD = (rt >> a) & MIPSDSP_Q0; \ 1695461c08dfSJia Liu tempC = (rt >> b) & MIPSDSP_Q0; \ 1696461c08dfSJia Liu tempB = (rt >> c) & MIPSDSP_Q0; \ 1697461c08dfSJia Liu tempA = (rt >> d) & MIPSDSP_Q0; \ 1698461c08dfSJia Liu \ 1699461c08dfSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1700461c08dfSJia Liu } 1701461c08dfSJia Liu 1702461c08dfSJia Liu PRECEU_QH(obl, 56, 48, 40, 32); 1703461c08dfSJia Liu PRECEU_QH(obr, 24, 16, 8, 0); 1704461c08dfSJia Liu PRECEU_QH(obla, 56, 40, 24, 8); 1705461c08dfSJia Liu PRECEU_QH(obra, 48, 32, 16, 0); 1706461c08dfSJia Liu 1707461c08dfSJia Liu #undef PRECEU_QH 1708461c08dfSJia Liu 1709461c08dfSJia Liu #endif 1710461c08dfSJia Liu 171177c5fa8bSJia Liu /** DSP GPR-Based Shift Sub-class insns **/ 171277c5fa8bSJia Liu #define SHIFT_QB(name, func) \ 171377c5fa8bSJia Liu target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \ 171477c5fa8bSJia Liu { \ 171577c5fa8bSJia Liu uint8_t rt3, rt2, rt1, rt0; \ 171677c5fa8bSJia Liu \ 171777c5fa8bSJia Liu sa = sa & 0x07; \ 171877c5fa8bSJia Liu \ 171977c5fa8bSJia Liu MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 172077c5fa8bSJia Liu \ 172177c5fa8bSJia Liu rt3 = mipsdsp_##func(rt3, sa); \ 172277c5fa8bSJia Liu rt2 = mipsdsp_##func(rt2, sa); \ 172377c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa); \ 172477c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa); \ 172577c5fa8bSJia Liu \ 172677c5fa8bSJia Liu return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \ 172777c5fa8bSJia Liu } 172877c5fa8bSJia Liu 172977c5fa8bSJia Liu #define SHIFT_QB_ENV(name, func) \ 173077c5fa8bSJia Liu target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\ 173177c5fa8bSJia Liu CPUMIPSState *env) \ 173277c5fa8bSJia Liu { \ 173377c5fa8bSJia Liu uint8_t rt3, rt2, rt1, rt0; \ 173477c5fa8bSJia Liu \ 173577c5fa8bSJia Liu sa = sa & 0x07; \ 173677c5fa8bSJia Liu \ 173777c5fa8bSJia Liu MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 173877c5fa8bSJia Liu \ 173977c5fa8bSJia Liu rt3 = mipsdsp_##func(rt3, sa, env); \ 174077c5fa8bSJia Liu rt2 = mipsdsp_##func(rt2, sa, env); \ 174177c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa, env); \ 174277c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa, env); \ 174377c5fa8bSJia Liu \ 174477c5fa8bSJia Liu return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \ 174577c5fa8bSJia Liu } 174677c5fa8bSJia Liu 174777c5fa8bSJia Liu SHIFT_QB_ENV(shll, lshift8); 174877c5fa8bSJia Liu SHIFT_QB(shrl, rshift_u8); 174977c5fa8bSJia Liu 175077c5fa8bSJia Liu SHIFT_QB(shra, rashift8); 175177c5fa8bSJia Liu SHIFT_QB(shra_r, rnd8_rashift); 175277c5fa8bSJia Liu 175377c5fa8bSJia Liu #undef SHIFT_QB 175477c5fa8bSJia Liu #undef SHIFT_QB_ENV 175577c5fa8bSJia Liu 175677c5fa8bSJia Liu #if defined(TARGET_MIPS64) 175777c5fa8bSJia Liu #define SHIFT_OB(name, func) \ 175877c5fa8bSJia Liu target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \ 175977c5fa8bSJia Liu { \ 176077c5fa8bSJia Liu int i; \ 176177c5fa8bSJia Liu uint8_t rt_t[8]; \ 176277c5fa8bSJia Liu uint64_t temp; \ 176377c5fa8bSJia Liu \ 176477c5fa8bSJia Liu sa = sa & 0x07; \ 176577c5fa8bSJia Liu temp = 0; \ 176677c5fa8bSJia Liu \ 176777c5fa8bSJia Liu for (i = 0; i < 8; i++) { \ 176877c5fa8bSJia Liu rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ 176977c5fa8bSJia Liu rt_t[i] = mipsdsp_##func(rt_t[i], sa); \ 177077c5fa8bSJia Liu temp |= (uint64_t)rt_t[i] << (8 * i); \ 177177c5fa8bSJia Liu } \ 177277c5fa8bSJia Liu \ 177377c5fa8bSJia Liu return temp; \ 177477c5fa8bSJia Liu } 177577c5fa8bSJia Liu 177677c5fa8bSJia Liu #define SHIFT_OB_ENV(name, func) \ 177777c5fa8bSJia Liu target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \ 177877c5fa8bSJia Liu CPUMIPSState *env) \ 177977c5fa8bSJia Liu { \ 178077c5fa8bSJia Liu int i; \ 178177c5fa8bSJia Liu uint8_t rt_t[8]; \ 178277c5fa8bSJia Liu uint64_t temp; \ 178377c5fa8bSJia Liu \ 178477c5fa8bSJia Liu sa = sa & 0x07; \ 178577c5fa8bSJia Liu temp = 0; \ 178677c5fa8bSJia Liu \ 178777c5fa8bSJia Liu for (i = 0; i < 8; i++) { \ 178877c5fa8bSJia Liu rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ 178977c5fa8bSJia Liu rt_t[i] = mipsdsp_##func(rt_t[i], sa, env); \ 179077c5fa8bSJia Liu temp |= (uint64_t)rt_t[i] << (8 * i); \ 179177c5fa8bSJia Liu } \ 179277c5fa8bSJia Liu \ 179377c5fa8bSJia Liu return temp; \ 179477c5fa8bSJia Liu } 179577c5fa8bSJia Liu 179677c5fa8bSJia Liu SHIFT_OB_ENV(shll, lshift8); 179777c5fa8bSJia Liu SHIFT_OB(shrl, rshift_u8); 179877c5fa8bSJia Liu 179977c5fa8bSJia Liu SHIFT_OB(shra, rashift8); 180077c5fa8bSJia Liu SHIFT_OB(shra_r, rnd8_rashift); 180177c5fa8bSJia Liu 180277c5fa8bSJia Liu #undef SHIFT_OB 180377c5fa8bSJia Liu #undef SHIFT_OB_ENV 180477c5fa8bSJia Liu 180577c5fa8bSJia Liu #endif 180677c5fa8bSJia Liu 180777c5fa8bSJia Liu #define SHIFT_PH(name, func) \ 180877c5fa8bSJia Liu target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \ 180977c5fa8bSJia Liu CPUMIPSState *env) \ 181077c5fa8bSJia Liu { \ 181177c5fa8bSJia Liu uint16_t rth, rtl; \ 181277c5fa8bSJia Liu \ 181377c5fa8bSJia Liu sa = sa & 0x0F; \ 181477c5fa8bSJia Liu \ 181577c5fa8bSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 181677c5fa8bSJia Liu \ 181777c5fa8bSJia Liu rth = mipsdsp_##func(rth, sa, env); \ 181877c5fa8bSJia Liu rtl = mipsdsp_##func(rtl, sa, env); \ 181977c5fa8bSJia Liu \ 182077c5fa8bSJia Liu return MIPSDSP_RETURN32_16(rth, rtl); \ 182177c5fa8bSJia Liu } 182277c5fa8bSJia Liu 182377c5fa8bSJia Liu SHIFT_PH(shll, lshift16); 182477c5fa8bSJia Liu SHIFT_PH(shll_s, sat16_lshift); 182577c5fa8bSJia Liu 182677c5fa8bSJia Liu #undef SHIFT_PH 182777c5fa8bSJia Liu 182877c5fa8bSJia Liu #if defined(TARGET_MIPS64) 182977c5fa8bSJia Liu #define SHIFT_QH(name, func) \ 183077c5fa8bSJia Liu target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \ 183177c5fa8bSJia Liu { \ 183277c5fa8bSJia Liu uint16_t rt3, rt2, rt1, rt0; \ 183377c5fa8bSJia Liu \ 183477c5fa8bSJia Liu sa = sa & 0x0F; \ 183577c5fa8bSJia Liu \ 183677c5fa8bSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 183777c5fa8bSJia Liu \ 183877c5fa8bSJia Liu rt3 = mipsdsp_##func(rt3, sa); \ 183977c5fa8bSJia Liu rt2 = mipsdsp_##func(rt2, sa); \ 184077c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa); \ 184177c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa); \ 184277c5fa8bSJia Liu \ 184377c5fa8bSJia Liu return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \ 184477c5fa8bSJia Liu } 184577c5fa8bSJia Liu 184677c5fa8bSJia Liu #define SHIFT_QH_ENV(name, func) \ 184777c5fa8bSJia Liu target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \ 184877c5fa8bSJia Liu CPUMIPSState *env) \ 184977c5fa8bSJia Liu { \ 185077c5fa8bSJia Liu uint16_t rt3, rt2, rt1, rt0; \ 185177c5fa8bSJia Liu \ 185277c5fa8bSJia Liu sa = sa & 0x0F; \ 185377c5fa8bSJia Liu \ 185477c5fa8bSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 185577c5fa8bSJia Liu \ 185677c5fa8bSJia Liu rt3 = mipsdsp_##func(rt3, sa, env); \ 185777c5fa8bSJia Liu rt2 = mipsdsp_##func(rt2, sa, env); \ 185877c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa, env); \ 185977c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa, env); \ 186077c5fa8bSJia Liu \ 186177c5fa8bSJia Liu return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \ 186277c5fa8bSJia Liu } 186377c5fa8bSJia Liu 186477c5fa8bSJia Liu SHIFT_QH_ENV(shll, lshift16); 186577c5fa8bSJia Liu SHIFT_QH_ENV(shll_s, sat16_lshift); 186677c5fa8bSJia Liu 186777c5fa8bSJia Liu SHIFT_QH(shrl, rshift_u16); 186877c5fa8bSJia Liu SHIFT_QH(shra, rashift16); 186977c5fa8bSJia Liu SHIFT_QH(shra_r, rnd16_rashift); 187077c5fa8bSJia Liu 187177c5fa8bSJia Liu #undef SHIFT_QH 187277c5fa8bSJia Liu #undef SHIFT_QH_ENV 187377c5fa8bSJia Liu 187477c5fa8bSJia Liu #endif 187577c5fa8bSJia Liu 187677c5fa8bSJia Liu #define SHIFT_W(name, func) \ 187777c5fa8bSJia Liu target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \ 187877c5fa8bSJia Liu { \ 187977c5fa8bSJia Liu uint32_t temp; \ 188077c5fa8bSJia Liu \ 188177c5fa8bSJia Liu sa = sa & 0x1F; \ 188277c5fa8bSJia Liu temp = mipsdsp_##func(rt, sa); \ 188377c5fa8bSJia Liu \ 188477c5fa8bSJia Liu return (target_long)(int32_t)temp; \ 188577c5fa8bSJia Liu } 188677c5fa8bSJia Liu 188777c5fa8bSJia Liu #define SHIFT_W_ENV(name, func) \ 188877c5fa8bSJia Liu target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \ 188977c5fa8bSJia Liu CPUMIPSState *env) \ 189077c5fa8bSJia Liu { \ 189177c5fa8bSJia Liu uint32_t temp; \ 189277c5fa8bSJia Liu \ 189377c5fa8bSJia Liu sa = sa & 0x1F; \ 189477c5fa8bSJia Liu temp = mipsdsp_##func(rt, sa, env); \ 189577c5fa8bSJia Liu \ 189677c5fa8bSJia Liu return (target_long)(int32_t)temp; \ 189777c5fa8bSJia Liu } 189877c5fa8bSJia Liu 189977c5fa8bSJia Liu SHIFT_W_ENV(shll_s, sat32_lshift); 190077c5fa8bSJia Liu SHIFT_W(shra_r, rnd32_rashift); 190177c5fa8bSJia Liu 190277c5fa8bSJia Liu #undef SHIFT_W 190377c5fa8bSJia Liu #undef SHIFT_W_ENV 190477c5fa8bSJia Liu 190577c5fa8bSJia Liu #if defined(TARGET_MIPS64) 190677c5fa8bSJia Liu #define SHIFT_PW(name, func) \ 190777c5fa8bSJia Liu target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \ 190877c5fa8bSJia Liu { \ 190977c5fa8bSJia Liu uint32_t rt1, rt0; \ 191077c5fa8bSJia Liu \ 191177c5fa8bSJia Liu sa = sa & 0x1F; \ 191277c5fa8bSJia Liu MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 191377c5fa8bSJia Liu \ 191477c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa); \ 191577c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa); \ 191677c5fa8bSJia Liu \ 191777c5fa8bSJia Liu return MIPSDSP_RETURN64_32(rt1, rt0); \ 191877c5fa8bSJia Liu } 191977c5fa8bSJia Liu 192077c5fa8bSJia Liu #define SHIFT_PW_ENV(name, func) \ 192177c5fa8bSJia Liu target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \ 192277c5fa8bSJia Liu CPUMIPSState *env) \ 192377c5fa8bSJia Liu { \ 192477c5fa8bSJia Liu uint32_t rt1, rt0; \ 192577c5fa8bSJia Liu \ 192677c5fa8bSJia Liu sa = sa & 0x1F; \ 192777c5fa8bSJia Liu MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 192877c5fa8bSJia Liu \ 192977c5fa8bSJia Liu rt1 = mipsdsp_##func(rt1, sa, env); \ 193077c5fa8bSJia Liu rt0 = mipsdsp_##func(rt0, sa, env); \ 193177c5fa8bSJia Liu \ 193277c5fa8bSJia Liu return MIPSDSP_RETURN64_32(rt1, rt0); \ 193377c5fa8bSJia Liu } 193477c5fa8bSJia Liu 193577c5fa8bSJia Liu SHIFT_PW_ENV(shll, lshift32); 193677c5fa8bSJia Liu SHIFT_PW_ENV(shll_s, sat32_lshift); 193777c5fa8bSJia Liu 193877c5fa8bSJia Liu SHIFT_PW(shra, rashift32); 193977c5fa8bSJia Liu SHIFT_PW(shra_r, rnd32_rashift); 194077c5fa8bSJia Liu 194177c5fa8bSJia Liu #undef SHIFT_PW 194277c5fa8bSJia Liu #undef SHIFT_PW_ENV 194377c5fa8bSJia Liu 194477c5fa8bSJia Liu #endif 194577c5fa8bSJia Liu 194677c5fa8bSJia Liu #define SHIFT_PH(name, func) \ 194777c5fa8bSJia Liu target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \ 194877c5fa8bSJia Liu { \ 194977c5fa8bSJia Liu uint16_t rth, rtl; \ 195077c5fa8bSJia Liu \ 195177c5fa8bSJia Liu sa = sa & 0x0F; \ 195277c5fa8bSJia Liu \ 195377c5fa8bSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 195477c5fa8bSJia Liu \ 195577c5fa8bSJia Liu rth = mipsdsp_##func(rth, sa); \ 195677c5fa8bSJia Liu rtl = mipsdsp_##func(rtl, sa); \ 195777c5fa8bSJia Liu \ 195877c5fa8bSJia Liu return MIPSDSP_RETURN32_16(rth, rtl); \ 195977c5fa8bSJia Liu } 196077c5fa8bSJia Liu 196177c5fa8bSJia Liu SHIFT_PH(shrl, rshift_u16); 196277c5fa8bSJia Liu SHIFT_PH(shra, rashift16); 196377c5fa8bSJia Liu SHIFT_PH(shra_r, rnd16_rashift); 196477c5fa8bSJia Liu 196577c5fa8bSJia Liu #undef SHIFT_PH 196677c5fa8bSJia Liu 1967a22260aeSJia Liu /** DSP Multiply Sub-class insns **/ 1968a22260aeSJia Liu /* Return value made up by two 16bits value. 1969a22260aeSJia Liu * FIXME give the macro a better name. 1970a22260aeSJia Liu */ 1971a22260aeSJia Liu #define MUL_RETURN32_16_PH(name, func, \ 1972a22260aeSJia Liu rsmov1, rsmov2, rsfilter, \ 1973a22260aeSJia Liu rtmov1, rtmov2, rtfilter) \ 1974a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 1975a22260aeSJia Liu CPUMIPSState *env) \ 1976a22260aeSJia Liu { \ 1977a22260aeSJia Liu uint16_t rsB, rsA, rtB, rtA; \ 1978a22260aeSJia Liu \ 1979a22260aeSJia Liu rsB = (rs >> rsmov1) & rsfilter; \ 1980a22260aeSJia Liu rsA = (rs >> rsmov2) & rsfilter; \ 1981a22260aeSJia Liu rtB = (rt >> rtmov1) & rtfilter; \ 1982a22260aeSJia Liu rtA = (rt >> rtmov2) & rtfilter; \ 1983a22260aeSJia Liu \ 1984a22260aeSJia Liu rsB = mipsdsp_##func(rsB, rtB, env); \ 1985a22260aeSJia Liu rsA = mipsdsp_##func(rsA, rtA, env); \ 1986a22260aeSJia Liu \ 1987a22260aeSJia Liu return MIPSDSP_RETURN32_16(rsB, rsA); \ 1988a22260aeSJia Liu } 1989a22260aeSJia Liu 1990a22260aeSJia Liu MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \ 1991a22260aeSJia Liu 24, 16, MIPSDSP_Q0, \ 1992a22260aeSJia Liu 16, 0, MIPSDSP_LO); 1993a22260aeSJia Liu MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \ 1994a22260aeSJia Liu 8, 0, MIPSDSP_Q0, \ 1995a22260aeSJia Liu 16, 0, MIPSDSP_LO); 1996a22260aeSJia Liu MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \ 1997a22260aeSJia Liu 16, 0, MIPSDSP_LO, \ 1998a22260aeSJia Liu 16, 0, MIPSDSP_LO); 1999a22260aeSJia Liu MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \ 2000a22260aeSJia Liu 16, 0, MIPSDSP_LO, \ 2001a22260aeSJia Liu 16, 0, MIPSDSP_LO); 2002a22260aeSJia Liu MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \ 2003a22260aeSJia Liu 16, 0, MIPSDSP_LO, \ 2004a22260aeSJia Liu 16, 0, MIPSDSP_LO); 2005a22260aeSJia Liu MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \ 2006a22260aeSJia Liu 16, 0, MIPSDSP_LO, \ 2007a22260aeSJia Liu 16, 0, MIPSDSP_LO); 2008a22260aeSJia Liu 2009a22260aeSJia Liu #undef MUL_RETURN32_16_PH 2010a22260aeSJia Liu 2011a22260aeSJia Liu #define MUL_RETURN32_32_ph(name, func, movbits) \ 2012a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2013a22260aeSJia Liu CPUMIPSState *env) \ 2014a22260aeSJia Liu { \ 2015a22260aeSJia Liu int16_t rsh, rth; \ 2016a22260aeSJia Liu int32_t temp; \ 2017a22260aeSJia Liu \ 2018a22260aeSJia Liu rsh = (rs >> movbits) & MIPSDSP_LO; \ 2019a22260aeSJia Liu rth = (rt >> movbits) & MIPSDSP_LO; \ 2020a22260aeSJia Liu temp = mipsdsp_##func(rsh, rth, env); \ 2021a22260aeSJia Liu \ 2022a22260aeSJia Liu return (target_long)(int32_t)temp; \ 2023a22260aeSJia Liu } 2024a22260aeSJia Liu 2025a22260aeSJia Liu MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16); 2026a22260aeSJia Liu MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0); 2027a22260aeSJia Liu 2028a22260aeSJia Liu #undef MUL_RETURN32_32_ph 2029a22260aeSJia Liu 2030a22260aeSJia Liu #define MUL_VOID_PH(name, use_ac_env) \ 2031a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2032a22260aeSJia Liu CPUMIPSState *env) \ 2033a22260aeSJia Liu { \ 2034a22260aeSJia Liu int16_t rsh, rsl, rth, rtl; \ 2035a22260aeSJia Liu int32_t tempB, tempA; \ 2036a22260aeSJia Liu int64_t acc, dotp; \ 2037a22260aeSJia Liu \ 2038a22260aeSJia Liu MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ 2039a22260aeSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 2040a22260aeSJia Liu \ 2041a22260aeSJia Liu if (use_ac_env == 1) { \ 2042a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ 2043a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env); \ 2044a22260aeSJia Liu } else { \ 2045a22260aeSJia Liu tempB = mipsdsp_mul_u16_u16(rsh, rth); \ 2046a22260aeSJia Liu tempA = mipsdsp_mul_u16_u16(rsl, rtl); \ 2047a22260aeSJia Liu } \ 2048a22260aeSJia Liu \ 2049a22260aeSJia Liu dotp = (int64_t)tempB - (int64_t)tempA; \ 2050a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2051a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2052a22260aeSJia Liu dotp = dotp + acc; \ 2053a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2054a22260aeSJia Liu ((dotp & MIPSDSP_LHI) >> 32); \ 2055a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO); \ 2056a22260aeSJia Liu } 2057a22260aeSJia Liu 2058a22260aeSJia Liu MUL_VOID_PH(mulsaq_s_w_ph, 1); 2059a22260aeSJia Liu MUL_VOID_PH(mulsa_w_ph, 0); 2060a22260aeSJia Liu 2061a22260aeSJia Liu #undef MUL_VOID_PH 2062a22260aeSJia Liu 2063a22260aeSJia Liu #if defined(TARGET_MIPS64) 2064a22260aeSJia Liu #define MUL_RETURN64_16_QH(name, func, \ 2065a22260aeSJia Liu rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \ 2066a22260aeSJia Liu rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \ 2067a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2068a22260aeSJia Liu CPUMIPSState *env) \ 2069a22260aeSJia Liu { \ 2070a22260aeSJia Liu uint16_t rs3, rs2, rs1, rs0; \ 2071a22260aeSJia Liu uint16_t rt3, rt2, rt1, rt0; \ 2072a22260aeSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 2073a22260aeSJia Liu \ 2074a22260aeSJia Liu rs3 = (rs >> rsmov1) & rsfilter; \ 2075a22260aeSJia Liu rs2 = (rs >> rsmov2) & rsfilter; \ 2076a22260aeSJia Liu rs1 = (rs >> rsmov3) & rsfilter; \ 2077a22260aeSJia Liu rs0 = (rs >> rsmov4) & rsfilter; \ 2078a22260aeSJia Liu rt3 = (rt >> rtmov1) & rtfilter; \ 2079a22260aeSJia Liu rt2 = (rt >> rtmov2) & rtfilter; \ 2080a22260aeSJia Liu rt1 = (rt >> rtmov3) & rtfilter; \ 2081a22260aeSJia Liu rt0 = (rt >> rtmov4) & rtfilter; \ 2082a22260aeSJia Liu \ 2083a22260aeSJia Liu tempD = mipsdsp_##func(rs3, rt3, env); \ 2084a22260aeSJia Liu tempC = mipsdsp_##func(rs2, rt2, env); \ 2085a22260aeSJia Liu tempB = mipsdsp_##func(rs1, rt1, env); \ 2086a22260aeSJia Liu tempA = mipsdsp_##func(rs0, rt0, env); \ 2087a22260aeSJia Liu \ 2088a22260aeSJia Liu return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 2089a22260aeSJia Liu } 2090a22260aeSJia Liu 2091a22260aeSJia Liu MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \ 2092a22260aeSJia Liu 56, 48, 40, 32, MIPSDSP_Q0, \ 2093a22260aeSJia Liu 48, 32, 16, 0, MIPSDSP_LO); 2094a22260aeSJia Liu MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \ 2095a22260aeSJia Liu 24, 16, 8, 0, MIPSDSP_Q0, \ 2096a22260aeSJia Liu 48, 32, 16, 0, MIPSDSP_LO); 2097a22260aeSJia Liu MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \ 2098a22260aeSJia Liu 48, 32, 16, 0, MIPSDSP_LO, \ 2099a22260aeSJia Liu 48, 32, 16, 0, MIPSDSP_LO); 2100a22260aeSJia Liu 2101a22260aeSJia Liu #undef MUL_RETURN64_16_QH 2102a22260aeSJia Liu 2103a22260aeSJia Liu #define MUL_RETURN64_32_QH(name, \ 2104a22260aeSJia Liu rsmov1, rsmov2, \ 2105a22260aeSJia Liu rtmov1, rtmov2) \ 2106a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2107a22260aeSJia Liu CPUMIPSState *env) \ 2108a22260aeSJia Liu { \ 2109a22260aeSJia Liu uint16_t rsB, rsA; \ 2110a22260aeSJia Liu uint16_t rtB, rtA; \ 2111a22260aeSJia Liu uint32_t tempB, tempA; \ 2112a22260aeSJia Liu \ 2113a22260aeSJia Liu rsB = (rs >> rsmov1) & MIPSDSP_LO; \ 2114a22260aeSJia Liu rsA = (rs >> rsmov2) & MIPSDSP_LO; \ 2115a22260aeSJia Liu rtB = (rt >> rtmov1) & MIPSDSP_LO; \ 2116a22260aeSJia Liu rtA = (rt >> rtmov2) & MIPSDSP_LO; \ 2117a22260aeSJia Liu \ 2118a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env); \ 2119a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env); \ 2120a22260aeSJia Liu \ 2121a22260aeSJia Liu return ((uint64_t)tempB << 32) | (uint64_t)tempA; \ 2122a22260aeSJia Liu } 2123a22260aeSJia Liu 2124a22260aeSJia Liu MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32); 2125a22260aeSJia Liu MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0); 2126a22260aeSJia Liu 2127a22260aeSJia Liu #undef MUL_RETURN64_32_QH 2128a22260aeSJia Liu 2129a22260aeSJia Liu void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac, 2130a22260aeSJia Liu CPUMIPSState *env) 2131a22260aeSJia Liu { 2132a22260aeSJia Liu int16_t rs3, rs2, rs1, rs0; 2133a22260aeSJia Liu int16_t rt3, rt2, rt1, rt0; 2134a22260aeSJia Liu int32_t tempD, tempC, tempB, tempA; 2135a22260aeSJia Liu int64_t acc[2]; 2136a22260aeSJia Liu int64_t temp[2]; 2137a22260aeSJia Liu int64_t temp_sum; 2138a22260aeSJia Liu 2139a22260aeSJia Liu MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); 2140a22260aeSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); 2141a22260aeSJia Liu 2142a22260aeSJia Liu tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); 2143a22260aeSJia Liu tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); 2144a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); 2145a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); 2146a22260aeSJia Liu 2147a22260aeSJia Liu temp[0] = ((int32_t)tempD - (int32_t)tempC) + 2148a22260aeSJia Liu ((int32_t)tempB - (int32_t)tempA); 2149a22260aeSJia Liu temp[0] = (int64_t)(temp[0] << 30) >> 30; 2150a22260aeSJia Liu if (((temp[0] >> 33) & 0x01) == 0) { 2151a22260aeSJia Liu temp[1] = 0x00; 2152a22260aeSJia Liu } else { 2153a22260aeSJia Liu temp[1] = ~0ull; 2154a22260aeSJia Liu } 2155a22260aeSJia Liu 2156a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; 2157a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; 2158a22260aeSJia Liu 2159a22260aeSJia Liu temp_sum = acc[0] + temp[0]; 2160a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && 2161a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { 2162a22260aeSJia Liu acc[1] += 1; 2163a22260aeSJia Liu } 2164a22260aeSJia Liu acc[0] = temp_sum; 2165a22260aeSJia Liu acc[1] += temp[1]; 2166a22260aeSJia Liu 2167a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; 2168a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; 2169a22260aeSJia Liu } 2170a22260aeSJia Liu #endif 2171a22260aeSJia Liu 2172a22260aeSJia Liu #define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ 2173a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2174a22260aeSJia Liu CPUMIPSState *env) \ 2175a22260aeSJia Liu { \ 2176a22260aeSJia Liu uint8_t rs3, rs2; \ 2177a22260aeSJia Liu uint8_t rt3, rt2; \ 2178a22260aeSJia Liu uint16_t tempB, tempA; \ 2179a22260aeSJia Liu uint64_t tempC, dotp; \ 2180a22260aeSJia Liu \ 2181a22260aeSJia Liu rs3 = (rs >> rsmov1) & MIPSDSP_Q0; \ 2182a22260aeSJia Liu rs2 = (rs >> rsmov2) & MIPSDSP_Q0; \ 2183a22260aeSJia Liu rt3 = (rt >> rtmov1) & MIPSDSP_Q0; \ 2184a22260aeSJia Liu rt2 = (rt >> rtmov2) & MIPSDSP_Q0; \ 2185a22260aeSJia Liu tempB = mipsdsp_##func(rs3, rt3); \ 2186a22260aeSJia Liu tempA = mipsdsp_##func(rs2, rt2); \ 2187a22260aeSJia Liu dotp = (int64_t)tempB + (int64_t)tempA; \ 2188a22260aeSJia Liu if (is_add) { \ 2189a22260aeSJia Liu tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \ 2190a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \ 2191a22260aeSJia Liu + dotp; \ 2192a22260aeSJia Liu } else { \ 2193a22260aeSJia Liu tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \ 2194a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \ 2195a22260aeSJia Liu - dotp; \ 2196a22260aeSJia Liu } \ 2197a22260aeSJia Liu \ 2198a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2199a22260aeSJia Liu ((tempC & MIPSDSP_LHI) >> 32); \ 2200a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \ 2201a22260aeSJia Liu } 2202a22260aeSJia Liu 2203a22260aeSJia Liu DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16); 2204a22260aeSJia Liu DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0); 2205a22260aeSJia Liu DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16); 2206a22260aeSJia Liu DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0); 2207a22260aeSJia Liu 2208a22260aeSJia Liu #undef DP_QB 2209a22260aeSJia Liu 2210a22260aeSJia Liu #if defined(TARGET_MIPS64) 2211a22260aeSJia Liu #define DP_OB(name, add_sub, \ 2212a22260aeSJia Liu rsmov1, rsmov2, rsmov3, rsmov4, \ 2213a22260aeSJia Liu rtmov1, rtmov2, rtmov3, rtmov4) \ 2214a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2215a22260aeSJia Liu CPUMIPSState *env) \ 2216a22260aeSJia Liu { \ 2217a22260aeSJia Liu uint8_t rsD, rsC, rsB, rsA; \ 2218a22260aeSJia Liu uint8_t rtD, rtC, rtB, rtA; \ 2219a22260aeSJia Liu uint16_t tempD, tempC, tempB, tempA; \ 2220a22260aeSJia Liu uint64_t temp[2]; \ 2221a22260aeSJia Liu uint64_t acc[2]; \ 2222a22260aeSJia Liu uint64_t temp_sum; \ 2223a22260aeSJia Liu \ 2224a22260aeSJia Liu temp[0] = 0; \ 2225a22260aeSJia Liu temp[1] = 0; \ 2226a22260aeSJia Liu \ 2227a22260aeSJia Liu rsD = (rs >> rsmov1) & MIPSDSP_Q0; \ 2228a22260aeSJia Liu rsC = (rs >> rsmov2) & MIPSDSP_Q0; \ 2229a22260aeSJia Liu rsB = (rs >> rsmov3) & MIPSDSP_Q0; \ 2230a22260aeSJia Liu rsA = (rs >> rsmov4) & MIPSDSP_Q0; \ 2231a22260aeSJia Liu rtD = (rt >> rtmov1) & MIPSDSP_Q0; \ 2232a22260aeSJia Liu rtC = (rt >> rtmov2) & MIPSDSP_Q0; \ 2233a22260aeSJia Liu rtB = (rt >> rtmov3) & MIPSDSP_Q0; \ 2234a22260aeSJia Liu rtA = (rt >> rtmov4) & MIPSDSP_Q0; \ 2235a22260aeSJia Liu \ 2236a22260aeSJia Liu tempD = mipsdsp_mul_u8_u8(rsD, rtD); \ 2237a22260aeSJia Liu tempC = mipsdsp_mul_u8_u8(rsC, rtC); \ 2238a22260aeSJia Liu tempB = mipsdsp_mul_u8_u8(rsB, rtB); \ 2239a22260aeSJia Liu tempA = mipsdsp_mul_u8_u8(rsA, rtA); \ 2240a22260aeSJia Liu \ 2241a22260aeSJia Liu temp[0] = (uint64_t)tempD + (uint64_t)tempC + \ 2242a22260aeSJia Liu (uint64_t)tempB + (uint64_t)tempA; \ 2243a22260aeSJia Liu \ 2244a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 2245a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 2246a22260aeSJia Liu \ 2247a22260aeSJia Liu if (add_sub) { \ 2248a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 2249a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2250a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2251a22260aeSJia Liu acc[1] += 1; \ 2252a22260aeSJia Liu } \ 2253a22260aeSJia Liu temp[0] = temp_sum; \ 2254a22260aeSJia Liu temp[1] = acc[1] + temp[1]; \ 2255a22260aeSJia Liu } else { \ 2256a22260aeSJia Liu temp_sum = acc[0] - temp[0]; \ 2257a22260aeSJia Liu if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ 2258a22260aeSJia Liu acc[1] -= 1; \ 2259a22260aeSJia Liu } \ 2260a22260aeSJia Liu temp[0] = temp_sum; \ 2261a22260aeSJia Liu temp[1] = acc[1] - temp[1]; \ 2262a22260aeSJia Liu } \ 2263a22260aeSJia Liu \ 2264a22260aeSJia Liu env->active_tc.HI[ac] = temp[1]; \ 2265a22260aeSJia Liu env->active_tc.LO[ac] = temp[0]; \ 2266a22260aeSJia Liu } 2267a22260aeSJia Liu 2268a22260aeSJia Liu DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32); 2269a22260aeSJia Liu DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0); 2270a22260aeSJia Liu DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32); 2271a22260aeSJia Liu DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0); 2272a22260aeSJia Liu 2273a22260aeSJia Liu #undef DP_OB 2274a22260aeSJia Liu #endif 2275a22260aeSJia Liu 2276a22260aeSJia Liu #define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ 2277a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2278a22260aeSJia Liu CPUMIPSState *env) \ 2279a22260aeSJia Liu { \ 2280da1a4cefSPetar Jovanovic int16_t rsB, rsA, rtB, rtA; \ 2281a22260aeSJia Liu int32_t tempA, tempB; \ 2282a22260aeSJia Liu int64_t acc; \ 2283a22260aeSJia Liu \ 2284a22260aeSJia Liu rsB = (rs >> rsmov1) & MIPSDSP_LO; \ 2285a22260aeSJia Liu rsA = (rs >> rsmov2) & MIPSDSP_LO; \ 2286a22260aeSJia Liu rtB = (rt >> rtmov1) & MIPSDSP_LO; \ 2287a22260aeSJia Liu rtA = (rt >> rtmov2) & MIPSDSP_LO; \ 2288a22260aeSJia Liu \ 2289a22260aeSJia Liu tempB = (int32_t)rsB * (int32_t)rtB; \ 2290a22260aeSJia Liu tempA = (int32_t)rsA * (int32_t)rtA; \ 2291a22260aeSJia Liu \ 2292a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2293a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2294a22260aeSJia Liu \ 2295a22260aeSJia Liu if (is_add) { \ 2296a22260aeSJia Liu acc = acc + ((int64_t)tempB + (int64_t)tempA); \ 2297a22260aeSJia Liu } else { \ 2298a22260aeSJia Liu acc = acc - ((int64_t)tempB + (int64_t)tempA); \ 2299a22260aeSJia Liu } \ 2300a22260aeSJia Liu \ 2301a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \ 2302a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO); \ 2303a22260aeSJia Liu } 2304a22260aeSJia Liu 2305a22260aeSJia Liu DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0); 2306a22260aeSJia Liu DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16); 2307a22260aeSJia Liu DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0); 2308a22260aeSJia Liu DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16); 2309a22260aeSJia Liu #undef DP_NOFUNC_PH 2310a22260aeSJia Liu 2311a22260aeSJia Liu #define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ 2312a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2313a22260aeSJia Liu CPUMIPSState *env) \ 2314a22260aeSJia Liu { \ 2315a22260aeSJia Liu int16_t rsB, rsA, rtB, rtA; \ 2316a22260aeSJia Liu int32_t tempB, tempA; \ 2317a22260aeSJia Liu int64_t acc, dotp; \ 2318a22260aeSJia Liu \ 2319a22260aeSJia Liu rsB = (rs >> rsmov1) & MIPSDSP_LO; \ 2320a22260aeSJia Liu rsA = (rs >> rsmov2) & MIPSDSP_LO; \ 2321a22260aeSJia Liu rtB = (rt >> rtmov1) & MIPSDSP_LO; \ 2322a22260aeSJia Liu rtA = (rt >> rtmov2) & MIPSDSP_LO; \ 2323a22260aeSJia Liu \ 2324a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env); \ 2325a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env); \ 2326a22260aeSJia Liu \ 2327a22260aeSJia Liu dotp = (int64_t)tempB + (int64_t)tempA; \ 2328a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2329a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2330a22260aeSJia Liu \ 2331a22260aeSJia Liu if (is_add) { \ 2332a22260aeSJia Liu acc = acc + dotp; \ 2333a22260aeSJia Liu } else { \ 2334a22260aeSJia Liu acc = acc - dotp; \ 2335a22260aeSJia Liu } \ 2336a22260aeSJia Liu \ 2337a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2338a22260aeSJia Liu ((acc & MIPSDSP_LHI) >> 32); \ 2339a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t) \ 2340a22260aeSJia Liu (acc & MIPSDSP_LLO); \ 2341a22260aeSJia Liu } 2342a22260aeSJia Liu 2343a22260aeSJia Liu DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0); 2344a22260aeSJia Liu DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16); 2345a22260aeSJia Liu DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0); 2346a22260aeSJia Liu DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16); 2347a22260aeSJia Liu 2348a22260aeSJia Liu #undef DP_HASFUNC_PH 2349a22260aeSJia Liu 2350a22260aeSJia Liu #define DP_128OPERATION_PH(name, is_add) \ 2351a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2352a22260aeSJia Liu CPUMIPSState *env) \ 2353a22260aeSJia Liu { \ 2354a22260aeSJia Liu int16_t rsh, rsl, rth, rtl; \ 2355a22260aeSJia Liu int32_t tempB, tempA, tempC62_31, tempC63; \ 2356a22260aeSJia Liu int64_t acc, dotp, tempC; \ 2357a22260aeSJia Liu \ 2358a22260aeSJia Liu MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ 2359a22260aeSJia Liu MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 2360a22260aeSJia Liu \ 2361a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env); \ 2362a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env); \ 2363a22260aeSJia Liu \ 2364a22260aeSJia Liu dotp = (int64_t)tempB + (int64_t)tempA; \ 2365a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2366a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2367a22260aeSJia Liu if (is_add) { \ 2368a22260aeSJia Liu tempC = acc + dotp; \ 2369a22260aeSJia Liu } else { \ 2370a22260aeSJia Liu tempC = acc - dotp; \ 2371a22260aeSJia Liu } \ 2372a22260aeSJia Liu tempC63 = (tempC >> 63) & 0x01; \ 2373a22260aeSJia Liu tempC62_31 = (tempC >> 31) & 0xFFFFFFFF; \ 2374a22260aeSJia Liu \ 2375a22260aeSJia Liu if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) { \ 2376a22260aeSJia Liu tempC = 0x7FFFFFFF; \ 2377a22260aeSJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); \ 2378a22260aeSJia Liu } \ 2379a22260aeSJia Liu \ 2380a22260aeSJia Liu if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) { \ 2381a22260aeSJia Liu tempC = (int64_t)(int32_t)0x80000000; \ 2382a22260aeSJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); \ 2383a22260aeSJia Liu } \ 2384a22260aeSJia Liu \ 2385a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2386a22260aeSJia Liu ((tempC & MIPSDSP_LHI) >> 32); \ 2387a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t) \ 2388a22260aeSJia Liu (tempC & MIPSDSP_LLO); \ 2389a22260aeSJia Liu } 2390a22260aeSJia Liu 2391a22260aeSJia Liu DP_128OPERATION_PH(dpaqx_sa_w_ph, 1); 2392a22260aeSJia Liu DP_128OPERATION_PH(dpsqx_sa_w_ph, 0); 2393a22260aeSJia Liu 2394a22260aeSJia Liu #undef DP_128OPERATION_HP 2395a22260aeSJia Liu 2396a22260aeSJia Liu #if defined(TARGET_MIPS64) 2397a22260aeSJia Liu #define DP_QH(name, is_add, use_ac_env) \ 2398a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2399a22260aeSJia Liu CPUMIPSState *env) \ 2400a22260aeSJia Liu { \ 2401a22260aeSJia Liu int32_t rs3, rs2, rs1, rs0; \ 2402a22260aeSJia Liu int32_t rt3, rt2, rt1, rt0; \ 2403a22260aeSJia Liu int32_t tempD, tempC, tempB, tempA; \ 2404a22260aeSJia Liu int64_t acc[2]; \ 2405a22260aeSJia Liu int64_t temp[2]; \ 2406a22260aeSJia Liu int64_t temp_sum; \ 2407a22260aeSJia Liu \ 2408a22260aeSJia Liu MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ 2409a22260aeSJia Liu MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 2410a22260aeSJia Liu \ 2411a22260aeSJia Liu if (use_ac_env) { \ 2412a22260aeSJia Liu tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); \ 2413a22260aeSJia Liu tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); \ 2414a22260aeSJia Liu tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); \ 2415a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); \ 2416a22260aeSJia Liu } else { \ 2417a22260aeSJia Liu tempD = mipsdsp_mul_u16_u16(rs3, rt3); \ 2418a22260aeSJia Liu tempC = mipsdsp_mul_u16_u16(rs2, rt2); \ 2419a22260aeSJia Liu tempB = mipsdsp_mul_u16_u16(rs1, rt1); \ 2420a22260aeSJia Liu tempA = mipsdsp_mul_u16_u16(rs0, rt0); \ 2421a22260aeSJia Liu } \ 2422a22260aeSJia Liu \ 2423a22260aeSJia Liu temp[0] = (int64_t)tempD + (int64_t)tempC + \ 2424a22260aeSJia Liu (int64_t)tempB + (int64_t)tempA; \ 2425a22260aeSJia Liu \ 2426a22260aeSJia Liu if (temp[0] >= 0) { \ 2427a22260aeSJia Liu temp[1] = 0; \ 2428a22260aeSJia Liu } else { \ 2429a22260aeSJia Liu temp[1] = ~0ull; \ 2430a22260aeSJia Liu } \ 2431a22260aeSJia Liu \ 2432a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 2433a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 2434a22260aeSJia Liu \ 2435a22260aeSJia Liu if (is_add) { \ 2436a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 2437a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2438a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2439a22260aeSJia Liu acc[1] = acc[1] + 1; \ 2440a22260aeSJia Liu } \ 2441a22260aeSJia Liu temp[0] = temp_sum; \ 2442a22260aeSJia Liu temp[1] = acc[1] + temp[1]; \ 2443a22260aeSJia Liu } else { \ 2444a22260aeSJia Liu temp_sum = acc[0] - temp[0]; \ 2445a22260aeSJia Liu if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ 2446a22260aeSJia Liu acc[1] = acc[1] - 1; \ 2447a22260aeSJia Liu } \ 2448a22260aeSJia Liu temp[0] = temp_sum; \ 2449a22260aeSJia Liu temp[1] = acc[1] - temp[1]; \ 2450a22260aeSJia Liu } \ 2451a22260aeSJia Liu \ 2452a22260aeSJia Liu env->active_tc.HI[ac] = temp[1]; \ 2453a22260aeSJia Liu env->active_tc.LO[ac] = temp[0]; \ 2454a22260aeSJia Liu } 2455a22260aeSJia Liu 2456a22260aeSJia Liu DP_QH(dpa_w_qh, 1, 0); 2457a22260aeSJia Liu DP_QH(dpaq_s_w_qh, 1, 1); 2458a22260aeSJia Liu DP_QH(dps_w_qh, 0, 0); 2459a22260aeSJia Liu DP_QH(dpsq_s_w_qh, 0, 1); 2460a22260aeSJia Liu 2461a22260aeSJia Liu #undef DP_QH 2462a22260aeSJia Liu 2463a22260aeSJia Liu #endif 2464a22260aeSJia Liu 2465a22260aeSJia Liu #define DP_L_W(name, is_add) \ 2466a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2467a22260aeSJia Liu CPUMIPSState *env) \ 2468a22260aeSJia Liu { \ 2469a22260aeSJia Liu int32_t temp63; \ 2470a22260aeSJia Liu int64_t dotp, acc; \ 2471a22260aeSJia Liu uint64_t temp; \ 247220c334a7SPetar Jovanovic bool overflow; \ 2473a22260aeSJia Liu \ 2474a22260aeSJia Liu dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \ 2475a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2476a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 247720c334a7SPetar Jovanovic if (is_add) { \ 247820c334a7SPetar Jovanovic temp = acc + dotp; \ 247920c334a7SPetar Jovanovic overflow = MIPSDSP_OVERFLOW_ADD((uint64_t)acc, (uint64_t)dotp, \ 248020c334a7SPetar Jovanovic temp, (0x01ull << 63)); \ 248120c334a7SPetar Jovanovic } else { \ 248220c334a7SPetar Jovanovic temp = acc - dotp; \ 248320c334a7SPetar Jovanovic overflow = MIPSDSP_OVERFLOW_SUB((uint64_t)acc, (uint64_t)dotp, \ 248420c334a7SPetar Jovanovic temp, (0x01ull << 63)); \ 2485a22260aeSJia Liu } \ 2486a22260aeSJia Liu \ 248720c334a7SPetar Jovanovic if (overflow) { \ 2488a22260aeSJia Liu temp63 = (temp >> 63) & 0x01; \ 2489a22260aeSJia Liu if (temp63 == 1) { \ 2490a22260aeSJia Liu temp = (0x01ull << 63) - 1; \ 2491a22260aeSJia Liu } else { \ 2492a22260aeSJia Liu temp = 0x01ull << 63; \ 2493a22260aeSJia Liu } \ 2494a22260aeSJia Liu \ 2495a22260aeSJia Liu set_DSPControl_overflow_flag(1, 16 + ac, env); \ 2496a22260aeSJia Liu } \ 2497a22260aeSJia Liu \ 2498a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2499a22260aeSJia Liu ((temp & MIPSDSP_LHI) >> 32); \ 2500a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t) \ 2501a22260aeSJia Liu (temp & MIPSDSP_LLO); \ 2502a22260aeSJia Liu } 2503a22260aeSJia Liu 2504a22260aeSJia Liu DP_L_W(dpaq_sa_l_w, 1); 2505a22260aeSJia Liu DP_L_W(dpsq_sa_l_w, 0); 2506a22260aeSJia Liu 2507a22260aeSJia Liu #undef DP_L_W 2508a22260aeSJia Liu 2509a22260aeSJia Liu #if defined(TARGET_MIPS64) 2510a22260aeSJia Liu #define DP_L_PW(name, func) \ 2511a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2512a22260aeSJia Liu CPUMIPSState *env) \ 2513a22260aeSJia Liu { \ 2514a22260aeSJia Liu int32_t rs1, rs0; \ 2515a22260aeSJia Liu int32_t rt1, rt0; \ 2516a22260aeSJia Liu int64_t tempB[2], tempA[2]; \ 2517a22260aeSJia Liu int64_t temp[2]; \ 2518a22260aeSJia Liu int64_t acc[2]; \ 2519a22260aeSJia Liu int64_t temp_sum; \ 2520a22260aeSJia Liu \ 2521a22260aeSJia Liu temp[0] = 0; \ 2522a22260aeSJia Liu temp[1] = 0; \ 2523a22260aeSJia Liu \ 2524a22260aeSJia Liu MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ 2525a22260aeSJia Liu MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 2526a22260aeSJia Liu \ 2527a22260aeSJia Liu tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); \ 2528a22260aeSJia Liu tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); \ 2529a22260aeSJia Liu \ 2530a22260aeSJia Liu if (tempB[0] >= 0) { \ 2531a22260aeSJia Liu tempB[1] = 0x00; \ 2532a22260aeSJia Liu } else { \ 2533a22260aeSJia Liu tempB[1] = ~0ull; \ 2534a22260aeSJia Liu } \ 2535a22260aeSJia Liu \ 2536a22260aeSJia Liu if (tempA[0] >= 0) { \ 2537a22260aeSJia Liu tempA[1] = 0x00; \ 2538a22260aeSJia Liu } else { \ 2539a22260aeSJia Liu tempA[1] = ~0ull; \ 2540a22260aeSJia Liu } \ 2541a22260aeSJia Liu \ 2542a22260aeSJia Liu temp_sum = tempB[0] + tempA[0]; \ 2543a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)tempB[0]) && \ 2544a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)tempA[0])) { \ 2545a22260aeSJia Liu temp[1] += 1; \ 2546a22260aeSJia Liu } \ 2547a22260aeSJia Liu temp[0] = temp_sum; \ 2548a22260aeSJia Liu temp[1] += tempB[1] + tempA[1]; \ 2549a22260aeSJia Liu \ 2550a22260aeSJia Liu mipsdsp_##func(acc, ac, temp, env); \ 2551a22260aeSJia Liu \ 2552a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; \ 2553a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; \ 2554a22260aeSJia Liu } 2555a22260aeSJia Liu 2556a22260aeSJia Liu DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63); 2557a22260aeSJia Liu DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63); 2558a22260aeSJia Liu 2559a22260aeSJia Liu #undef DP_L_PW 2560a22260aeSJia Liu 2561a22260aeSJia Liu void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac, 2562a22260aeSJia Liu CPUMIPSState *env) 2563a22260aeSJia Liu { 2564a22260aeSJia Liu int32_t rs1, rs0; 2565a22260aeSJia Liu int32_t rt1, rt0; 2566a22260aeSJia Liu int64_t tempB[2], tempA[2]; 2567a22260aeSJia Liu int64_t temp[2]; 2568a22260aeSJia Liu int64_t acc[2]; 2569a22260aeSJia Liu int64_t temp_sum; 2570a22260aeSJia Liu 2571a22260aeSJia Liu rs1 = (rs >> 32) & MIPSDSP_LLO; 2572a22260aeSJia Liu rs0 = rs & MIPSDSP_LLO; 2573a22260aeSJia Liu rt1 = (rt >> 32) & MIPSDSP_LLO; 2574a22260aeSJia Liu rt0 = rt & MIPSDSP_LLO; 2575a22260aeSJia Liu 2576a22260aeSJia Liu tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); 2577a22260aeSJia Liu tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); 2578a22260aeSJia Liu 2579a22260aeSJia Liu if (tempB[0] >= 0) { 2580a22260aeSJia Liu tempB[1] = 0x00; 2581a22260aeSJia Liu } else { 2582a22260aeSJia Liu tempB[1] = ~0ull; 2583a22260aeSJia Liu } 2584a22260aeSJia Liu 2585a22260aeSJia Liu if (tempA[0] >= 0) { 2586a22260aeSJia Liu tempA[1] = 0x00; 2587a22260aeSJia Liu } else { 2588a22260aeSJia Liu tempA[1] = ~0ull; 2589a22260aeSJia Liu } 2590a22260aeSJia Liu 2591a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; 2592a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; 2593a22260aeSJia Liu 2594a22260aeSJia Liu temp_sum = tempB[0] - tempA[0]; 2595a22260aeSJia Liu if ((uint64_t)temp_sum > (uint64_t)tempB[0]) { 2596a22260aeSJia Liu tempB[1] -= 1; 2597a22260aeSJia Liu } 2598a22260aeSJia Liu temp[0] = temp_sum; 2599a22260aeSJia Liu temp[1] = tempB[1] - tempA[1]; 2600a22260aeSJia Liu 2601a22260aeSJia Liu if ((temp[1] & 0x01) == 0) { 2602a22260aeSJia Liu temp[1] = 0x00; 2603a22260aeSJia Liu } else { 2604a22260aeSJia Liu temp[1] = ~0ull; 2605a22260aeSJia Liu } 2606a22260aeSJia Liu 2607a22260aeSJia Liu temp_sum = acc[0] + temp[0]; 2608a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && 2609a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { 2610a22260aeSJia Liu acc[1] += 1; 2611a22260aeSJia Liu } 2612a22260aeSJia Liu acc[0] = temp_sum; 2613a22260aeSJia Liu acc[1] += temp[1]; 2614a22260aeSJia Liu 2615a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; 2616a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; 2617a22260aeSJia Liu } 2618a22260aeSJia Liu #endif 2619a22260aeSJia Liu 2620a22260aeSJia Liu #define MAQ_S_W(name, mov) \ 2621a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2622a22260aeSJia Liu CPUMIPSState *env) \ 2623a22260aeSJia Liu { \ 2624a22260aeSJia Liu int16_t rsh, rth; \ 2625a22260aeSJia Liu int32_t tempA; \ 2626a22260aeSJia Liu int64_t tempL, acc; \ 2627a22260aeSJia Liu \ 2628a22260aeSJia Liu rsh = (rs >> mov) & MIPSDSP_LO; \ 2629a22260aeSJia Liu rth = (rt >> mov) & MIPSDSP_LO; \ 2630a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ 2631a22260aeSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2632a22260aeSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2633a22260aeSJia Liu tempL = (int64_t)tempA + acc; \ 2634a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t) \ 2635a22260aeSJia Liu ((tempL & MIPSDSP_LHI) >> 32); \ 2636a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t) \ 2637a22260aeSJia Liu (tempL & MIPSDSP_LLO); \ 2638a22260aeSJia Liu } 2639a22260aeSJia Liu 2640a22260aeSJia Liu MAQ_S_W(maq_s_w_phl, 16); 2641a22260aeSJia Liu MAQ_S_W(maq_s_w_phr, 0); 2642a22260aeSJia Liu 2643a22260aeSJia Liu #undef MAQ_S_W 2644a22260aeSJia Liu 2645a22260aeSJia Liu #define MAQ_SA_W(name, mov) \ 2646a22260aeSJia Liu void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2647a22260aeSJia Liu CPUMIPSState *env) \ 2648a22260aeSJia Liu { \ 2649a22260aeSJia Liu int16_t rsh, rth; \ 2650a22260aeSJia Liu int32_t tempA; \ 2651a22260aeSJia Liu \ 2652a22260aeSJia Liu rsh = (rs >> mov) & MIPSDSP_LO; \ 2653a22260aeSJia Liu rth = (rt >> mov) & MIPSDSP_LO; \ 2654a22260aeSJia Liu tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ 2655a22260aeSJia Liu tempA = mipsdsp_sat32_acc_q31(ac, tempA, env); \ 2656a22260aeSJia Liu \ 2657a22260aeSJia Liu env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA & \ 2658a22260aeSJia Liu MIPSDSP_LHI) >> 32); \ 2659a22260aeSJia Liu env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA & \ 2660a22260aeSJia Liu MIPSDSP_LLO); \ 2661a22260aeSJia Liu } 2662a22260aeSJia Liu 2663a22260aeSJia Liu MAQ_SA_W(maq_sa_w_phl, 16); 2664a22260aeSJia Liu MAQ_SA_W(maq_sa_w_phr, 0); 2665a22260aeSJia Liu 2666a22260aeSJia Liu #undef MAQ_SA_W 2667a22260aeSJia Liu 2668a22260aeSJia Liu #define MULQ_W(name, addvar) \ 2669a22260aeSJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2670a22260aeSJia Liu CPUMIPSState *env) \ 2671a22260aeSJia Liu { \ 2672a345481bSPetar Jovanovic int32_t rs_t, rt_t; \ 2673a22260aeSJia Liu int32_t tempI; \ 2674a22260aeSJia Liu int64_t tempL; \ 2675a22260aeSJia Liu \ 2676a22260aeSJia Liu rs_t = rs & MIPSDSP_LLO; \ 2677a22260aeSJia Liu rt_t = rt & MIPSDSP_LLO; \ 2678a22260aeSJia Liu \ 2679a22260aeSJia Liu if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) { \ 2680a22260aeSJia Liu tempL = 0x7FFFFFFF00000000ull; \ 2681a22260aeSJia Liu set_DSPControl_overflow_flag(1, 21, env); \ 2682a22260aeSJia Liu } else { \ 2683a22260aeSJia Liu tempL = ((int64_t)rs_t * (int64_t)rt_t) << 1; \ 2684a22260aeSJia Liu tempL += addvar; \ 2685a22260aeSJia Liu } \ 2686a22260aeSJia Liu tempI = (tempL & MIPSDSP_LHI) >> 32; \ 2687a22260aeSJia Liu \ 2688a22260aeSJia Liu return (target_long)(int32_t)tempI; \ 2689a22260aeSJia Liu } 2690a22260aeSJia Liu 2691a22260aeSJia Liu MULQ_W(mulq_s_w, 0); 2692a22260aeSJia Liu MULQ_W(mulq_rs_w, 0x80000000ull); 2693a22260aeSJia Liu 2694a22260aeSJia Liu #undef MULQ_W 2695a22260aeSJia Liu 2696a22260aeSJia Liu #if defined(TARGET_MIPS64) 2697a22260aeSJia Liu 2698a22260aeSJia Liu #define MAQ_S_W_QH(name, mov) \ 2699a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2700a22260aeSJia Liu CPUMIPSState *env) \ 2701a22260aeSJia Liu { \ 2702a22260aeSJia Liu int16_t rs_t, rt_t; \ 2703a22260aeSJia Liu int32_t temp_mul; \ 2704a22260aeSJia Liu int64_t temp[2]; \ 2705a22260aeSJia Liu int64_t acc[2]; \ 2706a22260aeSJia Liu int64_t temp_sum; \ 2707a22260aeSJia Liu \ 2708a22260aeSJia Liu temp[0] = 0; \ 2709a22260aeSJia Liu temp[1] = 0; \ 2710a22260aeSJia Liu \ 2711a22260aeSJia Liu rs_t = (rs >> mov) & MIPSDSP_LO; \ 2712a22260aeSJia Liu rt_t = (rt >> mov) & MIPSDSP_LO; \ 2713a22260aeSJia Liu temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \ 2714a22260aeSJia Liu \ 2715a22260aeSJia Liu temp[0] = (int64_t)temp_mul; \ 2716a22260aeSJia Liu if (temp[0] >= 0) { \ 2717a22260aeSJia Liu temp[1] = 0x00; \ 2718a22260aeSJia Liu } else { \ 2719a22260aeSJia Liu temp[1] = ~0ull; \ 2720a22260aeSJia Liu } \ 2721a22260aeSJia Liu \ 2722a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 2723a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 2724a22260aeSJia Liu \ 2725a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 2726a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2727a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2728a22260aeSJia Liu acc[1] += 1; \ 2729a22260aeSJia Liu } \ 2730a22260aeSJia Liu acc[0] = temp_sum; \ 2731a22260aeSJia Liu acc[1] += temp[1]; \ 2732a22260aeSJia Liu \ 2733a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; \ 2734a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; \ 2735a22260aeSJia Liu } 2736a22260aeSJia Liu 2737a22260aeSJia Liu MAQ_S_W_QH(maq_s_w_qhll, 48); 2738a22260aeSJia Liu MAQ_S_W_QH(maq_s_w_qhlr, 32); 2739a22260aeSJia Liu MAQ_S_W_QH(maq_s_w_qhrl, 16); 2740a22260aeSJia Liu MAQ_S_W_QH(maq_s_w_qhrr, 0); 2741a22260aeSJia Liu 2742a22260aeSJia Liu #undef MAQ_S_W_QH 2743a22260aeSJia Liu 2744a22260aeSJia Liu #define MAQ_SA_W(name, mov) \ 2745a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2746a22260aeSJia Liu CPUMIPSState *env) \ 2747a22260aeSJia Liu { \ 2748a22260aeSJia Liu int16_t rs_t, rt_t; \ 2749a22260aeSJia Liu int32_t temp; \ 2750a22260aeSJia Liu int64_t acc[2]; \ 2751a22260aeSJia Liu \ 2752a22260aeSJia Liu rs_t = (rs >> mov) & MIPSDSP_LO; \ 2753a22260aeSJia Liu rt_t = (rt >> mov) & MIPSDSP_LO; \ 2754a22260aeSJia Liu temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \ 2755a22260aeSJia Liu temp = mipsdsp_sat32_acc_q31(ac, temp, env); \ 2756a22260aeSJia Liu \ 2757a22260aeSJia Liu acc[0] = (int64_t)(int32_t)temp; \ 2758a22260aeSJia Liu if (acc[0] >= 0) { \ 2759a22260aeSJia Liu acc[1] = 0x00; \ 2760a22260aeSJia Liu } else { \ 2761a22260aeSJia Liu acc[1] = ~0ull; \ 2762a22260aeSJia Liu } \ 2763a22260aeSJia Liu \ 2764a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; \ 2765a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; \ 2766a22260aeSJia Liu } 2767a22260aeSJia Liu 2768a22260aeSJia Liu MAQ_SA_W(maq_sa_w_qhll, 48); 2769a22260aeSJia Liu MAQ_SA_W(maq_sa_w_qhlr, 32); 2770a22260aeSJia Liu MAQ_SA_W(maq_sa_w_qhrl, 16); 2771a22260aeSJia Liu MAQ_SA_W(maq_sa_w_qhrr, 0); 2772a22260aeSJia Liu 2773a22260aeSJia Liu #undef MAQ_SA_W 2774a22260aeSJia Liu 2775a22260aeSJia Liu #define MAQ_S_L_PW(name, mov) \ 2776a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2777a22260aeSJia Liu CPUMIPSState *env) \ 2778a22260aeSJia Liu { \ 2779a22260aeSJia Liu int32_t rs_t, rt_t; \ 2780a22260aeSJia Liu int64_t temp[2]; \ 2781a22260aeSJia Liu int64_t acc[2]; \ 2782a22260aeSJia Liu int64_t temp_sum; \ 2783a22260aeSJia Liu \ 2784a22260aeSJia Liu temp[0] = 0; \ 2785a22260aeSJia Liu temp[1] = 0; \ 2786a22260aeSJia Liu \ 2787a22260aeSJia Liu rs_t = (rs >> mov) & MIPSDSP_LLO; \ 2788a22260aeSJia Liu rt_t = (rt >> mov) & MIPSDSP_LLO; \ 2789a22260aeSJia Liu \ 2790a22260aeSJia Liu temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env); \ 2791a22260aeSJia Liu if (temp[0] >= 0) { \ 2792a22260aeSJia Liu temp[1] = 0x00; \ 2793a22260aeSJia Liu } else { \ 2794a22260aeSJia Liu temp[1] = ~0ull; \ 2795a22260aeSJia Liu } \ 2796a22260aeSJia Liu \ 2797a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 2798a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 2799a22260aeSJia Liu \ 2800a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 2801a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2802a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2803a22260aeSJia Liu acc[1] += 1; \ 2804a22260aeSJia Liu } \ 2805a22260aeSJia Liu acc[0] = temp_sum; \ 2806a22260aeSJia Liu acc[1] += temp[1]; \ 2807a22260aeSJia Liu \ 2808a22260aeSJia Liu env->active_tc.HI[ac] = acc[1]; \ 2809a22260aeSJia Liu env->active_tc.LO[ac] = acc[0]; \ 2810a22260aeSJia Liu } 2811a22260aeSJia Liu 2812a22260aeSJia Liu MAQ_S_L_PW(maq_s_l_pwl, 32); 2813a22260aeSJia Liu MAQ_S_L_PW(maq_s_l_pwr, 0); 2814a22260aeSJia Liu 2815a22260aeSJia Liu #undef MAQ_S_L_PW 2816a22260aeSJia Liu 2817a22260aeSJia Liu #define DM_OPERATE(name, func, is_add, sigext) \ 2818a22260aeSJia Liu void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2819a22260aeSJia Liu CPUMIPSState *env) \ 2820a22260aeSJia Liu { \ 2821a22260aeSJia Liu int32_t rs1, rs0; \ 2822a22260aeSJia Liu int32_t rt1, rt0; \ 2823a22260aeSJia Liu int64_t tempBL[2], tempAL[2]; \ 2824a22260aeSJia Liu int64_t acc[2]; \ 2825a22260aeSJia Liu int64_t temp[2]; \ 2826a22260aeSJia Liu int64_t temp_sum; \ 2827a22260aeSJia Liu \ 2828a22260aeSJia Liu temp[0] = 0x00; \ 2829a22260aeSJia Liu temp[1] = 0x00; \ 2830a22260aeSJia Liu \ 2831a22260aeSJia Liu MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ 2832a22260aeSJia Liu MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 2833a22260aeSJia Liu \ 2834a22260aeSJia Liu if (sigext) { \ 2835a22260aeSJia Liu tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1); \ 2836a22260aeSJia Liu tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0); \ 2837a22260aeSJia Liu \ 2838a22260aeSJia Liu if (tempBL[0] >= 0) { \ 2839a22260aeSJia Liu tempBL[1] = 0x0; \ 2840a22260aeSJia Liu } else { \ 2841a22260aeSJia Liu tempBL[1] = ~0ull; \ 2842a22260aeSJia Liu } \ 2843a22260aeSJia Liu \ 2844a22260aeSJia Liu if (tempAL[0] >= 0) { \ 2845a22260aeSJia Liu tempAL[1] = 0x0; \ 2846a22260aeSJia Liu } else { \ 2847a22260aeSJia Liu tempAL[1] = ~0ull; \ 2848a22260aeSJia Liu } \ 2849a22260aeSJia Liu } else { \ 2850a22260aeSJia Liu tempBL[0] = mipsdsp_##func(rs1, rt1); \ 2851a22260aeSJia Liu tempAL[0] = mipsdsp_##func(rs0, rt0); \ 2852a22260aeSJia Liu tempBL[1] = 0; \ 2853a22260aeSJia Liu tempAL[1] = 0; \ 2854a22260aeSJia Liu } \ 2855a22260aeSJia Liu \ 2856a22260aeSJia Liu acc[1] = env->active_tc.HI[ac]; \ 2857a22260aeSJia Liu acc[0] = env->active_tc.LO[ac]; \ 2858a22260aeSJia Liu \ 2859a22260aeSJia Liu temp_sum = tempBL[0] + tempAL[0]; \ 2860a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) && \ 2861a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)tempAL[0])) { \ 2862a22260aeSJia Liu temp[1] += 1; \ 2863a22260aeSJia Liu } \ 2864a22260aeSJia Liu temp[0] = temp_sum; \ 2865a22260aeSJia Liu temp[1] += tempBL[1] + tempAL[1]; \ 2866a22260aeSJia Liu \ 2867a22260aeSJia Liu if (is_add) { \ 2868a22260aeSJia Liu temp_sum = acc[0] + temp[0]; \ 2869a22260aeSJia Liu if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2870a22260aeSJia Liu ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2871a22260aeSJia Liu acc[1] += 1; \ 2872a22260aeSJia Liu } \ 2873a22260aeSJia Liu temp[0] = temp_sum; \ 2874a22260aeSJia Liu temp[1] = acc[1] + temp[1]; \ 2875a22260aeSJia Liu } else { \ 2876a22260aeSJia Liu temp_sum = acc[0] - temp[0]; \ 2877a22260aeSJia Liu if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ 2878a22260aeSJia Liu acc[1] -= 1; \ 2879a22260aeSJia Liu } \ 2880a22260aeSJia Liu temp[0] = temp_sum; \ 2881a22260aeSJia Liu temp[1] = acc[1] - temp[1]; \ 2882a22260aeSJia Liu } \ 2883a22260aeSJia Liu \ 2884a22260aeSJia Liu env->active_tc.HI[ac] = temp[1]; \ 2885a22260aeSJia Liu env->active_tc.LO[ac] = temp[0]; \ 2886a22260aeSJia Liu } 2887a22260aeSJia Liu 2888a22260aeSJia Liu DM_OPERATE(dmadd, mul_i32_i32, 1, 1); 2889a22260aeSJia Liu DM_OPERATE(dmaddu, mul_u32_u32, 1, 0); 2890a22260aeSJia Liu DM_OPERATE(dmsub, mul_i32_i32, 0, 1); 2891a22260aeSJia Liu DM_OPERATE(dmsubu, mul_u32_u32, 0, 0); 2892a22260aeSJia Liu #undef DM_OPERATE 2893a22260aeSJia Liu #endif 2894a22260aeSJia Liu 28951cb6686cSJia Liu /** DSP Bit/Manipulation Sub-class insns **/ 28961cb6686cSJia Liu target_ulong helper_bitrev(target_ulong rt) 28971cb6686cSJia Liu { 28981cb6686cSJia Liu int32_t temp; 28991cb6686cSJia Liu uint32_t rd; 29001cb6686cSJia Liu int i; 29011cb6686cSJia Liu 29021cb6686cSJia Liu temp = rt & MIPSDSP_LO; 29031cb6686cSJia Liu rd = 0; 29041cb6686cSJia Liu for (i = 0; i < 16; i++) { 29051cb6686cSJia Liu rd = (rd << 1) | (temp & 1); 29061cb6686cSJia Liu temp = temp >> 1; 29071cb6686cSJia Liu } 29081cb6686cSJia Liu 29091cb6686cSJia Liu return (target_ulong)rd; 29101cb6686cSJia Liu } 29111cb6686cSJia Liu 2912d8992825SPetar Jovanovic #define BIT_INSV(name, posfilter, ret_type) \ 29131cb6686cSJia Liu target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \ 29141cb6686cSJia Liu target_ulong rt) \ 29151cb6686cSJia Liu { \ 29161cb6686cSJia Liu uint32_t pos, size, msb, lsb; \ 2917d8992825SPetar Jovanovic uint32_t const sizefilter = 0x3F; \ 2918d8992825SPetar Jovanovic target_ulong temp; \ 29191cb6686cSJia Liu target_ulong dspc; \ 29201cb6686cSJia Liu \ 29211cb6686cSJia Liu dspc = env->active_tc.DSPControl; \ 29221cb6686cSJia Liu \ 29231cb6686cSJia Liu pos = dspc & posfilter; \ 29241cb6686cSJia Liu size = (dspc >> 7) & sizefilter; \ 29251cb6686cSJia Liu \ 29261cb6686cSJia Liu msb = pos + size - 1; \ 29271cb6686cSJia Liu lsb = pos; \ 29281cb6686cSJia Liu \ 29291cb6686cSJia Liu if (lsb > msb || (msb > TARGET_LONG_BITS)) { \ 29301cb6686cSJia Liu return rt; \ 29311cb6686cSJia Liu } \ 29321cb6686cSJia Liu \ 2933d8992825SPetar Jovanovic temp = deposit64(rt, pos, size, rs); \ 29341cb6686cSJia Liu \ 29351cb6686cSJia Liu return (target_long)(ret_type)temp; \ 29361cb6686cSJia Liu } 29371cb6686cSJia Liu 2938d8992825SPetar Jovanovic BIT_INSV(insv, 0x1F, int32_t); 29391cb6686cSJia Liu #ifdef TARGET_MIPS64 2940d8992825SPetar Jovanovic BIT_INSV(dinsv, 0x7F, target_long); 29411cb6686cSJia Liu #endif 29421cb6686cSJia Liu 29431cb6686cSJia Liu #undef BIT_INSV 29441cb6686cSJia Liu 29451cb6686cSJia Liu 294626690560SJia Liu /** DSP Compare-Pick Sub-class insns **/ 294726690560SJia Liu #define CMP_HAS_RET(name, func, split_num, filter, bit_size) \ 294826690560SJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt) \ 294926690560SJia Liu { \ 295026690560SJia Liu uint32_t rs_t, rt_t; \ 295126690560SJia Liu uint8_t cc; \ 295226690560SJia Liu uint32_t temp = 0; \ 295326690560SJia Liu int i; \ 295426690560SJia Liu \ 295526690560SJia Liu for (i = 0; i < split_num; i++) { \ 295626690560SJia Liu rs_t = (rs >> (bit_size * i)) & filter; \ 295726690560SJia Liu rt_t = (rt >> (bit_size * i)) & filter; \ 295826690560SJia Liu cc = mipsdsp_##func(rs_t, rt_t); \ 295926690560SJia Liu temp |= cc << i; \ 296026690560SJia Liu } \ 296126690560SJia Liu \ 296226690560SJia Liu return (target_ulong)temp; \ 296326690560SJia Liu } 296426690560SJia Liu 296526690560SJia Liu CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); 296626690560SJia Liu CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); 296726690560SJia Liu CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); 296826690560SJia Liu 296926690560SJia Liu #ifdef TARGET_MIPS64 297026690560SJia Liu CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); 297126690560SJia Liu CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); 297226690560SJia Liu CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8); 297326690560SJia Liu #endif 297426690560SJia Liu 297526690560SJia Liu #undef CMP_HAS_RET 297626690560SJia Liu 297726690560SJia Liu 297826690560SJia Liu #define CMP_NO_RET(name, func, split_num, filter, bit_size) \ 297926690560SJia Liu void helper_##name(target_ulong rs, target_ulong rt, \ 298026690560SJia Liu CPUMIPSState *env) \ 298126690560SJia Liu { \ 298226690560SJia Liu int##bit_size##_t rs_t, rt_t; \ 298326690560SJia Liu int##bit_size##_t flag = 0; \ 298426690560SJia Liu int##bit_size##_t cc; \ 298526690560SJia Liu int i; \ 298626690560SJia Liu \ 298726690560SJia Liu for (i = 0; i < split_num; i++) { \ 298826690560SJia Liu rs_t = (rs >> (bit_size * i)) & filter; \ 298926690560SJia Liu rt_t = (rt >> (bit_size * i)) & filter; \ 299026690560SJia Liu \ 299126690560SJia Liu cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t); \ 299226690560SJia Liu flag |= cc << i; \ 299326690560SJia Liu } \ 299426690560SJia Liu \ 299526690560SJia Liu set_DSPControl_24(flag, split_num, env); \ 299626690560SJia Liu } 299726690560SJia Liu 299826690560SJia Liu CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); 299926690560SJia Liu CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); 300026690560SJia Liu CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); 300126690560SJia Liu 300226690560SJia Liu CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16); 300326690560SJia Liu CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16); 300426690560SJia Liu CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16); 300526690560SJia Liu 300626690560SJia Liu #ifdef TARGET_MIPS64 300726690560SJia Liu CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); 300826690560SJia Liu CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); 300926690560SJia Liu CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8); 301026690560SJia Liu 301126690560SJia Liu CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16); 301226690560SJia Liu CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16); 301326690560SJia Liu CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16); 301426690560SJia Liu 301526690560SJia Liu CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32); 301626690560SJia Liu CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32); 301726690560SJia Liu CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32); 301826690560SJia Liu #endif 301926690560SJia Liu #undef CMP_NO_RET 302026690560SJia Liu 302126690560SJia Liu #if defined(TARGET_MIPS64) 302226690560SJia Liu 302326690560SJia Liu #define CMPGDU_OB(name) \ 302426690560SJia Liu target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \ 302526690560SJia Liu CPUMIPSState *env) \ 302626690560SJia Liu { \ 302726690560SJia Liu int i; \ 302826690560SJia Liu uint8_t rs_t, rt_t; \ 302926690560SJia Liu uint32_t cond; \ 303026690560SJia Liu \ 303126690560SJia Liu cond = 0; \ 303226690560SJia Liu \ 303326690560SJia Liu for (i = 0; i < 8; i++) { \ 303426690560SJia Liu rs_t = (rs >> (8 * i)) & MIPSDSP_Q0; \ 303526690560SJia Liu rt_t = (rt >> (8 * i)) & MIPSDSP_Q0; \ 303626690560SJia Liu \ 303726690560SJia Liu if (mipsdsp_cmpu_##name(rs_t, rt_t)) { \ 303826690560SJia Liu cond |= 0x01 << i; \ 303926690560SJia Liu } \ 304026690560SJia Liu } \ 304126690560SJia Liu \ 304226690560SJia Liu set_DSPControl_24(cond, 8, env); \ 304326690560SJia Liu \ 304426690560SJia Liu return (uint64_t)cond; \ 304526690560SJia Liu } 304626690560SJia Liu 304726690560SJia Liu CMPGDU_OB(eq) 304826690560SJia Liu CMPGDU_OB(lt) 304926690560SJia Liu CMPGDU_OB(le) 305026690560SJia Liu #undef CMPGDU_OB 305126690560SJia Liu #endif 305226690560SJia Liu 305326690560SJia Liu #define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \ 305426690560SJia Liu target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 305526690560SJia Liu CPUMIPSState *env) \ 305626690560SJia Liu { \ 305726690560SJia Liu uint32_t rs_t, rt_t; \ 305826690560SJia Liu uint32_t cc; \ 305926690560SJia Liu target_ulong dsp; \ 306026690560SJia Liu int i; \ 306126690560SJia Liu target_ulong result = 0; \ 306226690560SJia Liu \ 306326690560SJia Liu dsp = env->active_tc.DSPControl; \ 306426690560SJia Liu for (i = 0; i < split_num; i++) { \ 306526690560SJia Liu rs_t = (rs >> (bit_size * i)) & filter; \ 306626690560SJia Liu rt_t = (rt >> (bit_size * i)) & filter; \ 306726690560SJia Liu cc = (dsp >> (24 + i)) & 0x01; \ 306826690560SJia Liu cc = cc == 1 ? rs_t : rt_t; \ 306926690560SJia Liu \ 307026690560SJia Liu result |= (target_ulong)cc << (bit_size * i); \ 307126690560SJia Liu } \ 307226690560SJia Liu \ 307326690560SJia Liu if (ret32bit) { \ 307426690560SJia Liu result = (target_long)(int32_t)(result & MIPSDSP_LLO); \ 307526690560SJia Liu } \ 307626690560SJia Liu \ 307726690560SJia Liu return result; \ 307826690560SJia Liu } 307926690560SJia Liu 308026690560SJia Liu PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1); 308126690560SJia Liu PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1); 308226690560SJia Liu 308326690560SJia Liu #ifdef TARGET_MIPS64 308426690560SJia Liu PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0); 308526690560SJia Liu PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0); 308626690560SJia Liu PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0); 308726690560SJia Liu #endif 308826690560SJia Liu #undef PICK_INSN 308926690560SJia Liu 309026690560SJia Liu target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt) 309126690560SJia Liu { 309226690560SJia Liu uint32_t rsl, rth; 309326690560SJia Liu 309426690560SJia Liu rsl = rs & MIPSDSP_LO; 309526690560SJia Liu rth = (rt & MIPSDSP_HI) >> 16; 309626690560SJia Liu 309726690560SJia Liu return (target_long)(int32_t)((rsl << 16) | rth); 309826690560SJia Liu } 309926690560SJia Liu 310026690560SJia Liu #if defined(TARGET_MIPS64) 310126690560SJia Liu target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt) 310226690560SJia Liu { 310326690560SJia Liu uint32_t rs0, rt1; 310426690560SJia Liu 310526690560SJia Liu rs0 = rs & MIPSDSP_LLO; 310626690560SJia Liu rt1 = (rt >> 32) & MIPSDSP_LLO; 310726690560SJia Liu 310826690560SJia Liu return ((uint64_t)rs0 << 32) | (uint64_t)rt1; 310926690560SJia Liu } 311026690560SJia Liu #endif 311126690560SJia Liu 3112b53371edSJia Liu /** DSP Accumulator and DSPControl Access Sub-class insns **/ 3113b53371edSJia Liu target_ulong helper_extr_w(target_ulong ac, target_ulong shift, 3114b53371edSJia Liu CPUMIPSState *env) 3115b53371edSJia Liu { 3116b53371edSJia Liu int32_t tempI; 3117b53371edSJia Liu int64_t tempDL[2]; 3118b53371edSJia Liu 3119b8abbbe8SPetar Jovanovic shift = shift & 0x1F; 3120b53371edSJia Liu 3121b53371edSJia Liu mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); 3122b53371edSJia Liu if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3123b53371edSJia Liu (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3124b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3125b53371edSJia Liu } 3126b53371edSJia Liu 3127b53371edSJia Liu tempI = (tempDL[0] >> 1) & MIPSDSP_LLO; 3128b53371edSJia Liu 3129b53371edSJia Liu tempDL[0] += 1; 3130b53371edSJia Liu if (tempDL[0] == 0) { 3131b53371edSJia Liu tempDL[1] += 1; 3132b53371edSJia Liu } 3133b53371edSJia Liu 31348b758d05SPetar Jovanovic if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 31358b758d05SPetar Jovanovic ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3136b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3137b53371edSJia Liu } 3138b53371edSJia Liu 3139b53371edSJia Liu return (target_long)tempI; 3140b53371edSJia Liu } 3141b53371edSJia Liu 3142b53371edSJia Liu target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift, 3143b53371edSJia Liu CPUMIPSState *env) 3144b53371edSJia Liu { 3145b53371edSJia Liu int64_t tempDL[2]; 3146b53371edSJia Liu 3147b8abbbe8SPetar Jovanovic shift = shift & 0x1F; 3148b53371edSJia Liu 3149b53371edSJia Liu mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); 3150b53371edSJia Liu if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3151b53371edSJia Liu (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3152b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3153b53371edSJia Liu } 3154b53371edSJia Liu 3155b53371edSJia Liu tempDL[0] += 1; 3156b53371edSJia Liu if (tempDL[0] == 0) { 3157b53371edSJia Liu tempDL[1] += 1; 3158b53371edSJia Liu } 3159b53371edSJia Liu 31608b758d05SPetar Jovanovic if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 31618b758d05SPetar Jovanovic ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3162b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3163b53371edSJia Liu } 3164b53371edSJia Liu 3165b53371edSJia Liu return (target_long)(int32_t)(tempDL[0] >> 1); 3166b53371edSJia Liu } 3167b53371edSJia Liu 3168b53371edSJia Liu target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift, 3169b53371edSJia Liu CPUMIPSState *env) 3170b53371edSJia Liu { 3171b53371edSJia Liu int32_t tempI, temp64; 3172b53371edSJia Liu int64_t tempDL[2]; 3173b53371edSJia Liu 3174b8abbbe8SPetar Jovanovic shift = shift & 0x1F; 3175b53371edSJia Liu 3176b53371edSJia Liu mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); 3177b53371edSJia Liu if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3178b53371edSJia Liu (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3179b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3180b53371edSJia Liu } 3181b53371edSJia Liu tempDL[0] += 1; 3182b53371edSJia Liu if (tempDL[0] == 0) { 3183b53371edSJia Liu tempDL[1] += 1; 3184b53371edSJia Liu } 3185b53371edSJia Liu tempI = tempDL[0] >> 1; 3186b53371edSJia Liu 31878b758d05SPetar Jovanovic if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 31888b758d05SPetar Jovanovic ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 31898b758d05SPetar Jovanovic temp64 = tempDL[1] & 0x01; 3190b53371edSJia Liu if (temp64 == 0) { 3191b53371edSJia Liu tempI = 0x7FFFFFFF; 3192b53371edSJia Liu } else { 3193b53371edSJia Liu tempI = 0x80000000; 3194b53371edSJia Liu } 3195b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3196b53371edSJia Liu } 3197b53371edSJia Liu 3198b53371edSJia Liu return (target_long)tempI; 3199b53371edSJia Liu } 3200b53371edSJia Liu 3201b53371edSJia Liu #if defined(TARGET_MIPS64) 3202b53371edSJia Liu target_ulong helper_dextr_w(target_ulong ac, target_ulong shift, 3203b53371edSJia Liu CPUMIPSState *env) 3204b53371edSJia Liu { 3205b53371edSJia Liu uint64_t temp[3]; 3206b53371edSJia Liu 3207b53371edSJia Liu shift = shift & 0x3F; 3208b53371edSJia Liu 3209b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3210b53371edSJia Liu 3211b53371edSJia Liu return (int64_t)(int32_t)(temp[0] >> 1); 3212b53371edSJia Liu } 3213b53371edSJia Liu 3214b53371edSJia Liu target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift, 3215b53371edSJia Liu CPUMIPSState *env) 3216b53371edSJia Liu { 3217b53371edSJia Liu uint64_t temp[3]; 3218b53371edSJia Liu uint32_t temp128; 3219b53371edSJia Liu 3220b53371edSJia Liu shift = shift & 0x3F; 3221b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3222b53371edSJia Liu 3223b53371edSJia Liu temp[0] += 1; 3224b53371edSJia Liu if (temp[0] == 0) { 3225b53371edSJia Liu temp[1] += 1; 3226b53371edSJia Liu if (temp[1] == 0) { 3227b53371edSJia Liu temp[2] += 1; 3228b53371edSJia Liu } 3229b53371edSJia Liu } 3230b53371edSJia Liu 3231b53371edSJia Liu temp128 = temp[2] & 0x01; 3232b53371edSJia Liu 3233b53371edSJia Liu if ((temp128 != 0 || temp[1] != 0) && 3234b53371edSJia Liu (temp128 != 1 || temp[1] != ~0ull)) { 3235b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3236b53371edSJia Liu } 3237b53371edSJia Liu 3238b53371edSJia Liu return (int64_t)(int32_t)(temp[0] >> 1); 3239b53371edSJia Liu } 3240b53371edSJia Liu 3241b53371edSJia Liu target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift, 3242b53371edSJia Liu CPUMIPSState *env) 3243b53371edSJia Liu { 3244b53371edSJia Liu uint64_t temp[3]; 3245b53371edSJia Liu uint32_t temp128; 3246b53371edSJia Liu 3247b53371edSJia Liu shift = shift & 0x3F; 3248b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3249b53371edSJia Liu 3250b53371edSJia Liu temp[0] += 1; 3251b53371edSJia Liu if (temp[0] == 0) { 3252b53371edSJia Liu temp[1] += 1; 3253b53371edSJia Liu if (temp[1] == 0) { 3254b53371edSJia Liu temp[2] += 1; 3255b53371edSJia Liu } 3256b53371edSJia Liu } 3257b53371edSJia Liu 3258b53371edSJia Liu temp128 = temp[2] & 0x01; 3259b53371edSJia Liu 3260b53371edSJia Liu if ((temp128 != 0 || temp[1] != 0) && 3261b53371edSJia Liu (temp128 != 1 || temp[1] != ~0ull)) { 3262b53371edSJia Liu if (temp128 == 0) { 3263b53371edSJia Liu temp[0] = 0x0FFFFFFFF; 3264b53371edSJia Liu } else { 32651cfd981fSBlue Swirl temp[0] = 0x0100000000ULL; 3266b53371edSJia Liu } 3267b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3268b53371edSJia Liu } 3269b53371edSJia Liu 3270b53371edSJia Liu return (int64_t)(int32_t)(temp[0] >> 1); 3271b53371edSJia Liu } 3272b53371edSJia Liu 3273b53371edSJia Liu target_ulong helper_dextr_l(target_ulong ac, target_ulong shift, 3274b53371edSJia Liu CPUMIPSState *env) 3275b53371edSJia Liu { 3276b53371edSJia Liu uint64_t temp[3]; 3277b53371edSJia Liu target_ulong result; 3278b53371edSJia Liu 3279b53371edSJia Liu shift = shift & 0x3F; 3280b53371edSJia Liu 3281b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3282b53371edSJia Liu result = (temp[1] << 63) | (temp[0] >> 1); 3283b53371edSJia Liu 3284b53371edSJia Liu return result; 3285b53371edSJia Liu } 3286b53371edSJia Liu 3287b53371edSJia Liu target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, 3288b53371edSJia Liu CPUMIPSState *env) 3289b53371edSJia Liu { 3290b53371edSJia Liu uint64_t temp[3]; 3291b53371edSJia Liu uint32_t temp128; 3292b53371edSJia Liu target_ulong result; 3293b53371edSJia Liu 3294b53371edSJia Liu shift = shift & 0x3F; 3295b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3296b53371edSJia Liu 3297b53371edSJia Liu temp[0] += 1; 3298b53371edSJia Liu if (temp[0] == 0) { 3299b53371edSJia Liu temp[1] += 1; 3300b53371edSJia Liu if (temp[1] == 0) { 3301b53371edSJia Liu temp[2] += 1; 3302b53371edSJia Liu } 3303b53371edSJia Liu } 3304b53371edSJia Liu 3305b53371edSJia Liu temp128 = temp[2] & 0x01; 3306b53371edSJia Liu 3307b53371edSJia Liu if ((temp128 != 0 || temp[1] != 0) && 3308b53371edSJia Liu (temp128 != 1 || temp[1] != ~0ull)) { 3309b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3310b53371edSJia Liu } 3311b53371edSJia Liu 3312b53371edSJia Liu result = (temp[1] << 63) | (temp[0] >> 1); 3313b53371edSJia Liu 3314b53371edSJia Liu return result; 3315b53371edSJia Liu } 3316b53371edSJia Liu 3317b53371edSJia Liu target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, 3318b53371edSJia Liu CPUMIPSState *env) 3319b53371edSJia Liu { 3320b53371edSJia Liu uint64_t temp[3]; 3321b53371edSJia Liu uint32_t temp128; 3322b53371edSJia Liu target_ulong result; 3323b53371edSJia Liu 3324b53371edSJia Liu shift = shift & 0x3F; 3325b53371edSJia Liu mipsdsp_rndrashift_acc(temp, ac, shift, env); 3326b53371edSJia Liu 3327b53371edSJia Liu temp[0] += 1; 3328b53371edSJia Liu if (temp[0] == 0) { 3329b53371edSJia Liu temp[1] += 1; 3330b53371edSJia Liu if (temp[1] == 0) { 3331b53371edSJia Liu temp[2] += 1; 3332b53371edSJia Liu } 3333b53371edSJia Liu } 3334b53371edSJia Liu 3335b53371edSJia Liu temp128 = temp[2] & 0x01; 3336b53371edSJia Liu 3337b53371edSJia Liu if ((temp128 != 0 || temp[1] != 0) && 3338b53371edSJia Liu (temp128 != 1 || temp[1] != ~0ull)) { 3339b53371edSJia Liu if (temp128 == 0) { 3340b53371edSJia Liu temp[1] &= ~0x00ull - 1; 3341b53371edSJia Liu temp[0] |= ~0x00ull - 1; 3342b53371edSJia Liu } else { 3343b53371edSJia Liu temp[1] |= 0x01; 3344b53371edSJia Liu temp[0] &= 0x01; 3345b53371edSJia Liu } 3346b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3347b53371edSJia Liu } 3348b53371edSJia Liu result = (temp[1] << 63) | (temp[0] >> 1); 3349b53371edSJia Liu 3350b53371edSJia Liu return result; 3351b53371edSJia Liu } 3352b53371edSJia Liu #endif 3353b53371edSJia Liu 3354b53371edSJia Liu target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift, 3355b53371edSJia Liu CPUMIPSState *env) 3356b53371edSJia Liu { 3357b8abbbe8SPetar Jovanovic int64_t temp, acc; 3358b53371edSJia Liu 3359b8abbbe8SPetar Jovanovic shift = shift & 0x1F; 3360b53371edSJia Liu 3361b8abbbe8SPetar Jovanovic acc = ((int64_t)env->active_tc.HI[ac] << 32) | 3362b8abbbe8SPetar Jovanovic ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); 3363b8abbbe8SPetar Jovanovic 3364b8abbbe8SPetar Jovanovic temp = acc >> shift; 3365b8abbbe8SPetar Jovanovic 3366b53371edSJia Liu if (temp > (int64_t)0x7FFF) { 3367b53371edSJia Liu temp = 0x00007FFF; 3368b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 33691cfd981fSBlue Swirl } else if (temp < (int64_t)0xFFFFFFFFFFFF8000ULL) { 3370b53371edSJia Liu temp = 0xFFFF8000; 3371b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3372b53371edSJia Liu } 3373b53371edSJia Liu 3374b53371edSJia Liu return (target_long)(int32_t)(temp & 0xFFFFFFFF); 3375b53371edSJia Liu } 3376b53371edSJia Liu 3377b53371edSJia Liu 3378b53371edSJia Liu #if defined(TARGET_MIPS64) 3379b53371edSJia Liu target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift, 3380b53371edSJia Liu CPUMIPSState *env) 3381b53371edSJia Liu { 3382b53371edSJia Liu int64_t temp[2]; 3383b53371edSJia Liu uint32_t temp127; 3384b53371edSJia Liu 3385b53371edSJia Liu shift = shift & 0x1F; 3386b53371edSJia Liu 3387b53371edSJia Liu mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env); 3388b53371edSJia Liu 3389b53371edSJia Liu temp127 = (temp[1] >> 63) & 0x01; 3390b53371edSJia Liu 3391b53371edSJia Liu if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) { 3392b53371edSJia Liu temp[0] &= 0xFFFF0000; 3393b53371edSJia Liu temp[0] |= 0x00007FFF; 3394b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3395b53371edSJia Liu } else if ((temp127 == 1) && 3396b53371edSJia Liu (temp[1] < 0xFFFFFFFFFFFFFFFFll 3397b53371edSJia Liu || temp[0] < 0xFFFFFFFFFFFF1000ll)) { 3398b53371edSJia Liu temp[0] &= 0xFFFF0000; 3399b53371edSJia Liu temp[0] |= 0x00008000; 3400b53371edSJia Liu set_DSPControl_overflow_flag(1, 23, env); 3401b53371edSJia Liu } 3402b53371edSJia Liu 3403b53371edSJia Liu return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO); 3404b53371edSJia Liu } 3405b53371edSJia Liu 3406b53371edSJia Liu #endif 3407b53371edSJia Liu 3408b53371edSJia Liu target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env) 3409b53371edSJia Liu { 3410b53371edSJia Liu int32_t start_pos; 3411b53371edSJia Liu int sub; 3412b53371edSJia Liu uint32_t temp; 3413b53371edSJia Liu uint64_t acc; 3414b53371edSJia Liu 3415b53371edSJia Liu size = size & 0x1F; 3416b53371edSJia Liu 3417b53371edSJia Liu temp = 0; 3418b53371edSJia Liu start_pos = get_DSPControl_pos(env); 3419b53371edSJia Liu sub = start_pos - (size + 1); 3420b53371edSJia Liu if (sub >= -1) { 3421b53371edSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | 3422b53371edSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); 3423489ed4bbSPetar Jovanovic temp = (acc >> (start_pos - size)) & (~0U >> (31 - size)); 3424b53371edSJia Liu set_DSPControl_efi(0, env); 3425b53371edSJia Liu } else { 3426b53371edSJia Liu set_DSPControl_efi(1, env); 3427b53371edSJia Liu } 3428b53371edSJia Liu 3429b53371edSJia Liu return (target_ulong)temp; 3430b53371edSJia Liu } 3431b53371edSJia Liu 3432b53371edSJia Liu target_ulong helper_extpdp(target_ulong ac, target_ulong size, 3433b53371edSJia Liu CPUMIPSState *env) 3434b53371edSJia Liu { 3435b53371edSJia Liu int32_t start_pos; 3436b53371edSJia Liu int sub; 3437b53371edSJia Liu uint32_t temp; 3438b53371edSJia Liu uint64_t acc; 3439b53371edSJia Liu 3440b53371edSJia Liu size = size & 0x1F; 3441b53371edSJia Liu temp = 0; 3442b53371edSJia Liu start_pos = get_DSPControl_pos(env); 3443b53371edSJia Liu sub = start_pos - (size + 1); 3444b53371edSJia Liu if (sub >= -1) { 3445b53371edSJia Liu acc = ((uint64_t)env->active_tc.HI[ac] << 32) | 3446b53371edSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); 34470ba365f4SPetar Jovanovic temp = extract64(acc, start_pos - size, size + 1); 3448b53371edSJia Liu 34490ba365f4SPetar Jovanovic set_DSPControl_pos(sub, env); 3450b53371edSJia Liu set_DSPControl_efi(0, env); 3451b53371edSJia Liu } else { 3452b53371edSJia Liu set_DSPControl_efi(1, env); 3453b53371edSJia Liu } 3454b53371edSJia Liu 3455b53371edSJia Liu return (target_ulong)temp; 3456b53371edSJia Liu } 3457b53371edSJia Liu 3458b53371edSJia Liu 3459b53371edSJia Liu #if defined(TARGET_MIPS64) 3460b53371edSJia Liu target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env) 3461b53371edSJia Liu { 3462b53371edSJia Liu int start_pos; 3463b53371edSJia Liu int len; 3464b53371edSJia Liu int sub; 3465b53371edSJia Liu uint64_t tempB, tempA; 3466b53371edSJia Liu uint64_t temp; 3467b53371edSJia Liu 3468b53371edSJia Liu temp = 0; 3469b53371edSJia Liu 3470b53371edSJia Liu size = size & 0x3F; 3471b53371edSJia Liu start_pos = get_DSPControl_pos(env); 3472b53371edSJia Liu len = start_pos - size; 3473b53371edSJia Liu tempB = env->active_tc.HI[ac]; 3474b53371edSJia Liu tempA = env->active_tc.LO[ac]; 3475b53371edSJia Liu 3476b53371edSJia Liu sub = start_pos - (size + 1); 3477b53371edSJia Liu 3478b53371edSJia Liu if (sub >= -1) { 3479b53371edSJia Liu temp = (tempB << (64 - len)) | (tempA >> len); 3480e6e2784cSYongbok Kim temp = temp & ((1ULL << (size + 1)) - 1); 3481b53371edSJia Liu set_DSPControl_efi(0, env); 3482b53371edSJia Liu } else { 3483b53371edSJia Liu set_DSPControl_efi(1, env); 3484b53371edSJia Liu } 3485b53371edSJia Liu 3486b53371edSJia Liu return temp; 3487b53371edSJia Liu } 3488b53371edSJia Liu 3489b53371edSJia Liu target_ulong helper_dextpdp(target_ulong ac, target_ulong size, 3490b53371edSJia Liu CPUMIPSState *env) 3491b53371edSJia Liu { 3492b53371edSJia Liu int start_pos; 3493b53371edSJia Liu int len; 3494b53371edSJia Liu int sub; 3495b53371edSJia Liu uint64_t tempB, tempA; 3496b53371edSJia Liu uint64_t temp; 3497b53371edSJia Liu 3498b53371edSJia Liu temp = 0; 3499b53371edSJia Liu size = size & 0x3F; 3500b53371edSJia Liu start_pos = get_DSPControl_pos(env); 3501b53371edSJia Liu len = start_pos - size; 3502b53371edSJia Liu tempB = env->active_tc.HI[ac]; 3503b53371edSJia Liu tempA = env->active_tc.LO[ac]; 3504b53371edSJia Liu 3505b53371edSJia Liu sub = start_pos - (size + 1); 3506b53371edSJia Liu 3507b53371edSJia Liu if (sub >= -1) { 3508b53371edSJia Liu temp = (tempB << (64 - len)) | (tempA >> len); 3509e6e2784cSYongbok Kim temp = temp & ((1ULL << (size + 1)) - 1); 3510b53371edSJia Liu set_DSPControl_pos(sub, env); 3511b53371edSJia Liu set_DSPControl_efi(0, env); 3512b53371edSJia Liu } else { 3513b53371edSJia Liu set_DSPControl_efi(1, env); 3514b53371edSJia Liu } 3515b53371edSJia Liu 3516b53371edSJia Liu return temp; 3517b53371edSJia Liu } 3518b53371edSJia Liu 3519b53371edSJia Liu #endif 3520b53371edSJia Liu 3521b53371edSJia Liu void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env) 3522b53371edSJia Liu { 3523b53371edSJia Liu int8_t rs5_0; 3524b53371edSJia Liu uint64_t temp, acc; 3525b53371edSJia Liu 3526b53371edSJia Liu rs5_0 = rs & 0x3F; 3527b53371edSJia Liu rs5_0 = (int8_t)(rs5_0 << 2) >> 2; 352819e6c50dSPetar Jovanovic 352919e6c50dSPetar Jovanovic if (unlikely(rs5_0 == 0)) { 353019e6c50dSPetar Jovanovic return; 353119e6c50dSPetar Jovanovic } 353219e6c50dSPetar Jovanovic 3533b53371edSJia Liu acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) | 3534b53371edSJia Liu ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); 353519e6c50dSPetar Jovanovic 3536b53371edSJia Liu if (rs5_0 > 0) { 3537b53371edSJia Liu temp = acc >> rs5_0; 3538b53371edSJia Liu } else { 353919e6c50dSPetar Jovanovic temp = acc << -rs5_0; 3540b53371edSJia Liu } 3541b53371edSJia Liu 3542b53371edSJia Liu env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32); 3543b53371edSJia Liu env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO); 3544b53371edSJia Liu } 3545b53371edSJia Liu 3546b53371edSJia Liu #if defined(TARGET_MIPS64) 3547b53371edSJia Liu void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env) 3548b53371edSJia Liu { 3549b53371edSJia Liu int8_t shift_t; 3550b53371edSJia Liu uint64_t tempB, tempA; 3551b53371edSJia Liu 3552b53371edSJia Liu shift_t = (int8_t)(shift << 1) >> 1; 3553b53371edSJia Liu 3554b53371edSJia Liu tempB = env->active_tc.HI[ac]; 3555b53371edSJia Liu tempA = env->active_tc.LO[ac]; 3556b53371edSJia Liu 3557b53371edSJia Liu if (shift_t != 0) { 3558b53371edSJia Liu if (shift_t >= 0) { 3559b53371edSJia Liu tempA = (tempB << (64 - shift_t)) | (tempA >> shift_t); 3560b53371edSJia Liu tempB = tempB >> shift_t; 3561b53371edSJia Liu } else { 3562b53371edSJia Liu shift_t = -shift_t; 3563b53371edSJia Liu tempB = (tempB << shift_t) | (tempA >> (64 - shift_t)); 3564b53371edSJia Liu tempA = tempA << shift_t; 3565b53371edSJia Liu } 3566b53371edSJia Liu } 3567b53371edSJia Liu 3568b53371edSJia Liu env->active_tc.HI[ac] = tempB; 3569b53371edSJia Liu env->active_tc.LO[ac] = tempA; 3570b53371edSJia Liu } 3571b53371edSJia Liu 3572b53371edSJia Liu #endif 3573b53371edSJia Liu void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env) 3574b53371edSJia Liu { 3575b53371edSJia Liu int32_t tempA, tempB, pos; 3576b53371edSJia Liu 3577b53371edSJia Liu tempA = rs; 3578b53371edSJia Liu tempB = env->active_tc.LO[ac]; 3579b53371edSJia Liu env->active_tc.HI[ac] = (target_long)tempB; 3580b53371edSJia Liu env->active_tc.LO[ac] = (target_long)tempA; 3581b53371edSJia Liu pos = get_DSPControl_pos(env); 3582b53371edSJia Liu 3583b53371edSJia Liu if (pos > 32) { 3584b53371edSJia Liu return; 3585b53371edSJia Liu } else { 3586b53371edSJia Liu set_DSPControl_pos(pos + 32, env); 3587b53371edSJia Liu } 3588b53371edSJia Liu } 3589b53371edSJia Liu 3590b53371edSJia Liu #if defined(TARGET_MIPS64) 3591b53371edSJia Liu void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env) 3592b53371edSJia Liu { 3593b53371edSJia Liu uint8_t ac_t; 3594b53371edSJia Liu uint8_t pos; 3595b53371edSJia Liu uint64_t tempB, tempA; 3596b53371edSJia Liu 3597b53371edSJia Liu ac_t = ac & 0x3; 3598b53371edSJia Liu 3599b53371edSJia Liu tempA = rs; 3600b53371edSJia Liu tempB = env->active_tc.LO[ac_t]; 3601b53371edSJia Liu 3602b53371edSJia Liu env->active_tc.HI[ac_t] = tempB; 3603b53371edSJia Liu env->active_tc.LO[ac_t] = tempA; 3604b53371edSJia Liu 3605b53371edSJia Liu pos = get_DSPControl_pos(env); 3606b53371edSJia Liu 3607b53371edSJia Liu if (pos <= 64) { 3608b53371edSJia Liu pos = pos + 64; 3609b53371edSJia Liu set_DSPControl_pos(pos, env); 3610b53371edSJia Liu } 3611b53371edSJia Liu } 3612b53371edSJia Liu #endif 3613b53371edSJia Liu 3614084d0497SRichard Henderson void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env) 3615b53371edSJia Liu { 3616b53371edSJia Liu uint8_t mask[6]; 3617b53371edSJia Liu uint8_t i; 3618b53371edSJia Liu uint32_t newbits, overwrite; 3619b53371edSJia Liu target_ulong dsp; 3620b53371edSJia Liu 3621b53371edSJia Liu newbits = 0x00; 3622b53371edSJia Liu overwrite = 0xFFFFFFFF; 3623b53371edSJia Liu dsp = env->active_tc.DSPControl; 3624b53371edSJia Liu 3625b53371edSJia Liu for (i = 0; i < 6; i++) { 3626b53371edSJia Liu mask[i] = (mask_num >> i) & 0x01; 3627b53371edSJia Liu } 3628b53371edSJia Liu 3629b53371edSJia Liu if (mask[0] == 1) { 3630b53371edSJia Liu #if defined(TARGET_MIPS64) 3631b53371edSJia Liu overwrite &= 0xFFFFFF80; 3632b53371edSJia Liu newbits &= 0xFFFFFF80; 3633b53371edSJia Liu newbits |= 0x0000007F & rs; 3634b53371edSJia Liu #else 3635b53371edSJia Liu overwrite &= 0xFFFFFFC0; 3636b53371edSJia Liu newbits &= 0xFFFFFFC0; 3637b53371edSJia Liu newbits |= 0x0000003F & rs; 3638b53371edSJia Liu #endif 3639b53371edSJia Liu } 3640b53371edSJia Liu 3641b53371edSJia Liu if (mask[1] == 1) { 3642b53371edSJia Liu overwrite &= 0xFFFFE07F; 3643b53371edSJia Liu newbits &= 0xFFFFE07F; 3644b53371edSJia Liu newbits |= 0x00001F80 & rs; 3645b53371edSJia Liu } 3646b53371edSJia Liu 3647b53371edSJia Liu if (mask[2] == 1) { 3648b53371edSJia Liu overwrite &= 0xFFFFDFFF; 3649b53371edSJia Liu newbits &= 0xFFFFDFFF; 3650b53371edSJia Liu newbits |= 0x00002000 & rs; 3651b53371edSJia Liu } 3652b53371edSJia Liu 3653b53371edSJia Liu if (mask[3] == 1) { 3654b53371edSJia Liu overwrite &= 0xFF00FFFF; 3655b53371edSJia Liu newbits &= 0xFF00FFFF; 3656b53371edSJia Liu newbits |= 0x00FF0000 & rs; 3657b53371edSJia Liu } 3658b53371edSJia Liu 3659b53371edSJia Liu if (mask[4] == 1) { 3660b53371edSJia Liu overwrite &= 0x00FFFFFF; 3661b53371edSJia Liu newbits &= 0x00FFFFFF; 3662eec8972aSPetar Jovanovic #if defined(TARGET_MIPS64) 3663b53371edSJia Liu newbits |= 0xFF000000 & rs; 3664eec8972aSPetar Jovanovic #else 3665eec8972aSPetar Jovanovic newbits |= 0x0F000000 & rs; 3666eec8972aSPetar Jovanovic #endif 3667b53371edSJia Liu } 3668b53371edSJia Liu 3669b53371edSJia Liu if (mask[5] == 1) { 3670b53371edSJia Liu overwrite &= 0xFFFFBFFF; 3671b53371edSJia Liu newbits &= 0xFFFFBFFF; 3672b53371edSJia Liu newbits |= 0x00004000 & rs; 3673b53371edSJia Liu } 3674b53371edSJia Liu 3675b53371edSJia Liu dsp = dsp & overwrite; 3676b53371edSJia Liu dsp = dsp | newbits; 3677b53371edSJia Liu env->active_tc.DSPControl = dsp; 3678b53371edSJia Liu } 3679b53371edSJia Liu 3680084d0497SRichard Henderson void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env) 3681084d0497SRichard Henderson { 3682327e9759SStefan Weil cpu_wrdsp(rs, mask_num, env); 3683084d0497SRichard Henderson } 3684084d0497SRichard Henderson 3685084d0497SRichard Henderson uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env) 3686b53371edSJia Liu { 3687b53371edSJia Liu uint8_t mask[6]; 3688b53371edSJia Liu uint32_t ruler, i; 3689b53371edSJia Liu target_ulong temp; 3690b53371edSJia Liu target_ulong dsp; 3691b53371edSJia Liu 3692b53371edSJia Liu ruler = 0x01; 3693b53371edSJia Liu for (i = 0; i < 6; i++) { 3694084d0497SRichard Henderson mask[i] = (mask_num & ruler) >> i ; 3695b53371edSJia Liu ruler = ruler << 1; 3696b53371edSJia Liu } 3697b53371edSJia Liu 3698b53371edSJia Liu temp = 0x00; 3699b53371edSJia Liu dsp = env->active_tc.DSPControl; 3700b53371edSJia Liu 3701b53371edSJia Liu if (mask[0] == 1) { 3702b53371edSJia Liu #if defined(TARGET_MIPS64) 3703b53371edSJia Liu temp |= dsp & 0x7F; 3704b53371edSJia Liu #else 3705b53371edSJia Liu temp |= dsp & 0x3F; 3706b53371edSJia Liu #endif 3707b53371edSJia Liu } 3708b53371edSJia Liu 3709b53371edSJia Liu if (mask[1] == 1) { 3710b53371edSJia Liu temp |= dsp & 0x1F80; 3711b53371edSJia Liu } 3712b53371edSJia Liu 3713b53371edSJia Liu if (mask[2] == 1) { 3714b53371edSJia Liu temp |= dsp & 0x2000; 3715b53371edSJia Liu } 3716b53371edSJia Liu 3717b53371edSJia Liu if (mask[3] == 1) { 3718b53371edSJia Liu temp |= dsp & 0x00FF0000; 3719b53371edSJia Liu } 3720b53371edSJia Liu 3721b53371edSJia Liu if (mask[4] == 1) { 3722eec8972aSPetar Jovanovic #if defined(TARGET_MIPS64) 3723b53371edSJia Liu temp |= dsp & 0xFF000000; 3724eec8972aSPetar Jovanovic #else 3725eec8972aSPetar Jovanovic temp |= dsp & 0x0F000000; 3726eec8972aSPetar Jovanovic #endif 3727b53371edSJia Liu } 3728b53371edSJia Liu 3729b53371edSJia Liu if (mask[5] == 1) { 3730b53371edSJia Liu temp |= dsp & 0x4000; 3731b53371edSJia Liu } 3732b53371edSJia Liu 3733b53371edSJia Liu return temp; 3734b53371edSJia Liu } 3735b53371edSJia Liu 3736084d0497SRichard Henderson target_ulong helper_rddsp(target_ulong mask_num, CPUMIPSState *env) 3737084d0497SRichard Henderson { 3738084d0497SRichard Henderson return cpu_rddsp(mask_num, env); 3739084d0497SRichard Henderson } 3740084d0497SRichard Henderson 3741b53371edSJia Liu 3742461c08dfSJia Liu #undef MIPSDSP_LHI 3743461c08dfSJia Liu #undef MIPSDSP_LLO 3744461c08dfSJia Liu #undef MIPSDSP_HI 3745461c08dfSJia Liu #undef MIPSDSP_LO 3746461c08dfSJia Liu #undef MIPSDSP_Q3 3747461c08dfSJia Liu #undef MIPSDSP_Q2 3748461c08dfSJia Liu #undef MIPSDSP_Q1 3749461c08dfSJia Liu #undef MIPSDSP_Q0 3750461c08dfSJia Liu 3751461c08dfSJia Liu #undef MIPSDSP_SPLIT32_8 3752461c08dfSJia Liu #undef MIPSDSP_SPLIT32_16 3753461c08dfSJia Liu 3754461c08dfSJia Liu #undef MIPSDSP_RETURN32_8 3755461c08dfSJia Liu #undef MIPSDSP_RETURN32_16 3756461c08dfSJia Liu 3757461c08dfSJia Liu #ifdef TARGET_MIPS64 3758461c08dfSJia Liu #undef MIPSDSP_SPLIT64_16 3759461c08dfSJia Liu #undef MIPSDSP_SPLIT64_32 3760461c08dfSJia Liu #undef MIPSDSP_RETURN64_16 3761461c08dfSJia Liu #undef MIPSDSP_RETURN64_32 3762461c08dfSJia Liu #endif 3763