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