|
|
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
18: * License along with this library; if not, write to the Free Software
1.1.1.3 ! root 19: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
1.1 root 20: */
21:
22: #include <stdio.h>
1.1.1.2 root 23: #include <string.h>
1.1 root 24:
25: #include "config.h"
26: #include "cpu.h"
27: #include "exec-all.h"
1.1.1.3 ! root 28: #include "qemu-common.h"
! 29: #include "gdbstub.h"
! 30:
! 31: #include "helpers.h"
! 32:
! 33: #define SIGNBIT (1u << 31)
1.1 root 34:
1.1.1.2 root 35: enum m68k_cpuid {
36: M68K_CPUID_M5206,
37: M68K_CPUID_M5208,
38: M68K_CPUID_CFV4E,
39: M68K_CPUID_ANY,
40: };
41:
42: typedef struct m68k_def_t m68k_def_t;
43:
44: struct m68k_def_t {
45: const char * name;
46: enum m68k_cpuid id;
47: };
48:
49: static m68k_def_t m68k_cpu_defs[] = {
50: {"m5206", M68K_CPUID_M5206},
51: {"m5208", M68K_CPUID_M5208},
52: {"cfv4e", M68K_CPUID_CFV4E},
53: {"any", M68K_CPUID_ANY},
54: {NULL, 0},
55: };
56:
1.1.1.3 ! root 57: static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
! 58: {
! 59: if (n < 8) {
! 60: stfq_p(mem_buf, env->fregs[n]);
! 61: return 8;
! 62: }
! 63: if (n < 11) {
! 64: /* FP control registers (not implemented) */
! 65: memset(mem_buf, 0, 4);
! 66: return 4;
! 67: }
! 68: return 0;
! 69: }
! 70:
! 71: static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
! 72: {
! 73: if (n < 8) {
! 74: env->fregs[n] = ldfq_p(mem_buf);
! 75: return 8;
! 76: }
! 77: if (n < 11) {
! 78: /* FP control registers (not implemented) */
! 79: return 4;
! 80: }
! 81: return 0;
! 82: }
! 83:
1.1.1.2 root 84: static void m68k_set_feature(CPUM68KState *env, int feature)
85: {
86: env->features |= (1u << feature);
87: }
88:
89: static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
90: {
91: m68k_def_t *def;
92:
93: for (def = m68k_cpu_defs; def->name; def++) {
94: if (strcmp(def->name, name) == 0)
95: break;
96: }
97: if (!def->name)
98: return -1;
99:
100: switch (def->id) {
101: case M68K_CPUID_M5206:
102: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
103: break;
104: case M68K_CPUID_M5208:
105: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
106: m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
107: m68k_set_feature(env, M68K_FEATURE_BRAL);
108: m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
109: m68k_set_feature(env, M68K_FEATURE_USP);
110: break;
111: case M68K_CPUID_CFV4E:
112: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
113: m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
114: m68k_set_feature(env, M68K_FEATURE_BRAL);
115: m68k_set_feature(env, M68K_FEATURE_CF_FPU);
116: m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
117: m68k_set_feature(env, M68K_FEATURE_USP);
118: break;
119: case M68K_CPUID_ANY:
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_CF_ISA_APLUSC);
123: m68k_set_feature(env, M68K_FEATURE_BRAL);
124: m68k_set_feature(env, M68K_FEATURE_CF_FPU);
125: /* MAC and EMAC are mututally exclusive, so pick EMAC.
126: It's mostly backwards compatible. */
127: m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
128: m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
129: m68k_set_feature(env, M68K_FEATURE_USP);
130: m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
131: m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
132: break;
133: }
134:
135: register_m68k_insns(env);
1.1.1.3 ! root 136: if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
! 137: gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
! 138: 11, "cf-fp.xml", 18);
! 139: }
! 140: /* TODO: Add [E]MAC registers. */
1.1.1.2 root 141: return 0;
142: }
143:
144: void cpu_reset(CPUM68KState *env)
145: {
1.1.1.3 ! root 146: if (qemu_loglevel_mask(CPU_LOG_RESET)) {
! 147: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
! 148: log_cpu_state(env, 0);
! 149: }
! 150:
1.1.1.2 root 151: memset(env, 0, offsetof(CPUM68KState, breakpoints));
152: #if !defined (CONFIG_USER_ONLY)
153: env->sr = 0x2700;
154: #endif
155: m68k_switch_sp(env);
156: /* ??? FP regs should be initialized to NaN. */
157: env->cc_op = CC_OP_FLAGS;
158: /* TODO: We should set PC from the interrupt vector. */
159: env->pc = 0;
160: tlb_flush(env, 1);
161: }
162:
163: CPUM68KState *cpu_m68k_init(const char *cpu_model)
164: {
165: CPUM68KState *env;
1.1.1.3 ! root 166: static int inited;
1.1.1.2 root 167:
1.1.1.3 ! root 168: env = qemu_mallocz(sizeof(CPUM68KState));
1.1.1.2 root 169: cpu_exec_init(env);
1.1.1.3 ! root 170: if (!inited) {
! 171: inited = 1;
! 172: m68k_tcg_init();
! 173: }
1.1.1.2 root 174:
175: env->cpu_model_str = cpu_model;
176:
177: if (cpu_m68k_set_model(env, cpu_model) < 0) {
178: cpu_m68k_close(env);
179: return NULL;
180: }
181:
182: cpu_reset(env);
183: return env;
184: }
185:
186: void cpu_m68k_close(CPUM68KState *env)
187: {
188: qemu_free(env);
189: }
190:
1.1 root 191: void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
192: {
193: int flags;
194: uint32_t src;
195: uint32_t dest;
196: uint32_t tmp;
197:
198: #define HIGHBIT 0x80000000u
199:
200: #define SET_NZ(x) do { \
201: if ((x) == 0) \
202: flags |= CCF_Z; \
203: else if ((int32_t)(x) < 0) \
204: flags |= CCF_N; \
205: } while (0)
206:
207: #define SET_FLAGS_SUB(type, utype) do { \
208: SET_NZ((type)dest); \
209: tmp = dest + src; \
210: if ((utype) tmp < (utype) src) \
211: flags |= CCF_C; \
212: if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
213: flags |= CCF_V; \
214: } while (0)
215:
216: flags = 0;
217: src = env->cc_src;
218: dest = env->cc_dest;
219: switch (cc_op) {
220: case CC_OP_FLAGS:
221: flags = dest;
222: break;
223: case CC_OP_LOGIC:
224: SET_NZ(dest);
225: break;
226: case CC_OP_ADD:
227: SET_NZ(dest);
228: if (dest < src)
229: flags |= CCF_C;
230: tmp = dest - src;
231: if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
232: flags |= CCF_V;
233: break;
234: case CC_OP_SUB:
235: SET_FLAGS_SUB(int32_t, uint32_t);
236: break;
237: case CC_OP_CMPB:
238: SET_FLAGS_SUB(int8_t, uint8_t);
239: break;
240: case CC_OP_CMPW:
241: SET_FLAGS_SUB(int16_t, uint16_t);
242: break;
243: case CC_OP_ADDX:
244: SET_NZ(dest);
245: if (dest <= src)
246: flags |= CCF_C;
247: tmp = dest - src - 1;
248: if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
249: flags |= CCF_V;
250: break;
251: case CC_OP_SUBX:
252: SET_NZ(dest);
253: tmp = dest + src + 1;
254: if (tmp <= src)
255: flags |= CCF_C;
256: if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
257: flags |= CCF_V;
258: break;
1.1.1.3 ! root 259: case CC_OP_SHIFT:
! 260: SET_NZ(dest);
! 261: if (src)
1.1 root 262: flags |= CCF_C;
263: break;
264: default:
265: cpu_abort(env, "Bad CC_OP %d", cc_op);
266: }
267: env->cc_op = CC_OP_FLAGS;
268: env->cc_dest = flags;
269: }
270:
1.1.1.3 ! root 271: void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
1.1.1.2 root 272: {
273: switch (reg) {
274: case 0x02: /* CACR */
275: env->cacr = val;
276: m68k_switch_sp(env);
277: break;
278: case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
279: /* TODO: Implement Access Control Registers. */
280: break;
281: case 0x801: /* VBR */
282: env->vbr = val;
283: break;
284: /* TODO: Implement control registers. */
285: default:
286: cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
287: reg, val);
288: }
289: }
290:
1.1.1.3 ! root 291: void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
1.1.1.2 root 292: {
293: uint32_t acc;
294: int8_t exthigh;
295: uint8_t extlow;
296: uint64_t regval;
297: int i;
298: if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
299: for (i = 0; i < 4; i++) {
300: regval = env->macc[i];
301: exthigh = regval >> 40;
302: if (env->macsr & MACSR_FI) {
303: acc = regval >> 8;
304: extlow = regval;
305: } else {
306: acc = regval;
307: extlow = regval >> 32;
308: }
309: if (env->macsr & MACSR_FI) {
310: regval = (((uint64_t)acc) << 8) | extlow;
311: regval |= ((int64_t)exthigh) << 40;
312: } else if (env->macsr & MACSR_SU) {
313: regval = acc | (((int64_t)extlow) << 32);
314: regval |= ((int64_t)exthigh) << 40;
315: } else {
316: regval = acc | (((uint64_t)extlow) << 32);
317: regval |= ((uint64_t)(uint8_t)exthigh) << 40;
318: }
319: env->macc[i] = regval;
320: }
321: }
322: env->macsr = val;
323: }
324:
325: void m68k_switch_sp(CPUM68KState *env)
326: {
327: int new_sp;
328:
329: env->sp[env->current_sp] = env->aregs[7];
330: new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
331: ? M68K_SSP : M68K_USP;
332: env->aregs[7] = env->sp[new_sp];
333: env->current_sp = new_sp;
334: }
335:
336: /* MMU */
337:
338: /* TODO: This will need fixing once the MMU is implemented. */
339: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
340: {
341: return addr;
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:
356: int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
357: int mmu_idx, int is_softmmu)
358: {
359: int prot;
360:
361: address &= TARGET_PAGE_MASK;
362: prot = PAGE_READ | PAGE_WRITE;
363: return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
364: }
365:
366: /* Notify CPU of a pending interrupt. Prioritization and vectoring should
367: be handled by the interrupt controller. Real hardware only requests
368: the vector when the interrupt is acknowledged by the CPU. For
369: simplicitly we calculate it when the interrupt is signalled. */
370: void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
371: {
372: env->pending_level = level;
373: env->pending_vector = vector;
374: if (level)
375: cpu_interrupt(env, CPU_INTERRUPT_HARD);
376: else
377: cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
378: }
379:
380: #endif
1.1.1.3 ! root 381:
! 382: uint32_t HELPER(bitrev)(uint32_t x)
! 383: {
! 384: x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
! 385: x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
! 386: x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
! 387: return bswap32(x);
! 388: }
! 389:
! 390: uint32_t HELPER(ff1)(uint32_t x)
! 391: {
! 392: int n;
! 393: for (n = 32; x; n--)
! 394: x >>= 1;
! 395: return n;
! 396: }
! 397:
! 398: uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
! 399: {
! 400: /* The result has the opposite sign to the original value. */
! 401: if (ccr & CCF_V)
! 402: val = (((int32_t)val) >> 31) ^ SIGNBIT;
! 403: return val;
! 404: }
! 405:
! 406: uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
! 407: {
! 408: uint32_t res;
! 409: uint32_t old_flags;
! 410:
! 411: old_flags = env->cc_dest;
! 412: if (env->cc_x) {
! 413: env->cc_x = (op1 <= op2);
! 414: env->cc_op = CC_OP_SUBX;
! 415: res = op1 - (op2 + 1);
! 416: } else {
! 417: env->cc_x = (op1 < op2);
! 418: env->cc_op = CC_OP_SUB;
! 419: res = op1 - op2;
! 420: }
! 421: env->cc_dest = res;
! 422: env->cc_src = op2;
! 423: cpu_m68k_flush_flags(env, env->cc_op);
! 424: /* !Z is sticky. */
! 425: env->cc_dest &= (old_flags | ~CCF_Z);
! 426: return res;
! 427: }
! 428:
! 429: uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
! 430: {
! 431: uint32_t res;
! 432: uint32_t old_flags;
! 433:
! 434: old_flags = env->cc_dest;
! 435: if (env->cc_x) {
! 436: res = op1 + op2 + 1;
! 437: env->cc_x = (res <= op2);
! 438: env->cc_op = CC_OP_ADDX;
! 439: } else {
! 440: res = op1 + op2;
! 441: env->cc_x = (res < op2);
! 442: env->cc_op = CC_OP_ADD;
! 443: }
! 444: env->cc_dest = res;
! 445: env->cc_src = op2;
! 446: cpu_m68k_flush_flags(env, env->cc_op);
! 447: /* !Z is sticky. */
! 448: env->cc_dest &= (old_flags | ~CCF_Z);
! 449: return res;
! 450: }
! 451:
! 452: uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
! 453: {
! 454: return a < b;
! 455: }
! 456:
! 457: uint32_t HELPER(btest)(uint32_t x)
! 458: {
! 459: return x != 0;
! 460: }
! 461:
! 462: void HELPER(set_sr)(CPUState *env, uint32_t val)
! 463: {
! 464: env->sr = val & 0xffff;
! 465: m68k_switch_sp(env);
! 466: }
! 467:
! 468: uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
! 469: {
! 470: uint32_t result;
! 471: uint32_t cf;
! 472:
! 473: shift &= 63;
! 474: if (shift == 0) {
! 475: result = val;
! 476: cf = env->cc_src & CCF_C;
! 477: } else if (shift < 32) {
! 478: result = val << shift;
! 479: cf = (val >> (32 - shift)) & 1;
! 480: } else if (shift == 32) {
! 481: result = 0;
! 482: cf = val & 1;
! 483: } else /* shift > 32 */ {
! 484: result = 0;
! 485: cf = 0;
! 486: }
! 487: env->cc_src = cf;
! 488: env->cc_x = (cf != 0);
! 489: env->cc_dest = result;
! 490: return result;
! 491: }
! 492:
! 493: uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
! 494: {
! 495: uint32_t result;
! 496: uint32_t cf;
! 497:
! 498: shift &= 63;
! 499: if (shift == 0) {
! 500: result = val;
! 501: cf = env->cc_src & CCF_C;
! 502: } else if (shift < 32) {
! 503: result = val >> shift;
! 504: cf = (val >> (shift - 1)) & 1;
! 505: } else if (shift == 32) {
! 506: result = 0;
! 507: cf = val >> 31;
! 508: } else /* shift > 32 */ {
! 509: result = 0;
! 510: cf = 0;
! 511: }
! 512: env->cc_src = cf;
! 513: env->cc_x = (cf != 0);
! 514: env->cc_dest = result;
! 515: return result;
! 516: }
! 517:
! 518: uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
! 519: {
! 520: uint32_t result;
! 521: uint32_t cf;
! 522:
! 523: shift &= 63;
! 524: if (shift == 0) {
! 525: result = val;
! 526: cf = (env->cc_src & CCF_C) != 0;
! 527: } else if (shift < 32) {
! 528: result = (int32_t)val >> shift;
! 529: cf = (val >> (shift - 1)) & 1;
! 530: } else /* shift >= 32 */ {
! 531: result = (int32_t)val >> 31;
! 532: cf = val >> 31;
! 533: }
! 534: env->cc_src = cf;
! 535: env->cc_x = cf;
! 536: env->cc_dest = result;
! 537: return result;
! 538: }
! 539:
! 540: /* FPU helpers. */
! 541: uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
! 542: {
! 543: return float64_to_int32(val, &env->fp_status);
! 544: }
! 545:
! 546: float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
! 547: {
! 548: return float64_to_float32(val, &env->fp_status);
! 549: }
! 550:
! 551: float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
! 552: {
! 553: return int32_to_float64(val, &env->fp_status);
! 554: }
! 555:
! 556: float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
! 557: {
! 558: return float32_to_float64(val, &env->fp_status);
! 559: }
! 560:
! 561: float64 HELPER(iround_f64)(CPUState *env, float64 val)
! 562: {
! 563: return float64_round_to_int(val, &env->fp_status);
! 564: }
! 565:
! 566: float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
! 567: {
! 568: return float64_trunc_to_int(val, &env->fp_status);
! 569: }
! 570:
! 571: float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
! 572: {
! 573: return float64_sqrt(val, &env->fp_status);
! 574: }
! 575:
! 576: float64 HELPER(abs_f64)(float64 val)
! 577: {
! 578: return float64_abs(val);
! 579: }
! 580:
! 581: float64 HELPER(chs_f64)(float64 val)
! 582: {
! 583: return float64_chs(val);
! 584: }
! 585:
! 586: float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
! 587: {
! 588: return float64_add(a, b, &env->fp_status);
! 589: }
! 590:
! 591: float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
! 592: {
! 593: return float64_sub(a, b, &env->fp_status);
! 594: }
! 595:
! 596: float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
! 597: {
! 598: return float64_mul(a, b, &env->fp_status);
! 599: }
! 600:
! 601: float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
! 602: {
! 603: return float64_div(a, b, &env->fp_status);
! 604: }
! 605:
! 606: float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
! 607: {
! 608: /* ??? This may incorrectly raise exceptions. */
! 609: /* ??? Should flush denormals to zero. */
! 610: float64 res;
! 611: res = float64_sub(a, b, &env->fp_status);
! 612: if (float64_is_nan(res)) {
! 613: /* +/-inf compares equal against itself, but sub returns nan. */
! 614: if (!float64_is_nan(a)
! 615: && !float64_is_nan(b)) {
! 616: res = float64_zero;
! 617: if (float64_lt_quiet(a, res, &env->fp_status))
! 618: res = float64_chs(res);
! 619: }
! 620: }
! 621: return res;
! 622: }
! 623:
! 624: uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
! 625: {
! 626: return float64_compare_quiet(val, float64_zero, &env->fp_status);
! 627: }
! 628:
! 629: /* MAC unit. */
! 630: /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
! 631: take values, others take register numbers and manipulate the contents
! 632: in-place. */
! 633: void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
! 634: {
! 635: uint32_t mask;
! 636: env->macc[dest] = env->macc[src];
! 637: mask = MACSR_PAV0 << dest;
! 638: if (env->macsr & (MACSR_PAV0 << src))
! 639: env->macsr |= mask;
! 640: else
! 641: env->macsr &= ~mask;
! 642: }
! 643:
! 644: uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
! 645: {
! 646: int64_t product;
! 647: int64_t res;
! 648:
! 649: product = (uint64_t)op1 * op2;
! 650: res = (product << 24) >> 24;
! 651: if (res != product) {
! 652: env->macsr |= MACSR_V;
! 653: if (env->macsr & MACSR_OMC) {
! 654: /* Make sure the accumulate operation overflows. */
! 655: if (product < 0)
! 656: res = ~(1ll << 50);
! 657: else
! 658: res = 1ll << 50;
! 659: }
! 660: }
! 661: return res;
! 662: }
! 663:
! 664: uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
! 665: {
! 666: uint64_t product;
! 667:
! 668: product = (uint64_t)op1 * op2;
! 669: if (product & (0xffffffull << 40)) {
! 670: env->macsr |= MACSR_V;
! 671: if (env->macsr & MACSR_OMC) {
! 672: /* Make sure the accumulate operation overflows. */
! 673: product = 1ll << 50;
! 674: } else {
! 675: product &= ((1ull << 40) - 1);
! 676: }
! 677: }
! 678: return product;
! 679: }
! 680:
! 681: uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
! 682: {
! 683: uint64_t product;
! 684: uint32_t remainder;
! 685:
! 686: product = (uint64_t)op1 * op2;
! 687: if (env->macsr & MACSR_RT) {
! 688: remainder = product & 0xffffff;
! 689: product >>= 24;
! 690: if (remainder > 0x800000)
! 691: product++;
! 692: else if (remainder == 0x800000)
! 693: product += (product & 1);
! 694: } else {
! 695: product >>= 24;
! 696: }
! 697: return product;
! 698: }
! 699:
! 700: void HELPER(macsats)(CPUState *env, uint32_t acc)
! 701: {
! 702: int64_t tmp;
! 703: int64_t result;
! 704: tmp = env->macc[acc];
! 705: result = ((tmp << 16) >> 16);
! 706: if (result != tmp) {
! 707: env->macsr |= MACSR_V;
! 708: }
! 709: if (env->macsr & MACSR_V) {
! 710: env->macsr |= MACSR_PAV0 << acc;
! 711: if (env->macsr & MACSR_OMC) {
! 712: /* The result is saturated to 32 bits, despite overflow occuring
! 713: at 48 bits. Seems weird, but that's what the hardware docs
! 714: say. */
! 715: result = (result >> 63) ^ 0x7fffffff;
! 716: }
! 717: }
! 718: env->macc[acc] = result;
! 719: }
! 720:
! 721: void HELPER(macsatu)(CPUState *env, uint32_t acc)
! 722: {
! 723: uint64_t val;
! 724:
! 725: val = env->macc[acc];
! 726: if (val & (0xffffull << 48)) {
! 727: env->macsr |= MACSR_V;
! 728: }
! 729: if (env->macsr & MACSR_V) {
! 730: env->macsr |= MACSR_PAV0 << acc;
! 731: if (env->macsr & MACSR_OMC) {
! 732: if (val > (1ull << 53))
! 733: val = 0;
! 734: else
! 735: val = (1ull << 48) - 1;
! 736: } else {
! 737: val &= ((1ull << 48) - 1);
! 738: }
! 739: }
! 740: env->macc[acc] = val;
! 741: }
! 742:
! 743: void HELPER(macsatf)(CPUState *env, uint32_t acc)
! 744: {
! 745: int64_t sum;
! 746: int64_t result;
! 747:
! 748: sum = env->macc[acc];
! 749: result = (sum << 16) >> 16;
! 750: if (result != sum) {
! 751: env->macsr |= MACSR_V;
! 752: }
! 753: if (env->macsr & MACSR_V) {
! 754: env->macsr |= MACSR_PAV0 << acc;
! 755: if (env->macsr & MACSR_OMC) {
! 756: result = (result >> 63) ^ 0x7fffffffffffll;
! 757: }
! 758: }
! 759: env->macc[acc] = result;
! 760: }
! 761:
! 762: void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
! 763: {
! 764: uint64_t val;
! 765: val = env->macc[acc];
! 766: if (val == 0)
! 767: env->macsr |= MACSR_Z;
! 768: else if (val & (1ull << 47));
! 769: env->macsr |= MACSR_N;
! 770: if (env->macsr & (MACSR_PAV0 << acc)) {
! 771: env->macsr |= MACSR_V;
! 772: }
! 773: if (env->macsr & MACSR_FI) {
! 774: val = ((int64_t)val) >> 40;
! 775: if (val != 0 && val != -1)
! 776: env->macsr |= MACSR_EV;
! 777: } else if (env->macsr & MACSR_SU) {
! 778: val = ((int64_t)val) >> 32;
! 779: if (val != 0 && val != -1)
! 780: env->macsr |= MACSR_EV;
! 781: } else {
! 782: if ((val >> 32) != 0)
! 783: env->macsr |= MACSR_EV;
! 784: }
! 785: }
! 786:
! 787: void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
! 788: {
! 789: cpu_m68k_flush_flags(env, cc_op);
! 790: }
! 791:
! 792: uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
! 793: {
! 794: int rem;
! 795: uint32_t result;
! 796:
! 797: if (env->macsr & MACSR_SU) {
! 798: /* 16-bit rounding. */
! 799: rem = val & 0xffffff;
! 800: val = (val >> 24) & 0xffffu;
! 801: if (rem > 0x800000)
! 802: val++;
! 803: else if (rem == 0x800000)
! 804: val += (val & 1);
! 805: } else if (env->macsr & MACSR_RT) {
! 806: /* 32-bit rounding. */
! 807: rem = val & 0xff;
! 808: val >>= 8;
! 809: if (rem > 0x80)
! 810: val++;
! 811: else if (rem == 0x80)
! 812: val += (val & 1);
! 813: } else {
! 814: /* No rounding. */
! 815: val >>= 8;
! 816: }
! 817: if (env->macsr & MACSR_OMC) {
! 818: /* Saturate. */
! 819: if (env->macsr & MACSR_SU) {
! 820: if (val != (uint16_t) val) {
! 821: result = ((val >> 63) ^ 0x7fff) & 0xffff;
! 822: } else {
! 823: result = val & 0xffff;
! 824: }
! 825: } else {
! 826: if (val != (uint32_t)val) {
! 827: result = ((uint32_t)(val >> 63) & 0x7fffffff);
! 828: } else {
! 829: result = (uint32_t)val;
! 830: }
! 831: }
! 832: } else {
! 833: /* No saturation. */
! 834: if (env->macsr & MACSR_SU) {
! 835: result = val & 0xffff;
! 836: } else {
! 837: result = (uint32_t)val;
! 838: }
! 839: }
! 840: return result;
! 841: }
! 842:
! 843: uint32_t HELPER(get_macs)(uint64_t val)
! 844: {
! 845: if (val == (int32_t)val) {
! 846: return (int32_t)val;
! 847: } else {
! 848: return (val >> 61) ^ ~SIGNBIT;
! 849: }
! 850: }
! 851:
! 852: uint32_t HELPER(get_macu)(uint64_t val)
! 853: {
! 854: if ((val >> 32) == 0) {
! 855: return (uint32_t)val;
! 856: } else {
! 857: return 0xffffffffu;
! 858: }
! 859: }
! 860:
! 861: uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
! 862: {
! 863: uint32_t val;
! 864: val = env->macc[acc] & 0x00ff;
! 865: val = (env->macc[acc] >> 32) & 0xff00;
! 866: val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
! 867: val |= (env->macc[acc + 1] >> 16) & 0xff000000;
! 868: return val;
! 869: }
! 870:
! 871: uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
! 872: {
! 873: uint32_t val;
! 874: val = (env->macc[acc] >> 32) & 0xffff;
! 875: val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
! 876: return val;
! 877: }
! 878:
! 879: void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
! 880: {
! 881: int64_t res;
! 882: int32_t tmp;
! 883: res = env->macc[acc] & 0xffffffff00ull;
! 884: tmp = (int16_t)(val & 0xff00);
! 885: res |= ((int64_t)tmp) << 32;
! 886: res |= val & 0xff;
! 887: env->macc[acc] = res;
! 888: res = env->macc[acc + 1] & 0xffffffff00ull;
! 889: tmp = (val & 0xff000000);
! 890: res |= ((int64_t)tmp) << 16;
! 891: res |= (val >> 16) & 0xff;
! 892: env->macc[acc + 1] = res;
! 893: }
! 894:
! 895: void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
! 896: {
! 897: int64_t res;
! 898: int32_t tmp;
! 899: res = (uint32_t)env->macc[acc];
! 900: tmp = (int16_t)val;
! 901: res |= ((int64_t)tmp) << 32;
! 902: env->macc[acc] = res;
! 903: res = (uint32_t)env->macc[acc + 1];
! 904: tmp = val & 0xffff0000;
! 905: res |= (int64_t)tmp << 16;
! 906: env->macc[acc + 1] = res;
! 907: }
! 908:
! 909: void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
! 910: {
! 911: uint64_t res;
! 912: res = (uint32_t)env->macc[acc];
! 913: res |= ((uint64_t)(val & 0xffff)) << 32;
! 914: env->macc[acc] = res;
! 915: res = (uint32_t)env->macc[acc + 1];
! 916: res |= (uint64_t)(val & 0xffff0000) << 16;
! 917: env->macc[acc + 1] = res;
! 918: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.