]> git.proxmox.com Git - qemu.git/blob - target-sh4/op_helper.c
Adjust s390 addresses (the MSB is defined as "to be ignored").
[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 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 }