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