xref: /openbmc/qemu/target/rx/op_helper.c (revision 022b9bce)
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 
_set_psw(CPURXState * env,uint32_t psw,uint32_t rte)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 
helper_set_psw(CPURXState * env,uint32_t psw)49075d047eSYoshinori Sato void helper_set_psw(CPURXState *env, uint32_t psw)
50075d047eSYoshinori Sato {
51075d047eSYoshinori Sato     _set_psw(env, psw, 0);
52075d047eSYoshinori Sato }
53075d047eSYoshinori Sato 
helper_set_psw_rte(CPURXState * env,uint32_t psw)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 
helper_pack_psw(CPURXState * env)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 */
update_fpsw(CPURXState * env,float32 ret,uintptr_t retaddr)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         }
102075d047eSYoshinori Sato         if ((xcpt & (float_flag_input_denormal
103075d047eSYoshinori Sato                      | float_flag_output_denormal))
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 
helper_set_fpsw(CPURXState * env,uint32_t val)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 
FLOATOP(fadd,float32_add)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 
helper_ftoi(CPURXState * env,float32 t0)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 
helper_round(CPURXState * env,float32 t0)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 
helper_itof(CPURXState * env,uint32_t t0)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 */
helper_scmpu(CPURXState * env)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,
219*022b9bceSAnton 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,
225*022b9bceSAnton 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,
231*022b9bceSAnton 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 
helper_sstr(CPURXState * env,uint32_t sz)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 
smov(uint32_t mode,CPURXState * env)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 
helper_smovu(CPURXState * env)269075d047eSYoshinori Sato void helper_smovu(CPURXState *env)
270075d047eSYoshinori Sato {
271075d047eSYoshinori Sato     smov(OP_SMOVU, env);
272075d047eSYoshinori Sato }
273075d047eSYoshinori Sato 
helper_smovf(CPURXState * env)274075d047eSYoshinori Sato void helper_smovf(CPURXState *env)
275075d047eSYoshinori Sato {
276075d047eSYoshinori Sato     smov(OP_SMOVF, env);
277075d047eSYoshinori Sato }
278075d047eSYoshinori Sato 
helper_smovb(CPURXState * env)279075d047eSYoshinori Sato void helper_smovb(CPURXState *env)
280075d047eSYoshinori Sato {
281075d047eSYoshinori Sato     smov(OP_SMOVB, env);
282075d047eSYoshinori Sato }
283075d047eSYoshinori Sato 
284075d047eSYoshinori Sato 
helper_suntil(CPURXState * env,uint32_t sz)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 
helper_swhile(CPURXState * env,uint32_t sz)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 */
helper_rmpa(CPURXState * env,uint32_t sz)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 
helper_racw(CPURXState * env,uint32_t imm)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 
helper_satr(CPURXState * env)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 */
helper_div(CPURXState * env,uint32_t num,uint32_t den)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 
helper_divu(CPURXState * env,uint32_t num,uint32_t den)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
raise_exception(CPURXState * env,int index,uintptr_t retaddr)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 
helper_raise_privilege_violation(CPURXState * env)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 
helper_raise_access_fault(CPURXState * env)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 
helper_raise_illegal_instruction(CPURXState * env)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 
helper_wait(CPURXState * env)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 
helper_rxint(CPURXState * env,uint32_t vec)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 
helper_rxbrk(CPURXState * env)4638905770bSMarc-André Lureau G_NORETURN void helper_rxbrk(CPURXState *env)
464075d047eSYoshinori Sato {
465075d047eSYoshinori Sato     raise_exception(env, 0x100, 0);
466075d047eSYoshinori Sato }
467