xref: /qemu/target/rx/op_helper.c (revision 7cef6d686309e2792186504ae17cf4f3eb57ef68)
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/helper-proto.h"
23*42fa9665SPhilippe Mathieu-Daudé #include "accel/tcg/cpu-ldst.h"
24075d047eSYoshinori Sato #include "fpu/softfloat.h"
25fafe0021SRichard Henderson #include "tcg/debug-assert.h"
26075d047eSYoshinori Sato 
278905770bSMarc-André Lureau static inline G_NORETURN
288905770bSMarc-André Lureau void raise_exception(CPURXState *env, int index,
29075d047eSYoshinori Sato                      uintptr_t retaddr);
30075d047eSYoshinori Sato 
_set_psw(CPURXState * env,uint32_t psw,uint32_t rte)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 
helper_set_psw(CPURXState * env,uint32_t psw)48075d047eSYoshinori Sato void helper_set_psw(CPURXState *env, uint32_t psw)
49075d047eSYoshinori Sato {
50075d047eSYoshinori Sato     _set_psw(env, psw, 0);
51075d047eSYoshinori Sato }
52075d047eSYoshinori Sato 
helper_set_psw_rte(CPURXState * env,uint32_t psw)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 
helper_pack_psw(CPURXState * env)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 */
update_fpsw(CPURXState * env,float32 ret,uintptr_t retaddr)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         }
101584b7aecSPeter Maydell         if ((xcpt & (float_flag_input_denormal_flushed
1027af64d10SPeter Maydell                      | float_flag_output_denormal_flushed))
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 
helper_set_fpsw(CPURXState * env,uint32_t val)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 
FLOATOP(fadd,float32_add)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 
helper_ftoi(CPURXState * env,float32 t0)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 
helper_round(CPURXState * env,float32 t0)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 
helper_itof(CPURXState * env,uint32_t t0)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 */
helper_scmpu(CPURXState * env)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,
218022b9bceSAnton Johansson                                      abi_ptr 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,
224022b9bceSAnton Johansson                                      abi_ptr 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,
230022b9bceSAnton Johansson                                  abi_ptr 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 
helper_sstr(CPURXState * env,uint32_t sz)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 
smov(uint32_t mode,CPURXState * env)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 
helper_smovu(CPURXState * env)268075d047eSYoshinori Sato void helper_smovu(CPURXState *env)
269075d047eSYoshinori Sato {
270075d047eSYoshinori Sato     smov(OP_SMOVU, env);
271075d047eSYoshinori Sato }
272075d047eSYoshinori Sato 
helper_smovf(CPURXState * env)273075d047eSYoshinori Sato void helper_smovf(CPURXState *env)
274075d047eSYoshinori Sato {
275075d047eSYoshinori Sato     smov(OP_SMOVF, env);
276075d047eSYoshinori Sato }
277075d047eSYoshinori Sato 
helper_smovb(CPURXState * env)278075d047eSYoshinori Sato void helper_smovb(CPURXState *env)
279075d047eSYoshinori Sato {
280075d047eSYoshinori Sato     smov(OP_SMOVB, env);
281075d047eSYoshinori Sato }
282075d047eSYoshinori Sato 
283075d047eSYoshinori Sato 
helper_suntil(CPURXState * env,uint32_t sz)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 
helper_swhile(CPURXState * env,uint32_t sz)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 */
helper_rmpa(CPURXState * env,uint32_t sz)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 
helper_racw(CPURXState * env,uint32_t imm)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 
helper_satr(CPURXState * env)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 */
helper_div(CPURXState * env,uint32_t num,uint32_t den)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 
helper_divu(CPURXState * env,uint32_t num,uint32_t den)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 */
4228905770bSMarc-André Lureau static inline G_NORETURN
raise_exception(CPURXState * env,int index,uintptr_t retaddr)4238905770bSMarc-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 
helper_raise_privilege_violation(CPURXState * env)4328905770bSMarc-André Lureau G_NORETURN void helper_raise_privilege_violation(CPURXState *env)
433075d047eSYoshinori Sato {
434075d047eSYoshinori Sato     raise_exception(env, 20, GETPC());
435075d047eSYoshinori Sato }
436075d047eSYoshinori Sato 
helper_raise_access_fault(CPURXState * env)4378905770bSMarc-André Lureau G_NORETURN void helper_raise_access_fault(CPURXState *env)
438075d047eSYoshinori Sato {
439075d047eSYoshinori Sato     raise_exception(env, 21, GETPC());
440075d047eSYoshinori Sato }
441075d047eSYoshinori Sato 
helper_raise_illegal_instruction(CPURXState * env)4428905770bSMarc-André Lureau G_NORETURN void helper_raise_illegal_instruction(CPURXState *env)
443075d047eSYoshinori Sato {
444075d047eSYoshinori Sato     raise_exception(env, 23, GETPC());
445075d047eSYoshinori Sato }
446075d047eSYoshinori Sato 
helper_wait(CPURXState * env)4478905770bSMarc-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;
453335cd065STomoaki Kawada     env->psw_i = 1;
454075d047eSYoshinori Sato     raise_exception(env, EXCP_HLT, 0);
455075d047eSYoshinori Sato }
456075d047eSYoshinori Sato 
helper_rxint(CPURXState * env,uint32_t vec)4578905770bSMarc-André Lureau G_NORETURN void helper_rxint(CPURXState *env, uint32_t vec)
458075d047eSYoshinori Sato {
459075d047eSYoshinori Sato     raise_exception(env, 0x100 + vec, 0);
460075d047eSYoshinori Sato }
461075d047eSYoshinori Sato 
helper_rxbrk(CPURXState * env)4628905770bSMarc-André Lureau G_NORETURN void helper_rxbrk(CPURXState *env)
463075d047eSYoshinori Sato {
464075d047eSYoshinori Sato     raise_exception(env, 0x100, 0);
465075d047eSYoshinori Sato }
466