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