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