root / target-sh4 / op_helper.c @ 5fafdf24
History | View | Annotate | Download (6.5 kB)
1 | fdf9b3e8 | bellard | /*
|
---|---|---|---|
2 | fdf9b3e8 | bellard | * SH4 emulation
|
3 | 5fafdf24 | ths | *
|
4 | fdf9b3e8 | bellard | * Copyright (c) 2005 Samuel Tardieu
|
5 | fdf9b3e8 | bellard | *
|
6 | fdf9b3e8 | bellard | * This library is free software; you can redistribute it and/or
|
7 | fdf9b3e8 | bellard | * modify it under the terms of the GNU Lesser General Public
|
8 | fdf9b3e8 | bellard | * License as published by the Free Software Foundation; either
|
9 | fdf9b3e8 | bellard | * version 2 of the License, or (at your option) any later version.
|
10 | fdf9b3e8 | bellard | *
|
11 | fdf9b3e8 | bellard | * This library is distributed in the hope that it will be useful,
|
12 | fdf9b3e8 | bellard | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | fdf9b3e8 | bellard | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | fdf9b3e8 | bellard | * Lesser General Public License for more details.
|
15 | fdf9b3e8 | bellard | *
|
16 | fdf9b3e8 | bellard | * You should have received a copy of the GNU Lesser General Public
|
17 | fdf9b3e8 | bellard | * License along with this library; if not, write to the Free Software
|
18 | fdf9b3e8 | bellard | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19 | fdf9b3e8 | bellard | */
|
20 | fdf9b3e8 | bellard | #include <assert.h> |
21 | fdf9b3e8 | bellard | #include "exec.h" |
22 | fdf9b3e8 | bellard | |
23 | fdf9b3e8 | bellard | void do_raise_exception(void) |
24 | fdf9b3e8 | bellard | { |
25 | fdf9b3e8 | bellard | cpu_loop_exit(); |
26 | fdf9b3e8 | bellard | } |
27 | fdf9b3e8 | bellard | |
28 | fdf9b3e8 | bellard | #ifndef CONFIG_USER_ONLY
|
29 | fdf9b3e8 | bellard | |
30 | fdf9b3e8 | bellard | #define MMUSUFFIX _mmu
|
31 | fdf9b3e8 | bellard | #define GETPC() (__builtin_return_address(0)) |
32 | fdf9b3e8 | bellard | |
33 | fdf9b3e8 | bellard | #define SHIFT 0 |
34 | fdf9b3e8 | bellard | #include "softmmu_template.h" |
35 | fdf9b3e8 | bellard | |
36 | fdf9b3e8 | bellard | #define SHIFT 1 |
37 | fdf9b3e8 | bellard | #include "softmmu_template.h" |
38 | fdf9b3e8 | bellard | |
39 | fdf9b3e8 | bellard | #define SHIFT 2 |
40 | fdf9b3e8 | bellard | #include "softmmu_template.h" |
41 | fdf9b3e8 | bellard | |
42 | fdf9b3e8 | bellard | #define SHIFT 3 |
43 | fdf9b3e8 | bellard | #include "softmmu_template.h" |
44 | fdf9b3e8 | bellard | |
45 | fdf9b3e8 | bellard | void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) |
46 | fdf9b3e8 | bellard | { |
47 | fdf9b3e8 | bellard | TranslationBlock *tb; |
48 | fdf9b3e8 | bellard | CPUState *saved_env; |
49 | fdf9b3e8 | bellard | unsigned long pc; |
50 | fdf9b3e8 | bellard | int ret;
|
51 | fdf9b3e8 | bellard | |
52 | fdf9b3e8 | bellard | /* XXX: hack to restore env in all cases, even if not called from
|
53 | fdf9b3e8 | bellard | generated code */
|
54 | fdf9b3e8 | bellard | saved_env = env; |
55 | fdf9b3e8 | bellard | env = cpu_single_env; |
56 | fdf9b3e8 | bellard | ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, is_user, 1);
|
57 | fdf9b3e8 | bellard | if (ret) {
|
58 | fdf9b3e8 | bellard | if (retaddr) {
|
59 | fdf9b3e8 | bellard | /* now we have a real cpu fault */
|
60 | fdf9b3e8 | bellard | pc = (unsigned long) retaddr; |
61 | fdf9b3e8 | bellard | tb = tb_find_pc(pc); |
62 | fdf9b3e8 | bellard | if (tb) {
|
63 | fdf9b3e8 | bellard | /* the PC is inside the translated code. It means that we have
|
64 | fdf9b3e8 | bellard | a virtual CPU fault */
|
65 | fdf9b3e8 | bellard | cpu_restore_state(tb, env, pc, NULL);
|
66 | fdf9b3e8 | bellard | } |
67 | fdf9b3e8 | bellard | } |
68 | fdf9b3e8 | bellard | do_raise_exception(); |
69 | fdf9b3e8 | bellard | } |
70 | fdf9b3e8 | bellard | env = saved_env; |
71 | fdf9b3e8 | bellard | } |
72 | fdf9b3e8 | bellard | |
73 | fdf9b3e8 | bellard | #endif
|
74 | fdf9b3e8 | bellard | |
75 | fdf9b3e8 | bellard | void helper_addc_T0_T1(void) |
76 | fdf9b3e8 | bellard | { |
77 | fdf9b3e8 | bellard | uint32_t tmp0, tmp1; |
78 | fdf9b3e8 | bellard | |
79 | fdf9b3e8 | bellard | tmp1 = T0 + T1; |
80 | fdf9b3e8 | bellard | tmp0 = T1; |
81 | fdf9b3e8 | bellard | T1 = tmp1 + (env->sr & 1);
|
82 | fdf9b3e8 | bellard | if (tmp0 > tmp1)
|
83 | fdf9b3e8 | bellard | env->sr |= SR_T; |
84 | fdf9b3e8 | bellard | else
|
85 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
86 | fdf9b3e8 | bellard | if (tmp1 > T1)
|
87 | fdf9b3e8 | bellard | env->sr |= SR_T; |
88 | fdf9b3e8 | bellard | } |
89 | fdf9b3e8 | bellard | |
90 | fdf9b3e8 | bellard | void helper_addv_T0_T1(void) |
91 | fdf9b3e8 | bellard | { |
92 | fdf9b3e8 | bellard | uint32_t dest, src, ans; |
93 | fdf9b3e8 | bellard | |
94 | fdf9b3e8 | bellard | if ((int32_t) T1 >= 0) |
95 | fdf9b3e8 | bellard | dest = 0;
|
96 | fdf9b3e8 | bellard | else
|
97 | fdf9b3e8 | bellard | dest = 1;
|
98 | fdf9b3e8 | bellard | if ((int32_t) T0 >= 0) |
99 | fdf9b3e8 | bellard | src = 0;
|
100 | fdf9b3e8 | bellard | else
|
101 | fdf9b3e8 | bellard | src = 1;
|
102 | fdf9b3e8 | bellard | src += dest; |
103 | fdf9b3e8 | bellard | T1 += T0; |
104 | fdf9b3e8 | bellard | if ((int32_t) T1 >= 0) |
105 | fdf9b3e8 | bellard | ans = 0;
|
106 | fdf9b3e8 | bellard | else
|
107 | fdf9b3e8 | bellard | ans = 1;
|
108 | fdf9b3e8 | bellard | ans += dest; |
109 | fdf9b3e8 | bellard | if (src == 0 || src == 2) { |
110 | fdf9b3e8 | bellard | if (ans == 1) |
111 | fdf9b3e8 | bellard | env->sr |= SR_T; |
112 | fdf9b3e8 | bellard | else
|
113 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
114 | fdf9b3e8 | bellard | } else
|
115 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
116 | fdf9b3e8 | bellard | } |
117 | fdf9b3e8 | bellard | |
118 | fdf9b3e8 | bellard | #define T (env->sr & SR_T)
|
119 | fdf9b3e8 | bellard | #define Q (env->sr & SR_Q ? 1 : 0) |
120 | fdf9b3e8 | bellard | #define M (env->sr & SR_M ? 1 : 0) |
121 | fdf9b3e8 | bellard | #define SETT env->sr |= SR_T
|
122 | fdf9b3e8 | bellard | #define CLRT env->sr &= ~SR_T
|
123 | fdf9b3e8 | bellard | #define SETQ env->sr |= SR_Q
|
124 | fdf9b3e8 | bellard | #define CLRQ env->sr &= ~SR_Q
|
125 | fdf9b3e8 | bellard | #define SETM env->sr |= SR_M
|
126 | fdf9b3e8 | bellard | #define CLRM env->sr &= ~SR_M
|
127 | fdf9b3e8 | bellard | |
128 | fdf9b3e8 | bellard | void helper_div1_T0_T1(void) |
129 | fdf9b3e8 | bellard | { |
130 | fdf9b3e8 | bellard | uint32_t tmp0, tmp2; |
131 | fdf9b3e8 | bellard | uint8_t old_q, tmp1 = 0xff;
|
132 | fdf9b3e8 | bellard | |
133 | 397e923f | pbrook | //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
|
134 | fdf9b3e8 | bellard | old_q = Q; |
135 | fdf9b3e8 | bellard | if ((0x80000000 & T1) != 0) |
136 | fdf9b3e8 | bellard | SETQ; |
137 | fdf9b3e8 | bellard | else
|
138 | fdf9b3e8 | bellard | CLRQ; |
139 | fdf9b3e8 | bellard | tmp2 = T0; |
140 | fdf9b3e8 | bellard | T1 <<= 1;
|
141 | fdf9b3e8 | bellard | T1 |= T; |
142 | fdf9b3e8 | bellard | switch (old_q) {
|
143 | fdf9b3e8 | bellard | case 0: |
144 | fdf9b3e8 | bellard | switch (M) {
|
145 | fdf9b3e8 | bellard | case 0: |
146 | fdf9b3e8 | bellard | tmp0 = T1; |
147 | fdf9b3e8 | bellard | T1 -= tmp2; |
148 | fdf9b3e8 | bellard | tmp1 = T1 > tmp0; |
149 | fdf9b3e8 | bellard | switch (Q) {
|
150 | fdf9b3e8 | bellard | case 0: |
151 | fdf9b3e8 | bellard | if (tmp1)
|
152 | fdf9b3e8 | bellard | SETQ; |
153 | fdf9b3e8 | bellard | else
|
154 | fdf9b3e8 | bellard | CLRQ; |
155 | fdf9b3e8 | bellard | break;
|
156 | fdf9b3e8 | bellard | case 1: |
157 | fdf9b3e8 | bellard | if (tmp1 == 0) |
158 | fdf9b3e8 | bellard | SETQ; |
159 | fdf9b3e8 | bellard | else
|
160 | fdf9b3e8 | bellard | CLRQ; |
161 | fdf9b3e8 | bellard | break;
|
162 | fdf9b3e8 | bellard | } |
163 | fdf9b3e8 | bellard | break;
|
164 | fdf9b3e8 | bellard | case 1: |
165 | fdf9b3e8 | bellard | tmp0 = T1; |
166 | fdf9b3e8 | bellard | T1 += tmp2; |
167 | fdf9b3e8 | bellard | tmp1 = T1 < tmp0; |
168 | fdf9b3e8 | bellard | switch (Q) {
|
169 | fdf9b3e8 | bellard | case 0: |
170 | fdf9b3e8 | bellard | if (tmp1 == 0) |
171 | fdf9b3e8 | bellard | SETQ; |
172 | fdf9b3e8 | bellard | else
|
173 | fdf9b3e8 | bellard | CLRQ; |
174 | fdf9b3e8 | bellard | break;
|
175 | fdf9b3e8 | bellard | case 1: |
176 | fdf9b3e8 | bellard | if (tmp1)
|
177 | fdf9b3e8 | bellard | SETQ; |
178 | fdf9b3e8 | bellard | else
|
179 | fdf9b3e8 | bellard | CLRQ; |
180 | fdf9b3e8 | bellard | break;
|
181 | fdf9b3e8 | bellard | } |
182 | fdf9b3e8 | bellard | break;
|
183 | fdf9b3e8 | bellard | } |
184 | fdf9b3e8 | bellard | break;
|
185 | fdf9b3e8 | bellard | case 1: |
186 | fdf9b3e8 | bellard | switch (M) {
|
187 | fdf9b3e8 | bellard | case 0: |
188 | fdf9b3e8 | bellard | tmp0 = T1; |
189 | fdf9b3e8 | bellard | T1 += tmp2; |
190 | fdf9b3e8 | bellard | tmp1 = T1 < tmp0; |
191 | fdf9b3e8 | bellard | switch (Q) {
|
192 | fdf9b3e8 | bellard | case 0: |
193 | fdf9b3e8 | bellard | if (tmp1)
|
194 | fdf9b3e8 | bellard | SETQ; |
195 | fdf9b3e8 | bellard | else
|
196 | fdf9b3e8 | bellard | CLRQ; |
197 | fdf9b3e8 | bellard | break;
|
198 | fdf9b3e8 | bellard | case 1: |
199 | fdf9b3e8 | bellard | if (tmp1 == 0) |
200 | fdf9b3e8 | bellard | SETQ; |
201 | fdf9b3e8 | bellard | else
|
202 | fdf9b3e8 | bellard | CLRQ; |
203 | fdf9b3e8 | bellard | break;
|
204 | fdf9b3e8 | bellard | } |
205 | fdf9b3e8 | bellard | break;
|
206 | fdf9b3e8 | bellard | case 1: |
207 | fdf9b3e8 | bellard | tmp0 = T1; |
208 | fdf9b3e8 | bellard | T1 -= tmp2; |
209 | fdf9b3e8 | bellard | tmp1 = T1 > tmp0; |
210 | fdf9b3e8 | bellard | switch (Q) {
|
211 | fdf9b3e8 | bellard | case 0: |
212 | fdf9b3e8 | bellard | if (tmp1 == 0) |
213 | fdf9b3e8 | bellard | SETQ; |
214 | fdf9b3e8 | bellard | else
|
215 | fdf9b3e8 | bellard | CLRQ; |
216 | fdf9b3e8 | bellard | break;
|
217 | fdf9b3e8 | bellard | case 1: |
218 | fdf9b3e8 | bellard | if (tmp1)
|
219 | fdf9b3e8 | bellard | SETQ; |
220 | fdf9b3e8 | bellard | else
|
221 | fdf9b3e8 | bellard | CLRQ; |
222 | fdf9b3e8 | bellard | break;
|
223 | fdf9b3e8 | bellard | } |
224 | fdf9b3e8 | bellard | break;
|
225 | fdf9b3e8 | bellard | } |
226 | fdf9b3e8 | bellard | break;
|
227 | fdf9b3e8 | bellard | } |
228 | fdf9b3e8 | bellard | if (Q == M)
|
229 | fdf9b3e8 | bellard | SETT; |
230 | fdf9b3e8 | bellard | else
|
231 | fdf9b3e8 | bellard | CLRT; |
232 | 397e923f | pbrook | //printf("Output: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
|
233 | fdf9b3e8 | bellard | } |
234 | fdf9b3e8 | bellard | |
235 | fdf9b3e8 | bellard | void helper_dmulsl_T0_T1()
|
236 | fdf9b3e8 | bellard | { |
237 | fdf9b3e8 | bellard | int64_t res; |
238 | fdf9b3e8 | bellard | |
239 | fdf9b3e8 | bellard | res = (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1; |
240 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
241 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
242 | fdf9b3e8 | bellard | } |
243 | fdf9b3e8 | bellard | |
244 | fdf9b3e8 | bellard | void helper_dmulul_T0_T1()
|
245 | fdf9b3e8 | bellard | { |
246 | fdf9b3e8 | bellard | uint64_t res; |
247 | fdf9b3e8 | bellard | |
248 | fdf9b3e8 | bellard | res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1; |
249 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
250 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
251 | fdf9b3e8 | bellard | } |
252 | fdf9b3e8 | bellard | |
253 | fdf9b3e8 | bellard | void helper_macl_T0_T1()
|
254 | fdf9b3e8 | bellard | { |
255 | fdf9b3e8 | bellard | int64_t res; |
256 | fdf9b3e8 | bellard | |
257 | fdf9b3e8 | bellard | res = ((uint64_t) env->mach << 32) | env->macl;
|
258 | fdf9b3e8 | bellard | res += (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1; |
259 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
260 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
261 | fdf9b3e8 | bellard | if (env->sr & SR_S) {
|
262 | fdf9b3e8 | bellard | if (res < 0) |
263 | fdf9b3e8 | bellard | env->mach |= 0xffff0000;
|
264 | fdf9b3e8 | bellard | else
|
265 | fdf9b3e8 | bellard | env->mach &= 0x00007fff;
|
266 | fdf9b3e8 | bellard | } |
267 | fdf9b3e8 | bellard | } |
268 | fdf9b3e8 | bellard | |
269 | fdf9b3e8 | bellard | void helper_macw_T0_T1()
|
270 | fdf9b3e8 | bellard | { |
271 | fdf9b3e8 | bellard | int64_t res; |
272 | fdf9b3e8 | bellard | |
273 | fdf9b3e8 | bellard | res = ((uint64_t) env->mach << 32) | env->macl;
|
274 | fdf9b3e8 | bellard | res += (int64_t) (int16_t) T0 *(int64_t) (int16_t) T1; |
275 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
276 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
277 | fdf9b3e8 | bellard | if (env->sr & SR_S) {
|
278 | fdf9b3e8 | bellard | if (res < -0x80000000) { |
279 | fdf9b3e8 | bellard | env->mach = 1;
|
280 | fdf9b3e8 | bellard | env->macl = 0x80000000;
|
281 | fdf9b3e8 | bellard | } else if (res > 0x000000007fffffff) { |
282 | fdf9b3e8 | bellard | env->mach = 1;
|
283 | fdf9b3e8 | bellard | env->macl = 0x7fffffff;
|
284 | fdf9b3e8 | bellard | } |
285 | fdf9b3e8 | bellard | } |
286 | fdf9b3e8 | bellard | } |
287 | fdf9b3e8 | bellard | |
288 | fdf9b3e8 | bellard | void helper_negc_T0()
|
289 | fdf9b3e8 | bellard | { |
290 | fdf9b3e8 | bellard | uint32_t temp; |
291 | fdf9b3e8 | bellard | |
292 | fdf9b3e8 | bellard | temp = -T0; |
293 | fdf9b3e8 | bellard | T0 = temp - (env->sr & SR_T); |
294 | fdf9b3e8 | bellard | if (0 < temp) |
295 | fdf9b3e8 | bellard | env->sr |= SR_T; |
296 | fdf9b3e8 | bellard | else
|
297 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
298 | fdf9b3e8 | bellard | if (temp < T0)
|
299 | fdf9b3e8 | bellard | env->sr |= SR_T; |
300 | fdf9b3e8 | bellard | } |
301 | fdf9b3e8 | bellard | |
302 | fdf9b3e8 | bellard | void helper_subc_T0_T1()
|
303 | fdf9b3e8 | bellard | { |
304 | fdf9b3e8 | bellard | uint32_t tmp0, tmp1; |
305 | fdf9b3e8 | bellard | |
306 | fdf9b3e8 | bellard | tmp1 = T1 - T0; |
307 | fdf9b3e8 | bellard | tmp0 = T1; |
308 | fdf9b3e8 | bellard | T1 = tmp1 - (env->sr & SR_T); |
309 | fdf9b3e8 | bellard | if (tmp0 < tmp1)
|
310 | fdf9b3e8 | bellard | env->sr |= SR_T; |
311 | fdf9b3e8 | bellard | else
|
312 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
313 | fdf9b3e8 | bellard | if (tmp1 < T1)
|
314 | fdf9b3e8 | bellard | env->sr |= SR_T; |
315 | fdf9b3e8 | bellard | } |
316 | fdf9b3e8 | bellard | |
317 | fdf9b3e8 | bellard | void helper_subv_T0_T1()
|
318 | fdf9b3e8 | bellard | { |
319 | fdf9b3e8 | bellard | int32_t dest, src, ans; |
320 | fdf9b3e8 | bellard | |
321 | fdf9b3e8 | bellard | if ((int32_t) T1 >= 0) |
322 | fdf9b3e8 | bellard | dest = 0;
|
323 | fdf9b3e8 | bellard | else
|
324 | fdf9b3e8 | bellard | dest = 1;
|
325 | fdf9b3e8 | bellard | if ((int32_t) T0 >= 0) |
326 | fdf9b3e8 | bellard | src = 0;
|
327 | fdf9b3e8 | bellard | else
|
328 | fdf9b3e8 | bellard | src = 1;
|
329 | fdf9b3e8 | bellard | src += dest; |
330 | fdf9b3e8 | bellard | T1 -= T0; |
331 | fdf9b3e8 | bellard | if ((int32_t) T1 >= 0) |
332 | fdf9b3e8 | bellard | ans = 0;
|
333 | fdf9b3e8 | bellard | else
|
334 | fdf9b3e8 | bellard | ans = 1;
|
335 | fdf9b3e8 | bellard | ans += dest; |
336 | fdf9b3e8 | bellard | if (src == 1) { |
337 | fdf9b3e8 | bellard | if (ans == 1) |
338 | fdf9b3e8 | bellard | env->sr |= SR_T; |
339 | fdf9b3e8 | bellard | else
|
340 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
341 | fdf9b3e8 | bellard | } else
|
342 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
343 | fdf9b3e8 | bellard | } |
344 | fdf9b3e8 | bellard | |
345 | fdf9b3e8 | bellard | void helper_rotcl(uint32_t * addr)
|
346 | fdf9b3e8 | bellard | { |
347 | fdf9b3e8 | bellard | uint32_t new; |
348 | fdf9b3e8 | bellard | |
349 | fdf9b3e8 | bellard | new = (*addr << 1) | (env->sr & SR_T);
|
350 | fdf9b3e8 | bellard | if (*addr & 0x80000000) |
351 | fdf9b3e8 | bellard | env->sr |= SR_T; |
352 | fdf9b3e8 | bellard | else
|
353 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
354 | fdf9b3e8 | bellard | *addr = new; |
355 | fdf9b3e8 | bellard | } |
356 | fdf9b3e8 | bellard | |
357 | fdf9b3e8 | bellard | void helper_rotcr(uint32_t * addr)
|
358 | fdf9b3e8 | bellard | { |
359 | fdf9b3e8 | bellard | uint32_t new; |
360 | fdf9b3e8 | bellard | |
361 | fdf9b3e8 | bellard | new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0); |
362 | fdf9b3e8 | bellard | if (*addr & 1) |
363 | fdf9b3e8 | bellard | env->sr |= SR_T; |
364 | fdf9b3e8 | bellard | else
|
365 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
366 | fdf9b3e8 | bellard | *addr = new; |
367 | fdf9b3e8 | bellard | } |