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