]> Git Repo - qemu.git/blob - target-m68k/helper.c
pci: Unregister BARs before device exit
[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 typedef struct M68kCPUListState {
29     fprintf_function cpu_fprintf;
30     FILE *file;
31 } M68kCPUListState;
32
33 /* Sort alphabetically, except for "any". */
34 static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
35 {
36     ObjectClass *class_a = (ObjectClass *)a;
37     ObjectClass *class_b = (ObjectClass *)b;
38     const char *name_a, *name_b;
39
40     name_a = object_class_get_name(class_a);
41     name_b = object_class_get_name(class_b);
42     if (strcmp(name_a, "any") == 0) {
43         return 1;
44     } else if (strcmp(name_b, "any") == 0) {
45         return -1;
46     } else {
47         return strcasecmp(name_a, name_b);
48     }
49 }
50
51 static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
52 {
53     ObjectClass *c = data;
54     M68kCPUListState *s = user_data;
55
56     (*s->cpu_fprintf)(s->file, "%s\n",
57                       object_class_get_name(c));
58 }
59
60 void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
61 {
62     M68kCPUListState 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 void cpu_state_reset(CPUM68KState *env)
102 {
103     cpu_reset(ENV_GET_CPU(env));
104 }
105
106 CPUM68KState *cpu_m68k_init(const char *cpu_model)
107 {
108     M68kCPU *cpu;
109     CPUM68KState *env;
110     static int inited;
111
112     if (object_class_by_name(cpu_model) == NULL) {
113         return NULL;
114     }
115     cpu = M68K_CPU(object_new(cpu_model));
116     env = &cpu->env;
117
118     if (!inited) {
119         inited = 1;
120         m68k_tcg_init();
121     }
122
123     env->cpu_model_str = cpu_model;
124
125     register_m68k_insns(env);
126     if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
127         gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
128                                  11, "cf-fp.xml", 18);
129     }
130     /* TODO: Add [E]MAC registers.  */
131
132     cpu_reset(ENV_GET_CPU(env));
133     qemu_init_vcpu(env);
134     return env;
135 }
136
137 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
138 {
139     int flags;
140     uint32_t src;
141     uint32_t dest;
142     uint32_t tmp;
143
144 #define HIGHBIT 0x80000000u
145
146 #define SET_NZ(x) do { \
147     if ((x) == 0) \
148         flags |= CCF_Z; \
149     else if ((int32_t)(x) < 0) \
150         flags |= CCF_N; \
151     } while (0)
152
153 #define SET_FLAGS_SUB(type, utype) do { \
154     SET_NZ((type)dest); \
155     tmp = dest + src; \
156     if ((utype) tmp < (utype) src) \
157         flags |= CCF_C; \
158     if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
159         flags |= CCF_V; \
160     } while (0)
161
162     flags = 0;
163     src = env->cc_src;
164     dest = env->cc_dest;
165     switch (cc_op) {
166     case CC_OP_FLAGS:
167         flags = dest;
168         break;
169     case CC_OP_LOGIC:
170         SET_NZ(dest);
171         break;
172     case CC_OP_ADD:
173         SET_NZ(dest);
174         if (dest < src)
175             flags |= CCF_C;
176         tmp = dest - src;
177         if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
178             flags |= CCF_V;
179         break;
180     case CC_OP_SUB:
181         SET_FLAGS_SUB(int32_t, uint32_t);
182         break;
183     case CC_OP_CMPB:
184         SET_FLAGS_SUB(int8_t, uint8_t);
185         break;
186     case CC_OP_CMPW:
187         SET_FLAGS_SUB(int16_t, uint16_t);
188         break;
189     case CC_OP_ADDX:
190         SET_NZ(dest);
191         if (dest <= src)
192             flags |= CCF_C;
193         tmp = dest - src - 1;
194         if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
195             flags |= CCF_V;
196         break;
197     case CC_OP_SUBX:
198         SET_NZ(dest);
199         tmp = dest + src + 1;
200         if (tmp <= src)
201             flags |= CCF_C;
202         if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
203             flags |= CCF_V;
204         break;
205     case CC_OP_SHIFT:
206         SET_NZ(dest);
207         if (src)
208             flags |= CCF_C;
209         break;
210     default:
211         cpu_abort(env, "Bad CC_OP %d", cc_op);
212     }
213     env->cc_op = CC_OP_FLAGS;
214     env->cc_dest = flags;
215 }
216
217 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
218 {
219     switch (reg) {
220     case 0x02: /* CACR */
221         env->cacr = val;
222         m68k_switch_sp(env);
223         break;
224     case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
225         /* TODO: Implement Access Control Registers.  */
226         break;
227     case 0x801: /* VBR */
228         env->vbr = val;
229         break;
230     /* TODO: Implement control registers.  */
231     default:
232         cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
233                   reg, val);
234     }
235 }
236
237 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
238 {
239     uint32_t acc;
240     int8_t exthigh;
241     uint8_t extlow;
242     uint64_t regval;
243     int i;
244     if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
245         for (i = 0; i < 4; i++) {
246             regval = env->macc[i];
247             exthigh = regval >> 40;
248             if (env->macsr & MACSR_FI) {
249                 acc = regval >> 8;
250                 extlow = regval;
251             } else {
252                 acc = regval;
253                 extlow = regval >> 32;
254             }
255             if (env->macsr & MACSR_FI) {
256                 regval = (((uint64_t)acc) << 8) | extlow;
257                 regval |= ((int64_t)exthigh) << 40;
258             } else if (env->macsr & MACSR_SU) {
259                 regval = acc | (((int64_t)extlow) << 32);
260                 regval |= ((int64_t)exthigh) << 40;
261             } else {
262                 regval = acc | (((uint64_t)extlow) << 32);
263                 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
264             }
265             env->macc[i] = regval;
266         }
267     }
268     env->macsr = val;
269 }
270
271 void m68k_switch_sp(CPUM68KState *env)
272 {
273     int new_sp;
274
275     env->sp[env->current_sp] = env->aregs[7];
276     new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
277              ? M68K_SSP : M68K_USP;
278     env->aregs[7] = env->sp[new_sp];
279     env->current_sp = new_sp;
280 }
281
282 #if defined(CONFIG_USER_ONLY)
283
284 int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
285                                int mmu_idx)
286 {
287     env->exception_index = EXCP_ACCESS;
288     env->mmu.ar = address;
289     return 1;
290 }
291
292 #else
293
294 /* MMU */
295
296 /* TODO: This will need fixing once the MMU is implemented.  */
297 target_phys_addr_t cpu_get_phys_page_debug(CPUM68KState *env, target_ulong addr)
298 {
299     return addr;
300 }
301
302 int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
303                                int mmu_idx)
304 {
305     int prot;
306
307     address &= TARGET_PAGE_MASK;
308     prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
309     tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
310     return 0;
311 }
312
313 /* Notify CPU of a pending interrupt.  Prioritization and vectoring should
314    be handled by the interrupt controller.  Real hardware only requests
315    the vector when the interrupt is acknowledged by the CPU.  For
316    simplicitly we calculate it when the interrupt is signalled.  */
317 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
318 {
319     env->pending_level = level;
320     env->pending_vector = vector;
321     if (level)
322         cpu_interrupt(env, CPU_INTERRUPT_HARD);
323     else
324         cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
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.072042 seconds and 4 git commands to generate.