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