|
|
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"
1.1.1.3 root 26: #include "qemu-common.h"
27: #include "gdbstub.h"
28:
29: #include "helpers.h"
30:
31: #define SIGNBIT (1u << 31)
1.1 root 32:
1.1.1.2 root 33: enum m68k_cpuid {
34: M68K_CPUID_M5206,
35: M68K_CPUID_M5208,
36: M68K_CPUID_CFV4E,
37: M68K_CPUID_ANY,
38: };
39:
40: typedef struct m68k_def_t m68k_def_t;
41:
42: struct m68k_def_t {
43: const char * name;
44: enum m68k_cpuid id;
45: };
46:
47: static m68k_def_t m68k_cpu_defs[] = {
48: {"m5206", M68K_CPUID_M5206},
49: {"m5208", M68K_CPUID_M5208},
50: {"cfv4e", M68K_CPUID_CFV4E},
51: {"any", M68K_CPUID_ANY},
52: {NULL, 0},
53: };
54:
1.1.1.6 root 55: void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
1.1.1.4 root 56: {
57: unsigned int i;
58:
59: for (i = 0; m68k_cpu_defs[i].name; i++) {
60: (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
61: }
62: }
63:
1.1.1.3 root 64: static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
65: {
66: if (n < 8) {
67: stfq_p(mem_buf, env->fregs[n]);
68: return 8;
69: }
70: if (n < 11) {
71: /* FP control registers (not implemented) */
72: memset(mem_buf, 0, 4);
73: return 4;
74: }
75: return 0;
76: }
77:
78: static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
79: {
80: if (n < 8) {
81: env->fregs[n] = ldfq_p(mem_buf);
82: return 8;
83: }
84: if (n < 11) {
85: /* FP control registers (not implemented) */
86: return 4;
87: }
88: return 0;
89: }
90:
1.1.1.2 root 91: static void m68k_set_feature(CPUM68KState *env, int feature)
92: {
93: env->features |= (1u << feature);
94: }
95:
96: static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
97: {
98: m68k_def_t *def;
99:
100: for (def = m68k_cpu_defs; def->name; def++) {
101: if (strcmp(def->name, name) == 0)
102: break;
103: }
104: if (!def->name)
105: return -1;
106:
107: switch (def->id) {
108: case M68K_CPUID_M5206:
109: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
110: break;
111: case M68K_CPUID_M5208:
112: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
113: m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
114: m68k_set_feature(env, M68K_FEATURE_BRAL);
115: m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
116: m68k_set_feature(env, M68K_FEATURE_USP);
117: break;
118: case M68K_CPUID_CFV4E:
119: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
120: m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
121: m68k_set_feature(env, M68K_FEATURE_BRAL);
122: m68k_set_feature(env, M68K_FEATURE_CF_FPU);
123: m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
124: m68k_set_feature(env, M68K_FEATURE_USP);
125: break;
126: case M68K_CPUID_ANY:
127: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
128: m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
129: m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
130: m68k_set_feature(env, M68K_FEATURE_BRAL);
131: m68k_set_feature(env, M68K_FEATURE_CF_FPU);
132: /* MAC and EMAC are mututally exclusive, so pick EMAC.
133: It's mostly backwards compatible. */
134: m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
135: m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
136: m68k_set_feature(env, M68K_FEATURE_USP);
137: m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
138: m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
139: break;
140: }
141:
142: register_m68k_insns(env);
1.1.1.3 root 143: if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
144: gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
145: 11, "cf-fp.xml", 18);
146: }
147: /* TODO: Add [E]MAC registers. */
1.1.1.2 root 148: return 0;
149: }
150:
151: void cpu_reset(CPUM68KState *env)
152: {
1.1.1.3 root 153: if (qemu_loglevel_mask(CPU_LOG_RESET)) {
154: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
155: log_cpu_state(env, 0);
156: }
157:
1.1.1.2 root 158: memset(env, 0, offsetof(CPUM68KState, breakpoints));
159: #if !defined (CONFIG_USER_ONLY)
160: env->sr = 0x2700;
161: #endif
162: m68k_switch_sp(env);
163: /* ??? FP regs should be initialized to NaN. */
164: env->cc_op = CC_OP_FLAGS;
165: /* TODO: We should set PC from the interrupt vector. */
166: env->pc = 0;
167: tlb_flush(env, 1);
168: }
169:
170: CPUM68KState *cpu_m68k_init(const char *cpu_model)
171: {
172: CPUM68KState *env;
1.1.1.3 root 173: static int inited;
1.1.1.2 root 174:
1.1.1.3 root 175: env = qemu_mallocz(sizeof(CPUM68KState));
1.1.1.2 root 176: cpu_exec_init(env);
1.1.1.3 root 177: if (!inited) {
178: inited = 1;
179: m68k_tcg_init();
180: }
1.1.1.2 root 181:
182: env->cpu_model_str = cpu_model;
183:
184: if (cpu_m68k_set_model(env, cpu_model) < 0) {
185: cpu_m68k_close(env);
186: return NULL;
187: }
188:
189: cpu_reset(env);
1.1.1.4 root 190: qemu_init_vcpu(env);
1.1.1.2 root 191: return env;
192: }
193:
194: void cpu_m68k_close(CPUM68KState *env)
195: {
196: qemu_free(env);
197: }
198:
1.1 root 199: void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
200: {
201: int flags;
202: uint32_t src;
203: uint32_t dest;
204: uint32_t tmp;
205:
206: #define HIGHBIT 0x80000000u
207:
208: #define SET_NZ(x) do { \
209: if ((x) == 0) \
210: flags |= CCF_Z; \
211: else if ((int32_t)(x) < 0) \
212: flags |= CCF_N; \
213: } while (0)
214:
215: #define SET_FLAGS_SUB(type, utype) do { \
216: SET_NZ((type)dest); \
217: tmp = dest + src; \
218: if ((utype) tmp < (utype) src) \
219: flags |= CCF_C; \
220: if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
221: flags |= CCF_V; \
222: } while (0)
223:
224: flags = 0;
225: src = env->cc_src;
226: dest = env->cc_dest;
227: switch (cc_op) {
228: case CC_OP_FLAGS:
229: flags = dest;
230: break;
231: case CC_OP_LOGIC:
232: SET_NZ(dest);
233: break;
234: case CC_OP_ADD:
235: SET_NZ(dest);
236: if (dest < src)
237: flags |= CCF_C;
238: tmp = dest - src;
239: if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
240: flags |= CCF_V;
241: break;
242: case CC_OP_SUB:
243: SET_FLAGS_SUB(int32_t, uint32_t);
244: break;
245: case CC_OP_CMPB:
246: SET_FLAGS_SUB(int8_t, uint8_t);
247: break;
248: case CC_OP_CMPW:
249: SET_FLAGS_SUB(int16_t, uint16_t);
250: break;
251: case CC_OP_ADDX:
252: SET_NZ(dest);
253: if (dest <= src)
254: flags |= CCF_C;
255: tmp = dest - src - 1;
256: if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
257: flags |= CCF_V;
258: break;
259: case CC_OP_SUBX:
260: SET_NZ(dest);
261: tmp = dest + src + 1;
262: if (tmp <= src)
263: flags |= CCF_C;
264: if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
265: flags |= CCF_V;
266: break;
1.1.1.3 root 267: case CC_OP_SHIFT:
268: SET_NZ(dest);
269: if (src)
1.1 root 270: flags |= CCF_C;
271: break;
272: default:
273: cpu_abort(env, "Bad CC_OP %d", cc_op);
274: }
275: env->cc_op = CC_OP_FLAGS;
276: env->cc_dest = flags;
277: }
278:
1.1.1.3 root 279: void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
1.1.1.2 root 280: {
281: switch (reg) {
282: case 0x02: /* CACR */
283: env->cacr = val;
284: m68k_switch_sp(env);
285: break;
286: case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
287: /* TODO: Implement Access Control Registers. */
288: break;
289: case 0x801: /* VBR */
290: env->vbr = val;
291: break;
292: /* TODO: Implement control registers. */
293: default:
294: cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
295: reg, val);
296: }
297: }
298:
1.1.1.3 root 299: void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
1.1.1.2 root 300: {
301: uint32_t acc;
302: int8_t exthigh;
303: uint8_t extlow;
304: uint64_t regval;
305: int i;
306: if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
307: for (i = 0; i < 4; i++) {
308: regval = env->macc[i];
309: exthigh = regval >> 40;
310: if (env->macsr & MACSR_FI) {
311: acc = regval >> 8;
312: extlow = regval;
313: } else {
314: acc = regval;
315: extlow = regval >> 32;
316: }
317: if (env->macsr & MACSR_FI) {
318: regval = (((uint64_t)acc) << 8) | extlow;
319: regval |= ((int64_t)exthigh) << 40;
320: } else if (env->macsr & MACSR_SU) {
321: regval = acc | (((int64_t)extlow) << 32);
322: regval |= ((int64_t)exthigh) << 40;
323: } else {
324: regval = acc | (((uint64_t)extlow) << 32);
325: regval |= ((uint64_t)(uint8_t)exthigh) << 40;
326: }
327: env->macc[i] = regval;
328: }
329: }
330: env->macsr = val;
331: }
332:
333: void m68k_switch_sp(CPUM68KState *env)
334: {
335: int new_sp;
336:
337: env->sp[env->current_sp] = env->aregs[7];
338: new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
339: ? M68K_SSP : M68K_USP;
340: env->aregs[7] = env->sp[new_sp];
341: env->current_sp = new_sp;
342: }
343:
344: #if defined(CONFIG_USER_ONLY)
345:
346: int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
347: int mmu_idx, int is_softmmu)
348: {
349: env->exception_index = EXCP_ACCESS;
350: env->mmu.ar = address;
351: return 1;
352: }
353:
354: #else
355:
1.1.1.5 root 356: /* MMU */
357:
358: /* TODO: This will need fixing once the MMU is implemented. */
359: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
360: {
361: return addr;
362: }
363:
1.1.1.2 root 364: int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
365: int mmu_idx, int is_softmmu)
366: {
367: int prot;
368:
369: address &= TARGET_PAGE_MASK;
1.1.1.5 root 370: prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
371: tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
372: return 0;
1.1.1.2 root 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);
1.1.1.6 root 616: if (float64_is_quiet_nan(res)) {
1.1.1.3 root 617: /* +/-inf compares equal against itself, but sub returns nan. */
1.1.1.6 root 618: if (!float64_is_quiet_nan(a)
619: && !float64_is_quiet_nan(b)) {
1.1.1.3 root 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) {
1.1.1.7 ! root 716: /* The result is saturated to 32 bits, despite overflow occurring
1.1.1.3 root 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];
1.1.1.5 root 770: if (val == 0) {
1.1.1.3 root 771: env->macsr |= MACSR_Z;
1.1.1.5 root 772: } else if (val & (1ull << 47)) {
1.1.1.3 root 773: env->macsr |= MACSR_N;
1.1.1.5 root 774: }
1.1.1.3 root 775: if (env->macsr & (MACSR_PAV0 << acc)) {
776: env->macsr |= MACSR_V;
777: }
778: if (env->macsr & MACSR_FI) {
779: val = ((int64_t)val) >> 40;
780: if (val != 0 && val != -1)
781: env->macsr |= MACSR_EV;
782: } else if (env->macsr & MACSR_SU) {
783: val = ((int64_t)val) >> 32;
784: if (val != 0 && val != -1)
785: env->macsr |= MACSR_EV;
786: } else {
787: if ((val >> 32) != 0)
788: env->macsr |= MACSR_EV;
789: }
790: }
791:
792: void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
793: {
794: cpu_m68k_flush_flags(env, cc_op);
795: }
796:
797: uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
798: {
799: int rem;
800: uint32_t result;
801:
802: if (env->macsr & MACSR_SU) {
803: /* 16-bit rounding. */
804: rem = val & 0xffffff;
805: val = (val >> 24) & 0xffffu;
806: if (rem > 0x800000)
807: val++;
808: else if (rem == 0x800000)
809: val += (val & 1);
810: } else if (env->macsr & MACSR_RT) {
811: /* 32-bit rounding. */
812: rem = val & 0xff;
813: val >>= 8;
814: if (rem > 0x80)
815: val++;
816: else if (rem == 0x80)
817: val += (val & 1);
818: } else {
819: /* No rounding. */
820: val >>= 8;
821: }
822: if (env->macsr & MACSR_OMC) {
823: /* Saturate. */
824: if (env->macsr & MACSR_SU) {
825: if (val != (uint16_t) val) {
826: result = ((val >> 63) ^ 0x7fff) & 0xffff;
827: } else {
828: result = val & 0xffff;
829: }
830: } else {
831: if (val != (uint32_t)val) {
832: result = ((uint32_t)(val >> 63) & 0x7fffffff);
833: } else {
834: result = (uint32_t)val;
835: }
836: }
837: } else {
838: /* No saturation. */
839: if (env->macsr & MACSR_SU) {
840: result = val & 0xffff;
841: } else {
842: result = (uint32_t)val;
843: }
844: }
845: return result;
846: }
847:
848: uint32_t HELPER(get_macs)(uint64_t val)
849: {
850: if (val == (int32_t)val) {
851: return (int32_t)val;
852: } else {
853: return (val >> 61) ^ ~SIGNBIT;
854: }
855: }
856:
857: uint32_t HELPER(get_macu)(uint64_t val)
858: {
859: if ((val >> 32) == 0) {
860: return (uint32_t)val;
861: } else {
862: return 0xffffffffu;
863: }
864: }
865:
866: uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
867: {
868: uint32_t val;
869: val = env->macc[acc] & 0x00ff;
870: val = (env->macc[acc] >> 32) & 0xff00;
871: val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
872: val |= (env->macc[acc + 1] >> 16) & 0xff000000;
873: return val;
874: }
875:
876: uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
877: {
878: uint32_t val;
879: val = (env->macc[acc] >> 32) & 0xffff;
880: val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
881: return val;
882: }
883:
884: void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
885: {
886: int64_t res;
887: int32_t tmp;
888: res = env->macc[acc] & 0xffffffff00ull;
889: tmp = (int16_t)(val & 0xff00);
890: res |= ((int64_t)tmp) << 32;
891: res |= val & 0xff;
892: env->macc[acc] = res;
893: res = env->macc[acc + 1] & 0xffffffff00ull;
894: tmp = (val & 0xff000000);
895: res |= ((int64_t)tmp) << 16;
896: res |= (val >> 16) & 0xff;
897: env->macc[acc + 1] = res;
898: }
899:
900: void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
901: {
902: int64_t res;
903: int32_t tmp;
904: res = (uint32_t)env->macc[acc];
905: tmp = (int16_t)val;
906: res |= ((int64_t)tmp) << 32;
907: env->macc[acc] = res;
908: res = (uint32_t)env->macc[acc + 1];
909: tmp = val & 0xffff0000;
910: res |= (int64_t)tmp << 16;
911: env->macc[acc + 1] = res;
912: }
913:
914: void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
915: {
916: uint64_t res;
917: res = (uint32_t)env->macc[acc];
918: res |= ((uint64_t)(val & 0xffff)) << 32;
919: env->macc[acc] = res;
920: res = (uint32_t)env->macc[acc + 1];
921: res |= (uint64_t)(val & 0xffff0000) << 16;
922: env->macc[acc + 1] = res;
923: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.