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

  ViewVC Help
Powered by ViewVC 1.1.26