Disk cache flush support.
[qemu/mini2440.git] / target-sh4 / op_helper.c
blob1c63fe587b424ac5c586c6eb49fe8a362389b59f
1 /*
2 * SH4 emulation
3 *
4 * Copyright (c) 2005 Samuel Tardieu
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.
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.
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
20 #include <assert.h>
21 #include "exec.h"
23 void cpu_loop_exit(void)
25 longjmp(env->jmp_env, 1);
28 void do_raise_exception(void)
30 cpu_loop_exit();
33 #ifndef CONFIG_USER_ONLY
35 #define MMUSUFFIX _mmu
36 #define GETPC() (__builtin_return_address(0))
38 #define SHIFT 0
39 #include "softmmu_template.h"
41 #define SHIFT 1
42 #include "softmmu_template.h"
44 #define SHIFT 2
45 #include "softmmu_template.h"
47 #define SHIFT 3
48 #include "softmmu_template.h"
50 void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
52 TranslationBlock *tb;
53 CPUState *saved_env;
54 unsigned long pc;
55 int ret;
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);
73 do_raise_exception();
75 env = saved_env;
78 #endif
80 void helper_addc_T0_T1(void)
82 uint32_t tmp0, tmp1;
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;
95 void helper_addv_T0_T1(void)
97 uint32_t dest, src, ans;
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;
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
133 void helper_div1_T0_T1(void)
135 uint32_t tmp0, tmp2;
136 uint8_t old_q, tmp1 = 0xff;
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;
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;
187 break;
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;
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;
229 break;
231 break;
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);
240 void helper_dmulsl_T0_T1()
242 int64_t res;
244 res = (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
245 env->mach = (res >> 32) & 0xffffffff;
246 env->macl = res & 0xffffffff;
249 void helper_dmulul_T0_T1()
251 uint64_t res;
253 res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1;
254 env->mach = (res >> 32) & 0xffffffff;
255 env->macl = res & 0xffffffff;
258 void helper_macl_T0_T1()
260 int64_t res;
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;
274 void helper_macw_T0_T1()
276 int64_t res;
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;
293 void helper_negc_T0()
295 uint32_t temp;
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;
307 void helper_subc_T0_T1()
309 uint32_t tmp0, tmp1;
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;
322 void helper_subv_T0_T1()
324 int32_t dest, src, ans;
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;
350 void helper_rotcl(uint32_t * addr)
352 uint32_t new;
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;
362 void helper_rotcr(uint32_t * addr)
364 uint32_t new;
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;