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" 26075d047eSYoshinori Sato 27*8905770bSMarc-André Lureau static inline G_NORETURN 28*8905770bSMarc-André Lureau void raise_exception(CPURXState *env, int index, 29075d047eSYoshinori Sato uintptr_t retaddr); 30075d047eSYoshinori Sato 31075d047eSYoshinori Sato static void _set_psw(CPURXState *env, uint32_t psw, uint32_t rte) 32075d047eSYoshinori Sato { 33075d047eSYoshinori Sato uint32_t prev_u; 34075d047eSYoshinori Sato prev_u = env->psw_u; 35075d047eSYoshinori Sato rx_cpu_unpack_psw(env, psw, rte); 36075d047eSYoshinori Sato if (prev_u != env->psw_u) { 37075d047eSYoshinori Sato /* switch r0 */ 38075d047eSYoshinori Sato if (env->psw_u) { 39075d047eSYoshinori Sato env->isp = env->regs[0]; 40075d047eSYoshinori Sato env->regs[0] = env->usp; 41075d047eSYoshinori Sato } else { 42075d047eSYoshinori Sato env->usp = env->regs[0]; 43075d047eSYoshinori Sato env->regs[0] = env->isp; 44075d047eSYoshinori Sato } 45075d047eSYoshinori Sato } 46075d047eSYoshinori Sato } 47075d047eSYoshinori Sato 48075d047eSYoshinori Sato void helper_set_psw(CPURXState *env, uint32_t psw) 49075d047eSYoshinori Sato { 50075d047eSYoshinori Sato _set_psw(env, psw, 0); 51075d047eSYoshinori Sato } 52075d047eSYoshinori Sato 53075d047eSYoshinori Sato void helper_set_psw_rte(CPURXState *env, uint32_t psw) 54075d047eSYoshinori Sato { 55075d047eSYoshinori Sato _set_psw(env, psw, 1); 56075d047eSYoshinori Sato } 57075d047eSYoshinori Sato 58075d047eSYoshinori Sato uint32_t helper_pack_psw(CPURXState *env) 59075d047eSYoshinori Sato { 60075d047eSYoshinori Sato return rx_cpu_pack_psw(env); 61075d047eSYoshinori Sato } 62075d047eSYoshinori Sato 63075d047eSYoshinori Sato #define SET_FPSW(b) \ 64075d047eSYoshinori Sato do { \ 65075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, C ## b, 1); \ 66075d047eSYoshinori Sato if (!FIELD_EX32(env->fpsw, FPSW, E ## b)) { \ 67075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, F ## b, 1); \ 68075d047eSYoshinori Sato } \ 69075d047eSYoshinori Sato } while (0) 70075d047eSYoshinori Sato 71075d047eSYoshinori Sato /* fp operations */ 72075d047eSYoshinori Sato static void update_fpsw(CPURXState *env, float32 ret, uintptr_t retaddr) 73075d047eSYoshinori Sato { 74075d047eSYoshinori Sato int xcpt, cause, enable; 75075d047eSYoshinori Sato 76075d047eSYoshinori Sato env->psw_z = ret & ~(1 << 31); /* mask sign bit */ 77075d047eSYoshinori Sato env->psw_s = ret; 78075d047eSYoshinori Sato 79075d047eSYoshinori Sato xcpt = get_float_exception_flags(&env->fp_status); 80075d047eSYoshinori Sato 81075d047eSYoshinori Sato /* Clear the cause entries */ 82075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, CAUSE, 0); 83075d047eSYoshinori Sato 84075d047eSYoshinori Sato /* set FPSW */ 85075d047eSYoshinori Sato if (unlikely(xcpt)) { 86075d047eSYoshinori Sato if (xcpt & float_flag_invalid) { 87075d047eSYoshinori Sato SET_FPSW(V); 88075d047eSYoshinori Sato } 89075d047eSYoshinori Sato if (xcpt & float_flag_divbyzero) { 90075d047eSYoshinori Sato SET_FPSW(Z); 91075d047eSYoshinori Sato } 92075d047eSYoshinori Sato if (xcpt & float_flag_overflow) { 93075d047eSYoshinori Sato SET_FPSW(O); 94075d047eSYoshinori Sato } 95075d047eSYoshinori Sato if (xcpt & float_flag_underflow) { 96075d047eSYoshinori Sato SET_FPSW(U); 97075d047eSYoshinori Sato } 98075d047eSYoshinori Sato if (xcpt & float_flag_inexact) { 99075d047eSYoshinori Sato SET_FPSW(X); 100075d047eSYoshinori Sato } 101075d047eSYoshinori Sato if ((xcpt & (float_flag_input_denormal 102075d047eSYoshinori Sato | float_flag_output_denormal)) 103075d047eSYoshinori Sato && !FIELD_EX32(env->fpsw, FPSW, DN)) { 104075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, CE, 1); 105075d047eSYoshinori Sato } 106075d047eSYoshinori Sato 107075d047eSYoshinori Sato /* update FPSW_FLAG_S */ 108075d047eSYoshinori Sato if (FIELD_EX32(env->fpsw, FPSW, FLAGS) != 0) { 109075d047eSYoshinori Sato env->fpsw = FIELD_DP32(env->fpsw, FPSW, FS, 1); 110075d047eSYoshinori Sato } 111075d047eSYoshinori Sato 112075d047eSYoshinori Sato /* Generate an exception if enabled */ 113075d047eSYoshinori Sato cause = FIELD_EX32(env->fpsw, FPSW, CAUSE); 114075d047eSYoshinori Sato enable = FIELD_EX32(env->fpsw, FPSW, ENABLE); 115075d047eSYoshinori Sato enable |= 1 << 5; /* CE always enabled */ 116075d047eSYoshinori Sato if (cause & enable) { 117075d047eSYoshinori Sato raise_exception(env, 21, retaddr); 118075d047eSYoshinori Sato } 119075d047eSYoshinori Sato } 120075d047eSYoshinori Sato } 121075d047eSYoshinori Sato 122075d047eSYoshinori Sato void helper_set_fpsw(CPURXState *env, uint32_t val) 123075d047eSYoshinori Sato { 124075d047eSYoshinori Sato static const int roundmode[] = { 125075d047eSYoshinori Sato float_round_nearest_even, 126075d047eSYoshinori Sato float_round_to_zero, 127075d047eSYoshinori Sato float_round_up, 128075d047eSYoshinori Sato float_round_down, 129075d047eSYoshinori Sato }; 130075d047eSYoshinori Sato uint32_t fpsw = env->fpsw; 131075d047eSYoshinori Sato fpsw |= 0x7fffff03; 132075d047eSYoshinori Sato val &= ~0x80000000; 133075d047eSYoshinori Sato fpsw &= val; 134075d047eSYoshinori Sato FIELD_DP32(fpsw, FPSW, FS, FIELD_EX32(fpsw, FPSW, FLAGS) != 0); 135075d047eSYoshinori Sato env->fpsw = fpsw; 136075d047eSYoshinori Sato set_float_rounding_mode(roundmode[FIELD_EX32(env->fpsw, FPSW, RM)], 137075d047eSYoshinori Sato &env->fp_status); 138075d047eSYoshinori Sato } 139075d047eSYoshinori Sato 140075d047eSYoshinori Sato #define FLOATOP(op, func) \ 141075d047eSYoshinori Sato float32 helper_##op(CPURXState *env, float32 t0, float32 t1) \ 142075d047eSYoshinori Sato { \ 143075d047eSYoshinori Sato float32 ret; \ 144075d047eSYoshinori Sato ret = func(t0, t1, &env->fp_status); \ 145075d047eSYoshinori Sato update_fpsw(env, *(uint32_t *)&ret, GETPC()); \ 146075d047eSYoshinori Sato return ret; \ 147075d047eSYoshinori Sato } 148075d047eSYoshinori Sato 149075d047eSYoshinori Sato FLOATOP(fadd, float32_add) 150075d047eSYoshinori Sato FLOATOP(fsub, float32_sub) 151075d047eSYoshinori Sato FLOATOP(fmul, float32_mul) 152075d047eSYoshinori Sato FLOATOP(fdiv, float32_div) 153075d047eSYoshinori Sato 154075d047eSYoshinori Sato void helper_fcmp(CPURXState *env, float32 t0, float32 t1) 155075d047eSYoshinori Sato { 156075d047eSYoshinori Sato int st; 157075d047eSYoshinori Sato st = float32_compare(t0, t1, &env->fp_status); 158075d047eSYoshinori Sato update_fpsw(env, 0, GETPC()); 159075d047eSYoshinori Sato env->psw_z = 1; 160075d047eSYoshinori Sato env->psw_s = env->psw_o = 0; 161075d047eSYoshinori Sato switch (st) { 162075d047eSYoshinori Sato case float_relation_equal: 163075d047eSYoshinori Sato env->psw_z = 0; 164075d047eSYoshinori Sato break; 165075d047eSYoshinori Sato case float_relation_less: 166075d047eSYoshinori Sato env->psw_s = -1; 167075d047eSYoshinori Sato break; 168075d047eSYoshinori Sato case float_relation_unordered: 169075d047eSYoshinori Sato env->psw_o = -1; 170075d047eSYoshinori Sato break; 171075d047eSYoshinori Sato } 172075d047eSYoshinori Sato } 173075d047eSYoshinori Sato 174075d047eSYoshinori Sato uint32_t helper_ftoi(CPURXState *env, float32 t0) 175075d047eSYoshinori Sato { 176075d047eSYoshinori Sato uint32_t ret; 177075d047eSYoshinori Sato ret = float32_to_int32_round_to_zero(t0, &env->fp_status); 178075d047eSYoshinori Sato update_fpsw(env, ret, GETPC()); 179075d047eSYoshinori Sato return ret; 180075d047eSYoshinori Sato } 181075d047eSYoshinori Sato 182075d047eSYoshinori Sato uint32_t helper_round(CPURXState *env, float32 t0) 183075d047eSYoshinori Sato { 184075d047eSYoshinori Sato uint32_t ret; 185075d047eSYoshinori Sato ret = float32_to_int32(t0, &env->fp_status); 186075d047eSYoshinori Sato update_fpsw(env, ret, GETPC()); 187075d047eSYoshinori Sato return ret; 188075d047eSYoshinori Sato } 189075d047eSYoshinori Sato 190075d047eSYoshinori Sato float32 helper_itof(CPURXState *env, uint32_t t0) 191075d047eSYoshinori Sato { 192075d047eSYoshinori Sato float32 ret; 193075d047eSYoshinori Sato ret = int32_to_float32(t0, &env->fp_status); 194075d047eSYoshinori Sato update_fpsw(env, ret, GETPC()); 195075d047eSYoshinori Sato return ret; 196075d047eSYoshinori Sato } 197075d047eSYoshinori Sato 198075d047eSYoshinori Sato /* string operations */ 199075d047eSYoshinori Sato void helper_scmpu(CPURXState *env) 200075d047eSYoshinori Sato { 201075d047eSYoshinori Sato uint8_t tmp0, tmp1; 202075d047eSYoshinori Sato if (env->regs[3] == 0) { 203075d047eSYoshinori Sato return; 204075d047eSYoshinori Sato } 20577182df1SStefan Weil do { 206075d047eSYoshinori Sato tmp0 = cpu_ldub_data_ra(env, env->regs[1]++, GETPC()); 207075d047eSYoshinori Sato tmp1 = cpu_ldub_data_ra(env, env->regs[2]++, GETPC()); 208075d047eSYoshinori Sato env->regs[3]--; 209075d047eSYoshinori Sato if (tmp0 != tmp1 || tmp0 == '\0') { 210075d047eSYoshinori Sato break; 211075d047eSYoshinori Sato } 21277182df1SStefan Weil } while (env->regs[3] != 0); 213075d047eSYoshinori Sato env->psw_z = tmp0 - tmp1; 214075d047eSYoshinori Sato env->psw_c = (tmp0 >= tmp1); 215075d047eSYoshinori Sato } 216075d047eSYoshinori Sato 217075d047eSYoshinori Sato static uint32_t (* const cpu_ldufn[])(CPUArchState *env, 218075d047eSYoshinori Sato target_ulong ptr, 219075d047eSYoshinori Sato uintptr_t retaddr) = { 220075d047eSYoshinori Sato cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra, 221075d047eSYoshinori Sato }; 222075d047eSYoshinori Sato 223075d047eSYoshinori Sato static uint32_t (* const cpu_ldfn[])(CPUArchState *env, 224075d047eSYoshinori Sato target_ulong ptr, 225075d047eSYoshinori Sato uintptr_t retaddr) = { 226075d047eSYoshinori Sato cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra, 227075d047eSYoshinori Sato }; 228075d047eSYoshinori Sato 229075d047eSYoshinori Sato static void (* const cpu_stfn[])(CPUArchState *env, 230075d047eSYoshinori Sato target_ulong ptr, 231075d047eSYoshinori Sato uint32_t val, 232075d047eSYoshinori Sato uintptr_t retaddr) = { 233075d047eSYoshinori Sato cpu_stb_data_ra, cpu_stw_data_ra, cpu_stl_data_ra, 234075d047eSYoshinori Sato }; 235075d047eSYoshinori Sato 236075d047eSYoshinori Sato void helper_sstr(CPURXState *env, uint32_t sz) 237075d047eSYoshinori Sato { 238075d047eSYoshinori Sato tcg_debug_assert(sz < 3); 239075d047eSYoshinori Sato while (env->regs[3] != 0) { 240075d047eSYoshinori Sato cpu_stfn[sz](env, env->regs[1], env->regs[2], GETPC()); 241075d047eSYoshinori Sato env->regs[1] += 1 << sz; 242075d047eSYoshinori Sato env->regs[3]--; 243075d047eSYoshinori Sato } 244075d047eSYoshinori Sato } 245075d047eSYoshinori Sato 246075d047eSYoshinori Sato #define OP_SMOVU 1 247075d047eSYoshinori Sato #define OP_SMOVF 0 248075d047eSYoshinori Sato #define OP_SMOVB 2 249075d047eSYoshinori Sato 250075d047eSYoshinori Sato static void smov(uint32_t mode, CPURXState *env) 251075d047eSYoshinori Sato { 252075d047eSYoshinori Sato uint8_t tmp; 253075d047eSYoshinori Sato int dir; 254075d047eSYoshinori Sato 255075d047eSYoshinori Sato dir = (mode & OP_SMOVB) ? -1 : 1; 256075d047eSYoshinori Sato while (env->regs[3] != 0) { 257075d047eSYoshinori Sato tmp = cpu_ldub_data_ra(env, env->regs[2], GETPC()); 258075d047eSYoshinori Sato cpu_stb_data_ra(env, env->regs[1], tmp, GETPC()); 259075d047eSYoshinori Sato env->regs[1] += dir; 260075d047eSYoshinori Sato env->regs[2] += dir; 261075d047eSYoshinori Sato env->regs[3]--; 262075d047eSYoshinori Sato if ((mode & OP_SMOVU) && tmp == 0) { 263075d047eSYoshinori Sato break; 264075d047eSYoshinori Sato } 265075d047eSYoshinori Sato } 266075d047eSYoshinori Sato } 267075d047eSYoshinori Sato 268075d047eSYoshinori Sato void helper_smovu(CPURXState *env) 269075d047eSYoshinori Sato { 270075d047eSYoshinori Sato smov(OP_SMOVU, env); 271075d047eSYoshinori Sato } 272075d047eSYoshinori Sato 273075d047eSYoshinori Sato void helper_smovf(CPURXState *env) 274075d047eSYoshinori Sato { 275075d047eSYoshinori Sato smov(OP_SMOVF, env); 276075d047eSYoshinori Sato } 277075d047eSYoshinori Sato 278075d047eSYoshinori Sato void helper_smovb(CPURXState *env) 279075d047eSYoshinori Sato { 280075d047eSYoshinori Sato smov(OP_SMOVB, env); 281075d047eSYoshinori Sato } 282075d047eSYoshinori Sato 283075d047eSYoshinori Sato 284075d047eSYoshinori Sato void helper_suntil(CPURXState *env, uint32_t sz) 285075d047eSYoshinori Sato { 286075d047eSYoshinori Sato uint32_t tmp; 287075d047eSYoshinori Sato tcg_debug_assert(sz < 3); 288075d047eSYoshinori Sato if (env->regs[3] == 0) { 289075d047eSYoshinori Sato return ; 290075d047eSYoshinori Sato } 29177182df1SStefan Weil do { 292075d047eSYoshinori Sato tmp = cpu_ldufn[sz](env, env->regs[1], GETPC()); 293075d047eSYoshinori Sato env->regs[1] += 1 << sz; 294075d047eSYoshinori Sato env->regs[3]--; 295075d047eSYoshinori Sato if (tmp == env->regs[2]) { 296075d047eSYoshinori Sato break; 297075d047eSYoshinori Sato } 29877182df1SStefan Weil } while (env->regs[3] != 0); 299075d047eSYoshinori Sato env->psw_z = tmp - env->regs[2]; 300075d047eSYoshinori Sato env->psw_c = (tmp <= env->regs[2]); 301075d047eSYoshinori Sato } 302075d047eSYoshinori Sato 303075d047eSYoshinori Sato void helper_swhile(CPURXState *env, uint32_t sz) 304075d047eSYoshinori Sato { 305075d047eSYoshinori Sato uint32_t tmp; 306075d047eSYoshinori Sato tcg_debug_assert(sz < 3); 307075d047eSYoshinori Sato if (env->regs[3] == 0) { 308075d047eSYoshinori Sato return ; 309075d047eSYoshinori Sato } 31077182df1SStefan Weil do { 311075d047eSYoshinori Sato tmp = cpu_ldufn[sz](env, env->regs[1], GETPC()); 312075d047eSYoshinori Sato env->regs[1] += 1 << sz; 313075d047eSYoshinori Sato env->regs[3]--; 314075d047eSYoshinori Sato if (tmp != env->regs[2]) { 315075d047eSYoshinori Sato break; 316075d047eSYoshinori Sato } 31777182df1SStefan Weil } while (env->regs[3] != 0); 318075d047eSYoshinori Sato env->psw_z = env->regs[3]; 319075d047eSYoshinori Sato env->psw_c = (tmp <= env->regs[2]); 320075d047eSYoshinori Sato } 321075d047eSYoshinori Sato 32297841438SLichang Zhao /* accumulator operations */ 323075d047eSYoshinori Sato void helper_rmpa(CPURXState *env, uint32_t sz) 324075d047eSYoshinori Sato { 325075d047eSYoshinori Sato uint64_t result_l, prev; 326075d047eSYoshinori Sato int32_t result_h; 327075d047eSYoshinori Sato int64_t tmp0, tmp1; 328075d047eSYoshinori Sato 329075d047eSYoshinori Sato if (env->regs[3] == 0) { 330075d047eSYoshinori Sato return; 331075d047eSYoshinori Sato } 332075d047eSYoshinori Sato result_l = env->regs[5]; 333075d047eSYoshinori Sato result_l <<= 32; 334075d047eSYoshinori Sato result_l |= env->regs[4]; 335075d047eSYoshinori Sato result_h = env->regs[6]; 336075d047eSYoshinori Sato env->psw_o = 0; 337075d047eSYoshinori Sato 338075d047eSYoshinori Sato while (env->regs[3] != 0) { 339075d047eSYoshinori Sato tmp0 = cpu_ldfn[sz](env, env->regs[1], GETPC()); 340075d047eSYoshinori Sato tmp1 = cpu_ldfn[sz](env, env->regs[2], GETPC()); 341075d047eSYoshinori Sato tmp0 *= tmp1; 342075d047eSYoshinori Sato prev = result_l; 343075d047eSYoshinori Sato result_l += tmp0; 344075d047eSYoshinori Sato /* carry / bollow */ 345075d047eSYoshinori Sato if (tmp0 < 0) { 346075d047eSYoshinori Sato if (prev > result_l) { 347075d047eSYoshinori Sato result_h--; 348075d047eSYoshinori Sato } 349075d047eSYoshinori Sato } else { 350075d047eSYoshinori Sato if (prev < result_l) { 351075d047eSYoshinori Sato result_h++; 352075d047eSYoshinori Sato } 353075d047eSYoshinori Sato } 354075d047eSYoshinori Sato 355075d047eSYoshinori Sato env->regs[1] += 1 << sz; 356075d047eSYoshinori Sato env->regs[2] += 1 << sz; 357075d047eSYoshinori Sato } 358075d047eSYoshinori Sato env->psw_s = result_h; 359075d047eSYoshinori Sato env->psw_o = (result_h != 0 && result_h != -1) << 31; 360075d047eSYoshinori Sato env->regs[6] = result_h; 361075d047eSYoshinori Sato env->regs[5] = result_l >> 32; 362075d047eSYoshinori Sato env->regs[4] = result_l & 0xffffffff; 363075d047eSYoshinori Sato } 364075d047eSYoshinori Sato 365075d047eSYoshinori Sato void helper_racw(CPURXState *env, uint32_t imm) 366075d047eSYoshinori Sato { 367075d047eSYoshinori Sato int64_t acc; 368075d047eSYoshinori Sato acc = env->acc; 369075d047eSYoshinori Sato acc <<= (imm + 1); 370075d047eSYoshinori Sato acc += 0x0000000080000000LL; 371075d047eSYoshinori Sato if (acc > 0x00007fff00000000LL) { 372075d047eSYoshinori Sato acc = 0x00007fff00000000LL; 373075d047eSYoshinori Sato } else if (acc < -0x800000000000LL) { 374075d047eSYoshinori Sato acc = -0x800000000000LL; 375075d047eSYoshinori Sato } else { 376075d047eSYoshinori Sato acc &= 0xffffffff00000000LL; 377075d047eSYoshinori Sato } 378075d047eSYoshinori Sato env->acc = acc; 379075d047eSYoshinori Sato } 380075d047eSYoshinori Sato 381075d047eSYoshinori Sato void helper_satr(CPURXState *env) 382075d047eSYoshinori Sato { 383075d047eSYoshinori Sato if (env->psw_o >> 31) { 384075d047eSYoshinori Sato if ((int)env->psw_s < 0) { 385075d047eSYoshinori Sato env->regs[6] = 0x00000000; 386075d047eSYoshinori Sato env->regs[5] = 0x7fffffff; 387075d047eSYoshinori Sato env->regs[4] = 0xffffffff; 388075d047eSYoshinori Sato } else { 389075d047eSYoshinori Sato env->regs[6] = 0xffffffff; 390075d047eSYoshinori Sato env->regs[5] = 0x80000000; 391075d047eSYoshinori Sato env->regs[4] = 0x00000000; 392075d047eSYoshinori Sato } 393075d047eSYoshinori Sato } 394075d047eSYoshinori Sato } 395075d047eSYoshinori Sato 396075d047eSYoshinori Sato /* div */ 397075d047eSYoshinori Sato uint32_t helper_div(CPURXState *env, uint32_t num, uint32_t den) 398075d047eSYoshinori Sato { 399075d047eSYoshinori Sato uint32_t ret = num; 400075d047eSYoshinori Sato if (!((num == INT_MIN && den == -1) || den == 0)) { 401075d047eSYoshinori Sato ret = (int32_t)num / (int32_t)den; 402075d047eSYoshinori Sato env->psw_o = 0; 403075d047eSYoshinori Sato } else { 404075d047eSYoshinori Sato env->psw_o = -1; 405075d047eSYoshinori Sato } 406075d047eSYoshinori Sato return ret; 407075d047eSYoshinori Sato } 408075d047eSYoshinori Sato 409075d047eSYoshinori Sato uint32_t helper_divu(CPURXState *env, uint32_t num, uint32_t den) 410075d047eSYoshinori Sato { 411075d047eSYoshinori Sato uint32_t ret = num; 412075d047eSYoshinori Sato if (den != 0) { 413075d047eSYoshinori Sato ret = num / den; 414075d047eSYoshinori Sato env->psw_o = 0; 415075d047eSYoshinori Sato } else { 416075d047eSYoshinori Sato env->psw_o = -1; 417075d047eSYoshinori Sato } 418075d047eSYoshinori Sato return ret; 419075d047eSYoshinori Sato } 420075d047eSYoshinori Sato 421075d047eSYoshinori Sato /* exception */ 422*8905770bSMarc-André Lureau static inline G_NORETURN 423*8905770bSMarc-André Lureau void raise_exception(CPURXState *env, int index, 424075d047eSYoshinori Sato uintptr_t retaddr) 425075d047eSYoshinori Sato { 426075d047eSYoshinori Sato CPUState *cs = env_cpu(env); 427075d047eSYoshinori Sato 428075d047eSYoshinori Sato cs->exception_index = index; 429075d047eSYoshinori Sato cpu_loop_exit_restore(cs, retaddr); 430075d047eSYoshinori Sato } 431075d047eSYoshinori Sato 432*8905770bSMarc-André Lureau G_NORETURN void helper_raise_privilege_violation(CPURXState *env) 433075d047eSYoshinori Sato { 434075d047eSYoshinori Sato raise_exception(env, 20, GETPC()); 435075d047eSYoshinori Sato } 436075d047eSYoshinori Sato 437*8905770bSMarc-André Lureau G_NORETURN void helper_raise_access_fault(CPURXState *env) 438075d047eSYoshinori Sato { 439075d047eSYoshinori Sato raise_exception(env, 21, GETPC()); 440075d047eSYoshinori Sato } 441075d047eSYoshinori Sato 442*8905770bSMarc-André Lureau G_NORETURN void helper_raise_illegal_instruction(CPURXState *env) 443075d047eSYoshinori Sato { 444075d047eSYoshinori Sato raise_exception(env, 23, GETPC()); 445075d047eSYoshinori Sato } 446075d047eSYoshinori Sato 447*8905770bSMarc-André Lureau G_NORETURN void helper_wait(CPURXState *env) 448075d047eSYoshinori Sato { 449075d047eSYoshinori Sato CPUState *cs = env_cpu(env); 450075d047eSYoshinori Sato 451075d047eSYoshinori Sato cs->halted = 1; 452075d047eSYoshinori Sato env->in_sleep = 1; 453075d047eSYoshinori Sato raise_exception(env, EXCP_HLT, 0); 454075d047eSYoshinori Sato } 455075d047eSYoshinori Sato 456*8905770bSMarc-André Lureau G_NORETURN void helper_rxint(CPURXState *env, uint32_t vec) 457075d047eSYoshinori Sato { 458075d047eSYoshinori Sato raise_exception(env, 0x100 + vec, 0); 459075d047eSYoshinori Sato } 460075d047eSYoshinori Sato 461*8905770bSMarc-André Lureau G_NORETURN void helper_rxbrk(CPURXState *env) 462075d047eSYoshinori Sato { 463075d047eSYoshinori Sato raise_exception(env, 0x100, 0); 464075d047eSYoshinori Sato } 465