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