SH4: convert control/status register load/store to TCG
[qemu] / target-sh4 / op_helper.c
1 /*
2  *  SH4 emulation
3  *
4  *  Copyright (c) 2005 Samuel Tardieu
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <assert.h>
21 #include "exec.h"
22
23 #ifndef CONFIG_USER_ONLY
24
25 #define MMUSUFFIX _mmu
26
27 #define SHIFT 0
28 #include "softmmu_template.h"
29
30 #define SHIFT 1
31 #include "softmmu_template.h"
32
33 #define SHIFT 2
34 #include "softmmu_template.h"
35
36 #define SHIFT 3
37 #include "softmmu_template.h"
38
39 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
40 {
41     TranslationBlock *tb;
42     CPUState *saved_env;
43     unsigned long pc;
44     int ret;
45
46     /* XXX: hack to restore env in all cases, even if not called from
47        generated code */
48     saved_env = env;
49     env = cpu_single_env;
50     ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
51     if (ret) {
52         if (retaddr) {
53             /* now we have a real cpu fault */
54             pc = (unsigned long) retaddr;
55             tb = tb_find_pc(pc);
56             if (tb) {
57                 /* the PC is inside the translated code. It means that we have
58                    a virtual CPU fault */
59                 cpu_restore_state(tb, env, pc, NULL);
60             }
61         }
62         cpu_loop_exit();
63     }
64     env = saved_env;
65 }
66
67 #endif
68
69 void helper_ldtlb(void)
70 {
71 #ifdef CONFIG_USER_ONLY
72     /* XXXXX */
73     assert(0);
74 #else
75     cpu_load_tlb(env);
76 #endif
77 }
78
79 void helper_raise_illegal_instruction(void)
80 {
81     env->exception_index = 0x180;
82     cpu_loop_exit();
83 }
84
85 void helper_raise_slot_illegal_instruction(void)
86 {
87     env->exception_index = 0x1a0;
88     cpu_loop_exit();
89 }
90
91 void helper_debug(void)
92 {
93     env->exception_index = EXCP_DEBUG;
94     cpu_loop_exit();
95 }
96
97 void helper_sleep(void)
98 {
99     env->halted = 1;
100     env->exception_index = EXCP_HLT;
101     cpu_loop_exit();
102 }
103
104 void helper_trapa(uint32_t tra)
105 {
106     env->tra = tra << 2;
107     env->exception_index = 0x160;
108     cpu_loop_exit();
109 }
110
111 uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
112 {
113     uint32_t tmp0, tmp1;
114
115     tmp1 = arg0 + arg1;
116     tmp0 = arg1;
117     arg1 = tmp1 + (env->sr & 1);
118     if (tmp0 > tmp1)
119         env->sr |= SR_T;
120     else
121         env->sr &= ~SR_T;
122     if (tmp1 > arg1)
123         env->sr |= SR_T;
124     return arg1;
125 }
126
127 uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
128 {
129     uint32_t dest, src, ans;
130
131     if ((int32_t) arg1 >= 0)
132         dest = 0;
133     else
134         dest = 1;
135     if ((int32_t) arg0 >= 0)
136         src = 0;
137     else
138         src = 1;
139     src += dest;
140     arg1 += arg0;
141     if ((int32_t) arg1 >= 0)
142         ans = 0;
143     else
144         ans = 1;
145     ans += dest;
146     if (src == 0 || src == 2) {
147         if (ans == 1)
148             env->sr |= SR_T;
149         else
150             env->sr &= ~SR_T;
151     } else
152         env->sr &= ~SR_T;
153     return arg1;
154 }
155
156 #define T (env->sr & SR_T)
157 #define Q (env->sr & SR_Q ? 1 : 0)
158 #define M (env->sr & SR_M ? 1 : 0)
159 #define SETT env->sr |= SR_T
160 #define CLRT env->sr &= ~SR_T
161 #define SETQ env->sr |= SR_Q
162 #define CLRQ env->sr &= ~SR_Q
163 #define SETM env->sr |= SR_M
164 #define CLRM env->sr &= ~SR_M
165
166 void helper_div1_T0_T1(void)
167 {
168     uint32_t tmp0, tmp2;
169     uint8_t old_q, tmp1 = 0xff;
170
171     //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
172     old_q = Q;
173     if ((0x80000000 & T1) != 0)
174         SETQ;
175     else
176         CLRQ;
177     tmp2 = T0;
178     T1 <<= 1;
179     T1 |= T;
180     switch (old_q) {
181     case 0:
182         switch (M) {
183         case 0:
184             tmp0 = T1;
185             T1 -= tmp2;
186             tmp1 = T1 > tmp0;
187             switch (Q) {
188             case 0:
189                 if (tmp1)
190                     SETQ;
191                 else
192                     CLRQ;
193                 break;
194             case 1:
195                 if (tmp1 == 0)
196                     SETQ;
197                 else
198                     CLRQ;
199                 break;
200             }
201             break;
202         case 1:
203             tmp0 = T1;
204             T1 += tmp2;
205             tmp1 = T1 < tmp0;
206             switch (Q) {
207             case 0:
208                 if (tmp1 == 0)
209                     SETQ;
210                 else
211                     CLRQ;
212                 break;
213             case 1:
214                 if (tmp1)
215                     SETQ;
216                 else
217                     CLRQ;
218                 break;
219             }
220             break;
221         }
222         break;
223     case 1:
224         switch (M) {
225         case 0:
226             tmp0 = T1;
227             T1 += tmp2;
228             tmp1 = T1 < tmp0;
229             switch (Q) {
230             case 0:
231                 if (tmp1)
232                     SETQ;
233                 else
234                     CLRQ;
235                 break;
236             case 1:
237                 if (tmp1 == 0)
238                     SETQ;
239                 else
240                     CLRQ;
241                 break;
242             }
243             break;
244         case 1:
245             tmp0 = T1;
246             T1 -= tmp2;
247             tmp1 = T1 > tmp0;
248             switch (Q) {
249             case 0:
250                 if (tmp1 == 0)
251                     SETQ;
252                 else
253                     CLRQ;
254                 break;
255             case 1:
256                 if (tmp1)
257                     SETQ;
258                 else
259                     CLRQ;
260                 break;
261             }
262             break;
263         }
264         break;
265     }
266     if (Q == M)
267         SETT;
268     else
269         CLRT;
270     //printf("Output: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
271 }
272
273 void helper_macl(uint32_t arg0, uint32_t arg1)
274 {
275     int64_t res;
276
277     res = ((uint64_t) env->mach << 32) | env->macl;
278     res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
279     env->mach = (res >> 32) & 0xffffffff;
280     env->macl = res & 0xffffffff;
281     if (env->sr & SR_S) {
282         if (res < 0)
283             env->mach |= 0xffff0000;
284         else
285             env->mach &= 0x00007fff;
286     }
287 }
288
289 void helper_macw(uint32_t arg0, uint32_t arg1)
290 {
291     int64_t res;
292
293     res = ((uint64_t) env->mach << 32) | env->macl;
294     res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
295     env->mach = (res >> 32) & 0xffffffff;
296     env->macl = res & 0xffffffff;
297     if (env->sr & SR_S) {
298         if (res < -0x80000000) {
299             env->mach = 1;
300             env->macl = 0x80000000;
301         } else if (res > 0x000000007fffffff) {
302             env->mach = 1;
303             env->macl = 0x7fffffff;
304         }
305     }
306 }
307
308 uint32_t helper_negc(uint32_t arg)
309 {
310     uint32_t temp;
311
312     temp = -arg;
313     arg = temp - (env->sr & SR_T);
314     if (0 < temp)
315         env->sr |= SR_T;
316     else
317         env->sr &= ~SR_T;
318     if (temp < arg)
319         env->sr |= SR_T;
320     return arg;
321 }
322
323 uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
324 {
325     uint32_t tmp0, tmp1;
326
327     tmp1 = arg1 - arg0;
328     tmp0 = arg1;
329     arg1 = tmp1 - (env->sr & SR_T);
330     if (tmp0 < tmp1)
331         env->sr |= SR_T;
332     else
333         env->sr &= ~SR_T;
334     if (tmp1 < arg1)
335         env->sr |= SR_T;
336     return arg1;
337 }
338
339 uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
340 {
341     int32_t dest, src, ans;
342
343     if ((int32_t) arg1 >= 0)
344         dest = 0;
345     else
346         dest = 1;
347     if ((int32_t) arg0 >= 0)
348         src = 0;
349     else
350         src = 1;
351     src += dest;
352     arg1 -= arg0;
353     if ((int32_t) arg1 >= 0)
354         ans = 0;
355     else
356         ans = 1;
357     ans += dest;
358     if (src == 1) {
359         if (ans == 1)
360             env->sr |= SR_T;
361         else
362             env->sr &= ~SR_T;
363     } else
364         env->sr &= ~SR_T;
365     return arg1;
366 }
367
368 void helper_rotcl(uint32_t * addr)
369 {
370     uint32_t new;
371
372     new = (*addr << 1) | (env->sr & SR_T);
373     if (*addr & 0x80000000)
374         env->sr |= SR_T;
375     else
376         env->sr &= ~SR_T;
377     *addr = new;
378 }
379
380 void helper_rotcr(uint32_t * addr)
381 {
382     uint32_t new;
383
384     new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
385     if (*addr & 1)
386         env->sr |= SR_T;
387     else
388         env->sr &= ~SR_T;
389     *addr = new;
390 }
391
392 void helper_ld_fpscr(uint32_t val)
393 {
394     env->fpscr = val & 0x003fffff;
395     if (val & 0x01)
396         set_float_rounding_mode(float_round_to_zero, &env->fp_status);
397     else
398         set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
399 }