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