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