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