summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted/MachineSimulation821.c
blob: bbf0509c239a8e44510161b0c988c98bf07a4ba1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
#include "compiler/Scheduler.h"
#include "compiler/PCode.h"
#include "compiler/PCodeInfo.h"

// https://www.nxp.com/docs/en/user-guide/MPC821UM.pdf

typedef enum Stage {
    BranchUnit,
    Stage1,
    Stage2,
    LSU1,
    LSU2,
    CRUnit,
    NumStages,
    Stage7
} Stage;

static struct {
    // the instruction currently in this pipeline stage
    PCode *instr;

    // how many cycles are left for this instruction to finish
    int remaining;
} pipeline[NumStages];

enum {
    MaxEntries = 6
};

static struct {
    // how many entries remain unused in the queue
    unsigned int free;

    // how many entries are currently used in the queue
    unsigned int used;

    // the index of the next instruction that will be retired
    unsigned int nextToRetire;

    // the index of the next free slot that will be used when an instruction is dispatched
    unsigned int nextFreeSlot;

    // circular array of entries in the completion queue
    struct {
        PCode *instr;
        int completed;
    } entries[MaxEntries];
} completionbuffers;

static struct {
    // the initial stage for this instruction
    Stage stage;

    // the total amount of cycles required by this instruction
    char latency;

    // how long it takes to finish each stage
    char cycles[3];

    // does this instruction serialise?
    char serializes;
} instruction_timing[OPCODE_MAX] = {
    BranchUnit,  0,  0,  0,  0,  0,  // PC_B
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BC
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BCLR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BCCTR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BT
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BTLR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BTCTR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BF
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BFLR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BFCTR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BDNZ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BDNZT
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BDNZF
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BDZ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BDZT
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BDZF
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BLR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BCTR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BCTRL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_BLRL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_LBZ
    LSU1,  2,  1,  1,  0,  0,  // PC_LBZU
    LSU1,  2,  1,  1,  0,  0,  // PC_LBZX
    LSU1,  2,  1,  1,  0,  0,  // PC_LBZUX
    LSU1,  2,  1,  1,  0,  0,  // PC_LHZ
    LSU1,  2,  1,  1,  0,  0,  // PC_LHZU
    LSU1,  2,  1,  1,  0,  0,  // PC_LHZX
    LSU1,  2,  1,  1,  0,  0,  // PC_LHZUX
    LSU1,  2,  1,  1,  0,  0,  // PC_LHA
    LSU1,  2,  1,  1,  0,  0,  // PC_LHAU
    LSU1,  2,  1,  1,  0,  0,  // PC_LHAX
    LSU1,  2,  1,  1,  0,  0,  // PC_LHAUX
    LSU1,  2,  1,  1,  0,  0,  // PC_LHBRX
    LSU1,  2,  1,  1,  0,  0,  // PC_LWZ
    LSU1,  2,  1,  1,  0,  0,  // PC_LWZU
    LSU1,  2,  1,  1,  0,  0,  // PC_LWZX
    LSU1,  2,  1,  1,  0,  0,  // PC_LWZUX
    LSU1,  2,  1,  1,  0,  0,  // PC_LWBRX
    LSU1,  2,  1,  1,  0,  0,  // PC_LMW
    LSU1,  2,  1,  1,  0,  0,  // PC_STB
    LSU1,  2,  1,  1,  0,  0,  // PC_STBU
    LSU1,  2,  1,  1,  0,  0,  // PC_STBX
    LSU1,  2,  1,  1,  0,  0,  // PC_STBUX
    LSU1,  2,  1,  1,  0,  0,  // PC_STH
    LSU1,  2,  1,  1,  0,  0,  // PC_STHU
    LSU1,  2,  1,  1,  0,  0,  // PC_STHX
    LSU1,  2,  1,  1,  0,  0,  // PC_STHUX
    LSU1,  2,  1,  1,  0,  0,  // PC_STHBRX
    LSU1,  2,  1,  1,  0,  0,  // PC_STW
    LSU1,  2,  1,  1,  0,  0,  // PC_STWU
    LSU1,  2,  1,  1,  0,  0,  // PC_STWX
    LSU1,  2,  1,  1,  0,  0,  // PC_STWUX
    LSU1,  2,  1,  1,  0,  0,  // PC_STWBRX
    LSU1,  2,  1,  1,  0,  0,  // PC_STMW
    LSU1,  2,  1,  1,  0,  0,  // PC_DCBF
    LSU1,  2,  1,  1,  0,  0,  // PC_DCBST
    LSU1,  2,  1,  1,  0,  0,  // PC_DCBT
    LSU1,  2,  1,  1,  0,  0,  // PC_DCBTST
    LSU1,  2,  1,  1,  0,  0,  // PC_DCBZ
    LSU1,  2,  1,  1,  0,  0,  // PC_ADD
    Stage1,  1,  1,  0,  0,  0,  // PC_ADDC
    Stage1,  1,  1,  0,  0,  0,  // PC_ADDE
    Stage1,  1,  1,  0,  0,  0,  // PC_ADDI
    Stage1,  1,  1,  0,  0,  0,  // PC_ADDIC
    Stage1,  1,  1,  0,  0,  0,  // PC_ADDICR
    Stage1,  1,  1,  0,  0,  0,  // PC_ADDIS
    Stage1,  1,  1,  0,  0,  0,  // PC_ADDME
    Stage1,  1,  1,  0,  0,  0,  // PC_ADDZE
    Stage1,  1,  1,  0,  0,  0,  // PC_DIVW
    Stage1,  37, 37, 0,  0,  0,  // PC_DIVWU
    Stage1,  37, 37, 0,  0,  0,  // PC_MULHW
    Stage1,  5,  5,  0,  0,  0,  // PC_MULHWU
    Stage1,  5,  5,  0,  0,  0,  // PC_MULLI
    Stage1,  3,  3,  0,  0,  0,  // PC_MULLW
    Stage1,  5,  5,  0,  0,  0,  // PC_NEG
    Stage1,  1,  1,  0,  0,  0,  // PC_SUBF
    Stage1,  1,  1,  0,  0,  0,  // PC_SUBFC
    Stage1,  1,  1,  0,  0,  0,  // PC_SUBFE
    Stage1,  1,  1,  0,  0,  0,  // PC_SUBFIC
    Stage1,  1,  1,  0,  0,  0,  // PC_SUBFME
    Stage1,  1,  1,  0,  0,  0,  // PC_SUBFZE
    Stage1,  1,  1,  0,  0,  0,  // PC_CMPI
    Stage1,  3,  1,  0,  0,  0,  // PC_CMP
    Stage1,  3,  1,  0,  0,  0,  // PC_CMPLI
    Stage1,  3,  1,  0,  0,  0,  // PC_CMPL
    Stage1,  3,  1,  0,  0,  0,  // PC_ANDI
    Stage1,  1,  1,  0,  0,  0,  // PC_ANDIS
    Stage1,  1,  1,  0,  0,  0,  // PC_ORI
    Stage1,  1,  1,  0,  0,  0,  // PC_ORIS
    Stage1,  1,  1,  0,  0,  0,  // PC_XORI
    Stage1,  1,  1,  0,  0,  0,  // PC_XORIS
    Stage1,  1,  1,  0,  0,  0,  // PC_AND
    Stage1,  1,  1,  0,  0,  0,  // PC_OR
    Stage1,  1,  1,  0,  0,  0,  // PC_XOR
    Stage1,  1,  1,  0,  0,  0,  // PC_NAND
    Stage1,  1,  1,  0,  0,  0,  // PC_NOR
    Stage1,  1,  1,  0,  0,  0,  // PC_EQV
    Stage1,  1,  1,  0,  0,  0,  // PC_ANDC
    Stage1,  1,  1,  0,  0,  0,  // PC_ORC
    Stage1,  1,  1,  0,  0,  0,  // PC_EXTSB
    Stage1,  1,  1,  0,  0,  0,  // PC_EXTSH
    Stage1,  1,  1,  0,  0,  0,  // PC_CNTLZW
    Stage1,  1,  1,  0,  0,  0,  // PC_RLWINM
    Stage1,  1,  1,  0,  0,  0,  // PC_RLWNM
    Stage1,  1,  1,  0,  0,  0,  // PC_RLWIMI
    Stage1,  1,  1,  0,  0,  0,  // PC_SLW
    Stage1,  1,  1,  0,  0,  0,  // PC_SRW
    Stage1,  1,  1,  0,  0,  0,  // PC_SRAWI
    Stage1,  1,  1,  0,  0,  0,  // PC_SRAW
    Stage1,  1,  1,  0,  0,  0,  // PC_CRAND
    CRUnit,  1,  1,  0,  0,  0,  // PC_CRANDC
    CRUnit,  1,  1,  0,  0,  0,  // PC_CREQV
    CRUnit,  1,  1,  0,  0,  0,  // PC_CRNAND
    CRUnit,  1,  1,  0,  0,  0,  // PC_CRNOR
    CRUnit,  1,  1,  0,  0,  0,  // PC_CROR
    CRUnit,  1,  1,  0,  0,  0,  // PC_CRORC
    CRUnit,  1,  1,  0,  0,  0,  // PC_CRXOR
    CRUnit,  1,  1,  0,  0,  0,  // PC_MCRF
    CRUnit,  1,  1,  0,  0,  0,  // PC_MTXER
    Stage1,  1,  1,  0,  0,  0,  // PC_MTCTR
    BranchUnit,  2,  2,  0,  0,  0,  // PC_MTLR
    BranchUnit,  2,  2,  0,  0,  0,  // PC_MTCRF
    Stage1,  1,  1,  0,  0,  0,  // PC_MTMSR
    Stage1,  1,  1,  0,  0,  0,  // PC_MTSPR
    Stage1,  1,  1,  0,  0,  0,  // PC_MFMSR
    Stage1,  1,  1,  0,  0,  0,  // PC_MFSPR
    Stage1,  1,  1,  0,  0,  0,  // PC_MFXER
    Stage7,  3,  1,  1,  1,  0,  // PC_MFCTR
    Stage7,  3,  1,  1,  1,  0,  // PC_MFLR
    Stage1,  1,  1,  0,  0,  0,  // PC_MFCR
    Stage1,  1,  1,  0,  0,  0,  // PC_MFFS
    Stage1,  1,  1,  0,  0,  0,  // PC_MTFSF
    Stage1,  1,  1,  0,  0,  0,  // PC_EIEIO
    Stage1,  1,  1,  0,  0,  0,  // PC_ISYNC
    Stage1,  1,  1,  0,  0,  0,  // PC_SYNC
    Stage1,  1,  1,  0,  0,  0,  // PC_RFI
    Stage1,  1,  1,  0,  0,  0,  // PC_LI
    LSU1,  2,  1,  1,  0,  0,  // PC_LIS
    LSU1,  2,  1,  1,  0,  0,  // PC_MR
    LSU1,  2,  1,  1,  0,  0,  // PC_NOP
    LSU1,  2,  1,  1,  0,  0,  // PC_NOT
    LSU1,  2,  1,  1,  0,  0,  // PC_LFS
    LSU1,  2,  1,  1,  0,  0,  // PC_LFSU
    LSU1,  2,  1,  1,  0,  0,  // PC_LFSX
    LSU1,  2,  1,  1,  0,  0,  // PC_LFSUX
    LSU1,  2,  1,  1,  0,  0,  // PC_LFD
    LSU1,  2,  1,  1,  0,  0,  // PC_LFDU
    LSU1,  2,  1,  1,  0,  0,  // PC_LFDX
    LSU1,  2,  1,  1,  0,  0,  // PC_LFDUX
    LSU1,  2,  1,  1,  0,  0,  // PC_STFS
    LSU1,  2,  1,  1,  0,  0,  // PC_STFSU
    LSU1,  2,  1,  1,  0,  0,  // PC_STFSX
    LSU1,  2,  1,  1,  0,  0,  // PC_STFSUX
    Stage7,  3,  1,  1,  1,  0,  // PC_STFD
    Stage7,  3,  1,  1,  1,  0,  // PC_STFDU
    Stage7,  3,  1,  1,  1,  0,  // PC_STFDX
    Stage7,  3,  1,  1,  1,  0,  // PC_STFDUX
    Stage7,  3,  1,  1,  1,  0,  // PC_FMR
    Stage7,  3,  1,  1,  1,  0,  // PC_FABS
    Stage7,  3,  1,  1,  1,  0,  // PC_FNEG
    Stage7,  3,  1,  1,  1,  0,  // PC_FNABS
    Stage7,  4,  2,  1,  1,  0,  // PC_FADD
    Stage7,  3,  1,  1,  1,  0,  // PC_FADDS
    Stage7,  33, 33, 0,  0,  0,  // PC_FSUB
    Stage7,  18, 18, 0,  0,  0,  // PC_FSUBS
    Stage7,  4,  2,  1,  1,  0,  // PC_FMUL
    Stage7,  3,  1,  1,  1,  0,  // PC_FMULS
    Stage7,  4,  2,  1,  1,  0,  // PC_FDIV
    Stage7,  3,  1,  1,  1,  0,  // PC_FDIVS
    Stage7,  4,  2,  1,  1,  0,  // PC_FMADD
    Stage7,  3,  1,  1,  1,  0,  // PC_FMADDS
    Stage7,  4,  2,  1,  1,  0,  // PC_FMSUB
    Stage7,  3,  1,  1,  1,  0,  // PC_FMSUBS
    Stage7,  18, 18, 0,  0,  0,  // PC_FNMADD
    Stage7,  3,  1,  1,  1,  0,  // PC_FNMADDS
    Stage7,  3,  1,  1,  1,  0,  // PC_FNMSUB
    Stage7,  3,  1,  1,  1,  0,  // PC_FNMSUBS
    Stage7,  3,  1,  1,  1,  0,  // PC_FRES
    Stage7,  3,  1,  1,  1,  0,  // PC_FRSQRTE
    Stage7,  5,  1,  1,  1,  0,  // PC_FSEL
    Stage7,  5,  1,  1,  1,  0,  // PC_FRSP
    LSU1,  1,  0,  0,  0,  0,  // PC_FCTIW
    LSU1,  1,  0,  0,  0,  0,  // PC_FCTIWZ
    LSU1,  1,  0,  0,  0,  0,  // PC_FCMPU
    LSU1,  1,  0,  0,  0,  0,  // PC_FCMPO
    LSU1,  1,  0,  0,  0,  0,  // PC_LWARX
    LSU1,  1,  0,  0,  0,  0,  // PC_LSWI
    LSU1,  1,  0,  0,  0,  0,  // PC_LSWX
    Stage1,  1,  0,  0,  0,  0,  // PC_STFIWX
    Stage1,  1,  0,  0,  0,  0,  // PC_STSWI
    Stage1,  1,  0,  0,  0,  0,  // PC_STSWX
    Stage1,  1,  0,  0,  0,  0,  // PC_STWCX
    Stage1,  1,  0,  0,  0,  0,  // PC_ECIWX
    Stage1,  1,  0,  0,  0,  0,  // PC_ECOWX
    Stage1,  1,  0,  0,  0,  0,  // PC_DCBI
    Stage1,  1,  0,  0,  0,  0,  // PC_ICBI
    Stage1,  1,  0,  0,  0,  0,  // PC_MCRFS
    Stage1,  1,  0,  0,  0,  0,  // PC_MCRXR
    Stage1,  1,  0,  0,  0,  0,  // PC_MFTB
    Stage1,  1,  0,  0,  0,  0,  // PC_MFSR
    Stage1,  1,  0,  0,  0,  0,  // PC_MTSR
    Stage1,  1,  0,  0,  0,  0,  // PC_MFSRIN
    Stage1,  1,  0,  0,  0,  0,  // PC_MTSRIN
    Stage1,  1,  0,  0,  0,  0,  // PC_MTFSB0
    Stage1,  1,  0,  0,  0,  0,  // PC_MTFSB1
    Stage1,  1,  0,  0,  0,  0,  // PC_MTFSFI
    Stage1,  1,  0,  0,  0,  1,  // PC_SC
    Stage1,  1,  0,  0,  0,  1,  // PC_FSQRT
    Stage1,  1,  0,  0,  0,  0,  // PC_FSQRTS
    Stage1,  1,  0,  0,  0,  0,  // PC_TLBIA
    Stage1,  1,  0,  0,  0,  0,  // PC_TLBIE
    Stage1,  1,  0,  0,  0,  0,  // PC_TLBLD
    Stage1,  1,  0,  0,  0,  0,  // PC_TLBLI
    Stage1,  1,  0,  0,  0,  0,  // PC_TLBSYNC
    Stage1,  1,  0,  0,  0,  0,  // PC_TW
    Stage1,  1,  0,  0,  0,  1,  // PC_TRAP
    Stage1,  1,  0,  0,  0,  1,  // PC_TWI
    Stage1,  1,  0,  0,  0,  1,  // PC_OPWORD
    Stage1,  1,  0,  0,  0,  1,  // PC_MFROM
    Stage1,  1,  0,  0,  0,  0,  // PC_DSA
    Stage1,  1,  0,  0,  0,  0,  // PC_ESA
    Stage1,  1,  0,  0,  0,  0,  // PC_DCCCI
    Stage1,  0,  0,  0,  0,  0,  // PC_DCREAD
    Stage1,  0,  0,  0,  0,  0,  // PC_ICBT
    Stage1,  0,  0,  0,  0,  0,  // PC_ICCCI
    Stage1,  0,  0,  0,  0,  0,  // PC_ICREAD
    Stage1,  0,  0,  0,  0,  0,  // PC_RFCI
    Stage1,  0,  0,  0,  0,  0,  // PC_TLBRE
    Stage1,  0,  0,  0,  0,  0,  // PC_TLBSX
    Stage1,  0,  0,  0,  0,  0,  // PC_TLBWE
    Stage1,  0,  0,  0,  0,  0,  // PC_WRTEE
    Stage1,  0,  0,  0,  0,  0,  // PC_WRTEEI
    Stage1,  0,  0,  0,  0,  0,  // PC_MFDCR
    Stage1,  0,  0,  0,  0,  0,  // PC_MTDCR
    Stage1,  0,  0,  0,  0,  0,  // PC_DCBA
    Stage1,  0,  0,  0,  0,  0,  // PC_DSS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_DSSALL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_DST
    BranchUnit,  0,  0,  0,  0,  0,  // PC_DSTT
    BranchUnit,  0,  0,  0,  0,  0,  // PC_DSTST
    BranchUnit,  0,  0,  0,  0,  0,  // PC_DSTSTT
    BranchUnit,  0,  0,  0,  0,  0,  // PC_LVEBX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_LVEHX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_LVEWX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_LVSL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_LVSR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_LVX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_LVXL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_STVEBX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_STVEHX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_STVEWX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_STVX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_STVXL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_MFVSCR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_MTVSCR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDCUW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDSBS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDSHS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDSWS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDUBM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDUBS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDUHM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDUHS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDUWM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VADDUWS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VAND
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VANDC
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VAVGSB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VAVGSH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VAVGSW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VAVGUB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VAVGUH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VAVGUW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCFSX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCFUX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPBFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPEQFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPEQUB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPEQUH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPEQUW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPGEFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPGTFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPGTSB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPGTSH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPGTSW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPGTUB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPGTUH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCMPGTUW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCTSXS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VCTUXS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VEXPTEFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VLOGEFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMAXFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMAXSB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMAXSH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMAXSW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMAXUB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMAXUH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMAXUW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMINFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMINSB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMINSH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMINSW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMINUB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMINUH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMINUW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMRGHB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMRGHH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMRGHW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMRGLB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMRGLH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMRGLW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMULESB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMULESH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMULEUB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMULEUH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMULOSB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMULOSH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMULOUB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMULOUH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VNOR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VOR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPKPX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPKSHSS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPKSHUS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPKSWSS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPKSWUS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPKUHUM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPKUHUS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPKUWUM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPKUWUS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VREFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VRFIM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VRFIN
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VRFIP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VRFIZ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VRLB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VRLH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VRLW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VRSQRTEFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSLB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSLH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSLO
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSLW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSPLTB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSPLTH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSPLTW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSPLTISB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSPLTISH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSPLTISW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSRAB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSRAH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSRAW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSRB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSRH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSRO
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSRW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBCUW
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBSBS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBSHS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBSWS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBUBM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBUBS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBUHM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBUHS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBUWM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUBUWS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUMSWS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUM2SWS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUM4SBS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUM4SHS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSUM4UBS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VUPKHPX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VUPKHSB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VUPKHSH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VUPKLPX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VUPKLSB
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VUPKLSH
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VXOR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMADDFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMHADDSHS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMHRADDSHS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMLADDUHM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMSUMMBM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMSUMSHM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMSUMSHS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMSUMUBM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMSUMUHM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMSUMUHS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VNMSUBFP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VPERM
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSEL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VSLDOI
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_VMRP
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SLE
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SLEQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SLIQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SLLIQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SLLQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SLQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SRAIQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SRAQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SRE
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SREA
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SREQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SRIQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SRLIQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SRLQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_SRQ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_MASKG
    BranchUnit,  0,  0,  0,  0,  0,  // PC_MASKIR
    BranchUnit,  0,  0,  0,  0,  0,  // PC_LSCBX
    BranchUnit,  0,  0,  0,  0,  0,  // PC_DIV
    BranchUnit,  0,  0,  0,  0,  0,  // PC_DIVS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_DOZ
    BranchUnit,  0,  0,  0,  0,  0,  // PC_MUL
    BranchUnit,  0,  0,  0,  0,  0,  // PC_NABS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_ABS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_CLCS
    BranchUnit,  0,  0,  0,  0,  0,  // PC_DOZI
    BranchUnit,  0,  0,  0,  0,  0,  // PC_RLMI
    BranchUnit,  0,  0,  0,  0,  0,  // PC_RRIB
};

static void advance(int firstStage, int oldStage, int newStage) {
    PCode *instr = pipeline[oldStage].instr;
    int cycles = instruction_timing[instr->op].cycles[newStage - firstStage];
    pipeline[newStage].instr = instr;
    pipeline[newStage].remaining = cycles;
    pipeline[oldStage].instr = NULL;
}

static void assign_completion_buffer(PCode *instr) {
    completionbuffers.used++;
    completionbuffers.free--;
    completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr;
    completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0;
    completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries;
}

static void complete_instruction(int stage) {
    PCode *instr = pipeline[stage].instr;
    int buf = 0;
    while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr)
        buf++;

    completionbuffers.entries[buf].completed = 1;
    pipeline[stage].instr = NULL;
}

static void retire_instruction(void) {
    completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL;
    completionbuffers.used--;
    completionbuffers.free++;
    completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries;
}

static int latency(PCode *instr) {
    int cycles = instruction_timing[instr->op].latency;
    if (PCODE_FLAG_SET_F(instr) & fRecordBit)
        cycles += 2;
    if (instr->op == PC_LMW || instr->op == PC_STMW)
        cycles += instr->argCount - 2;
    return cycles;
}

static void initialize(void) {
    int stage;
    int i;

    for (stage = 0; stage < NumStages; stage++)
        pipeline[stage].instr = NULL;

    completionbuffers.free = MaxEntries;
    completionbuffers.used = 0;
    completionbuffers.nextToRetire = 0;
    completionbuffers.nextFreeSlot = 0;
    for (i = 0; i < MaxEntries; i++)
        completionbuffers.entries[i].instr = NULL;
}

static int can_issue(PCode *instr) {
    int stage;

    if (completionbuffers.free == 0)
        return 0;

    stage = instruction_timing[instr->op].stage;
    if (pipeline[stage].instr)
        return 0;

    if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite))
        return 0;

    return 1;
}

static void issue(PCode *instr) {
    int stage = instruction_timing[instr->op].stage;
    int cycles = instruction_timing[instr->op].cycles[0];
    assign_completion_buffer(instr);
    pipeline[stage].instr = instr;
    pipeline[stage].remaining = cycles;
}

static void advance_clock(void) {
    int stage;

    for (stage = 0; stage < NumStages; stage++) {
        if (pipeline[stage].instr && pipeline[stage].remaining)
            --pipeline[stage].remaining;
    }

    if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) {
        retire_instruction();
        if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) {
            retire_instruction();
        }
    }

    if (pipeline[Stage1].instr && pipeline[Stage1].remaining == 0)
        complete_instruction(Stage1);
    if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0)
        complete_instruction(LSU2);
    if (pipeline[BranchUnit].instr && pipeline[BranchUnit].remaining == 0)
        complete_instruction(BranchUnit);

    if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr)
        advance(LSU1, LSU1, LSU2);
}

static int serializes(PCode *instr) {
    return instruction_timing[instr->op].serializes;
}

MachineInfo machine821 = {
    1,
    0,
    0,
    &latency,
    &initialize,
    &can_issue,
    &issue,
    &advance_clock,
    &serializes,
    &default_uses_vpermute_unit
};