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