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

  ViewVC Help
Powered by ViewVC 1.1.26