32x and sms savestates. Core-independent z80 state. SS bugfixing/refactoring.
[picodrive.git] / cpu / sh2 / sh2.c
1 #include <string.h>
2 #include <stddef.h>
3
4 #include "sh2.h"
5 #include "../debug.h"
6 #include "compiler.h"
7
8 #define I 0xf0
9
10 SH2 *sh2; // active sh2
11
12 int sh2_init(SH2 *sh2, int is_slave)
13 {
14         int ret = 0;
15
16         memset(sh2, 0, sizeof(*sh2));
17         sh2->is_slave = is_slave;
18         pdb_register_cpu(sh2, PDBCT_SH2, is_slave ? "ssh2" : "msh2");
19 #ifdef DRC_SH2
20         ret = sh2_drc_init(sh2);
21 #endif
22         return ret;
23 }
24
25 void sh2_finish(SH2 *sh2)
26 {
27 #ifdef DRC_SH2
28         sh2_drc_finish(sh2);
29 #endif
30 }
31
32 void sh2_reset(SH2 *sh2)
33 {
34         sh2->pc = p32x_sh2_read32(0, sh2);
35         sh2->r[15] = p32x_sh2_read32(4, sh2);
36         sh2->sr = I;
37         sh2->vbr = 0;
38         sh2->pending_int_irq = 0;
39 }
40
41 void sh2_do_irq(SH2 *sh2, int level, int vector)
42 {
43         sh2->r[15] -= 4;
44         p32x_sh2_write32(sh2->r[15], sh2->sr, sh2);     /* push SR onto stack */
45         sh2->r[15] -= 4;
46         p32x_sh2_write32(sh2->r[15], sh2->pc, sh2);     /* push PC onto stack */
47
48         /* set I flags in SR */
49         sh2->sr = (sh2->sr & ~I) | (level << 4);
50
51         /* fetch PC */
52         sh2->pc = p32x_sh2_read32(sh2->vbr + vector * 4, sh2);
53
54         /* 13 cycles at best */
55         sh2->cycles_done += 13;
56 //      sh2->icount -= 13;
57 }
58
59 void sh2_irl_irq(SH2 *sh2, int level, int nested_call)
60 {
61         sh2->pending_irl = level;
62         if (level < sh2->pending_int_irq)
63                 level = sh2->pending_int_irq;
64         sh2->pending_level = level;
65
66         if (!nested_call) {
67                 // not in memhandler, so handle this now (recompiler friendly)
68                 // do this to avoid missing irqs that other SH2 might clear
69                 if (level > ((sh2->sr >> 4) & 0x0f)) {
70                         int vector = sh2->irq_callback(sh2, level);
71                         sh2_do_irq(sh2, level, vector);
72                 }
73         }
74         else
75                 sh2->test_irq = 1;
76 }
77
78 void sh2_internal_irq(SH2 *sh2, int level, int vector)
79 {
80         // FIXME: multiple internal irqs not handled..
81         // assuming internal irqs never clear until accepted
82         sh2->pending_int_irq = level;
83         sh2->pending_int_vector = vector;
84         if (level > sh2->pending_level)
85                 sh2->pending_level = level;
86
87         sh2->test_irq = 1;
88 }
89
90 #define SH2_REG_SIZE (offsetof(SH2, macl) + sizeof(sh2->macl))
91
92 void sh2_pack(const SH2 *sh2, unsigned char *buff)
93 {
94         unsigned int *p;
95
96         memcpy(buff, sh2, SH2_REG_SIZE);
97         p = (void *)(buff + SH2_REG_SIZE);
98
99         p[0] = sh2->pending_int_irq;
100         p[1] = sh2->pending_int_vector;
101         p[2] = sh2->cycles_aim;
102         p[3] = sh2->cycles_done;
103 }
104
105 void sh2_unpack(SH2 *sh2, const unsigned char *buff)
106 {
107         unsigned int *p;
108
109         memcpy(sh2, buff, SH2_REG_SIZE);
110         p = (void *)(buff + SH2_REG_SIZE);
111
112         sh2->pending_int_irq = p[0];
113         sh2->pending_int_vector = p[1];
114         sh2->cycles_aim = p[2];
115         sh2->cycles_done = p[3];
116 }
117