|
|
1.1 root 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 cpu_loop_exit(void)
24: {
25: longjmp(env->jmp_env, 1);
26: }
27:
28: void do_raise_exception(void)
29: {
30: cpu_loop_exit();
31: }
32:
33: #ifndef CONFIG_USER_ONLY
34:
35: #define MMUSUFFIX _mmu
36: #define GETPC() (__builtin_return_address(0))
37:
38: #define SHIFT 0
39: #include "softmmu_template.h"
40:
41: #define SHIFT 1
42: #include "softmmu_template.h"
43:
44: #define SHIFT 2
45: #include "softmmu_template.h"
46:
47: #define SHIFT 3
48: #include "softmmu_template.h"
49:
50: void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
51: {
52: TranslationBlock *tb;
53: CPUState *saved_env;
54: unsigned long pc;
55: int ret;
56:
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);
71: }
72: }
73: do_raise_exception();
74: }
75: env = saved_env;
76: }
77:
78: #endif
79:
80: void helper_addc_T0_T1(void)
81: {
82: uint32_t tmp0, tmp1;
83:
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;
93: }
94:
95: void helper_addv_T0_T1(void)
96: {
97: uint32_t dest, src, ans;
98:
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;
121: }
122:
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
132:
133: void helper_div1_T0_T1(void)
134: {
135: uint32_t tmp0, tmp2;
136: uint8_t old_q, tmp1 = 0xff;
137:
1.1.1.2 ! root 138: //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
1.1 root 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;
167: }
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;
186: }
187: break;
188: }
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;
209: }
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;
228: }
229: break;
230: }
231: break;
232: }
233: if (Q == M)
234: SETT;
235: else
236: CLRT;
1.1.1.2 ! root 237: //printf("Output: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
1.1 root 238: }
239:
240: void helper_dmulsl_T0_T1()
241: {
242: int64_t res;
243:
244: res = (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
245: env->mach = (res >> 32) & 0xffffffff;
246: env->macl = res & 0xffffffff;
247: }
248:
249: void helper_dmulul_T0_T1()
250: {
251: uint64_t res;
252:
253: res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1;
254: env->mach = (res >> 32) & 0xffffffff;
255: env->macl = res & 0xffffffff;
256: }
257:
258: void helper_macl_T0_T1()
259: {
260: int64_t res;
261:
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;
271: }
272: }
273:
274: void helper_macw_T0_T1()
275: {
276: int64_t res;
277:
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;
289: }
290: }
291: }
292:
293: void helper_negc_T0()
294: {
295: uint32_t temp;
296:
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;
305: }
306:
307: void helper_subc_T0_T1()
308: {
309: uint32_t tmp0, tmp1;
310:
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;
320: }
321:
322: void helper_subv_T0_T1()
323: {
324: int32_t dest, src, ans;
325:
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;
348: }
349:
350: void helper_rotcl(uint32_t * addr)
351: {
352: uint32_t new;
353:
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;
360: }
361:
362: void helper_rotcr(uint32_t * addr)
363: {
364: uint32_t new;
365:
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;
372: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.