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