root / target-m68k / op.c @ 89fc88da
History | View | Annotate | Download (20.6 kB)
1 | e6e5906b | pbrook | /*
|
---|---|---|---|
2 | e6e5906b | pbrook | * m68k micro operations
|
3 | 5fafdf24 | ths | *
|
4 | 0633879f | pbrook | * Copyright (c) 2006-2007 CodeSourcery
|
5 | e6e5906b | pbrook | * Written by Paul Brook
|
6 | e6e5906b | pbrook | *
|
7 | e6e5906b | pbrook | * This library is free software; you can redistribute it and/or
|
8 | e6e5906b | pbrook | * modify it under the terms of the GNU Lesser General Public
|
9 | e6e5906b | pbrook | * License as published by the Free Software Foundation; either
|
10 | e6e5906b | pbrook | * version 2 of the License, or (at your option) any later version.
|
11 | e6e5906b | pbrook | *
|
12 | e6e5906b | pbrook | * This library is distributed in the hope that it will be useful,
|
13 | e6e5906b | pbrook | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | e6e5906b | pbrook | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 | e6e5906b | pbrook | * General Public License for more details.
|
16 | e6e5906b | pbrook | *
|
17 | e6e5906b | pbrook | * You should have received a copy of the GNU Lesser General Public
|
18 | e6e5906b | pbrook | * License along with this library; if not, write to the Free Software
|
19 | e6e5906b | pbrook | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
20 | e6e5906b | pbrook | */
|
21 | e6e5906b | pbrook | |
22 | e6e5906b | pbrook | #include "exec.h" |
23 | e6e5906b | pbrook | #include "m68k-qreg.h" |
24 | e6e5906b | pbrook | |
25 | e6e5906b | pbrook | #ifndef offsetof
|
26 | e6e5906b | pbrook | #define offsetof(type, field) ((size_t) &((type *)0)->field) |
27 | e6e5906b | pbrook | #endif
|
28 | e6e5906b | pbrook | |
29 | e6e5906b | pbrook | static long qreg_offsets[] = { |
30 | e6e5906b | pbrook | #define DEFO32(name, offset) offsetof(CPUState, offset),
|
31 | e6e5906b | pbrook | #define DEFR(name, reg, mode) -1, |
32 | e6e5906b | pbrook | #define DEFF64(name, offset) offsetof(CPUState, offset),
|
33 | e6e5906b | pbrook | 0,
|
34 | e6e5906b | pbrook | #include "qregs.def" |
35 | e6e5906b | pbrook | }; |
36 | e6e5906b | pbrook | |
37 | e6e5906b | pbrook | #define CPU_FP_STATUS env->fp_status
|
38 | e6e5906b | pbrook | |
39 | e6e5906b | pbrook | #define RAISE_EXCEPTION(n) do { \ |
40 | e6e5906b | pbrook | env->exception_index = n; \ |
41 | e6e5906b | pbrook | cpu_loop_exit(); \ |
42 | e6e5906b | pbrook | } while(0) |
43 | e6e5906b | pbrook | |
44 | e6e5906b | pbrook | #define get_op helper_get_op
|
45 | e6e5906b | pbrook | #define set_op helper_set_op
|
46 | e6e5906b | pbrook | #define get_opf64 helper_get_opf64
|
47 | e6e5906b | pbrook | #define set_opf64 helper_set_opf64
|
48 | e6e5906b | pbrook | uint32_t |
49 | e6e5906b | pbrook | get_op(int qreg)
|
50 | e6e5906b | pbrook | { |
51 | 7ec47ead | pbrook | if (qreg >= TARGET_NUM_QREGS) {
|
52 | 7ec47ead | pbrook | return env->qregs[qreg - TARGET_NUM_QREGS];
|
53 | 7ec47ead | pbrook | } else if (qreg == QREG_T0) { |
54 | e6e5906b | pbrook | return T0;
|
55 | e6e5906b | pbrook | } else {
|
56 | 7ec47ead | pbrook | return *(uint32_t *)(((long)env) + qreg_offsets[qreg]); |
57 | e6e5906b | pbrook | } |
58 | e6e5906b | pbrook | } |
59 | e6e5906b | pbrook | |
60 | e6e5906b | pbrook | void set_op(int qreg, uint32_t val) |
61 | e6e5906b | pbrook | { |
62 | 7ec47ead | pbrook | if (qreg >= TARGET_NUM_QREGS) {
|
63 | 7ec47ead | pbrook | env->qregs[qreg - TARGET_NUM_QREGS] = val; |
64 | 7ec47ead | pbrook | } else if (qreg == QREG_T0) { |
65 | e6e5906b | pbrook | T0 = val; |
66 | e6e5906b | pbrook | } else {
|
67 | 7ec47ead | pbrook | *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val;
|
68 | e6e5906b | pbrook | } |
69 | e6e5906b | pbrook | } |
70 | e6e5906b | pbrook | |
71 | e6e5906b | pbrook | float64 get_opf64(int qreg)
|
72 | e6e5906b | pbrook | { |
73 | e6e5906b | pbrook | if (qreg < TARGET_NUM_QREGS) {
|
74 | e6e5906b | pbrook | return *(float64 *)(((long)env) + qreg_offsets[qreg]); |
75 | e6e5906b | pbrook | } else {
|
76 | e6e5906b | pbrook | return *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS];
|
77 | e6e5906b | pbrook | } |
78 | e6e5906b | pbrook | } |
79 | e6e5906b | pbrook | |
80 | e6e5906b | pbrook | void set_opf64(int qreg, float64 val) |
81 | e6e5906b | pbrook | { |
82 | e6e5906b | pbrook | if (qreg < TARGET_NUM_QREGS) {
|
83 | e6e5906b | pbrook | *(float64 *)(((long)env) + qreg_offsets[qreg]) = val;
|
84 | e6e5906b | pbrook | } else {
|
85 | e6e5906b | pbrook | *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS] = val; |
86 | e6e5906b | pbrook | } |
87 | e6e5906b | pbrook | } |
88 | e6e5906b | pbrook | |
89 | 0633879f | pbrook | #define OP(name) void OPPROTO glue(op_,name) (void) |
90 | e6e5906b | pbrook | |
91 | e6e5906b | pbrook | OP(mov32) |
92 | e6e5906b | pbrook | { |
93 | e6e5906b | pbrook | set_op(PARAM1, get_op(PARAM2)); |
94 | e6e5906b | pbrook | FORCE_RET(); |
95 | e6e5906b | pbrook | } |
96 | e6e5906b | pbrook | |
97 | e6e5906b | pbrook | OP(mov32_im) |
98 | e6e5906b | pbrook | { |
99 | e6e5906b | pbrook | set_op(PARAM1, PARAM2); |
100 | e6e5906b | pbrook | FORCE_RET(); |
101 | e6e5906b | pbrook | } |
102 | e6e5906b | pbrook | |
103 | e6e5906b | pbrook | OP(movf64) |
104 | e6e5906b | pbrook | { |
105 | e6e5906b | pbrook | set_opf64(PARAM1, get_opf64(PARAM2)); |
106 | e6e5906b | pbrook | FORCE_RET(); |
107 | e6e5906b | pbrook | } |
108 | e6e5906b | pbrook | |
109 | e6e5906b | pbrook | OP(zerof64) |
110 | e6e5906b | pbrook | { |
111 | e6e5906b | pbrook | set_opf64(PARAM1, 0);
|
112 | e6e5906b | pbrook | FORCE_RET(); |
113 | e6e5906b | pbrook | } |
114 | e6e5906b | pbrook | |
115 | e6e5906b | pbrook | OP(add32) |
116 | e6e5906b | pbrook | { |
117 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
118 | e6e5906b | pbrook | uint32_t op3 = get_op(PARAM3); |
119 | e6e5906b | pbrook | set_op(PARAM1, op2 + op3); |
120 | e6e5906b | pbrook | FORCE_RET(); |
121 | e6e5906b | pbrook | } |
122 | e6e5906b | pbrook | |
123 | e6e5906b | pbrook | OP(sub32) |
124 | e6e5906b | pbrook | { |
125 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
126 | e6e5906b | pbrook | uint32_t op3 = get_op(PARAM3); |
127 | e6e5906b | pbrook | set_op(PARAM1, op2 - op3); |
128 | e6e5906b | pbrook | FORCE_RET(); |
129 | e6e5906b | pbrook | } |
130 | e6e5906b | pbrook | |
131 | e6e5906b | pbrook | OP(mul32) |
132 | e6e5906b | pbrook | { |
133 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
134 | e6e5906b | pbrook | uint32_t op3 = get_op(PARAM3); |
135 | e6e5906b | pbrook | set_op(PARAM1, op2 * op3); |
136 | e6e5906b | pbrook | FORCE_RET(); |
137 | e6e5906b | pbrook | } |
138 | e6e5906b | pbrook | |
139 | e6e5906b | pbrook | OP(not32) |
140 | e6e5906b | pbrook | { |
141 | e6e5906b | pbrook | uint32_t arg = get_op(PARAM2); |
142 | e6e5906b | pbrook | set_op(PARAM1, ~arg); |
143 | e6e5906b | pbrook | FORCE_RET(); |
144 | e6e5906b | pbrook | } |
145 | e6e5906b | pbrook | |
146 | e6e5906b | pbrook | OP(neg32) |
147 | e6e5906b | pbrook | { |
148 | e6e5906b | pbrook | uint32_t arg = get_op(PARAM2); |
149 | e6e5906b | pbrook | set_op(PARAM1, -arg); |
150 | e6e5906b | pbrook | FORCE_RET(); |
151 | e6e5906b | pbrook | } |
152 | e6e5906b | pbrook | |
153 | e6e5906b | pbrook | OP(bswap32) |
154 | e6e5906b | pbrook | { |
155 | e6e5906b | pbrook | uint32_t arg = get_op(PARAM2); |
156 | e6e5906b | pbrook | arg = (arg >> 24) | (arg << 24) |
157 | e6e5906b | pbrook | | ((arg >> 16) & 0xff00) | ((arg << 16) & 0xff0000); |
158 | e6e5906b | pbrook | set_op(PARAM1, arg); |
159 | e6e5906b | pbrook | FORCE_RET(); |
160 | e6e5906b | pbrook | } |
161 | e6e5906b | pbrook | |
162 | e6e5906b | pbrook | OP(btest) |
163 | e6e5906b | pbrook | { |
164 | e6e5906b | pbrook | uint32_t op1 = get_op(PARAM1); |
165 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
166 | e6e5906b | pbrook | if (op1 & op2)
|
167 | e6e5906b | pbrook | env->cc_dest &= ~CCF_Z; |
168 | e6e5906b | pbrook | else
|
169 | e6e5906b | pbrook | env->cc_dest |= CCF_Z; |
170 | e6e5906b | pbrook | FORCE_RET(); |
171 | e6e5906b | pbrook | } |
172 | e6e5906b | pbrook | |
173 | 821f7e76 | pbrook | OP(ff1) |
174 | 821f7e76 | pbrook | { |
175 | 821f7e76 | pbrook | uint32_t arg = get_op(PARAM2); |
176 | 821f7e76 | pbrook | int n;
|
177 | 821f7e76 | pbrook | for (n = 32; arg; n--) |
178 | 821f7e76 | pbrook | arg >>= 1;
|
179 | 821f7e76 | pbrook | set_op(PARAM1, n); |
180 | 821f7e76 | pbrook | FORCE_RET(); |
181 | 821f7e76 | pbrook | } |
182 | 821f7e76 | pbrook | |
183 | 8d7fe053 | pbrook | OP(subx_cc) |
184 | e6e5906b | pbrook | { |
185 | e6e5906b | pbrook | uint32_t op1 = get_op(PARAM1); |
186 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
187 | e6e5906b | pbrook | uint32_t res; |
188 | e6e5906b | pbrook | if (env->cc_x) {
|
189 | e6e5906b | pbrook | env->cc_x = (op1 <= op2); |
190 | e6e5906b | pbrook | env->cc_op = CC_OP_SUBX; |
191 | e6e5906b | pbrook | res = op1 - (op2 + 1);
|
192 | e6e5906b | pbrook | } else {
|
193 | e6e5906b | pbrook | env->cc_x = (op1 < op2); |
194 | e6e5906b | pbrook | env->cc_op = CC_OP_SUB; |
195 | e6e5906b | pbrook | res = op1 - op2; |
196 | e6e5906b | pbrook | } |
197 | e6e5906b | pbrook | set_op(PARAM1, res); |
198 | e6e5906b | pbrook | FORCE_RET(); |
199 | e6e5906b | pbrook | } |
200 | e6e5906b | pbrook | |
201 | 8d7fe053 | pbrook | OP(addx_cc) |
202 | e6e5906b | pbrook | { |
203 | e6e5906b | pbrook | uint32_t op1 = get_op(PARAM1); |
204 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
205 | e6e5906b | pbrook | uint32_t res; |
206 | e6e5906b | pbrook | if (env->cc_x) {
|
207 | e6e5906b | pbrook | res = op1 + op2 + 1;
|
208 | e6e5906b | pbrook | env->cc_x = (res <= op2); |
209 | e6e5906b | pbrook | env->cc_op = CC_OP_ADDX; |
210 | e6e5906b | pbrook | } else {
|
211 | e6e5906b | pbrook | res = op1 + op2; |
212 | e6e5906b | pbrook | env->cc_x = (res < op2); |
213 | e6e5906b | pbrook | env->cc_op = CC_OP_ADD; |
214 | e6e5906b | pbrook | } |
215 | e6e5906b | pbrook | set_op(PARAM1, res); |
216 | e6e5906b | pbrook | FORCE_RET(); |
217 | e6e5906b | pbrook | } |
218 | e6e5906b | pbrook | |
219 | e6e5906b | pbrook | /* Logic ops. */
|
220 | e6e5906b | pbrook | |
221 | e6e5906b | pbrook | OP(and32) |
222 | e6e5906b | pbrook | { |
223 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
224 | e6e5906b | pbrook | uint32_t op3 = get_op(PARAM3); |
225 | e6e5906b | pbrook | set_op(PARAM1, op2 & op3); |
226 | e6e5906b | pbrook | FORCE_RET(); |
227 | e6e5906b | pbrook | } |
228 | e6e5906b | pbrook | |
229 | e6e5906b | pbrook | OP(or32) |
230 | e6e5906b | pbrook | { |
231 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
232 | e6e5906b | pbrook | uint32_t op3 = get_op(PARAM3); |
233 | e6e5906b | pbrook | set_op(PARAM1, op2 | op3); |
234 | e6e5906b | pbrook | FORCE_RET(); |
235 | e6e5906b | pbrook | } |
236 | e6e5906b | pbrook | |
237 | e6e5906b | pbrook | OP(xor32) |
238 | e6e5906b | pbrook | { |
239 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
240 | e6e5906b | pbrook | uint32_t op3 = get_op(PARAM3); |
241 | e6e5906b | pbrook | set_op(PARAM1, op2 ^ op3); |
242 | e6e5906b | pbrook | FORCE_RET(); |
243 | e6e5906b | pbrook | } |
244 | e6e5906b | pbrook | |
245 | e6e5906b | pbrook | /* Shifts. */
|
246 | e6e5906b | pbrook | OP(shl32) |
247 | e6e5906b | pbrook | { |
248 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
249 | e6e5906b | pbrook | uint32_t op3 = get_op(PARAM3); |
250 | e6e5906b | pbrook | uint32_t result; |
251 | e6e5906b | pbrook | result = op2 << op3; |
252 | e6e5906b | pbrook | set_op(PARAM1, result); |
253 | e6e5906b | pbrook | FORCE_RET(); |
254 | e6e5906b | pbrook | } |
255 | e6e5906b | pbrook | |
256 | e6e5906b | pbrook | OP(shl_cc) |
257 | e6e5906b | pbrook | { |
258 | e6e5906b | pbrook | uint32_t op1 = get_op(PARAM1); |
259 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
260 | e6e5906b | pbrook | uint32_t result; |
261 | e6e5906b | pbrook | result = op1 << op2; |
262 | e6e5906b | pbrook | set_op(PARAM1, result); |
263 | e6e5906b | pbrook | env->cc_x = (op1 << (op2 - 1)) & 1; |
264 | e6e5906b | pbrook | FORCE_RET(); |
265 | e6e5906b | pbrook | } |
266 | e6e5906b | pbrook | |
267 | e6e5906b | pbrook | OP(shr32) |
268 | e6e5906b | pbrook | { |
269 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
270 | e6e5906b | pbrook | uint32_t op3 = get_op(PARAM3); |
271 | e6e5906b | pbrook | uint32_t result; |
272 | e6e5906b | pbrook | result = op2 >> op3; |
273 | e6e5906b | pbrook | set_op(PARAM1, result); |
274 | e6e5906b | pbrook | FORCE_RET(); |
275 | e6e5906b | pbrook | } |
276 | e6e5906b | pbrook | |
277 | e6e5906b | pbrook | OP(shr_cc) |
278 | e6e5906b | pbrook | { |
279 | e6e5906b | pbrook | uint32_t op1 = get_op(PARAM1); |
280 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
281 | e6e5906b | pbrook | uint32_t result; |
282 | e6e5906b | pbrook | result = op1 >> op2; |
283 | e6e5906b | pbrook | set_op(PARAM1, result); |
284 | e6e5906b | pbrook | env->cc_x = (op1 >> (op2 - 1)) & 1; |
285 | e6e5906b | pbrook | FORCE_RET(); |
286 | e6e5906b | pbrook | } |
287 | e6e5906b | pbrook | |
288 | acf930aa | pbrook | OP(sar32) |
289 | acf930aa | pbrook | { |
290 | acf930aa | pbrook | int32_t op2 = get_op(PARAM2); |
291 | acf930aa | pbrook | uint32_t op3 = get_op(PARAM3); |
292 | acf930aa | pbrook | uint32_t result; |
293 | acf930aa | pbrook | result = op2 >> op3; |
294 | acf930aa | pbrook | set_op(PARAM1, result); |
295 | acf930aa | pbrook | FORCE_RET(); |
296 | acf930aa | pbrook | } |
297 | acf930aa | pbrook | |
298 | e6e5906b | pbrook | OP(sar_cc) |
299 | e6e5906b | pbrook | { |
300 | e6e5906b | pbrook | int32_t op1 = get_op(PARAM1); |
301 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
302 | e6e5906b | pbrook | uint32_t result; |
303 | e6e5906b | pbrook | result = op1 >> op2; |
304 | e6e5906b | pbrook | set_op(PARAM1, result); |
305 | e6e5906b | pbrook | env->cc_x = (op1 >> (op2 - 1)) & 1; |
306 | e6e5906b | pbrook | FORCE_RET(); |
307 | e6e5906b | pbrook | } |
308 | e6e5906b | pbrook | |
309 | e6e5906b | pbrook | /* Value extend. */
|
310 | e6e5906b | pbrook | |
311 | e6e5906b | pbrook | OP(ext8u32) |
312 | e6e5906b | pbrook | { |
313 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
314 | e6e5906b | pbrook | set_op(PARAM1, (uint8_t)op2); |
315 | e6e5906b | pbrook | FORCE_RET(); |
316 | e6e5906b | pbrook | } |
317 | e6e5906b | pbrook | |
318 | e6e5906b | pbrook | OP(ext8s32) |
319 | e6e5906b | pbrook | { |
320 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
321 | e6e5906b | pbrook | set_op(PARAM1, (int8_t)op2); |
322 | e6e5906b | pbrook | FORCE_RET(); |
323 | e6e5906b | pbrook | } |
324 | e6e5906b | pbrook | |
325 | e6e5906b | pbrook | OP(ext16u32) |
326 | e6e5906b | pbrook | { |
327 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
328 | e6e5906b | pbrook | set_op(PARAM1, (uint16_t)op2); |
329 | e6e5906b | pbrook | FORCE_RET(); |
330 | e6e5906b | pbrook | } |
331 | e6e5906b | pbrook | |
332 | e6e5906b | pbrook | OP(ext16s32) |
333 | e6e5906b | pbrook | { |
334 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
335 | e6e5906b | pbrook | set_op(PARAM1, (int16_t)op2); |
336 | e6e5906b | pbrook | FORCE_RET(); |
337 | e6e5906b | pbrook | } |
338 | e6e5906b | pbrook | |
339 | e6e5906b | pbrook | OP(flush_flags) |
340 | e6e5906b | pbrook | { |
341 | 0cf5c677 | pbrook | cpu_m68k_flush_flags(env, env->cc_op); |
342 | e6e5906b | pbrook | FORCE_RET(); |
343 | e6e5906b | pbrook | } |
344 | e6e5906b | pbrook | |
345 | e6e5906b | pbrook | OP(divu) |
346 | e6e5906b | pbrook | { |
347 | e6e5906b | pbrook | uint32_t num; |
348 | e6e5906b | pbrook | uint32_t den; |
349 | e6e5906b | pbrook | uint32_t quot; |
350 | e6e5906b | pbrook | uint32_t rem; |
351 | e6e5906b | pbrook | uint32_t flags; |
352 | 3b46e624 | ths | |
353 | e6e5906b | pbrook | num = env->div1; |
354 | e6e5906b | pbrook | den = env->div2; |
355 | e6e5906b | pbrook | /* ??? This needs to make sure the throwing location is accurate. */
|
356 | e6e5906b | pbrook | if (den == 0) |
357 | e6e5906b | pbrook | RAISE_EXCEPTION(EXCP_DIV0); |
358 | e6e5906b | pbrook | quot = num / den; |
359 | e6e5906b | pbrook | rem = num % den; |
360 | e6e5906b | pbrook | flags = 0;
|
361 | 2d37be61 | pbrook | /* Avoid using a PARAM1 of zero. This breaks dyngen because it uses
|
362 | 2d37be61 | pbrook | the address of a symbol, and gcc knows symbols can't have address
|
363 | 2d37be61 | pbrook | zero. */
|
364 | 2d37be61 | pbrook | if (PARAM1 == 2 && quot > 0xffff) |
365 | e6e5906b | pbrook | flags |= CCF_V; |
366 | e6e5906b | pbrook | if (quot == 0) |
367 | e6e5906b | pbrook | flags |= CCF_Z; |
368 | e6e5906b | pbrook | else if ((int32_t)quot < 0) |
369 | e6e5906b | pbrook | flags |= CCF_N; |
370 | e6e5906b | pbrook | env->div1 = quot; |
371 | e6e5906b | pbrook | env->div2 = rem; |
372 | e6e5906b | pbrook | env->cc_dest = flags; |
373 | e6e5906b | pbrook | FORCE_RET(); |
374 | e6e5906b | pbrook | } |
375 | e6e5906b | pbrook | |
376 | e6e5906b | pbrook | OP(divs) |
377 | e6e5906b | pbrook | { |
378 | e6e5906b | pbrook | int32_t num; |
379 | e6e5906b | pbrook | int32_t den; |
380 | e6e5906b | pbrook | int32_t quot; |
381 | e6e5906b | pbrook | int32_t rem; |
382 | e6e5906b | pbrook | int32_t flags; |
383 | 3b46e624 | ths | |
384 | e6e5906b | pbrook | num = env->div1; |
385 | e6e5906b | pbrook | den = env->div2; |
386 | e6e5906b | pbrook | if (den == 0) |
387 | e6e5906b | pbrook | RAISE_EXCEPTION(EXCP_DIV0); |
388 | e6e5906b | pbrook | quot = num / den; |
389 | e6e5906b | pbrook | rem = num % den; |
390 | e6e5906b | pbrook | flags = 0;
|
391 | 2d37be61 | pbrook | if (PARAM1 == 2 && quot != (int16_t)quot) |
392 | e6e5906b | pbrook | flags |= CCF_V; |
393 | e6e5906b | pbrook | if (quot == 0) |
394 | e6e5906b | pbrook | flags |= CCF_Z; |
395 | e6e5906b | pbrook | else if (quot < 0) |
396 | e6e5906b | pbrook | flags |= CCF_N; |
397 | e6e5906b | pbrook | env->div1 = quot; |
398 | e6e5906b | pbrook | env->div2 = rem; |
399 | e6e5906b | pbrook | env->cc_dest = flags; |
400 | e6e5906b | pbrook | FORCE_RET(); |
401 | e6e5906b | pbrook | } |
402 | e6e5906b | pbrook | |
403 | a87295e8 | pbrook | /* Halt is special because it may be a semihosting call. */
|
404 | 0633879f | pbrook | OP(halt) |
405 | 0633879f | pbrook | { |
406 | a87295e8 | pbrook | RAISE_EXCEPTION(EXCP_HALT_INSN); |
407 | a87295e8 | pbrook | FORCE_RET(); |
408 | a87295e8 | pbrook | } |
409 | a87295e8 | pbrook | |
410 | a87295e8 | pbrook | OP(stop) |
411 | a87295e8 | pbrook | { |
412 | 0633879f | pbrook | env->halted = 1;
|
413 | 0633879f | pbrook | RAISE_EXCEPTION(EXCP_HLT); |
414 | 0633879f | pbrook | FORCE_RET(); |
415 | 0633879f | pbrook | } |
416 | 0633879f | pbrook | |
417 | e6e5906b | pbrook | OP(raise_exception) |
418 | e6e5906b | pbrook | { |
419 | e6e5906b | pbrook | RAISE_EXCEPTION(PARAM1); |
420 | e6e5906b | pbrook | FORCE_RET(); |
421 | e6e5906b | pbrook | } |
422 | e6e5906b | pbrook | |
423 | e6e5906b | pbrook | /* Floating point comparison sets flags differently to other instructions. */
|
424 | e6e5906b | pbrook | |
425 | e6e5906b | pbrook | OP(sub_cmpf64) |
426 | e6e5906b | pbrook | { |
427 | e6e5906b | pbrook | float64 src0; |
428 | e6e5906b | pbrook | float64 src1; |
429 | e6e5906b | pbrook | src0 = get_opf64(PARAM2); |
430 | e6e5906b | pbrook | src1 = get_opf64(PARAM3); |
431 | e6e5906b | pbrook | set_opf64(PARAM1, helper_sub_cmpf64(env, src0, src1)); |
432 | e6e5906b | pbrook | FORCE_RET(); |
433 | e6e5906b | pbrook | } |
434 | e6e5906b | pbrook | |
435 | e6e5906b | pbrook | OP(update_xflag_tst) |
436 | e6e5906b | pbrook | { |
437 | e6e5906b | pbrook | uint32_t op1 = get_op(PARAM1); |
438 | e6e5906b | pbrook | env->cc_x = op1; |
439 | e6e5906b | pbrook | FORCE_RET(); |
440 | e6e5906b | pbrook | } |
441 | e6e5906b | pbrook | |
442 | e6e5906b | pbrook | OP(update_xflag_lt) |
443 | e6e5906b | pbrook | { |
444 | e6e5906b | pbrook | uint32_t op1 = get_op(PARAM1); |
445 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
446 | e6e5906b | pbrook | env->cc_x = (op1 < op2); |
447 | e6e5906b | pbrook | FORCE_RET(); |
448 | e6e5906b | pbrook | } |
449 | e6e5906b | pbrook | |
450 | e6e5906b | pbrook | OP(get_xflag) |
451 | e6e5906b | pbrook | { |
452 | e6e5906b | pbrook | set_op(PARAM1, env->cc_x); |
453 | e6e5906b | pbrook | FORCE_RET(); |
454 | e6e5906b | pbrook | } |
455 | e6e5906b | pbrook | |
456 | e6e5906b | pbrook | OP(logic_cc) |
457 | e6e5906b | pbrook | { |
458 | e6e5906b | pbrook | uint32_t op1 = get_op(PARAM1); |
459 | e6e5906b | pbrook | env->cc_dest = op1; |
460 | e6e5906b | pbrook | FORCE_RET(); |
461 | e6e5906b | pbrook | } |
462 | e6e5906b | pbrook | |
463 | e6e5906b | pbrook | OP(update_cc_add) |
464 | e6e5906b | pbrook | { |
465 | e6e5906b | pbrook | uint32_t op1 = get_op(PARAM1); |
466 | e6e5906b | pbrook | uint32_t op2 = get_op(PARAM2); |
467 | e6e5906b | pbrook | env->cc_dest = op1; |
468 | e6e5906b | pbrook | env->cc_src = op2; |
469 | e6e5906b | pbrook | FORCE_RET(); |
470 | e6e5906b | pbrook | } |
471 | e6e5906b | pbrook | |
472 | e6e5906b | pbrook | OP(fp_result) |
473 | e6e5906b | pbrook | { |
474 | e6e5906b | pbrook | env->fp_result = get_opf64(PARAM1); |
475 | e6e5906b | pbrook | FORCE_RET(); |
476 | e6e5906b | pbrook | } |
477 | e6e5906b | pbrook | |
478 | 20dcee94 | pbrook | OP(set_sr) |
479 | 20dcee94 | pbrook | { |
480 | 0cf5c677 | pbrook | env->sr = get_op(PARAM1) & 0xffff;
|
481 | 20dcee94 | pbrook | m68k_switch_sp(env); |
482 | 20dcee94 | pbrook | FORCE_RET(); |
483 | 20dcee94 | pbrook | } |
484 | 20dcee94 | pbrook | |
485 | e6e5906b | pbrook | OP(jmp) |
486 | e6e5906b | pbrook | { |
487 | e6e5906b | pbrook | GOTO_LABEL_PARAM(1);
|
488 | e6e5906b | pbrook | } |
489 | e6e5906b | pbrook | |
490 | 06d92f40 | pbrook | OP(set_T0_z32) |
491 | e6e5906b | pbrook | { |
492 | e6e5906b | pbrook | uint32_t arg = get_op(PARAM1); |
493 | 06d92f40 | pbrook | T0 = (arg == 0);
|
494 | e6e5906b | pbrook | FORCE_RET(); |
495 | e6e5906b | pbrook | } |
496 | e6e5906b | pbrook | |
497 | 06d92f40 | pbrook | OP(set_T0_nz32) |
498 | e6e5906b | pbrook | { |
499 | e6e5906b | pbrook | uint32_t arg = get_op(PARAM1); |
500 | 06d92f40 | pbrook | T0 = (arg != 0);
|
501 | e6e5906b | pbrook | FORCE_RET(); |
502 | e6e5906b | pbrook | } |
503 | e6e5906b | pbrook | |
504 | 06d92f40 | pbrook | OP(set_T0_s32) |
505 | e6e5906b | pbrook | { |
506 | e6e5906b | pbrook | int32_t arg = get_op(PARAM1); |
507 | 06d92f40 | pbrook | T0 = (arg > 0);
|
508 | e6e5906b | pbrook | FORCE_RET(); |
509 | e6e5906b | pbrook | } |
510 | e6e5906b | pbrook | |
511 | 06d92f40 | pbrook | OP(set_T0_ns32) |
512 | e6e5906b | pbrook | { |
513 | e6e5906b | pbrook | int32_t arg = get_op(PARAM1); |
514 | 06d92f40 | pbrook | T0 = (arg >= 0);
|
515 | 06d92f40 | pbrook | FORCE_RET(); |
516 | 06d92f40 | pbrook | } |
517 | 06d92f40 | pbrook | |
518 | 06d92f40 | pbrook | OP(jmp_T0) |
519 | 06d92f40 | pbrook | { |
520 | 06d92f40 | pbrook | if (T0)
|
521 | 06d92f40 | pbrook | GOTO_LABEL_PARAM(1);
|
522 | e6e5906b | pbrook | FORCE_RET(); |
523 | e6e5906b | pbrook | } |
524 | e6e5906b | pbrook | |
525 | e6e5906b | pbrook | void OPPROTO op_goto_tb0(void) |
526 | e6e5906b | pbrook | { |
527 | e6e5906b | pbrook | GOTO_TB(op_goto_tb0, PARAM1, 0);
|
528 | e6e5906b | pbrook | } |
529 | e6e5906b | pbrook | |
530 | e6e5906b | pbrook | void OPPROTO op_goto_tb1(void) |
531 | e6e5906b | pbrook | { |
532 | e6e5906b | pbrook | GOTO_TB(op_goto_tb1, PARAM1, 1);
|
533 | e6e5906b | pbrook | } |
534 | e6e5906b | pbrook | |
535 | e6e5906b | pbrook | OP(exit_tb) |
536 | e6e5906b | pbrook | { |
537 | e6e5906b | pbrook | EXIT_TB(); |
538 | e6e5906b | pbrook | } |
539 | e6e5906b | pbrook | |
540 | e6e5906b | pbrook | |
541 | e6e5906b | pbrook | /* Floating point. */
|
542 | e6e5906b | pbrook | OP(f64_to_i32) |
543 | e6e5906b | pbrook | { |
544 | e6e5906b | pbrook | set_op(PARAM1, float64_to_int32(get_opf64(PARAM2), &CPU_FP_STATUS)); |
545 | e6e5906b | pbrook | FORCE_RET(); |
546 | e6e5906b | pbrook | } |
547 | e6e5906b | pbrook | |
548 | e6e5906b | pbrook | OP(f64_to_f32) |
549 | e6e5906b | pbrook | { |
550 | e6e5906b | pbrook | union {
|
551 | e6e5906b | pbrook | float32 f; |
552 | e6e5906b | pbrook | uint32_t i; |
553 | e6e5906b | pbrook | } u; |
554 | e6e5906b | pbrook | u.f = float64_to_float32(get_opf64(PARAM2), &CPU_FP_STATUS); |
555 | e6e5906b | pbrook | set_op(PARAM1, u.i); |
556 | e6e5906b | pbrook | FORCE_RET(); |
557 | e6e5906b | pbrook | } |
558 | e6e5906b | pbrook | |
559 | e6e5906b | pbrook | OP(i32_to_f64) |
560 | e6e5906b | pbrook | { |
561 | e6e5906b | pbrook | set_opf64(PARAM1, int32_to_float64(get_op(PARAM2), &CPU_FP_STATUS)); |
562 | e6e5906b | pbrook | FORCE_RET(); |
563 | e6e5906b | pbrook | } |
564 | e6e5906b | pbrook | |
565 | e6e5906b | pbrook | OP(f32_to_f64) |
566 | e6e5906b | pbrook | { |
567 | e6e5906b | pbrook | union {
|
568 | e6e5906b | pbrook | float32 f; |
569 | e6e5906b | pbrook | uint32_t i; |
570 | e6e5906b | pbrook | } u; |
571 | e6e5906b | pbrook | u.i = get_op(PARAM2); |
572 | e6e5906b | pbrook | set_opf64(PARAM1, float32_to_float64(u.f, &CPU_FP_STATUS)); |
573 | e6e5906b | pbrook | FORCE_RET(); |
574 | e6e5906b | pbrook | } |
575 | e6e5906b | pbrook | |
576 | e6e5906b | pbrook | OP(absf64) |
577 | e6e5906b | pbrook | { |
578 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
579 | e6e5906b | pbrook | set_opf64(PARAM1, float64_abs(op0)); |
580 | e6e5906b | pbrook | FORCE_RET(); |
581 | e6e5906b | pbrook | } |
582 | e6e5906b | pbrook | |
583 | e6e5906b | pbrook | OP(chsf64) |
584 | e6e5906b | pbrook | { |
585 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
586 | e6e5906b | pbrook | set_opf64(PARAM1, float64_chs(op0)); |
587 | e6e5906b | pbrook | FORCE_RET(); |
588 | e6e5906b | pbrook | } |
589 | e6e5906b | pbrook | |
590 | e6e5906b | pbrook | OP(sqrtf64) |
591 | e6e5906b | pbrook | { |
592 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
593 | e6e5906b | pbrook | set_opf64(PARAM1, float64_sqrt(op0, &CPU_FP_STATUS)); |
594 | e6e5906b | pbrook | FORCE_RET(); |
595 | e6e5906b | pbrook | } |
596 | e6e5906b | pbrook | |
597 | e6e5906b | pbrook | OP(addf64) |
598 | e6e5906b | pbrook | { |
599 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
600 | e6e5906b | pbrook | float64 op1 = get_opf64(PARAM3); |
601 | e6e5906b | pbrook | set_opf64(PARAM1, float64_add(op0, op1, &CPU_FP_STATUS)); |
602 | e6e5906b | pbrook | FORCE_RET(); |
603 | e6e5906b | pbrook | } |
604 | e6e5906b | pbrook | |
605 | e6e5906b | pbrook | OP(subf64) |
606 | e6e5906b | pbrook | { |
607 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
608 | e6e5906b | pbrook | float64 op1 = get_opf64(PARAM3); |
609 | e6e5906b | pbrook | set_opf64(PARAM1, float64_sub(op0, op1, &CPU_FP_STATUS)); |
610 | e6e5906b | pbrook | FORCE_RET(); |
611 | e6e5906b | pbrook | } |
612 | e6e5906b | pbrook | |
613 | e6e5906b | pbrook | OP(mulf64) |
614 | e6e5906b | pbrook | { |
615 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
616 | e6e5906b | pbrook | float64 op1 = get_opf64(PARAM3); |
617 | e6e5906b | pbrook | set_opf64(PARAM1, float64_mul(op0, op1, &CPU_FP_STATUS)); |
618 | e6e5906b | pbrook | FORCE_RET(); |
619 | e6e5906b | pbrook | } |
620 | e6e5906b | pbrook | |
621 | e6e5906b | pbrook | OP(divf64) |
622 | e6e5906b | pbrook | { |
623 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
624 | e6e5906b | pbrook | float64 op1 = get_opf64(PARAM3); |
625 | e6e5906b | pbrook | set_opf64(PARAM1, float64_div(op0, op1, &CPU_FP_STATUS)); |
626 | e6e5906b | pbrook | FORCE_RET(); |
627 | e6e5906b | pbrook | } |
628 | e6e5906b | pbrook | |
629 | e6e5906b | pbrook | OP(iround_f64) |
630 | e6e5906b | pbrook | { |
631 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
632 | e6e5906b | pbrook | set_opf64(PARAM1, float64_round_to_int(op0, &CPU_FP_STATUS)); |
633 | e6e5906b | pbrook | FORCE_RET(); |
634 | e6e5906b | pbrook | } |
635 | e6e5906b | pbrook | |
636 | e6e5906b | pbrook | OP(itrunc_f64) |
637 | e6e5906b | pbrook | { |
638 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
639 | e6e5906b | pbrook | set_opf64(PARAM1, float64_trunc_to_int(op0, &CPU_FP_STATUS)); |
640 | e6e5906b | pbrook | FORCE_RET(); |
641 | e6e5906b | pbrook | } |
642 | e6e5906b | pbrook | |
643 | e6e5906b | pbrook | OP(compare_quietf64) |
644 | e6e5906b | pbrook | { |
645 | e6e5906b | pbrook | float64 op0 = get_opf64(PARAM2); |
646 | e6e5906b | pbrook | float64 op1 = get_opf64(PARAM3); |
647 | e6e5906b | pbrook | set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS)); |
648 | e6e5906b | pbrook | FORCE_RET(); |
649 | e6e5906b | pbrook | } |
650 | 0633879f | pbrook | |
651 | 0633879f | pbrook | OP(movec) |
652 | 0633879f | pbrook | { |
653 | 0633879f | pbrook | int op1 = get_op(PARAM1);
|
654 | 0633879f | pbrook | uint32_t op2 = get_op(PARAM2); |
655 | 0633879f | pbrook | helper_movec(env, op1, op2); |
656 | 0633879f | pbrook | } |
657 | 0633879f | pbrook | |
658 | 0633879f | pbrook | /* Memory access. */
|
659 | 0633879f | pbrook | |
660 | 0633879f | pbrook | #define MEMSUFFIX _raw
|
661 | 0633879f | pbrook | #include "op_mem.h" |
662 | 0633879f | pbrook | |
663 | 0633879f | pbrook | #if !defined(CONFIG_USER_ONLY)
|
664 | 0633879f | pbrook | #define MEMSUFFIX _user
|
665 | 0633879f | pbrook | #include "op_mem.h" |
666 | 0633879f | pbrook | #define MEMSUFFIX _kernel
|
667 | 0633879f | pbrook | #include "op_mem.h" |
668 | 0633879f | pbrook | #endif
|
669 | acf930aa | pbrook | |
670 | acf930aa | pbrook | /* MAC unit. */
|
671 | acf930aa | pbrook | /* TODO: The MAC instructions use 64-bit arithmetic fairly extensively.
|
672 | acf930aa | pbrook | This results in fairly large ops (and sometimes other issues) on 32-bit
|
673 | acf930aa | pbrook | hosts. Maybe move most of them into helpers. */
|
674 | acf930aa | pbrook | OP(macmuls) |
675 | acf930aa | pbrook | { |
676 | acf930aa | pbrook | uint32_t op1 = get_op(PARAM1); |
677 | acf930aa | pbrook | uint32_t op2 = get_op(PARAM2); |
678 | acf930aa | pbrook | int64_t product; |
679 | acf930aa | pbrook | int64_t res; |
680 | acf930aa | pbrook | |
681 | acf930aa | pbrook | product = (uint64_t)op1 * op2; |
682 | acf930aa | pbrook | res = (product << 24) >> 24; |
683 | acf930aa | pbrook | if (res != product) {
|
684 | acf930aa | pbrook | env->macsr |= MACSR_V; |
685 | acf930aa | pbrook | if (env->macsr & MACSR_OMC) {
|
686 | acf930aa | pbrook | /* Make sure the accumulate operation overflows. */
|
687 | acf930aa | pbrook | if (product < 0) |
688 | acf930aa | pbrook | res = ~(1ll << 50); |
689 | acf930aa | pbrook | else
|
690 | acf930aa | pbrook | res = 1ll << 50; |
691 | acf930aa | pbrook | } |
692 | acf930aa | pbrook | } |
693 | acf930aa | pbrook | env->mactmp = res; |
694 | acf930aa | pbrook | FORCE_RET(); |
695 | acf930aa | pbrook | } |
696 | acf930aa | pbrook | |
697 | acf930aa | pbrook | OP(macmulu) |
698 | acf930aa | pbrook | { |
699 | acf930aa | pbrook | uint32_t op1 = get_op(PARAM1); |
700 | acf930aa | pbrook | uint32_t op2 = get_op(PARAM2); |
701 | acf930aa | pbrook | uint64_t product; |
702 | acf930aa | pbrook | |
703 | acf930aa | pbrook | product = (uint64_t)op1 * op2; |
704 | acf930aa | pbrook | if (product & (0xffffffull << 40)) { |
705 | acf930aa | pbrook | env->macsr |= MACSR_V; |
706 | acf930aa | pbrook | if (env->macsr & MACSR_OMC) {
|
707 | acf930aa | pbrook | /* Make sure the accumulate operation overflows. */
|
708 | acf930aa | pbrook | product = 1ll << 50; |
709 | acf930aa | pbrook | } else {
|
710 | acf930aa | pbrook | product &= ((1ull << 40) - 1); |
711 | acf930aa | pbrook | } |
712 | acf930aa | pbrook | } |
713 | acf930aa | pbrook | env->mactmp = product; |
714 | acf930aa | pbrook | FORCE_RET(); |
715 | acf930aa | pbrook | } |
716 | acf930aa | pbrook | |
717 | acf930aa | pbrook | OP(macmulf) |
718 | acf930aa | pbrook | { |
719 | acf930aa | pbrook | int32_t op1 = get_op(PARAM1); |
720 | acf930aa | pbrook | int32_t op2 = get_op(PARAM2); |
721 | acf930aa | pbrook | uint64_t product; |
722 | acf930aa | pbrook | uint32_t remainder; |
723 | acf930aa | pbrook | |
724 | acf930aa | pbrook | product = (uint64_t)op1 * op2; |
725 | acf930aa | pbrook | if (env->macsr & MACSR_RT) {
|
726 | acf930aa | pbrook | remainder = product & 0xffffff;
|
727 | acf930aa | pbrook | product >>= 24;
|
728 | acf930aa | pbrook | if (remainder > 0x800000) |
729 | acf930aa | pbrook | product++; |
730 | acf930aa | pbrook | else if (remainder == 0x800000) |
731 | acf930aa | pbrook | product += (product & 1);
|
732 | acf930aa | pbrook | } else {
|
733 | acf930aa | pbrook | product >>= 24;
|
734 | acf930aa | pbrook | } |
735 | acf930aa | pbrook | env->mactmp = product; |
736 | acf930aa | pbrook | FORCE_RET(); |
737 | acf930aa | pbrook | } |
738 | acf930aa | pbrook | |
739 | acf930aa | pbrook | OP(macshl) |
740 | acf930aa | pbrook | { |
741 | acf930aa | pbrook | env->mactmp <<= 1;
|
742 | acf930aa | pbrook | } |
743 | acf930aa | pbrook | |
744 | acf930aa | pbrook | OP(macshr) |
745 | acf930aa | pbrook | { |
746 | acf930aa | pbrook | env->mactmp >>= 1;
|
747 | acf930aa | pbrook | } |
748 | acf930aa | pbrook | |
749 | acf930aa | pbrook | OP(macadd) |
750 | acf930aa | pbrook | { |
751 | acf930aa | pbrook | int acc = PARAM1;
|
752 | acf930aa | pbrook | env->macc[acc] += env->mactmp; |
753 | acf930aa | pbrook | FORCE_RET(); |
754 | acf930aa | pbrook | } |
755 | acf930aa | pbrook | |
756 | acf930aa | pbrook | OP(macsub) |
757 | acf930aa | pbrook | { |
758 | acf930aa | pbrook | int acc = PARAM1;
|
759 | acf930aa | pbrook | env->macc[acc] -= env->mactmp; |
760 | acf930aa | pbrook | FORCE_RET(); |
761 | acf930aa | pbrook | } |
762 | acf930aa | pbrook | |
763 | acf930aa | pbrook | OP(macsats) |
764 | acf930aa | pbrook | { |
765 | acf930aa | pbrook | int acc = PARAM1;
|
766 | acf930aa | pbrook | int64_t sum; |
767 | acf930aa | pbrook | int64_t result; |
768 | acf930aa | pbrook | |
769 | acf930aa | pbrook | sum = env->macc[acc]; |
770 | acf930aa | pbrook | result = (sum << 16) >> 16; |
771 | acf930aa | pbrook | if (result != sum) {
|
772 | acf930aa | pbrook | env->macsr |= MACSR_V; |
773 | acf930aa | pbrook | } |
774 | acf930aa | pbrook | if (env->macsr & MACSR_V) {
|
775 | acf930aa | pbrook | env->macsr |= MACSR_PAV0 << acc; |
776 | acf930aa | pbrook | if (env->macsr & MACSR_OMC) {
|
777 | acf930aa | pbrook | /* The result is saturated to 32 bits, despite overflow occuring
|
778 | acf930aa | pbrook | at 48 bits. Seems weird, but that's what the hardware docs
|
779 | acf930aa | pbrook | say. */
|
780 | acf930aa | pbrook | result = (result >> 63) ^ 0x7fffffff; |
781 | acf930aa | pbrook | } |
782 | acf930aa | pbrook | } |
783 | acf930aa | pbrook | env->macc[acc] = result; |
784 | acf930aa | pbrook | FORCE_RET(); |
785 | acf930aa | pbrook | } |
786 | acf930aa | pbrook | |
787 | acf930aa | pbrook | OP(macsatu) |
788 | acf930aa | pbrook | { |
789 | acf930aa | pbrook | int acc = PARAM1;
|
790 | acf930aa | pbrook | uint64_t sum; |
791 | acf930aa | pbrook | |
792 | acf930aa | pbrook | sum = env->macc[acc]; |
793 | acf930aa | pbrook | if (sum & (0xffffull << 48)) { |
794 | acf930aa | pbrook | env->macsr |= MACSR_V; |
795 | acf930aa | pbrook | } |
796 | acf930aa | pbrook | if (env->macsr & MACSR_V) {
|
797 | acf930aa | pbrook | env->macsr |= MACSR_PAV0 << acc; |
798 | acf930aa | pbrook | if (env->macsr & MACSR_OMC) {
|
799 | acf930aa | pbrook | if (sum > (1ull << 53)) |
800 | acf930aa | pbrook | sum = 0;
|
801 | acf930aa | pbrook | else
|
802 | acf930aa | pbrook | sum = (1ull << 48) - 1; |
803 | acf930aa | pbrook | } else {
|
804 | acf930aa | pbrook | sum &= ((1ull << 48) - 1); |
805 | acf930aa | pbrook | } |
806 | acf930aa | pbrook | } |
807 | acf930aa | pbrook | FORCE_RET(); |
808 | acf930aa | pbrook | } |
809 | acf930aa | pbrook | |
810 | acf930aa | pbrook | OP(macsatf) |
811 | acf930aa | pbrook | { |
812 | acf930aa | pbrook | int acc = PARAM1;
|
813 | acf930aa | pbrook | int64_t sum; |
814 | acf930aa | pbrook | int64_t result; |
815 | acf930aa | pbrook | |
816 | acf930aa | pbrook | sum = env->macc[acc]; |
817 | acf930aa | pbrook | result = (sum << 16) >> 16; |
818 | acf930aa | pbrook | if (result != sum) {
|
819 | acf930aa | pbrook | env->macsr |= MACSR_V; |
820 | acf930aa | pbrook | } |
821 | acf930aa | pbrook | if (env->macsr & MACSR_V) {
|
822 | acf930aa | pbrook | env->macsr |= MACSR_PAV0 << acc; |
823 | acf930aa | pbrook | if (env->macsr & MACSR_OMC) {
|
824 | acf930aa | pbrook | result = (result >> 63) ^ 0x7fffffffffffll; |
825 | acf930aa | pbrook | } |
826 | acf930aa | pbrook | } |
827 | acf930aa | pbrook | env->macc[acc] = result; |
828 | acf930aa | pbrook | FORCE_RET(); |
829 | acf930aa | pbrook | } |
830 | acf930aa | pbrook | |
831 | acf930aa | pbrook | OP(mac_clear_flags) |
832 | acf930aa | pbrook | { |
833 | acf930aa | pbrook | env->macsr &= ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV); |
834 | acf930aa | pbrook | } |
835 | acf930aa | pbrook | |
836 | acf930aa | pbrook | OP(mac_set_flags) |
837 | acf930aa | pbrook | { |
838 | acf930aa | pbrook | int acc = PARAM1;
|
839 | acf930aa | pbrook | uint64_t val; |
840 | acf930aa | pbrook | val = env->macc[acc]; |
841 | acf930aa | pbrook | if (val == 0) |
842 | acf930aa | pbrook | env->macsr |= MACSR_Z; |
843 | acf930aa | pbrook | else if (val & (1ull << 47)); |
844 | acf930aa | pbrook | env->macsr |= MACSR_N; |
845 | acf930aa | pbrook | if (env->macsr & (MACSR_PAV0 << acc)) {
|
846 | acf930aa | pbrook | env->macsr |= MACSR_V; |
847 | acf930aa | pbrook | } |
848 | acf930aa | pbrook | if (env->macsr & MACSR_FI) {
|
849 | acf930aa | pbrook | val = ((int64_t)val) >> 40;
|
850 | acf930aa | pbrook | if (val != 0 && val != -1) |
851 | acf930aa | pbrook | env->macsr |= MACSR_EV; |
852 | acf930aa | pbrook | } else if (env->macsr & MACSR_SU) { |
853 | acf930aa | pbrook | val = ((int64_t)val) >> 32;
|
854 | acf930aa | pbrook | if (val != 0 && val != -1) |
855 | acf930aa | pbrook | env->macsr |= MACSR_EV; |
856 | acf930aa | pbrook | } else {
|
857 | acf930aa | pbrook | if ((val >> 32) != 0) |
858 | acf930aa | pbrook | env->macsr |= MACSR_EV; |
859 | acf930aa | pbrook | } |
860 | acf930aa | pbrook | FORCE_RET(); |
861 | acf930aa | pbrook | } |
862 | acf930aa | pbrook | |
863 | acf930aa | pbrook | OP(get_macf) |
864 | acf930aa | pbrook | { |
865 | acf930aa | pbrook | int acc = PARAM2;
|
866 | acf930aa | pbrook | int64_t val; |
867 | acf930aa | pbrook | int rem;
|
868 | acf930aa | pbrook | uint32_t result; |
869 | acf930aa | pbrook | |
870 | acf930aa | pbrook | val = env->macc[acc]; |
871 | acf930aa | pbrook | if (env->macsr & MACSR_SU) {
|
872 | acf930aa | pbrook | /* 16-bit rounding. */
|
873 | acf930aa | pbrook | rem = val & 0xffffff;
|
874 | acf930aa | pbrook | val = (val >> 24) & 0xffffu; |
875 | acf930aa | pbrook | if (rem > 0x800000) |
876 | acf930aa | pbrook | val++; |
877 | acf930aa | pbrook | else if (rem == 0x800000) |
878 | acf930aa | pbrook | val += (val & 1);
|
879 | acf930aa | pbrook | } else if (env->macsr & MACSR_RT) { |
880 | acf930aa | pbrook | /* 32-bit rounding. */
|
881 | acf930aa | pbrook | rem = val & 0xff;
|
882 | acf930aa | pbrook | val >>= 8;
|
883 | acf930aa | pbrook | if (rem > 0x80) |
884 | acf930aa | pbrook | val++; |
885 | acf930aa | pbrook | else if (rem == 0x80) |
886 | acf930aa | pbrook | val += (val & 1);
|
887 | acf930aa | pbrook | } else {
|
888 | acf930aa | pbrook | /* No rounding. */
|
889 | acf930aa | pbrook | val >>= 8;
|
890 | acf930aa | pbrook | } |
891 | acf930aa | pbrook | if (env->macsr & MACSR_OMC) {
|
892 | acf930aa | pbrook | /* Saturate. */
|
893 | acf930aa | pbrook | if (env->macsr & MACSR_SU) {
|
894 | acf930aa | pbrook | if (val != (uint16_t) val) {
|
895 | acf930aa | pbrook | result = ((val >> 63) ^ 0x7fff) & 0xffff; |
896 | acf930aa | pbrook | } else {
|
897 | acf930aa | pbrook | result = val & 0xffff;
|
898 | acf930aa | pbrook | } |
899 | acf930aa | pbrook | } else {
|
900 | acf930aa | pbrook | if (val != (uint32_t)val) {
|
901 | acf930aa | pbrook | result = ((uint32_t)(val >> 63) & 0x7fffffff); |
902 | acf930aa | pbrook | } else {
|
903 | acf930aa | pbrook | result = (uint32_t)val; |
904 | acf930aa | pbrook | } |
905 | acf930aa | pbrook | } |
906 | acf930aa | pbrook | } else {
|
907 | acf930aa | pbrook | /* No saturation. */
|
908 | acf930aa | pbrook | if (env->macsr & MACSR_SU) {
|
909 | acf930aa | pbrook | result = val & 0xffff;
|
910 | acf930aa | pbrook | } else {
|
911 | acf930aa | pbrook | result = (uint32_t)val; |
912 | acf930aa | pbrook | } |
913 | acf930aa | pbrook | } |
914 | acf930aa | pbrook | set_op(PARAM1, result); |
915 | acf930aa | pbrook | FORCE_RET(); |
916 | acf930aa | pbrook | } |
917 | acf930aa | pbrook | |
918 | acf930aa | pbrook | OP(get_maci) |
919 | acf930aa | pbrook | { |
920 | acf930aa | pbrook | int acc = PARAM2;
|
921 | acf930aa | pbrook | set_op(PARAM1, (uint32_t)env->macc[acc]); |
922 | acf930aa | pbrook | FORCE_RET(); |
923 | acf930aa | pbrook | } |
924 | acf930aa | pbrook | |
925 | acf930aa | pbrook | OP(get_macs) |
926 | acf930aa | pbrook | { |
927 | acf930aa | pbrook | int acc = PARAM2;
|
928 | acf930aa | pbrook | int64_t val = env->macc[acc]; |
929 | acf930aa | pbrook | uint32_t result; |
930 | acf930aa | pbrook | if (val == (int32_t)val) {
|
931 | acf930aa | pbrook | result = (int32_t)val; |
932 | acf930aa | pbrook | } else {
|
933 | acf930aa | pbrook | result = (val >> 61) ^ 0x7fffffff; |
934 | acf930aa | pbrook | } |
935 | acf930aa | pbrook | set_op(PARAM1, result); |
936 | acf930aa | pbrook | FORCE_RET(); |
937 | acf930aa | pbrook | } |
938 | acf930aa | pbrook | |
939 | acf930aa | pbrook | OP(get_macu) |
940 | acf930aa | pbrook | { |
941 | acf930aa | pbrook | int acc = PARAM2;
|
942 | acf930aa | pbrook | uint64_t val = env->macc[acc]; |
943 | acf930aa | pbrook | uint32_t result; |
944 | acf930aa | pbrook | if ((val >> 32) == 0) { |
945 | acf930aa | pbrook | result = (uint32_t)val; |
946 | acf930aa | pbrook | } else {
|
947 | acf930aa | pbrook | result = 0xffffffffu;
|
948 | acf930aa | pbrook | } |
949 | acf930aa | pbrook | set_op(PARAM1, result); |
950 | acf930aa | pbrook | FORCE_RET(); |
951 | acf930aa | pbrook | } |
952 | acf930aa | pbrook | |
953 | acf930aa | pbrook | OP(clear_mac) |
954 | acf930aa | pbrook | { |
955 | acf930aa | pbrook | int acc = PARAM1;
|
956 | acf930aa | pbrook | |
957 | acf930aa | pbrook | env->macc[acc] = 0;
|
958 | acf930aa | pbrook | env->macsr &= ~(MACSR_PAV0 << acc); |
959 | acf930aa | pbrook | FORCE_RET(); |
960 | acf930aa | pbrook | } |
961 | acf930aa | pbrook | |
962 | acf930aa | pbrook | OP(move_mac) |
963 | acf930aa | pbrook | { |
964 | acf930aa | pbrook | int dest = PARAM1;
|
965 | acf930aa | pbrook | int src = PARAM2;
|
966 | acf930aa | pbrook | uint32_t mask; |
967 | acf930aa | pbrook | env->macc[dest] = env->macc[src]; |
968 | acf930aa | pbrook | mask = MACSR_PAV0 << dest; |
969 | acf930aa | pbrook | if (env->macsr & (MACSR_PAV0 << src))
|
970 | acf930aa | pbrook | env->macsr |= mask; |
971 | acf930aa | pbrook | else
|
972 | acf930aa | pbrook | env->macsr &= ~mask; |
973 | acf930aa | pbrook | FORCE_RET(); |
974 | acf930aa | pbrook | } |
975 | acf930aa | pbrook | |
976 | acf930aa | pbrook | OP(get_mac_extf) |
977 | acf930aa | pbrook | { |
978 | acf930aa | pbrook | uint32_t val; |
979 | acf930aa | pbrook | int acc = PARAM2;
|
980 | acf930aa | pbrook | val = env->macc[acc] & 0x00ff;
|
981 | acf930aa | pbrook | val = (env->macc[acc] >> 32) & 0xff00; |
982 | acf930aa | pbrook | val |= (env->macc[acc + 1] << 16) & 0x00ff0000; |
983 | acf930aa | pbrook | val |= (env->macc[acc + 1] >> 16) & 0xff000000; |
984 | acf930aa | pbrook | set_op(PARAM1, val); |
985 | acf930aa | pbrook | FORCE_RET(); |
986 | acf930aa | pbrook | } |
987 | acf930aa | pbrook | |
988 | acf930aa | pbrook | OP(get_mac_exti) |
989 | acf930aa | pbrook | { |
990 | acf930aa | pbrook | uint32_t val; |
991 | acf930aa | pbrook | int acc = PARAM2;
|
992 | acf930aa | pbrook | val = (env->macc[acc] >> 32) & 0xffff; |
993 | acf930aa | pbrook | val |= (env->macc[acc + 1] >> 16) & 0xffff0000; |
994 | acf930aa | pbrook | set_op(PARAM1, val); |
995 | acf930aa | pbrook | FORCE_RET(); |
996 | acf930aa | pbrook | } |
997 | acf930aa | pbrook | |
998 | acf930aa | pbrook | OP(set_macf) |
999 | acf930aa | pbrook | { |
1000 | acf930aa | pbrook | int acc = PARAM2;
|
1001 | acf930aa | pbrook | int32_t val = get_op(PARAM1); |
1002 | acf930aa | pbrook | env->macc[acc] = ((int64_t)val) << 8;
|
1003 | acf930aa | pbrook | env->macsr &= ~(MACSR_PAV0 << acc); |
1004 | acf930aa | pbrook | FORCE_RET(); |
1005 | acf930aa | pbrook | } |
1006 | acf930aa | pbrook | |
1007 | acf930aa | pbrook | OP(set_macs) |
1008 | acf930aa | pbrook | { |
1009 | acf930aa | pbrook | int acc = PARAM2;
|
1010 | acf930aa | pbrook | int32_t val = get_op(PARAM1); |
1011 | acf930aa | pbrook | env->macc[acc] = val; |
1012 | acf930aa | pbrook | env->macsr &= ~(MACSR_PAV0 << acc); |
1013 | acf930aa | pbrook | FORCE_RET(); |
1014 | acf930aa | pbrook | } |
1015 | acf930aa | pbrook | |
1016 | acf930aa | pbrook | OP(set_macu) |
1017 | acf930aa | pbrook | { |
1018 | acf930aa | pbrook | int acc = PARAM2;
|
1019 | acf930aa | pbrook | uint32_t val = get_op(PARAM1); |
1020 | acf930aa | pbrook | env->macc[acc] = val; |
1021 | acf930aa | pbrook | env->macsr &= ~(MACSR_PAV0 << acc); |
1022 | acf930aa | pbrook | FORCE_RET(); |
1023 | acf930aa | pbrook | } |
1024 | acf930aa | pbrook | |
1025 | acf930aa | pbrook | OP(set_mac_extf) |
1026 | acf930aa | pbrook | { |
1027 | acf930aa | pbrook | int acc = PARAM2;
|
1028 | acf930aa | pbrook | int32_t val = get_op(PARAM1); |
1029 | acf930aa | pbrook | int64_t res; |
1030 | acf930aa | pbrook | int32_t tmp; |
1031 | acf930aa | pbrook | res = env->macc[acc] & 0xffffffff00ull;
|
1032 | acf930aa | pbrook | tmp = (int16_t)(val & 0xff00);
|
1033 | acf930aa | pbrook | res |= ((int64_t)tmp) << 32;
|
1034 | acf930aa | pbrook | res |= val & 0xff;
|
1035 | acf930aa | pbrook | env->macc[acc] = res; |
1036 | acf930aa | pbrook | res = env->macc[acc + 1] & 0xffffffff00ull; |
1037 | acf930aa | pbrook | tmp = (val & 0xff000000);
|
1038 | acf930aa | pbrook | res |= ((int64_t)tmp) << 16;
|
1039 | acf930aa | pbrook | res |= (val >> 16) & 0xff; |
1040 | acf930aa | pbrook | env->macc[acc + 1] = res;
|
1041 | acf930aa | pbrook | } |
1042 | acf930aa | pbrook | |
1043 | acf930aa | pbrook | OP(set_mac_exts) |
1044 | acf930aa | pbrook | { |
1045 | acf930aa | pbrook | int acc = PARAM2;
|
1046 | acf930aa | pbrook | int32_t val = get_op(PARAM1); |
1047 | acf930aa | pbrook | int64_t res; |
1048 | acf930aa | pbrook | int32_t tmp; |
1049 | acf930aa | pbrook | res = (uint32_t)env->macc[acc]; |
1050 | acf930aa | pbrook | tmp = (int16_t)val; |
1051 | acf930aa | pbrook | res |= ((int64_t)tmp) << 32;
|
1052 | acf930aa | pbrook | env->macc[acc] = res; |
1053 | acf930aa | pbrook | res = (uint32_t)env->macc[acc + 1];
|
1054 | acf930aa | pbrook | tmp = val & 0xffff0000;
|
1055 | acf930aa | pbrook | res |= (int64_t)tmp << 16;
|
1056 | acf930aa | pbrook | env->macc[acc + 1] = res;
|
1057 | acf930aa | pbrook | } |
1058 | acf930aa | pbrook | |
1059 | acf930aa | pbrook | OP(set_mac_extu) |
1060 | acf930aa | pbrook | { |
1061 | acf930aa | pbrook | int acc = PARAM2;
|
1062 | acf930aa | pbrook | int32_t val = get_op(PARAM1); |
1063 | acf930aa | pbrook | uint64_t res; |
1064 | acf930aa | pbrook | res = (uint32_t)env->macc[acc]; |
1065 | acf930aa | pbrook | res |= ((uint64_t)(val & 0xffff)) << 32; |
1066 | acf930aa | pbrook | env->macc[acc] = res; |
1067 | acf930aa | pbrook | res = (uint32_t)env->macc[acc + 1];
|
1068 | acf930aa | pbrook | res |= (uint64_t)(val & 0xffff0000) << 16; |
1069 | acf930aa | pbrook | env->macc[acc + 1] = res;
|
1070 | acf930aa | pbrook | } |
1071 | acf930aa | pbrook | |
1072 | acf930aa | pbrook | OP(set_macsr) |
1073 | acf930aa | pbrook | { |
1074 | acf930aa | pbrook | m68k_set_macsr(env, get_op(PARAM1)); |
1075 | acf930aa | pbrook | } |