/[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

Annotation of /M6502/M6502.xs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 108 - (hide annotations)
Fri Aug 3 09:18:08 2007 UTC (16 years, 8 months ago) by dpavlin
File size: 5504 byte(s)
rename MEM_SIZE to CACHE_SIZE to prevent clush with perl include
1 dpavlin 80 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5     #include "ppport.h"
6    
7 dpavlin 82 #include "M6502.h"
8     #include "config.h"
9    
10 dpavlin 89 M6502 *R = NULL;
11 dpavlin 87 int debug = 0;
12 dpavlin 82
13 dpavlin 108 byte opCache[CACHE_SIZE];
14 dpavlin 100
15 dpavlin 87 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 dpavlin 80 }
31    
32 dpavlin 87 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 dpavlin 89 /** 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 dpavlin 100 opCache[Addr] = byte;
102 dpavlin 89 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 dpavlin 100 opCache[Addr] = Value;
115 dpavlin 89 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 dpavlin 100 if ( opCache[Addr] ) return opCache[Addr];
130 dpavlin 89 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 dpavlin 84 int
168 dpavlin 82 reset (void) {
169     debugf(("M6502::reset called"));
170 dpavlin 83 if ( ! R ) {
171     debugf(("allocating space for R"));
172     R = malloc(sizeof(M6502));
173     if (!R) {
174 dpavlin 89 PerlIO_stdoutf("can't alloc %d bytes for M6502", sizeof(M6502));
175 dpavlin 83 exit(1);
176     }
177 dpavlin 100 memset( opCache, 0, sizeof(opCache) );
178 dpavlin 83 }
179 dpavlin 82 Reset6502(R);
180 dpavlin 84 debugf(("Reset6502 over"));
181 dpavlin 87 update_perl_R();
182 dpavlin 82 dump_R;
183 dpavlin 84 return 1;
184 dpavlin 82 }
185    
186 dpavlin 91 int exec(int cycles) {
187 dpavlin 93 int left;
188 dpavlin 89 debugf(("exec for %d cycles", cycles));
189    
190     if (!R) reset();
191    
192     update_C_R();
193 dpavlin 93 left = Exec6502(R, cycles);
194 dpavlin 89 update_perl_R();
195     debugf(("end of %d cycles CPU run\n", cycles));
196 dpavlin 93 return left;
197 dpavlin 89 }
198    
199 dpavlin 87 int set_debug(int state) {
200     debug = state;
201     return debug;
202     }
203 dpavlin 86
204 dpavlin 87 int get_debug(void) {
205     return debug;
206     }
207    
208 dpavlin 80 MODULE = M6502 PACKAGE = M6502
209    
210     PROTOTYPES: DISABLE
211    
212 dpavlin 87 int
213     set_debug(int state)
214 dpavlin 82
215 dpavlin 84 int
216 dpavlin 87 get_debug()
217    
218     int
219 dpavlin 82 reset()
220 dpavlin 87
221     void
222     update_C_R()
223    
224     void
225     update_perl_R()
226    
227 dpavlin 91 int
228     exec(int cycles)

  ViewVC Help
Powered by ViewVC 1.1.26