Commit | Line | Data |
---|---|---|
aea481da DE |
1 | /* Copyright (C) 1998, Cygnus Solutions |
2 | ||
3 | */ | |
4 | ||
5 | #include "sim-main.h" | |
486c714a | 6 | #include "sim-endian.h" |
aea481da | 7 | |
803f52b9 DE |
8 | #include "sky-device.h" |
9 | #include "sky-vu1.h" | |
10 | #include "sky-libvpe.h" | |
11 | #include "sky-vu.h" | |
9c577d9a IC |
12 | #include "sky-bits.h" |
13 | ||
14 | #include <assert.h> | |
aea481da DE |
15 | |
16 | VectorUnitState vu1_state; | |
17 | ||
04a7f72a IC |
18 | #define sim_warning printf |
19 | ||
f0bb94cd FCE |
20 | static char* vu1_umem_buffer = 0; |
21 | static char* vu1_mem_buffer = 0; | |
aea481da | 22 | |
52793fab | 23 | void init_vu1(void); |
aea481da DE |
24 | void init_vu(VectorUnitState *state, char* umem_buffer, char* mem_buffer); |
25 | ||
733cfc78 IC |
26 | static void dump_mem() { |
27 | int i; | |
28 | typedef int T[2048][4]; | |
29 | T *mem = (T*)&vu1_mem_buffer; | |
30 | ||
31 | for (i = 0; i < 200; i++) { | |
32 | printf("%d: %x %x %x %x\n", i, (*mem)[i][0], (*mem)[i][1], (*mem)[i][2], (*mem)[i][3]); | |
33 | } | |
34 | } | |
35 | ||
aea481da | 36 | void |
52793fab | 37 | vu1_issue(void) |
aea481da DE |
38 | { |
39 | if (vu1_state.runState == VU_RUN) | |
40 | vpecallms_cycle(&vu1_state); | |
41 | } | |
42 | ||
52793fab | 43 | static int |
aea481da DE |
44 | vu1_io_read_register_window(device *me, |
45 | void *dest, | |
46 | int space, | |
47 | address_word addr, | |
48 | unsigned nr_bytes, | |
49 | sim_cpu *processor, | |
50 | sim_cia cia) | |
51 | { | |
52 | /* Slow and crappy hack ... */ | |
53 | ||
9c577d9a | 54 | |
aea481da DE |
55 | int i; |
56 | ||
57 | char source_buffer[VU1_REGISTER_WINDOW_SIZE]; | |
58 | char* src; | |
59 | ||
9c577d9a IC |
60 | assert(nr_bytes == 1 || nr_bytes == 2 || nr_bytes == 4 || nr_bytes == 8 || nr_bytes == 16); |
61 | ||
aea481da DE |
62 | memcpy(source_buffer, &vu1_state.regs.VF[0][0], 0x200); /* copy VF registers */ |
63 | for (i = 0; i<16; i++ ) { | |
64 | *(short*)&source_buffer[0x200 + i*16] = vu1_state.regs.VI[i]; | |
65 | } | |
9c577d9a IC |
66 | *(u_long*)&source_buffer[VU1_MST - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MST; |
67 | *(u_long*)&source_buffer[VU1_MMC - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MMC; | |
68 | *(u_long*)&source_buffer[VU1_MCP - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MCP; | |
69 | *(u_long*)&source_buffer[VU1_MR - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MR; | |
70 | *(u_long*)&source_buffer[VU1_MI - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MI; | |
71 | *(u_long*)&source_buffer[VU1_MQ - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MQ; | |
72 | *(u_long*)&source_buffer[VU1_MP - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MP; | |
73 | *(u_long*)&source_buffer[VU1_MTPC - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MTPC; | |
74 | ||
75 | { | |
76 | u_long stat; | |
77 | stat = 0; | |
78 | if (vu1_state.runState == VU_RUN || vu1_state.runState == VU_BREAK) | |
79 | SET_BIT(stat, VPU_STAT_VBS1_BIT); | |
80 | ||
f0bb94cd | 81 | *(u_long*)&source_buffer[VPE1_STAT - VU1_REGISTER_WINDOW_START] = H2T_4(stat); |
9c577d9a | 82 | } |
aea481da | 83 | |
f0bb94cd FCE |
84 | *(u_long*)&source_buffer[VU1_CIA - VU1_REGISTER_WINDOW_START] = H2T_4(vu1_state.junk._vpepc); |
85 | /* XXX: other H2T_N's needed around here. */ | |
04a7f72a | 86 | |
486c714a | 87 | #if 0 |
52793fab IC |
88 | printf("%s: Read: %x, %d, dest: %x, space: %d, %x!\n", me->name, (int)addr, nr_bytes, (int)dest, space, *(int*)&(vu1_state.regs.VPE_STAT)); |
89 | printf(" vu1_state.regs.VPE_STAT = %x\n", *(int*)&(vu1_state.regs.VPE_STAT)); | |
486c714a | 90 | #endif |
aea481da DE |
91 | |
92 | if (addr + nr_bytes > VU1_REGISTER_WINDOW_END) { | |
93 | fprintf(stderr, "Error: Read past end of vu1 register window!!!\n"); | |
94 | exit(1); | |
95 | } | |
96 | ||
97 | src = &source_buffer[0] + (addr - VU1_REGISTER_WINDOW_START); | |
98 | memcpy(dest, src, nr_bytes); | |
99 | return nr_bytes; | |
100 | } | |
101 | ||
52793fab | 102 | static int |
aea481da DE |
103 | vu1_io_write_register_window(device *me, |
104 | const void *source, | |
105 | int space, | |
106 | address_word addr, | |
107 | unsigned nr_bytes, | |
108 | sim_cpu *processor, | |
109 | sim_cia cia) | |
110 | { | |
111 | char *dest; | |
112 | ||
04a7f72a IC |
113 | assert(nr_bytes == 4); |
114 | ||
115 | if (addr == VPE1_STAT) { | |
116 | /* Do nothing, read only register. */ | |
117 | sim_warning("vu1: Write to read/only register at address %lx.\n", (u_long)addr); | |
aea481da | 118 | return nr_bytes; |
04a7f72a | 119 | } else if (addr == VU1_MST) { |
486c714a | 120 | /* Magic switch to set _TOP register */ |
486c714a IC |
121 | vu1_state.junk._TOP = T2H_4(*(int*)source); |
122 | return nr_bytes; | |
04a7f72a | 123 | } else if (addr == VU1_CIA) { |
f62dff78 | 124 | vu1_state.junk.pc = vu1_state.junk._vpepc = T2H_4(*(int*)source); |
04a7f72a IC |
125 | vu1_state.runState = VU_RUN; |
126 | vu1_state.junk.eflag = 0; | |
127 | vu1_state.junk.peflag = 0; | |
128 | return nr_bytes; | |
129 | } | |
130 | ||
131 | /* Everything else does nothing... */ | |
132 | sim_warning("vu1: Write to unimplemented control register at address %lx.\n", (u_long)addr); | |
133 | return nr_bytes; | |
aea481da | 134 | |
486c714a | 135 | /*printf("%s: Write: %x, %d, source: %x, space: %d!\n", me->name, (int)addr, nr_bytes, (int)source, space);*/ |
aea481da DE |
136 | |
137 | if (addr + nr_bytes > VU1_REGISTER_WINDOW_END) { | |
138 | fprintf(stderr, "Error: Read past end of vu1 register window!!!\n"); | |
139 | exit(1); | |
140 | } | |
141 | ||
142 | dest = ((char*) (&vu1_state.regs)) + (addr - VU1_REGISTER_WINDOW_START); | |
143 | ||
144 | memcpy(dest, source, nr_bytes); | |
145 | ||
146 | return nr_bytes; | |
147 | } | |
148 | ||
149 | device vu1_device = | |
150 | { | |
151 | "vu1", | |
152 | &vu1_io_read_register_window, | |
153 | &vu1_io_write_register_window | |
154 | }; | |
155 | ||
156 | void | |
157 | vu1_init(SIM_DESC sd) | |
158 | { | |
159 | ||
160 | sim_core_attach (sd, | |
161 | NULL, | |
162 | 0 /*level*/, | |
163 | access_read_write, | |
164 | 0 /*space ???*/, | |
165 | VU1_REGISTER_WINDOW_START, | |
166 | VU1_REGISTER_WINDOW_SIZE /*nr_bytes*/, | |
167 | 0 /*modulo*/, | |
168 | &vu1_device, | |
169 | NULL /*buffer*/); | |
170 | ||
f0bb94cd | 171 | vu1_umem_buffer = zalloc(VU1_MEM0_SIZE); |
aea481da DE |
172 | sim_core_attach (sd, |
173 | NULL, | |
174 | 0 /*level*/, | |
175 | access_read_write, | |
176 | 0 /*space ???*/, | |
177 | VU1_MEM0_WINDOW_START, | |
178 | VU1_MEM0_SIZE /*nr_bytes*/, | |
179 | 0 /*modulo*/, | |
180 | 0 /*device*/, | |
f0bb94cd | 181 | vu1_umem_buffer /*buffer*/); |
aea481da | 182 | |
f0bb94cd | 183 | vu1_mem_buffer = zalloc(VU1_MEM1_SIZE); |
aea481da DE |
184 | sim_core_attach (sd, |
185 | NULL, | |
186 | 0 /*level*/, | |
187 | access_read_write, | |
188 | 0 /*space ???*/, | |
189 | VU1_MEM1_WINDOW_START, | |
190 | VU1_MEM1_SIZE /*nr_bytes*/, | |
191 | 0 /*modulo*/, | |
192 | 0 /*device*/, | |
f0bb94cd | 193 | vu1_mem_buffer /*buffer*/); |
aea481da DE |
194 | |
195 | init_vu1(); | |
196 | /*initvpe();*/ | |
197 | vpecallms_init(&vu1_state); | |
198 | } | |
199 | ||
200 | /****************************************************************************/ | |
201 | /* */ | |
202 | /* Sony Computer Entertainment CONFIDENTIAL */ | |
203 | /* (C) 1997 Sony Computer Entertainment Inc. All Rights Reserved */ | |
204 | /* */ | |
205 | /* VPE1 simulator */ | |
206 | /* */ | |
207 | /****************************************************************************/ | |
208 | ||
209 | #include <stdio.h> | |
210 | #include <sys/types.h> | |
211 | #include <strings.h> | |
72db5610 | 212 | #include "sky-libvpe.h" |
aea481da DE |
213 | |
214 | char ifilename[64] = "vu.bin"; | |
215 | char ofilename[64] = ""; | |
216 | char pfilename[64] = ""; | |
217 | ||
52793fab | 218 | static void abend2(char *fmt, char* p) { |
aea481da DE |
219 | fprintf(stderr, fmt, p); |
220 | exit(1); | |
221 | } | |
222 | ||
486c714a | 223 | void getoption(VectorUnitState* state); |
aea481da | 224 | |
52793fab | 225 | void init_vu1(void) { |
aea481da DE |
226 | init_vu(&vu1_state, &vu1_umem_buffer[0], &vu1_mem_buffer[0]); |
227 | } | |
228 | ||
229 | void init_vu(VectorUnitState *state, char* umem_buffer, char* mem_buffer) | |
230 | { | |
231 | FILE *fp; | |
232 | int i, j; | |
233 | u_long data[4]; | |
234 | ||
235 | /* set up memory buffers */ | |
236 | state->uMEM = (uMEM_Entry_Type *) umem_buffer; | |
237 | state->MEM = (MEM_Entry_Type*) mem_buffer; | |
238 | ||
239 | /* set up run state */ | |
240 | state->runState = VU_READY; | |
241 | ||
242 | /* read option */ | |
486c714a | 243 | getoption(state); |
aea481da DE |
244 | |
245 | /* read instruction file (mandatory) */ | |
246 | if (*ifilename) { | |
dde66fa7 IC |
247 | if((fp = fopen(ifilename, "r")) != NULL) { |
248 | for (i = 0; fread(&data[0], 4, 1, fp) != 0; i++) { | |
249 | fread(&data[1], 4, 1, fp); | |
250 | LoadMMem(state, i, data, 1); | |
251 | } | |
252 | fclose(fp); | |
aea481da | 253 | } |
aea481da DE |
254 | } |
255 | ||
256 | /* PKE dirven simvpe */ | |
257 | if (*pfilename) { | |
258 | /* initpke(pfilename); */ | |
259 | initvpe(&vu1_state); | |
260 | /* while (simpke() != -1) | |
261 | simvpe(); */ | |
262 | } | |
263 | ||
264 | /* conventional simvpe */ | |
265 | else { | |
266 | initvpe(&vu1_state); | |
267 | /*simvpe();*/ | |
268 | } | |
269 | ||
270 | /* write result memory image (optional) */ | |
271 | if (*ofilename) { | |
272 | if((fp = fopen(ofilename, "w")) == NULL) | |
273 | abend2("%s: can not open\n", ofilename); | |
274 | ||
275 | for(i = 0; i < 2048; i++){ | |
52793fab | 276 | StoreVUMem(state, i, data, 1); |
aea481da DE |
277 | for(j = 0; j < 4; j++) |
278 | fwrite(&data[j], 4, 1, fp); | |
279 | } | |
280 | fclose(fp); | |
281 | } | |
282 | } | |
283 | ||
52793fab | 284 | #if 0 |
aea481da DE |
285 | static void Usage(void) |
286 | { | |
287 | fprintf(stderr, "Usage: simvpe [options]\n"); | |
288 | fprintf(stderr, "\t\t-i instruction-file\n"); | |
289 | fprintf(stderr, "\t\t-o output-memory-file\n"); | |
290 | fprintf(stderr, "\t\t-t PKE-file (text type)\n"); | |
291 | fprintf(stderr, "\t\t-s start-address [default = 0]\n"); | |
292 | fprintf(stderr, "\t\t-d [interactive mode enable: default desable]\n"); | |
293 | fprintf(stderr, "\t\t-v [statistics mode enable: default desable]\n"); | |
294 | fprintf(stderr, "\t\t-p [debug print mode enable: default desable]\n"); | |
295 | } | |
52793fab | 296 | #endif |
aea481da | 297 | |
486c714a | 298 | void getoption(VectorUnitState* state) |
aea481da | 299 | { |
52793fab | 300 | #if 0 |
aea481da DE |
301 | int startline = 0; |
302 | int count = 1; | |
52793fab | 303 | #endif |
aea481da | 304 | |
486c714a IC |
305 | state->junk._is_dbg = 1; |
306 | state->junk._vpepc = 0; | |
307 | state->junk._is_verb = 0; | |
308 | state->junk._is_dump = 0; | |
374ed20d | 309 | state->junk._pgpuif = 4; /* MEMGPUIF */ |
486c714a IC |
310 | state->junk._ITOP = 20; |
311 | state->junk._TOP = 10; | |
aea481da DE |
312 | |
313 | #if 0 | |
314 | while(argc - count){ | |
315 | if(argv[count][0] == '-'){ | |
316 | switch(argv[count][1]){ | |
317 | case 'i': | |
318 | strcpy(ifilename, argv[count+1]); | |
319 | count += 2; | |
320 | break; | |
321 | case 'o': | |
322 | strcpy(ofilename, argv[count+1]); | |
323 | count += 2; | |
324 | break; | |
325 | case 't': | |
326 | strcpy(pfilename, argv[count+1]); | |
327 | count += 2; | |
328 | break; | |
329 | case 's': | |
330 | sscanf(argv[count+1], "%d", &startline); | |
486c714a | 331 | state->junk._vpepc = startline; |
aea481da DE |
332 | count += 2; |
333 | break; | |
334 | case 'd': | |
486c714a | 335 | state->junk._is_dbg = 1; |
aea481da DE |
336 | count += 1; |
337 | break; | |
338 | case 'v': | |
486c714a | 339 | state->junk._is_verb = 1; |
aea481da DE |
340 | count += 1; |
341 | break; | |
342 | case 'p': | |
486c714a | 343 | state->junk._is_dump = 1; |
aea481da DE |
344 | count += 1; |
345 | break; | |
346 | case 'h': | |
347 | case '?': | |
348 | Usage(); | |
349 | exit(1); | |
350 | break; | |
351 | default: | |
352 | Usage(); | |
353 | exit(1); | |
354 | } | |
355 | }else{ | |
356 | Usage(); | |
357 | exit(1); | |
358 | } | |
359 | } | |
360 | #endif | |
361 | } |