]> git.proxmox.com Git - mirror_qemu.git/blame - target-m68k/helper.c
mcf_intc: Pass M68kCPU to mcf_intc_init()
[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. */
a8170e5e 293hwaddr cpu_get_phys_page_debug(CPUM68KState *env, target_ulong 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. */
313void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
314{
315 env->pending_level = level;
316 env->pending_vector = vector;
317 if (level)
318 cpu_interrupt(env, CPU_INTERRUPT_HARD);
319 else
320 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
321}
322
323#endif
e1f3808e
PB
324
325uint32_t HELPER(bitrev)(uint32_t x)
326{
327 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
328 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
329 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
330 return bswap32(x);
331}
332
333uint32_t HELPER(ff1)(uint32_t x)
334{
335 int n;
336 for (n = 32; x; n--)
337 x >>= 1;
338 return n;
339}
340
341uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
342{
343 /* The result has the opposite sign to the original value. */
344 if (ccr & CCF_V)
345 val = (((int32_t)val) >> 31) ^ SIGNBIT;
346 return val;
347}
348
2b3e3cfe 349uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
350{
351 uint32_t res;
352 uint32_t old_flags;
353
354 old_flags = env->cc_dest;
355 if (env->cc_x) {
356 env->cc_x = (op1 <= op2);
357 env->cc_op = CC_OP_SUBX;
358 res = op1 - (op2 + 1);
359 } else {
360 env->cc_x = (op1 < op2);
361 env->cc_op = CC_OP_SUB;
362 res = op1 - op2;
363 }
364 env->cc_dest = res;
365 env->cc_src = op2;
366 cpu_m68k_flush_flags(env, env->cc_op);
367 /* !Z is sticky. */
368 env->cc_dest &= (old_flags | ~CCF_Z);
369 return res;
370}
371
2b3e3cfe 372uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
373{
374 uint32_t res;
375 uint32_t old_flags;
376
377 old_flags = env->cc_dest;
378 if (env->cc_x) {
379 res = op1 + op2 + 1;
380 env->cc_x = (res <= op2);
381 env->cc_op = CC_OP_ADDX;
382 } else {
383 res = op1 + op2;
384 env->cc_x = (res < op2);
385 env->cc_op = CC_OP_ADD;
386 }
387 env->cc_dest = res;
388 env->cc_src = op2;
389 cpu_m68k_flush_flags(env, env->cc_op);
390 /* !Z is sticky. */
391 env->cc_dest &= (old_flags | ~CCF_Z);
392 return res;
393}
394
395uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
396{
397 return a < b;
398}
399
2b3e3cfe 400void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
e1f3808e
PB
401{
402 env->sr = val & 0xffff;
403 m68k_switch_sp(env);
404}
405
2b3e3cfe 406uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e
PB
407{
408 uint32_t result;
409 uint32_t cf;
410
411 shift &= 63;
412 if (shift == 0) {
413 result = val;
414 cf = env->cc_src & CCF_C;
415 } else if (shift < 32) {
416 result = val << shift;
417 cf = (val >> (32 - shift)) & 1;
418 } else if (shift == 32) {
419 result = 0;
420 cf = val & 1;
421 } else /* shift > 32 */ {
422 result = 0;
423 cf = 0;
424 }
425 env->cc_src = cf;
426 env->cc_x = (cf != 0);
427 env->cc_dest = result;
428 return result;
429}
430
2b3e3cfe 431uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e
PB
432{
433 uint32_t result;
434 uint32_t cf;
435
436 shift &= 63;
437 if (shift == 0) {
438 result = val;
439 cf = env->cc_src & CCF_C;
440 } else if (shift < 32) {
441 result = val >> shift;
442 cf = (val >> (shift - 1)) & 1;
443 } else if (shift == 32) {
444 result = 0;
445 cf = val >> 31;
446 } else /* shift > 32 */ {
447 result = 0;
448 cf = 0;
449 }
450 env->cc_src = cf;
451 env->cc_x = (cf != 0);
452 env->cc_dest = result;
453 return result;
454}
455
2b3e3cfe 456uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e
PB
457{
458 uint32_t result;
459 uint32_t cf;
460
461 shift &= 63;
462 if (shift == 0) {
463 result = val;
464 cf = (env->cc_src & CCF_C) != 0;
465 } else if (shift < 32) {
466 result = (int32_t)val >> shift;
467 cf = (val >> (shift - 1)) & 1;
468 } else /* shift >= 32 */ {
469 result = (int32_t)val >> 31;
470 cf = val >> 31;
471 }
472 env->cc_src = cf;
473 env->cc_x = cf;
474 env->cc_dest = result;
475 return result;
476}
477
478/* FPU helpers. */
2b3e3cfe 479uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
e1f3808e
PB
480{
481 return float64_to_int32(val, &env->fp_status);
482}
483
2b3e3cfe 484float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
e1f3808e
PB
485{
486 return float64_to_float32(val, &env->fp_status);
487}
488
2b3e3cfe 489float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
e1f3808e
PB
490{
491 return int32_to_float64(val, &env->fp_status);
492}
493
2b3e3cfe 494float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
e1f3808e
PB
495{
496 return float32_to_float64(val, &env->fp_status);
497}
498
2b3e3cfe 499float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
500{
501 return float64_round_to_int(val, &env->fp_status);
502}
503
2b3e3cfe 504float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
505{
506 return float64_trunc_to_int(val, &env->fp_status);
507}
508
2b3e3cfe 509float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
510{
511 return float64_sqrt(val, &env->fp_status);
512}
513
514float64 HELPER(abs_f64)(float64 val)
515{
516 return float64_abs(val);
517}
518
519float64 HELPER(chs_f64)(float64 val)
520{
521 return float64_chs(val);
522}
523
2b3e3cfe 524float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
525{
526 return float64_add(a, b, &env->fp_status);
527}
528
2b3e3cfe 529float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
530{
531 return float64_sub(a, b, &env->fp_status);
532}
533
2b3e3cfe 534float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
535{
536 return float64_mul(a, b, &env->fp_status);
537}
538
2b3e3cfe 539float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
540{
541 return float64_div(a, b, &env->fp_status);
542}
543
2b3e3cfe 544float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
545{
546 /* ??? This may incorrectly raise exceptions. */
547 /* ??? Should flush denormals to zero. */
548 float64 res;
549 res = float64_sub(a, b, &env->fp_status);
18569871 550 if (float64_is_quiet_nan(res)) {
e1f3808e 551 /* +/-inf compares equal against itself, but sub returns nan. */
18569871
PM
552 if (!float64_is_quiet_nan(a)
553 && !float64_is_quiet_nan(b)) {
e1f3808e
PB
554 res = float64_zero;
555 if (float64_lt_quiet(a, res, &env->fp_status))
556 res = float64_chs(res);
557 }
558 }
559 return res;
560}
561
2b3e3cfe 562uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
563{
564 return float64_compare_quiet(val, float64_zero, &env->fp_status);
565}
566
567/* MAC unit. */
568/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
569 take values, others take register numbers and manipulate the contents
570 in-place. */
2b3e3cfe 571void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
e1f3808e
PB
572{
573 uint32_t mask;
574 env->macc[dest] = env->macc[src];
575 mask = MACSR_PAV0 << dest;
576 if (env->macsr & (MACSR_PAV0 << src))
577 env->macsr |= mask;
578 else
579 env->macsr &= ~mask;
580}
581
2b3e3cfe 582uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
583{
584 int64_t product;
585 int64_t res;
586
587 product = (uint64_t)op1 * op2;
588 res = (product << 24) >> 24;
589 if (res != product) {
590 env->macsr |= MACSR_V;
591 if (env->macsr & MACSR_OMC) {
592 /* Make sure the accumulate operation overflows. */
593 if (product < 0)
594 res = ~(1ll << 50);
595 else
596 res = 1ll << 50;
597 }
598 }
599 return res;
600}
601
2b3e3cfe 602uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
603{
604 uint64_t product;
605
606 product = (uint64_t)op1 * op2;
607 if (product & (0xffffffull << 40)) {
608 env->macsr |= MACSR_V;
609 if (env->macsr & MACSR_OMC) {
610 /* Make sure the accumulate operation overflows. */
611 product = 1ll << 50;
612 } else {
613 product &= ((1ull << 40) - 1);
614 }
615 }
616 return product;
617}
618
2b3e3cfe 619uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
620{
621 uint64_t product;
622 uint32_t remainder;
623
624 product = (uint64_t)op1 * op2;
625 if (env->macsr & MACSR_RT) {
626 remainder = product & 0xffffff;
627 product >>= 24;
628 if (remainder > 0x800000)
629 product++;
630 else if (remainder == 0x800000)
631 product += (product & 1);
632 } else {
633 product >>= 24;
634 }
635 return product;
636}
637
2b3e3cfe 638void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
639{
640 int64_t tmp;
641 int64_t result;
642 tmp = env->macc[acc];
643 result = ((tmp << 16) >> 16);
644 if (result != tmp) {
645 env->macsr |= MACSR_V;
646 }
647 if (env->macsr & MACSR_V) {
648 env->macsr |= MACSR_PAV0 << acc;
649 if (env->macsr & MACSR_OMC) {
a1c7273b 650 /* The result is saturated to 32 bits, despite overflow occurring
e1f3808e
PB
651 at 48 bits. Seems weird, but that's what the hardware docs
652 say. */
653 result = (result >> 63) ^ 0x7fffffff;
654 }
655 }
656 env->macc[acc] = result;
657}
658
2b3e3cfe 659void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
660{
661 uint64_t val;
662
663 val = env->macc[acc];
664 if (val & (0xffffull << 48)) {
665 env->macsr |= MACSR_V;
666 }
667 if (env->macsr & MACSR_V) {
668 env->macsr |= MACSR_PAV0 << acc;
669 if (env->macsr & MACSR_OMC) {
670 if (val > (1ull << 53))
671 val = 0;
672 else
673 val = (1ull << 48) - 1;
674 } else {
675 val &= ((1ull << 48) - 1);
676 }
677 }
678 env->macc[acc] = val;
679}
680
2b3e3cfe 681void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
682{
683 int64_t sum;
684 int64_t result;
685
686 sum = env->macc[acc];
687 result = (sum << 16) >> 16;
688 if (result != sum) {
689 env->macsr |= MACSR_V;
690 }
691 if (env->macsr & MACSR_V) {
692 env->macsr |= MACSR_PAV0 << acc;
693 if (env->macsr & MACSR_OMC) {
694 result = (result >> 63) ^ 0x7fffffffffffll;
695 }
696 }
697 env->macc[acc] = result;
698}
699
2b3e3cfe 700void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
701{
702 uint64_t val;
703 val = env->macc[acc];
c4162574 704 if (val == 0) {
e1f3808e 705 env->macsr |= MACSR_Z;
c4162574 706 } else if (val & (1ull << 47)) {
e1f3808e 707 env->macsr |= MACSR_N;
c4162574 708 }
e1f3808e
PB
709 if (env->macsr & (MACSR_PAV0 << acc)) {
710 env->macsr |= MACSR_V;
711 }
712 if (env->macsr & MACSR_FI) {
713 val = ((int64_t)val) >> 40;
714 if (val != 0 && val != -1)
715 env->macsr |= MACSR_EV;
716 } else if (env->macsr & MACSR_SU) {
717 val = ((int64_t)val) >> 32;
718 if (val != 0 && val != -1)
719 env->macsr |= MACSR_EV;
720 } else {
721 if ((val >> 32) != 0)
722 env->macsr |= MACSR_EV;
723 }
724}
725
2b3e3cfe 726void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
e1f3808e
PB
727{
728 cpu_m68k_flush_flags(env, cc_op);
729}
730
2b3e3cfe 731uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
e1f3808e
PB
732{
733 int rem;
734 uint32_t result;
735
736 if (env->macsr & MACSR_SU) {
737 /* 16-bit rounding. */
738 rem = val & 0xffffff;
739 val = (val >> 24) & 0xffffu;
740 if (rem > 0x800000)
741 val++;
742 else if (rem == 0x800000)
743 val += (val & 1);
744 } else if (env->macsr & MACSR_RT) {
745 /* 32-bit rounding. */
746 rem = val & 0xff;
747 val >>= 8;
748 if (rem > 0x80)
749 val++;
750 else if (rem == 0x80)
751 val += (val & 1);
752 } else {
753 /* No rounding. */
754 val >>= 8;
755 }
756 if (env->macsr & MACSR_OMC) {
757 /* Saturate. */
758 if (env->macsr & MACSR_SU) {
759 if (val != (uint16_t) val) {
760 result = ((val >> 63) ^ 0x7fff) & 0xffff;
761 } else {
762 result = val & 0xffff;
763 }
764 } else {
765 if (val != (uint32_t)val) {
766 result = ((uint32_t)(val >> 63) & 0x7fffffff);
767 } else {
768 result = (uint32_t)val;
769 }
770 }
771 } else {
772 /* No saturation. */
773 if (env->macsr & MACSR_SU) {
774 result = val & 0xffff;
775 } else {
776 result = (uint32_t)val;
777 }
778 }
779 return result;
780}
781
782uint32_t HELPER(get_macs)(uint64_t val)
783{
784 if (val == (int32_t)val) {
785 return (int32_t)val;
786 } else {
787 return (val >> 61) ^ ~SIGNBIT;
788 }
789}
790
791uint32_t HELPER(get_macu)(uint64_t val)
792{
793 if ((val >> 32) == 0) {
794 return (uint32_t)val;
795 } else {
796 return 0xffffffffu;
797 }
798}
799
2b3e3cfe 800uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
801{
802 uint32_t val;
803 val = env->macc[acc] & 0x00ff;
804 val = (env->macc[acc] >> 32) & 0xff00;
805 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
806 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
807 return val;
808}
809
2b3e3cfe 810uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
811{
812 uint32_t val;
813 val = (env->macc[acc] >> 32) & 0xffff;
814 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
815 return val;
816}
817
2b3e3cfe 818void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
819{
820 int64_t res;
821 int32_t tmp;
822 res = env->macc[acc] & 0xffffffff00ull;
823 tmp = (int16_t)(val & 0xff00);
824 res |= ((int64_t)tmp) << 32;
825 res |= val & 0xff;
826 env->macc[acc] = res;
827 res = env->macc[acc + 1] & 0xffffffff00ull;
828 tmp = (val & 0xff000000);
829 res |= ((int64_t)tmp) << 16;
830 res |= (val >> 16) & 0xff;
831 env->macc[acc + 1] = res;
832}
833
2b3e3cfe 834void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
835{
836 int64_t res;
837 int32_t tmp;
838 res = (uint32_t)env->macc[acc];
839 tmp = (int16_t)val;
840 res |= ((int64_t)tmp) << 32;
841 env->macc[acc] = res;
842 res = (uint32_t)env->macc[acc + 1];
843 tmp = val & 0xffff0000;
844 res |= (int64_t)tmp << 16;
845 env->macc[acc + 1] = res;
846}
847
2b3e3cfe 848void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
849{
850 uint64_t res;
851 res = (uint32_t)env->macc[acc];
852 res |= ((uint64_t)(val & 0xffff)) << 32;
853 env->macc[acc] = res;
854 res = (uint32_t)env->macc[acc + 1];
855 res |= (uint64_t)(val & 0xffff0000) << 16;
856 env->macc[acc + 1] = res;
857}