/[VRac]/M6502/M6502.xs
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /M6502/M6502.xs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 108 - (show annotations)
Fri Aug 3 09:18:08 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 5504 byte(s)
rename MEM_SIZE to CACHE_SIZE to prevent clush with perl include
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include "ppport.h"
6
7 #include "M6502.h"
8 #include "config.h"
9
10 M6502 *R = NULL;
11 int debug = 0;
12
13 byte opCache[CACHE_SIZE];
14
15 void update_C_R(void) {
16 R->A = SvIV( get_sv("M6502::A", FALSE) );
17 R->P = SvIV( get_sv("M6502::P", FALSE) );
18 R->X = SvIV( get_sv("M6502::X", FALSE) );
19 R->Y = SvIV( get_sv("M6502::Y", FALSE) );
20 R->S = SvIV( get_sv("M6502::S", FALSE) );
21 R->PC.W = SvIV( get_sv("M6502::PC", FALSE) );
22 R->IPeriod = SvIV( get_sv("M6502::IPeriod", FALSE) );
23 R->IRequest = SvIV( get_sv("M6502::IRequest", FALSE) );
24 R->IAutoReset = SvIV( get_sv("M6502::IAutoReset", FALSE) );
25 R->TrapBadOps = SvIV( get_sv("M6502::TrapBadOps", FALSE) );
26 R->Trap = SvIV( get_sv("M6502::Trap", FALSE) );
27 R->Trace = SvIV( get_sv("M6502::Trace", FALSE) );
28 debugf(("pull_R finished"));
29 dump_R;
30 }
31
32 void update_perl_R(void) {
33 debugf(("update_perl_R"));
34 dSP;
35 ENTER;
36 SAVETMPS;
37 PUSHMARK(SP);
38 XPUSHs( sv_2mortal( newSViv( R->A ) ) );
39 XPUSHs( sv_2mortal( newSViv( R->P ) ) );
40 XPUSHs( sv_2mortal( newSViv( R->X ) ) );
41 XPUSHs( sv_2mortal( newSViv( R->Y ) ) );
42 XPUSHs( sv_2mortal( newSViv( R->S ) ) );
43 XPUSHs( sv_2mortal( newSViv( R->PC.W ) ) );
44 XPUSHs( sv_2mortal( newSViv( R->IPeriod ) ) );
45 XPUSHs( sv_2mortal( newSViv( R->ICount ) ) );
46 XPUSHs( sv_2mortal( newSViv( R->IRequest ) ) );
47 XPUSHs( sv_2mortal( newSViv( R->IAutoReset ) ) );
48 XPUSHs( sv_2mortal( newSViv( R->TrapBadOps ) ) );
49 XPUSHs( sv_2mortal( newSViv( R->Trap ) ) );
50 XPUSHs( sv_2mortal( newSViv( R->Trace ) ) );
51 PUTBACK;
52 call_pv("M6502::_update_perl_R", G_DISCARD );
53 debugf(("_update_perl_R returned to C"));
54 dump_R;
55 FREETMPS;
56 LEAVE;
57 }
58
59 /** Debug6502() **********************************************/
60
61 byte Debug6502(M6502 *R) {
62 dump_R;
63 return 1; // continue emulation
64 }
65
66 /** Rd6502()/Wr6502/Op6502() *********************************/
67 /** These functions are called when access to RAM occurs. **/
68 /** They allow to control memory access. Op6502 is the same **/
69 /** as Rd6502, but used to read *opcodes* only, when many **/
70 /** checks can be skipped to make it fast. It is only **/
71 /** required if there is a #define FAST_RDOP. **/
72 /************************************ TO BE WRITTEN BY USER **/
73
74 byte mem(word Addr) {
75 byte byte;
76 int count;
77 debugf(("mem(%04x)", Addr));
78 dSP;
79 ENTER;
80 SAVETMPS;
81 PUSHMARK(SP);
82 XPUSHs( sv_2mortal( newSViv( Addr ) ) );
83 PUTBACK;
84 count = call_pv("M6502::_read", G_ARRAY | G_EVAL );
85 debugf(("got %d values", count));
86 SPAGAIN;
87 if (SvTRUE(ERRSV)) {
88 printf("ERROR: %s", SvPV_nolen( ERRSV ) );
89 exit(1);
90 }
91 if ( count != 1 ) {
92 printf("expect 1 return value, got %d", count);
93 exit(1);
94 }
95 SV *sv;
96 sv = POPs;
97 byte = SvIV(sv);
98 FREETMPS;
99 LEAVE;
100 debugf(("mem(%04x) = %02x", Addr, byte));
101 opCache[Addr] = byte;
102 return byte;
103 }
104
105 byte Rd6502(register word Addr) {
106 byte Value;
107 Value = mem(Addr);
108 debugf(("Rd6502(%04x) = %02x", Addr, Value));
109 return Value;
110 }
111
112 void Wr6502(register word Addr,register byte Value) {
113 debugf(("Wr6502(%04x,%02x)", Addr, Value));
114 opCache[Addr] = Value;
115 dSP;
116 ENTER;
117 SAVETMPS;
118 PUSHMARK(SP);
119 XPUSHs( sv_2mortal( newSViv( Addr ) ) );
120 XPUSHs( sv_2mortal( newSViv( Value ) ) );
121 PUTBACK;
122 call_pv("M6502::_write", G_DISCARD );
123 FREETMPS;
124 LEAVE;
125 }
126
127 byte Op6502(register word Addr) {
128 byte Op;
129 if ( opCache[Addr] ) return opCache[Addr];
130 Op = mem(Addr);
131 debugf(("Op6502(%04x,%02x) PC:%04x", Addr, Op, R->PC.W));
132 return Op;
133 }
134
135 /** Loop6502() ***********************************************/
136 /** 6502 emulation calls this function periodically to **/
137 /** check if the system hardware requires any interrupts. **/
138 /** This function must return one of following values: **/
139 /** INT_NONE, INT_IRQ, INT_NMI, or INT_QUIT to exit the **/
140 /** emulation loop. **/
141 /************************************ TO BE WRITTEN BY USER **/
142
143 int hw_int = INT_NONE;
144
145 byte Loop6502(register M6502 *R) {
146 debugf(("Loop6502"));
147 dump_R;
148 return hw_int;
149 }
150
151 /** Patch6502() **********************************************/
152 /** Emulation calls this function when it encounters an **/
153 /** unknown opcode. This can be used to patch the code to **/
154 /** emulate BIOS calls, such as disk and tape access. The **/
155 /** function should return 1 if the exception was handled, **/
156 /** or 0 if the opcode was truly illegal. **/
157 /************************************ TO BE WRITTEN BY USER **/
158 byte Patch6502(register byte Op,register M6502 *R) {
159 debugf(("Patch6502(%02x)", Op));
160 dump_R;
161 hw_int = INT_QUIT;
162 return 0;
163 }
164
165 /*************************************************************/
166
167 int
168 reset (void) {
169 debugf(("M6502::reset called"));
170 if ( ! R ) {
171 debugf(("allocating space for R"));
172 R = malloc(sizeof(M6502));
173 if (!R) {
174 PerlIO_stdoutf("can't alloc %d bytes for M6502", sizeof(M6502));
175 exit(1);
176 }
177 memset( opCache, 0, sizeof(opCache) );
178 }
179 Reset6502(R);
180 debugf(("Reset6502 over"));
181 update_perl_R();
182 dump_R;
183 return 1;
184 }
185
186 int exec(int cycles) {
187 int left;
188 debugf(("exec for %d cycles", cycles));
189
190 if (!R) reset();
191
192 update_C_R();
193 left = Exec6502(R, cycles);
194 update_perl_R();
195 debugf(("end of %d cycles CPU run\n", cycles));
196 return left;
197 }
198
199 int set_debug(int state) {
200 debug = state;
201 return debug;
202 }
203
204 int get_debug(void) {
205 return debug;
206 }
207
208 MODULE = M6502 PACKAGE = M6502
209
210 PROTOTYPES: DISABLE
211
212 int
213 set_debug(int state)
214
215 int
216 get_debug()
217
218 int
219 reset()
220
221 void
222 update_C_R()
223
224 void
225 update_perl_R()
226
227 int
228 exec(int cycles)

  ViewVC Help
Powered by ViewVC 1.1.26