1075d047eSYoshinori Sato /* 2075d047eSYoshinori Sato * RX helper functions 3075d047eSYoshinori Sato * 4075d047eSYoshinori Sato * Copyright (c) 2019 Yoshinori Sato 5075d047eSYoshinori Sato * 6075d047eSYoshinori Sato * This program is free software; you can redistribute it and/or modify it 7075d047eSYoshinori Sato * under the terms and conditions of the GNU General Public License, 8075d047eSYoshinori Sato * version 2 or later, as published by the Free Software Foundation. 9075d047eSYoshinori Sato * 10075d047eSYoshinori Sato * This program is distributed in the hope it will be useful, but WITHOUT 11075d047eSYoshinori Sato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12075d047eSYoshinori Sato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13075d047eSYoshinori Sato * more details. 14075d047eSYoshinori Sato * 15075d047eSYoshinori Sato * You should have received a copy of the GNU General Public License along with 16075d047eSYoshinori Sato * this program. If not, see <http://www.gnu.org/licenses/>. 17075d047eSYoshinori Sato */ 18075d047eSYoshinori Sato 19075d047eSYoshinori Sato #include "qemu/osdep.h" 20075d047eSYoshinori Sato #include "qemu/bitops.h" 21075d047eSYoshinori Sato #include "cpu.h" 22075d047eSYoshinori Sato #include "exec/exec-all.h" 23075d047eSYoshinori Sato #include "exec/helper-proto.h" 24075d047eSYoshinori Sato #include "exec/cpu_ldst.h" 25075d047eSYoshinori Sato #include "fpu/softfloat.h" 26fafe0021SRichard Henderson #include "tcg/debug-assert.h" 27075d047eSYoshinori Sato 288905770bSMarc-André Lureau static inline G_NORETURN 298905770bSMarc-André Lureau void raise_exception(CPURXState *env, int index, 30075d047eSYoshinori Sato uintptr_t retaddr); 31075d047eSYoshinori Sato 32075d047eSYoshinori Sato static void _set_psw(CPURXState *env, uint32_t psw, uint32_t rte) 33075d047eSYoshinori Sato { 34075d047eSYoshinori Sato uint32_t prev_u; 35075d047eSYoshinori Sato prev_u = env->psw_u; 36075d047eSYoshinori Sato rx_cpu_unpack_psw(env, psw, rte); 37075d047eSYoshinori Sato if (prev_u != env->psw_u) { 38075d047eSYoshinori Sato /* switch r0 */ 39075d047eSYoshinori Sato if (env->psw_u) { 40075d047eSYoshinori Sato env->isp = env->regs[0]; 41075d047eSYoshinori Sato env->regs[0] = env->usp; 42075d047eSYoshinori Sato } else { 43075d047eSYoshinori Sato env->usp = env->regs[0]; 44075d047eSYoshinori Sato env->regs[0] = env->isp; 45075d047eSYoshinori Sato } 46075d047eSYoshinori Sato } 47075d047eSYoshinori Sato } 48075d047eSYoshinori Sato 49075d047eSYoshinori Sato void helper_set_psw(CPURXState *env, uint32_t psw) 50075d047eSYoshinori Sato { 51075d047eSYoshinori Sato _set_psw(env, psw, 0); 52075d047eSYoshinori Sato } 53075d047eSYoshinori Sato 54075d047eSYoshinori Sato void helper_set_psw_rte(CPURXState *env, uint32_t psw) 55075d047eSYoshinori Sato { 56075d047eSYoshinori Sato _set_psw(env, psw, 1); 57075d047eSYoshinori Sato } 58075d047eSYoshinori Sato 59075d047eSYoshinori Sato uint32_t helper_pack_psw(CPURXState *env) 60075d047eSYoshinori Sato { 61075d047eSYoshinori Sato return rx_cpu_pack_psw(env); 62075d047eSYoshinori Sato } 63075d047eSYoshinori Sato 64075d047eSYoshinori Sato #define SET_FPSW(b) \ 65075d047eSYoshinori Sato do { \ 66075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, C ## b, 1); \ 67075d047eSYoshinori Sato if (!FIELD_EX32(env->fpsw, FPSW, E ## b)) { \ 68075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, F ## b, 1); \ 69075d047eSYoshinori Sato } \ 70075d047eSYoshinori Sato } while (0) 71075d047eSYoshinori Sato 72075d047eSYoshinori Sato /* fp operations */ 73075d047eSYoshinori Sato static void update_fpsw(CPURXState *env, float32 ret, uintptr_t retaddr) 74075d047eSYoshinori Sato { 75075d047eSYoshinori Sato int xcpt, cause, enable; 76075d047eSYoshinori Sato 77075d047eSYoshinori Sato env->psw_z = ret & ~(1 << 31); /* mask sign bit */ 78075d047eSYoshinori Sato env->psw_s = ret; 79075d047eSYoshinori Sato 80075d047eSYoshinori Sato xcpt = get_float_exception_flags(&env->fp_status); 81075d047eSYoshinori Sato 82075d047eSYoshinori Sato /* Clear the cause entries */ 83075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, CAUSE, 0); 84075d047eSYoshinori Sato 85075d047eSYoshinori Sato /* set FPSW */ 86075d047eSYoshinori Sato if (unlikely(xcpt)) { 87075d047eSYoshinori Sato if (xcpt & float_flag_invalid) { 88075d047eSYoshinori Sato SET_FPSW(V); 89075d047eSYoshinori Sato } 90075d047eSYoshinori Sato if (xcpt & float_flag_divbyzero) { 91075d047eSYoshinori Sato SET_FPSW(Z); 92075d047eSYoshinori Sato } 93075d047eSYoshinori Sato if (xcpt & float_flag_overflow) { 94075d047eSYoshinori Sato SET_FPSW(O); 95075d047eSYoshinori Sato } 96075d047eSYoshinori Sato if (xcpt & float_flag_underflow) { 97075d047eSYoshinori Sato SET_FPSW(U); 98075d047eSYoshinori Sato } 99075d047eSYoshinori Sato if (xcpt & float_flag_inexact) { 100075d047eSYoshinori Sato SET_FPSW(X); 101075d047eSYoshinori Sato } 102584b7aecSPeter Maydell if ((xcpt & (float_flag_input_denormal_flushed 103*7af64d10SPeter Maydell | float_flag_output_denormal_flushed)) 104075d047eSYoshinori Sato && !FIELD_EX32(env->fpsw, FPSW, DN)) { 105075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, CE, 1); 106075d047eSYoshinori Sato } 107075d047eSYoshinori Sato 108075d047eSYoshinori Sato /* update FPSW_FLAG_S */ 109075d047eSYoshinori Sato if (FIELD_EX32(env->fpsw, FPSW, FLAGS) != 0) { 110075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, FS, 1); 111075d047eSYoshinori Sato } 112075d047eSYoshinori Sato 113075d047eSYoshinori Sato /* Generate an exception if enabled */ 114075d047eSYoshinori Sato cause = FIELD_EX32(env->fpsw, FPSW, CAUSE); 115075d047eSYoshinori Sato enable = FIELD_EX32(env->fpsw, FPSW, ENABLE); 116075d047eSYoshinori Sato enable |= 1 << 5; /* CE always enabled */ 117075d047eSYoshinori Sato if (cause & enable) { 118075d047eSYoshinori Sato raise_exception(env, 21, retaddr); 119075d047eSYoshinori Sato } 120075d047eSYoshinori Sato } 121075d047eSYoshinori Sato } 122075d047eSYoshinori Sato 123075d047eSYoshinori Sato void helper_set_fpsw(CPURXState *env, uint32_t val) 124075d047eSYoshinori Sato { 125075d047eSYoshinori Sato static const int roundmode[] = { 126075d047eSYoshinori Sato float_round_nearest_even, 127075d047eSYoshinori Sato float_round_to_zero, 128075d047eSYoshinori Sato float_round_up, 129075d047eSYoshinori Sato float_round_down, 130075d047eSYoshinori Sato }; 131075d047eSYoshinori Sato uint32_t fpsw = env->fpsw; 132075d047eSYoshinori Sato fpsw |= 0x7fffff03; 133075d047eSYoshinori Sato val &= ~0x80000000; 134075d047eSYoshinori Sato fpsw &= val; 135075d047eSYoshinori Sato FIELD_DP32(fpsw, FPSW, FS, FIELD_EX32(fpsw, FPSW, FLAGS) != 0); 136075d047eSYoshinori Sato env->fpsw = fpsw; 137075d047eSYoshinori Sato set_float_rounding_mode(roundmode[FIELD_EX32(env->fpsw, FPSW, RM)], 138075d047eSYoshinori Sato &env->fp_status); 139075d047eSYoshinori Sato } 140075d047eSYoshinori Sato 141075d047eSYoshinori Sato #define FLOATOP(op, func) \ 142075d047eSYoshinori Sato float32 helper_##op(CPURXState *env, float32 t0, float32 t1) \ 143075d047eSYoshinori Sato { \ 144075d047eSYoshinori Sato float32 ret; \ 145075d047eSYoshinori Sato ret = func(t0, t1, &env->fp_status); \ 146075d047eSYoshinori Sato update_fpsw(env, *(uint32_t *)&ret, GETPC()); \ 147075d047eSYoshinori Sato return ret; \ 148075d047eSYoshinori Sato } 149075d047eSYoshinori Sato 150075d047eSYoshinori Sato FLOATOP(fadd, float32_add) 151075d047eSYoshinori Sato FLOATOP(fsub, float32_sub) 152075d047eSYoshinori Sato FLOATOP(fmul, float32_mul) 153075d047eSYoshinori Sato FLOATOP(fdiv, float32_div) 154075d047eSYoshinori Sato 155075d047eSYoshinori Sato void helper_fcmp(CPURXState *env, float32 t0, float32 t1) 156075d047eSYoshinori Sato { 157075d047eSYoshinori Sato int st; 158075d047eSYoshinori Sato st = float32_compare(t0, t1, &env->fp_status); 159075d047eSYoshinori Sato update_fpsw(env, 0, GETPC()); 160075d047eSYoshinori Sato env->psw_z = 1; 161075d047eSYoshinori Sato env->psw_s = env->psw_o = 0; 162075d047eSYoshinori Sato switch (st) { 163075d047eSYoshinori Sato case float_relation_equal: 164075d047eSYoshinori Sato env->psw_z = 0; 165075d047eSYoshinori Sato break; 166075d047eSYoshinori Sato case float_relation_less: 167075d047eSYoshinori Sato env->psw_s = -1; 168075d047eSYoshinori Sato break; 169075d047eSYoshinori Sato case float_relation_unordered: 170075d047eSYoshinori Sato env->psw_o = -1; 171075d047eSYoshinori Sato break; 172075d047eSYoshinori Sato } 173075d047eSYoshinori Sato } 174075d047eSYoshinori Sato 175075d047eSYoshinori Sato uint32_t helper_ftoi(CPURXState *env, float32 t0) 176075d047eSYoshinori Sato { 177075d047eSYoshinori Sato uint32_t ret; 178075d047eSYoshinori Sato ret = float32_to_int32_round_to_zero(t0, &env->fp_status); 179075d047eSYoshinori Sato update_fpsw(env, ret, GETPC()); 180075d047eSYoshinori Sato return ret; 181075d047eSYoshinori Sato } 182075d047eSYoshinori Sato 183075d047eSYoshinori Sato uint32_t helper_round(CPURXState *env, float32 t0) 184075d047eSYoshinori Sato { 185075d047eSYoshinori Sato uint32_t ret; 186075d047eSYoshinori Sato ret = float32_to_int32(t0, &env->fp_status); 187075d047eSYoshinori Sato update_fpsw(env, ret, GETPC()); 188075d047eSYoshinori Sato return ret; 189075d047eSYoshinori Sato } 190075d047eSYoshinori Sato 191075d047eSYoshinori Sato float32 helper_itof(CPURXState *env, uint32_t t0) 192075d047eSYoshinori Sato { 193075d047eSYoshinori Sato float32 ret; 194075d047eSYoshinori Sato ret = int32_to_float32(t0, &env->fp_status); 195075d047eSYoshinori Sato update_fpsw(env, ret, GETPC()); 196075d047eSYoshinori Sato return ret; 197075d047eSYoshinori Sato } 198075d047eSYoshinori Sato 199075d047eSYoshinori Sato /* string operations */ 200075d047eSYoshinori Sato void helper_scmpu(CPURXState *env) 201075d047eSYoshinori Sato { 202075d047eSYoshinori Sato uint8_t tmp0, tmp1; 203075d047eSYoshinori Sato if (env->regs[3] == 0) { 204075d047eSYoshinori Sato return; 205075d047eSYoshinori Sato } 20677182df1SStefan Weil do { 207075d047eSYoshinori Sato tmp0 = cpu_ldub_data_ra(env, env->regs[1]++, GETPC()); 208075d047eSYoshinori Sato tmp1 = cpu_ldub_data_ra(env, env->regs[2]++, GETPC()); 209075d047eSYoshinori Sato env->regs[3]--; 210075d047eSYoshinori Sato if (tmp0 != tmp1 || tmp0 == '\0') { 211075d047eSYoshinori Sato break; 212075d047eSYoshinori Sato } 21377182df1SStefan Weil } while (env->regs[3] != 0); 214075d047eSYoshinori Sato env->psw_z = tmp0 - tmp1; 215075d047eSYoshinori Sato env->psw_c = (tmp0 >= tmp1); 216075d047eSYoshinori Sato } 217075d047eSYoshinori Sato 218075d047eSYoshinori Sato static uint32_t (* const cpu_ldufn[])(CPUArchState *env, 219022b9bceSAnton Johansson abi_ptr ptr, 220075d047eSYoshinori Sato uintptr_t retaddr) = { 221075d047eSYoshinori Sato cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra, 222075d047eSYoshinori Sato }; 223075d047eSYoshinori Sato 224075d047eSYoshinori Sato static uint32_t (* const cpu_ldfn[])(CPUArchState *env, 225022b9bceSAnton Johansson abi_ptr ptr, 226075d047eSYoshinori Sato uintptr_t retaddr) = { 227075d047eSYoshinori Sato cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra, 228075d047eSYoshinori Sato }; 229075d047eSYoshinori Sato 230075d047eSYoshinori Sato static void (* const cpu_stfn[])(CPUArchState *env, 231022b9bceSAnton Johansson abi_ptr ptr, 232075d047eSYoshinori Sato uint32_t val, 233075d047eSYoshinori Sato uintptr_t retaddr) = { 234075d047eSYoshinori Sato cpu_stb_data_ra, cpu_stw_data_ra, cpu_stl_data_ra, 235075d047eSYoshinori Sato }; 236075d047eSYoshinori Sato 237075d047eSYoshinori Sato void helper_sstr(CPURXState *env, uint32_t sz) 238075d047eSYoshinori Sato { 239075d047eSYoshinori Sato tcg_debug_assert(sz < 3); 240075d047eSYoshinori Sato while (env->regs[3] != 0) { 241075d047eSYoshinori Sato cpu_stfn[sz](env, env->regs[1], env->regs[2], GETPC()); 242075d047eSYoshinori Sato env->regs[1] += 1 << sz; 243075d047eSYoshinori Sato env->regs[3]--; 244075d047eSYoshinori Sato } 245075d047eSYoshinori Sato } 246075d047eSYoshinori Sato 247075d047eSYoshinori Sato #define OP_SMOVU 1 248075d047eSYoshinori Sato #define OP_SMOVF 0 249075d047eSYoshinori Sato #define OP_SMOVB 2 250075d047eSYoshinori Sato 251075d047eSYoshinori Sato static void smov(uint32_t mode, CPURXState *env) 252075d047eSYoshinori Sato { 253075d047eSYoshinori Sato uint8_t tmp; 254075d047eSYoshinori Sato int dir; 255075d047eSYoshinori Sato 256075d047eSYoshinori Sato dir = (mode & OP_SMOVB) ? -1 : 1; 257075d047eSYoshinori Sato while (env->regs[3] != 0) { 258075d047eSYoshinori Sato tmp = cpu_ldub_data_ra(env, env->regs[2], GETPC()); 259075d047eSYoshinori Sato cpu_stb_data_ra(env, env->regs[1], tmp, GETPC()); 260075d047eSYoshinori Sato env->regs[1] += dir; 261075d047eSYoshinori Sato env->regs[2] += dir; 262075d047eSYoshinori Sato env->regs[3]--; 263075d047eSYoshinori Sato if ((mode & OP_SMOVU) && tmp == 0) { 264075d047eSYoshinori Sato break; 265075d047eSYoshinori Sato } 266075d047eSYoshinori Sato } 267075d047eSYoshinori Sato } 268075d047eSYoshinori Sato 269075d047eSYoshinori Sato void helper_smovu(CPURXState *env) 270075d047eSYoshinori Sato { 271075d047eSYoshinori Sato smov(OP_SMOVU, env); 272075d047eSYoshinori Sato } 273075d047eSYoshinori Sato 274075d047eSYoshinori Sato void helper_smovf(CPURXState *env) 275075d047eSYoshinori Sato { 276075d047eSYoshinori Sato smov(OP_SMOVF, env); 277075d047eSYoshinori Sato } 278075d047eSYoshinori Sato 279075d047eSYoshinori Sato void helper_smovb(CPURXState *env) 280075d047eSYoshinori Sato { 281075d047eSYoshinori Sato smov(OP_SMOVB, env); 282075d047eSYoshinori Sato } 283075d047eSYoshinori Sato 284075d047eSYoshinori Sato 285075d047eSYoshinori Sato void helper_suntil(CPURXState *env, uint32_t sz) 286075d047eSYoshinori Sato { 287075d047eSYoshinori Sato uint32_t tmp; 288075d047eSYoshinori Sato tcg_debug_assert(sz < 3); 289075d047eSYoshinori Sato if (env->regs[3] == 0) { 290075d047eSYoshinori Sato return; 291075d047eSYoshinori Sato } 29277182df1SStefan Weil do { 293075d047eSYoshinori Sato tmp = cpu_ldufn[sz](env, env->regs[1], GETPC()); 294075d047eSYoshinori Sato env->regs[1] += 1 << sz; 295075d047eSYoshinori Sato env->regs[3]--; 296075d047eSYoshinori Sato if (tmp == env->regs[2]) { 297075d047eSYoshinori Sato break; 298075d047eSYoshinori Sato } 29977182df1SStefan Weil } while (env->regs[3] != 0); 300075d047eSYoshinori Sato env->psw_z = tmp - env->regs[2]; 301075d047eSYoshinori Sato env->psw_c = (tmp <= env->regs[2]); 302075d047eSYoshinori Sato } 303075d047eSYoshinori Sato 304075d047eSYoshinori Sato void helper_swhile(CPURXState *env, uint32_t sz) 305075d047eSYoshinori Sato { 306075d047eSYoshinori Sato uint32_t tmp; 307075d047eSYoshinori Sato tcg_debug_assert(sz < 3); 308075d047eSYoshinori Sato if (env->regs[3] == 0) { 309075d047eSYoshinori Sato return; 310075d047eSYoshinori Sato } 31177182df1SStefan Weil do { 312075d047eSYoshinori Sato tmp = cpu_ldufn[sz](env, env->regs[1], GETPC()); 313075d047eSYoshinori Sato env->regs[1] += 1 << sz; 314075d047eSYoshinori Sato env->regs[3]--; 315075d047eSYoshinori Sato if (tmp != env->regs[2]) { 316075d047eSYoshinori Sato break; 317075d047eSYoshinori Sato } 31877182df1SStefan Weil } while (env->regs[3] != 0); 319075d047eSYoshinori Sato env->psw_z = env->regs[3]; 320075d047eSYoshinori Sato env->psw_c = (tmp <= env->regs[2]); 321075d047eSYoshinori Sato } 322075d047eSYoshinori Sato 32397841438SLichang Zhao /* accumulator operations */ 324075d047eSYoshinori Sato void helper_rmpa(CPURXState *env, uint32_t sz) 325075d047eSYoshinori Sato { 326075d047eSYoshinori Sato uint64_t result_l, prev; 327075d047eSYoshinori Sato int32_t result_h; 328075d047eSYoshinori Sato int64_t tmp0, tmp1; 329075d047eSYoshinori Sato 330075d047eSYoshinori Sato if (env->regs[3] == 0) { 331075d047eSYoshinori Sato return; 332075d047eSYoshinori Sato } 333075d047eSYoshinori Sato result_l = env->regs[5]; 334075d047eSYoshinori Sato result_l <<= 32; 335075d047eSYoshinori Sato result_l |= env->regs[4]; 336075d047eSYoshinori Sato result_h = env->regs[6]; 337075d047eSYoshinori Sato env->psw_o = 0; 338075d047eSYoshinori Sato 339075d047eSYoshinori Sato while (env->regs[3] != 0) { 340075d047eSYoshinori Sato tmp0 = cpu_ldfn[sz](env, env->regs[1], GETPC()); 341075d047eSYoshinori Sato tmp1 = cpu_ldfn[sz](env, env->regs[2], GETPC()); 342075d047eSYoshinori Sato tmp0 *= tmp1; 343075d047eSYoshinori Sato prev = result_l; 344075d047eSYoshinori Sato result_l += tmp0; 345075d047eSYoshinori Sato /* carry / bollow */ 346075d047eSYoshinori Sato if (tmp0 < 0) { 347075d047eSYoshinori Sato if (prev > result_l) { 348075d047eSYoshinori Sato result_h--; 349075d047eSYoshinori Sato } 350075d047eSYoshinori Sato } else { 351075d047eSYoshinori Sato if (prev < result_l) { 352075d047eSYoshinori Sato result_h++; 353075d047eSYoshinori Sato } 354075d047eSYoshinori Sato } 355075d047eSYoshinori Sato 356075d047eSYoshinori Sato env->regs[1] += 1 << sz; 357075d047eSYoshinori Sato env->regs[2] += 1 << sz; 358075d047eSYoshinori Sato } 359075d047eSYoshinori Sato env->psw_s = result_h; 360075d047eSYoshinori Sato env->psw_o = (result_h != 0 && result_h != -1) << 31; 361075d047eSYoshinori Sato env->regs[6] = result_h; 362075d047eSYoshinori Sato env->regs[5] = result_l >> 32; 363075d047eSYoshinori Sato env->regs[4] = result_l & 0xffffffff; 364075d047eSYoshinori Sato } 365075d047eSYoshinori Sato 366075d047eSYoshinori Sato void helper_racw(CPURXState *env, uint32_t imm) 367075d047eSYoshinori Sato { 368075d047eSYoshinori Sato int64_t acc; 369075d047eSYoshinori Sato acc = env->acc; 370075d047eSYoshinori Sato acc <<= (imm + 1); 371075d047eSYoshinori Sato acc += 0x0000000080000000LL; 372075d047eSYoshinori Sato if (acc > 0x00007fff00000000LL) { 373075d047eSYoshinori Sato acc = 0x00007fff00000000LL; 374075d047eSYoshinori Sato } else if (acc < -0x800000000000LL) { 375075d047eSYoshinori Sato acc = -0x800000000000LL; 376075d047eSYoshinori Sato } else { 377075d047eSYoshinori Sato acc &= 0xffffffff00000000LL; 378075d047eSYoshinori Sato } 379075d047eSYoshinori Sato env->acc = acc; 380075d047eSYoshinori Sato } 381075d047eSYoshinori Sato 382075d047eSYoshinori Sato void helper_satr(CPURXState *env) 383075d047eSYoshinori Sato { 384075d047eSYoshinori Sato if (env->psw_o >> 31) { 385075d047eSYoshinori Sato if ((int)env->psw_s < 0) { 386075d047eSYoshinori Sato env->regs[6] = 0x00000000; 387075d047eSYoshinori Sato env->regs[5] = 0x7fffffff; 388075d047eSYoshinori Sato env->regs[4] = 0xffffffff; 389075d047eSYoshinori Sato } else { 390075d047eSYoshinori Sato env->regs[6] = 0xffffffff; 391075d047eSYoshinori Sato env->regs[5] = 0x80000000; 392075d047eSYoshinori Sato env->regs[4] = 0x00000000; 393075d047eSYoshinori Sato } 394075d047eSYoshinori Sato } 395075d047eSYoshinori Sato } 396075d047eSYoshinori Sato 397075d047eSYoshinori Sato /* div */ 398075d047eSYoshinori Sato uint32_t helper_div(CPURXState *env, uint32_t num, uint32_t den) 399075d047eSYoshinori Sato { 400075d047eSYoshinori Sato uint32_t ret = num; 401075d047eSYoshinori Sato if (!((num == INT_MIN && den == -1) || den == 0)) { 402075d047eSYoshinori Sato ret = (int32_t)num / (int32_t)den; 403075d047eSYoshinori Sato env->psw_o = 0; 404075d047eSYoshinori Sato } else { 405075d047eSYoshinori Sato env->psw_o = -1; 406075d047eSYoshinori Sato } 407075d047eSYoshinori Sato return ret; 408075d047eSYoshinori Sato } 409075d047eSYoshinori Sato 410075d047eSYoshinori Sato uint32_t helper_divu(CPURXState *env, uint32_t num, uint32_t den) 411075d047eSYoshinori Sato { 412075d047eSYoshinori Sato uint32_t ret = num; 413075d047eSYoshinori Sato if (den != 0) { 414075d047eSYoshinori Sato ret = num / den; 415075d047eSYoshinori Sato env->psw_o = 0; 416075d047eSYoshinori Sato } else { 417075d047eSYoshinori Sato env->psw_o = -1; 418075d047eSYoshinori Sato } 419075d047eSYoshinori Sato return ret; 420075d047eSYoshinori Sato } 421075d047eSYoshinori Sato 422075d047eSYoshinori Sato /* exception */ 4238905770bSMarc-André Lureau static inline G_NORETURN 4248905770bSMarc-André Lureau void raise_exception(CPURXState *env, int index, 425075d047eSYoshinori Sato uintptr_t retaddr) 426075d047eSYoshinori Sato { 427075d047eSYoshinori Sato CPUState *cs = env_cpu(env); 428075d047eSYoshinori Sato 429075d047eSYoshinori Sato cs->exception_index = index; 430075d047eSYoshinori Sato cpu_loop_exit_restore(cs, retaddr); 431075d047eSYoshinori Sato } 432075d047eSYoshinori Sato 4338905770bSMarc-André Lureau G_NORETURN void helper_raise_privilege_violation(CPURXState *env) 434075d047eSYoshinori Sato { 435075d047eSYoshinori Sato raise_exception(env, 20, GETPC()); 436075d047eSYoshinori Sato } 437075d047eSYoshinori Sato 4388905770bSMarc-André Lureau G_NORETURN void helper_raise_access_fault(CPURXState *env) 439075d047eSYoshinori Sato { 440075d047eSYoshinori Sato raise_exception(env, 21, GETPC()); 441075d047eSYoshinori Sato } 442075d047eSYoshinori Sato 4438905770bSMarc-André Lureau G_NORETURN void helper_raise_illegal_instruction(CPURXState *env) 444075d047eSYoshinori Sato { 445075d047eSYoshinori Sato raise_exception(env, 23, GETPC()); 446075d047eSYoshinori Sato } 447075d047eSYoshinori Sato 4488905770bSMarc-André Lureau G_NORETURN void helper_wait(CPURXState *env) 449075d047eSYoshinori Sato { 450075d047eSYoshinori Sato CPUState *cs = env_cpu(env); 451075d047eSYoshinori Sato 452075d047eSYoshinori Sato cs->halted = 1; 453075d047eSYoshinori Sato env->in_sleep = 1; 454335cd065STomoaki Kawada env->psw_i = 1; 455075d047eSYoshinori Sato raise_exception(env, EXCP_HLT, 0); 456075d047eSYoshinori Sato } 457075d047eSYoshinori Sato 4588905770bSMarc-André Lureau G_NORETURN void helper_rxint(CPURXState *env, uint32_t vec) 459075d047eSYoshinori Sato { 460075d047eSYoshinori Sato raise_exception(env, 0x100 + vec, 0); 461075d047eSYoshinori Sato } 462075d047eSYoshinori Sato 4638905770bSMarc-André Lureau G_NORETURN void helper_rxbrk(CPURXState *env) 464075d047eSYoshinori Sato { 465075d047eSYoshinori Sato raise_exception(env, 0x100, 0); 466075d047eSYoshinori Sato } 467