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