]> git.proxmox.com Git - qemu.git/blob - target-sh4/op_helper.c
SH4: convert some more arithmetics ops to TCG
[qemu.git] / 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 void helper_div1_T0_T1(void)
167 {
168 uint32_t tmp0, tmp2;
169 uint8_t old_q, tmp1 = 0xff;
170
171 //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
172 old_q = Q;
173 if ((0x80000000 & T1) != 0)
174 SETQ;
175 else
176 CLRQ;
177 tmp2 = T0;
178 T1 <<= 1;
179 T1 |= T;
180 switch (old_q) {
181 case 0:
182 switch (M) {
183 case 0:
184 tmp0 = T1;
185 T1 -= tmp2;
186 tmp1 = T1 > 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 = T1;
204 T1 += tmp2;
205 tmp1 = T1 < 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 = T1;
227 T1 += tmp2;
228 tmp1 = T1 < 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 = T1;
246 T1 -= tmp2;
247 tmp1 = T1 > 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: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
271 }
272
273 void helper_macl(uint32_t arg0, uint32_t arg1)
274 {
275 int64_t res;
276
277 res = ((uint64_t) env->mach << 32) | env->macl;
278 res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
279 env->mach = (res >> 32) & 0xffffffff;
280 env->macl = res & 0xffffffff;
281 if (env->sr & SR_S) {
282 if (res < 0)
283 env->mach |= 0xffff0000;
284 else
285 env->mach &= 0x00007fff;
286 }
287 }
288
289 void helper_macw(uint32_t arg0, uint32_t arg1)
290 {
291 int64_t res;
292
293 res = ((uint64_t) env->mach << 32) | env->macl;
294 res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
295 env->mach = (res >> 32) & 0xffffffff;
296 env->macl = res & 0xffffffff;
297 if (env->sr & SR_S) {
298 if (res < -0x80000000) {
299 env->mach = 1;
300 env->macl = 0x80000000;
301 } else if (res > 0x000000007fffffff) {
302 env->mach = 1;
303 env->macl = 0x7fffffff;
304 }
305 }
306 }
307
308 uint32_t helper_negc(uint32_t arg)
309 {
310 uint32_t temp;
311
312 temp = -arg;
313 arg = temp - (env->sr & SR_T);
314 if (0 < temp)
315 env->sr |= SR_T;
316 else
317 env->sr &= ~SR_T;
318 if (temp < arg)
319 env->sr |= SR_T;
320 return arg;
321 }
322
323 uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
324 {
325 uint32_t tmp0, tmp1;
326
327 tmp1 = arg1 - arg0;
328 tmp0 = arg1;
329 arg1 = tmp1 - (env->sr & SR_T);
330 if (tmp0 < tmp1)
331 env->sr |= SR_T;
332 else
333 env->sr &= ~SR_T;
334 if (tmp1 < arg1)
335 env->sr |= SR_T;
336 return arg1;
337 }
338
339 uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
340 {
341 int32_t dest, src, ans;
342
343 if ((int32_t) arg1 >= 0)
344 dest = 0;
345 else
346 dest = 1;
347 if ((int32_t) arg0 >= 0)
348 src = 0;
349 else
350 src = 1;
351 src += dest;
352 arg1 -= arg0;
353 if ((int32_t) arg1 >= 0)
354 ans = 0;
355 else
356 ans = 1;
357 ans += dest;
358 if (src == 1) {
359 if (ans == 1)
360 env->sr |= SR_T;
361 else
362 env->sr &= ~SR_T;
363 } else
364 env->sr &= ~SR_T;
365 return arg1;
366 }
367
368 void helper_rotcl(uint32_t * addr)
369 {
370 uint32_t new;
371
372 new = (*addr << 1) | (env->sr & SR_T);
373 if (*addr & 0x80000000)
374 env->sr |= SR_T;
375 else
376 env->sr &= ~SR_T;
377 *addr = new;
378 }
379
380 void helper_rotcr(uint32_t * addr)
381 {
382 uint32_t new;
383
384 new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
385 if (*addr & 1)
386 env->sr |= SR_T;
387 else
388 env->sr &= ~SR_T;
389 *addr = new;
390 }