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