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