SH4: Convert remaining non-fp ops 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 uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
167 {
168     uint32_t tmp0, tmp2;
169     uint8_t old_q, tmp1 = 0xff;
170
171     //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
172     old_q = Q;
173     if ((0x80000000 & arg1) != 0)
174         SETQ;
175     else
176         CLRQ;
177     tmp2 = arg0;
178     arg1 <<= 1;
179     arg1 |= T;
180     switch (old_q) {
181     case 0:
182         switch (M) {
183         case 0:
184             tmp0 = arg1;
185             arg1 -= tmp2;
186             tmp1 = arg1 > 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 = arg1;
204             arg1 += tmp2;
205             tmp1 = arg1 < 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 = arg1;
227             arg1 += tmp2;
228             tmp1 = arg1 < 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 = arg1;
246             arg1 -= tmp2;
247             tmp1 = arg1 > 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: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
271     return arg1;
272 }
273
274 void helper_macl(uint32_t arg0, uint32_t arg1)
275 {
276     int64_t res;
277
278     res = ((uint64_t) env->mach << 32) | env->macl;
279     res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
280     env->mach = (res >> 32) & 0xffffffff;
281     env->macl = res & 0xffffffff;
282     if (env->sr & SR_S) {
283         if (res < 0)
284             env->mach |= 0xffff0000;
285         else
286             env->mach &= 0x00007fff;
287     }
288 }
289
290 void helper_macw(uint32_t arg0, uint32_t arg1)
291 {
292     int64_t res;
293
294     res = ((uint64_t) env->mach << 32) | env->macl;
295     res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
296     env->mach = (res >> 32) & 0xffffffff;
297     env->macl = res & 0xffffffff;
298     if (env->sr & SR_S) {
299         if (res < -0x80000000) {
300             env->mach = 1;
301             env->macl = 0x80000000;
302         } else if (res > 0x000000007fffffff) {
303             env->mach = 1;
304             env->macl = 0x7fffffff;
305         }
306     }
307 }
308
309 uint32_t helper_negc(uint32_t arg)
310 {
311     uint32_t temp;
312
313     temp = -arg;
314     arg = temp - (env->sr & SR_T);
315     if (0 < temp)
316         env->sr |= SR_T;
317     else
318         env->sr &= ~SR_T;
319     if (temp < arg)
320         env->sr |= SR_T;
321     return arg;
322 }
323
324 uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
325 {
326     uint32_t tmp0, tmp1;
327
328     tmp1 = arg1 - arg0;
329     tmp0 = arg1;
330     arg1 = tmp1 - (env->sr & SR_T);
331     if (tmp0 < tmp1)
332         env->sr |= SR_T;
333     else
334         env->sr &= ~SR_T;
335     if (tmp1 < arg1)
336         env->sr |= SR_T;
337     return arg1;
338 }
339
340 uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
341 {
342     int32_t dest, src, ans;
343
344     if ((int32_t) arg1 >= 0)
345         dest = 0;
346     else
347         dest = 1;
348     if ((int32_t) arg0 >= 0)
349         src = 0;
350     else
351         src = 1;
352     src += dest;
353     arg1 -= arg0;
354     if ((int32_t) arg1 >= 0)
355         ans = 0;
356     else
357         ans = 1;
358     ans += dest;
359     if (src == 1) {
360         if (ans == 1)
361             env->sr |= SR_T;
362         else
363             env->sr &= ~SR_T;
364     } else
365         env->sr &= ~SR_T;
366     return arg1;
367 }
368
369 void helper_ld_fpscr(uint32_t val)
370 {
371     env->fpscr = val & 0x003fffff;
372     if (val & 0x01)
373         set_float_rounding_mode(float_round_to_zero, &env->fp_status);
374     else
375         set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
376 }