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