Add missing softfloat helpers.
[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 void cpu_loop_exit(void)
24 {
25     longjmp(env->jmp_env, 1);
26 }
27
28 void do_raise_exception(void)
29 {
30     cpu_loop_exit();
31 }
32
33 #ifndef CONFIG_USER_ONLY
34
35 #define MMUSUFFIX _mmu
36 #define GETPC() (__builtin_return_address(0))
37
38 #define SHIFT 0
39 #include "softmmu_template.h"
40
41 #define SHIFT 1
42 #include "softmmu_template.h"
43
44 #define SHIFT 2
45 #include "softmmu_template.h"
46
47 #define SHIFT 3
48 #include "softmmu_template.h"
49
50 void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
51 {
52     TranslationBlock *tb;
53     CPUState *saved_env;
54     unsigned long pc;
55     int ret;
56
57     /* XXX: hack to restore env in all cases, even if not called from
58        generated code */
59     saved_env = env;
60     env = cpu_single_env;
61     ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, is_user, 1);
62     if (ret) {
63         if (retaddr) {
64             /* now we have a real cpu fault */
65             pc = (unsigned long) retaddr;
66             tb = tb_find_pc(pc);
67             if (tb) {
68                 /* the PC is inside the translated code. It means that we have
69                    a virtual CPU fault */
70                 cpu_restore_state(tb, env, pc, NULL);
71             }
72         }
73         do_raise_exception();
74     }
75     env = saved_env;
76 }
77
78 #endif
79
80 void helper_addc_T0_T1(void)
81 {
82     uint32_t tmp0, tmp1;
83
84     tmp1 = T0 + T1;
85     tmp0 = T1;
86     T1 = tmp1 + (env->sr & 1);
87     if (tmp0 > tmp1)
88         env->sr |= SR_T;
89     else
90         env->sr &= ~SR_T;
91     if (tmp1 > T1)
92         env->sr |= SR_T;
93 }
94
95 void helper_addv_T0_T1(void)
96 {
97     uint32_t dest, src, ans;
98
99     if ((int32_t) T1 >= 0)
100         dest = 0;
101     else
102         dest = 1;
103     if ((int32_t) T0 >= 0)
104         src = 0;
105     else
106         src = 1;
107     src += dest;
108     T1 += T0;
109     if ((int32_t) T1 >= 0)
110         ans = 0;
111     else
112         ans = 1;
113     ans += dest;
114     if (src == 0 || src == 2) {
115         if (ans == 1)
116             env->sr |= SR_T;
117         else
118             env->sr &= ~SR_T;
119     } else
120         env->sr &= ~SR_T;
121 }
122
123 #define T (env->sr & SR_T)
124 #define Q (env->sr & SR_Q ? 1 : 0)
125 #define M (env->sr & SR_M ? 1 : 0)
126 #define SETT env->sr |= SR_T
127 #define CLRT env->sr &= ~SR_T
128 #define SETQ env->sr |= SR_Q
129 #define CLRQ env->sr &= ~SR_Q
130 #define SETM env->sr |= SR_M
131 #define CLRM env->sr &= ~SR_M
132
133 void helper_div1_T0_T1(void)
134 {
135     uint32_t tmp0, tmp2;
136     uint8_t old_q, tmp1 = 0xff;
137
138     //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
139     old_q = Q;
140     if ((0x80000000 & T1) != 0)
141         SETQ;
142     else
143         CLRQ;
144     tmp2 = T0;
145     T1 <<= 1;
146     T1 |= T;
147     switch (old_q) {
148     case 0:
149         switch (M) {
150         case 0:
151             tmp0 = T1;
152             T1 -= tmp2;
153             tmp1 = T1 > tmp0;
154             switch (Q) {
155             case 0:
156                 if (tmp1)
157                     SETQ;
158                 else
159                     CLRQ;
160                 break;
161             case 1:
162                 if (tmp1 == 0)
163                     SETQ;
164                 else
165                     CLRQ;
166                 break;
167             }
168             break;
169         case 1:
170             tmp0 = T1;
171             T1 += tmp2;
172             tmp1 = T1 < tmp0;
173             switch (Q) {
174             case 0:
175                 if (tmp1 == 0)
176                     SETQ;
177                 else
178                     CLRQ;
179                 break;
180             case 1:
181                 if (tmp1)
182                     SETQ;
183                 else
184                     CLRQ;
185                 break;
186             }
187             break;
188         }
189         break;
190     case 1:
191         switch (M) {
192         case 0:
193             tmp0 = T1;
194             T1 += tmp2;
195             tmp1 = T1 < tmp0;
196             switch (Q) {
197             case 0:
198                 if (tmp1)
199                     SETQ;
200                 else
201                     CLRQ;
202                 break;
203             case 1:
204                 if (tmp1 == 0)
205                     SETQ;
206                 else
207                     CLRQ;
208                 break;
209             }
210             break;
211         case 1:
212             tmp0 = T1;
213             T1 -= tmp2;
214             tmp1 = T1 > tmp0;
215             switch (Q) {
216             case 0:
217                 if (tmp1 == 0)
218                     SETQ;
219                 else
220                     CLRQ;
221                 break;
222             case 1:
223                 if (tmp1)
224                     SETQ;
225                 else
226                     CLRQ;
227                 break;
228             }
229             break;
230         }
231         break;
232     }
233     if (Q == M)
234         SETT;
235     else
236         CLRT;
237     //printf("Output: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
238 }
239
240 void helper_dmulsl_T0_T1()
241 {
242     int64_t res;
243
244     res = (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
245     env->mach = (res >> 32) & 0xffffffff;
246     env->macl = res & 0xffffffff;
247 }
248
249 void helper_dmulul_T0_T1()
250 {
251     uint64_t res;
252
253     res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1;
254     env->mach = (res >> 32) & 0xffffffff;
255     env->macl = res & 0xffffffff;
256 }
257
258 void helper_macl_T0_T1()
259 {
260     int64_t res;
261
262     res = ((uint64_t) env->mach << 32) | env->macl;
263     res += (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
264     env->mach = (res >> 32) & 0xffffffff;
265     env->macl = res & 0xffffffff;
266     if (env->sr & SR_S) {
267         if (res < 0)
268             env->mach |= 0xffff0000;
269         else
270             env->mach &= 0x00007fff;
271     }
272 }
273
274 void helper_macw_T0_T1()
275 {
276     int64_t res;
277
278     res = ((uint64_t) env->mach << 32) | env->macl;
279     res += (int64_t) (int16_t) T0 *(int64_t) (int16_t) T1;
280     env->mach = (res >> 32) & 0xffffffff;
281     env->macl = res & 0xffffffff;
282     if (env->sr & SR_S) {
283         if (res < -0x80000000) {
284             env->mach = 1;
285             env->macl = 0x80000000;
286         } else if (res > 0x000000007fffffff) {
287             env->mach = 1;
288             env->macl = 0x7fffffff;
289         }
290     }
291 }
292
293 void helper_negc_T0()
294 {
295     uint32_t temp;
296
297     temp = -T0;
298     T0 = temp - (env->sr & SR_T);
299     if (0 < temp)
300         env->sr |= SR_T;
301     else
302         env->sr &= ~SR_T;
303     if (temp < T0)
304         env->sr |= SR_T;
305 }
306
307 void helper_subc_T0_T1()
308 {
309     uint32_t tmp0, tmp1;
310
311     tmp1 = T1 - T0;
312     tmp0 = T1;
313     T1 = tmp1 - (env->sr & SR_T);
314     if (tmp0 < tmp1)
315         env->sr |= SR_T;
316     else
317         env->sr &= ~SR_T;
318     if (tmp1 < T1)
319         env->sr |= SR_T;
320 }
321
322 void helper_subv_T0_T1()
323 {
324     int32_t dest, src, ans;
325
326     if ((int32_t) T1 >= 0)
327         dest = 0;
328     else
329         dest = 1;
330     if ((int32_t) T0 >= 0)
331         src = 0;
332     else
333         src = 1;
334     src += dest;
335     T1 -= T0;
336     if ((int32_t) T1 >= 0)
337         ans = 0;
338     else
339         ans = 1;
340     ans += dest;
341     if (src == 1) {
342         if (ans == 1)
343             env->sr |= SR_T;
344         else
345             env->sr &= ~SR_T;
346     } else
347         env->sr &= ~SR_T;
348 }
349
350 void helper_rotcl(uint32_t * addr)
351 {
352     uint32_t new;
353
354     new = (*addr << 1) | (env->sr & SR_T);
355     if (*addr & 0x80000000)
356         env->sr |= SR_T;
357     else
358         env->sr &= ~SR_T;
359     *addr = new;
360 }
361
362 void helper_rotcr(uint32_t * addr)
363 {
364     uint32_t new;
365
366     new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
367     if (*addr & 1)
368         env->sr |= SR_T;
369     else
370         env->sr &= ~SR_T;
371     *addr = new;
372 }