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