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