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