1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "cpu.h"
23#include "exec/exec-all.h"
24#include "exec/gdbstub.h"
25
26#include "exec/helper-proto.h"
27
28#define SIGNBIT (1u << 31)
29
30
31static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
32{
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);
39 if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
40 return 1;
41 } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
42 return -1;
43 } else {
44 return strcasecmp(name_a, name_b);
45 }
46}
47
48static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
49{
50 ObjectClass *c = data;
51 CPUListState *s = user_data;
52 const char *typename;
53 char *name;
54
55 typename = object_class_get_name(c);
56 name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
57 (*s->cpu_fprintf)(s->file, "%s\n",
58 name);
59 g_free(name);
60}
61
62void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
63{
64 CPUListState s = {
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
76static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
77{
78 if (n < 8) {
79 stfq_p(mem_buf, env->fregs[n]);
80 return 8;
81 }
82 if (n < 11) {
83
84 memset(mem_buf, 0, 4);
85 return 4;
86 }
87 return 0;
88}
89
90static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
91{
92 if (n < 8) {
93 env->fregs[n] = ldfq_p(mem_buf);
94 return 8;
95 }
96 if (n < 11) {
97
98 return 4;
99 }
100 return 0;
101}
102
103M68kCPU *cpu_m68k_init(const char *cpu_model)
104{
105 M68kCPU *cpu;
106 CPUM68KState *env;
107 ObjectClass *oc;
108
109 oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model);
110 if (oc == NULL) {
111 return NULL;
112 }
113 cpu = M68K_CPU(object_new(object_class_get_name(oc)));
114 env = &cpu->env;
115
116 register_m68k_insns(env);
117
118 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
119
120 return cpu;
121}
122
123void m68k_cpu_init_gdb(M68kCPU *cpu)
124{
125 CPUState *cs = CPU(cpu);
126 CPUM68KState *env = &cpu->env;
127
128 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
129 gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg,
130 11, "cf-fp.xml", 18);
131 }
132
133}
134
135void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
136{
137 M68kCPU *cpu = m68k_env_get_cpu(env);
138
139 switch (reg) {
140 case 0x02:
141 env->cacr = val;
142 m68k_switch_sp(env);
143 break;
144 case 0x04: case 0x05: case 0x06: case 0x07:
145
146 break;
147 case 0x801:
148 env->vbr = val;
149 break;
150
151 default:
152 cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
153 reg, val);
154 }
155}
156
157void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
158{
159 uint32_t acc;
160 int8_t exthigh;
161 uint8_t extlow;
162 uint64_t regval;
163 int i;
164 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
165 for (i = 0; i < 4; i++) {
166 regval = env->macc[i];
167 exthigh = regval >> 40;
168 if (env->macsr & MACSR_FI) {
169 acc = regval >> 8;
170 extlow = regval;
171 } else {
172 acc = regval;
173 extlow = regval >> 32;
174 }
175 if (env->macsr & MACSR_FI) {
176 regval = (((uint64_t)acc) << 8) | extlow;
177 regval |= ((int64_t)exthigh) << 40;
178 } else if (env->macsr & MACSR_SU) {
179 regval = acc | (((int64_t)extlow) << 32);
180 regval |= ((int64_t)exthigh) << 40;
181 } else {
182 regval = acc | (((uint64_t)extlow) << 32);
183 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
184 }
185 env->macc[i] = regval;
186 }
187 }
188 env->macsr = val;
189}
190
191void m68k_switch_sp(CPUM68KState *env)
192{
193 int new_sp;
194
195 env->sp[env->current_sp] = env->aregs[7];
196 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
197 ? M68K_SSP : M68K_USP;
198 env->aregs[7] = env->sp[new_sp];
199 env->current_sp = new_sp;
200}
201
202#if defined(CONFIG_USER_ONLY)
203
204int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
205 int mmu_idx)
206{
207 M68kCPU *cpu = M68K_CPU(cs);
208
209 cs->exception_index = EXCP_ACCESS;
210 cpu->env.mmu.ar = address;
211 return 1;
212}
213
214#else
215
216
217
218
219hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
220{
221 return addr;
222}
223
224int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
225 int mmu_idx)
226{
227 int prot;
228
229 address &= TARGET_PAGE_MASK;
230 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
231 tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
232 return 0;
233}
234
235
236
237
238
239void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
240{
241 CPUState *cs = CPU(cpu);
242 CPUM68KState *env = &cpu->env;
243
244 env->pending_level = level;
245 env->pending_vector = vector;
246 if (level) {
247 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
248 } else {
249 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
250 }
251}
252
253#endif
254
255uint32_t HELPER(bitrev)(uint32_t x)
256{
257 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
258 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
259 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
260 return bswap32(x);
261}
262
263uint32_t HELPER(ff1)(uint32_t x)
264{
265 int n;
266 for (n = 32; x; n--)
267 x >>= 1;
268 return n;
269}
270
271uint32_t HELPER(sats)(uint32_t val, uint32_t v)
272{
273
274 if ((int32_t)v < 0) {
275 val = (((int32_t)val) >> 31) ^ SIGNBIT;
276 }
277 return val;
278}
279
280void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
281{
282 env->sr = val & 0xffe0;
283 cpu_m68k_set_ccr(env, val);
284 m68k_switch_sp(env);
285}
286
287uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
288{
289 uint64_t result;
290
291 shift &= 63;
292 result = (uint64_t)val << shift;
293
294 env->cc_c = (result >> 32) & 1;
295 env->cc_n = result;
296 env->cc_z = result;
297 env->cc_v = 0;
298 env->cc_x = shift ? env->cc_c : env->cc_x;
299
300 return result;
301}
302
303uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
304{
305 uint64_t temp;
306 uint32_t result;
307
308 shift &= 63;
309 temp = (uint64_t)val << 32 >> shift;
310 result = temp >> 32;
311
312 env->cc_c = (temp >> 31) & 1;
313 env->cc_n = result;
314 env->cc_z = result;
315 env->cc_v = 0;
316 env->cc_x = shift ? env->cc_c : env->cc_x;
317
318 return result;
319}
320
321uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
322{
323 uint64_t temp;
324 uint32_t result;
325
326 shift &= 63;
327 temp = (int64_t)val << 32 >> shift;
328 result = temp >> 32;
329
330 env->cc_c = (temp >> 31) & 1;
331 env->cc_n = result;
332 env->cc_z = result;
333 env->cc_v = result ^ val;
334 env->cc_x = shift ? env->cc_c : env->cc_x;
335
336 return result;
337}
338
339
340uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
341{
342 return float64_to_int32(val, &env->fp_status);
343}
344
345float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
346{
347 return float64_to_float32(val, &env->fp_status);
348}
349
350float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
351{
352 return int32_to_float64(val, &env->fp_status);
353}
354
355float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
356{
357 return float32_to_float64(val, &env->fp_status);
358}
359
360float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
361{
362 return float64_round_to_int(val, &env->fp_status);
363}
364
365float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
366{
367 return float64_trunc_to_int(val, &env->fp_status);
368}
369
370float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
371{
372 return float64_sqrt(val, &env->fp_status);
373}
374
375float64 HELPER(abs_f64)(float64 val)
376{
377 return float64_abs(val);
378}
379
380float64 HELPER(chs_f64)(float64 val)
381{
382 return float64_chs(val);
383}
384
385float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
386{
387 return float64_add(a, b, &env->fp_status);
388}
389
390float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
391{
392 return float64_sub(a, b, &env->fp_status);
393}
394
395float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
396{
397 return float64_mul(a, b, &env->fp_status);
398}
399
400float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
401{
402 return float64_div(a, b, &env->fp_status);
403}
404
405float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
406{
407
408
409 float64 res;
410 res = float64_sub(a, b, &env->fp_status);
411 if (float64_is_quiet_nan(res, &env->fp_status)) {
412
413 if (!float64_is_quiet_nan(a, &env->fp_status)
414 && !float64_is_quiet_nan(b, &env->fp_status)) {
415 res = float64_zero;
416 if (float64_lt_quiet(a, res, &env->fp_status))
417 res = float64_chs(res);
418 }
419 }
420 return res;
421}
422
423uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
424{
425 return float64_compare_quiet(val, float64_zero, &env->fp_status);
426}
427
428
429
430
431
432void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
433{
434 uint32_t mask;
435 env->macc[dest] = env->macc[src];
436 mask = MACSR_PAV0 << dest;
437 if (env->macsr & (MACSR_PAV0 << src))
438 env->macsr |= mask;
439 else
440 env->macsr &= ~mask;
441}
442
443uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
444{
445 int64_t product;
446 int64_t res;
447
448 product = (uint64_t)op1 * op2;
449 res = (product << 24) >> 24;
450 if (res != product) {
451 env->macsr |= MACSR_V;
452 if (env->macsr & MACSR_OMC) {
453
454 if (product < 0)
455 res = ~(1ll << 50);
456 else
457 res = 1ll << 50;
458 }
459 }
460 return res;
461}
462
463uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
464{
465 uint64_t product;
466
467 product = (uint64_t)op1 * op2;
468 if (product & (0xffffffull << 40)) {
469 env->macsr |= MACSR_V;
470 if (env->macsr & MACSR_OMC) {
471
472 product = 1ll << 50;
473 } else {
474 product &= ((1ull << 40) - 1);
475 }
476 }
477 return product;
478}
479
480uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
481{
482 uint64_t product;
483 uint32_t remainder;
484
485 product = (uint64_t)op1 * op2;
486 if (env->macsr & MACSR_RT) {
487 remainder = product & 0xffffff;
488 product >>= 24;
489 if (remainder > 0x800000)
490 product++;
491 else if (remainder == 0x800000)
492 product += (product & 1);
493 } else {
494 product >>= 24;
495 }
496 return product;
497}
498
499void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
500{
501 int64_t tmp;
502 int64_t result;
503 tmp = env->macc[acc];
504 result = ((tmp << 16) >> 16);
505 if (result != tmp) {
506 env->macsr |= MACSR_V;
507 }
508 if (env->macsr & MACSR_V) {
509 env->macsr |= MACSR_PAV0 << acc;
510 if (env->macsr & MACSR_OMC) {
511
512
513
514 result = (result >> 63) ^ 0x7fffffff;
515 }
516 }
517 env->macc[acc] = result;
518}
519
520void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
521{
522 uint64_t val;
523
524 val = env->macc[acc];
525 if (val & (0xffffull << 48)) {
526 env->macsr |= MACSR_V;
527 }
528 if (env->macsr & MACSR_V) {
529 env->macsr |= MACSR_PAV0 << acc;
530 if (env->macsr & MACSR_OMC) {
531 if (val > (1ull << 53))
532 val = 0;
533 else
534 val = (1ull << 48) - 1;
535 } else {
536 val &= ((1ull << 48) - 1);
537 }
538 }
539 env->macc[acc] = val;
540}
541
542void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
543{
544 int64_t sum;
545 int64_t result;
546
547 sum = env->macc[acc];
548 result = (sum << 16) >> 16;
549 if (result != sum) {
550 env->macsr |= MACSR_V;
551 }
552 if (env->macsr & MACSR_V) {
553 env->macsr |= MACSR_PAV0 << acc;
554 if (env->macsr & MACSR_OMC) {
555 result = (result >> 63) ^ 0x7fffffffffffll;
556 }
557 }
558 env->macc[acc] = result;
559}
560
561void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
562{
563 uint64_t val;
564 val = env->macc[acc];
565 if (val == 0) {
566 env->macsr |= MACSR_Z;
567 } else if (val & (1ull << 47)) {
568 env->macsr |= MACSR_N;
569 }
570 if (env->macsr & (MACSR_PAV0 << acc)) {
571 env->macsr |= MACSR_V;
572 }
573 if (env->macsr & MACSR_FI) {
574 val = ((int64_t)val) >> 40;
575 if (val != 0 && val != -1)
576 env->macsr |= MACSR_EV;
577 } else if (env->macsr & MACSR_SU) {
578 val = ((int64_t)val) >> 32;
579 if (val != 0 && val != -1)
580 env->macsr |= MACSR_EV;
581 } else {
582 if ((val >> 32) != 0)
583 env->macsr |= MACSR_EV;
584 }
585}
586
587#define EXTSIGN(val, index) ( \
588 (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
589)
590
591#define COMPUTE_CCR(op, x, n, z, v, c) { \
592 switch (op) { \
593 case CC_OP_FLAGS: \
594 \
595 break; \
596 case CC_OP_ADDB: \
597 case CC_OP_ADDW: \
598 case CC_OP_ADDL: \
599 res = n; \
600 src2 = v; \
601 src1 = EXTSIGN(res - src2, op - CC_OP_ADDB); \
602 c = x; \
603 z = n; \
604 v = (res ^ src1) & ~(src1 ^ src2); \
605 break; \
606 case CC_OP_SUBB: \
607 case CC_OP_SUBW: \
608 case CC_OP_SUBL: \
609 res = n; \
610 src2 = v; \
611 src1 = EXTSIGN(res + src2, op - CC_OP_SUBB); \
612 c = x; \
613 z = n; \
614 v = (res ^ src1) & (src1 ^ src2); \
615 break; \
616 case CC_OP_CMPB: \
617 case CC_OP_CMPW: \
618 case CC_OP_CMPL: \
619 src1 = n; \
620 src2 = v; \
621 res = EXTSIGN(src1 - src2, op - CC_OP_CMPB); \
622 n = res; \
623 z = res; \
624 c = src1 < src2; \
625 v = (res ^ src1) & (src1 ^ src2); \
626 break; \
627 case CC_OP_LOGIC: \
628 c = v = 0; \
629 z = n; \
630 break; \
631 default: \
632 cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op); \
633 } \
634} while (0)
635
636uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
637{
638 uint32_t x, c, n, z, v;
639 uint32_t res, src1, src2;
640
641 x = env->cc_x;
642 n = env->cc_n;
643 z = env->cc_z;
644 v = env->cc_v;
645 c = env->cc_c;
646
647 COMPUTE_CCR(env->cc_op, x, n, z, v, c);
648
649 n = n >> 31;
650 z = (z == 0);
651 v = v >> 31;
652
653 return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
654}
655
656uint32_t HELPER(get_ccr)(CPUM68KState *env)
657{
658 return cpu_m68k_get_ccr(env);
659}
660
661void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
662{
663 env->cc_x = (ccr & CCF_X ? 1 : 0);
664 env->cc_n = (ccr & CCF_N ? -1 : 0);
665 env->cc_z = (ccr & CCF_Z ? 0 : 1);
666 env->cc_v = (ccr & CCF_V ? -1 : 0);
667 env->cc_c = (ccr & CCF_C ? 1 : 0);
668 env->cc_op = CC_OP_FLAGS;
669}
670
671void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
672{
673 cpu_m68k_set_ccr(env, ccr);
674}
675
676void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
677{
678 uint32_t res, src1, src2;
679
680 COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
681 env->cc_op = CC_OP_FLAGS;
682}
683
684uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
685{
686 int rem;
687 uint32_t result;
688
689 if (env->macsr & MACSR_SU) {
690
691 rem = val & 0xffffff;
692 val = (val >> 24) & 0xffffu;
693 if (rem > 0x800000)
694 val++;
695 else if (rem == 0x800000)
696 val += (val & 1);
697 } else if (env->macsr & MACSR_RT) {
698
699 rem = val & 0xff;
700 val >>= 8;
701 if (rem > 0x80)
702 val++;
703 else if (rem == 0x80)
704 val += (val & 1);
705 } else {
706
707 val >>= 8;
708 }
709 if (env->macsr & MACSR_OMC) {
710
711 if (env->macsr & MACSR_SU) {
712 if (val != (uint16_t) val) {
713 result = ((val >> 63) ^ 0x7fff) & 0xffff;
714 } else {
715 result = val & 0xffff;
716 }
717 } else {
718 if (val != (uint32_t)val) {
719 result = ((uint32_t)(val >> 63) & 0x7fffffff);
720 } else {
721 result = (uint32_t)val;
722 }
723 }
724 } else {
725
726 if (env->macsr & MACSR_SU) {
727 result = val & 0xffff;
728 } else {
729 result = (uint32_t)val;
730 }
731 }
732 return result;
733}
734
735uint32_t HELPER(get_macs)(uint64_t val)
736{
737 if (val == (int32_t)val) {
738 return (int32_t)val;
739 } else {
740 return (val >> 61) ^ ~SIGNBIT;
741 }
742}
743
744uint32_t HELPER(get_macu)(uint64_t val)
745{
746 if ((val >> 32) == 0) {
747 return (uint32_t)val;
748 } else {
749 return 0xffffffffu;
750 }
751}
752
753uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
754{
755 uint32_t val;
756 val = env->macc[acc] & 0x00ff;
757 val |= (env->macc[acc] >> 32) & 0xff00;
758 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
759 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
760 return val;
761}
762
763uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
764{
765 uint32_t val;
766 val = (env->macc[acc] >> 32) & 0xffff;
767 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
768 return val;
769}
770
771void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
772{
773 int64_t res;
774 int32_t tmp;
775 res = env->macc[acc] & 0xffffffff00ull;
776 tmp = (int16_t)(val & 0xff00);
777 res |= ((int64_t)tmp) << 32;
778 res |= val & 0xff;
779 env->macc[acc] = res;
780 res = env->macc[acc + 1] & 0xffffffff00ull;
781 tmp = (val & 0xff000000);
782 res |= ((int64_t)tmp) << 16;
783 res |= (val >> 16) & 0xff;
784 env->macc[acc + 1] = res;
785}
786
787void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
788{
789 int64_t res;
790 int32_t tmp;
791 res = (uint32_t)env->macc[acc];
792 tmp = (int16_t)val;
793 res |= ((int64_t)tmp) << 32;
794 env->macc[acc] = res;
795 res = (uint32_t)env->macc[acc + 1];
796 tmp = val & 0xffff0000;
797 res |= (int64_t)tmp << 16;
798 env->macc[acc + 1] = res;
799}
800
801void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
802{
803 uint64_t res;
804 res = (uint32_t)env->macc[acc];
805 res |= ((uint64_t)(val & 0xffff)) << 32;
806 env->macc[acc] = res;
807 res = (uint32_t)env->macc[acc + 1];
808 res |= (uint64_t)(val & 0xffff0000) << 16;
809 env->macc[acc + 1] = res;
810}
811