/[VRac]/M6502/perl.c
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/perl.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26