148e06fe0SBastian Koppelmann /* 248e06fe0SBastian Koppelmann * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn 348e06fe0SBastian Koppelmann * 448e06fe0SBastian Koppelmann * This library is free software; you can redistribute it and/or 548e06fe0SBastian Koppelmann * modify it under the terms of the GNU Lesser General Public 648e06fe0SBastian Koppelmann * License as published by the Free Software Foundation; either 748e06fe0SBastian Koppelmann * version 2 of the License, or (at your option) any later version. 848e06fe0SBastian Koppelmann * 948e06fe0SBastian Koppelmann * This library is distributed in the hope that it will be useful, 1048e06fe0SBastian Koppelmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 1148e06fe0SBastian Koppelmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1248e06fe0SBastian Koppelmann * Lesser General Public License for more details. 1348e06fe0SBastian Koppelmann * 1448e06fe0SBastian Koppelmann * You should have received a copy of the GNU Lesser General Public 1548e06fe0SBastian Koppelmann * License along with this library; if not, see <http://www.gnu.org/licenses/>. 1648e06fe0SBastian Koppelmann */ 1748e06fe0SBastian Koppelmann #include <stdlib.h> 1848e06fe0SBastian Koppelmann #include "cpu.h" 1948e06fe0SBastian Koppelmann #include "qemu/host-utils.h" 2048e06fe0SBastian Koppelmann #include "exec/helper-proto.h" 2148e06fe0SBastian Koppelmann #include "exec/cpu_ldst.h" 2248e06fe0SBastian Koppelmann 233a16ecb0SBastian Koppelmann /* Addressing mode helper */ 243a16ecb0SBastian Koppelmann 253a16ecb0SBastian Koppelmann static uint16_t reverse16(uint16_t val) 263a16ecb0SBastian Koppelmann { 273a16ecb0SBastian Koppelmann uint8_t high = (uint8_t)(val >> 8); 283a16ecb0SBastian Koppelmann uint8_t low = (uint8_t)(val & 0xff); 293a16ecb0SBastian Koppelmann 303a16ecb0SBastian Koppelmann uint16_t rh, rl; 313a16ecb0SBastian Koppelmann 323a16ecb0SBastian Koppelmann rl = (uint16_t)((high * 0x0202020202ULL & 0x010884422010ULL) % 1023); 333a16ecb0SBastian Koppelmann rh = (uint16_t)((low * 0x0202020202ULL & 0x010884422010ULL) % 1023); 343a16ecb0SBastian Koppelmann 353a16ecb0SBastian Koppelmann return (rh << 8) | rl; 363a16ecb0SBastian Koppelmann } 373a16ecb0SBastian Koppelmann 383a16ecb0SBastian Koppelmann uint32_t helper_br_update(uint32_t reg) 393a16ecb0SBastian Koppelmann { 403a16ecb0SBastian Koppelmann uint32_t index = reg & 0xffff; 413a16ecb0SBastian Koppelmann uint32_t incr = reg >> 16; 423a16ecb0SBastian Koppelmann uint32_t new_index = reverse16(reverse16(index) + reverse16(incr)); 433a16ecb0SBastian Koppelmann return reg - index + new_index; 443a16ecb0SBastian Koppelmann } 453a16ecb0SBastian Koppelmann 463a16ecb0SBastian Koppelmann uint32_t helper_circ_update(uint32_t reg, uint32_t off) 473a16ecb0SBastian Koppelmann { 483a16ecb0SBastian Koppelmann uint32_t index = reg & 0xffff; 493a16ecb0SBastian Koppelmann uint32_t length = reg >> 16; 503a16ecb0SBastian Koppelmann int32_t new_index = index + off; 513a16ecb0SBastian Koppelmann if (new_index < 0) { 523a16ecb0SBastian Koppelmann new_index += length; 533a16ecb0SBastian Koppelmann } else { 543a16ecb0SBastian Koppelmann new_index %= length; 553a16ecb0SBastian Koppelmann } 563a16ecb0SBastian Koppelmann return reg - index + new_index; 573a16ecb0SBastian Koppelmann } 583a16ecb0SBastian Koppelmann 59e4e39176SBastian Koppelmann static uint32_t ssov32(CPUTriCoreState *env, int64_t arg) 60e4e39176SBastian Koppelmann { 61e4e39176SBastian Koppelmann uint32_t ret; 62e4e39176SBastian Koppelmann int64_t max_pos = INT32_MAX; 63e4e39176SBastian Koppelmann int64_t max_neg = INT32_MIN; 64e4e39176SBastian Koppelmann if (arg > max_pos) { 65e4e39176SBastian Koppelmann env->PSW_USB_V = (1 << 31); 66e4e39176SBastian Koppelmann env->PSW_USB_SV = (1 << 31); 67e4e39176SBastian Koppelmann ret = (target_ulong)max_pos; 68e4e39176SBastian Koppelmann } else { 69e4e39176SBastian Koppelmann if (arg < max_neg) { 70e4e39176SBastian Koppelmann env->PSW_USB_V = (1 << 31); 71e4e39176SBastian Koppelmann env->PSW_USB_SV = (1 << 31); 72e4e39176SBastian Koppelmann ret = (target_ulong)max_neg; 73e4e39176SBastian Koppelmann } else { 74e4e39176SBastian Koppelmann env->PSW_USB_V = 0; 75e4e39176SBastian Koppelmann ret = (target_ulong)arg; 76e4e39176SBastian Koppelmann } 77e4e39176SBastian Koppelmann } 78e4e39176SBastian Koppelmann env->PSW_USB_AV = arg ^ arg * 2u; 79e4e39176SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 80e4e39176SBastian Koppelmann return ret; 81e4e39176SBastian Koppelmann } 822692802aSBastian Koppelmann 8385d604afSBastian Koppelmann static uint32_t suov32_pos(CPUTriCoreState *env, uint64_t arg) 84e4e39176SBastian Koppelmann { 85e4e39176SBastian Koppelmann uint32_t ret; 8685d604afSBastian Koppelmann uint64_t max_pos = UINT32_MAX; 87e4e39176SBastian Koppelmann if (arg > max_pos) { 88e4e39176SBastian Koppelmann env->PSW_USB_V = (1 << 31); 89e4e39176SBastian Koppelmann env->PSW_USB_SV = (1 << 31); 90e4e39176SBastian Koppelmann ret = (target_ulong)max_pos; 91e4e39176SBastian Koppelmann } else { 9285d604afSBastian Koppelmann env->PSW_USB_V = 0; 9385d604afSBastian Koppelmann ret = (target_ulong)arg; 9485d604afSBastian Koppelmann } 9585d604afSBastian Koppelmann env->PSW_USB_AV = arg ^ arg * 2u; 9685d604afSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 9785d604afSBastian Koppelmann return ret; 9885d604afSBastian Koppelmann } 9985d604afSBastian Koppelmann 10085d604afSBastian Koppelmann static uint32_t suov32_neg(CPUTriCoreState *env, int64_t arg) 10185d604afSBastian Koppelmann { 10285d604afSBastian Koppelmann uint32_t ret; 10385d604afSBastian Koppelmann 104e4e39176SBastian Koppelmann if (arg < 0) { 105e4e39176SBastian Koppelmann env->PSW_USB_V = (1 << 31); 106e4e39176SBastian Koppelmann env->PSW_USB_SV = (1 << 31); 107e4e39176SBastian Koppelmann ret = 0; 108e4e39176SBastian Koppelmann } else { 109e4e39176SBastian Koppelmann env->PSW_USB_V = 0; 110e4e39176SBastian Koppelmann ret = (target_ulong)arg; 111e4e39176SBastian Koppelmann } 112e4e39176SBastian Koppelmann env->PSW_USB_AV = arg ^ arg * 2u; 113e4e39176SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 114e4e39176SBastian Koppelmann return ret; 115e4e39176SBastian Koppelmann } 1160974257eSBastian Koppelmann 117d5de7839SBastian Koppelmann static uint32_t ssov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1) 118d5de7839SBastian Koppelmann { 119d5de7839SBastian Koppelmann int32_t max_pos = INT16_MAX; 120d5de7839SBastian Koppelmann int32_t max_neg = INT16_MIN; 121d5de7839SBastian Koppelmann int32_t av0, av1; 122d5de7839SBastian Koppelmann 123d5de7839SBastian Koppelmann env->PSW_USB_V = 0; 124d5de7839SBastian Koppelmann av0 = hw0 ^ hw0 * 2u; 125d5de7839SBastian Koppelmann if (hw0 > max_pos) { 126d5de7839SBastian Koppelmann env->PSW_USB_V = (1 << 31); 127d5de7839SBastian Koppelmann hw0 = max_pos; 128d5de7839SBastian Koppelmann } else if (hw0 < max_neg) { 129d5de7839SBastian Koppelmann env->PSW_USB_V = (1 << 31); 130d5de7839SBastian Koppelmann hw0 = max_neg; 131d5de7839SBastian Koppelmann } 132d5de7839SBastian Koppelmann 133d5de7839SBastian Koppelmann av1 = hw1 ^ hw1 * 2u; 134d5de7839SBastian Koppelmann if (hw1 > max_pos) { 135d5de7839SBastian Koppelmann env->PSW_USB_V = (1 << 31); 136d5de7839SBastian Koppelmann hw1 = max_pos; 137d5de7839SBastian Koppelmann } else if (hw1 < max_neg) { 138d5de7839SBastian Koppelmann env->PSW_USB_V = (1 << 31); 139d5de7839SBastian Koppelmann hw1 = max_neg; 140d5de7839SBastian Koppelmann } 141d5de7839SBastian Koppelmann 142d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 143d5de7839SBastian Koppelmann env->PSW_USB_AV = (av0 | av1) << 16; 144d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 145d5de7839SBastian Koppelmann return (hw0 & 0xffff) | (hw1 << 16); 146d5de7839SBastian Koppelmann } 147d5de7839SBastian Koppelmann 148d5de7839SBastian Koppelmann static uint32_t suov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1) 149d5de7839SBastian Koppelmann { 150d5de7839SBastian Koppelmann int32_t max_pos = UINT16_MAX; 151d5de7839SBastian Koppelmann int32_t av0, av1; 152d5de7839SBastian Koppelmann 153d5de7839SBastian Koppelmann env->PSW_USB_V = 0; 154d5de7839SBastian Koppelmann av0 = hw0 ^ hw0 * 2u; 155d5de7839SBastian Koppelmann if (hw0 > max_pos) { 156d5de7839SBastian Koppelmann env->PSW_USB_V = (1 << 31); 157d5de7839SBastian Koppelmann hw0 = max_pos; 158d5de7839SBastian Koppelmann } else if (hw0 < 0) { 159d5de7839SBastian Koppelmann env->PSW_USB_V = (1 << 31); 160d5de7839SBastian Koppelmann hw0 = 0; 161d5de7839SBastian Koppelmann } 162d5de7839SBastian Koppelmann 163d5de7839SBastian Koppelmann av1 = hw1 ^ hw1 * 2u; 164d5de7839SBastian Koppelmann if (hw1 > max_pos) { 165d5de7839SBastian Koppelmann env->PSW_USB_V = (1 << 31); 166d5de7839SBastian Koppelmann hw1 = max_pos; 167d5de7839SBastian Koppelmann } else if (hw1 < 0) { 168d5de7839SBastian Koppelmann env->PSW_USB_V = (1 << 31); 169d5de7839SBastian Koppelmann hw1 = 0; 170d5de7839SBastian Koppelmann } 171d5de7839SBastian Koppelmann 172d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 173d5de7839SBastian Koppelmann env->PSW_USB_AV = (av0 | av1) << 16; 174d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 175d5de7839SBastian Koppelmann return (hw0 & 0xffff) | (hw1 << 16); 176d5de7839SBastian Koppelmann } 1770974257eSBastian Koppelmann 1782692802aSBastian Koppelmann target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, 1792692802aSBastian Koppelmann target_ulong r2) 1802692802aSBastian Koppelmann { 1812692802aSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 1822692802aSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 1832692802aSBastian Koppelmann int64_t result = t1 + t2; 184e4e39176SBastian Koppelmann return ssov32(env, result); 1852692802aSBastian Koppelmann } 1862692802aSBastian Koppelmann 1872e430e1cSBastian Koppelmann uint64_t helper_add64_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) 1882e430e1cSBastian Koppelmann { 1892e430e1cSBastian Koppelmann uint64_t result; 1902e430e1cSBastian Koppelmann int64_t ovf; 1912e430e1cSBastian Koppelmann 1922e430e1cSBastian Koppelmann result = r1 + r2; 1932e430e1cSBastian Koppelmann ovf = (result ^ r1) & ~(r1 ^ r2); 1942e430e1cSBastian Koppelmann env->PSW_USB_AV = (result ^ result * 2u) >> 32; 1952e430e1cSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 1962e430e1cSBastian Koppelmann if (ovf < 0) { 1972e430e1cSBastian Koppelmann env->PSW_USB_V = (1 << 31); 1982e430e1cSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 1992e430e1cSBastian Koppelmann /* ext_ret > MAX_INT */ 2002e430e1cSBastian Koppelmann if ((int64_t)r1 >= 0) { 2012e430e1cSBastian Koppelmann result = INT64_MAX; 2022e430e1cSBastian Koppelmann /* ext_ret < MIN_INT */ 2032e430e1cSBastian Koppelmann } else { 2042e430e1cSBastian Koppelmann result = INT64_MIN; 2052e430e1cSBastian Koppelmann } 2062e430e1cSBastian Koppelmann } else { 2072e430e1cSBastian Koppelmann env->PSW_USB_V = 0; 2082e430e1cSBastian Koppelmann } 2092e430e1cSBastian Koppelmann return result; 2102e430e1cSBastian Koppelmann } 2112e430e1cSBastian Koppelmann 212d5de7839SBastian Koppelmann target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1, 213d5de7839SBastian Koppelmann target_ulong r2) 214d5de7839SBastian Koppelmann { 215d5de7839SBastian Koppelmann int32_t ret_hw0, ret_hw1; 216d5de7839SBastian Koppelmann 217d5de7839SBastian Koppelmann ret_hw0 = sextract32(r1, 0, 16) + sextract32(r2, 0, 16); 218d5de7839SBastian Koppelmann ret_hw1 = sextract32(r1, 16, 16) + sextract32(r2, 16, 16); 219d5de7839SBastian Koppelmann return ssov16(env, ret_hw0, ret_hw1); 220d5de7839SBastian Koppelmann } 221d5de7839SBastian Koppelmann 2222e430e1cSBastian Koppelmann uint32_t helper_addr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 2232e430e1cSBastian Koppelmann uint32_t r2_h) 2242e430e1cSBastian Koppelmann { 2252e430e1cSBastian Koppelmann int64_t mul_res0 = sextract64(r1, 0, 32); 2262e430e1cSBastian Koppelmann int64_t mul_res1 = sextract64(r1, 32, 32); 2272e430e1cSBastian Koppelmann int64_t r2_low = sextract64(r2_l, 0, 32); 2282e430e1cSBastian Koppelmann int64_t r2_high = sextract64(r2_h, 0, 32); 2292e430e1cSBastian Koppelmann int64_t result0, result1; 2302e430e1cSBastian Koppelmann uint32_t ovf0, ovf1; 2312e430e1cSBastian Koppelmann uint32_t avf0, avf1; 2322e430e1cSBastian Koppelmann 2332e430e1cSBastian Koppelmann ovf0 = ovf1 = 0; 2342e430e1cSBastian Koppelmann 2352e430e1cSBastian Koppelmann result0 = r2_low + mul_res0 + 0x8000; 2362e430e1cSBastian Koppelmann result1 = r2_high + mul_res1 + 0x8000; 2372e430e1cSBastian Koppelmann 2382e430e1cSBastian Koppelmann avf0 = result0 * 2u; 2392e430e1cSBastian Koppelmann avf0 = result0 ^ avf0; 2402e430e1cSBastian Koppelmann avf1 = result1 * 2u; 2412e430e1cSBastian Koppelmann avf1 = result1 ^ avf1; 2422e430e1cSBastian Koppelmann 2432e430e1cSBastian Koppelmann if (result0 > INT32_MAX) { 2442e430e1cSBastian Koppelmann ovf0 = (1 << 31); 2452e430e1cSBastian Koppelmann result0 = INT32_MAX; 2462e430e1cSBastian Koppelmann } else if (result0 < INT32_MIN) { 2472e430e1cSBastian Koppelmann ovf0 = (1 << 31); 2482e430e1cSBastian Koppelmann result0 = INT32_MIN; 2492e430e1cSBastian Koppelmann } 2502e430e1cSBastian Koppelmann 2512e430e1cSBastian Koppelmann if (result1 > INT32_MAX) { 2522e430e1cSBastian Koppelmann ovf1 = (1 << 31); 2532e430e1cSBastian Koppelmann result1 = INT32_MAX; 2542e430e1cSBastian Koppelmann } else if (result1 < INT32_MIN) { 2552e430e1cSBastian Koppelmann ovf1 = (1 << 31); 2562e430e1cSBastian Koppelmann result1 = INT32_MIN; 2572e430e1cSBastian Koppelmann } 2582e430e1cSBastian Koppelmann 2592e430e1cSBastian Koppelmann env->PSW_USB_V = ovf0 | ovf1; 2602e430e1cSBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 2612e430e1cSBastian Koppelmann 2622e430e1cSBastian Koppelmann env->PSW_USB_AV = avf0 | avf1; 2632e430e1cSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 2642e430e1cSBastian Koppelmann 2652e430e1cSBastian Koppelmann return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 2662e430e1cSBastian Koppelmann } 2672e430e1cSBastian Koppelmann 268bebe80fcSBastian Koppelmann uint32_t helper_addsur_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 269bebe80fcSBastian Koppelmann uint32_t r2_h) 270bebe80fcSBastian Koppelmann { 271bebe80fcSBastian Koppelmann int64_t mul_res0 = sextract64(r1, 0, 32); 272bebe80fcSBastian Koppelmann int64_t mul_res1 = sextract64(r1, 32, 32); 273bebe80fcSBastian Koppelmann int64_t r2_low = sextract64(r2_l, 0, 32); 274bebe80fcSBastian Koppelmann int64_t r2_high = sextract64(r2_h, 0, 32); 275bebe80fcSBastian Koppelmann int64_t result0, result1; 276bebe80fcSBastian Koppelmann uint32_t ovf0, ovf1; 277bebe80fcSBastian Koppelmann uint32_t avf0, avf1; 278bebe80fcSBastian Koppelmann 279bebe80fcSBastian Koppelmann ovf0 = ovf1 = 0; 280bebe80fcSBastian Koppelmann 281bebe80fcSBastian Koppelmann result0 = r2_low - mul_res0 + 0x8000; 282bebe80fcSBastian Koppelmann result1 = r2_high + mul_res1 + 0x8000; 283bebe80fcSBastian Koppelmann 284bebe80fcSBastian Koppelmann avf0 = result0 * 2u; 285bebe80fcSBastian Koppelmann avf0 = result0 ^ avf0; 286bebe80fcSBastian Koppelmann avf1 = result1 * 2u; 287bebe80fcSBastian Koppelmann avf1 = result1 ^ avf1; 288bebe80fcSBastian Koppelmann 289bebe80fcSBastian Koppelmann if (result0 > INT32_MAX) { 290bebe80fcSBastian Koppelmann ovf0 = (1 << 31); 291bebe80fcSBastian Koppelmann result0 = INT32_MAX; 292bebe80fcSBastian Koppelmann } else if (result0 < INT32_MIN) { 293bebe80fcSBastian Koppelmann ovf0 = (1 << 31); 294bebe80fcSBastian Koppelmann result0 = INT32_MIN; 295bebe80fcSBastian Koppelmann } 296bebe80fcSBastian Koppelmann 297bebe80fcSBastian Koppelmann if (result1 > INT32_MAX) { 298bebe80fcSBastian Koppelmann ovf1 = (1 << 31); 299bebe80fcSBastian Koppelmann result1 = INT32_MAX; 300bebe80fcSBastian Koppelmann } else if (result1 < INT32_MIN) { 301bebe80fcSBastian Koppelmann ovf1 = (1 << 31); 302bebe80fcSBastian Koppelmann result1 = INT32_MIN; 303bebe80fcSBastian Koppelmann } 304bebe80fcSBastian Koppelmann 305bebe80fcSBastian Koppelmann env->PSW_USB_V = ovf0 | ovf1; 306bebe80fcSBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 307bebe80fcSBastian Koppelmann 308bebe80fcSBastian Koppelmann env->PSW_USB_AV = avf0 | avf1; 309bebe80fcSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 310bebe80fcSBastian Koppelmann 311bebe80fcSBastian Koppelmann return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 312bebe80fcSBastian Koppelmann } 313bebe80fcSBastian Koppelmann 3142e430e1cSBastian Koppelmann 3150974257eSBastian Koppelmann target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, 3160974257eSBastian Koppelmann target_ulong r2) 3170974257eSBastian Koppelmann { 3180974257eSBastian Koppelmann int64_t t1 = extract64(r1, 0, 32); 3190974257eSBastian Koppelmann int64_t t2 = extract64(r2, 0, 32); 3200974257eSBastian Koppelmann int64_t result = t1 + t2; 32185d604afSBastian Koppelmann return suov32_pos(env, result); 3220974257eSBastian Koppelmann } 3230974257eSBastian Koppelmann 324d5de7839SBastian Koppelmann target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1, 325d5de7839SBastian Koppelmann target_ulong r2) 326d5de7839SBastian Koppelmann { 327d5de7839SBastian Koppelmann int32_t ret_hw0, ret_hw1; 328d5de7839SBastian Koppelmann 329d5de7839SBastian Koppelmann ret_hw0 = extract32(r1, 0, 16) + extract32(r2, 0, 16); 330d5de7839SBastian Koppelmann ret_hw1 = extract32(r1, 16, 16) + extract32(r2, 16, 16); 331d5de7839SBastian Koppelmann return suov16(env, ret_hw0, ret_hw1); 332d5de7839SBastian Koppelmann } 333d5de7839SBastian Koppelmann 3342692802aSBastian Koppelmann target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, 3352692802aSBastian Koppelmann target_ulong r2) 3362692802aSBastian Koppelmann { 3372692802aSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 3382692802aSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 3392692802aSBastian Koppelmann int64_t result = t1 - t2; 340e4e39176SBastian Koppelmann return ssov32(env, result); 3412692802aSBastian Koppelmann } 3422692802aSBastian Koppelmann 343d5de7839SBastian Koppelmann target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1, 344d5de7839SBastian Koppelmann target_ulong r2) 345d5de7839SBastian Koppelmann { 346d5de7839SBastian Koppelmann int32_t ret_hw0, ret_hw1; 347d5de7839SBastian Koppelmann 348d5de7839SBastian Koppelmann ret_hw0 = sextract32(r1, 0, 16) - sextract32(r2, 0, 16); 349d5de7839SBastian Koppelmann ret_hw1 = sextract32(r1, 16, 16) - sextract32(r2, 16, 16); 350d5de7839SBastian Koppelmann return ssov16(env, ret_hw0, ret_hw1); 351d5de7839SBastian Koppelmann } 352d5de7839SBastian Koppelmann 3530974257eSBastian Koppelmann target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, 3540974257eSBastian Koppelmann target_ulong r2) 3550974257eSBastian Koppelmann { 3560974257eSBastian Koppelmann int64_t t1 = extract64(r1, 0, 32); 3570974257eSBastian Koppelmann int64_t t2 = extract64(r2, 0, 32); 3580974257eSBastian Koppelmann int64_t result = t1 - t2; 35985d604afSBastian Koppelmann return suov32_neg(env, result); 3600974257eSBastian Koppelmann } 3610974257eSBastian Koppelmann 362d5de7839SBastian Koppelmann target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1, 363d5de7839SBastian Koppelmann target_ulong r2) 364d5de7839SBastian Koppelmann { 365d5de7839SBastian Koppelmann int32_t ret_hw0, ret_hw1; 366d5de7839SBastian Koppelmann 367d5de7839SBastian Koppelmann ret_hw0 = extract32(r1, 0, 16) - extract32(r2, 0, 16); 368d5de7839SBastian Koppelmann ret_hw1 = extract32(r1, 16, 16) - extract32(r2, 16, 16); 369d5de7839SBastian Koppelmann return suov16(env, ret_hw0, ret_hw1); 370d5de7839SBastian Koppelmann } 371d5de7839SBastian Koppelmann 3720974257eSBastian Koppelmann target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1, 3730974257eSBastian Koppelmann target_ulong r2) 3740974257eSBastian Koppelmann { 3750974257eSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 3760974257eSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 3770974257eSBastian Koppelmann int64_t result = t1 * t2; 378e4e39176SBastian Koppelmann return ssov32(env, result); 3790974257eSBastian Koppelmann } 3800974257eSBastian Koppelmann 3810974257eSBastian Koppelmann target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1, 3820974257eSBastian Koppelmann target_ulong r2) 3830974257eSBastian Koppelmann { 3840974257eSBastian Koppelmann int64_t t1 = extract64(r1, 0, 32); 3850974257eSBastian Koppelmann int64_t t2 = extract64(r2, 0, 32); 3860974257eSBastian Koppelmann int64_t result = t1 * t2; 3875f30046fSBastian Koppelmann 38885d604afSBastian Koppelmann return suov32_pos(env, result); 3890974257eSBastian Koppelmann } 3900974257eSBastian Koppelmann 3910974257eSBastian Koppelmann target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, 3920974257eSBastian Koppelmann target_ulong r2) 3930974257eSBastian Koppelmann { 3940974257eSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 3950974257eSBastian Koppelmann int32_t t2 = sextract64(r2, 0, 6); 3960974257eSBastian Koppelmann int64_t result; 3970974257eSBastian Koppelmann if (t2 == 0) { 3980974257eSBastian Koppelmann result = t1; 3990974257eSBastian Koppelmann } else if (t2 > 0) { 4000974257eSBastian Koppelmann result = t1 << t2; 4010974257eSBastian Koppelmann } else { 4020974257eSBastian Koppelmann result = t1 >> -t2; 4030974257eSBastian Koppelmann } 404e4e39176SBastian Koppelmann return ssov32(env, result); 4050974257eSBastian Koppelmann } 4060974257eSBastian Koppelmann 407d5de7839SBastian Koppelmann uint32_t helper_abs_ssov(CPUTriCoreState *env, target_ulong r1) 408d5de7839SBastian Koppelmann { 409d5de7839SBastian Koppelmann target_ulong result; 410d5de7839SBastian Koppelmann result = ((int32_t)r1 >= 0) ? r1 : (0 - r1); 411d5de7839SBastian Koppelmann return ssov32(env, result); 412d5de7839SBastian Koppelmann } 413d5de7839SBastian Koppelmann 414d5de7839SBastian Koppelmann uint32_t helper_abs_h_ssov(CPUTriCoreState *env, target_ulong r1) 415d5de7839SBastian Koppelmann { 416d5de7839SBastian Koppelmann int32_t ret_h0, ret_h1; 417d5de7839SBastian Koppelmann 418d5de7839SBastian Koppelmann ret_h0 = sextract32(r1, 0, 16); 419d5de7839SBastian Koppelmann ret_h0 = (ret_h0 >= 0) ? ret_h0 : (0 - ret_h0); 420d5de7839SBastian Koppelmann 421d5de7839SBastian Koppelmann ret_h1 = sextract32(r1, 16, 16); 422d5de7839SBastian Koppelmann ret_h1 = (ret_h1 >= 0) ? ret_h1 : (0 - ret_h1); 423d5de7839SBastian Koppelmann 424d5de7839SBastian Koppelmann return ssov16(env, ret_h0, ret_h1); 425d5de7839SBastian Koppelmann } 426d5de7839SBastian Koppelmann 4270974257eSBastian Koppelmann target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, 4280974257eSBastian Koppelmann target_ulong r2) 4290974257eSBastian Koppelmann { 4300974257eSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 4310974257eSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 4320974257eSBastian Koppelmann int64_t result; 4330974257eSBastian Koppelmann 4340974257eSBastian Koppelmann if (t1 > t2) { 4350974257eSBastian Koppelmann result = t1 - t2; 4360974257eSBastian Koppelmann } else { 4370974257eSBastian Koppelmann result = t2 - t1; 4380974257eSBastian Koppelmann } 439e4e39176SBastian Koppelmann return ssov32(env, result); 4400974257eSBastian Koppelmann } 441328f1f0fSBastian Koppelmann 442d5de7839SBastian Koppelmann uint32_t helper_absdif_h_ssov(CPUTriCoreState *env, target_ulong r1, 443d5de7839SBastian Koppelmann target_ulong r2) 444d5de7839SBastian Koppelmann { 445d5de7839SBastian Koppelmann int32_t t1, t2; 446d5de7839SBastian Koppelmann int32_t ret_h0, ret_h1; 447d5de7839SBastian Koppelmann 448d5de7839SBastian Koppelmann t1 = sextract32(r1, 0, 16); 449d5de7839SBastian Koppelmann t2 = sextract32(r2, 0, 16); 450d5de7839SBastian Koppelmann if (t1 > t2) { 451d5de7839SBastian Koppelmann ret_h0 = t1 - t2; 452d5de7839SBastian Koppelmann } else { 453d5de7839SBastian Koppelmann ret_h0 = t2 - t1; 454d5de7839SBastian Koppelmann } 455d5de7839SBastian Koppelmann 456d5de7839SBastian Koppelmann t1 = sextract32(r1, 16, 16); 457d5de7839SBastian Koppelmann t2 = sextract32(r2, 16, 16); 458d5de7839SBastian Koppelmann if (t1 > t2) { 459d5de7839SBastian Koppelmann ret_h1 = t1 - t2; 460d5de7839SBastian Koppelmann } else { 461d5de7839SBastian Koppelmann ret_h1 = t2 - t1; 462d5de7839SBastian Koppelmann } 463d5de7839SBastian Koppelmann 464d5de7839SBastian Koppelmann return ssov16(env, ret_h0, ret_h1); 465d5de7839SBastian Koppelmann } 466d5de7839SBastian Koppelmann 467328f1f0fSBastian Koppelmann target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1, 468328f1f0fSBastian Koppelmann target_ulong r2, target_ulong r3) 469328f1f0fSBastian Koppelmann { 470328f1f0fSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 471328f1f0fSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 472328f1f0fSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 473328f1f0fSBastian Koppelmann int64_t result; 474328f1f0fSBastian Koppelmann 475328f1f0fSBastian Koppelmann result = t2 + (t1 * t3); 476e4e39176SBastian Koppelmann return ssov32(env, result); 477328f1f0fSBastian Koppelmann } 478328f1f0fSBastian Koppelmann 479328f1f0fSBastian Koppelmann target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1, 480328f1f0fSBastian Koppelmann target_ulong r2, target_ulong r3) 481328f1f0fSBastian Koppelmann { 482328f1f0fSBastian Koppelmann uint64_t t1 = extract64(r1, 0, 32); 483328f1f0fSBastian Koppelmann uint64_t t2 = extract64(r2, 0, 32); 484328f1f0fSBastian Koppelmann uint64_t t3 = extract64(r3, 0, 32); 485328f1f0fSBastian Koppelmann int64_t result; 486328f1f0fSBastian Koppelmann 487328f1f0fSBastian Koppelmann result = t2 + (t1 * t3); 48885d604afSBastian Koppelmann return suov32_pos(env, result); 489328f1f0fSBastian Koppelmann } 490328f1f0fSBastian Koppelmann 491328f1f0fSBastian Koppelmann uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1, 492328f1f0fSBastian Koppelmann uint64_t r2, target_ulong r3) 493328f1f0fSBastian Koppelmann { 494328f1f0fSBastian Koppelmann uint64_t ret, ovf; 495328f1f0fSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 496328f1f0fSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 497328f1f0fSBastian Koppelmann int64_t mul; 498328f1f0fSBastian Koppelmann 499328f1f0fSBastian Koppelmann mul = t1 * t3; 500328f1f0fSBastian Koppelmann ret = mul + r2; 501328f1f0fSBastian Koppelmann ovf = (ret ^ mul) & ~(mul ^ r2); 502328f1f0fSBastian Koppelmann 503811ea608SBastian Koppelmann t1 = ret >> 32; 504811ea608SBastian Koppelmann env->PSW_USB_AV = t1 ^ t1 * 2u; 505811ea608SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 506811ea608SBastian Koppelmann 507328f1f0fSBastian Koppelmann if ((int64_t)ovf < 0) { 508328f1f0fSBastian Koppelmann env->PSW_USB_V = (1 << 31); 509328f1f0fSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 510328f1f0fSBastian Koppelmann /* ext_ret > MAX_INT */ 511328f1f0fSBastian Koppelmann if (mul >= 0) { 512328f1f0fSBastian Koppelmann ret = INT64_MAX; 513328f1f0fSBastian Koppelmann /* ext_ret < MIN_INT */ 514328f1f0fSBastian Koppelmann } else { 515328f1f0fSBastian Koppelmann ret = INT64_MIN; 516328f1f0fSBastian Koppelmann } 517328f1f0fSBastian Koppelmann } else { 518328f1f0fSBastian Koppelmann env->PSW_USB_V = 0; 519328f1f0fSBastian Koppelmann } 520328f1f0fSBastian Koppelmann 521328f1f0fSBastian Koppelmann return ret; 522328f1f0fSBastian Koppelmann } 523328f1f0fSBastian Koppelmann 524b00aa8ecSBastian Koppelmann uint32_t 525b00aa8ecSBastian Koppelmann helper_madd32_q_add_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) 526b00aa8ecSBastian Koppelmann { 527b00aa8ecSBastian Koppelmann int64_t result; 528b00aa8ecSBastian Koppelmann 529b00aa8ecSBastian Koppelmann result = (r1 + r2); 530b00aa8ecSBastian Koppelmann 531b00aa8ecSBastian Koppelmann env->PSW_USB_AV = (result ^ result * 2u); 532b00aa8ecSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 533b00aa8ecSBastian Koppelmann 534b00aa8ecSBastian Koppelmann /* we do the saturation by hand, since we produce an overflow on the host 535b00aa8ecSBastian Koppelmann if the mul before was (0x80000000 * 0x80000000) << 1). If this is the 536b00aa8ecSBastian Koppelmann case, we flip the saturated value. */ 537b00aa8ecSBastian Koppelmann if (r2 == 0x8000000000000000LL) { 538b00aa8ecSBastian Koppelmann if (result > 0x7fffffffLL) { 539b00aa8ecSBastian Koppelmann env->PSW_USB_V = (1 << 31); 540b00aa8ecSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 541b00aa8ecSBastian Koppelmann result = INT32_MIN; 542b00aa8ecSBastian Koppelmann } else if (result < -0x80000000LL) { 543b00aa8ecSBastian Koppelmann env->PSW_USB_V = (1 << 31); 544b00aa8ecSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 545b00aa8ecSBastian Koppelmann result = INT32_MAX; 546b00aa8ecSBastian Koppelmann } else { 547b00aa8ecSBastian Koppelmann env->PSW_USB_V = 0; 548b00aa8ecSBastian Koppelmann } 549b00aa8ecSBastian Koppelmann } else { 550b00aa8ecSBastian Koppelmann if (result > 0x7fffffffLL) { 551b00aa8ecSBastian Koppelmann env->PSW_USB_V = (1 << 31); 552b00aa8ecSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 553b00aa8ecSBastian Koppelmann result = INT32_MAX; 554b00aa8ecSBastian Koppelmann } else if (result < -0x80000000LL) { 555b00aa8ecSBastian Koppelmann env->PSW_USB_V = (1 << 31); 556b00aa8ecSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 557b00aa8ecSBastian Koppelmann result = INT32_MIN; 558b00aa8ecSBastian Koppelmann } else { 559b00aa8ecSBastian Koppelmann env->PSW_USB_V = 0; 560b00aa8ecSBastian Koppelmann } 561b00aa8ecSBastian Koppelmann } 562b00aa8ecSBastian Koppelmann return (uint32_t)result; 563b00aa8ecSBastian Koppelmann } 564b00aa8ecSBastian Koppelmann 565b00aa8ecSBastian Koppelmann uint64_t helper_madd64_q_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2, 566b00aa8ecSBastian Koppelmann uint32_t r3, uint32_t n) 567b00aa8ecSBastian Koppelmann { 568b00aa8ecSBastian Koppelmann int64_t t1 = (int64_t)r1; 569b00aa8ecSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 570b00aa8ecSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 571b00aa8ecSBastian Koppelmann int64_t result, mul; 572b00aa8ecSBastian Koppelmann int64_t ovf; 573b00aa8ecSBastian Koppelmann 574b00aa8ecSBastian Koppelmann mul = (t2 * t3) << n; 575b00aa8ecSBastian Koppelmann result = mul + t1; 576b00aa8ecSBastian Koppelmann 577b00aa8ecSBastian Koppelmann env->PSW_USB_AV = (result ^ result * 2u) >> 32; 578b00aa8ecSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 579b00aa8ecSBastian Koppelmann 580b00aa8ecSBastian Koppelmann ovf = (result ^ mul) & ~(mul ^ t1); 581b00aa8ecSBastian Koppelmann /* we do the saturation by hand, since we produce an overflow on the host 582b00aa8ecSBastian Koppelmann if the mul was (0x80000000 * 0x80000000) << 1). If this is the 583b00aa8ecSBastian Koppelmann case, we flip the saturated value. */ 584b00aa8ecSBastian Koppelmann if ((r2 == 0x80000000) && (r3 == 0x80000000) && (n == 1)) { 585b00aa8ecSBastian Koppelmann if (ovf >= 0) { 586b00aa8ecSBastian Koppelmann env->PSW_USB_V = (1 << 31); 587b00aa8ecSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 588b00aa8ecSBastian Koppelmann /* ext_ret > MAX_INT */ 589b00aa8ecSBastian Koppelmann if (mul < 0) { 590b00aa8ecSBastian Koppelmann result = INT64_MAX; 591b00aa8ecSBastian Koppelmann /* ext_ret < MIN_INT */ 592b00aa8ecSBastian Koppelmann } else { 593b00aa8ecSBastian Koppelmann result = INT64_MIN; 594b00aa8ecSBastian Koppelmann } 595b00aa8ecSBastian Koppelmann } else { 596b00aa8ecSBastian Koppelmann env->PSW_USB_V = 0; 597b00aa8ecSBastian Koppelmann } 598b00aa8ecSBastian Koppelmann } else { 599b00aa8ecSBastian Koppelmann if (ovf < 0) { 600b00aa8ecSBastian Koppelmann env->PSW_USB_V = (1 << 31); 601b00aa8ecSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 602b00aa8ecSBastian Koppelmann /* ext_ret > MAX_INT */ 603b00aa8ecSBastian Koppelmann if (mul >= 0) { 604b00aa8ecSBastian Koppelmann result = INT64_MAX; 605b00aa8ecSBastian Koppelmann /* ext_ret < MIN_INT */ 606b00aa8ecSBastian Koppelmann } else { 607b00aa8ecSBastian Koppelmann result = INT64_MIN; 608b00aa8ecSBastian Koppelmann } 609b00aa8ecSBastian Koppelmann } else { 610b00aa8ecSBastian Koppelmann env->PSW_USB_V = 0; 611b00aa8ecSBastian Koppelmann } 612b00aa8ecSBastian Koppelmann } 613b00aa8ecSBastian Koppelmann return (uint64_t)result; 614b00aa8ecSBastian Koppelmann } 615b00aa8ecSBastian Koppelmann 616b00aa8ecSBastian Koppelmann uint32_t helper_maddr_q_ssov(CPUTriCoreState *env, uint32_t r1, uint32_t r2, 617b00aa8ecSBastian Koppelmann uint32_t r3, uint32_t n) 618b00aa8ecSBastian Koppelmann { 619b00aa8ecSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 620b00aa8ecSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 621b00aa8ecSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 622b00aa8ecSBastian Koppelmann int64_t mul, ret; 623b00aa8ecSBastian Koppelmann 624b00aa8ecSBastian Koppelmann if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { 625b00aa8ecSBastian Koppelmann mul = 0x7fffffff; 626b00aa8ecSBastian Koppelmann } else { 627b00aa8ecSBastian Koppelmann mul = (t2 * t3) << n; 628b00aa8ecSBastian Koppelmann } 629b00aa8ecSBastian Koppelmann 630b00aa8ecSBastian Koppelmann ret = t1 + mul + 0x8000; 631b00aa8ecSBastian Koppelmann 632b00aa8ecSBastian Koppelmann env->PSW_USB_AV = ret ^ ret * 2u; 633b00aa8ecSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 634b00aa8ecSBastian Koppelmann 635b00aa8ecSBastian Koppelmann if (ret > 0x7fffffffll) { 636b00aa8ecSBastian Koppelmann env->PSW_USB_V = (1 << 31); 637b00aa8ecSBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 638b00aa8ecSBastian Koppelmann ret = INT32_MAX; 639b00aa8ecSBastian Koppelmann } else if (ret < -0x80000000ll) { 640b00aa8ecSBastian Koppelmann env->PSW_USB_V = (1 << 31); 641b00aa8ecSBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 642b00aa8ecSBastian Koppelmann ret = INT32_MIN; 643b00aa8ecSBastian Koppelmann } else { 644b00aa8ecSBastian Koppelmann env->PSW_USB_V = 0; 645b00aa8ecSBastian Koppelmann } 646b00aa8ecSBastian Koppelmann return ret & 0xffff0000ll; 647b00aa8ecSBastian Koppelmann } 648b00aa8ecSBastian Koppelmann 649328f1f0fSBastian Koppelmann uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1, 650328f1f0fSBastian Koppelmann uint64_t r2, target_ulong r3) 651328f1f0fSBastian Koppelmann { 652328f1f0fSBastian Koppelmann uint64_t ret, mul; 653328f1f0fSBastian Koppelmann uint64_t t1 = extract64(r1, 0, 32); 654328f1f0fSBastian Koppelmann uint64_t t3 = extract64(r3, 0, 32); 655328f1f0fSBastian Koppelmann 656328f1f0fSBastian Koppelmann mul = t1 * t3; 657328f1f0fSBastian Koppelmann ret = mul + r2; 658328f1f0fSBastian Koppelmann 659811ea608SBastian Koppelmann t1 = ret >> 32; 660811ea608SBastian Koppelmann env->PSW_USB_AV = t1 ^ t1 * 2u; 661811ea608SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 662811ea608SBastian Koppelmann 663328f1f0fSBastian Koppelmann if (ret < r2) { 664328f1f0fSBastian Koppelmann env->PSW_USB_V = (1 << 31); 665328f1f0fSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 666328f1f0fSBastian Koppelmann /* saturate */ 667328f1f0fSBastian Koppelmann ret = UINT64_MAX; 668328f1f0fSBastian Koppelmann } else { 669328f1f0fSBastian Koppelmann env->PSW_USB_V = 0; 670328f1f0fSBastian Koppelmann } 671328f1f0fSBastian Koppelmann return ret; 672328f1f0fSBastian Koppelmann } 673328f1f0fSBastian Koppelmann 674328f1f0fSBastian Koppelmann target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1, 675328f1f0fSBastian Koppelmann target_ulong r2, target_ulong r3) 676328f1f0fSBastian Koppelmann { 677328f1f0fSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 678328f1f0fSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 679328f1f0fSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 680328f1f0fSBastian Koppelmann int64_t result; 681328f1f0fSBastian Koppelmann 682328f1f0fSBastian Koppelmann result = t2 - (t1 * t3); 683e4e39176SBastian Koppelmann return ssov32(env, result); 684328f1f0fSBastian Koppelmann } 685328f1f0fSBastian Koppelmann 686328f1f0fSBastian Koppelmann target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1, 687328f1f0fSBastian Koppelmann target_ulong r2, target_ulong r3) 688328f1f0fSBastian Koppelmann { 6893debbb5aSBastian Koppelmann uint64_t t1 = extract64(r1, 0, 32); 6903debbb5aSBastian Koppelmann uint64_t t2 = extract64(r2, 0, 32); 6913debbb5aSBastian Koppelmann uint64_t t3 = extract64(r3, 0, 32); 6923debbb5aSBastian Koppelmann uint64_t result; 6933debbb5aSBastian Koppelmann uint64_t mul; 694328f1f0fSBastian Koppelmann 6953debbb5aSBastian Koppelmann mul = (t1 * t3); 6963debbb5aSBastian Koppelmann result = t2 - mul; 6973debbb5aSBastian Koppelmann 6983debbb5aSBastian Koppelmann env->PSW_USB_AV = result ^ result * 2u; 6993debbb5aSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 7003debbb5aSBastian Koppelmann /* we calculate ovf by hand here, because the multiplication can overflow on 7013debbb5aSBastian Koppelmann the host, which would give false results if we compare to less than 7023debbb5aSBastian Koppelmann zero */ 7033debbb5aSBastian Koppelmann if (mul > t2) { 7043debbb5aSBastian Koppelmann env->PSW_USB_V = (1 << 31); 7053debbb5aSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 7063debbb5aSBastian Koppelmann result = 0; 7073debbb5aSBastian Koppelmann } else { 7083debbb5aSBastian Koppelmann env->PSW_USB_V = 0; 7093debbb5aSBastian Koppelmann } 7103debbb5aSBastian Koppelmann return result; 711328f1f0fSBastian Koppelmann } 712328f1f0fSBastian Koppelmann 713328f1f0fSBastian Koppelmann uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1, 714328f1f0fSBastian Koppelmann uint64_t r2, target_ulong r3) 715328f1f0fSBastian Koppelmann { 716328f1f0fSBastian Koppelmann uint64_t ret, ovf; 717328f1f0fSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 718328f1f0fSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 719328f1f0fSBastian Koppelmann int64_t mul; 720328f1f0fSBastian Koppelmann 721328f1f0fSBastian Koppelmann mul = t1 * t3; 722328f1f0fSBastian Koppelmann ret = r2 - mul; 723328f1f0fSBastian Koppelmann ovf = (ret ^ r2) & (mul ^ r2); 724328f1f0fSBastian Koppelmann 725811ea608SBastian Koppelmann t1 = ret >> 32; 726811ea608SBastian Koppelmann env->PSW_USB_AV = t1 ^ t1 * 2u; 727811ea608SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 728811ea608SBastian Koppelmann 729328f1f0fSBastian Koppelmann if ((int64_t)ovf < 0) { 730328f1f0fSBastian Koppelmann env->PSW_USB_V = (1 << 31); 731328f1f0fSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 732328f1f0fSBastian Koppelmann /* ext_ret > MAX_INT */ 733328f1f0fSBastian Koppelmann if (mul < 0) { 734328f1f0fSBastian Koppelmann ret = INT64_MAX; 735328f1f0fSBastian Koppelmann /* ext_ret < MIN_INT */ 736328f1f0fSBastian Koppelmann } else { 737328f1f0fSBastian Koppelmann ret = INT64_MIN; 738328f1f0fSBastian Koppelmann } 739328f1f0fSBastian Koppelmann } else { 740328f1f0fSBastian Koppelmann env->PSW_USB_V = 0; 741328f1f0fSBastian Koppelmann } 742328f1f0fSBastian Koppelmann return ret; 743328f1f0fSBastian Koppelmann } 744328f1f0fSBastian Koppelmann 745328f1f0fSBastian Koppelmann uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1, 746328f1f0fSBastian Koppelmann uint64_t r2, target_ulong r3) 747328f1f0fSBastian Koppelmann { 748328f1f0fSBastian Koppelmann uint64_t ret, mul; 749328f1f0fSBastian Koppelmann uint64_t t1 = extract64(r1, 0, 32); 750328f1f0fSBastian Koppelmann uint64_t t3 = extract64(r3, 0, 32); 751328f1f0fSBastian Koppelmann 752328f1f0fSBastian Koppelmann mul = t1 * t3; 753328f1f0fSBastian Koppelmann ret = r2 - mul; 754328f1f0fSBastian Koppelmann 755811ea608SBastian Koppelmann t1 = ret >> 32; 756811ea608SBastian Koppelmann env->PSW_USB_AV = t1 ^ t1 * 2u; 757811ea608SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 758811ea608SBastian Koppelmann 759328f1f0fSBastian Koppelmann if (ret > r2) { 760328f1f0fSBastian Koppelmann env->PSW_USB_V = (1 << 31); 761328f1f0fSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 762328f1f0fSBastian Koppelmann /* saturate */ 763328f1f0fSBastian Koppelmann ret = 0; 764328f1f0fSBastian Koppelmann } else { 765328f1f0fSBastian Koppelmann env->PSW_USB_V = 0; 766328f1f0fSBastian Koppelmann } 767328f1f0fSBastian Koppelmann return ret; 768328f1f0fSBastian Koppelmann } 769328f1f0fSBastian Koppelmann 770d5de7839SBastian Koppelmann uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg) 771d5de7839SBastian Koppelmann { 772d5de7839SBastian Koppelmann int32_t b, i; 773d5de7839SBastian Koppelmann int32_t ovf = 0; 774d5de7839SBastian Koppelmann int32_t avf = 0; 775d5de7839SBastian Koppelmann int32_t ret = 0; 776d5de7839SBastian Koppelmann 777d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { 778d5de7839SBastian Koppelmann b = sextract32(arg, i * 8, 8); 779d5de7839SBastian Koppelmann b = (b >= 0) ? b : (0 - b); 780d5de7839SBastian Koppelmann ovf |= (b > 0x7F) || (b < -0x80); 781d5de7839SBastian Koppelmann avf |= b ^ b * 2u; 782d5de7839SBastian Koppelmann ret |= (b & 0xff) << (i * 8); 783d5de7839SBastian Koppelmann } 784d5de7839SBastian Koppelmann 785d5de7839SBastian Koppelmann env->PSW_USB_V = ovf << 31; 786d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 787d5de7839SBastian Koppelmann env->PSW_USB_AV = avf << 24; 788d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 789d5de7839SBastian Koppelmann 790d5de7839SBastian Koppelmann return ret; 791d5de7839SBastian Koppelmann } 792d5de7839SBastian Koppelmann 793d5de7839SBastian Koppelmann uint32_t helper_abs_h(CPUTriCoreState *env, target_ulong arg) 794d5de7839SBastian Koppelmann { 795d5de7839SBastian Koppelmann int32_t h, i; 796d5de7839SBastian Koppelmann int32_t ovf = 0; 797d5de7839SBastian Koppelmann int32_t avf = 0; 798d5de7839SBastian Koppelmann int32_t ret = 0; 799d5de7839SBastian Koppelmann 800d5de7839SBastian Koppelmann for (i = 0; i < 2; i++) { 801d5de7839SBastian Koppelmann h = sextract32(arg, i * 16, 16); 802d5de7839SBastian Koppelmann h = (h >= 0) ? h : (0 - h); 803d5de7839SBastian Koppelmann ovf |= (h > 0x7FFF) || (h < -0x8000); 804d5de7839SBastian Koppelmann avf |= h ^ h * 2u; 805d5de7839SBastian Koppelmann ret |= (h & 0xffff) << (i * 16); 806d5de7839SBastian Koppelmann } 807d5de7839SBastian Koppelmann 808d5de7839SBastian Koppelmann env->PSW_USB_V = ovf << 31; 809d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 810d5de7839SBastian Koppelmann env->PSW_USB_AV = avf << 16; 811d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 812d5de7839SBastian Koppelmann 813d5de7839SBastian Koppelmann return ret; 814d5de7839SBastian Koppelmann } 815d5de7839SBastian Koppelmann 816d5de7839SBastian Koppelmann uint32_t helper_absdif_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 817d5de7839SBastian Koppelmann { 818d5de7839SBastian Koppelmann int32_t b, i; 819d5de7839SBastian Koppelmann int32_t extr_r2; 820d5de7839SBastian Koppelmann int32_t ovf = 0; 821d5de7839SBastian Koppelmann int32_t avf = 0; 822d5de7839SBastian Koppelmann int32_t ret = 0; 823d5de7839SBastian Koppelmann 824d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { 825d5de7839SBastian Koppelmann extr_r2 = sextract32(r2, i * 8, 8); 826d5de7839SBastian Koppelmann b = sextract32(r1, i * 8, 8); 827d5de7839SBastian Koppelmann b = (b > extr_r2) ? (b - extr_r2) : (extr_r2 - b); 828d5de7839SBastian Koppelmann ovf |= (b > 0x7F) || (b < -0x80); 829d5de7839SBastian Koppelmann avf |= b ^ b * 2u; 830d5de7839SBastian Koppelmann ret |= (b & 0xff) << (i * 8); 831d5de7839SBastian Koppelmann } 832d5de7839SBastian Koppelmann 833d5de7839SBastian Koppelmann env->PSW_USB_V = ovf << 31; 834d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 835d5de7839SBastian Koppelmann env->PSW_USB_AV = avf << 24; 836d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 837d5de7839SBastian Koppelmann return ret; 838d5de7839SBastian Koppelmann } 839d5de7839SBastian Koppelmann 840d5de7839SBastian Koppelmann uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 841d5de7839SBastian Koppelmann { 842d5de7839SBastian Koppelmann int32_t h, i; 843d5de7839SBastian Koppelmann int32_t extr_r2; 844d5de7839SBastian Koppelmann int32_t ovf = 0; 845d5de7839SBastian Koppelmann int32_t avf = 0; 846d5de7839SBastian Koppelmann int32_t ret = 0; 847d5de7839SBastian Koppelmann 848d5de7839SBastian Koppelmann for (i = 0; i < 2; i++) { 849d5de7839SBastian Koppelmann extr_r2 = sextract32(r2, i * 16, 16); 850d5de7839SBastian Koppelmann h = sextract32(r1, i * 16, 16); 851d5de7839SBastian Koppelmann h = (h > extr_r2) ? (h - extr_r2) : (extr_r2 - h); 852d5de7839SBastian Koppelmann ovf |= (h > 0x7FFF) || (h < -0x8000); 853d5de7839SBastian Koppelmann avf |= h ^ h * 2u; 854d5de7839SBastian Koppelmann ret |= (h & 0xffff) << (i * 16); 855d5de7839SBastian Koppelmann } 856d5de7839SBastian Koppelmann 857d5de7839SBastian Koppelmann env->PSW_USB_V = ovf << 31; 858d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 859d5de7839SBastian Koppelmann env->PSW_USB_AV = avf << 16; 860d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 861d5de7839SBastian Koppelmann 862d5de7839SBastian Koppelmann return ret; 863d5de7839SBastian Koppelmann } 864d5de7839SBastian Koppelmann 8652e430e1cSBastian Koppelmann uint32_t helper_addr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 8662e430e1cSBastian Koppelmann uint32_t r2_h) 8672e430e1cSBastian Koppelmann { 8682e430e1cSBastian Koppelmann int64_t mul_res0 = sextract64(r1, 0, 32); 8692e430e1cSBastian Koppelmann int64_t mul_res1 = sextract64(r1, 32, 32); 8702e430e1cSBastian Koppelmann int64_t r2_low = sextract64(r2_l, 0, 32); 8712e430e1cSBastian Koppelmann int64_t r2_high = sextract64(r2_h, 0, 32); 8722e430e1cSBastian Koppelmann int64_t result0, result1; 8732e430e1cSBastian Koppelmann uint32_t ovf0, ovf1; 8742e430e1cSBastian Koppelmann uint32_t avf0, avf1; 8752e430e1cSBastian Koppelmann 8762e430e1cSBastian Koppelmann ovf0 = ovf1 = 0; 8772e430e1cSBastian Koppelmann 8782e430e1cSBastian Koppelmann result0 = r2_low + mul_res0 + 0x8000; 8792e430e1cSBastian Koppelmann result1 = r2_high + mul_res1 + 0x8000; 8802e430e1cSBastian Koppelmann 8812e430e1cSBastian Koppelmann if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { 8822e430e1cSBastian Koppelmann ovf0 = (1 << 31); 8832e430e1cSBastian Koppelmann } 8842e430e1cSBastian Koppelmann 8852e430e1cSBastian Koppelmann if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { 8862e430e1cSBastian Koppelmann ovf1 = (1 << 31); 8872e430e1cSBastian Koppelmann } 8882e430e1cSBastian Koppelmann 8892e430e1cSBastian Koppelmann env->PSW_USB_V = ovf0 | ovf1; 8902e430e1cSBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 8912e430e1cSBastian Koppelmann 8922e430e1cSBastian Koppelmann avf0 = result0 * 2u; 8932e430e1cSBastian Koppelmann avf0 = result0 ^ avf0; 8942e430e1cSBastian Koppelmann avf1 = result1 * 2u; 8952e430e1cSBastian Koppelmann avf1 = result1 ^ avf1; 8962e430e1cSBastian Koppelmann 8972e430e1cSBastian Koppelmann env->PSW_USB_AV = avf0 | avf1; 8982e430e1cSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 8992e430e1cSBastian Koppelmann 9002e430e1cSBastian Koppelmann return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 9012e430e1cSBastian Koppelmann } 9022e430e1cSBastian Koppelmann 903bebe80fcSBastian Koppelmann uint32_t helper_addsur_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 904bebe80fcSBastian Koppelmann uint32_t r2_h) 905bebe80fcSBastian Koppelmann { 906bebe80fcSBastian Koppelmann int64_t mul_res0 = sextract64(r1, 0, 32); 907bebe80fcSBastian Koppelmann int64_t mul_res1 = sextract64(r1, 32, 32); 908bebe80fcSBastian Koppelmann int64_t r2_low = sextract64(r2_l, 0, 32); 909bebe80fcSBastian Koppelmann int64_t r2_high = sextract64(r2_h, 0, 32); 910bebe80fcSBastian Koppelmann int64_t result0, result1; 911bebe80fcSBastian Koppelmann uint32_t ovf0, ovf1; 912bebe80fcSBastian Koppelmann uint32_t avf0, avf1; 913bebe80fcSBastian Koppelmann 914bebe80fcSBastian Koppelmann ovf0 = ovf1 = 0; 915bebe80fcSBastian Koppelmann 916bebe80fcSBastian Koppelmann result0 = r2_low - mul_res0 + 0x8000; 917bebe80fcSBastian Koppelmann result1 = r2_high + mul_res1 + 0x8000; 918bebe80fcSBastian Koppelmann 919bebe80fcSBastian Koppelmann if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { 920bebe80fcSBastian Koppelmann ovf0 = (1 << 31); 921bebe80fcSBastian Koppelmann } 922bebe80fcSBastian Koppelmann 923bebe80fcSBastian Koppelmann if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { 924bebe80fcSBastian Koppelmann ovf1 = (1 << 31); 925bebe80fcSBastian Koppelmann } 926bebe80fcSBastian Koppelmann 927bebe80fcSBastian Koppelmann env->PSW_USB_V = ovf0 | ovf1; 928bebe80fcSBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 929bebe80fcSBastian Koppelmann 930bebe80fcSBastian Koppelmann avf0 = result0 * 2u; 931bebe80fcSBastian Koppelmann avf0 = result0 ^ avf0; 932bebe80fcSBastian Koppelmann avf1 = result1 * 2u; 933bebe80fcSBastian Koppelmann avf1 = result1 ^ avf1; 934bebe80fcSBastian Koppelmann 935bebe80fcSBastian Koppelmann env->PSW_USB_AV = avf0 | avf1; 936bebe80fcSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 937bebe80fcSBastian Koppelmann 938bebe80fcSBastian Koppelmann return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 939bebe80fcSBastian Koppelmann } 940bebe80fcSBastian Koppelmann 941b00aa8ecSBastian Koppelmann uint32_t helper_maddr_q(CPUTriCoreState *env, uint32_t r1, uint32_t r2, 942b00aa8ecSBastian Koppelmann uint32_t r3, uint32_t n) 943b00aa8ecSBastian Koppelmann { 944b00aa8ecSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 945b00aa8ecSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 946b00aa8ecSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 947b00aa8ecSBastian Koppelmann int64_t mul, ret; 948b00aa8ecSBastian Koppelmann 949b00aa8ecSBastian Koppelmann if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { 950b00aa8ecSBastian Koppelmann mul = 0x7fffffff; 951b00aa8ecSBastian Koppelmann } else { 952b00aa8ecSBastian Koppelmann mul = (t2 * t3) << n; 953b00aa8ecSBastian Koppelmann } 954b00aa8ecSBastian Koppelmann 955b00aa8ecSBastian Koppelmann ret = t1 + mul + 0x8000; 956b00aa8ecSBastian Koppelmann 957b00aa8ecSBastian Koppelmann if ((ret > 0x7fffffffll) || (ret < -0x80000000ll)) { 958b00aa8ecSBastian Koppelmann env->PSW_USB_V = (1 << 31); 959b00aa8ecSBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 960b00aa8ecSBastian Koppelmann } else { 961b00aa8ecSBastian Koppelmann env->PSW_USB_V = 0; 962b00aa8ecSBastian Koppelmann } 963b00aa8ecSBastian Koppelmann env->PSW_USB_AV = ret ^ ret * 2u; 964b00aa8ecSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 965b00aa8ecSBastian Koppelmann 966b00aa8ecSBastian Koppelmann return ret & 0xffff0000ll; 967b00aa8ecSBastian Koppelmann } 968b00aa8ecSBastian Koppelmann 969d5de7839SBastian Koppelmann uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 970d5de7839SBastian Koppelmann { 971d5de7839SBastian Koppelmann int32_t b, i; 972d5de7839SBastian Koppelmann int32_t extr_r1, extr_r2; 973d5de7839SBastian Koppelmann int32_t ovf = 0; 974d5de7839SBastian Koppelmann int32_t avf = 0; 975d5de7839SBastian Koppelmann uint32_t ret = 0; 976d5de7839SBastian Koppelmann 977d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { 978d5de7839SBastian Koppelmann extr_r1 = sextract32(r1, i * 8, 8); 979d5de7839SBastian Koppelmann extr_r2 = sextract32(r2, i * 8, 8); 980d5de7839SBastian Koppelmann 981d5de7839SBastian Koppelmann b = extr_r1 + extr_r2; 982d5de7839SBastian Koppelmann ovf |= ((b > 0x7f) || (b < -0x80)); 983d5de7839SBastian Koppelmann avf |= b ^ b * 2u; 984d5de7839SBastian Koppelmann ret |= ((b & 0xff) << (i*8)); 985d5de7839SBastian Koppelmann } 986d5de7839SBastian Koppelmann 987d5de7839SBastian Koppelmann env->PSW_USB_V = (ovf << 31); 988d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 989d5de7839SBastian Koppelmann env->PSW_USB_AV = avf << 24; 990d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 991d5de7839SBastian Koppelmann 992d5de7839SBastian Koppelmann return ret; 993d5de7839SBastian Koppelmann } 994d5de7839SBastian Koppelmann 995d5de7839SBastian Koppelmann uint32_t helper_add_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 996d5de7839SBastian Koppelmann { 997d5de7839SBastian Koppelmann int32_t h, i; 998d5de7839SBastian Koppelmann int32_t extr_r1, extr_r2; 999d5de7839SBastian Koppelmann int32_t ovf = 0; 1000d5de7839SBastian Koppelmann int32_t avf = 0; 1001d5de7839SBastian Koppelmann int32_t ret = 0; 1002d5de7839SBastian Koppelmann 1003d5de7839SBastian Koppelmann for (i = 0; i < 2; i++) { 1004d5de7839SBastian Koppelmann extr_r1 = sextract32(r1, i * 16, 16); 1005d5de7839SBastian Koppelmann extr_r2 = sextract32(r2, i * 16, 16); 1006d5de7839SBastian Koppelmann h = extr_r1 + extr_r2; 1007d5de7839SBastian Koppelmann ovf |= ((h > 0x7fff) || (h < -0x8000)); 1008d5de7839SBastian Koppelmann avf |= h ^ h * 2u; 1009d5de7839SBastian Koppelmann ret |= (h & 0xffff) << (i * 16); 1010d5de7839SBastian Koppelmann } 1011d5de7839SBastian Koppelmann 1012d5de7839SBastian Koppelmann env->PSW_USB_V = (ovf << 31); 1013d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 1014d5de7839SBastian Koppelmann env->PSW_USB_AV = (avf << 16); 1015d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 1016d5de7839SBastian Koppelmann 1017d5de7839SBastian Koppelmann return ret; 1018d5de7839SBastian Koppelmann } 1019d5de7839SBastian Koppelmann 1020d5de7839SBastian Koppelmann uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 1021d5de7839SBastian Koppelmann { 1022d5de7839SBastian Koppelmann int32_t b, i; 1023d5de7839SBastian Koppelmann int32_t extr_r1, extr_r2; 1024d5de7839SBastian Koppelmann int32_t ovf = 0; 1025d5de7839SBastian Koppelmann int32_t avf = 0; 1026d5de7839SBastian Koppelmann uint32_t ret = 0; 1027d5de7839SBastian Koppelmann 1028d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { 1029d5de7839SBastian Koppelmann extr_r1 = sextract32(r1, i * 8, 8); 1030d5de7839SBastian Koppelmann extr_r2 = sextract32(r2, i * 8, 8); 1031d5de7839SBastian Koppelmann 1032d5de7839SBastian Koppelmann b = extr_r1 - extr_r2; 1033d5de7839SBastian Koppelmann ovf |= ((b > 0x7f) || (b < -0x80)); 1034d5de7839SBastian Koppelmann avf |= b ^ b * 2u; 1035d5de7839SBastian Koppelmann ret |= ((b & 0xff) << (i*8)); 1036d5de7839SBastian Koppelmann } 1037d5de7839SBastian Koppelmann 1038d5de7839SBastian Koppelmann env->PSW_USB_V = (ovf << 31); 1039d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 1040d5de7839SBastian Koppelmann env->PSW_USB_AV = avf << 24; 1041d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 1042d5de7839SBastian Koppelmann 1043d5de7839SBastian Koppelmann return ret; 1044d5de7839SBastian Koppelmann } 1045d5de7839SBastian Koppelmann 1046d5de7839SBastian Koppelmann uint32_t helper_sub_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 1047d5de7839SBastian Koppelmann { 1048d5de7839SBastian Koppelmann int32_t h, i; 1049d5de7839SBastian Koppelmann int32_t extr_r1, extr_r2; 1050d5de7839SBastian Koppelmann int32_t ovf = 0; 1051d5de7839SBastian Koppelmann int32_t avf = 0; 1052d5de7839SBastian Koppelmann int32_t ret = 0; 1053d5de7839SBastian Koppelmann 1054d5de7839SBastian Koppelmann for (i = 0; i < 2; i++) { 1055d5de7839SBastian Koppelmann extr_r1 = sextract32(r1, i * 16, 16); 1056d5de7839SBastian Koppelmann extr_r2 = sextract32(r2, i * 16, 16); 1057d5de7839SBastian Koppelmann h = extr_r1 - extr_r2; 1058d5de7839SBastian Koppelmann ovf |= ((h > 0x7fff) || (h < -0x8000)); 1059d5de7839SBastian Koppelmann avf |= h ^ h * 2u; 1060d5de7839SBastian Koppelmann ret |= (h & 0xffff) << (i * 16); 1061d5de7839SBastian Koppelmann } 1062d5de7839SBastian Koppelmann 1063d5de7839SBastian Koppelmann env->PSW_USB_V = (ovf << 31); 1064d5de7839SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 1065d5de7839SBastian Koppelmann env->PSW_USB_AV = avf << 16; 1066d5de7839SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 1067d5de7839SBastian Koppelmann 1068d5de7839SBastian Koppelmann return ret; 1069d5de7839SBastian Koppelmann } 1070d5de7839SBastian Koppelmann 1071d5de7839SBastian Koppelmann uint32_t helper_eq_b(target_ulong r1, target_ulong r2) 1072d5de7839SBastian Koppelmann { 1073d5de7839SBastian Koppelmann int32_t ret; 1074d5de7839SBastian Koppelmann int32_t i, msk; 1075d5de7839SBastian Koppelmann 1076d5de7839SBastian Koppelmann ret = 0; 1077d5de7839SBastian Koppelmann msk = 0xff; 1078d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { 1079d5de7839SBastian Koppelmann if ((r1 & msk) == (r2 & msk)) { 1080d5de7839SBastian Koppelmann ret |= msk; 1081d5de7839SBastian Koppelmann } 1082d5de7839SBastian Koppelmann msk = msk << 8; 1083d5de7839SBastian Koppelmann } 1084d5de7839SBastian Koppelmann 1085d5de7839SBastian Koppelmann return ret; 1086d5de7839SBastian Koppelmann } 1087d5de7839SBastian Koppelmann 1088d5de7839SBastian Koppelmann uint32_t helper_eq_h(target_ulong r1, target_ulong r2) 1089d5de7839SBastian Koppelmann { 1090d5de7839SBastian Koppelmann int32_t ret = 0; 1091d5de7839SBastian Koppelmann 1092d5de7839SBastian Koppelmann if ((r1 & 0xffff) == (r2 & 0xffff)) { 1093d5de7839SBastian Koppelmann ret = 0xffff; 1094d5de7839SBastian Koppelmann } 1095d5de7839SBastian Koppelmann 1096d5de7839SBastian Koppelmann if ((r1 & 0xffff0000) == (r2 & 0xffff0000)) { 1097d5de7839SBastian Koppelmann ret |= 0xffff0000; 1098d5de7839SBastian Koppelmann } 1099d5de7839SBastian Koppelmann 1100d5de7839SBastian Koppelmann return ret; 1101d5de7839SBastian Koppelmann } 1102d5de7839SBastian Koppelmann 1103d5de7839SBastian Koppelmann uint32_t helper_eqany_b(target_ulong r1, target_ulong r2) 1104d5de7839SBastian Koppelmann { 1105d5de7839SBastian Koppelmann int32_t i; 1106d5de7839SBastian Koppelmann uint32_t ret = 0; 1107d5de7839SBastian Koppelmann 1108d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { 1109d5de7839SBastian Koppelmann ret |= (sextract32(r1, i * 8, 8) == sextract32(r2, i * 8, 8)); 1110d5de7839SBastian Koppelmann } 1111d5de7839SBastian Koppelmann 1112d5de7839SBastian Koppelmann return ret; 1113d5de7839SBastian Koppelmann } 1114d5de7839SBastian Koppelmann 1115d5de7839SBastian Koppelmann uint32_t helper_eqany_h(target_ulong r1, target_ulong r2) 1116d5de7839SBastian Koppelmann { 1117d5de7839SBastian Koppelmann uint32_t ret; 1118d5de7839SBastian Koppelmann 1119d5de7839SBastian Koppelmann ret = (sextract32(r1, 0, 16) == sextract32(r2, 0, 16)); 1120d5de7839SBastian Koppelmann ret |= (sextract32(r1, 16, 16) == sextract32(r2, 16, 16)); 1121d5de7839SBastian Koppelmann 1122d5de7839SBastian Koppelmann return ret; 1123d5de7839SBastian Koppelmann } 1124d5de7839SBastian Koppelmann 1125d5de7839SBastian Koppelmann uint32_t helper_lt_b(target_ulong r1, target_ulong r2) 1126d5de7839SBastian Koppelmann { 1127d5de7839SBastian Koppelmann int32_t i; 1128d5de7839SBastian Koppelmann uint32_t ret = 0; 1129d5de7839SBastian Koppelmann 1130d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { 1131d5de7839SBastian Koppelmann if (sextract32(r1, i * 8, 8) < sextract32(r2, i * 8, 8)) { 1132d5de7839SBastian Koppelmann ret |= (0xff << (i * 8)); 1133d5de7839SBastian Koppelmann } 1134d5de7839SBastian Koppelmann } 1135d5de7839SBastian Koppelmann 1136d5de7839SBastian Koppelmann return ret; 1137d5de7839SBastian Koppelmann } 1138d5de7839SBastian Koppelmann 1139d5de7839SBastian Koppelmann uint32_t helper_lt_bu(target_ulong r1, target_ulong r2) 1140d5de7839SBastian Koppelmann { 1141d5de7839SBastian Koppelmann int32_t i; 1142d5de7839SBastian Koppelmann uint32_t ret = 0; 1143d5de7839SBastian Koppelmann 1144d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { 1145d5de7839SBastian Koppelmann if (extract32(r1, i * 8, 8) < extract32(r2, i * 8, 8)) { 1146d5de7839SBastian Koppelmann ret |= (0xff << (i * 8)); 1147d5de7839SBastian Koppelmann } 1148d5de7839SBastian Koppelmann } 1149d5de7839SBastian Koppelmann 1150d5de7839SBastian Koppelmann return ret; 1151d5de7839SBastian Koppelmann } 1152d5de7839SBastian Koppelmann 1153d5de7839SBastian Koppelmann uint32_t helper_lt_h(target_ulong r1, target_ulong r2) 1154d5de7839SBastian Koppelmann { 1155d5de7839SBastian Koppelmann uint32_t ret = 0; 1156d5de7839SBastian Koppelmann 1157d5de7839SBastian Koppelmann if (sextract32(r1, 0, 16) < sextract32(r2, 0, 16)) { 1158d5de7839SBastian Koppelmann ret |= 0xffff; 1159d5de7839SBastian Koppelmann } 1160d5de7839SBastian Koppelmann 1161d5de7839SBastian Koppelmann if (sextract32(r1, 16, 16) < sextract32(r2, 16, 16)) { 1162d5de7839SBastian Koppelmann ret |= 0xffff0000; 1163d5de7839SBastian Koppelmann } 1164d5de7839SBastian Koppelmann 1165d5de7839SBastian Koppelmann return ret; 1166d5de7839SBastian Koppelmann } 1167d5de7839SBastian Koppelmann 1168d5de7839SBastian Koppelmann uint32_t helper_lt_hu(target_ulong r1, target_ulong r2) 1169d5de7839SBastian Koppelmann { 1170d5de7839SBastian Koppelmann uint32_t ret = 0; 1171d5de7839SBastian Koppelmann 1172d5de7839SBastian Koppelmann if (extract32(r1, 0, 16) < extract32(r2, 0, 16)) { 1173d5de7839SBastian Koppelmann ret |= 0xffff; 1174d5de7839SBastian Koppelmann } 1175d5de7839SBastian Koppelmann 1176d5de7839SBastian Koppelmann if (extract32(r1, 16, 16) < extract32(r2, 16, 16)) { 1177d5de7839SBastian Koppelmann ret |= 0xffff0000; 1178d5de7839SBastian Koppelmann } 1179d5de7839SBastian Koppelmann 1180d5de7839SBastian Koppelmann return ret; 1181d5de7839SBastian Koppelmann } 1182d5de7839SBastian Koppelmann 1183d5de7839SBastian Koppelmann #define EXTREMA_H_B(name, op) \ 1184d5de7839SBastian Koppelmann uint32_t helper_##name ##_b(target_ulong r1, target_ulong r2) \ 1185d5de7839SBastian Koppelmann { \ 1186d5de7839SBastian Koppelmann int32_t i, extr_r1, extr_r2; \ 1187d5de7839SBastian Koppelmann uint32_t ret = 0; \ 1188d5de7839SBastian Koppelmann \ 1189d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { \ 1190d5de7839SBastian Koppelmann extr_r1 = sextract32(r1, i * 8, 8); \ 1191d5de7839SBastian Koppelmann extr_r2 = sextract32(r2, i * 8, 8); \ 1192d5de7839SBastian Koppelmann extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1193d5de7839SBastian Koppelmann ret |= (extr_r1 & 0xff) << (i * 8); \ 1194d5de7839SBastian Koppelmann } \ 1195d5de7839SBastian Koppelmann return ret; \ 1196d5de7839SBastian Koppelmann } \ 1197d5de7839SBastian Koppelmann \ 1198d5de7839SBastian Koppelmann uint32_t helper_##name ##_bu(target_ulong r1, target_ulong r2)\ 1199d5de7839SBastian Koppelmann { \ 1200d5de7839SBastian Koppelmann int32_t i; \ 1201d5de7839SBastian Koppelmann uint32_t extr_r1, extr_r2; \ 1202d5de7839SBastian Koppelmann uint32_t ret = 0; \ 1203d5de7839SBastian Koppelmann \ 1204d5de7839SBastian Koppelmann for (i = 0; i < 4; i++) { \ 1205d5de7839SBastian Koppelmann extr_r1 = extract32(r1, i * 8, 8); \ 1206d5de7839SBastian Koppelmann extr_r2 = extract32(r2, i * 8, 8); \ 1207d5de7839SBastian Koppelmann extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1208d5de7839SBastian Koppelmann ret |= (extr_r1 & 0xff) << (i * 8); \ 1209d5de7839SBastian Koppelmann } \ 1210d5de7839SBastian Koppelmann return ret; \ 1211d5de7839SBastian Koppelmann } \ 1212d5de7839SBastian Koppelmann \ 1213d5de7839SBastian Koppelmann uint32_t helper_##name ##_h(target_ulong r1, target_ulong r2) \ 1214d5de7839SBastian Koppelmann { \ 1215d5de7839SBastian Koppelmann int32_t extr_r1, extr_r2; \ 1216d5de7839SBastian Koppelmann uint32_t ret = 0; \ 1217d5de7839SBastian Koppelmann \ 1218d5de7839SBastian Koppelmann extr_r1 = sextract32(r1, 0, 16); \ 1219d5de7839SBastian Koppelmann extr_r2 = sextract32(r2, 0, 16); \ 1220d5de7839SBastian Koppelmann ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1221d5de7839SBastian Koppelmann ret = ret & 0xffff; \ 1222d5de7839SBastian Koppelmann \ 1223d5de7839SBastian Koppelmann extr_r1 = sextract32(r1, 16, 16); \ 1224d5de7839SBastian Koppelmann extr_r2 = sextract32(r2, 16, 16); \ 1225d5de7839SBastian Koppelmann extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1226d5de7839SBastian Koppelmann ret |= extr_r1 << 16; \ 1227d5de7839SBastian Koppelmann \ 1228d5de7839SBastian Koppelmann return ret; \ 1229d5de7839SBastian Koppelmann } \ 1230d5de7839SBastian Koppelmann \ 1231d5de7839SBastian Koppelmann uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\ 1232d5de7839SBastian Koppelmann { \ 1233d5de7839SBastian Koppelmann uint32_t extr_r1, extr_r2; \ 1234d5de7839SBastian Koppelmann uint32_t ret = 0; \ 1235d5de7839SBastian Koppelmann \ 1236d5de7839SBastian Koppelmann extr_r1 = extract32(r1, 0, 16); \ 1237d5de7839SBastian Koppelmann extr_r2 = extract32(r2, 0, 16); \ 1238d5de7839SBastian Koppelmann ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1239d5de7839SBastian Koppelmann ret = ret & 0xffff; \ 1240d5de7839SBastian Koppelmann \ 1241d5de7839SBastian Koppelmann extr_r1 = extract32(r1, 16, 16); \ 1242d5de7839SBastian Koppelmann extr_r2 = extract32(r2, 16, 16); \ 1243d5de7839SBastian Koppelmann extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1244d5de7839SBastian Koppelmann ret |= extr_r1 << (16); \ 1245d5de7839SBastian Koppelmann \ 1246d5de7839SBastian Koppelmann return ret; \ 1247d5de7839SBastian Koppelmann } \ 124809532255SBastian Koppelmann \ 124909532255SBastian Koppelmann uint64_t helper_ix##name(uint64_t r1, uint32_t r2) \ 125009532255SBastian Koppelmann { \ 125109532255SBastian Koppelmann int64_t r2l, r2h, r1hl; \ 125209532255SBastian Koppelmann uint64_t ret = 0; \ 125309532255SBastian Koppelmann \ 125409532255SBastian Koppelmann ret = ((r1 + 2) & 0xffff); \ 125509532255SBastian Koppelmann r2l = sextract64(r2, 0, 16); \ 125609532255SBastian Koppelmann r2h = sextract64(r2, 16, 16); \ 125709532255SBastian Koppelmann r1hl = sextract64(r1, 32, 16); \ 125809532255SBastian Koppelmann \ 125909532255SBastian Koppelmann if ((r2l op ## = r2h) && (r2l op r1hl)) { \ 126009532255SBastian Koppelmann ret |= (r2l & 0xffff) << 32; \ 126109532255SBastian Koppelmann ret |= extract64(r1, 0, 16) << 16; \ 126209532255SBastian Koppelmann } else if ((r2h op r2l) && (r2h op r1hl)) { \ 126309532255SBastian Koppelmann ret |= extract64(r2, 16, 16) << 32; \ 126409532255SBastian Koppelmann ret |= extract64(r1 + 1, 0, 16) << 16; \ 126509532255SBastian Koppelmann } else { \ 126609532255SBastian Koppelmann ret |= r1 & 0xffffffff0000ull; \ 126709532255SBastian Koppelmann } \ 126809532255SBastian Koppelmann return ret; \ 126909532255SBastian Koppelmann } \ 127009532255SBastian Koppelmann \ 127109532255SBastian Koppelmann uint64_t helper_ix##name ##_u(uint64_t r1, uint32_t r2) \ 127209532255SBastian Koppelmann { \ 127309532255SBastian Koppelmann int64_t r2l, r2h, r1hl; \ 127409532255SBastian Koppelmann uint64_t ret = 0; \ 127509532255SBastian Koppelmann \ 127609532255SBastian Koppelmann ret = ((r1 + 2) & 0xffff); \ 127709532255SBastian Koppelmann r2l = extract64(r2, 0, 16); \ 127809532255SBastian Koppelmann r2h = extract64(r2, 16, 16); \ 127909532255SBastian Koppelmann r1hl = extract64(r1, 32, 16); \ 128009532255SBastian Koppelmann \ 128109532255SBastian Koppelmann if ((r2l op ## = r2h) && (r2l op r1hl)) { \ 128209532255SBastian Koppelmann ret |= (r2l & 0xffff) << 32; \ 128309532255SBastian Koppelmann ret |= extract64(r1, 0, 16) << 16; \ 128409532255SBastian Koppelmann } else if ((r2h op r2l) && (r2h op r1hl)) { \ 128509532255SBastian Koppelmann ret |= extract64(r2, 16, 16) << 32; \ 128609532255SBastian Koppelmann ret |= extract64(r1 + 1, 0, 16) << 16; \ 128709532255SBastian Koppelmann } else { \ 128809532255SBastian Koppelmann ret |= r1 & 0xffffffff0000ull; \ 128909532255SBastian Koppelmann } \ 129009532255SBastian Koppelmann return ret; \ 129109532255SBastian Koppelmann } 1292d5de7839SBastian Koppelmann 1293d5de7839SBastian Koppelmann EXTREMA_H_B(max, >) 1294d5de7839SBastian Koppelmann EXTREMA_H_B(min, <) 1295d5de7839SBastian Koppelmann 1296d5de7839SBastian Koppelmann #undef EXTREMA_H_B 1297d5de7839SBastian Koppelmann 12980b79a781SBastian Koppelmann uint32_t helper_clo(target_ulong r1) 12990b79a781SBastian Koppelmann { 13000b79a781SBastian Koppelmann return clo32(r1); 13010b79a781SBastian Koppelmann } 13020b79a781SBastian Koppelmann 13030b79a781SBastian Koppelmann uint32_t helper_clo_h(target_ulong r1) 13040b79a781SBastian Koppelmann { 13050b79a781SBastian Koppelmann uint32_t ret_hw0 = extract32(r1, 0, 16); 13060b79a781SBastian Koppelmann uint32_t ret_hw1 = extract32(r1, 16, 16); 13070b79a781SBastian Koppelmann 13080b79a781SBastian Koppelmann ret_hw0 = clo32(ret_hw0 << 16); 13090b79a781SBastian Koppelmann ret_hw1 = clo32(ret_hw1 << 16); 13100b79a781SBastian Koppelmann 13110b79a781SBastian Koppelmann if (ret_hw0 > 16) { 13120b79a781SBastian Koppelmann ret_hw0 = 16; 13130b79a781SBastian Koppelmann } 13140b79a781SBastian Koppelmann if (ret_hw1 > 16) { 13150b79a781SBastian Koppelmann ret_hw1 = 16; 13160b79a781SBastian Koppelmann } 13170b79a781SBastian Koppelmann 13180b79a781SBastian Koppelmann return ret_hw0 | (ret_hw1 << 16); 13190b79a781SBastian Koppelmann } 13200b79a781SBastian Koppelmann 13210b79a781SBastian Koppelmann uint32_t helper_clz(target_ulong r1) 13220b79a781SBastian Koppelmann { 13230b79a781SBastian Koppelmann return clz32(r1); 13240b79a781SBastian Koppelmann } 13250b79a781SBastian Koppelmann 13260b79a781SBastian Koppelmann uint32_t helper_clz_h(target_ulong r1) 13270b79a781SBastian Koppelmann { 13280b79a781SBastian Koppelmann uint32_t ret_hw0 = extract32(r1, 0, 16); 13290b79a781SBastian Koppelmann uint32_t ret_hw1 = extract32(r1, 16, 16); 13300b79a781SBastian Koppelmann 13310b79a781SBastian Koppelmann ret_hw0 = clz32(ret_hw0 << 16); 13320b79a781SBastian Koppelmann ret_hw1 = clz32(ret_hw1 << 16); 13330b79a781SBastian Koppelmann 13340b79a781SBastian Koppelmann if (ret_hw0 > 16) { 13350b79a781SBastian Koppelmann ret_hw0 = 16; 13360b79a781SBastian Koppelmann } 13370b79a781SBastian Koppelmann if (ret_hw1 > 16) { 13380b79a781SBastian Koppelmann ret_hw1 = 16; 13390b79a781SBastian Koppelmann } 13400b79a781SBastian Koppelmann 13410b79a781SBastian Koppelmann return ret_hw0 | (ret_hw1 << 16); 13420b79a781SBastian Koppelmann } 13430b79a781SBastian Koppelmann 13440b79a781SBastian Koppelmann uint32_t helper_cls(target_ulong r1) 13450b79a781SBastian Koppelmann { 13460b79a781SBastian Koppelmann return clrsb32(r1); 13470b79a781SBastian Koppelmann } 13480b79a781SBastian Koppelmann 13490b79a781SBastian Koppelmann uint32_t helper_cls_h(target_ulong r1) 13500b79a781SBastian Koppelmann { 13510b79a781SBastian Koppelmann uint32_t ret_hw0 = extract32(r1, 0, 16); 13520b79a781SBastian Koppelmann uint32_t ret_hw1 = extract32(r1, 16, 16); 13530b79a781SBastian Koppelmann 13540b79a781SBastian Koppelmann ret_hw0 = clrsb32(ret_hw0 << 16); 13550b79a781SBastian Koppelmann ret_hw1 = clrsb32(ret_hw1 << 16); 13560b79a781SBastian Koppelmann 13570b79a781SBastian Koppelmann if (ret_hw0 > 15) { 13580b79a781SBastian Koppelmann ret_hw0 = 15; 13590b79a781SBastian Koppelmann } 13600b79a781SBastian Koppelmann if (ret_hw1 > 15) { 13610b79a781SBastian Koppelmann ret_hw1 = 15; 13620b79a781SBastian Koppelmann } 13630b79a781SBastian Koppelmann 13640b79a781SBastian Koppelmann return ret_hw0 | (ret_hw1 << 16); 13650b79a781SBastian Koppelmann } 13660b79a781SBastian Koppelmann 13670b79a781SBastian Koppelmann uint32_t helper_sh(target_ulong r1, target_ulong r2) 13680b79a781SBastian Koppelmann { 13690b79a781SBastian Koppelmann int32_t shift_count = sextract32(r2, 0, 6); 13700b79a781SBastian Koppelmann 13710b79a781SBastian Koppelmann if (shift_count == -32) { 13720b79a781SBastian Koppelmann return 0; 13730b79a781SBastian Koppelmann } else if (shift_count < 0) { 13740b79a781SBastian Koppelmann return r1 >> -shift_count; 13750b79a781SBastian Koppelmann } else { 13760b79a781SBastian Koppelmann return r1 << shift_count; 13770b79a781SBastian Koppelmann } 13780b79a781SBastian Koppelmann } 13790b79a781SBastian Koppelmann 13800b79a781SBastian Koppelmann uint32_t helper_sh_h(target_ulong r1, target_ulong r2) 13810b79a781SBastian Koppelmann { 13820b79a781SBastian Koppelmann int32_t ret_hw0, ret_hw1; 13830b79a781SBastian Koppelmann int32_t shift_count; 13840b79a781SBastian Koppelmann 13850b79a781SBastian Koppelmann shift_count = sextract32(r2, 0, 5); 13860b79a781SBastian Koppelmann 13870b79a781SBastian Koppelmann if (shift_count == -16) { 13880b79a781SBastian Koppelmann return 0; 13890b79a781SBastian Koppelmann } else if (shift_count < 0) { 13900b79a781SBastian Koppelmann ret_hw0 = extract32(r1, 0, 16) >> -shift_count; 13910b79a781SBastian Koppelmann ret_hw1 = extract32(r1, 16, 16) >> -shift_count; 13920b79a781SBastian Koppelmann return (ret_hw0 & 0xffff) | (ret_hw1 << 16); 13930b79a781SBastian Koppelmann } else { 13940b79a781SBastian Koppelmann ret_hw0 = extract32(r1, 0, 16) << shift_count; 13950b79a781SBastian Koppelmann ret_hw1 = extract32(r1, 16, 16) << shift_count; 13960b79a781SBastian Koppelmann return (ret_hw0 & 0xffff) | (ret_hw1 << 16); 13970b79a781SBastian Koppelmann } 13980b79a781SBastian Koppelmann } 13990b79a781SBastian Koppelmann 14000b79a781SBastian Koppelmann uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 14010b79a781SBastian Koppelmann { 14020b79a781SBastian Koppelmann int32_t shift_count; 14030b79a781SBastian Koppelmann int64_t result, t1; 14040b79a781SBastian Koppelmann uint32_t ret; 14050b79a781SBastian Koppelmann 14060b79a781SBastian Koppelmann shift_count = sextract32(r2, 0, 6); 14070b79a781SBastian Koppelmann t1 = sextract32(r1, 0, 32); 14080b79a781SBastian Koppelmann 14090b79a781SBastian Koppelmann if (shift_count == 0) { 14100b79a781SBastian Koppelmann env->PSW_USB_C = env->PSW_USB_V = 0; 14110b79a781SBastian Koppelmann ret = r1; 14120b79a781SBastian Koppelmann } else if (shift_count == -32) { 14130b79a781SBastian Koppelmann env->PSW_USB_C = r1; 14140b79a781SBastian Koppelmann env->PSW_USB_V = 0; 14150b79a781SBastian Koppelmann ret = t1 >> 31; 14160b79a781SBastian Koppelmann } else if (shift_count > 0) { 14170b79a781SBastian Koppelmann result = t1 << shift_count; 14180b79a781SBastian Koppelmann /* calc carry */ 1419452e3d49SPeter Maydell env->PSW_USB_C = ((result & 0xffffffff00000000ULL) != 0); 14200b79a781SBastian Koppelmann /* calc v */ 14210b79a781SBastian Koppelmann env->PSW_USB_V = (((result > 0x7fffffffLL) || 14220b79a781SBastian Koppelmann (result < -0x80000000LL)) << 31); 14230b79a781SBastian Koppelmann /* calc sv */ 14240b79a781SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 14250b79a781SBastian Koppelmann ret = (uint32_t)result; 14260b79a781SBastian Koppelmann } else { 14270b79a781SBastian Koppelmann env->PSW_USB_V = 0; 14280b79a781SBastian Koppelmann env->PSW_USB_C = (r1 & ((1 << -shift_count) - 1)); 14290b79a781SBastian Koppelmann ret = t1 >> -shift_count; 14300b79a781SBastian Koppelmann } 14310b79a781SBastian Koppelmann 14320b79a781SBastian Koppelmann env->PSW_USB_AV = ret ^ ret * 2u; 14330b79a781SBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 14340b79a781SBastian Koppelmann 14350b79a781SBastian Koppelmann return ret; 14360b79a781SBastian Koppelmann } 14370b79a781SBastian Koppelmann 14380b79a781SBastian Koppelmann uint32_t helper_sha_h(target_ulong r1, target_ulong r2) 14390b79a781SBastian Koppelmann { 14400b79a781SBastian Koppelmann int32_t shift_count; 14410b79a781SBastian Koppelmann int32_t ret_hw0, ret_hw1; 14420b79a781SBastian Koppelmann 14430b79a781SBastian Koppelmann shift_count = sextract32(r2, 0, 5); 14440b79a781SBastian Koppelmann 14450b79a781SBastian Koppelmann if (shift_count == 0) { 14460b79a781SBastian Koppelmann return r1; 14470b79a781SBastian Koppelmann } else if (shift_count < 0) { 14480b79a781SBastian Koppelmann ret_hw0 = sextract32(r1, 0, 16) >> -shift_count; 14490b79a781SBastian Koppelmann ret_hw1 = sextract32(r1, 16, 16) >> -shift_count; 14500b79a781SBastian Koppelmann return (ret_hw0 & 0xffff) | (ret_hw1 << 16); 14510b79a781SBastian Koppelmann } else { 14520b79a781SBastian Koppelmann ret_hw0 = sextract32(r1, 0, 16) << shift_count; 14530b79a781SBastian Koppelmann ret_hw1 = sextract32(r1, 16, 16) << shift_count; 14540b79a781SBastian Koppelmann return (ret_hw0 & 0xffff) | (ret_hw1 << 16); 14550b79a781SBastian Koppelmann } 14560b79a781SBastian Koppelmann } 14570b79a781SBastian Koppelmann 1458e2bed107SBastian Koppelmann uint32_t helper_bmerge(target_ulong r1, target_ulong r2) 1459e2bed107SBastian Koppelmann { 1460e2bed107SBastian Koppelmann uint32_t i, ret; 1461e2bed107SBastian Koppelmann 1462e2bed107SBastian Koppelmann ret = 0; 1463e2bed107SBastian Koppelmann for (i = 0; i < 16; i++) { 1464e2bed107SBastian Koppelmann ret |= (r1 & 1) << (2 * i + 1); 1465e2bed107SBastian Koppelmann ret |= (r2 & 1) << (2 * i); 1466e2bed107SBastian Koppelmann r1 = r1 >> 1; 1467e2bed107SBastian Koppelmann r2 = r2 >> 1; 1468e2bed107SBastian Koppelmann } 1469e2bed107SBastian Koppelmann return ret; 1470e2bed107SBastian Koppelmann } 1471e2bed107SBastian Koppelmann 1472e2bed107SBastian Koppelmann uint64_t helper_bsplit(uint32_t r1) 1473e2bed107SBastian Koppelmann { 1474e2bed107SBastian Koppelmann int32_t i; 1475e2bed107SBastian Koppelmann uint64_t ret; 1476e2bed107SBastian Koppelmann 1477e2bed107SBastian Koppelmann ret = 0; 1478e2bed107SBastian Koppelmann for (i = 0; i < 32; i = i + 2) { 1479e2bed107SBastian Koppelmann /* even */ 1480e2bed107SBastian Koppelmann ret |= (r1 & 1) << (i/2); 1481e2bed107SBastian Koppelmann r1 = r1 >> 1; 1482e2bed107SBastian Koppelmann /* odd */ 1483e2bed107SBastian Koppelmann ret |= (uint64_t)(r1 & 1) << (i/2 + 32); 1484e2bed107SBastian Koppelmann r1 = r1 >> 1; 1485e2bed107SBastian Koppelmann } 1486e2bed107SBastian Koppelmann return ret; 1487e2bed107SBastian Koppelmann } 1488e2bed107SBastian Koppelmann 1489e2bed107SBastian Koppelmann uint32_t helper_parity(target_ulong r1) 1490e2bed107SBastian Koppelmann { 1491e2bed107SBastian Koppelmann uint32_t ret; 1492e2bed107SBastian Koppelmann uint32_t nOnes, i; 1493e2bed107SBastian Koppelmann 1494e2bed107SBastian Koppelmann ret = 0; 1495e2bed107SBastian Koppelmann nOnes = 0; 1496e2bed107SBastian Koppelmann for (i = 0; i < 8; i++) { 1497e2bed107SBastian Koppelmann ret ^= (r1 & 1); 1498e2bed107SBastian Koppelmann r1 = r1 >> 1; 1499e2bed107SBastian Koppelmann } 1500e2bed107SBastian Koppelmann /* second byte */ 1501e2bed107SBastian Koppelmann nOnes = 0; 1502e2bed107SBastian Koppelmann for (i = 0; i < 8; i++) { 1503e2bed107SBastian Koppelmann nOnes ^= (r1 & 1); 1504e2bed107SBastian Koppelmann r1 = r1 >> 1; 1505e2bed107SBastian Koppelmann } 1506e2bed107SBastian Koppelmann ret |= nOnes << 8; 1507e2bed107SBastian Koppelmann /* third byte */ 1508e2bed107SBastian Koppelmann nOnes = 0; 1509e2bed107SBastian Koppelmann for (i = 0; i < 8; i++) { 1510e2bed107SBastian Koppelmann nOnes ^= (r1 & 1); 1511e2bed107SBastian Koppelmann r1 = r1 >> 1; 1512e2bed107SBastian Koppelmann } 1513e2bed107SBastian Koppelmann ret |= nOnes << 16; 1514e2bed107SBastian Koppelmann /* fourth byte */ 1515e2bed107SBastian Koppelmann nOnes = 0; 1516e2bed107SBastian Koppelmann for (i = 0; i < 8; i++) { 1517e2bed107SBastian Koppelmann nOnes ^= (r1 & 1); 1518e2bed107SBastian Koppelmann r1 = r1 >> 1; 1519e2bed107SBastian Koppelmann } 1520e2bed107SBastian Koppelmann ret |= nOnes << 24; 1521e2bed107SBastian Koppelmann 1522e2bed107SBastian Koppelmann return ret; 1523e2bed107SBastian Koppelmann } 1524e2bed107SBastian Koppelmann 152509532255SBastian Koppelmann uint32_t helper_pack(uint32_t carry, uint32_t r1_low, uint32_t r1_high, 152609532255SBastian Koppelmann target_ulong r2) 152709532255SBastian Koppelmann { 152809532255SBastian Koppelmann uint32_t ret; 152909532255SBastian Koppelmann int32_t fp_exp, fp_frac, temp_exp, fp_exp_frac; 153009532255SBastian Koppelmann int32_t int_exp = r1_high; 153109532255SBastian Koppelmann int32_t int_mant = r1_low; 153209532255SBastian Koppelmann uint32_t flag_rnd = (int_mant & (1 << 7)) && ( 153309532255SBastian Koppelmann (int_mant & (1 << 8)) || 153409532255SBastian Koppelmann (int_mant & 0x7f) || 153509532255SBastian Koppelmann (carry != 0)); 153609532255SBastian Koppelmann if (((int_mant & (1<<31)) == 0) && (int_exp == 255)) { 153709532255SBastian Koppelmann fp_exp = 255; 153809532255SBastian Koppelmann fp_frac = extract32(int_mant, 8, 23); 153909532255SBastian Koppelmann } else if ((int_mant & (1<<31)) && (int_exp >= 127)) { 154009532255SBastian Koppelmann fp_exp = 255; 154109532255SBastian Koppelmann fp_frac = 0; 154209532255SBastian Koppelmann } else if ((int_mant & (1<<31)) && (int_exp <= -128)) { 154309532255SBastian Koppelmann fp_exp = 0; 154409532255SBastian Koppelmann fp_frac = 0; 154509532255SBastian Koppelmann } else if (int_mant == 0) { 154609532255SBastian Koppelmann fp_exp = 0; 154709532255SBastian Koppelmann fp_frac = 0; 154809532255SBastian Koppelmann } else { 154909532255SBastian Koppelmann if (((int_mant & (1 << 31)) == 0)) { 155009532255SBastian Koppelmann temp_exp = 0; 155109532255SBastian Koppelmann } else { 155209532255SBastian Koppelmann temp_exp = int_exp + 128; 155309532255SBastian Koppelmann } 155409532255SBastian Koppelmann fp_exp_frac = (((temp_exp & 0xff) << 23) | 155509532255SBastian Koppelmann extract32(int_mant, 8, 23)) 155609532255SBastian Koppelmann + flag_rnd; 155709532255SBastian Koppelmann fp_exp = extract32(fp_exp_frac, 23, 8); 155809532255SBastian Koppelmann fp_frac = extract32(fp_exp_frac, 0, 23); 155909532255SBastian Koppelmann } 156009532255SBastian Koppelmann ret = r2 & (1 << 31); 156109532255SBastian Koppelmann ret = ret + (fp_exp << 23); 156209532255SBastian Koppelmann ret = ret + (fp_frac & 0x7fffff); 156309532255SBastian Koppelmann 156409532255SBastian Koppelmann return ret; 156509532255SBastian Koppelmann } 156609532255SBastian Koppelmann 1567e2bed107SBastian Koppelmann uint64_t helper_unpack(target_ulong arg1) 1568e2bed107SBastian Koppelmann { 1569e2bed107SBastian Koppelmann int32_t fp_exp = extract32(arg1, 23, 8); 1570e2bed107SBastian Koppelmann int32_t fp_frac = extract32(arg1, 0, 23); 1571e2bed107SBastian Koppelmann uint64_t ret; 1572e2bed107SBastian Koppelmann int32_t int_exp, int_mant; 1573e2bed107SBastian Koppelmann 1574e2bed107SBastian Koppelmann if (fp_exp == 255) { 1575e2bed107SBastian Koppelmann int_exp = 255; 1576e2bed107SBastian Koppelmann int_mant = (fp_frac << 7); 1577e2bed107SBastian Koppelmann } else if ((fp_exp == 0) && (fp_frac == 0)) { 1578e2bed107SBastian Koppelmann int_exp = -127; 1579e2bed107SBastian Koppelmann int_mant = 0; 1580e2bed107SBastian Koppelmann } else if ((fp_exp == 0) && (fp_frac != 0)) { 1581e2bed107SBastian Koppelmann int_exp = -126; 1582e2bed107SBastian Koppelmann int_mant = (fp_frac << 7); 1583e2bed107SBastian Koppelmann } else { 1584e2bed107SBastian Koppelmann int_exp = fp_exp - 127; 1585e2bed107SBastian Koppelmann int_mant = (fp_frac << 7); 1586e2bed107SBastian Koppelmann int_mant |= (1 << 30); 1587e2bed107SBastian Koppelmann } 1588e2bed107SBastian Koppelmann ret = int_exp; 1589e2bed107SBastian Koppelmann ret = ret << 32; 1590e2bed107SBastian Koppelmann ret |= int_mant; 1591e2bed107SBastian Koppelmann 1592e2bed107SBastian Koppelmann return ret; 1593e2bed107SBastian Koppelmann } 1594e2bed107SBastian Koppelmann 1595e2bed107SBastian Koppelmann uint64_t helper_dvinit_b_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 1596e2bed107SBastian Koppelmann { 1597e2bed107SBastian Koppelmann uint64_t ret; 1598e2bed107SBastian Koppelmann int32_t abs_sig_dividend, abs_base_dividend, abs_divisor; 1599e2bed107SBastian Koppelmann int32_t quotient_sign; 1600e2bed107SBastian Koppelmann 1601e2bed107SBastian Koppelmann ret = sextract32(r1, 0, 32); 1602e2bed107SBastian Koppelmann ret = ret << 24; 1603e2bed107SBastian Koppelmann quotient_sign = 0; 1604e2bed107SBastian Koppelmann if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { 1605e2bed107SBastian Koppelmann ret |= 0xffffff; 1606e2bed107SBastian Koppelmann quotient_sign = 1; 1607e2bed107SBastian Koppelmann } 1608e2bed107SBastian Koppelmann 1609e2bed107SBastian Koppelmann abs_sig_dividend = abs(r1) >> 7; 1610e2bed107SBastian Koppelmann abs_base_dividend = abs(r1) & 0x7f; 1611e2bed107SBastian Koppelmann abs_divisor = abs(r1); 1612e2bed107SBastian Koppelmann /* calc overflow */ 1613e2bed107SBastian Koppelmann env->PSW_USB_V = 0; 1614e2bed107SBastian Koppelmann if ((quotient_sign) && (abs_divisor)) { 1615e2bed107SBastian Koppelmann env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) && 1616e2bed107SBastian Koppelmann (abs_base_dividend >= abs_divisor)) || 1617e2bed107SBastian Koppelmann (abs_sig_dividend > abs_divisor)); 1618e2bed107SBastian Koppelmann } else { 1619e2bed107SBastian Koppelmann env->PSW_USB_V = (abs_sig_dividend >= abs_divisor); 1620e2bed107SBastian Koppelmann } 1621e2bed107SBastian Koppelmann env->PSW_USB_V = env->PSW_USB_V << 31; 1622e2bed107SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 1623e2bed107SBastian Koppelmann env->PSW_USB_AV = 0; 1624e2bed107SBastian Koppelmann 1625e2bed107SBastian Koppelmann return ret; 1626e2bed107SBastian Koppelmann } 1627e2bed107SBastian Koppelmann 1628e2bed107SBastian Koppelmann uint64_t helper_dvinit_b_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 1629e2bed107SBastian Koppelmann { 1630e2bed107SBastian Koppelmann uint64_t ret = sextract32(r1, 0, 32); 1631e2bed107SBastian Koppelmann 1632e2bed107SBastian Koppelmann ret = ret << 24; 1633e2bed107SBastian Koppelmann if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { 1634e2bed107SBastian Koppelmann ret |= 0xffffff; 1635e2bed107SBastian Koppelmann } 1636e2bed107SBastian Koppelmann /* calc overflow */ 1637e2bed107SBastian Koppelmann env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffffff80))); 1638e2bed107SBastian Koppelmann env->PSW_USB_V = env->PSW_USB_V << 31; 1639e2bed107SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 1640e2bed107SBastian Koppelmann env->PSW_USB_AV = 0; 1641e2bed107SBastian Koppelmann 1642e2bed107SBastian Koppelmann return ret; 1643e2bed107SBastian Koppelmann } 1644e2bed107SBastian Koppelmann 1645e2bed107SBastian Koppelmann uint64_t helper_dvinit_h_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 1646e2bed107SBastian Koppelmann { 1647e2bed107SBastian Koppelmann uint64_t ret; 1648e2bed107SBastian Koppelmann int32_t abs_sig_dividend, abs_base_dividend, abs_divisor; 1649e2bed107SBastian Koppelmann int32_t quotient_sign; 1650e2bed107SBastian Koppelmann 1651e2bed107SBastian Koppelmann ret = sextract32(r1, 0, 32); 1652e2bed107SBastian Koppelmann ret = ret << 16; 1653e2bed107SBastian Koppelmann quotient_sign = 0; 1654e2bed107SBastian Koppelmann if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { 1655e2bed107SBastian Koppelmann ret |= 0xffff; 1656e2bed107SBastian Koppelmann quotient_sign = 1; 1657e2bed107SBastian Koppelmann } 1658e2bed107SBastian Koppelmann 1659e2bed107SBastian Koppelmann abs_sig_dividend = abs(r1) >> 7; 1660e2bed107SBastian Koppelmann abs_base_dividend = abs(r1) & 0x7f; 1661e2bed107SBastian Koppelmann abs_divisor = abs(r1); 1662e2bed107SBastian Koppelmann /* calc overflow */ 1663e2bed107SBastian Koppelmann env->PSW_USB_V = 0; 1664e2bed107SBastian Koppelmann if ((quotient_sign) && (abs_divisor)) { 1665e2bed107SBastian Koppelmann env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) && 1666e2bed107SBastian Koppelmann (abs_base_dividend >= abs_divisor)) || 1667e2bed107SBastian Koppelmann (abs_sig_dividend > abs_divisor)); 1668e2bed107SBastian Koppelmann } else { 1669e2bed107SBastian Koppelmann env->PSW_USB_V = (abs_sig_dividend >= abs_divisor); 1670e2bed107SBastian Koppelmann } 1671e2bed107SBastian Koppelmann env->PSW_USB_V = env->PSW_USB_V << 31; 1672e2bed107SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 1673e2bed107SBastian Koppelmann env->PSW_USB_AV = 0; 1674e2bed107SBastian Koppelmann 1675e2bed107SBastian Koppelmann return ret; 1676e2bed107SBastian Koppelmann } 1677e2bed107SBastian Koppelmann 1678e2bed107SBastian Koppelmann uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 1679e2bed107SBastian Koppelmann { 1680e2bed107SBastian Koppelmann uint64_t ret = sextract32(r1, 0, 32); 1681e2bed107SBastian Koppelmann 1682e2bed107SBastian Koppelmann ret = ret << 16; 1683e2bed107SBastian Koppelmann if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { 1684e2bed107SBastian Koppelmann ret |= 0xffff; 1685e2bed107SBastian Koppelmann } 1686e2bed107SBastian Koppelmann /* calc overflow */ 1687e2bed107SBastian Koppelmann env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffff8000))); 1688e2bed107SBastian Koppelmann env->PSW_USB_V = env->PSW_USB_V << 31; 1689e2bed107SBastian Koppelmann env->PSW_USB_SV |= env->PSW_USB_V; 1690e2bed107SBastian Koppelmann env->PSW_USB_AV = 0; 1691e2bed107SBastian Koppelmann 1692e2bed107SBastian Koppelmann return ret; 1693e2bed107SBastian Koppelmann } 1694e2bed107SBastian Koppelmann 169509532255SBastian Koppelmann uint64_t helper_dvadj(uint64_t r1, uint32_t r2) 169609532255SBastian Koppelmann { 169709532255SBastian Koppelmann int32_t x_sign = (r1 >> 63); 169809532255SBastian Koppelmann int32_t q_sign = x_sign ^ (r2 >> 31); 169909532255SBastian Koppelmann int32_t eq_pos = x_sign & ((r1 >> 32) == r2); 170009532255SBastian Koppelmann int32_t eq_neg = x_sign & ((r1 >> 32) == -r2); 170109532255SBastian Koppelmann uint32_t quotient; 170209532255SBastian Koppelmann uint64_t ret, remainder; 170309532255SBastian Koppelmann 170409532255SBastian Koppelmann if ((q_sign & ~eq_neg) | eq_pos) { 170509532255SBastian Koppelmann quotient = (r1 + 1) & 0xffffffff; 170609532255SBastian Koppelmann } else { 170709532255SBastian Koppelmann quotient = r1 & 0xffffffff; 170809532255SBastian Koppelmann } 170909532255SBastian Koppelmann 171009532255SBastian Koppelmann if (eq_pos | eq_neg) { 171109532255SBastian Koppelmann remainder = 0; 171209532255SBastian Koppelmann } else { 171309532255SBastian Koppelmann remainder = (r1 & 0xffffffff00000000ull); 171409532255SBastian Koppelmann } 171509532255SBastian Koppelmann ret = remainder|quotient; 171609532255SBastian Koppelmann return ret; 171709532255SBastian Koppelmann } 171809532255SBastian Koppelmann 171909532255SBastian Koppelmann uint64_t helper_dvstep(uint64_t r1, uint32_t r2) 172009532255SBastian Koppelmann { 172109532255SBastian Koppelmann int32_t dividend_sign = extract64(r1, 63, 1); 172209532255SBastian Koppelmann int32_t divisor_sign = extract32(r2, 31, 1); 172309532255SBastian Koppelmann int32_t quotient_sign = (dividend_sign != divisor_sign); 172409532255SBastian Koppelmann int32_t addend, dividend_quotient, remainder; 172509532255SBastian Koppelmann int32_t i, temp; 172609532255SBastian Koppelmann 172709532255SBastian Koppelmann if (quotient_sign) { 172809532255SBastian Koppelmann addend = r2; 172909532255SBastian Koppelmann } else { 173009532255SBastian Koppelmann addend = -r2; 173109532255SBastian Koppelmann } 173209532255SBastian Koppelmann dividend_quotient = (int32_t)r1; 173309532255SBastian Koppelmann remainder = (int32_t)(r1 >> 32); 173409532255SBastian Koppelmann 173509532255SBastian Koppelmann for (i = 0; i < 8; i++) { 173609532255SBastian Koppelmann remainder = (remainder << 1) | extract32(dividend_quotient, 31, 1); 173709532255SBastian Koppelmann dividend_quotient <<= 1; 173809532255SBastian Koppelmann temp = remainder + addend; 173909532255SBastian Koppelmann if ((temp < 0) == dividend_sign) { 174009532255SBastian Koppelmann remainder = temp; 174109532255SBastian Koppelmann } 174209532255SBastian Koppelmann if (((temp < 0) == dividend_sign)) { 174309532255SBastian Koppelmann dividend_quotient = dividend_quotient | !quotient_sign; 174409532255SBastian Koppelmann } else { 174509532255SBastian Koppelmann dividend_quotient = dividend_quotient | quotient_sign; 174609532255SBastian Koppelmann } 174709532255SBastian Koppelmann } 174809532255SBastian Koppelmann return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient; 174909532255SBastian Koppelmann } 175009532255SBastian Koppelmann 175109532255SBastian Koppelmann uint64_t helper_dvstep_u(uint64_t r1, uint32_t r2) 175209532255SBastian Koppelmann { 175309532255SBastian Koppelmann int32_t dividend_quotient = extract64(r1, 0, 32); 175409532255SBastian Koppelmann int64_t remainder = extract64(r1, 32, 32); 175509532255SBastian Koppelmann int32_t i; 175609532255SBastian Koppelmann int64_t temp; 175709532255SBastian Koppelmann for (i = 0; i < 8; i++) { 175809532255SBastian Koppelmann remainder = (remainder << 1) | extract32(dividend_quotient, 31, 1); 175909532255SBastian Koppelmann dividend_quotient <<= 1; 176009532255SBastian Koppelmann temp = (remainder & 0xffffffff) - r2; 176109532255SBastian Koppelmann if (temp >= 0) { 176209532255SBastian Koppelmann remainder = temp; 176309532255SBastian Koppelmann } 176409532255SBastian Koppelmann dividend_quotient = dividend_quotient | !(temp < 0); 176509532255SBastian Koppelmann } 176609532255SBastian Koppelmann return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient; 176709532255SBastian Koppelmann } 176809532255SBastian Koppelmann 17699655b932SBastian Koppelmann uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01, 17709655b932SBastian Koppelmann uint32_t arg10, uint32_t arg11, uint32_t n) 17719655b932SBastian Koppelmann { 17729655b932SBastian Koppelmann uint64_t ret; 17739655b932SBastian Koppelmann uint32_t result0, result1; 17749655b932SBastian Koppelmann 17759655b932SBastian Koppelmann int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && 17769655b932SBastian Koppelmann ((arg10 & 0xffff) == 0x8000) && (n == 1); 17779655b932SBastian Koppelmann int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && 17789655b932SBastian Koppelmann ((arg11 & 0xffff) == 0x8000) && (n == 1); 17799655b932SBastian Koppelmann if (sc1) { 17809655b932SBastian Koppelmann result1 = 0x7fffffff; 17819655b932SBastian Koppelmann } else { 17829655b932SBastian Koppelmann result1 = (((uint32_t)(arg00 * arg10)) << n); 17839655b932SBastian Koppelmann } 17849655b932SBastian Koppelmann if (sc0) { 17859655b932SBastian Koppelmann result0 = 0x7fffffff; 17869655b932SBastian Koppelmann } else { 17879655b932SBastian Koppelmann result0 = (((uint32_t)(arg01 * arg11)) << n); 17889655b932SBastian Koppelmann } 17899655b932SBastian Koppelmann ret = (((uint64_t)result1 << 32)) | result0; 17909655b932SBastian Koppelmann return ret; 17919655b932SBastian Koppelmann } 17929655b932SBastian Koppelmann 17939655b932SBastian Koppelmann uint64_t helper_mulm_h(uint32_t arg00, uint32_t arg01, 17949655b932SBastian Koppelmann uint32_t arg10, uint32_t arg11, uint32_t n) 17959655b932SBastian Koppelmann { 17969655b932SBastian Koppelmann uint64_t ret; 17979655b932SBastian Koppelmann int64_t result0, result1; 17989655b932SBastian Koppelmann 17999655b932SBastian Koppelmann int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && 18009655b932SBastian Koppelmann ((arg10 & 0xffff) == 0x8000) && (n == 1); 18019655b932SBastian Koppelmann int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && 18029655b932SBastian Koppelmann ((arg11 & 0xffff) == 0x8000) && (n == 1); 18039655b932SBastian Koppelmann 18049655b932SBastian Koppelmann if (sc1) { 18059655b932SBastian Koppelmann result1 = 0x7fffffff; 18069655b932SBastian Koppelmann } else { 18079655b932SBastian Koppelmann result1 = (((int32_t)arg00 * (int32_t)arg10) << n); 18089655b932SBastian Koppelmann } 18099655b932SBastian Koppelmann if (sc0) { 18109655b932SBastian Koppelmann result0 = 0x7fffffff; 18119655b932SBastian Koppelmann } else { 18129655b932SBastian Koppelmann result0 = (((int32_t)arg01 * (int32_t)arg11) << n); 18139655b932SBastian Koppelmann } 18149655b932SBastian Koppelmann ret = (result1 + result0); 18159655b932SBastian Koppelmann ret = ret << 16; 18169655b932SBastian Koppelmann return ret; 18179655b932SBastian Koppelmann } 18189655b932SBastian Koppelmann uint32_t helper_mulr_h(uint32_t arg00, uint32_t arg01, 18199655b932SBastian Koppelmann uint32_t arg10, uint32_t arg11, uint32_t n) 18209655b932SBastian Koppelmann { 18219655b932SBastian Koppelmann uint32_t result0, result1; 18229655b932SBastian Koppelmann 18239655b932SBastian Koppelmann int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && 18249655b932SBastian Koppelmann ((arg10 & 0xffff) == 0x8000) && (n == 1); 18259655b932SBastian Koppelmann int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && 18269655b932SBastian Koppelmann ((arg11 & 0xffff) == 0x8000) && (n == 1); 18279655b932SBastian Koppelmann 18289655b932SBastian Koppelmann if (sc1) { 18299655b932SBastian Koppelmann result1 = 0x7fffffff; 18309655b932SBastian Koppelmann } else { 18319655b932SBastian Koppelmann result1 = ((arg00 * arg10) << n) + 0x8000; 18329655b932SBastian Koppelmann } 18339655b932SBastian Koppelmann if (sc0) { 18349655b932SBastian Koppelmann result0 = 0x7fffffff; 18359655b932SBastian Koppelmann } else { 18369655b932SBastian Koppelmann result0 = ((arg01 * arg11) << n) + 0x8000; 18379655b932SBastian Koppelmann } 18389655b932SBastian Koppelmann return (result1 & 0xffff0000) | (result0 >> 16); 18399655b932SBastian Koppelmann } 18409655b932SBastian Koppelmann 18419a31922bSBastian Koppelmann /* context save area (CSA) related helpers */ 18429a31922bSBastian Koppelmann 18439a31922bSBastian Koppelmann static int cdc_increment(target_ulong *psw) 18449a31922bSBastian Koppelmann { 18459a31922bSBastian Koppelmann if ((*psw & MASK_PSW_CDC) == 0x7f) { 18469a31922bSBastian Koppelmann return 0; 18479a31922bSBastian Koppelmann } 18489a31922bSBastian Koppelmann 18499a31922bSBastian Koppelmann (*psw)++; 18509a31922bSBastian Koppelmann /* check for overflow */ 18519a31922bSBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 18529a31922bSBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 18539a31922bSBastian Koppelmann int count = *psw & mask; 18549a31922bSBastian Koppelmann if (count == 0) { 18559a31922bSBastian Koppelmann (*psw)--; 18569a31922bSBastian Koppelmann return 1; 18579a31922bSBastian Koppelmann } 18589a31922bSBastian Koppelmann return 0; 18599a31922bSBastian Koppelmann } 18609a31922bSBastian Koppelmann 18619a31922bSBastian Koppelmann static int cdc_decrement(target_ulong *psw) 18629a31922bSBastian Koppelmann { 18639a31922bSBastian Koppelmann if ((*psw & MASK_PSW_CDC) == 0x7f) { 18649a31922bSBastian Koppelmann return 0; 18659a31922bSBastian Koppelmann } 18669a31922bSBastian Koppelmann /* check for underflow */ 18679a31922bSBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 18689a31922bSBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 18699a31922bSBastian Koppelmann int count = *psw & mask; 18709a31922bSBastian Koppelmann if (count == 0) { 18719a31922bSBastian Koppelmann return 1; 18729a31922bSBastian Koppelmann } 18739a31922bSBastian Koppelmann (*psw)--; 18749a31922bSBastian Koppelmann return 0; 18759a31922bSBastian Koppelmann } 18769a31922bSBastian Koppelmann 187744ea3430SBastian Koppelmann static bool cdc_zero(target_ulong *psw) 187844ea3430SBastian Koppelmann { 187944ea3430SBastian Koppelmann int cdc = *psw & MASK_PSW_CDC; 188044ea3430SBastian Koppelmann /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC == 188144ea3430SBastian Koppelmann 7'b1111111, otherwise returns FALSE. */ 188244ea3430SBastian Koppelmann if (cdc == 0x7f) { 188344ea3430SBastian Koppelmann return true; 188444ea3430SBastian Koppelmann } 188544ea3430SBastian Koppelmann /* find CDC.COUNT */ 188644ea3430SBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 188744ea3430SBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 188844ea3430SBastian Koppelmann int count = *psw & mask; 188944ea3430SBastian Koppelmann return count == 0; 189044ea3430SBastian Koppelmann } 189144ea3430SBastian Koppelmann 1892030c58dfSBastian Koppelmann static void save_context_upper(CPUTriCoreState *env, int ea) 18939a31922bSBastian Koppelmann { 18949a31922bSBastian Koppelmann cpu_stl_data(env, ea, env->PCXI); 18959a31922bSBastian Koppelmann cpu_stl_data(env, ea+4, env->PSW); 18969a31922bSBastian Koppelmann cpu_stl_data(env, ea+8, env->gpr_a[10]); 18979a31922bSBastian Koppelmann cpu_stl_data(env, ea+12, env->gpr_a[11]); 18989a31922bSBastian Koppelmann cpu_stl_data(env, ea+16, env->gpr_d[8]); 18999a31922bSBastian Koppelmann cpu_stl_data(env, ea+20, env->gpr_d[9]); 19009a31922bSBastian Koppelmann cpu_stl_data(env, ea+24, env->gpr_d[10]); 19019a31922bSBastian Koppelmann cpu_stl_data(env, ea+28, env->gpr_d[11]); 19029a31922bSBastian Koppelmann cpu_stl_data(env, ea+32, env->gpr_a[12]); 19039a31922bSBastian Koppelmann cpu_stl_data(env, ea+36, env->gpr_a[13]); 19049a31922bSBastian Koppelmann cpu_stl_data(env, ea+40, env->gpr_a[14]); 19059a31922bSBastian Koppelmann cpu_stl_data(env, ea+44, env->gpr_a[15]); 19069a31922bSBastian Koppelmann cpu_stl_data(env, ea+48, env->gpr_d[12]); 19079a31922bSBastian Koppelmann cpu_stl_data(env, ea+52, env->gpr_d[13]); 19089a31922bSBastian Koppelmann cpu_stl_data(env, ea+56, env->gpr_d[14]); 19099a31922bSBastian Koppelmann cpu_stl_data(env, ea+60, env->gpr_d[15]); 19109a31922bSBastian Koppelmann } 19119a31922bSBastian Koppelmann 1912030c58dfSBastian Koppelmann static void save_context_lower(CPUTriCoreState *env, int ea) 19135de93515SBastian Koppelmann { 19145de93515SBastian Koppelmann cpu_stl_data(env, ea, env->PCXI); 1915030c58dfSBastian Koppelmann cpu_stl_data(env, ea+4, env->gpr_a[11]); 19165de93515SBastian Koppelmann cpu_stl_data(env, ea+8, env->gpr_a[2]); 19175de93515SBastian Koppelmann cpu_stl_data(env, ea+12, env->gpr_a[3]); 19185de93515SBastian Koppelmann cpu_stl_data(env, ea+16, env->gpr_d[0]); 19195de93515SBastian Koppelmann cpu_stl_data(env, ea+20, env->gpr_d[1]); 19205de93515SBastian Koppelmann cpu_stl_data(env, ea+24, env->gpr_d[2]); 19215de93515SBastian Koppelmann cpu_stl_data(env, ea+28, env->gpr_d[3]); 19225de93515SBastian Koppelmann cpu_stl_data(env, ea+32, env->gpr_a[4]); 19235de93515SBastian Koppelmann cpu_stl_data(env, ea+36, env->gpr_a[5]); 19245de93515SBastian Koppelmann cpu_stl_data(env, ea+40, env->gpr_a[6]); 19255de93515SBastian Koppelmann cpu_stl_data(env, ea+44, env->gpr_a[7]); 19265de93515SBastian Koppelmann cpu_stl_data(env, ea+48, env->gpr_d[4]); 19275de93515SBastian Koppelmann cpu_stl_data(env, ea+52, env->gpr_d[5]); 19285de93515SBastian Koppelmann cpu_stl_data(env, ea+56, env->gpr_d[6]); 19295de93515SBastian Koppelmann cpu_stl_data(env, ea+60, env->gpr_d[7]); 19305de93515SBastian Koppelmann } 19315de93515SBastian Koppelmann 19329a31922bSBastian Koppelmann static void restore_context_upper(CPUTriCoreState *env, int ea, 19339a31922bSBastian Koppelmann target_ulong *new_PCXI, target_ulong *new_PSW) 19349a31922bSBastian Koppelmann { 19359a31922bSBastian Koppelmann *new_PCXI = cpu_ldl_data(env, ea); 19369a31922bSBastian Koppelmann *new_PSW = cpu_ldl_data(env, ea+4); 19379a31922bSBastian Koppelmann env->gpr_a[10] = cpu_ldl_data(env, ea+8); 19389a31922bSBastian Koppelmann env->gpr_a[11] = cpu_ldl_data(env, ea+12); 19399a31922bSBastian Koppelmann env->gpr_d[8] = cpu_ldl_data(env, ea+16); 19409a31922bSBastian Koppelmann env->gpr_d[9] = cpu_ldl_data(env, ea+20); 19419a31922bSBastian Koppelmann env->gpr_d[10] = cpu_ldl_data(env, ea+24); 19429a31922bSBastian Koppelmann env->gpr_d[11] = cpu_ldl_data(env, ea+28); 19439a31922bSBastian Koppelmann env->gpr_a[12] = cpu_ldl_data(env, ea+32); 19449a31922bSBastian Koppelmann env->gpr_a[13] = cpu_ldl_data(env, ea+36); 19459a31922bSBastian Koppelmann env->gpr_a[14] = cpu_ldl_data(env, ea+40); 19469a31922bSBastian Koppelmann env->gpr_a[15] = cpu_ldl_data(env, ea+44); 19479a31922bSBastian Koppelmann env->gpr_d[12] = cpu_ldl_data(env, ea+48); 19489a31922bSBastian Koppelmann env->gpr_d[13] = cpu_ldl_data(env, ea+52); 19499a31922bSBastian Koppelmann env->gpr_d[14] = cpu_ldl_data(env, ea+56); 19509a31922bSBastian Koppelmann env->gpr_d[15] = cpu_ldl_data(env, ea+60); 19519a31922bSBastian Koppelmann } 19529a31922bSBastian Koppelmann 195359543d4eSBastian Koppelmann static void restore_context_lower(CPUTriCoreState *env, int ea, 195459543d4eSBastian Koppelmann target_ulong *ra, target_ulong *pcxi) 195559543d4eSBastian Koppelmann { 195659543d4eSBastian Koppelmann *pcxi = cpu_ldl_data(env, ea); 195759543d4eSBastian Koppelmann *ra = cpu_ldl_data(env, ea+4); 195859543d4eSBastian Koppelmann env->gpr_a[2] = cpu_ldl_data(env, ea+8); 195959543d4eSBastian Koppelmann env->gpr_a[3] = cpu_ldl_data(env, ea+12); 196059543d4eSBastian Koppelmann env->gpr_d[0] = cpu_ldl_data(env, ea+16); 196159543d4eSBastian Koppelmann env->gpr_d[1] = cpu_ldl_data(env, ea+20); 196259543d4eSBastian Koppelmann env->gpr_d[2] = cpu_ldl_data(env, ea+24); 196359543d4eSBastian Koppelmann env->gpr_d[3] = cpu_ldl_data(env, ea+28); 196459543d4eSBastian Koppelmann env->gpr_a[4] = cpu_ldl_data(env, ea+32); 196559543d4eSBastian Koppelmann env->gpr_a[5] = cpu_ldl_data(env, ea+36); 196659543d4eSBastian Koppelmann env->gpr_a[6] = cpu_ldl_data(env, ea+40); 196759543d4eSBastian Koppelmann env->gpr_a[7] = cpu_ldl_data(env, ea+44); 196859543d4eSBastian Koppelmann env->gpr_d[4] = cpu_ldl_data(env, ea+48); 196959543d4eSBastian Koppelmann env->gpr_d[5] = cpu_ldl_data(env, ea+52); 197059543d4eSBastian Koppelmann env->gpr_d[6] = cpu_ldl_data(env, ea+56); 197159543d4eSBastian Koppelmann env->gpr_d[7] = cpu_ldl_data(env, ea+60); 197259543d4eSBastian Koppelmann } 197359543d4eSBastian Koppelmann 19749a31922bSBastian Koppelmann void helper_call(CPUTriCoreState *env, uint32_t next_pc) 19759a31922bSBastian Koppelmann { 19769a31922bSBastian Koppelmann target_ulong tmp_FCX; 19779a31922bSBastian Koppelmann target_ulong ea; 19789a31922bSBastian Koppelmann target_ulong new_FCX; 19799a31922bSBastian Koppelmann target_ulong psw; 19809a31922bSBastian Koppelmann 19819a31922bSBastian Koppelmann psw = psw_read(env); 19829a31922bSBastian Koppelmann /* if (FCX == 0) trap(FCU); */ 19839a31922bSBastian Koppelmann if (env->FCX == 0) { 19849a31922bSBastian Koppelmann /* FCU trap */ 19859a31922bSBastian Koppelmann } 19869a31922bSBastian Koppelmann /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */ 19879a31922bSBastian Koppelmann if (psw & MASK_PSW_CDE) { 19889a31922bSBastian Koppelmann if (cdc_increment(&psw)) { 19899a31922bSBastian Koppelmann /* CDO trap */ 19909a31922bSBastian Koppelmann } 19919a31922bSBastian Koppelmann } 19929a31922bSBastian Koppelmann /* PSW.CDE = 1;*/ 19939a31922bSBastian Koppelmann psw |= MASK_PSW_CDE; 19949a31922bSBastian Koppelmann /* tmp_FCX = FCX; */ 19959a31922bSBastian Koppelmann tmp_FCX = env->FCX; 19969a31922bSBastian Koppelmann /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ 19979a31922bSBastian Koppelmann ea = ((env->FCX & MASK_FCX_FCXS) << 12) + 19989a31922bSBastian Koppelmann ((env->FCX & MASK_FCX_FCXO) << 6); 1999030c58dfSBastian Koppelmann /* new_FCX = M(EA, word); */ 2000030c58dfSBastian Koppelmann new_FCX = cpu_ldl_data(env, ea); 2001030c58dfSBastian Koppelmann /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], 20029a31922bSBastian Koppelmann A[12], A[13], A[14], A[15], D[12], D[13], D[14], 20039a31922bSBastian Koppelmann D[15]}; */ 2004030c58dfSBastian Koppelmann save_context_upper(env, ea); 20059a31922bSBastian Koppelmann 20069a31922bSBastian Koppelmann /* PCXI.PCPN = ICR.CCPN; */ 20079a31922bSBastian Koppelmann env->PCXI = (env->PCXI & 0xffffff) + 20089a31922bSBastian Koppelmann ((env->ICR & MASK_ICR_CCPN) << 24); 20099a31922bSBastian Koppelmann /* PCXI.PIE = ICR.IE; */ 20109a31922bSBastian Koppelmann env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 20119a31922bSBastian Koppelmann ((env->ICR & MASK_ICR_IE) << 15)); 20129a31922bSBastian Koppelmann /* PCXI.UL = 1; */ 20139a31922bSBastian Koppelmann env->PCXI |= MASK_PCXI_UL; 20149a31922bSBastian Koppelmann 20159a31922bSBastian Koppelmann /* PCXI[19: 0] = FCX[19: 0]; */ 20169a31922bSBastian Koppelmann env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 20179a31922bSBastian Koppelmann /* FCX[19: 0] = new_FCX[19: 0]; */ 20189a31922bSBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 20199a31922bSBastian Koppelmann /* A[11] = next_pc[31: 0]; */ 20209a31922bSBastian Koppelmann env->gpr_a[11] = next_pc; 20219a31922bSBastian Koppelmann 20229a31922bSBastian Koppelmann /* if (tmp_FCX == LCX) trap(FCD);*/ 20239a31922bSBastian Koppelmann if (tmp_FCX == env->LCX) { 20249a31922bSBastian Koppelmann /* FCD trap */ 20259a31922bSBastian Koppelmann } 20269a31922bSBastian Koppelmann psw_write(env, psw); 20279a31922bSBastian Koppelmann } 20289a31922bSBastian Koppelmann 20299a31922bSBastian Koppelmann void helper_ret(CPUTriCoreState *env) 20309a31922bSBastian Koppelmann { 20319a31922bSBastian Koppelmann target_ulong ea; 20329a31922bSBastian Koppelmann target_ulong new_PCXI; 20339a31922bSBastian Koppelmann target_ulong new_PSW, psw; 20349a31922bSBastian Koppelmann 20359a31922bSBastian Koppelmann psw = psw_read(env); 20369a31922bSBastian Koppelmann /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/ 20379a31922bSBastian Koppelmann if (env->PSW & MASK_PSW_CDE) { 20389a31922bSBastian Koppelmann if (cdc_decrement(&(env->PSW))) { 20399a31922bSBastian Koppelmann /* CDU trap */ 20409a31922bSBastian Koppelmann } 20419a31922bSBastian Koppelmann } 20429a31922bSBastian Koppelmann /* if (PCXI[19: 0] == 0) then trap(CSU); */ 20439a31922bSBastian Koppelmann if ((env->PCXI & 0xfffff) == 0) { 20449a31922bSBastian Koppelmann /* CSU trap */ 20459a31922bSBastian Koppelmann } 20469a31922bSBastian Koppelmann /* if (PCXI.UL == 0) then trap(CTYP); */ 20479a31922bSBastian Koppelmann if ((env->PCXI & MASK_PCXI_UL) == 0) { 20489a31922bSBastian Koppelmann /* CTYP trap */ 20499a31922bSBastian Koppelmann } 20509a31922bSBastian Koppelmann /* PC = {A11 [31: 1], 1’b0}; */ 20519a31922bSBastian Koppelmann env->PC = env->gpr_a[11] & 0xfffffffe; 20529a31922bSBastian Koppelmann 20539a31922bSBastian Koppelmann /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */ 20549a31922bSBastian Koppelmann ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 20559a31922bSBastian Koppelmann ((env->PCXI & MASK_PCXI_PCXO) << 6); 20569a31922bSBastian Koppelmann /* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 2057030c58dfSBastian Koppelmann A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 20589a31922bSBastian Koppelmann restore_context_upper(env, ea, &new_PCXI, &new_PSW); 2059030c58dfSBastian Koppelmann /* M(EA, word) = FCX; */ 2060030c58dfSBastian Koppelmann cpu_stl_data(env, ea, env->FCX); 20619a31922bSBastian Koppelmann /* FCX[19: 0] = PCXI[19: 0]; */ 20629a31922bSBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 20639a31922bSBastian Koppelmann /* PCXI = new_PCXI; */ 20649a31922bSBastian Koppelmann env->PCXI = new_PCXI; 20659a31922bSBastian Koppelmann 20669a31922bSBastian Koppelmann if (tricore_feature(env, TRICORE_FEATURE_13)) { 20679a31922bSBastian Koppelmann /* PSW = new_PSW */ 20689a31922bSBastian Koppelmann psw_write(env, new_PSW); 20699a31922bSBastian Koppelmann } else { 20709a31922bSBastian Koppelmann /* PSW = {new_PSW[31:26], PSW[25:24], new_PSW[23:0]}; */ 20719a31922bSBastian Koppelmann psw_write(env, (new_PSW & ~(0x3000000)) + (psw & (0x3000000))); 20729a31922bSBastian Koppelmann } 20739a31922bSBastian Koppelmann } 20749a31922bSBastian Koppelmann 20755de93515SBastian Koppelmann void helper_bisr(CPUTriCoreState *env, uint32_t const9) 20765de93515SBastian Koppelmann { 20775de93515SBastian Koppelmann target_ulong tmp_FCX; 20785de93515SBastian Koppelmann target_ulong ea; 20795de93515SBastian Koppelmann target_ulong new_FCX; 20805de93515SBastian Koppelmann 20815de93515SBastian Koppelmann if (env->FCX == 0) { 20825de93515SBastian Koppelmann /* FCU trap */ 20835de93515SBastian Koppelmann } 20845de93515SBastian Koppelmann 20855de93515SBastian Koppelmann tmp_FCX = env->FCX; 20865de93515SBastian Koppelmann ea = ((env->FCX & 0xf0000) << 12) + ((env->FCX & 0xffff) << 6); 20875de93515SBastian Koppelmann 2088030c58dfSBastian Koppelmann /* new_FCX = M(EA, word); */ 2089030c58dfSBastian Koppelmann new_FCX = cpu_ldl_data(env, ea); 2090030c58dfSBastian Koppelmann /* M(EA, 16 * word) = {PCXI, A[11], A[2], A[3], D[0], D[1], D[2], D[3], A[4] 2091030c58dfSBastian Koppelmann , A[5], A[6], A[7], D[4], D[5], D[6], D[7]}; */ 2092030c58dfSBastian Koppelmann save_context_lower(env, ea); 2093030c58dfSBastian Koppelmann 20945de93515SBastian Koppelmann 20955de93515SBastian Koppelmann /* PCXI.PCPN = ICR.CCPN */ 20965de93515SBastian Koppelmann env->PCXI = (env->PCXI & 0xffffff) + 20975de93515SBastian Koppelmann ((env->ICR & MASK_ICR_CCPN) << 24); 20985de93515SBastian Koppelmann /* PCXI.PIE = ICR.IE */ 20995de93515SBastian Koppelmann env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 21005de93515SBastian Koppelmann ((env->ICR & MASK_ICR_IE) << 15)); 21015de93515SBastian Koppelmann /* PCXI.UL = 0 */ 21025de93515SBastian Koppelmann env->PCXI &= ~(MASK_PCXI_UL); 21035de93515SBastian Koppelmann /* PCXI[19: 0] = FCX[19: 0] */ 21045de93515SBastian Koppelmann env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 21055de93515SBastian Koppelmann /* FXC[19: 0] = new_FCX[19: 0] */ 21065de93515SBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 21075de93515SBastian Koppelmann /* ICR.IE = 1 */ 21085de93515SBastian Koppelmann env->ICR |= MASK_ICR_IE; 21095de93515SBastian Koppelmann 21105de93515SBastian Koppelmann env->ICR |= const9; /* ICR.CCPN = const9[7: 0];*/ 21115de93515SBastian Koppelmann 21125de93515SBastian Koppelmann if (tmp_FCX == env->LCX) { 21135de93515SBastian Koppelmann /* FCD trap */ 21145de93515SBastian Koppelmann } 21155de93515SBastian Koppelmann } 21165de93515SBastian Koppelmann 211744ea3430SBastian Koppelmann void helper_rfe(CPUTriCoreState *env) 211844ea3430SBastian Koppelmann { 211944ea3430SBastian Koppelmann target_ulong ea; 212044ea3430SBastian Koppelmann target_ulong new_PCXI; 212144ea3430SBastian Koppelmann target_ulong new_PSW; 212244ea3430SBastian Koppelmann /* if (PCXI[19: 0] == 0) then trap(CSU); */ 212344ea3430SBastian Koppelmann if ((env->PCXI & 0xfffff) == 0) { 212444ea3430SBastian Koppelmann /* raise csu trap */ 212544ea3430SBastian Koppelmann } 212644ea3430SBastian Koppelmann /* if (PCXI.UL == 0) then trap(CTYP); */ 212744ea3430SBastian Koppelmann if ((env->PCXI & MASK_PCXI_UL) == 0) { 212844ea3430SBastian Koppelmann /* raise CTYP trap */ 212944ea3430SBastian Koppelmann } 213044ea3430SBastian Koppelmann /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */ 213144ea3430SBastian Koppelmann if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) { 213244ea3430SBastian Koppelmann /* raise MNG trap */ 213344ea3430SBastian Koppelmann } 213444ea3430SBastian Koppelmann /* ICR.IE = PCXI.PIE; */ 213544ea3430SBastian Koppelmann env->ICR = (env->ICR & ~MASK_ICR_IE) + ((env->PCXI & MASK_PCXI_PIE) >> 15); 213644ea3430SBastian Koppelmann /* ICR.CCPN = PCXI.PCPN; */ 213744ea3430SBastian Koppelmann env->ICR = (env->ICR & ~MASK_ICR_CCPN) + 213844ea3430SBastian Koppelmann ((env->PCXI & MASK_PCXI_PCPN) >> 24); 213944ea3430SBastian Koppelmann /*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/ 214044ea3430SBastian Koppelmann ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 214144ea3430SBastian Koppelmann ((env->PCXI & MASK_PCXI_PCXO) << 6); 214244ea3430SBastian Koppelmann /*{new_PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 2143030c58dfSBastian Koppelmann A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 214444ea3430SBastian Koppelmann restore_context_upper(env, ea, &new_PCXI, &new_PSW); 2145030c58dfSBastian Koppelmann /* M(EA, word) = FCX;*/ 2146030c58dfSBastian Koppelmann cpu_stl_data(env, ea, env->FCX); 214744ea3430SBastian Koppelmann /* FCX[19: 0] = PCXI[19: 0]; */ 214844ea3430SBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 214944ea3430SBastian Koppelmann /* PCXI = new_PCXI; */ 215044ea3430SBastian Koppelmann env->PCXI = new_PCXI; 215144ea3430SBastian Koppelmann /* write psw */ 215244ea3430SBastian Koppelmann psw_write(env, new_PSW); 215344ea3430SBastian Koppelmann } 215444ea3430SBastian Koppelmann 215559543d4eSBastian Koppelmann void helper_ldlcx(CPUTriCoreState *env, uint32_t ea) 215659543d4eSBastian Koppelmann { 215759543d4eSBastian Koppelmann uint32_t dummy; 215859543d4eSBastian Koppelmann /* insn doesn't load PCXI and RA */ 215959543d4eSBastian Koppelmann restore_context_lower(env, ea, &dummy, &dummy); 216059543d4eSBastian Koppelmann } 216159543d4eSBastian Koppelmann 216259543d4eSBastian Koppelmann void helper_lducx(CPUTriCoreState *env, uint32_t ea) 216359543d4eSBastian Koppelmann { 216459543d4eSBastian Koppelmann uint32_t dummy; 216559543d4eSBastian Koppelmann /* insn doesn't load PCXI and PSW */ 216659543d4eSBastian Koppelmann restore_context_upper(env, ea, &dummy, &dummy); 216759543d4eSBastian Koppelmann } 216859543d4eSBastian Koppelmann 216959543d4eSBastian Koppelmann void helper_stlcx(CPUTriCoreState *env, uint32_t ea) 217059543d4eSBastian Koppelmann { 217159543d4eSBastian Koppelmann save_context_lower(env, ea); 217259543d4eSBastian Koppelmann } 217359543d4eSBastian Koppelmann 217459543d4eSBastian Koppelmann void helper_stucx(CPUTriCoreState *env, uint32_t ea) 217559543d4eSBastian Koppelmann { 217659543d4eSBastian Koppelmann save_context_upper(env, ea); 217759543d4eSBastian Koppelmann } 217859543d4eSBastian Koppelmann 21792b2f7d97SBastian Koppelmann void helper_psw_write(CPUTriCoreState *env, uint32_t arg) 21802b2f7d97SBastian Koppelmann { 21812b2f7d97SBastian Koppelmann psw_write(env, arg); 21822b2f7d97SBastian Koppelmann } 21832b2f7d97SBastian Koppelmann 21842b2f7d97SBastian Koppelmann uint32_t helper_psw_read(CPUTriCoreState *env) 21852b2f7d97SBastian Koppelmann { 21862b2f7d97SBastian Koppelmann return psw_read(env); 21872b2f7d97SBastian Koppelmann } 21882b2f7d97SBastian Koppelmann 21892b2f7d97SBastian Koppelmann 21902d30267eSBastian Koppelmann static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env, 21912d30267eSBastian Koppelmann uint32_t exception, 21922d30267eSBastian Koppelmann int error_code, 21932d30267eSBastian Koppelmann uintptr_t pc) 21942d30267eSBastian Koppelmann { 21952d30267eSBastian Koppelmann CPUState *cs = CPU(tricore_env_get_cpu(env)); 21962d30267eSBastian Koppelmann cs->exception_index = exception; 21972d30267eSBastian Koppelmann env->error_code = error_code; 21982d30267eSBastian Koppelmann 21992d30267eSBastian Koppelmann if (pc) { 22002d30267eSBastian Koppelmann /* now we have a real cpu fault */ 22012d30267eSBastian Koppelmann cpu_restore_state(cs, pc); 22022d30267eSBastian Koppelmann } 22032d30267eSBastian Koppelmann 22042d30267eSBastian Koppelmann cpu_loop_exit(cs); 22052d30267eSBastian Koppelmann } 22062d30267eSBastian Koppelmann 220748e06fe0SBastian Koppelmann void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx, 220848e06fe0SBastian Koppelmann uintptr_t retaddr) 220948e06fe0SBastian Koppelmann { 22102d30267eSBastian Koppelmann int ret; 22112d30267eSBastian Koppelmann ret = cpu_tricore_handle_mmu_fault(cs, addr, is_write, mmu_idx); 22122d30267eSBastian Koppelmann if (ret) { 22132d30267eSBastian Koppelmann TriCoreCPU *cpu = TRICORE_CPU(cs); 22142d30267eSBastian Koppelmann CPUTriCoreState *env = &cpu->env; 22152d30267eSBastian Koppelmann do_raise_exception_err(env, cs->exception_index, 22162d30267eSBastian Koppelmann env->error_code, retaddr); 221748e06fe0SBastian Koppelmann } 22182d30267eSBastian Koppelmann } 2219