* R5900 COP2 function nearly complete. PKE sim now aware of new GPUIF
[deliverable/binutils-gdb.git] / sim / mips / sky-pke.c
CommitLineData
aea481da
DE
1/* Copyright (C) 1998, Cygnus Solutions */
2
e2306992 3
10572b6a
AC
4#include "config.h"
5
aea481da 6#include <stdlib.h>
15232df4 7#include "sim-main.h"
db6dac32 8#include "sim-bits.h"
fba9bfed 9#include "sim-assert.h"
15232df4
FCE
10#include "sky-pke.h"
11#include "sky-dma.h"
12#include "sky-vu.h"
fba9bfed 13#include "sky-gpuif.h"
fd909089 14#include "sky-device.h"
aea481da 15
15232df4 16
10572b6a
AC
17#ifdef HAVE_STRING_H
18#include <string.h>
19#else
20#ifdef HAVE_STRINGS_H
21#include <strings.h>
22#endif
23#endif
24
aea481da
DE
25
26/* Internal function declarations */
27
28static int pke_io_read_buffer(device*, void*, int, address_word,
29 unsigned, sim_cpu*, sim_cia);
30static int pke_io_write_buffer(device*, const void*, int, address_word,
31 unsigned, sim_cpu*, sim_cia);
9614fb3c 32static void pke_reset(struct pke_device*);
e2306992 33static void pke_issue(SIM_DESC, struct pke_device*);
fba9bfed 34static void pke_pc_advance(struct pke_device*, int num_words);
9614fb3c
FCE
35static struct fifo_quadword* pke_pcrel_fifo(struct pke_device*, int operand_num,
36 unsigned_4** operand);
37static unsigned_4* pke_pcrel_operand(struct pke_device*, int operand_num);
38static unsigned_4 pke_pcrel_operand_bits(struct pke_device*, int bit_offset,
39 int bit_width, unsigned_4* sourceaddr);
fba9bfed 40static void pke_attach(SIM_DESC sd, struct pke_device* me);
43a6998b
FCE
41enum pke_check_target { chk_vu, chk_path1, chk_path2, chk_path3 };
42static int pke_check_stall(struct pke_device* me, enum pke_check_target what);
43static void pke_flip_dbf(struct pke_device* me);
9614fb3c 44static void pke_begin_interrupt_stall(struct pke_device* me);
43a6998b
FCE
45/* PKEcode handlers */
46static void pke_code_nop(struct pke_device* me, unsigned_4 pkecode);
47static void pke_code_stcycl(struct pke_device* me, unsigned_4 pkecode);
48static void pke_code_offset(struct pke_device* me, unsigned_4 pkecode);
49static void pke_code_base(struct pke_device* me, unsigned_4 pkecode);
50static void pke_code_itop(struct pke_device* me, unsigned_4 pkecode);
51static void pke_code_stmod(struct pke_device* me, unsigned_4 pkecode);
52static void pke_code_mskpath3(struct pke_device* me, unsigned_4 pkecode);
53static void pke_code_pkemark(struct pke_device* me, unsigned_4 pkecode);
54static void pke_code_flushe(struct pke_device* me, unsigned_4 pkecode);
55static void pke_code_flush(struct pke_device* me, unsigned_4 pkecode);
56static void pke_code_flusha(struct pke_device* me, unsigned_4 pkecode);
57static void pke_code_pkemscal(struct pke_device* me, unsigned_4 pkecode);
58static void pke_code_pkemscnt(struct pke_device* me, unsigned_4 pkecode);
59static void pke_code_pkemscalf(struct pke_device* me, unsigned_4 pkecode);
60static void pke_code_stmask(struct pke_device* me, unsigned_4 pkecode);
61static void pke_code_strow(struct pke_device* me, unsigned_4 pkecode);
62static void pke_code_stcol(struct pke_device* me, unsigned_4 pkecode);
63static void pke_code_mpg(struct pke_device* me, unsigned_4 pkecode);
64static void pke_code_direct(struct pke_device* me, unsigned_4 pkecode);
65static void pke_code_directhl(struct pke_device* me, unsigned_4 pkecode);
66static void pke_code_unpack(struct pke_device* me, unsigned_4 pkecode);
67static void pke_code_error(struct pke_device* me, unsigned_4 pkecode);
15232df4
FCE
68unsigned_4 pke_fifo_flush(struct pke_fifo*);
69void pke_fifo_reset(struct pke_fifo*);
70struct fifo_quadword* pke_fifo_fit(struct pke_fifo*);
71struct fifo_quadword* pke_fifo_access(struct pke_fifo*, unsigned_4 qwnum);
72void pke_fifo_old(struct pke_fifo*, unsigned_4 qwnum);
fba9bfed 73
aea481da
DE
74
75
76/* Static data */
77
78struct pke_device pke0_device =
79{
80 { "pke0", &pke_io_read_buffer, &pke_io_write_buffer }, /* device */
81 0, 0, /* ID, flags */
aea481da 82 {}, /* regs */
db6dac32 83 {}, 0, /* FIFO write buffer */
9614fb3c
FCE
84 { NULL, 0, 0, 0 }, /* FIFO */
85 NULL, /* FIFO trace file */
121d6745 86 -1, -1, 0, 0, 0, /* invalid FIFO cache */
fba9bfed 87 0, 0 /* pc */
aea481da
DE
88};
89
90
91struct pke_device pke1_device =
92{
93 { "pke1", &pke_io_read_buffer, &pke_io_write_buffer }, /* device */
94 1, 0, /* ID, flags */
aea481da 95 {}, /* regs */
db6dac32 96 {}, 0, /* FIFO write buffer */
9614fb3c
FCE
97 { NULL, 0, 0, 0 }, /* FIFO */
98 NULL, /* FIFO trace file */
121d6745 99 -1, -1, 0, 0, 0, /* invalid FIFO cache */
fba9bfed 100 0, 0 /* pc */
aea481da
DE
101};
102
103
104
105/* External functions */
106
107
fba9bfed 108/* Attach PKE addresses to main memory */
aea481da
DE
109
110void
111pke0_attach(SIM_DESC sd)
112{
fba9bfed 113 pke_attach(sd, & pke0_device);
9614fb3c 114 pke_reset(& pke0_device);
fba9bfed 115}
aea481da 116
fba9bfed
FCE
117void
118pke1_attach(SIM_DESC sd)
119{
120 pke_attach(sd, & pke1_device);
9614fb3c 121 pke_reset(& pke1_device);
aea481da
DE
122}
123
124
fba9bfed
FCE
125
126/* Issue a PKE instruction if possible */
aea481da
DE
127
128void
e2306992 129pke0_issue(SIM_DESC sd)
aea481da 130{
e2306992 131 pke_issue(sd, & pke0_device);
fba9bfed
FCE
132}
133
134void
e2306992 135pke1_issue(SIM_DESC sd)
fba9bfed 136{
653c2590 137 pke_issue(sd, & pke1_device);
fba9bfed
FCE
138}
139
140
141
142/* Internal functions */
143
144
145/* Attach PKE memory regions to simulator */
146
147void
148pke_attach(SIM_DESC sd, struct pke_device* me)
149{
150 /* register file */
e2306992 151 sim_core_attach (sd, NULL, 0, access_read_write, 0,
fba9bfed 152 (me->pke_number == 0) ? PKE0_REGISTER_WINDOW_START : PKE1_REGISTER_WINDOW_START,
aea481da
DE
153 PKE_REGISTER_WINDOW_SIZE /*nr_bytes*/,
154 0 /*modulo*/,
e2306992 155 (device*) me,
aea481da
DE
156 NULL /*buffer*/);
157
fba9bfed 158 /* FIFO port */
e2306992 159 sim_core_attach (sd, NULL, 0, access_read_write, 0,
fba9bfed 160 (me->pke_number == 0) ? PKE0_FIFO_ADDR : PKE1_FIFO_ADDR,
aea481da
DE
161 sizeof(quadword) /*nr_bytes*/,
162 0 /*modulo*/,
e2306992 163 (device*) me,
aea481da 164 NULL /*buffer*/);
aea481da 165
534a3d5c 166 /* VU MEM0 tracking table */
e2306992 167 sim_core_attach (sd, NULL, 0, access_read_write, 0,
534a3d5c
FCE
168 ((me->pke_number == 0) ? VU0_MEM0_SRCADDR_START : VU1_MEM0_SRCADDR_START),
169 ((me->pke_number == 0) ? VU0_MEM0_SIZE : VU1_MEM0_SIZE) / 2,
fba9bfed 170 0 /*modulo*/,
534a3d5c
FCE
171 NULL,
172 NULL /*buffer*/);
173
174 /* VU MEM1 tracking table */
175 sim_core_attach (sd, NULL, 0, access_read_write, 0,
176 ((me->pke_number == 0) ? VU0_MEM1_SRCADDR_START : VU1_MEM1_SRCADDR_START),
177 ((me->pke_number == 0) ? VU0_MEM1_SIZE : VU1_MEM1_SIZE) / 4,
178 0 /*modulo*/,
179 NULL,
180 NULL /*buffer*/);
181
e2306992
FCE
182
183 /* attach to trace file if appropriate */
184 {
185 char trace_envvar[80];
186 char* trace_filename = NULL;
187 sprintf(trace_envvar, "VIF%d_TRACE_FILE", me->pke_number);
188 trace_filename = getenv(trace_envvar);
189 if(trace_filename != NULL)
190 {
191 me->fifo_trace_file = fopen(trace_filename, "w");
192 if(me->fifo_trace_file == NULL)
e2306992 193 perror("VIF FIFO trace error on fopen");
b4d2f483
FCE
194 else
195 setvbuf(me->fifo_trace_file, NULL, _IOLBF, 0);
e2306992
FCE
196 }
197 }
aea481da
DE
198}
199
c567d0b9
RU
200/* Read PKE Pseudo-PC into buf in target order */
201int
202read_pke_pc (struct pke_device *me, void *buf)
203{
204 *((int *) buf) = H2T_4( me->fifo_pc );
205 return 4;
206}
207
208/* Read PKE reg into buf in target order */
209int
210read_pke_reg (struct pke_device *me, int reg_num, void *buf)
211{
212 /* handle reads to individual registers; clear `readable' on error */
213 switch (reg_num)
214 {
215 /* handle common case of register reading, side-effect free */
216 /* PKE1-only registers*/
217 case PKE_REG_BASE:
218 case PKE_REG_OFST:
219 case PKE_REG_TOPS:
220 case PKE_REG_TOP:
221 case PKE_REG_DBF:
222 if (me->pke_number == 0)
223 {
224 *((int *) buf) = 0;
225 break;
226 }
227 /* fall through */
228
229 /* PKE0 & PKE1 common registers*/
230 case PKE_REG_STAT:
231 case PKE_REG_ERR:
232 case PKE_REG_MARK:
233 case PKE_REG_CYCLE:
234 case PKE_REG_MODE:
235 case PKE_REG_NUM:
236 case PKE_REG_MASK:
237 case PKE_REG_CODE:
238 case PKE_REG_ITOPS:
239 case PKE_REG_ITOP:
240 case PKE_REG_R0:
241 case PKE_REG_R1:
242 case PKE_REG_R2:
243 case PKE_REG_R3:
244 case PKE_REG_C0:
245 case PKE_REG_C1:
246 case PKE_REG_C2:
247 case PKE_REG_C3:
248 *((int *) buf) = H2T_4(me->regs[reg_num][0]);
249 break;
250
251 /* handle common case of write-only registers */
252 case PKE_REG_FBRST:
253 *((int *) buf) = 0;
254 break;
255
256 default:
257 ASSERT(0); /* tests above should prevent this possibility */
258 }
259
260 return 4;
261}
aea481da
DE
262
263
aea481da
DE
264/* Handle a PKE read; return no. of bytes read */
265
266int
267pke_io_read_buffer(device *me_,
268 void *dest,
269 int space,
270 address_word addr,
271 unsigned nr_bytes,
fba9bfed 272 sim_cpu *cpu,
aea481da
DE
273 sim_cia cia)
274{
275 /* downcast to gather embedding pke_device struct */
276 struct pke_device* me = (struct pke_device*) me_;
277
fba9bfed
FCE
278 /* find my address ranges */
279 address_word my_reg_start =
280 (me->pke_number == 0) ? PKE0_REGISTER_WINDOW_START : PKE1_REGISTER_WINDOW_START;
281 address_word my_fifo_addr =
282 (me->pke_number == 0) ? PKE0_FIFO_ADDR : PKE1_FIFO_ADDR;
283
aea481da
DE
284 /* enforce that an access does not span more than one quadword */
285 address_word low = ADDR_TRUNC_QW(addr);
286 address_word high = ADDR_TRUNC_QW(addr + nr_bytes - 1);
287 if(low != high)
288 return 0;
289
290 /* classify address & handle */
fba9bfed 291 if((addr >= my_reg_start) && (addr < my_reg_start + PKE_REGISTER_WINDOW_SIZE))
aea481da
DE
292 {
293 /* register bank */
fba9bfed
FCE
294 int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4;
295 int reg_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside register bank */
fba9bfed
FCE
296 quadword result;
297
298 /* clear result */
299 result[0] = result[1] = result[2] = result[3] = 0;
aea481da 300
c567d0b9 301 read_pke_reg (me, reg_num, result);
aea481da 302
fba9bfed 303 /* perform transfer & return */
c567d0b9 304 memcpy(dest, ((unsigned_1*) &result) + reg_byte, nr_bytes);
aea481da 305
b4d2f483 306 return nr_bytes;
aea481da
DE
307 /* NOTREACHED */
308 }
fba9bfed
FCE
309 else if(addr >= my_fifo_addr &&
310 addr < my_fifo_addr + sizeof(quadword))
aea481da
DE
311 {
312 /* FIFO */
313
fba9bfed
FCE
314 /* FIFO is not readable: return a word of zeroes */
315 memset(dest, 0, nr_bytes);
316 return nr_bytes;
aea481da
DE
317 }
318
319 /* NOTREACHED */
fba9bfed 320 return 0;
aea481da
DE
321}
322
c567d0b9
RU
323/* Write PKE reg from buf, which is in target order */
324int
325write_pke_reg (struct pke_device *me, int reg_num, const void *buf)
326{
327 int writeable = 1;
328 /* make words host-endian */
329 unsigned_4 input = T2H_4( *((unsigned_4 *) buf) );
330
331 /* handle writes to individual registers; clear `writeable' on error */
332 switch (reg_num)
333 {
334 case PKE_REG_FBRST:
335 /* Order these tests from least to most overriding, in case
336 multiple bits are set. */
337 if(BIT_MASK_GET(input, PKE_REG_FBRST_STC_B, PKE_REG_FBRST_STC_E))
338 {
339 /* clear a bunch of status bits */
340 PKE_REG_MASK_SET(me, STAT, PSS, 0);
341 PKE_REG_MASK_SET(me, STAT, PFS, 0);
342 PKE_REG_MASK_SET(me, STAT, PIS, 0);
343 PKE_REG_MASK_SET(me, STAT, INT, 0);
344 PKE_REG_MASK_SET(me, STAT, ER0, 0);
345 PKE_REG_MASK_SET(me, STAT, ER1, 0);
346 me->flags &= ~PKE_FLAG_PENDING_PSS;
347 /* will allow resumption of possible stalled instruction */
348 }
349 if(BIT_MASK_GET(input, PKE_REG_FBRST_STP_B, PKE_REG_FBRST_STP_E))
350 {
351 me->flags |= PKE_FLAG_PENDING_PSS;
352 }
353 if(BIT_MASK_GET(input, PKE_REG_FBRST_FBK_B, PKE_REG_FBRST_FBK_E))
354 {
355 PKE_REG_MASK_SET(me, STAT, PFS, 1);
356 }
357 if(BIT_MASK_GET(input, PKE_REG_FBRST_RST_B, PKE_REG_FBRST_RST_E))
358 {
359 pke_reset(me);
360 }
361 break;
362
363 case PKE_REG_ERR:
364 /* copy bottom three bits */
365 BIT_MASK_SET(me->regs[PKE_REG_ERR][0], 0, 2, BIT_MASK_GET(input, 0, 2));
366 break;
367
368 case PKE_REG_MARK:
369 /* copy bottom sixteen bits */
370 PKE_REG_MASK_SET(me, MARK, MARK, BIT_MASK_GET(input, 0, 15));
371 /* reset MRK bit in STAT */
372 PKE_REG_MASK_SET(me, STAT, MRK, 0);
373 break;
374
375 /* handle common case of read-only registers */
376 /* PKE1-only registers - not really necessary to handle separately */
377 case PKE_REG_BASE:
378 case PKE_REG_OFST:
379 case PKE_REG_TOPS:
380 case PKE_REG_TOP:
381 case PKE_REG_DBF:
382 if(me->pke_number == 0)
383 writeable = 0;
384 /* fall through */
385 /* PKE0 & PKE1 common registers*/
386 case PKE_REG_STAT:
387 /* ignore FDR bit for PKE1_STAT -- simulator does not implement PKE->RAM transfers */
388 case PKE_REG_CYCLE:
389 case PKE_REG_MODE:
390 case PKE_REG_NUM:
391 case PKE_REG_MASK:
392 case PKE_REG_CODE:
393 case PKE_REG_ITOPS:
394 case PKE_REG_ITOP:
395 case PKE_REG_R0:
396 case PKE_REG_R1:
397 case PKE_REG_R2:
398 case PKE_REG_R3:
399 case PKE_REG_C0:
400 case PKE_REG_C1:
401 case PKE_REG_C2:
402 case PKE_REG_C3:
403 writeable = 0;
404 break;
405
406 default:
407 ASSERT(0); /* test above should prevent this possibility */
408 }
409
410 /* perform return */
411 if(! writeable)
412 {
413 return 0; /* error */
414 }
aea481da 415
c567d0b9
RU
416 return 4;
417}
418/* Handle a PKE write; return no. of bytes written */
aea481da
DE
419
420int
421pke_io_write_buffer(device *me_,
422 const void *src,
423 int space,
424 address_word addr,
425 unsigned nr_bytes,
fba9bfed 426 sim_cpu *cpu,
aea481da
DE
427 sim_cia cia)
428{
429 /* downcast to gather embedding pke_device struct */
430 struct pke_device* me = (struct pke_device*) me_;
431
fba9bfed
FCE
432 /* find my address ranges */
433 address_word my_reg_start =
434 (me->pke_number == 0) ? PKE0_REGISTER_WINDOW_START : PKE1_REGISTER_WINDOW_START;
435 address_word my_fifo_addr =
436 (me->pke_number == 0) ? PKE0_FIFO_ADDR : PKE1_FIFO_ADDR;
437
aea481da
DE
438 /* enforce that an access does not span more than one quadword */
439 address_word low = ADDR_TRUNC_QW(addr);
440 address_word high = ADDR_TRUNC_QW(addr + nr_bytes - 1);
441 if(low != high)
442 return 0;
443
444 /* classify address & handle */
fba9bfed 445 if((addr >= my_reg_start) && (addr < my_reg_start + PKE_REGISTER_WINDOW_SIZE))
aea481da
DE
446 {
447 /* register bank */
fba9bfed
FCE
448 int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4;
449 int reg_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside register bank */
fba9bfed
FCE
450 quadword input;
451
452 /* clear input */
453 input[0] = input[1] = input[2] = input[3] = 0;
aea481da 454
fba9bfed
FCE
455 /* write user-given bytes into input */
456 memcpy(((unsigned_1*) &input) + reg_byte, src, nr_bytes);
457
c567d0b9 458 write_pke_reg (me, reg_num, input);
b4d2f483
FCE
459 return nr_bytes;
460
aea481da
DE
461 /* NOTREACHED */
462 }
fba9bfed
FCE
463 else if(addr >= my_fifo_addr &&
464 addr < my_fifo_addr + sizeof(quadword))
aea481da
DE
465 {
466 /* FIFO */
fba9bfed 467 struct fifo_quadword* fqw;
db6dac32 468 int fifo_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside fifo quadword */
e2306992 469 unsigned_4 dma_tag_present = 0;
db6dac32
FCE
470 int i;
471
f0bb94cd 472 /* collect potentially-partial quadword in write buffer; LE byte order */
db6dac32
FCE
473 memcpy(((unsigned_1*)& me->fifo_qw_in_progress) + fifo_byte, src, nr_bytes);
474 /* mark bytes written */
475 for(i = fifo_byte; i < fifo_byte + nr_bytes; i++)
476 BIT_MASK_SET(me->fifo_qw_done, i, i, 1);
477
478 /* return if quadword not quite written yet */
479 if(BIT_MASK_GET(me->fifo_qw_done, 0, sizeof(quadword)-1) !=
e2306992 480 BIT_MASK_BTW(0, sizeof(quadword)-1))
db6dac32 481 return nr_bytes;
aea481da 482
db6dac32
FCE
483 /* all done - process quadword after clearing flag */
484 BIT_MASK_SET(me->fifo_qw_done, 0, sizeof(quadword)-1, 0);
aea481da 485
9614fb3c
FCE
486 /* allocate required address in FIFO */
487 fqw = pke_fifo_fit(& me->fifo);
488 ASSERT(fqw != NULL);
aea481da 489
9614fb3c 490 /* fill in unclassified FIFO quadword data in host byte order */
e2306992
FCE
491 fqw->word_class[0] = fqw->word_class[1] =
492 fqw->word_class[2] = fqw->word_class[3] = wc_unknown;
f0bb94cd
FCE
493 fqw->data[0] = T2H_4(me->fifo_qw_in_progress[0]);
494 fqw->data[1] = T2H_4(me->fifo_qw_in_progress[1]);
495 fqw->data[2] = T2H_4(me->fifo_qw_in_progress[2]);
496 fqw->data[3] = T2H_4(me->fifo_qw_in_progress[3]);
9614fb3c
FCE
497
498 /* read DMAC-supplied indicators */
e2306992 499 ASSERT(sizeof(unsigned_4) == 4);
534a3d5c 500 PKE_MEM_READ(me, (me->pke_number == 0 ? DMA_D0_MADR : DMA_D1_MADR),
f0bb94cd 501 & fqw->source_address, /* converted to host-endian */
e2306992 502 4);
534a3d5c 503 PKE_MEM_READ(me, (me->pke_number == 0 ? DMA_D0_PKTFLAG : DMA_D1_PKTFLAG),
e2306992
FCE
504 & dma_tag_present,
505 4);
506
507 if(dma_tag_present)
508 {
509 /* lower two words are DMA tags */
510 fqw->word_class[0] = fqw->word_class[1] = wc_dma;
511 }
512
fba9bfed
FCE
513 /* set FQC to "1" as FIFO is now not empty */
514 PKE_REG_MASK_SET(me, STAT, FQC, 1);
aea481da
DE
515
516 /* okay */
517 return nr_bytes;
518 }
519
520 /* NOTREACHED */
fba9bfed 521 return 0;
aea481da
DE
522}
523
524
525
9614fb3c
FCE
526/* Reset the PKE */
527void
528pke_reset(struct pke_device* me)
529{
530 /* advance PC over last quadword in FIFO; keep previous FIFO history */
531 me->fifo_pc = pke_fifo_flush(& me->fifo);
532 me->qw_pc = 0;
533 /* clear registers, flag, other state */
534 memset(me->regs, 0, sizeof(me->regs));
535 me->fifo_qw_done = 0;
536 me->flags = 0;
537}
538
539
540
fba9bfed 541/* Issue & swallow next PKE opcode if possible/available */
aea481da
DE
542
543void
e2306992 544pke_issue(SIM_DESC sd, struct pke_device* me)
aea481da 545{
fba9bfed
FCE
546 struct fifo_quadword* fqw;
547 unsigned_4 fw;
10572b6a 548 unsigned_4 cmd, intr;
fba9bfed 549
fd909089
FCE
550 /* 1 -- fetch PKE instruction */
551
552 /* confirm availability of new quadword of PKE instructions */
9614fb3c
FCE
553 fqw = pke_fifo_access(& me->fifo, me->fifo_pc);
554 if(fqw == NULL)
fd909089
FCE
555 return;
556
557 /* skip over DMA tag, if present */
558 pke_pc_advance(me, 0);
9614fb3c
FCE
559 /* note: this can only change qw_pc from 0 to 2 and will not
560 invalidate fqw */
fd909089
FCE
561
562 /* "fetch" instruction quadword and word */
fd909089
FCE
563 fw = fqw->data[me->qw_pc];
564
565 /* store word in PKECODE register */
566 me->regs[PKE_REG_CODE][0] = fw;
567
568
569 /* 2 -- test go / no-go for PKE execution */
fba9bfed 570
db6dac32
FCE
571 /* switch on STAT:PSS if PSS-pending and in idle state */
572 if((PKE_REG_MASK_GET(me, STAT, PPS) == PKE_REG_STAT_PPS_IDLE) &&
573 (me->flags & PKE_FLAG_PENDING_PSS) != 0)
574 {
575 me->flags &= ~PKE_FLAG_PENDING_PSS;
576 PKE_REG_MASK_SET(me, STAT, PSS, 1);
577 }
578
fba9bfed 579 /* check for stall/halt control bits */
db6dac32
FCE
580 if(PKE_REG_MASK_GET(me, STAT, PFS) ||
581 PKE_REG_MASK_GET(me, STAT, PSS) || /* note special treatment below */
9614fb3c
FCE
582 /* PEW bit not a reason to keep stalling - it's just an indication, re-computed below */
583 /* PGW bit not a reason to keep stalling - it's just an indication, re-computed below */
584 /* ER0/ER1 not a reason to keep stalling - it's just an indication */
fd909089 585 PKE_REG_MASK_GET(me, STAT, PIS))
fba9bfed 586 {
fd909089
FCE
587 /* (still) stalled */
588 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL);
589 /* try again next cycle */
43a6998b 590 return;
fba9bfed 591 }
fba9bfed 592
fba9bfed
FCE
593
594 /* 3 -- decode PKE instruction */
595
fd909089
FCE
596 /* decoding */
597 if(PKE_REG_MASK_GET(me, STAT, PPS) == PKE_REG_STAT_PPS_IDLE)
598 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_DECODE);
599
600 /* Extract relevant bits from PKEcode */
fba9bfed
FCE
601 intr = BIT_MASK_GET(fw, PKE_OPCODE_I_B, PKE_OPCODE_I_E);
602 cmd = BIT_MASK_GET(fw, PKE_OPCODE_CMD_B, PKE_OPCODE_CMD_E);
fba9bfed 603
d22ea5d0 604 /* handle interrupts */
fba9bfed
FCE
605 if(intr)
606 {
fd909089 607 /* are we resuming an interrupt-stalled instruction? */
d22ea5d0
FCE
608 if(me->flags & PKE_FLAG_INT_NOLOOP)
609 {
610 /* clear loop-prevention flag */
611 me->flags &= ~PKE_FLAG_INT_NOLOOP;
fd909089
FCE
612
613 /* fall through to decode & execute */
614 /* The pke_code_* functions should not check the MSB in the
615 pkecode. */
d22ea5d0
FCE
616 }
617 else /* new interrupt-flagged instruction */
618 {
619 /* set INT flag in STAT register */
620 PKE_REG_MASK_SET(me, STAT, INT, 1);
621 /* set loop-prevention flag */
622 me->flags |= PKE_FLAG_INT_NOLOOP;
623
fd909089
FCE
624 /* set PIS if stall not masked */
625 if(!PKE_REG_MASK_GET(me, ERR, MII))
9614fb3c 626 pke_begin_interrupt_stall(me);
fd909089
FCE
627
628 /* suspend this instruction unless it's PKEMARK */
629 if(!IS_PKE_CMD(cmd, PKEMARK))
630 {
631 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL);
632 return;
633 }
634 else
635 {
636 ; /* fall through to decode & execute */
637 }
d22ea5d0 638 }
fba9bfed
FCE
639 }
640
5068e793 641
43a6998b 642 /* decode & execute */
fd909089 643 if(IS_PKE_CMD(cmd, PKENOP))
43a6998b 644 pke_code_nop(me, fw);
fd909089 645 else if(IS_PKE_CMD(cmd, STCYCL))
43a6998b 646 pke_code_stcycl(me, fw);
fd909089 647 else if(me->pke_number == 1 && IS_PKE_CMD(cmd, OFFSET))
43a6998b 648 pke_code_offset(me, fw);
fd909089 649 else if(me->pke_number == 1 && IS_PKE_CMD(cmd, BASE))
43a6998b 650 pke_code_base(me, fw);
fd909089 651 else if(IS_PKE_CMD(cmd, ITOP))
43a6998b 652 pke_code_itop(me, fw);
fd909089 653 else if(IS_PKE_CMD(cmd, STMOD))
43a6998b 654 pke_code_stmod(me, fw);
fd909089 655 else if(me->pke_number == 1 && IS_PKE_CMD(cmd, MSKPATH3))
43a6998b 656 pke_code_mskpath3(me, fw);
fba9bfed 657 else if(IS_PKE_CMD(cmd, PKEMARK))
43a6998b 658 pke_code_pkemark(me, fw);
fd909089 659 else if(IS_PKE_CMD(cmd, FLUSHE))
43a6998b 660 pke_code_flushe(me, fw);
fd909089 661 else if(me->pke_number == 1 && IS_PKE_CMD(cmd, FLUSH))
43a6998b 662 pke_code_flush(me, fw);
fd909089 663 else if(me->pke_number == 1 && IS_PKE_CMD(cmd, FLUSHA))
43a6998b 664 pke_code_flusha(me, fw);
fd909089 665 else if(IS_PKE_CMD(cmd, PKEMSCAL))
43a6998b 666 pke_code_pkemscal(me, fw);
fd909089 667 else if(IS_PKE_CMD(cmd, PKEMSCNT))
43a6998b 668 pke_code_pkemscnt(me, fw);
fd909089 669 else if(me->pke_number == 1 && IS_PKE_CMD(cmd, PKEMSCALF))
43a6998b 670 pke_code_pkemscalf(me, fw);
fd909089 671 else if(IS_PKE_CMD(cmd, STMASK))
43a6998b 672 pke_code_stmask(me, fw);
fd909089 673 else if(IS_PKE_CMD(cmd, STROW))
43a6998b 674 pke_code_strow(me, fw);
fd909089 675 else if(IS_PKE_CMD(cmd, STCOL))
43a6998b 676 pke_code_stcol(me, fw);
fd909089 677 else if(IS_PKE_CMD(cmd, MPG))
43a6998b 678 pke_code_mpg(me, fw);
fd909089 679 else if(IS_PKE_CMD(cmd, DIRECT))
43a6998b 680 pke_code_direct(me, fw);
fd909089 681 else if(IS_PKE_CMD(cmd, DIRECTHL))
43a6998b 682 pke_code_directhl(me, fw);
fd909089 683 else if(IS_PKE_CMD(cmd, UNPACK))
43a6998b 684 pke_code_unpack(me, fw);
db6dac32 685 /* ... no other commands ... */
43a6998b
FCE
686 else
687 pke_code_error(me, fw);
688}
689
690
691
9614fb3c
FCE
692/* Clear out contents of FIFO; act as if it was empty. Return PC
693 pointing to one-past-last word. */
694
695unsigned_4
696pke_fifo_flush(struct pke_fifo* fifo)
697{
698 /* don't modify any state! */
699 return fifo->origin + fifo->next;
700}
701
702
703
121d6745
FCE
704/* Clear out contents of FIFO; make it really empty. */
705
706void
707pke_fifo_reset(struct pke_fifo* fifo)
708{
709 int i;
710
711 /* clear fifo quadwords */
712 for(i=0; i<fifo->next; i++)
713 {
714 zfree(fifo->quadwords[i]);
715 fifo->quadwords[i] = NULL;
716 }
717
718 /* reset pointers */
719 fifo->origin = 0;
720 fifo->next = 0;
721}
722
723
724
9614fb3c
FCE
725/* Make space for the next quadword in the FIFO. Allocate/enlarge
726 FIFO pointer block if necessary. Return a pointer to it. */
727
728struct fifo_quadword*
729pke_fifo_fit(struct pke_fifo* fifo)
730{
731 struct fifo_quadword* fqw;
732
733 /* out of space on quadword pointer array? */
734 if(fifo->next == fifo->length) /* also triggered before fifo->quadwords allocated */
735 {
736 struct fifo_quadword** new_qw;
737 unsigned_4 new_length = fifo->length + PKE_FIFO_GROW_SIZE;
738
739 /* allocate new pointer block */
740 new_qw = zalloc(new_length * sizeof(struct fifo_quadword*));
741 ASSERT(new_qw != NULL);
742
0b9843e5
FCE
743 /* copy over old contents, if any */
744 if(fifo->quadwords != NULL)
745 {
746 /* copy over old pointers to beginning of new block */
747 memcpy(new_qw, fifo->quadwords,
748 fifo->length * sizeof(struct fifo_quadword*));
749
750 /* free old block */
751 zfree(fifo->quadwords);
752 }
9614fb3c
FCE
753
754 /* replace pointers & counts */
755 fifo->quadwords = new_qw;
756 fifo->length = new_length;
757 }
758
759 /* sanity check */
760 ASSERT(fifo->quadwords != NULL);
761
762 /* allocate new quadword from heap */
763 fqw = zalloc(sizeof(struct fifo_quadword));
764 ASSERT(fqw != NULL);
765
766 /* push quadword onto fifo */
767 fifo->quadwords[fifo->next] = fqw;
768 fifo->next++;
769 return fqw;
770}
771
772
773
774/* Return a pointer to the FIFO quadword with given absolute index, or
775 NULL if it is out of range */
776
777struct fifo_quadword*
778pke_fifo_access(struct pke_fifo* fifo, unsigned_4 qwnum)
779{
780 struct fifo_quadword* fqw;
781
782 if((qwnum < fifo->origin) || /* before history */
783 (qwnum >= fifo->origin + fifo->next)) /* after last available quadword */
784 fqw = NULL;
785 else
786 {
787 ASSERT(fifo->quadwords != NULL); /* must be allocated already */
788 fqw = fifo->quadwords[qwnum - fifo->origin]; /* pull out pointer from array */
789 ASSERT(fqw != NULL); /* must be allocated already */
790 }
791
792 return fqw;
793}
794
795
796/* Authorize release of any FIFO entries older than given absolute quadword. */
797void
798pke_fifo_old(struct pke_fifo* fifo, unsigned_4 qwnum)
799{
800 /* do we have any too-old FIFO elements? */
801 if(fifo->origin + PKE_FIFO_ARCHEOLOGY < qwnum)
802 {
803 /* count quadwords to forget */
804 int horizon = qwnum - (fifo->origin + PKE_FIFO_ARCHEOLOGY);
805 int i;
806
807 /* free quadwords at indices below horizon */
808 for(i=0; i < horizon; i++)
809 zfree(fifo->quadwords[i]);
810
811 /* move surviving quadword pointers down to beginning of array */
812 for(i=horizon; i < fifo->next; i++)
813 fifo->quadwords[i-horizon] = fifo->quadwords[i];
814
815 /* clear duplicate pointers */
816 for(i=fifo->next - horizon; i < fifo->next; i++)
817 fifo->quadwords[i] = NULL;
818
819 /* adjust FIFO pointers */
820 fifo->origin = fifo->origin + horizon;
821 fifo->next = fifo->next - horizon;
822 }
823}
824
825
826
827
43a6998b 828/* advance the PC by given number of data words; update STAT/FQC
e2306992
FCE
829 field; assume FIFO is filled enough; classify passed-over words;
830 write FIFO trace line */
43a6998b
FCE
831
832void
833pke_pc_advance(struct pke_device* me, int num_words)
834{
835 int num = num_words;
e2306992 836 struct fifo_quadword* fq = NULL;
9614fb3c
FCE
837 unsigned_4 old_fifo_pc = me->fifo_pc;
838
e2306992 839 ASSERT(num_words >= 0);
43a6998b 840
b4d2f483
FCE
841 /* printf("pke %d pc_advance num_words %d\n", me->pke_number, num_words); */
842
843 while(1)
fba9bfed 844 {
9614fb3c
FCE
845 /* find next quadword, if any */
846 fq = pke_fifo_access(& me->fifo, me->fifo_pc);
43a6998b
FCE
847
848 /* skip over DMA tag words if present in word 0 or 1 */
9614fb3c 849 if(fq != NULL && fq->word_class[me->qw_pc] == wc_dma)
fba9bfed 850 {
43a6998b
FCE
851 /* skip by going around loop an extra time */
852 num ++;
fba9bfed 853 }
b4d2f483
FCE
854
855 /* nothing left to skip / no DMA tag here */
856 if(num == 0)
857 break;
e2306992 858
9614fb3c
FCE
859 /* we are supposed to skip existing words */
860 ASSERT(fq != NULL);
861
b4d2f483
FCE
862 /* one word skipped */
863 num --;
864
865 /* point to next word */
866 me->qw_pc ++;
867 if(me->qw_pc == 4)
e2306992 868 {
b4d2f483
FCE
869 me->qw_pc = 0;
870 me->fifo_pc ++;
e2306992 871
b4d2f483
FCE
872 /* trace the consumption of the FIFO quadword we just skipped over */
873 /* fq still points to it */
874 if(me->fifo_trace_file != NULL)
e2306992 875 {
b4d2f483
FCE
876 /* assert complete classification */
877 ASSERT(fq->word_class[3] != wc_unknown);
878 ASSERT(fq->word_class[2] != wc_unknown);
879 ASSERT(fq->word_class[1] != wc_unknown);
880 ASSERT(fq->word_class[0] != wc_unknown);
e2306992 881
b4d2f483
FCE
882 /* print trace record */
883 fprintf(me->fifo_trace_file,
884 "%d 0x%08x_%08x_%08x_%08x 0x%08x %c%c%c%c\n",
885 (me->pke_number == 0 ? 0 : 1),
886 (unsigned) fq->data[3], (unsigned) fq->data[2],
887 (unsigned) fq->data[1], (unsigned) fq->data[0],
888 (unsigned) fq->source_address,
889 fq->word_class[3], fq->word_class[2],
890 fq->word_class[1], fq->word_class[0]);
891 }
b4d2f483
FCE
892 } /* next quadword */
893 }
43a6998b 894
9614fb3c
FCE
895 /* age old entries before PC */
896 if(me->fifo_pc != old_fifo_pc)
897 {
898 /* we advanced the fifo-pc; authorize disposal of anything
899 before previous PKEcode */
900 pke_fifo_old(& me->fifo, old_fifo_pc);
901 }
902
43a6998b 903 /* clear FQC if FIFO is now empty */
9614fb3c
FCE
904 fq = pke_fifo_access(& me->fifo, me->fifo_pc);
905 if(fq == NULL)
fba9bfed 906 {
43a6998b 907 PKE_REG_MASK_SET(me, STAT, FQC, 0);
fba9bfed 908 }
e2306992
FCE
909 else /* annote the word where the PC lands as an PKEcode */
910 {
9614fb3c 911 ASSERT(fq->word_class[me->qw_pc] == wc_pkecode || fq->word_class[me->qw_pc] == wc_unknown);
e2306992
FCE
912 fq->word_class[me->qw_pc] = wc_pkecode;
913 }
43a6998b 914}
fba9bfed 915
fba9bfed 916
fba9bfed 917
9614fb3c
FCE
918
919
43a6998b
FCE
920/* Return pointer to FIFO quadword containing given operand# in FIFO.
921 `operand_num' starts at 1. Return pointer to operand word in last
922 argument, if non-NULL. If FIFO is not full enough, return 0.
923 Signal an ER0 indication upon skipping a DMA tag. */
fba9bfed 924
43a6998b 925struct fifo_quadword*
9614fb3c 926pke_pcrel_fifo(struct pke_device* me, int operand_num, unsigned_4** operand)
43a6998b 927{
121d6745 928 int num;
43a6998b 929 int new_qw_pc, new_fifo_pc;
e2306992 930 struct fifo_quadword* fq = NULL;
fba9bfed 931
121d6745
FCE
932 /* check for validity of last search results in cache */
933 if(me->last_fifo_pc == me->fifo_pc &&
934 me->last_qw_pc == me->qw_pc &&
935 operand_num > me->last_num)
936 {
937 /* continue search from last stop */
938 new_fifo_pc = me->last_new_fifo_pc;
939 new_qw_pc = me->last_new_qw_pc;
940 num = operand_num - me->last_num;
941 }
942 else
943 {
944 /* start search from scratch */
945 new_fifo_pc = me->fifo_pc;
946 new_qw_pc = me->qw_pc;
947 num = operand_num;
948 }
fba9bfed 949
121d6745 950 ASSERT(num > 0);
fba9bfed 951
9614fb3c 952 /* printf("pke %d pcrel_fifo operand_num %d\n", me->pke_number, operand_num); */
b4d2f483 953
e2306992 954 do
43a6998b
FCE
955 {
956 /* one word skipped */
957 num --;
fba9bfed 958
43a6998b
FCE
959 /* point to next word */
960 new_qw_pc ++;
961 if(new_qw_pc == 4)
fba9bfed 962 {
43a6998b
FCE
963 new_qw_pc = 0;
964 new_fifo_pc ++;
fba9bfed 965 }
fba9bfed 966
9614fb3c
FCE
967 fq = pke_fifo_access(& me->fifo, new_fifo_pc);
968
43a6998b 969 /* check for FIFO underflow */
9614fb3c
FCE
970 if(fq == NULL)
971 break;
43a6998b
FCE
972
973 /* skip over DMA tag words if present in word 0 or 1 */
e2306992 974 if(fq->word_class[new_qw_pc] == wc_dma)
fba9bfed 975 {
9614fb3c
FCE
976 /* set ER0 */
977 PKE_REG_MASK_SET(me, STAT, ER0, 1);
978
43a6998b 979 /* mismatch error! */
fd909089
FCE
980 if(! PKE_REG_MASK_GET(me, ERR, ME0))
981 {
9614fb3c 982 pke_begin_interrupt_stall(me);
fd909089
FCE
983 /* don't stall just yet -- finish this instruction */
984 /* the PPS_STALL state will be entered by pke_issue() next time */
985 }
43a6998b
FCE
986 /* skip by going around loop an extra time */
987 num ++;
fba9bfed
FCE
988 }
989 }
e2306992 990 while(num > 0);
fba9bfed 991
43a6998b 992 /* return pointer to operand word itself */
e2306992
FCE
993 if(fq != NULL)
994 {
995 *operand = & fq->data[new_qw_pc];
fba9bfed 996
9614fb3c
FCE
997 /* annote the word where the pseudo-PC lands as an PKE operand */
998 ASSERT(fq->word_class[new_qw_pc] == wc_pkedata || fq->word_class[new_qw_pc] == wc_unknown);
e2306992 999 fq->word_class[new_qw_pc] = wc_pkedata;
121d6745
FCE
1000
1001 /* store search results in cache */
1002 /* keys */
1003 me->last_fifo_pc = me->fifo_pc;
1004 me->last_qw_pc = me->qw_pc;
1005 /* values */
1006 me->last_num = operand_num;
1007 me->last_new_fifo_pc = new_fifo_pc;
1008 me->last_new_qw_pc = new_qw_pc;
e2306992
FCE
1009 }
1010
1011 return fq;
43a6998b 1012}
fba9bfed 1013
fba9bfed 1014
43a6998b
FCE
1015/* Return pointer to given operand# in FIFO. `operand_num' starts at 1.
1016 If FIFO is not full enough, return 0. Skip over DMA tags, but mark
1017 them as an error (ER0). */
fba9bfed 1018
43a6998b 1019unsigned_4*
9614fb3c 1020pke_pcrel_operand(struct pke_device* me, int operand_num)
43a6998b
FCE
1021{
1022 unsigned_4* operand = NULL;
1023 struct fifo_quadword* fifo_operand;
fba9bfed 1024
9614fb3c 1025 fifo_operand = pke_pcrel_fifo(me, operand_num, & operand);
fba9bfed 1026
43a6998b 1027 if(fifo_operand == NULL)
9614fb3c 1028 ASSERT(operand == NULL); /* pke_pcrel_fifo() ought leave it untouched */
fba9bfed 1029
43a6998b
FCE
1030 return operand;
1031}
fba9bfed 1032
fba9bfed 1033
db6dac32
FCE
1034/* Return a bit-field extract of given operand# in FIFO, and its
1035 source-addr. `bit_offset' starts at 0, referring to LSB after PKE
1036 instruction word. Width must be >0, <=32. Assume FIFO is full
1037 enough. Skip over DMA tags, but mark them as an error (ER0). */
1038
1039unsigned_4
9614fb3c 1040pke_pcrel_operand_bits(struct pke_device* me, int bit_offset, int bit_width, unsigned_4* source_addr)
db6dac32
FCE
1041{
1042 unsigned_4* word = NULL;
1043 unsigned_4 value;
1044 struct fifo_quadword* fifo_operand;
534a3d5c
FCE
1045 int wordnumber, bitnumber;
1046
1047 wordnumber = bit_offset/32;
1048 bitnumber = bit_offset%32;
db6dac32
FCE
1049
1050 /* find operand word with bitfield */
9614fb3c 1051 fifo_operand = pke_pcrel_fifo(me, wordnumber + 1, &word);
534a3d5c 1052 ASSERT(word != NULL);
db6dac32
FCE
1053
1054 /* extract bitfield from word */
534a3d5c 1055 value = BIT_MASK_GET(*word, bitnumber, bitnumber + bit_width - 1);
db6dac32
FCE
1056
1057 /* extract source addr from fifo word */
1058 *source_addr = fifo_operand->source_address;
1059
1060 return value;
1061}
1062
fba9bfed 1063
fba9bfed 1064
d22ea5d0
FCE
1065/* check for stall conditions on indicated devices (path* only on
1066 PKE1), do not change status; return 0 iff no stall */
43a6998b
FCE
1067int
1068pke_check_stall(struct pke_device* me, enum pke_check_target what)
1069{
1070 int any_stall = 0;
e2306992 1071 unsigned_4 cop2_stat, gpuif_stat;
43a6998b 1072
e2306992 1073 /* read status words */
534a3d5c
FCE
1074 ASSERT(sizeof(unsigned_4) == 4);
1075 PKE_MEM_READ(me, (GIF_REG_STAT),
1076 & gpuif_stat,
1077 4);
1078 PKE_MEM_READ(me, (COP2_REG_STAT_ADDR),
1079 & cop2_stat,
1080 4);
e2306992 1081
43a6998b
FCE
1082 /* perform checks */
1083 if(what == chk_vu)
1084 {
e2306992
FCE
1085 if(me->pke_number == 0)
1086 any_stall = BIT_MASK_GET(cop2_stat, COP2_REG_STAT_VBS0_B, COP2_REG_STAT_VBS0_E);
1087 else /* if(me->pke_number == 1) */
1088 any_stall = BIT_MASK_GET(cop2_stat, COP2_REG_STAT_VBS1_B, COP2_REG_STAT_VBS1_E);
db6dac32
FCE
1089 }
1090 else if(what == chk_path1) /* VU -> GPUIF */
1091 {
ebcfd86a 1092 ASSERT(me->pke_number == 1);
db6dac32 1093 if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 1)
43a6998b 1094 any_stall = 1;
fba9bfed 1095 }
db6dac32 1096 else if(what == chk_path2) /* PKE -> GPUIF */
fba9bfed 1097 {
ebcfd86a 1098 ASSERT(me->pke_number == 1);
db6dac32
FCE
1099 if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 2)
1100 any_stall = 1;
1101 }
1102 else if(what == chk_path3) /* DMA -> GPUIF */
1103 {
ebcfd86a 1104 ASSERT(me->pke_number == 1);
db6dac32 1105 if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 3)
43a6998b
FCE
1106 any_stall = 1;
1107 }
1108 else
1109 {
db6dac32
FCE
1110 /* invalid what */
1111 ASSERT(0);
43a6998b 1112 }
fba9bfed 1113
43a6998b
FCE
1114 /* any stall reasons? */
1115 return any_stall;
1116}
fba9bfed 1117
fba9bfed 1118
d22ea5d0 1119/* PKE1 only: flip the DBF bit; recompute TOPS, TOP */
43a6998b
FCE
1120void
1121pke_flip_dbf(struct pke_device* me)
1122{
370e0ef7 1123 int newdf;
d22ea5d0 1124 /* compute new TOP */
733cfc78
IC
1125 PKE_REG_MASK_SET(me, TOP, TOP,
1126 PKE_REG_MASK_GET(me, TOPS, TOPS));
43a6998b 1127 /* flip DBF */
370e0ef7
FCE
1128 newdf = PKE_REG_MASK_GET(me, DBF, DF) ? 0 : 1;
1129 PKE_REG_MASK_SET(me, DBF, DF, newdf);
1130 PKE_REG_MASK_SET(me, STAT, DBF, newdf);
43a6998b
FCE
1131 /* compute new TOPS */
1132 PKE_REG_MASK_SET(me, TOPS, TOPS,
1133 (PKE_REG_MASK_GET(me, BASE, BASE) +
370e0ef7
FCE
1134 newdf * PKE_REG_MASK_GET(me, OFST, OFFSET)));
1135
d22ea5d0
FCE
1136 /* this is equivalent to last word from okadaa (98-02-25):
1137 1) TOP=TOPS;
1138 2) TOPS=BASE + !DBF*OFFSET
1139 3) DBF=!DBF */
43a6998b 1140}
fba9bfed 1141
fba9bfed 1142
9614fb3c
FCE
1143/* set the STAT:PIS bit and send an interrupt to the 5900 */
1144void
1145pke_begin_interrupt_stall(struct pke_device* me)
1146{
1147 /* set PIS */
1148 PKE_REG_MASK_SET(me, STAT, PIS, 1);
1149
1150 /* XXX: send interrupt to 5900? */
1151}
1152
1153
1154
fba9bfed 1155
43a6998b
FCE
1156/* PKEcode handler functions -- responsible for checking and
1157 confirming old stall conditions, executing pkecode, updating PC and
1158 status registers -- may assume being run on correct PKE unit */
1159
1160void
1161pke_code_nop(struct pke_device* me, unsigned_4 pkecode)
1162{
1163 /* done */
1164 pke_pc_advance(me, 1);
1165 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1166}
fba9bfed 1167
fba9bfed 1168
43a6998b
FCE
1169void
1170pke_code_stcycl(struct pke_device* me, unsigned_4 pkecode)
1171{
1172 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
d22ea5d0 1173
43a6998b 1174 /* copy immediate value into CYCLE reg */
534a3d5c
FCE
1175 PKE_REG_MASK_SET(me, CYCLE, WL, BIT_MASK_GET(imm, 8, 15));
1176 PKE_REG_MASK_SET(me, CYCLE, CL, BIT_MASK_GET(imm, 0, 7));
43a6998b
FCE
1177 /* done */
1178 pke_pc_advance(me, 1);
1179 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1180}
fba9bfed 1181
fba9bfed 1182
43a6998b
FCE
1183void
1184pke_code_offset(struct pke_device* me, unsigned_4 pkecode)
1185{
1186 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
d22ea5d0 1187
43a6998b
FCE
1188 /* copy 10 bits to OFFSET field */
1189 PKE_REG_MASK_SET(me, OFST, OFFSET, BIT_MASK_GET(imm, 0, 9));
1190 /* clear DBF bit */
1191 PKE_REG_MASK_SET(me, DBF, DF, 0);
1192 /* clear other DBF bit */
1193 PKE_REG_MASK_SET(me, STAT, DBF, 0);
1194 /* set TOPS = BASE */
1195 PKE_REG_MASK_SET(me, TOPS, TOPS, PKE_REG_MASK_GET(me, BASE, BASE));
1196 /* done */
1197 pke_pc_advance(me, 1);
1198 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1199}
fba9bfed 1200
fba9bfed 1201
43a6998b
FCE
1202void
1203pke_code_base(struct pke_device* me, unsigned_4 pkecode)
1204{
1205 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
d22ea5d0 1206
43a6998b
FCE
1207 /* copy 10 bits to BASE field */
1208 PKE_REG_MASK_SET(me, BASE, BASE, BIT_MASK_GET(imm, 0, 9));
43a6998b
FCE
1209 /* done */
1210 pke_pc_advance(me, 1);
1211 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1212}
fba9bfed 1213
fba9bfed 1214
43a6998b
FCE
1215void
1216pke_code_itop(struct pke_device* me, unsigned_4 pkecode)
1217{
1218 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
d22ea5d0 1219
43a6998b
FCE
1220 /* copy 10 bits to ITOPS field */
1221 PKE_REG_MASK_SET(me, ITOPS, ITOPS, BIT_MASK_GET(imm, 0, 9));
1222 /* done */
1223 pke_pc_advance(me, 1);
1224 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1225}
fba9bfed 1226
fba9bfed 1227
43a6998b
FCE
1228void
1229pke_code_stmod(struct pke_device* me, unsigned_4 pkecode)
1230{
1231 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
d22ea5d0 1232
43a6998b
FCE
1233 /* copy 2 bits to MODE register */
1234 PKE_REG_MASK_SET(me, MODE, MDE, BIT_MASK_GET(imm, 0, 2));
1235 /* done */
1236 pke_pc_advance(me, 1);
1237 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1238}
fba9bfed 1239
43a6998b
FCE
1240
1241void
1242pke_code_mskpath3(struct pke_device* me, unsigned_4 pkecode)
1243{
b4d2f483
FCE
1244 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
1245 unsigned_4 gif_mode;
1246
89154e47 1247 /* set appropriate bit */
b4d2f483 1248 if(BIT_MASK_GET(imm, PKE_REG_MSKPATH3_B, PKE_REG_MSKPATH3_E) != 0)
ebcfd86a 1249 gif_mode = GIF_REG_STAT_M3P;
b4d2f483 1250 else
89154e47 1251 gif_mode = 0;
b4d2f483 1252
ebcfd86a
FCE
1253 /* write register to "read-only" register; gpuif code will look at M3P bit only */
1254 PKE_MEM_WRITE(me, GIF_REG_VIF_M3P, & gif_mode, 4);
b4d2f483 1255
b4d2f483
FCE
1256 /* done */
1257 pke_pc_advance(me, 1);
1258 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
43a6998b
FCE
1259}
1260
1261
1262void
1263pke_code_pkemark(struct pke_device* me, unsigned_4 pkecode)
1264{
1265 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
1266 /* copy 16 bits to MARK register */
1267 PKE_REG_MASK_SET(me, MARK, MARK, BIT_MASK_GET(imm, 0, 15));
1268 /* set MRK bit in STAT register - CPU2 v2.1 docs incorrect */
1269 PKE_REG_MASK_SET(me, STAT, MRK, 1);
1270 /* done */
1271 pke_pc_advance(me, 1);
1272 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1273}
1274
1275
1276void
1277pke_code_flushe(struct pke_device* me, unsigned_4 pkecode)
1278{
1279 /* compute next PEW bit */
1280 if(pke_check_stall(me, chk_vu))
1281 {
1282 /* VU busy */
1283 PKE_REG_MASK_SET(me, STAT, PEW, 1);
1284 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL);
1285 /* try again next cycle */
fba9bfed 1286 }
fba9bfed
FCE
1287 else
1288 {
43a6998b
FCE
1289 /* VU idle */
1290 PKE_REG_MASK_SET(me, STAT, PEW, 0);
1291 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
fba9bfed
FCE
1292 pke_pc_advance(me, 1);
1293 }
fba9bfed
FCE
1294}
1295
1296
43a6998b
FCE
1297void
1298pke_code_flush(struct pke_device* me, unsigned_4 pkecode)
1299{
1300 int something_busy = 0;
1301
1302 /* compute next PEW, PGW bits */
1303 if(pke_check_stall(me, chk_vu))
1304 {
1305 something_busy = 1;
1306 PKE_REG_MASK_SET(me, STAT, PEW, 1);
1307 }
1308 else
1309 PKE_REG_MASK_SET(me, STAT, PEW, 0);
fba9bfed
FCE
1310
1311
43a6998b
FCE
1312 if(pke_check_stall(me, chk_path1) ||
1313 pke_check_stall(me, chk_path2))
1314 {
1315 something_busy = 1;
1316 PKE_REG_MASK_SET(me, STAT, PGW, 1);
1317 }
1318 else
1319 PKE_REG_MASK_SET(me, STAT, PGW, 0);
fba9bfed 1320
43a6998b
FCE
1321 /* go or no go */
1322 if(something_busy)
1323 {
1324 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_WAIT);
1325 /* try again next cycle */
1326 }
1327 else
1328 {
1329 /* all idle */
1330 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1331 pke_pc_advance(me, 1);
1332 }
1333}
fba9bfed 1334
fba9bfed
FCE
1335
1336void
43a6998b 1337pke_code_flusha(struct pke_device* me, unsigned_4 pkecode)
fba9bfed 1338{
43a6998b 1339 int something_busy = 0;
fba9bfed 1340
43a6998b
FCE
1341 /* compute next PEW, PGW bits */
1342 if(pke_check_stall(me, chk_vu))
fba9bfed 1343 {
43a6998b
FCE
1344 something_busy = 1;
1345 PKE_REG_MASK_SET(me, STAT, PEW, 1);
fba9bfed 1346 }
43a6998b
FCE
1347 else
1348 PKE_REG_MASK_SET(me, STAT, PEW, 0);
fba9bfed 1349
43a6998b
FCE
1350
1351 if(pke_check_stall(me, chk_path1) ||
1352 pke_check_stall(me, chk_path2) ||
1353 pke_check_stall(me, chk_path3))
fba9bfed 1354 {
43a6998b
FCE
1355 something_busy = 1;
1356 PKE_REG_MASK_SET(me, STAT, PGW, 1);
fba9bfed 1357 }
43a6998b
FCE
1358 else
1359 PKE_REG_MASK_SET(me, STAT, PGW, 0);
fba9bfed 1360
43a6998b
FCE
1361 if(something_busy)
1362 {
1363 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_WAIT);
1364 /* try again next cycle */
1365 }
1366 else
1367 {
1368 /* all idle */
1369 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1370 pke_pc_advance(me, 1);
1371 }
fba9bfed
FCE
1372}
1373
1374
43a6998b
FCE
1375void
1376pke_code_pkemscal(struct pke_device* me, unsigned_4 pkecode)
1377{
1378 /* compute next PEW bit */
1379 if(pke_check_stall(me, chk_vu))
1380 {
1381 /* VU busy */
1382 PKE_REG_MASK_SET(me, STAT, PEW, 1);
1383 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL);
1384 /* try again next cycle */
1385 }
1386 else
1387 {
1388 unsigned_4 vu_pc;
1389 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
1390
1391 /* VU idle */
1392 PKE_REG_MASK_SET(me, STAT, PEW, 0);
1393
1394 /* flip DBF on PKE1 */
1395 if(me->pke_number == 1)
1396 pke_flip_dbf(me);
1397
f0bb94cd 1398 /* compute new PC for VU (host byte-order) */
db6dac32 1399 vu_pc = BIT_MASK_GET(imm, 0, 15);
f0bb94cd 1400 vu_pc = T2H_4(vu_pc);
534a3d5c 1401
43a6998b 1402 /* write new PC; callback function gets VU running */
534a3d5c
FCE
1403 ASSERT(sizeof(unsigned_4) == 4);
1404 PKE_MEM_WRITE(me, (me->pke_number == 0 ? VU0_CIA : VU1_CIA),
1405 & vu_pc,
1406 4);
43a6998b 1407
d22ea5d0
FCE
1408 /* copy ITOPS field to ITOP */
1409 PKE_REG_MASK_SET(me, ITOP, ITOP, PKE_REG_MASK_GET(me, ITOPS, ITOPS));
1410
43a6998b
FCE
1411 /* done */
1412 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1413 pke_pc_advance(me, 1);
1414 }
1415}
fba9bfed 1416
fba9bfed 1417
43a6998b
FCE
1418
1419void
1420pke_code_pkemscnt(struct pke_device* me, unsigned_4 pkecode)
fba9bfed 1421{
43a6998b
FCE
1422 /* compute next PEW bit */
1423 if(pke_check_stall(me, chk_vu))
1424 {
1425 /* VU busy */
1426 PKE_REG_MASK_SET(me, STAT, PEW, 1);
1427 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL);
1428 /* try again next cycle */
1429 }
1430 else
1431 {
1432 unsigned_4 vu_pc;
fba9bfed 1433
43a6998b
FCE
1434 /* VU idle */
1435 PKE_REG_MASK_SET(me, STAT, PEW, 0);
fba9bfed 1436
43a6998b
FCE
1437 /* flip DBF on PKE1 */
1438 if(me->pke_number == 1)
1439 pke_flip_dbf(me);
fba9bfed 1440
43a6998b 1441 /* read old PC */
534a3d5c
FCE
1442 ASSERT(sizeof(unsigned_4) == 4);
1443 PKE_MEM_READ(me, (me->pke_number == 0 ? VU0_CIA : VU1_CIA),
1444 & vu_pc,
1445 4);
43a6998b
FCE
1446
1447 /* rewrite new PC; callback function gets VU running */
534a3d5c
FCE
1448 ASSERT(sizeof(unsigned_4) == 4);
1449 PKE_MEM_WRITE(me, (me->pke_number == 0 ? VU0_CIA : VU1_CIA),
1450 & vu_pc,
1451 4);
43a6998b 1452
d22ea5d0
FCE
1453 /* copy ITOPS field to ITOP */
1454 PKE_REG_MASK_SET(me, ITOP, ITOP, PKE_REG_MASK_GET(me, ITOPS, ITOPS));
1455
43a6998b
FCE
1456 /* done */
1457 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1458 pke_pc_advance(me, 1);
1459 }
1460}
1461
1462
1463void
1464pke_code_pkemscalf(struct pke_device* me, unsigned_4 pkecode)
1465{
1466 int something_busy = 0;
1467
1468 /* compute next PEW, PGW bits */
1469 if(pke_check_stall(me, chk_vu))
fba9bfed 1470 {
43a6998b
FCE
1471 something_busy = 1;
1472 PKE_REG_MASK_SET(me, STAT, PEW, 1);
fba9bfed 1473 }
43a6998b
FCE
1474 else
1475 PKE_REG_MASK_SET(me, STAT, PEW, 0);
fba9bfed 1476
43a6998b
FCE
1477
1478 if(pke_check_stall(me, chk_path1) ||
1479 pke_check_stall(me, chk_path2) ||
1480 pke_check_stall(me, chk_path3))
1481 {
1482 something_busy = 1;
1483 PKE_REG_MASK_SET(me, STAT, PGW, 1);
1484 }
fba9bfed 1485 else
43a6998b 1486 PKE_REG_MASK_SET(me, STAT, PGW, 0);
fba9bfed 1487
43a6998b
FCE
1488 /* go or no go */
1489 if(something_busy)
1490 {
1491 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_WAIT);
1492 /* try again next cycle */
1493 }
1494 else
1495 {
1496 unsigned_4 vu_pc;
1497 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
1498
1499 /* flip DBF on PKE1 */
1500 if(me->pke_number == 1)
1501 pke_flip_dbf(me);
1502
f0bb94cd 1503 /* compute new PC for VU (host byte-order) */
db6dac32 1504 vu_pc = BIT_MASK_GET(imm, 0, 15);
f0bb94cd 1505 vu_pc = T2H_4(vu_pc);
534a3d5c
FCE
1506
1507 /* rewrite new PC; callback function gets VU running */
1508 ASSERT(sizeof(unsigned_4) == 4);
1509 PKE_MEM_WRITE(me, (me->pke_number == 0 ? VU0_CIA : VU1_CIA),
1510 & vu_pc,
1511 4);
43a6998b 1512
d22ea5d0
FCE
1513 /* copy ITOPS field to ITOP */
1514 PKE_REG_MASK_SET(me, ITOP, ITOP, PKE_REG_MASK_GET(me, ITOPS, ITOPS));
1515
43a6998b
FCE
1516 /* done */
1517 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1518 pke_pc_advance(me, 1);
1519 }
fba9bfed
FCE
1520}
1521
1522
43a6998b
FCE
1523void
1524pke_code_stmask(struct pke_device* me, unsigned_4 pkecode)
1525{
43a6998b 1526 unsigned_4* mask;
d22ea5d0 1527
d22ea5d0 1528 /* check that FIFO has one more word for STMASK operand */
9614fb3c 1529 mask = pke_pcrel_operand(me, 1);
43a6998b
FCE
1530 if(mask != NULL)
1531 {
1532 /* "transferring" operand */
1533 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
db6dac32
FCE
1534
1535 /* set NUM */
1536 PKE_REG_MASK_SET(me, NUM, NUM, 1);
1537
43a6998b
FCE
1538 /* fill the register */
1539 PKE_REG_MASK_SET(me, MASK, MASK, *mask);
db6dac32
FCE
1540
1541 /* set NUM */
1542 PKE_REG_MASK_SET(me, NUM, NUM, 0);
1543
43a6998b
FCE
1544 /* done */
1545 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
e2306992 1546 pke_pc_advance(me, 2);
43a6998b
FCE
1547 }
1548 else
1549 {
1550 /* need to wait for another word */
1551 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_WAIT);
1552 /* try again next cycle */
1553 }
1554}
fba9bfed 1555
fba9bfed 1556
43a6998b
FCE
1557void
1558pke_code_strow(struct pke_device* me, unsigned_4 pkecode)
fba9bfed 1559{
43a6998b
FCE
1560 /* check that FIFO has four more words for STROW operand */
1561 unsigned_4* last_op;
1562
9614fb3c 1563 last_op = pke_pcrel_operand(me, 4);
43a6998b
FCE
1564 if(last_op != NULL)
1565 {
1566 /* "transferring" operand */
1567 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
1568
db6dac32
FCE
1569 /* set NUM */
1570 PKE_REG_MASK_SET(me, NUM, NUM, 1);
1571
43a6998b 1572 /* copy ROW registers: must all exist if 4th operand exists */
9614fb3c
FCE
1573 me->regs[PKE_REG_R0][0] = * pke_pcrel_operand(me, 1);
1574 me->regs[PKE_REG_R1][0] = * pke_pcrel_operand(me, 2);
1575 me->regs[PKE_REG_R2][0] = * pke_pcrel_operand(me, 3);
1576 me->regs[PKE_REG_R3][0] = * pke_pcrel_operand(me, 4);
43a6998b 1577
db6dac32
FCE
1578 /* set NUM */
1579 PKE_REG_MASK_SET(me, NUM, NUM, 0);
1580
43a6998b
FCE
1581 /* done */
1582 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1583 pke_pc_advance(me, 5);
1584 }
1585 else
1586 {
1587 /* need to wait for another word */
1588 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_WAIT);
1589 /* try again next cycle */
1590 }
1591}
aea481da 1592
fba9bfed 1593
43a6998b
FCE
1594void
1595pke_code_stcol(struct pke_device* me, unsigned_4 pkecode)
1596{
1597 /* check that FIFO has four more words for STCOL operand */
1598 unsigned_4* last_op;
1599
9614fb3c 1600 last_op = pke_pcrel_operand(me, 4);
43a6998b 1601 if(last_op != NULL)
fba9bfed 1602 {
43a6998b
FCE
1603 /* "transferring" operand */
1604 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
1605
db6dac32
FCE
1606 /* set NUM */
1607 PKE_REG_MASK_SET(me, NUM, NUM, 1);
1608
43a6998b 1609 /* copy COL registers: must all exist if 4th operand exists */
9614fb3c
FCE
1610 me->regs[PKE_REG_C0][0] = * pke_pcrel_operand(me, 1);
1611 me->regs[PKE_REG_C1][0] = * pke_pcrel_operand(me, 2);
1612 me->regs[PKE_REG_C2][0] = * pke_pcrel_operand(me, 3);
1613 me->regs[PKE_REG_C3][0] = * pke_pcrel_operand(me, 4);
43a6998b 1614
db6dac32
FCE
1615 /* set NUM */
1616 PKE_REG_MASK_SET(me, NUM, NUM, 0);
1617
43a6998b
FCE
1618 /* done */
1619 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1620 pke_pc_advance(me, 5);
fba9bfed 1621 }
fba9bfed 1622 else
43a6998b
FCE
1623 {
1624 /* need to wait for another word */
1625 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_WAIT);
1626 /* try again next cycle */
1627 }
1628}
fba9bfed 1629
43a6998b
FCE
1630
1631void
1632pke_code_mpg(struct pke_device* me, unsigned_4 pkecode)
1633{
1634 unsigned_4* last_mpg_word;
1635 int num = BIT_MASK_GET(pkecode, PKE_OPCODE_NUM_B, PKE_OPCODE_NUM_E);
1636 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
1637
653c2590
FCE
1638 /* assert 64-bit alignment of MPG operand */
1639 if(me->qw_pc != 3 && me->qw_pc != 1)
1640 return pke_code_error(me, pkecode);
1641
43a6998b
FCE
1642 /* map zero to max+1 */
1643 if(num==0) num=0x100;
1644
1645 /* check that FIFO has a few more words for MPG operand */
9614fb3c 1646 last_mpg_word = pke_pcrel_operand(me, num*2); /* num: number of 64-bit words */
43a6998b
FCE
1647 if(last_mpg_word != NULL)
1648 {
1649 /* perform implied FLUSHE */
db6dac32 1650 if(pke_check_stall(me, chk_vu))
653c2590
FCE
1651 {
1652 /* VU busy */
1653 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL);
1654 /* retry this instruction next clock */
1655 }
1656 else
43a6998b
FCE
1657 {
1658 /* VU idle */
1659 int i;
1660
1661 /* "transferring" operand */
1662 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
1663
534a3d5c
FCE
1664 /* set NUM */
1665 PKE_REG_MASK_SET(me, NUM, NUM, num);
1666
1667 /* transfer VU instructions, one word-pair per iteration */
1668 for(i=0; i<num; i++)
43a6998b
FCE
1669 {
1670 address_word vu_addr_base, vu_addr;
1671 address_word vutrack_addr_base, vutrack_addr;
89154e47 1672 address_word vu_addr_max_size;
653c2590 1673 unsigned_4 vu_lower_opcode, vu_upper_opcode;
43a6998b 1674 unsigned_4* operand;
534a3d5c
FCE
1675 struct fifo_quadword* fq;
1676 int next_num;
1677
1678 /* decrement NUM */
1679 next_num = PKE_REG_MASK_GET(me, NUM, NUM) - 1;
1680 PKE_REG_MASK_SET(me, NUM, NUM, next_num);
43a6998b 1681
db6dac32 1682 /* imm: in 64-bit units for MPG instruction */
43a6998b
FCE
1683 /* VU*_MEM0 : instruction memory */
1684 vu_addr_base = (me->pke_number == 0) ?
733cfc78 1685 VU0_MEM0_WINDOW_START : VU1_MEM0_WINDOW_START;
89154e47
FCE
1686 vu_addr_max_size = (me->pke_number == 0) ?
1687 VU0_MEM0_SIZE : VU1_MEM0_SIZE;
43a6998b
FCE
1688 vutrack_addr_base = (me->pke_number == 0) ?
1689 VU0_MEM0_SRCADDR_START : VU1_MEM0_SRCADDR_START;
89154e47
FCE
1690
1691 /* compute VU address for this word-pair */
1692 vu_addr = vu_addr_base + (imm + i) * 8;
1693 /* check for vu_addr overflow */
1694 while(vu_addr >= vu_addr_base + vu_addr_max_size)
1695 vu_addr -= vu_addr_max_size;
1696
1697 /* compute VU tracking address */
1698 vutrack_addr = vutrack_addr_base + ((signed_8)vu_addr - (signed_8)vu_addr_base) / 2;
534a3d5c 1699
653c2590 1700 /* Fetch operand words; assume they are already little-endian for VU imem */
9614fb3c 1701 fq = pke_pcrel_fifo(me, i*2 + 1, & operand);
653c2590 1702 vu_lower_opcode = *operand;
9614fb3c 1703 vu_upper_opcode = *pke_pcrel_operand(me, i*2 + 2);
43a6998b
FCE
1704
1705 /* write data into VU memory */
f0bb94cd 1706 /* lower (scalar) opcode comes in first word ; macro performs H2T! */
534a3d5c 1707 PKE_MEM_WRITE(me, vu_addr,
b4d2f483 1708 & vu_lower_opcode,
653c2590 1709 4);
f0bb94cd 1710 /* upper (vector) opcode comes in second word ; H2T */
b4d2f483 1711 ASSERT(sizeof(unsigned_4) == 4);
653c2590 1712 PKE_MEM_WRITE(me, vu_addr + 4,
b4d2f483 1713 & vu_upper_opcode,
653c2590 1714 4);
43a6998b 1715
653c2590 1716 /* write tracking address in target byte-order */
653c2590 1717 ASSERT(sizeof(unsigned_4) == 4);
534a3d5c 1718 PKE_MEM_WRITE(me, vutrack_addr,
f0bb94cd 1719 & fq->source_address,
534a3d5c 1720 4);
43a6998b 1721 } /* VU xfer loop */
db6dac32
FCE
1722
1723 /* check NUM */
1724 ASSERT(PKE_REG_MASK_GET(me, NUM, NUM) == 0);
43a6998b
FCE
1725
1726 /* done */
1727 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1728 pke_pc_advance(me, 1 + num*2);
1729 }
43a6998b
FCE
1730 } /* if FIFO full enough */
1731 else
1732 {
1733 /* need to wait for another word */
1734 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_WAIT);
1735 /* retry this instruction next clock */
1736 }
aea481da
DE
1737}
1738
1739
43a6998b
FCE
1740void
1741pke_code_direct(struct pke_device* me, unsigned_4 pkecode)
1742{
1743 /* check that FIFO has a few more words for DIRECT operand */
1744 unsigned_4* last_direct_word;
1745 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
43a6998b 1746
653c2590
FCE
1747 /* assert 128-bit alignment of DIRECT operand */
1748 if(me->qw_pc != 3)
1749 return pke_code_error(me, pkecode);
1750
43a6998b
FCE
1751 /* map zero to max+1 */
1752 if(imm==0) imm=0x10000;
1753
9614fb3c 1754 last_direct_word = pke_pcrel_operand(me, imm*4); /* imm: number of 128-bit words */
43a6998b
FCE
1755 if(last_direct_word != NULL)
1756 {
1757 /* VU idle */
1758 int i;
f0bb94cd 1759 unsigned_16 fifo_data;
43a6998b
FCE
1760
1761 /* "transferring" operand */
1762 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
1763
1764 /* transfer GPUIF quadwords, one word per iteration */
1765 for(i=0; i<imm*4; i++)
1766 {
9614fb3c 1767 unsigned_4* operand = pke_pcrel_operand(me, 1+i);
43a6998b
FCE
1768
1769 /* collect word into quadword */
f0bb94cd 1770 *A4_16(&fifo_data, 3 - (i % 4)) = *operand;
0b9843e5 1771
534a3d5c
FCE
1772 /* write to GPUIF FIFO only with full quadword */
1773 if(i % 4 == 3)
43a6998b 1774 {
534a3d5c
FCE
1775 ASSERT(sizeof(fifo_data) == 16);
1776 PKE_MEM_WRITE(me, GIF_PATH2_FIFO_ADDR,
f0bb94cd 1777 & fifo_data,
534a3d5c 1778 16);
43a6998b 1779 } /* write collected quadword */
43a6998b
FCE
1780 } /* GPUIF xfer loop */
1781
1782 /* done */
1783 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
1784 pke_pc_advance(me, 1 + imm*4);
1785 } /* if FIFO full enough */
1786 else
1787 {
1788 /* need to wait for another word */
1789 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_WAIT);
1790 /* retry this instruction next clock */
1791 }
1792}
fba9bfed 1793
43a6998b
FCE
1794
1795void
1796pke_code_directhl(struct pke_device* me, unsigned_4 pkecode)
fba9bfed 1797{
43a6998b
FCE
1798 /* treat the same as DIRECTH */
1799 pke_code_direct(me, pkecode);
1800}
fba9bfed 1801
43a6998b
FCE
1802
1803void
1804pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
1805{
1806 int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
1807 int cmd = BIT_MASK_GET(pkecode, PKE_OPCODE_CMD_B, PKE_OPCODE_CMD_E);
1808 int num = BIT_MASK_GET(pkecode, PKE_OPCODE_NUM_B, PKE_OPCODE_NUM_E);
9614fb3c 1809 int nummx = (num == 0) ? 0x0100 : num;
db6dac32 1810 short vn = BIT_MASK_GET(cmd, 2, 3); /* unpack shape controls */
43a6998b 1811 short vl = BIT_MASK_GET(cmd, 0, 1);
43a6998b 1812 int m = BIT_MASK_GET(cmd, 4, 4);
db6dac32 1813 short cl = PKE_REG_MASK_GET(me, CYCLE, CL); /* cycle controls */
43a6998b 1814 short wl = PKE_REG_MASK_GET(me, CYCLE, WL);
9614fb3c 1815 short addrwl = (wl == 0) ? 0x0100 : wl;
db6dac32 1816 int r = BIT_MASK_GET(imm, 15, 15); /* indicator bits in imm value */
653c2590 1817 int usn = BIT_MASK_GET(imm, 14, 14);
db6dac32 1818
43a6998b 1819 int n, num_operands;
534a3d5c 1820 unsigned_4* last_operand_word = NULL;
9614fb3c
FCE
1821
1822 /* catch all illegal UNPACK variants */
1823 if(vl == 3 && vn < 3)
1824 {
1825 pke_code_error(me, pkecode);
1826 return;
1827 }
fba9bfed 1828
43a6998b 1829 /* compute PKEcode length, as given in CPU2 spec, v2.1 pg. 11 */
9614fb3c 1830 if(cl >= addrwl)
43a6998b
FCE
1831 n = num;
1832 else
9614fb3c 1833 n = cl * (nummx / addrwl) + PKE_LIMIT(nummx % addrwl, cl);
fd909089 1834 num_operands = (31 + (32 >> vl) * (vn+1) * n)/32; /* round up to next word */
43a6998b
FCE
1835
1836 /* confirm that FIFO has enough words in it */
534a3d5c 1837 if(num_operands > 0)
9614fb3c 1838 last_operand_word = pke_pcrel_operand(me, num_operands);
534a3d5c 1839 if(last_operand_word != NULL || num_operands == 0)
43a6998b 1840 {
534a3d5c
FCE
1841 address_word vu_addr_base, vutrack_addr_base;
1842 address_word vu_addr_max_size;
1843 int vector_num_out, vector_num_in;
43a6998b
FCE
1844
1845 /* "transferring" operand */
1846 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
1847
1848 /* don't check whether VU is idle */
db6dac32
FCE
1849
1850 /* compute VU address base */
43a6998b 1851 if(me->pke_number == 0)
534a3d5c 1852 {
d22ea5d0 1853 vu_addr_base = VU0_MEM1_WINDOW_START;
534a3d5c 1854 vu_addr_max_size = VU0_MEM1_SIZE;
d22ea5d0
FCE
1855 vutrack_addr_base = VU0_MEM1_SRCADDR_START;
1856 r = 0;
534a3d5c 1857 }
43a6998b
FCE
1858 else
1859 {
d22ea5d0 1860 vu_addr_base = VU1_MEM1_WINDOW_START;
534a3d5c 1861 vu_addr_max_size = VU1_MEM1_SIZE;
d22ea5d0 1862 vutrack_addr_base = VU1_MEM1_SRCADDR_START;
43a6998b 1863 }
db6dac32
FCE
1864
1865 /* set NUM */
9614fb3c 1866 PKE_REG_MASK_SET(me, NUM, NUM, nummx);
db6dac32 1867
43a6998b 1868 /* transfer given number of vectors */
534a3d5c
FCE
1869 vector_num_out = 0; /* output vector number being processed */
1870 vector_num_in = 0; /* argument vector number being processed */
db6dac32 1871 do
43a6998b
FCE
1872 {
1873 quadword vu_old_data;
1874 quadword vu_new_data;
1875 quadword unpacked_data;
1876 address_word vu_addr;
534a3d5c 1877 address_word vutrack_addr;
db6dac32 1878 unsigned_4 source_addr = 0;
43a6998b 1879 int i;
534a3d5c
FCE
1880 int next_num;
1881
db6dac32 1882 /* decrement NUM */
534a3d5c
FCE
1883 next_num = PKE_REG_MASK_GET(me, NUM, NUM) - 1;
1884 PKE_REG_MASK_SET(me, NUM, NUM, next_num);
1885
43a6998b
FCE
1886 /* compute VU destination address, as bytes in R5900 memory */
1887 if(cl >= wl)
1888 {
1889 /* map zero to max+1 */
d22ea5d0 1890 vu_addr = vu_addr_base + 16 * (BIT_MASK_GET(imm, 0, 9) +
fd909089
FCE
1891 (vector_num_out / addrwl) * cl +
1892 (vector_num_out % addrwl));
43a6998b
FCE
1893 }
1894 else
d22ea5d0 1895 vu_addr = vu_addr_base + 16 * (BIT_MASK_GET(imm, 0, 9) +
d22ea5d0 1896 vector_num_out);
fd909089
FCE
1897
1898 /* handle "R" double-buffering bit */
1899 if(r)
1900 vu_addr += 16 * PKE_REG_MASK_GET(me, TOPS, TOPS);
534a3d5c
FCE
1901
1902 /* check for vu_addr overflow */
1903 while(vu_addr >= vu_addr_base + vu_addr_max_size)
1904 vu_addr -= vu_addr_max_size;
1905
1906 /* compute address of tracking table entry */
1907 vutrack_addr = vutrack_addr_base + ((signed_8)vu_addr - (signed_8)vu_addr_base) / 4;
db6dac32 1908
f0bb94cd
FCE
1909 /* read old VU data word at address; reverse words if needed */
1910 {
1911 unsigned_16 vu_old_badwords;
1912 ASSERT(sizeof(vu_old_badwords) == 16);
1913 PKE_MEM_READ(me, vu_addr,
1914 &vu_old_badwords, 16);
1915 vu_old_data[0] = * A4_16(& vu_old_badwords, 3);
1916 vu_old_data[1] = * A4_16(& vu_old_badwords, 2);
1917 vu_old_data[2] = * A4_16(& vu_old_badwords, 1);
1918 vu_old_data[3] = * A4_16(& vu_old_badwords, 0);
1919 }
653c2590 1920
43a6998b
FCE
1921 /* For cyclic unpack, next operand quadword may come from instruction stream
1922 or be zero. */
9614fb3c
FCE
1923 if((cl < addrwl) &&
1924 (vector_num_out % addrwl) >= cl)
43a6998b
FCE
1925 {
1926 /* clear operand - used only in a "indeterminate" state */
1927 for(i = 0; i < 4; i++)
1928 unpacked_data[i] = 0;
1929 }
1930 else
1931 {
db6dac32 1932 /* compute packed vector dimensions */
9614fb3c 1933 int vectorbits = 0, unitbits = 0;
db6dac32
FCE
1934
1935 if(vl < 3) /* PKE_UNPACK_*_{32,16,8} */
43a6998b 1936 {
db6dac32
FCE
1937 unitbits = (32 >> vl);
1938 vectorbits = unitbits * (vn+1);
1939 }
1940 else if(vl == 3 && vn == 3) /* PKE_UNPACK_V4_5 */
1941 {
1942 unitbits = 5;
1943 vectorbits = 16;
1944 }
1945 else /* illegal unpack variant */
1946 {
9614fb3c
FCE
1947 /* should have been caught at top of function */
1948 ASSERT(0);
db6dac32
FCE
1949 }
1950
1951 /* loop over columns */
1952 for(i=0; i<=vn; i++)
1953 {
1954 unsigned_4 operand;
fba9bfed 1955
db6dac32
FCE
1956 /* offset in bits in current operand word */
1957 int bitoffset =
534a3d5c 1958 (vector_num_in * vectorbits) + (i * unitbits); /* # of bits from PKEcode */
43a6998b 1959
db6dac32
FCE
1960 /* last unit of V4_5 is only one bit wide */
1961 if(vl == 3 && vn == 3 && i == 3) /* PKE_UNPACK_V4_5 */
1962 unitbits = 1;
1963
9614fb3c
FCE
1964 /* confirm we're not reading more than we said we needed */
1965 if(vector_num_in * vectorbits >= num_operands * 32)
1966 {
1967 /* this condition may be triggered by illegal
1968 PKEcode / CYCLE combinations. */
1969 pke_code_error(me, pkecode);
1970 /* XXX: this case needs to be better understood,
1971 and detected at a better time. */
1972 return;
1973 }
1974
db6dac32 1975 /* fetch bitfield operand */
9614fb3c 1976 operand = pke_pcrel_operand_bits(me, bitoffset, unitbits, & source_addr);
db6dac32
FCE
1977
1978 /* selectively sign-extend; not for V4_5 1-bit value */
653c2590 1979 if(usn || unitbits == 1)
db6dac32 1980 unpacked_data[i] = operand;
653c2590
FCE
1981 else
1982 unpacked_data[i] = SEXT32(operand, unitbits-1);
43a6998b 1983 }
534a3d5c 1984
9614fb3c
FCE
1985 /* set remaining top words in vector */
1986 for(i=vn+1; i<4; i++)
1987 {
1988 if(vn == 0) /* S_{32,16,8}: copy lowest element */
1989 unpacked_data[i] = unpacked_data[0];
1990 else
1991 unpacked_data[i] = 0;
1992 }
fd909089 1993
534a3d5c
FCE
1994 /* consumed a vector from the PKE instruction stream */
1995 vector_num_in ++;
db6dac32 1996 } /* unpack word from instruction operand */
43a6998b 1997
9614fb3c
FCE
1998 /* process STMOD register for accumulation operations */
1999 switch(PKE_REG_MASK_GET(me, MODE, MDE))
2000 {
2001 case PKE_MODE_ADDROW: /* add row registers to output data */
b59e0b68 2002 case PKE_MODE_ACCROW: /* same .. later conditionally accumulate */
9614fb3c
FCE
2003 for(i=0; i<4; i++)
2004 /* exploit R0..R3 contiguity */
2005 unpacked_data[i] += me->regs[PKE_REG_R0 + i][0];
2006 break;
2007
9614fb3c
FCE
2008 case PKE_MODE_INPUT: /* pass data through */
2009 default: /* specified as undefined */
2010 ;
2011 }
2012
db6dac32 2013 /* compute replacement word */
43a6998b
FCE
2014 if(m) /* use mask register? */
2015 {
2016 /* compute index into mask register for this word */
b4d2f483 2017 int mask_index = PKE_LIMIT(vector_num_out % addrwl, 3);
43a6998b 2018
534a3d5c 2019 for(i=0; i<4; i++) /* loop over columns */
43a6998b
FCE
2020 {
2021 int mask_op = PKE_MASKREG_GET(me, mask_index, i);
2022 unsigned_4* masked_value = NULL;
43a6998b
FCE
2023
2024 switch(mask_op)
2025 {
2026 case PKE_MASKREG_INPUT:
9614fb3c 2027 masked_value = & unpacked_data[i];
b59e0b68
FCE
2028
2029 /* conditionally accumulate */
2030 if(PKE_REG_MASK_GET(me, MODE, MDE) == PKE_MODE_ACCROW)
2031 me->regs[PKE_REG_R0 + i][0] = unpacked_data[i];
2032
43a6998b
FCE
2033 break;
2034
2035 case PKE_MASKREG_ROW: /* exploit R0..R3 contiguity */
2036 masked_value = & me->regs[PKE_REG_R0 + i][0];
2037 break;
2038
2039 case PKE_MASKREG_COLUMN: /* exploit C0..C3 contiguity */
534a3d5c 2040 masked_value = & me->regs[PKE_REG_C0 + mask_index][0];
43a6998b
FCE
2041 break;
2042
2043 case PKE_MASKREG_NOTHING:
2044 /* "write inhibit" by re-copying old data */
2045 masked_value = & vu_old_data[i];
2046 break;
2047
2048 default:
2049 ASSERT(0);
2050 /* no other cases possible */
2051 }
2052
2053 /* copy masked value for column */
db6dac32 2054 vu_new_data[i] = *masked_value;
43a6998b 2055 } /* loop over columns */
db6dac32 2056 } /* mask */
43a6998b
FCE
2057 else
2058 {
2059 /* no mask - just copy over entire unpacked quadword */
2060 memcpy(vu_new_data, unpacked_data, sizeof(unpacked_data));
b59e0b68
FCE
2061
2062 /* conditionally store accumulated row results */
2063 if(PKE_REG_MASK_GET(me, MODE, MDE) == PKE_MODE_ACCROW)
2064 for(i=0; i<4; i++)
2065 me->regs[PKE_REG_R0 + i][0] = unpacked_data[i];
43a6998b 2066 }
43a6998b 2067
f0bb94cd
FCE
2068 /* write new VU data word at address; reverse words if needed */
2069 {
2070 unsigned_16 vu_new_badwords;
2071 * A4_16(& vu_new_badwords, 3) = vu_new_data[0];
2072 * A4_16(& vu_new_badwords, 2) = vu_new_data[1];
2073 * A4_16(& vu_new_badwords, 1) = vu_new_data[2];
2074 * A4_16(& vu_new_badwords, 0) = vu_new_data[3];
2075 ASSERT(sizeof(vu_new_badwords) == 16);
2076 PKE_MEM_WRITE(me, vu_addr,
2077 &vu_new_badwords, 16);
2078 }
2079
2080 /* write tracking address */
534a3d5c
FCE
2081 ASSERT(sizeof(unsigned_4) == 4);
2082 PKE_MEM_WRITE(me, vutrack_addr,
2083 & source_addr,
2084 4);
43a6998b
FCE
2085
2086 /* next vector please */
534a3d5c 2087 vector_num_out ++;
43a6998b 2088 } /* vector transfer loop */
db6dac32 2089 while(PKE_REG_MASK_GET(me, NUM, NUM) > 0);
43a6998b 2090
9614fb3c
FCE
2091 /* confirm we've written as many vectors as told */
2092 ASSERT(nummx == vector_num_out);
2093
43a6998b
FCE
2094 /* done */
2095 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
e2306992 2096 pke_pc_advance(me, 1 + num_operands);
43a6998b
FCE
2097 } /* PKE FIFO full enough */
2098 else
2099 {
2100 /* need to wait for another word */
2101 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_WAIT);
2102 /* retry this instruction next clock */
2103 }
2104}
2105
2106
2107void
2108pke_code_error(struct pke_device* me, unsigned_4 pkecode)
2109{
9614fb3c
FCE
2110 /* set ER1 flag in STAT register */
2111 PKE_REG_MASK_SET(me, STAT, ER1, 1);
2112
fd909089
FCE
2113 if(! PKE_REG_MASK_GET(me, ERR, ME1))
2114 {
9614fb3c 2115 pke_begin_interrupt_stall(me);
fd909089
FCE
2116 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL);
2117 }
2118 else
2119 {
2120 PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
2121 }
2122
43a6998b 2123 /* advance over faulty word */
43a6998b 2124 pke_pc_advance(me, 1);
fba9bfed 2125}
This page took 0.129351 seconds and 4 git commands to generate.