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