]> git.proxmox.com Git - mirror_qemu.git/blame - target-m68k/helper.c
cpu: Move exception_index field from CPU_COMMON to CPUState
[mirror_qemu.git] / target-m68k / helper.c
CommitLineData
e6e5906b
PB
1/*
2 * m68k op helpers
5fafdf24 3 *
0633879f 4 * Copyright (c) 2006-2007 CodeSourcery
e6e5906b
PB
5 * Written by Paul Brook
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
8167ee88 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
e6e5906b
PB
19 */
20
e6e5906b 21#include "cpu.h"
022c62cb 22#include "exec/gdbstub.h"
e6e5906b 23
e5e84d22 24#include "helper.h"
e1f3808e
PB
25
26#define SIGNBIT (1u << 31)
27
11150915
AF
28/* Sort alphabetically, except for "any". */
29static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
009a4356 30{
11150915
AF
31 ObjectClass *class_a = (ObjectClass *)a;
32 ObjectClass *class_b = (ObjectClass *)b;
33 const char *name_a, *name_b;
34
35 name_a = object_class_get_name(class_a);
36 name_b = object_class_get_name(class_b);
7a9f812b 37 if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
11150915 38 return 1;
7a9f812b 39 } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
11150915
AF
40 return -1;
41 } else {
42 return strcasecmp(name_a, name_b);
009a4356
LV
43 }
44}
45
11150915
AF
46static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
47{
48 ObjectClass *c = data;
92a31361 49 CPUListState *s = user_data;
7a9f812b
AF
50 const char *typename;
51 char *name;
11150915 52
7a9f812b
AF
53 typename = object_class_get_name(c);
54 name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
11150915 55 (*s->cpu_fprintf)(s->file, "%s\n",
7a9f812b
AF
56 name);
57 g_free(name);
11150915
AF
58}
59
60void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
61{
92a31361 62 CPUListState s = {
11150915
AF
63 .file = f,
64 .cpu_fprintf = cpu_fprintf,
65 };
66 GSList *list;
67
68 list = object_class_get_list(TYPE_M68K_CPU, false);
69 list = g_slist_sort(list, m68k_cpu_list_compare);
70 g_slist_foreach(list, m68k_cpu_list_entry, &s);
71 g_slist_free(list);
72}
73
2b3e3cfe 74static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
56aebc89
PB
75{
76 if (n < 8) {
77 stfq_p(mem_buf, env->fregs[n]);
78 return 8;
79 }
80 if (n < 11) {
81 /* FP control registers (not implemented) */
82 memset(mem_buf, 0, 4);
83 return 4;
84 }
85 return 0;
86}
87
2b3e3cfe 88static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
56aebc89
PB
89{
90 if (n < 8) {
91 env->fregs[n] = ldfq_p(mem_buf);
92 return 8;
93 }
94 if (n < 11) {
95 /* FP control registers (not implemented) */
96 return 4;
97 }
98 return 0;
99}
100
c7937d9f 101M68kCPU *cpu_m68k_init(const char *cpu_model)
aaed909a 102{
b9e7a234 103 M68kCPU *cpu;
aaed909a 104 CPUM68KState *env;
bc5b2da3 105 ObjectClass *oc;
aaed909a 106
bc5b2da3
AF
107 oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model);
108 if (oc == NULL) {
11150915
AF
109 return NULL;
110 }
bc5b2da3 111 cpu = M68K_CPU(object_new(object_class_get_name(oc)));
b9e7a234 112 env = &cpu->env;
01ba9816 113
11150915 114 register_m68k_insns(env);
6d1bbc62
AF
115
116 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
117
c7937d9f 118 return cpu;
6d1bbc62
AF
119}
120
121void m68k_cpu_init_gdb(M68kCPU *cpu)
122{
22169d41 123 CPUState *cs = CPU(cpu);
6d1bbc62
AF
124 CPUM68KState *env = &cpu->env;
125
11150915 126 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
22169d41 127 gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg,
11150915 128 11, "cf-fp.xml", 18);
aaed909a 129 }
11150915 130 /* TODO: Add [E]MAC registers. */
aaed909a 131}
0402f767 132
e6e5906b
PB
133void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
134{
135 int flags;
136 uint32_t src;
137 uint32_t dest;
138 uint32_t tmp;
139
140#define HIGHBIT 0x80000000u
141
142#define SET_NZ(x) do { \
143 if ((x) == 0) \
144 flags |= CCF_Z; \
145 else if ((int32_t)(x) < 0) \
146 flags |= CCF_N; \
147 } while (0)
148
149#define SET_FLAGS_SUB(type, utype) do { \
150 SET_NZ((type)dest); \
151 tmp = dest + src; \
152 if ((utype) tmp < (utype) src) \
153 flags |= CCF_C; \
154 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
155 flags |= CCF_V; \
156 } while (0)
157
158 flags = 0;
159 src = env->cc_src;
160 dest = env->cc_dest;
161 switch (cc_op) {
162 case CC_OP_FLAGS:
163 flags = dest;
164 break;
165 case CC_OP_LOGIC:
166 SET_NZ(dest);
167 break;
168 case CC_OP_ADD:
169 SET_NZ(dest);
170 if (dest < src)
171 flags |= CCF_C;
172 tmp = dest - src;
173 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
174 flags |= CCF_V;
175 break;
176 case CC_OP_SUB:
177 SET_FLAGS_SUB(int32_t, uint32_t);
178 break;
179 case CC_OP_CMPB:
180 SET_FLAGS_SUB(int8_t, uint8_t);
181 break;
182 case CC_OP_CMPW:
183 SET_FLAGS_SUB(int16_t, uint16_t);
184 break;
185 case CC_OP_ADDX:
186 SET_NZ(dest);
187 if (dest <= src)
188 flags |= CCF_C;
189 tmp = dest - src - 1;
190 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
191 flags |= CCF_V;
192 break;
193 case CC_OP_SUBX:
194 SET_NZ(dest);
195 tmp = dest + src + 1;
196 if (tmp <= src)
197 flags |= CCF_C;
198 if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
199 flags |= CCF_V;
200 break;
e1f3808e
PB
201 case CC_OP_SHIFT:
202 SET_NZ(dest);
203 if (src)
e6e5906b
PB
204 flags |= CCF_C;
205 break;
206 default:
207 cpu_abort(env, "Bad CC_OP %d", cc_op);
208 }
209 env->cc_op = CC_OP_FLAGS;
210 env->cc_dest = flags;
211}
212
e1f3808e 213void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
0633879f
PB
214{
215 switch (reg) {
216 case 0x02: /* CACR */
20dcee94
PB
217 env->cacr = val;
218 m68k_switch_sp(env);
219 break;
220 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
221 /* TODO: Implement Access Control Registers. */
0633879f
PB
222 break;
223 case 0x801: /* VBR */
224 env->vbr = val;
225 break;
226 /* TODO: Implement control registers. */
227 default:
228 cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
229 reg, val);
230 }
231}
232
e1f3808e 233void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
acf930aa
PB
234{
235 uint32_t acc;
236 int8_t exthigh;
237 uint8_t extlow;
238 uint64_t regval;
239 int i;
240 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
241 for (i = 0; i < 4; i++) {
242 regval = env->macc[i];
243 exthigh = regval >> 40;
244 if (env->macsr & MACSR_FI) {
245 acc = regval >> 8;
246 extlow = regval;
247 } else {
248 acc = regval;
249 extlow = regval >> 32;
250 }
251 if (env->macsr & MACSR_FI) {
252 regval = (((uint64_t)acc) << 8) | extlow;
253 regval |= ((int64_t)exthigh) << 40;
254 } else if (env->macsr & MACSR_SU) {
255 regval = acc | (((int64_t)extlow) << 32);
256 regval |= ((int64_t)exthigh) << 40;
257 } else {
258 regval = acc | (((uint64_t)extlow) << 32);
259 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
260 }
261 env->macc[i] = regval;
262 }
263 }
264 env->macsr = val;
265}
266
20dcee94
PB
267void m68k_switch_sp(CPUM68KState *env)
268{
269 int new_sp;
270
271 env->sp[env->current_sp] = env->aregs[7];
272 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
273 ? M68K_SSP : M68K_USP;
274 env->aregs[7] = env->sp[new_sp];
275 env->current_sp = new_sp;
276}
277
5fafdf24 278#if defined(CONFIG_USER_ONLY)
0633879f 279
7510454e
AF
280int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
281 int mmu_idx)
0633879f 282{
7510454e
AF
283 M68kCPU *cpu = M68K_CPU(cs);
284
27103424 285 cs->exception_index = EXCP_ACCESS;
7510454e 286 cpu->env.mmu.ar = address;
0633879f
PB
287 return 1;
288}
289
290#else
291
4fcc562b
PB
292/* MMU */
293
294/* TODO: This will need fixing once the MMU is implemented. */
00b941e5 295hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
4fcc562b
PB
296{
297 return addr;
298}
299
7510454e
AF
300int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
301 int mmu_idx)
0633879f 302{
7510454e 303 M68kCPU *cpu = M68K_CPU(cs);
0633879f
PB
304 int prot;
305
306 address &= TARGET_PAGE_MASK;
d4c430a8 307 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
7510454e 308 tlb_set_page(&cpu->env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
d4c430a8 309 return 0;
0633879f
PB
310}
311
312/* Notify CPU of a pending interrupt. Prioritization and vectoring should
313 be handled by the interrupt controller. Real hardware only requests
314 the vector when the interrupt is acknowledged by the CPU. For
315 simplicitly we calculate it when the interrupt is signalled. */
cb3fb38e 316void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
0633879f 317{
d8ed887b 318 CPUState *cs = CPU(cpu);
cb3fb38e
AF
319 CPUM68KState *env = &cpu->env;
320
0633879f
PB
321 env->pending_level = level;
322 env->pending_vector = vector;
d8ed887b 323 if (level) {
c3affe56 324 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
d8ed887b
AF
325 } else {
326 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
327 }
0633879f
PB
328}
329
330#endif
e1f3808e
PB
331
332uint32_t HELPER(bitrev)(uint32_t x)
333{
334 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
335 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
336 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
337 return bswap32(x);
338}
339
340uint32_t HELPER(ff1)(uint32_t x)
341{
342 int n;
343 for (n = 32; x; n--)
344 x >>= 1;
345 return n;
346}
347
348uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
349{
350 /* The result has the opposite sign to the original value. */
351 if (ccr & CCF_V)
352 val = (((int32_t)val) >> 31) ^ SIGNBIT;
353 return val;
354}
355
2b3e3cfe 356uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
357{
358 uint32_t res;
359 uint32_t old_flags;
360
361 old_flags = env->cc_dest;
362 if (env->cc_x) {
363 env->cc_x = (op1 <= op2);
364 env->cc_op = CC_OP_SUBX;
365 res = op1 - (op2 + 1);
366 } else {
367 env->cc_x = (op1 < op2);
368 env->cc_op = CC_OP_SUB;
369 res = op1 - op2;
370 }
371 env->cc_dest = res;
372 env->cc_src = op2;
373 cpu_m68k_flush_flags(env, env->cc_op);
374 /* !Z is sticky. */
375 env->cc_dest &= (old_flags | ~CCF_Z);
376 return res;
377}
378
2b3e3cfe 379uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
380{
381 uint32_t res;
382 uint32_t old_flags;
383
384 old_flags = env->cc_dest;
385 if (env->cc_x) {
386 res = op1 + op2 + 1;
387 env->cc_x = (res <= op2);
388 env->cc_op = CC_OP_ADDX;
389 } else {
390 res = op1 + op2;
391 env->cc_x = (res < op2);
392 env->cc_op = CC_OP_ADD;
393 }
394 env->cc_dest = res;
395 env->cc_src = op2;
396 cpu_m68k_flush_flags(env, env->cc_op);
397 /* !Z is sticky. */
398 env->cc_dest &= (old_flags | ~CCF_Z);
399 return res;
400}
401
402uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
403{
404 return a < b;
405}
406
2b3e3cfe 407void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
e1f3808e
PB
408{
409 env->sr = val & 0xffff;
410 m68k_switch_sp(env);
411}
412
2b3e3cfe 413uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e
PB
414{
415 uint32_t result;
416 uint32_t cf;
417
418 shift &= 63;
419 if (shift == 0) {
420 result = val;
421 cf = env->cc_src & CCF_C;
422 } else if (shift < 32) {
423 result = val << shift;
424 cf = (val >> (32 - shift)) & 1;
425 } else if (shift == 32) {
426 result = 0;
427 cf = val & 1;
428 } else /* shift > 32 */ {
429 result = 0;
430 cf = 0;
431 }
432 env->cc_src = cf;
433 env->cc_x = (cf != 0);
434 env->cc_dest = result;
435 return result;
436}
437
2b3e3cfe 438uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e
PB
439{
440 uint32_t result;
441 uint32_t cf;
442
443 shift &= 63;
444 if (shift == 0) {
445 result = val;
446 cf = env->cc_src & CCF_C;
447 } else if (shift < 32) {
448 result = val >> shift;
449 cf = (val >> (shift - 1)) & 1;
450 } else if (shift == 32) {
451 result = 0;
452 cf = val >> 31;
453 } else /* shift > 32 */ {
454 result = 0;
455 cf = 0;
456 }
457 env->cc_src = cf;
458 env->cc_x = (cf != 0);
459 env->cc_dest = result;
460 return result;
461}
462
2b3e3cfe 463uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e
PB
464{
465 uint32_t result;
466 uint32_t cf;
467
468 shift &= 63;
469 if (shift == 0) {
470 result = val;
471 cf = (env->cc_src & CCF_C) != 0;
472 } else if (shift < 32) {
473 result = (int32_t)val >> shift;
474 cf = (val >> (shift - 1)) & 1;
475 } else /* shift >= 32 */ {
476 result = (int32_t)val >> 31;
477 cf = val >> 31;
478 }
479 env->cc_src = cf;
480 env->cc_x = cf;
481 env->cc_dest = result;
482 return result;
483}
484
485/* FPU helpers. */
2b3e3cfe 486uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
e1f3808e
PB
487{
488 return float64_to_int32(val, &env->fp_status);
489}
490
2b3e3cfe 491float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
e1f3808e
PB
492{
493 return float64_to_float32(val, &env->fp_status);
494}
495
2b3e3cfe 496float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
e1f3808e
PB
497{
498 return int32_to_float64(val, &env->fp_status);
499}
500
2b3e3cfe 501float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
e1f3808e
PB
502{
503 return float32_to_float64(val, &env->fp_status);
504}
505
2b3e3cfe 506float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
507{
508 return float64_round_to_int(val, &env->fp_status);
509}
510
2b3e3cfe 511float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
512{
513 return float64_trunc_to_int(val, &env->fp_status);
514}
515
2b3e3cfe 516float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
517{
518 return float64_sqrt(val, &env->fp_status);
519}
520
521float64 HELPER(abs_f64)(float64 val)
522{
523 return float64_abs(val);
524}
525
526float64 HELPER(chs_f64)(float64 val)
527{
528 return float64_chs(val);
529}
530
2b3e3cfe 531float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
532{
533 return float64_add(a, b, &env->fp_status);
534}
535
2b3e3cfe 536float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
537{
538 return float64_sub(a, b, &env->fp_status);
539}
540
2b3e3cfe 541float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
542{
543 return float64_mul(a, b, &env->fp_status);
544}
545
2b3e3cfe 546float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
547{
548 return float64_div(a, b, &env->fp_status);
549}
550
2b3e3cfe 551float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
552{
553 /* ??? This may incorrectly raise exceptions. */
554 /* ??? Should flush denormals to zero. */
555 float64 res;
556 res = float64_sub(a, b, &env->fp_status);
18569871 557 if (float64_is_quiet_nan(res)) {
e1f3808e 558 /* +/-inf compares equal against itself, but sub returns nan. */
18569871
PM
559 if (!float64_is_quiet_nan(a)
560 && !float64_is_quiet_nan(b)) {
e1f3808e
PB
561 res = float64_zero;
562 if (float64_lt_quiet(a, res, &env->fp_status))
563 res = float64_chs(res);
564 }
565 }
566 return res;
567}
568
2b3e3cfe 569uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
570{
571 return float64_compare_quiet(val, float64_zero, &env->fp_status);
572}
573
574/* MAC unit. */
575/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
576 take values, others take register numbers and manipulate the contents
577 in-place. */
2b3e3cfe 578void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
e1f3808e
PB
579{
580 uint32_t mask;
581 env->macc[dest] = env->macc[src];
582 mask = MACSR_PAV0 << dest;
583 if (env->macsr & (MACSR_PAV0 << src))
584 env->macsr |= mask;
585 else
586 env->macsr &= ~mask;
587}
588
2b3e3cfe 589uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
590{
591 int64_t product;
592 int64_t res;
593
594 product = (uint64_t)op1 * op2;
595 res = (product << 24) >> 24;
596 if (res != product) {
597 env->macsr |= MACSR_V;
598 if (env->macsr & MACSR_OMC) {
599 /* Make sure the accumulate operation overflows. */
600 if (product < 0)
601 res = ~(1ll << 50);
602 else
603 res = 1ll << 50;
604 }
605 }
606 return res;
607}
608
2b3e3cfe 609uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
610{
611 uint64_t product;
612
613 product = (uint64_t)op1 * op2;
614 if (product & (0xffffffull << 40)) {
615 env->macsr |= MACSR_V;
616 if (env->macsr & MACSR_OMC) {
617 /* Make sure the accumulate operation overflows. */
618 product = 1ll << 50;
619 } else {
620 product &= ((1ull << 40) - 1);
621 }
622 }
623 return product;
624}
625
2b3e3cfe 626uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
627{
628 uint64_t product;
629 uint32_t remainder;
630
631 product = (uint64_t)op1 * op2;
632 if (env->macsr & MACSR_RT) {
633 remainder = product & 0xffffff;
634 product >>= 24;
635 if (remainder > 0x800000)
636 product++;
637 else if (remainder == 0x800000)
638 product += (product & 1);
639 } else {
640 product >>= 24;
641 }
642 return product;
643}
644
2b3e3cfe 645void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
646{
647 int64_t tmp;
648 int64_t result;
649 tmp = env->macc[acc];
650 result = ((tmp << 16) >> 16);
651 if (result != tmp) {
652 env->macsr |= MACSR_V;
653 }
654 if (env->macsr & MACSR_V) {
655 env->macsr |= MACSR_PAV0 << acc;
656 if (env->macsr & MACSR_OMC) {
a1c7273b 657 /* The result is saturated to 32 bits, despite overflow occurring
e1f3808e
PB
658 at 48 bits. Seems weird, but that's what the hardware docs
659 say. */
660 result = (result >> 63) ^ 0x7fffffff;
661 }
662 }
663 env->macc[acc] = result;
664}
665
2b3e3cfe 666void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
667{
668 uint64_t val;
669
670 val = env->macc[acc];
671 if (val & (0xffffull << 48)) {
672 env->macsr |= MACSR_V;
673 }
674 if (env->macsr & MACSR_V) {
675 env->macsr |= MACSR_PAV0 << acc;
676 if (env->macsr & MACSR_OMC) {
677 if (val > (1ull << 53))
678 val = 0;
679 else
680 val = (1ull << 48) - 1;
681 } else {
682 val &= ((1ull << 48) - 1);
683 }
684 }
685 env->macc[acc] = val;
686}
687
2b3e3cfe 688void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
689{
690 int64_t sum;
691 int64_t result;
692
693 sum = env->macc[acc];
694 result = (sum << 16) >> 16;
695 if (result != sum) {
696 env->macsr |= MACSR_V;
697 }
698 if (env->macsr & MACSR_V) {
699 env->macsr |= MACSR_PAV0 << acc;
700 if (env->macsr & MACSR_OMC) {
701 result = (result >> 63) ^ 0x7fffffffffffll;
702 }
703 }
704 env->macc[acc] = result;
705}
706
2b3e3cfe 707void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
708{
709 uint64_t val;
710 val = env->macc[acc];
c4162574 711 if (val == 0) {
e1f3808e 712 env->macsr |= MACSR_Z;
c4162574 713 } else if (val & (1ull << 47)) {
e1f3808e 714 env->macsr |= MACSR_N;
c4162574 715 }
e1f3808e
PB
716 if (env->macsr & (MACSR_PAV0 << acc)) {
717 env->macsr |= MACSR_V;
718 }
719 if (env->macsr & MACSR_FI) {
720 val = ((int64_t)val) >> 40;
721 if (val != 0 && val != -1)
722 env->macsr |= MACSR_EV;
723 } else if (env->macsr & MACSR_SU) {
724 val = ((int64_t)val) >> 32;
725 if (val != 0 && val != -1)
726 env->macsr |= MACSR_EV;
727 } else {
728 if ((val >> 32) != 0)
729 env->macsr |= MACSR_EV;
730 }
731}
732
2b3e3cfe 733void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
e1f3808e
PB
734{
735 cpu_m68k_flush_flags(env, cc_op);
736}
737
2b3e3cfe 738uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
e1f3808e
PB
739{
740 int rem;
741 uint32_t result;
742
743 if (env->macsr & MACSR_SU) {
744 /* 16-bit rounding. */
745 rem = val & 0xffffff;
746 val = (val >> 24) & 0xffffu;
747 if (rem > 0x800000)
748 val++;
749 else if (rem == 0x800000)
750 val += (val & 1);
751 } else if (env->macsr & MACSR_RT) {
752 /* 32-bit rounding. */
753 rem = val & 0xff;
754 val >>= 8;
755 if (rem > 0x80)
756 val++;
757 else if (rem == 0x80)
758 val += (val & 1);
759 } else {
760 /* No rounding. */
761 val >>= 8;
762 }
763 if (env->macsr & MACSR_OMC) {
764 /* Saturate. */
765 if (env->macsr & MACSR_SU) {
766 if (val != (uint16_t) val) {
767 result = ((val >> 63) ^ 0x7fff) & 0xffff;
768 } else {
769 result = val & 0xffff;
770 }
771 } else {
772 if (val != (uint32_t)val) {
773 result = ((uint32_t)(val >> 63) & 0x7fffffff);
774 } else {
775 result = (uint32_t)val;
776 }
777 }
778 } else {
779 /* No saturation. */
780 if (env->macsr & MACSR_SU) {
781 result = val & 0xffff;
782 } else {
783 result = (uint32_t)val;
784 }
785 }
786 return result;
787}
788
789uint32_t HELPER(get_macs)(uint64_t val)
790{
791 if (val == (int32_t)val) {
792 return (int32_t)val;
793 } else {
794 return (val >> 61) ^ ~SIGNBIT;
795 }
796}
797
798uint32_t HELPER(get_macu)(uint64_t val)
799{
800 if ((val >> 32) == 0) {
801 return (uint32_t)val;
802 } else {
803 return 0xffffffffu;
804 }
805}
806
2b3e3cfe 807uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
808{
809 uint32_t val;
810 val = env->macc[acc] & 0x00ff;
811 val = (env->macc[acc] >> 32) & 0xff00;
812 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
813 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
814 return val;
815}
816
2b3e3cfe 817uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
818{
819 uint32_t val;
820 val = (env->macc[acc] >> 32) & 0xffff;
821 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
822 return val;
823}
824
2b3e3cfe 825void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
826{
827 int64_t res;
828 int32_t tmp;
829 res = env->macc[acc] & 0xffffffff00ull;
830 tmp = (int16_t)(val & 0xff00);
831 res |= ((int64_t)tmp) << 32;
832 res |= val & 0xff;
833 env->macc[acc] = res;
834 res = env->macc[acc + 1] & 0xffffffff00ull;
835 tmp = (val & 0xff000000);
836 res |= ((int64_t)tmp) << 16;
837 res |= (val >> 16) & 0xff;
838 env->macc[acc + 1] = res;
839}
840
2b3e3cfe 841void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
842{
843 int64_t res;
844 int32_t tmp;
845 res = (uint32_t)env->macc[acc];
846 tmp = (int16_t)val;
847 res |= ((int64_t)tmp) << 32;
848 env->macc[acc] = res;
849 res = (uint32_t)env->macc[acc + 1];
850 tmp = val & 0xffff0000;
851 res |= (int64_t)tmp << 16;
852 env->macc[acc + 1] = res;
853}
854
2b3e3cfe 855void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
856{
857 uint64_t res;
858 res = (uint32_t)env->macc[acc];
859 res |= ((uint64_t)(val & 0xffff)) << 32;
860 env->macc[acc] = res;
861 res = (uint32_t)env->macc[acc + 1];
862 res |= (uint64_t)(val & 0xffff0000) << 16;
863 env->macc[acc + 1] = res;
864}