/[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 89 - (hide annotations)
Thu Aug 2 12:01:09 2007 UTC (16 years, 9 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 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 87 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 dpavlin 80 }
29    
30 dpavlin 87 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 dpavlin 89 /** 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 dpavlin 84 int
164 dpavlin 82 reset (void) {
165     debugf(("M6502::reset called"));
166 dpavlin 83 if ( ! R ) {
167     debugf(("allocating space for R"));
168     R = malloc(sizeof(M6502));
169     if (!R) {
170 dpavlin 89 PerlIO_stdoutf("can't alloc %d bytes for M6502", sizeof(M6502));
171 dpavlin 83 exit(1);
172     }
173     }
174 dpavlin 82 Reset6502(R);
175 dpavlin 84 debugf(("Reset6502 over"));
176 dpavlin 87 update_perl_R();
177 dpavlin 82 dump_R;
178 dpavlin 84 return 1;
179 dpavlin 82 }
180    
181 dpavlin 89 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 dpavlin 87 int set_debug(int state) {
193     debug = state;
194     return debug;
195     }
196 dpavlin 86
197 dpavlin 87 int get_debug(void) {
198     return debug;
199     }
200    
201 dpavlin 80 MODULE = M6502 PACKAGE = M6502
202    
203     PROTOTYPES: DISABLE
204    
205 dpavlin 87 int
206     set_debug(int state)
207 dpavlin 82
208 dpavlin 84 int
209 dpavlin 87 get_debug()
210    
211     int
212 dpavlin 82 reset()
213 dpavlin 87
214     void
215     update_C_R()
216    
217     void
218     update_perl_R()
219    

  ViewVC Help
Powered by ViewVC 1.1.26