]> git.proxmox.com Git - qemu.git/blame - target-m68k/helper.c
Merge remote branch 'rth/axp-next' into alpha-merge
[qemu.git] / target-m68k / helper.c
CommitLineData
e6e5906b
PB
1/*
2 * m68k op helpers
5fafdf24 3 *
0633879f 4 * Copyright (c) 2006-2007 CodeSourcery
e6e5906b
PB
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
8167ee88 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
e6e5906b
PB
19 */
20
21#include <stdio.h>
0402f767 22#include <string.h>
e6e5906b
PB
23
24#include "config.h"
25#include "cpu.h"
26#include "exec-all.h"
ca10f867 27#include "qemu-common.h"
56aebc89 28#include "gdbstub.h"
e6e5906b 29
e1f3808e
PB
30#include "helpers.h"
31
32#define SIGNBIT (1u << 31)
33
0402f767
PB
34enum m68k_cpuid {
35 M68K_CPUID_M5206,
20dcee94 36 M68K_CPUID_M5208,
0402f767
PB
37 M68K_CPUID_CFV4E,
38 M68K_CPUID_ANY,
39};
40
c227f099 41typedef struct m68k_def_t m68k_def_t;
aaed909a 42
c227f099 43struct m68k_def_t {
0402f767
PB
44 const char * name;
45 enum m68k_cpuid id;
46};
47
c227f099 48static m68k_def_t m68k_cpu_defs[] = {
5fafdf24
TS
49 {"m5206", M68K_CPUID_M5206},
50 {"m5208", M68K_CPUID_M5208},
0402f767
PB
51 {"cfv4e", M68K_CPUID_CFV4E},
52 {"any", M68K_CPUID_ANY},
5fafdf24 53 {NULL, 0},
0402f767
PB
54};
55
9a78eead 56void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
009a4356
LV
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
56aebc89
PB
65static 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
79static 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
0402f767
PB
92static void m68k_set_feature(CPUM68KState *env, int feature)
93{
94 env->features |= (1u << feature);
95}
96
aaed909a 97static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
0402f767 98{
c227f099 99 m68k_def_t *def;
0402f767
PB
100
101 for (def = m68k_cpu_defs; def->name; def++) {
102 if (strcmp(def->name, name) == 0)
103 break;
104 }
105 if (!def->name)
aaed909a 106 return -1;
0402f767
PB
107
108 switch (def->id) {
109 case M68K_CPUID_M5206:
110 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
111 break;
20dcee94
PB
112 case M68K_CPUID_M5208:
113 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
d315c888
PB
114 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
115 m68k_set_feature(env, M68K_FEATURE_BRAL);
20dcee94
PB
116 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
117 m68k_set_feature(env, M68K_FEATURE_USP);
118 break;
0402f767
PB
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);
d315c888 122 m68k_set_feature(env, M68K_FEATURE_BRAL);
0402f767 123 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
0402f767 124 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
20dcee94 125 m68k_set_feature(env, M68K_FEATURE_USP);
0402f767
PB
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);
d315c888
PB
130 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
131 m68k_set_feature(env, M68K_FEATURE_BRAL);
0402f767 132 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
acf930aa
PB
133 /* MAC and EMAC are mututally exclusive, so pick EMAC.
134 It's mostly backwards compatible. */
0402f767 135 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
d315c888 136 m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
20dcee94 137 m68k_set_feature(env, M68K_FEATURE_USP);
0402f767 138 m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
d315c888 139 m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
0402f767
PB
140 break;
141 }
142
143 register_m68k_insns(env);
56aebc89
PB
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. */
4f6cf9e8 149 return 0;
aaed909a
FB
150}
151
152void cpu_reset(CPUM68KState *env)
153{
eca1bdf4
AL
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
aaed909a
FB
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
171CPUM68KState *cpu_m68k_init(const char *cpu_model)
172{
173 CPUM68KState *env;
e1f3808e 174 static int inited;
aaed909a 175
6ad1d22b 176 env = qemu_mallocz(sizeof(CPUM68KState));
aaed909a 177 cpu_exec_init(env);
e1f3808e
PB
178 if (!inited) {
179 inited = 1;
180 m68k_tcg_init();
181 }
aaed909a 182
01ba9816
TS
183 env->cpu_model_str = cpu_model;
184
aaed909a
FB
185 if (cpu_m68k_set_model(env, cpu_model) < 0) {
186 cpu_m68k_close(env);
187 return NULL;
188 }
01ba9816 189
aaed909a 190 cpu_reset(env);
0bf46a40 191 qemu_init_vcpu(env);
aaed909a
FB
192 return env;
193}
0402f767 194
aaed909a
FB
195void cpu_m68k_close(CPUM68KState *env)
196{
197 qemu_free(env);
0402f767
PB
198}
199
e6e5906b
PB
200void 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;
e1f3808e
PB
268 case CC_OP_SHIFT:
269 SET_NZ(dest);
270 if (src)
e6e5906b
PB
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
e1f3808e 280void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
0633879f
PB
281{
282 switch (reg) {
283 case 0x02: /* CACR */
20dcee94
PB
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. */
0633879f
PB
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
e1f3808e 300void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
acf930aa
PB
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
20dcee94
PB
334void 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
5fafdf24 345#if defined(CONFIG_USER_ONLY)
0633879f
PB
346
347int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
6ebbf390 348 int mmu_idx, int is_softmmu)
0633879f
PB
349{
350 env->exception_index = EXCP_ACCESS;
351 env->mmu.ar = address;
352 return 1;
353}
354
355#else
356
4fcc562b
PB
357/* MMU */
358
359/* TODO: This will need fixing once the MMU is implemented. */
360target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
361{
362 return addr;
363}
364
0633879f 365int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
6ebbf390 366 int mmu_idx, int is_softmmu)
0633879f
PB
367{
368 int prot;
369
370 address &= TARGET_PAGE_MASK;
d4c430a8
PB
371 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
372 tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
373 return 0;
0633879f
PB
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. */
380void 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
e1f3808e
PB
391
392uint32_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
400uint32_t HELPER(ff1)(uint32_t x)
401{
402 int n;
403 for (n = 32; x; n--)
404 x >>= 1;
405 return n;
406}
407
408uint32_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
416uint32_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
439uint32_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
462uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
463{
464 return a < b;
465}
466
e1f3808e
PB
467void HELPER(set_sr)(CPUState *env, uint32_t val)
468{
469 env->sr = val & 0xffff;
470 m68k_switch_sp(env);
471}
472
473uint32_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
498uint32_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
523uint32_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. */
546uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
547{
548 return float64_to_int32(val, &env->fp_status);
549}
550
551float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
552{
553 return float64_to_float32(val, &env->fp_status);
554}
555
556float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
557{
558 return int32_to_float64(val, &env->fp_status);
559}
560
561float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
562{
563 return float32_to_float64(val, &env->fp_status);
564}
565
566float64 HELPER(iround_f64)(CPUState *env, float64 val)
567{
568 return float64_round_to_int(val, &env->fp_status);
569}
570
571float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
572{
573 return float64_trunc_to_int(val, &env->fp_status);
574}
575
576float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
577{
578 return float64_sqrt(val, &env->fp_status);
579}
580
581float64 HELPER(abs_f64)(float64 val)
582{
583 return float64_abs(val);
584}
585
586float64 HELPER(chs_f64)(float64 val)
587{
588 return float64_chs(val);
589}
590
591float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
592{
593 return float64_add(a, b, &env->fp_status);
594}
595
596float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
597{
598 return float64_sub(a, b, &env->fp_status);
599}
600
601float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
602{
603 return float64_mul(a, b, &env->fp_status);
604}
605
606float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
607{
608 return float64_div(a, b, &env->fp_status);
609}
610
611float64 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);
18569871 617 if (float64_is_quiet_nan(res)) {
e1f3808e 618 /* +/-inf compares equal against itself, but sub returns nan. */
18569871
PM
619 if (!float64_is_quiet_nan(a)
620 && !float64_is_quiet_nan(b)) {
e1f3808e
PB
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
629uint32_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. */
638void 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
649uint64_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
669uint64_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
686uint64_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
705void 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) {
a1c7273b 717 /* The result is saturated to 32 bits, despite overflow occurring
e1f3808e
PB
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
726void 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
748void 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
767void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
768{
769 uint64_t val;
770 val = env->macc[acc];
c4162574 771 if (val == 0) {
e1f3808e 772 env->macsr |= MACSR_Z;
c4162574 773 } else if (val & (1ull << 47)) {
e1f3808e 774 env->macsr |= MACSR_N;
c4162574 775 }
e1f3808e
PB
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
793void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
794{
795 cpu_m68k_flush_flags(env, cc_op);
796}
797
798uint32_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
849uint32_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
858uint32_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
867uint32_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
877uint32_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
885void 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
901void 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
915void 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}