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