]> Git Repo - qemu.git/blob - target-m68k/helper.c
Merge remote-tracking branch 'awilliam/tags/vfio-pci-for-qemu-20131010.0' into staging
[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 "exec/gdbstub.h"
23
24 #include "helper.h"
25
26 #define SIGNBIT (1u << 31)
27
28 /* Sort alphabetically, except for "any". */
29 static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
30 {
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);
37     if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
38         return 1;
39     } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
40         return -1;
41     } else {
42         return strcasecmp(name_a, name_b);
43     }
44 }
45
46 static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
47 {
48     ObjectClass *c = data;
49     CPUListState *s = user_data;
50     const char *typename;
51     char *name;
52
53     typename = object_class_get_name(c);
54     name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
55     (*s->cpu_fprintf)(s->file, "%s\n",
56                       name);
57     g_free(name);
58 }
59
60 void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
61 {
62     CPUListState s = {
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
74 static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
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
88 static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
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
101 M68kCPU *cpu_m68k_init(const char *cpu_model)
102 {
103     M68kCPU *cpu;
104     CPUM68KState *env;
105     ObjectClass *oc;
106
107     oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model);
108     if (oc == NULL) {
109         return NULL;
110     }
111     cpu = M68K_CPU(object_new(object_class_get_name(oc)));
112     env = &cpu->env;
113
114     register_m68k_insns(env);
115
116     object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
117
118     return cpu;
119 }
120
121 void m68k_cpu_init_gdb(M68kCPU *cpu)
122 {
123     CPUState *cs = CPU(cpu);
124     CPUM68KState *env = &cpu->env;
125
126     if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
127         gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg,
128                                  11, "cf-fp.xml", 18);
129     }
130     /* TODO: Add [E]MAC registers.  */
131 }
132
133 void 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;
201     case CC_OP_SHIFT:
202         SET_NZ(dest);
203         if (src)
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
213 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
214 {
215     switch (reg) {
216     case 0x02: /* CACR */
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.  */
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
233 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
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
267 void 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
278 #if defined(CONFIG_USER_ONLY)
279
280 int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
281                                int mmu_idx)
282 {
283     env->exception_index = EXCP_ACCESS;
284     env->mmu.ar = address;
285     return 1;
286 }
287
288 #else
289
290 /* MMU */
291
292 /* TODO: This will need fixing once the MMU is implemented.  */
293 hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
294 {
295     return addr;
296 }
297
298 int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
299                                int mmu_idx)
300 {
301     int prot;
302
303     address &= TARGET_PAGE_MASK;
304     prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
305     tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
306     return 0;
307 }
308
309 /* Notify CPU of a pending interrupt.  Prioritization and vectoring should
310    be handled by the interrupt controller.  Real hardware only requests
311    the vector when the interrupt is acknowledged by the CPU.  For
312    simplicitly we calculate it when the interrupt is signalled.  */
313 void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
314 {
315     CPUState *cs = CPU(cpu);
316     CPUM68KState *env = &cpu->env;
317
318     env->pending_level = level;
319     env->pending_vector = vector;
320     if (level) {
321         cpu_interrupt(cs, CPU_INTERRUPT_HARD);
322     } else {
323         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
324     }
325 }
326
327 #endif
328
329 uint32_t HELPER(bitrev)(uint32_t x)
330 {
331     x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
332     x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
333     x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
334     return bswap32(x);
335 }
336
337 uint32_t HELPER(ff1)(uint32_t x)
338 {
339     int n;
340     for (n = 32; x; n--)
341         x >>= 1;
342     return n;
343 }
344
345 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
346 {
347     /* The result has the opposite sign to the original value.  */
348     if (ccr & CCF_V)
349         val = (((int32_t)val) >> 31) ^ SIGNBIT;
350     return val;
351 }
352
353 uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
354 {
355     uint32_t res;
356     uint32_t old_flags;
357
358     old_flags = env->cc_dest;
359     if (env->cc_x) {
360         env->cc_x = (op1 <= op2);
361         env->cc_op = CC_OP_SUBX;
362         res = op1 - (op2 + 1);
363     } else {
364         env->cc_x = (op1 < op2);
365         env->cc_op = CC_OP_SUB;
366         res = op1 - op2;
367     }
368     env->cc_dest = res;
369     env->cc_src = op2;
370     cpu_m68k_flush_flags(env, env->cc_op);
371     /* !Z is sticky.  */
372     env->cc_dest &= (old_flags | ~CCF_Z);
373     return res;
374 }
375
376 uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
377 {
378     uint32_t res;
379     uint32_t old_flags;
380
381     old_flags = env->cc_dest;
382     if (env->cc_x) {
383         res = op1 + op2 + 1;
384         env->cc_x = (res <= op2);
385         env->cc_op = CC_OP_ADDX;
386     } else {
387         res = op1 + op2;
388         env->cc_x = (res < op2);
389         env->cc_op = CC_OP_ADD;
390     }
391     env->cc_dest = res;
392     env->cc_src = op2;
393     cpu_m68k_flush_flags(env, env->cc_op);
394     /* !Z is sticky.  */
395     env->cc_dest &= (old_flags | ~CCF_Z);
396     return res;
397 }
398
399 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
400 {
401     return a < b;
402 }
403
404 void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
405 {
406     env->sr = val & 0xffff;
407     m68k_switch_sp(env);
408 }
409
410 uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
411 {
412     uint32_t result;
413     uint32_t cf;
414
415     shift &= 63;
416     if (shift == 0) {
417         result = val;
418         cf = env->cc_src & CCF_C;
419     } else if (shift < 32) {
420         result = val << shift;
421         cf = (val >> (32 - shift)) & 1;
422     } else if (shift == 32) {
423         result = 0;
424         cf = val & 1;
425     } else /* shift > 32 */ {
426         result = 0;
427         cf = 0;
428     }
429     env->cc_src = cf;
430     env->cc_x = (cf != 0);
431     env->cc_dest = result;
432     return result;
433 }
434
435 uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
436 {
437     uint32_t result;
438     uint32_t cf;
439
440     shift &= 63;
441     if (shift == 0) {
442         result = val;
443         cf = env->cc_src & CCF_C;
444     } else if (shift < 32) {
445         result = val >> shift;
446         cf = (val >> (shift - 1)) & 1;
447     } else if (shift == 32) {
448         result = 0;
449         cf = val >> 31;
450     } else /* shift > 32 */ {
451         result = 0;
452         cf = 0;
453     }
454     env->cc_src = cf;
455     env->cc_x = (cf != 0);
456     env->cc_dest = result;
457     return result;
458 }
459
460 uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
461 {
462     uint32_t result;
463     uint32_t cf;
464
465     shift &= 63;
466     if (shift == 0) {
467         result = val;
468         cf = (env->cc_src & CCF_C) != 0;
469     } else if (shift < 32) {
470         result = (int32_t)val >> shift;
471         cf = (val >> (shift - 1)) & 1;
472     } else /* shift >= 32 */ {
473         result = (int32_t)val >> 31;
474         cf = val >> 31;
475     }
476     env->cc_src = cf;
477     env->cc_x = cf;
478     env->cc_dest = result;
479     return result;
480 }
481
482 /* FPU helpers.  */
483 uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
484 {
485     return float64_to_int32(val, &env->fp_status);
486 }
487
488 float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
489 {
490     return float64_to_float32(val, &env->fp_status);
491 }
492
493 float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
494 {
495     return int32_to_float64(val, &env->fp_status);
496 }
497
498 float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
499 {
500     return float32_to_float64(val, &env->fp_status);
501 }
502
503 float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
504 {
505     return float64_round_to_int(val, &env->fp_status);
506 }
507
508 float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
509 {
510     return float64_trunc_to_int(val, &env->fp_status);
511 }
512
513 float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
514 {
515     return float64_sqrt(val, &env->fp_status);
516 }
517
518 float64 HELPER(abs_f64)(float64 val)
519 {
520     return float64_abs(val);
521 }
522
523 float64 HELPER(chs_f64)(float64 val)
524 {
525     return float64_chs(val);
526 }
527
528 float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
529 {
530     return float64_add(a, b, &env->fp_status);
531 }
532
533 float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
534 {
535     return float64_sub(a, b, &env->fp_status);
536 }
537
538 float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
539 {
540     return float64_mul(a, b, &env->fp_status);
541 }
542
543 float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
544 {
545     return float64_div(a, b, &env->fp_status);
546 }
547
548 float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
549 {
550     /* ??? This may incorrectly raise exceptions.  */
551     /* ??? Should flush denormals to zero.  */
552     float64 res;
553     res = float64_sub(a, b, &env->fp_status);
554     if (float64_is_quiet_nan(res)) {
555         /* +/-inf compares equal against itself, but sub returns nan.  */
556         if (!float64_is_quiet_nan(a)
557             && !float64_is_quiet_nan(b)) {
558             res = float64_zero;
559             if (float64_lt_quiet(a, res, &env->fp_status))
560                 res = float64_chs(res);
561         }
562     }
563     return res;
564 }
565
566 uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
567 {
568     return float64_compare_quiet(val, float64_zero, &env->fp_status);
569 }
570
571 /* MAC unit.  */
572 /* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
573    take values,  others take register numbers and manipulate the contents
574    in-place.  */
575 void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
576 {
577     uint32_t mask;
578     env->macc[dest] = env->macc[src];
579     mask = MACSR_PAV0 << dest;
580     if (env->macsr & (MACSR_PAV0 << src))
581         env->macsr |= mask;
582     else
583         env->macsr &= ~mask;
584 }
585
586 uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
587 {
588     int64_t product;
589     int64_t res;
590
591     product = (uint64_t)op1 * op2;
592     res = (product << 24) >> 24;
593     if (res != product) {
594         env->macsr |= MACSR_V;
595         if (env->macsr & MACSR_OMC) {
596             /* Make sure the accumulate operation overflows.  */
597             if (product < 0)
598                 res = ~(1ll << 50);
599             else
600                 res = 1ll << 50;
601         }
602     }
603     return res;
604 }
605
606 uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
607 {
608     uint64_t product;
609
610     product = (uint64_t)op1 * op2;
611     if (product & (0xffffffull << 40)) {
612         env->macsr |= MACSR_V;
613         if (env->macsr & MACSR_OMC) {
614             /* Make sure the accumulate operation overflows.  */
615             product = 1ll << 50;
616         } else {
617             product &= ((1ull << 40) - 1);
618         }
619     }
620     return product;
621 }
622
623 uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
624 {
625     uint64_t product;
626     uint32_t remainder;
627
628     product = (uint64_t)op1 * op2;
629     if (env->macsr & MACSR_RT) {
630         remainder = product & 0xffffff;
631         product >>= 24;
632         if (remainder > 0x800000)
633             product++;
634         else if (remainder == 0x800000)
635             product += (product & 1);
636     } else {
637         product >>= 24;
638     }
639     return product;
640 }
641
642 void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
643 {
644     int64_t tmp;
645     int64_t result;
646     tmp = env->macc[acc];
647     result = ((tmp << 16) >> 16);
648     if (result != tmp) {
649         env->macsr |= MACSR_V;
650     }
651     if (env->macsr & MACSR_V) {
652         env->macsr |= MACSR_PAV0 << acc;
653         if (env->macsr & MACSR_OMC) {
654             /* The result is saturated to 32 bits, despite overflow occurring
655                at 48 bits.  Seems weird, but that's what the hardware docs
656                say.  */
657             result = (result >> 63) ^ 0x7fffffff;
658         }
659     }
660     env->macc[acc] = result;
661 }
662
663 void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
664 {
665     uint64_t val;
666
667     val = env->macc[acc];
668     if (val & (0xffffull << 48)) {
669         env->macsr |= MACSR_V;
670     }
671     if (env->macsr & MACSR_V) {
672         env->macsr |= MACSR_PAV0 << acc;
673         if (env->macsr & MACSR_OMC) {
674             if (val > (1ull << 53))
675                 val = 0;
676             else
677                 val = (1ull << 48) - 1;
678         } else {
679             val &= ((1ull << 48) - 1);
680         }
681     }
682     env->macc[acc] = val;
683 }
684
685 void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
686 {
687     int64_t sum;
688     int64_t result;
689
690     sum = env->macc[acc];
691     result = (sum << 16) >> 16;
692     if (result != sum) {
693         env->macsr |= MACSR_V;
694     }
695     if (env->macsr & MACSR_V) {
696         env->macsr |= MACSR_PAV0 << acc;
697         if (env->macsr & MACSR_OMC) {
698             result = (result >> 63) ^ 0x7fffffffffffll;
699         }
700     }
701     env->macc[acc] = result;
702 }
703
704 void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
705 {
706     uint64_t val;
707     val = env->macc[acc];
708     if (val == 0) {
709         env->macsr |= MACSR_Z;
710     } else if (val & (1ull << 47)) {
711         env->macsr |= MACSR_N;
712     }
713     if (env->macsr & (MACSR_PAV0 << acc)) {
714         env->macsr |= MACSR_V;
715     }
716     if (env->macsr & MACSR_FI) {
717         val = ((int64_t)val) >> 40;
718         if (val != 0 && val != -1)
719             env->macsr |= MACSR_EV;
720     } else if (env->macsr & MACSR_SU) {
721         val = ((int64_t)val) >> 32;
722         if (val != 0 && val != -1)
723             env->macsr |= MACSR_EV;
724     } else {
725         if ((val >> 32) != 0)
726             env->macsr |= MACSR_EV;
727     }
728 }
729
730 void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
731 {
732     cpu_m68k_flush_flags(env, cc_op);
733 }
734
735 uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
736 {
737     int rem;
738     uint32_t result;
739
740     if (env->macsr & MACSR_SU) {
741         /* 16-bit rounding.  */
742         rem = val & 0xffffff;
743         val = (val >> 24) & 0xffffu;
744         if (rem > 0x800000)
745             val++;
746         else if (rem == 0x800000)
747             val += (val & 1);
748     } else if (env->macsr & MACSR_RT) {
749         /* 32-bit rounding.  */
750         rem = val & 0xff;
751         val >>= 8;
752         if (rem > 0x80)
753             val++;
754         else if (rem == 0x80)
755             val += (val & 1);
756     } else {
757         /* No rounding.  */
758         val >>= 8;
759     }
760     if (env->macsr & MACSR_OMC) {
761         /* Saturate.  */
762         if (env->macsr & MACSR_SU) {
763             if (val != (uint16_t) val) {
764                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
765             } else {
766                 result = val & 0xffff;
767             }
768         } else {
769             if (val != (uint32_t)val) {
770                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
771             } else {
772                 result = (uint32_t)val;
773             }
774         }
775     } else {
776         /* No saturation.  */
777         if (env->macsr & MACSR_SU) {
778             result = val & 0xffff;
779         } else {
780             result = (uint32_t)val;
781         }
782     }
783     return result;
784 }
785
786 uint32_t HELPER(get_macs)(uint64_t val)
787 {
788     if (val == (int32_t)val) {
789         return (int32_t)val;
790     } else {
791         return (val >> 61) ^ ~SIGNBIT;
792     }
793 }
794
795 uint32_t HELPER(get_macu)(uint64_t val)
796 {
797     if ((val >> 32) == 0) {
798         return (uint32_t)val;
799     } else {
800         return 0xffffffffu;
801     }
802 }
803
804 uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
805 {
806     uint32_t val;
807     val = env->macc[acc] & 0x00ff;
808     val = (env->macc[acc] >> 32) & 0xff00;
809     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
810     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
811     return val;
812 }
813
814 uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
815 {
816     uint32_t val;
817     val = (env->macc[acc] >> 32) & 0xffff;
818     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
819     return val;
820 }
821
822 void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
823 {
824     int64_t res;
825     int32_t tmp;
826     res = env->macc[acc] & 0xffffffff00ull;
827     tmp = (int16_t)(val & 0xff00);
828     res |= ((int64_t)tmp) << 32;
829     res |= val & 0xff;
830     env->macc[acc] = res;
831     res = env->macc[acc + 1] & 0xffffffff00ull;
832     tmp = (val & 0xff000000);
833     res |= ((int64_t)tmp) << 16;
834     res |= (val >> 16) & 0xff;
835     env->macc[acc + 1] = res;
836 }
837
838 void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
839 {
840     int64_t res;
841     int32_t tmp;
842     res = (uint32_t)env->macc[acc];
843     tmp = (int16_t)val;
844     res |= ((int64_t)tmp) << 32;
845     env->macc[acc] = res;
846     res = (uint32_t)env->macc[acc + 1];
847     tmp = val & 0xffff0000;
848     res |= (int64_t)tmp << 16;
849     env->macc[acc + 1] = res;
850 }
851
852 void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
853 {
854     uint64_t res;
855     res = (uint32_t)env->macc[acc];
856     res |= ((uint64_t)(val & 0xffff)) << 32;
857     env->macc[acc] = res;
858     res = (uint32_t)env->macc[acc + 1];
859     res |= (uint64_t)(val & 0xffff0000) << 16;
860     env->macc[acc + 1] = res;
861 }
This page took 0.071382 seconds and 4 git commands to generate.