|
|
1.1 root 1: /*
2: * m68k op helpers
1.1.1.2 root 3: *
4: * Copyright (c) 2006-2007 CodeSourcery
1.1 root 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
1.1.1.4 ! root 18: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 19: */
20:
21: #include <stdio.h>
1.1.1.2 root 22: #include <string.h>
1.1 root 23:
24: #include "config.h"
25: #include "cpu.h"
26: #include "exec-all.h"
1.1.1.3 root 27: #include "qemu-common.h"
28: #include "gdbstub.h"
29:
30: #include "helpers.h"
31:
32: #define SIGNBIT (1u << 31)
1.1 root 33:
1.1.1.2 root 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:
1.1.1.4 ! root 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:
1.1.1.3 root 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:
1.1.1.2 root 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);
1.1.1.3 root 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. */
1.1.1.2 root 149: return 0;
150: }
151:
152: void cpu_reset(CPUM68KState *env)
153: {
1.1.1.3 root 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:
1.1.1.2 root 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;
1.1.1.3 root 174: static int inited;
1.1.1.2 root 175:
1.1.1.3 root 176: env = qemu_mallocz(sizeof(CPUM68KState));
1.1.1.2 root 177: cpu_exec_init(env);
1.1.1.3 root 178: if (!inited) {
179: inited = 1;
180: m68k_tcg_init();
181: }
1.1.1.2 root 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);
1.1.1.4 ! root 191: qemu_init_vcpu(env);
1.1.1.2 root 192: return env;
193: }
194:
195: void cpu_m68k_close(CPUM68KState *env)
196: {
197: qemu_free(env);
198: }
199:
1.1 root 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;
1.1.1.3 root 268: case CC_OP_SHIFT:
269: SET_NZ(dest);
270: if (src)
1.1 root 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:
1.1.1.3 root 280: void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
1.1.1.2 root 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:
1.1.1.3 root 300: void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
1.1.1.2 root 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: /* MMU */
346:
347: /* TODO: This will need fixing once the MMU is implemented. */
348: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
349: {
350: return addr;
351: }
352:
353: #if defined(CONFIG_USER_ONLY)
354:
355: int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
356: int mmu_idx, int is_softmmu)
357: {
358: env->exception_index = EXCP_ACCESS;
359: env->mmu.ar = address;
360: return 1;
361: }
362:
363: #else
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;
372: return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
373: }
374:
375: /* Notify CPU of a pending interrupt. Prioritization and vectoring should
376: be handled by the interrupt controller. Real hardware only requests
377: the vector when the interrupt is acknowledged by the CPU. For
378: simplicitly we calculate it when the interrupt is signalled. */
379: void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
380: {
381: env->pending_level = level;
382: env->pending_vector = vector;
383: if (level)
384: cpu_interrupt(env, CPU_INTERRUPT_HARD);
385: else
386: cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
387: }
388:
389: #endif
1.1.1.3 root 390:
391: uint32_t HELPER(bitrev)(uint32_t x)
392: {
393: x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
394: x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
395: x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
396: return bswap32(x);
397: }
398:
399: uint32_t HELPER(ff1)(uint32_t x)
400: {
401: int n;
402: for (n = 32; x; n--)
403: x >>= 1;
404: return n;
405: }
406:
407: uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
408: {
409: /* The result has the opposite sign to the original value. */
410: if (ccr & CCF_V)
411: val = (((int32_t)val) >> 31) ^ SIGNBIT;
412: return val;
413: }
414:
415: uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
416: {
417: uint32_t res;
418: uint32_t old_flags;
419:
420: old_flags = env->cc_dest;
421: if (env->cc_x) {
422: env->cc_x = (op1 <= op2);
423: env->cc_op = CC_OP_SUBX;
424: res = op1 - (op2 + 1);
425: } else {
426: env->cc_x = (op1 < op2);
427: env->cc_op = CC_OP_SUB;
428: res = op1 - op2;
429: }
430: env->cc_dest = res;
431: env->cc_src = op2;
432: cpu_m68k_flush_flags(env, env->cc_op);
433: /* !Z is sticky. */
434: env->cc_dest &= (old_flags | ~CCF_Z);
435: return res;
436: }
437:
438: uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
439: {
440: uint32_t res;
441: uint32_t old_flags;
442:
443: old_flags = env->cc_dest;
444: if (env->cc_x) {
445: res = op1 + op2 + 1;
446: env->cc_x = (res <= op2);
447: env->cc_op = CC_OP_ADDX;
448: } else {
449: res = op1 + op2;
450: env->cc_x = (res < op2);
451: env->cc_op = CC_OP_ADD;
452: }
453: env->cc_dest = res;
454: env->cc_src = op2;
455: cpu_m68k_flush_flags(env, env->cc_op);
456: /* !Z is sticky. */
457: env->cc_dest &= (old_flags | ~CCF_Z);
458: return res;
459: }
460:
461: uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
462: {
463: return a < b;
464: }
465:
466: void HELPER(set_sr)(CPUState *env, uint32_t val)
467: {
468: env->sr = val & 0xffff;
469: m68k_switch_sp(env);
470: }
471:
472: uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
473: {
474: uint32_t result;
475: uint32_t cf;
476:
477: shift &= 63;
478: if (shift == 0) {
479: result = val;
480: cf = env->cc_src & CCF_C;
481: } else if (shift < 32) {
482: result = val << shift;
483: cf = (val >> (32 - shift)) & 1;
484: } else if (shift == 32) {
485: result = 0;
486: cf = val & 1;
487: } else /* shift > 32 */ {
488: result = 0;
489: cf = 0;
490: }
491: env->cc_src = cf;
492: env->cc_x = (cf != 0);
493: env->cc_dest = result;
494: return result;
495: }
496:
497: uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
498: {
499: uint32_t result;
500: uint32_t cf;
501:
502: shift &= 63;
503: if (shift == 0) {
504: result = val;
505: cf = env->cc_src & CCF_C;
506: } else if (shift < 32) {
507: result = val >> shift;
508: cf = (val >> (shift - 1)) & 1;
509: } else if (shift == 32) {
510: result = 0;
511: cf = val >> 31;
512: } else /* shift > 32 */ {
513: result = 0;
514: cf = 0;
515: }
516: env->cc_src = cf;
517: env->cc_x = (cf != 0);
518: env->cc_dest = result;
519: return result;
520: }
521:
522: uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
523: {
524: uint32_t result;
525: uint32_t cf;
526:
527: shift &= 63;
528: if (shift == 0) {
529: result = val;
530: cf = (env->cc_src & CCF_C) != 0;
531: } else if (shift < 32) {
532: result = (int32_t)val >> shift;
533: cf = (val >> (shift - 1)) & 1;
534: } else /* shift >= 32 */ {
535: result = (int32_t)val >> 31;
536: cf = val >> 31;
537: }
538: env->cc_src = cf;
539: env->cc_x = cf;
540: env->cc_dest = result;
541: return result;
542: }
543:
544: /* FPU helpers. */
545: uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
546: {
547: return float64_to_int32(val, &env->fp_status);
548: }
549:
550: float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
551: {
552: return float64_to_float32(val, &env->fp_status);
553: }
554:
555: float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
556: {
557: return int32_to_float64(val, &env->fp_status);
558: }
559:
560: float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
561: {
562: return float32_to_float64(val, &env->fp_status);
563: }
564:
565: float64 HELPER(iround_f64)(CPUState *env, float64 val)
566: {
567: return float64_round_to_int(val, &env->fp_status);
568: }
569:
570: float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
571: {
572: return float64_trunc_to_int(val, &env->fp_status);
573: }
574:
575: float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
576: {
577: return float64_sqrt(val, &env->fp_status);
578: }
579:
580: float64 HELPER(abs_f64)(float64 val)
581: {
582: return float64_abs(val);
583: }
584:
585: float64 HELPER(chs_f64)(float64 val)
586: {
587: return float64_chs(val);
588: }
589:
590: float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
591: {
592: return float64_add(a, b, &env->fp_status);
593: }
594:
595: float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
596: {
597: return float64_sub(a, b, &env->fp_status);
598: }
599:
600: float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
601: {
602: return float64_mul(a, b, &env->fp_status);
603: }
604:
605: float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
606: {
607: return float64_div(a, b, &env->fp_status);
608: }
609:
610: float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
611: {
612: /* ??? This may incorrectly raise exceptions. */
613: /* ??? Should flush denormals to zero. */
614: float64 res;
615: res = float64_sub(a, b, &env->fp_status);
616: if (float64_is_nan(res)) {
617: /* +/-inf compares equal against itself, but sub returns nan. */
618: if (!float64_is_nan(a)
619: && !float64_is_nan(b)) {
620: res = float64_zero;
621: if (float64_lt_quiet(a, res, &env->fp_status))
622: res = float64_chs(res);
623: }
624: }
625: return res;
626: }
627:
628: uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
629: {
630: return float64_compare_quiet(val, float64_zero, &env->fp_status);
631: }
632:
633: /* MAC unit. */
634: /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
635: take values, others take register numbers and manipulate the contents
636: in-place. */
637: void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
638: {
639: uint32_t mask;
640: env->macc[dest] = env->macc[src];
641: mask = MACSR_PAV0 << dest;
642: if (env->macsr & (MACSR_PAV0 << src))
643: env->macsr |= mask;
644: else
645: env->macsr &= ~mask;
646: }
647:
648: uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
649: {
650: int64_t product;
651: int64_t res;
652:
653: product = (uint64_t)op1 * op2;
654: res = (product << 24) >> 24;
655: if (res != product) {
656: env->macsr |= MACSR_V;
657: if (env->macsr & MACSR_OMC) {
658: /* Make sure the accumulate operation overflows. */
659: if (product < 0)
660: res = ~(1ll << 50);
661: else
662: res = 1ll << 50;
663: }
664: }
665: return res;
666: }
667:
668: uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
669: {
670: uint64_t product;
671:
672: product = (uint64_t)op1 * op2;
673: if (product & (0xffffffull << 40)) {
674: env->macsr |= MACSR_V;
675: if (env->macsr & MACSR_OMC) {
676: /* Make sure the accumulate operation overflows. */
677: product = 1ll << 50;
678: } else {
679: product &= ((1ull << 40) - 1);
680: }
681: }
682: return product;
683: }
684:
685: uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
686: {
687: uint64_t product;
688: uint32_t remainder;
689:
690: product = (uint64_t)op1 * op2;
691: if (env->macsr & MACSR_RT) {
692: remainder = product & 0xffffff;
693: product >>= 24;
694: if (remainder > 0x800000)
695: product++;
696: else if (remainder == 0x800000)
697: product += (product & 1);
698: } else {
699: product >>= 24;
700: }
701: return product;
702: }
703:
704: void HELPER(macsats)(CPUState *env, uint32_t acc)
705: {
706: int64_t tmp;
707: int64_t result;
708: tmp = env->macc[acc];
709: result = ((tmp << 16) >> 16);
710: if (result != tmp) {
711: env->macsr |= MACSR_V;
712: }
713: if (env->macsr & MACSR_V) {
714: env->macsr |= MACSR_PAV0 << acc;
715: if (env->macsr & MACSR_OMC) {
716: /* The result is saturated to 32 bits, despite overflow occuring
717: at 48 bits. Seems weird, but that's what the hardware docs
718: say. */
719: result = (result >> 63) ^ 0x7fffffff;
720: }
721: }
722: env->macc[acc] = result;
723: }
724:
725: void HELPER(macsatu)(CPUState *env, uint32_t acc)
726: {
727: uint64_t val;
728:
729: val = env->macc[acc];
730: if (val & (0xffffull << 48)) {
731: env->macsr |= MACSR_V;
732: }
733: if (env->macsr & MACSR_V) {
734: env->macsr |= MACSR_PAV0 << acc;
735: if (env->macsr & MACSR_OMC) {
736: if (val > (1ull << 53))
737: val = 0;
738: else
739: val = (1ull << 48) - 1;
740: } else {
741: val &= ((1ull << 48) - 1);
742: }
743: }
744: env->macc[acc] = val;
745: }
746:
747: void HELPER(macsatf)(CPUState *env, uint32_t acc)
748: {
749: int64_t sum;
750: int64_t result;
751:
752: sum = env->macc[acc];
753: result = (sum << 16) >> 16;
754: if (result != sum) {
755: env->macsr |= MACSR_V;
756: }
757: if (env->macsr & MACSR_V) {
758: env->macsr |= MACSR_PAV0 << acc;
759: if (env->macsr & MACSR_OMC) {
760: result = (result >> 63) ^ 0x7fffffffffffll;
761: }
762: }
763: env->macc[acc] = result;
764: }
765:
766: void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
767: {
768: uint64_t val;
769: val = env->macc[acc];
770: if (val == 0)
771: env->macsr |= MACSR_Z;
772: else if (val & (1ull << 47));
773: env->macsr |= MACSR_N;
774: if (env->macsr & (MACSR_PAV0 << acc)) {
775: env->macsr |= MACSR_V;
776: }
777: if (env->macsr & MACSR_FI) {
778: val = ((int64_t)val) >> 40;
779: if (val != 0 && val != -1)
780: env->macsr |= MACSR_EV;
781: } else if (env->macsr & MACSR_SU) {
782: val = ((int64_t)val) >> 32;
783: if (val != 0 && val != -1)
784: env->macsr |= MACSR_EV;
785: } else {
786: if ((val >> 32) != 0)
787: env->macsr |= MACSR_EV;
788: }
789: }
790:
791: void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
792: {
793: cpu_m68k_flush_flags(env, cc_op);
794: }
795:
796: uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
797: {
798: int rem;
799: uint32_t result;
800:
801: if (env->macsr & MACSR_SU) {
802: /* 16-bit rounding. */
803: rem = val & 0xffffff;
804: val = (val >> 24) & 0xffffu;
805: if (rem > 0x800000)
806: val++;
807: else if (rem == 0x800000)
808: val += (val & 1);
809: } else if (env->macsr & MACSR_RT) {
810: /* 32-bit rounding. */
811: rem = val & 0xff;
812: val >>= 8;
813: if (rem > 0x80)
814: val++;
815: else if (rem == 0x80)
816: val += (val & 1);
817: } else {
818: /* No rounding. */
819: val >>= 8;
820: }
821: if (env->macsr & MACSR_OMC) {
822: /* Saturate. */
823: if (env->macsr & MACSR_SU) {
824: if (val != (uint16_t) val) {
825: result = ((val >> 63) ^ 0x7fff) & 0xffff;
826: } else {
827: result = val & 0xffff;
828: }
829: } else {
830: if (val != (uint32_t)val) {
831: result = ((uint32_t)(val >> 63) & 0x7fffffff);
832: } else {
833: result = (uint32_t)val;
834: }
835: }
836: } else {
837: /* No saturation. */
838: if (env->macsr & MACSR_SU) {
839: result = val & 0xffff;
840: } else {
841: result = (uint32_t)val;
842: }
843: }
844: return result;
845: }
846:
847: uint32_t HELPER(get_macs)(uint64_t val)
848: {
849: if (val == (int32_t)val) {
850: return (int32_t)val;
851: } else {
852: return (val >> 61) ^ ~SIGNBIT;
853: }
854: }
855:
856: uint32_t HELPER(get_macu)(uint64_t val)
857: {
858: if ((val >> 32) == 0) {
859: return (uint32_t)val;
860: } else {
861: return 0xffffffffu;
862: }
863: }
864:
865: uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
866: {
867: uint32_t val;
868: val = env->macc[acc] & 0x00ff;
869: val = (env->macc[acc] >> 32) & 0xff00;
870: val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
871: val |= (env->macc[acc + 1] >> 16) & 0xff000000;
872: return val;
873: }
874:
875: uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
876: {
877: uint32_t val;
878: val = (env->macc[acc] >> 32) & 0xffff;
879: val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
880: return val;
881: }
882:
883: void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
884: {
885: int64_t res;
886: int32_t tmp;
887: res = env->macc[acc] & 0xffffffff00ull;
888: tmp = (int16_t)(val & 0xff00);
889: res |= ((int64_t)tmp) << 32;
890: res |= val & 0xff;
891: env->macc[acc] = res;
892: res = env->macc[acc + 1] & 0xffffffff00ull;
893: tmp = (val & 0xff000000);
894: res |= ((int64_t)tmp) << 16;
895: res |= (val >> 16) & 0xff;
896: env->macc[acc + 1] = res;
897: }
898:
899: void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
900: {
901: int64_t res;
902: int32_t tmp;
903: res = (uint32_t)env->macc[acc];
904: tmp = (int16_t)val;
905: res |= ((int64_t)tmp) << 32;
906: env->macc[acc] = res;
907: res = (uint32_t)env->macc[acc + 1];
908: tmp = val & 0xffff0000;
909: res |= (int64_t)tmp << 16;
910: env->macc[acc + 1] = res;
911: }
912:
913: void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
914: {
915: uint64_t res;
916: res = (uint32_t)env->macc[acc];
917: res |= ((uint64_t)(val & 0xffff)) << 32;
918: env->macc[acc] = res;
919: res = (uint32_t)env->macc[acc + 1];
920: res |= (uint64_t)(val & 0xffff0000) << 16;
921: env->macc[acc + 1] = res;
922: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.