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