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