OpenCores
URL https://opencores.org/ocsvn/or2k/or2k/trunk

Subversion Repositories or2k

[/] [or2k/] [trunk/] [analysis-bin/] [insnanalysis/] [or1k-32-insn.c] - Blame information for rev 26

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 17 julius
/*
2
  Or1K instruction set-specific decoding and analysis functions.
3
 
4
  Julius Baxter, julius.baxter@orsoc.se
5
 
6
*/
7
 
8
 
9 16 julius
#include "stdio.h"
10
#include "stdint.h"
11
#include "stdlib.h"
12
#include "string.h"
13 20 julius
#include "assert.h"
14 16 julius
#include "or1k-32-insn.h"
15
 
16 22 julius
// Define the appropriate instruction type, and instruction_properties type
17
// These should also be defined in insnanalysis.h
18 16 julius
typedef uint32_t instruction;
19
typedef struct or1k_32_instruction_properties instruction_properties ;
20
 
21
#include "insn-lists.h"
22
 
23 19 julius
// Variable to keep track of unique instructions we have
24
int num_setup_insns;
25
int num_seen_insns;
26
 
27
struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS];
28
 
29
// Keep enough instructions required to do the maximum n-tuple set
30
// analysis.
31
int or1k_32_recent_insns[OR1K_MAX_GROUPINGS_ANALYSIS];
32
 
33 22 julius
// Function to take the raw binary instruction, and configure the insn_props
34
// struct with the appropriate settings for that instruction (string, attributes
35
// etc.)
36
// TODO: vector instructions aren't picked up - but compiler never generates
37
// them, so not a big issue.
38 16 julius
int or1k_32_analyse_insn(uint32_t insn,
39
                         struct or1k_32_instruction_properties  * insn_props)
40
{
41
 
42
  switch(insn_or1k_opcode(insn))
43
    {
44
    case 0x00:
45
      insn_props->insn_string="l.j";
46 18 julius
      insn_props->insn_index=0;
47 16 julius
      insn_props->has_jumptarg = 1;
48
      break;
49
 
50
    case 0x01:
51
      insn_props->insn_string="l.jal";
52 18 julius
      insn_props->insn_index=1;
53 16 julius
      insn_props->has_jumptarg = 1;
54
      break;
55
 
56
     case 0x03:
57
      insn_props->insn_string="l.bnf";
58 18 julius
      insn_props->insn_index=2;
59 16 julius
      insn_props->has_branchtarg = 1;
60
      break;
61
 
62
    case 0x04:
63
      insn_props->insn_string="l.bf";
64 18 julius
      insn_props->insn_index=3;
65 16 julius
      insn_props->has_branchtarg = 1;
66
      break;
67
 
68
    case 0x05:
69
      insn_props->insn_string="l.nop";
70 18 julius
      insn_props->insn_index=4;
71 16 julius
      break;
72
 
73
    case 0x06:
74
      if((insn_or1k_opcode_0x06_get_id(insn)))
75 18 julius
        {
76
          insn_props->insn_string="l.macrc";
77
          insn_props->insn_index=5;
78
        }
79 16 julius
      else
80
        {
81
          insn_props->insn_string="l.movhi";
82 18 julius
          insn_props->insn_index=6;
83 16 julius
          insn_props->has_rD = 1;
84
          insn_props->has_imm = 1;
85
        }
86
 
87
      break;
88
 
89
    case 0x08:
90
 
91
      switch(insn_or1k_opcode_0x08_get_id(insn))
92
        {
93
        case 0x0:
94
          insn_props->insn_string="l.sys";
95 18 julius
          insn_props->insn_index=7;
96 20 julius
          insn_props->has_imm = 1;
97 16 julius
          break;
98
        case 0x2:
99
          insn_props->insn_string="l.trap";
100 18 julius
          insn_props->insn_index=8;
101 16 julius
          break;
102
        case 0x4:
103
          insn_props->insn_string="l.msync";
104 18 julius
          insn_props->insn_index=9;
105 16 julius
          break;
106
        case 0x5:
107
          insn_props->insn_string="l.psync";
108 18 julius
          insn_props->insn_index=10;
109 16 julius
          break;
110
        case 0x6:
111
          insn_props->insn_string="l.csync";
112 18 julius
          insn_props->insn_index=11;
113 16 julius
          break;
114
        default:
115
          printf("Unknown id (0x%x) in opcode 0x8",
116
                 insn_or1k_opcode_0x08_get_id(insn) );
117
          return 1;
118
          break;
119
        }
120
      break;
121
 
122
    case 0x09:
123
      insn_props->insn_string="l.rfe";
124 18 julius
      insn_props->insn_index=12;
125 16 julius
      break;
126
 
127
    case 0x0a:
128
      switch(insn_or1k_opcode_0x0a_get_op_hi(insn))
129
        {
130
        case 0x1:
131
          switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
132
            {
133
            case 0x0:
134
              break;
135
            case 0x1:
136
              break;
137
            case 0x2:
138
              break;
139
            case 0x3:
140
              break;
141
            case 0x4:
142
              break;
143
            case 0x5:
144
              break;
145
            case 0x6:
146
              break;
147
            case 0x7:
148
              break;
149
            case 0x8:
150
              break;
151
            case 0x9:
152
              break;
153
            case 0xa:
154
              break;
155
            case 0xb:
156
              break;
157
            default:
158
              printf("Unknown lv.all_xx insn");
159 17 julius
              return 1;
160 16 julius
            }
161
        case 0x2:
162
          switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
163
            {
164
            case 0x0:
165
              break;
166
            case 0x1:
167
              break;
168
            case 0x2:
169
              break;
170
            case 0x3:
171
              break;
172
            case 0x4:
173
              break;
174
            case 0x5:
175
              break;
176
            case 0x6:
177
              break;
178
            case 0x7:
179
              break;
180
            case 0x8:
181
              break;
182
            case 0x9:
183
              break;
184
            case 0xa:
185
              break;
186
            case 0xb:
187
              break;
188
            default:
189
              printf("Unknown lv.any_xx insn");
190 17 julius
              return 1;
191 16 julius
            }
192
          break;
193
        case 0x3:
194
          switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
195
            {
196
            case 0x0:
197
              break;
198
            case 0x1:
199
              break;
200
            case 0x2:
201
              break;
202
            case 0x3:
203
              break;
204
            case 0x4:
205
              break;
206
            case 0x5:
207
              break;
208
            case 0x6:
209
              break;
210
            case 0x7:
211
              break;
212
            case 0x8:
213
              break;
214
            case 0x9:
215
              break;
216
            case 0xa:
217
              break;
218
            default:
219
              printf("Unknown lv.add/and/avg_xx insn");
220 17 julius
              return 1;
221 16 julius
            }
222
          break;
223
        case 0x4:
224
          switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
225
            {
226
            case 0x0:
227
              break;
228
            case 0x1:
229
              break;
230
            case 0x2:
231
              break;
232
            case 0x3:
233
              break;
234
            case 0x4:
235
              break;
236
            case 0x5:
237
              break;
238
            case 0x6:
239
              break;
240
            case 0x7:
241
              break;
242
            case 0x8:
243
              break;
244
            case 0x9:
245
              break;
246
            case 0xa:
247
              break;
248
            case 0xb:
249
              break;
250
            default:
251
              printf("Unknown lv.cmp_xx insn");
252 17 julius
              return 1;
253 16 julius
            }
254
          break;
255
        case 0x5:
256
          switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
257
            {
258
            case 0x4:
259
              break;
260
            case 0x5:
261
              break;
262
            case 0x6:
263
              break;
264
            case 0x7:
265
              break;
266
            case 0x8:
267
              break;
268
            case 0x9:
269
              break;
270
            case 0xa:
271
              break;
272
            case 0xb:
273
              break;
274
            case 0xc:
275
              break;
276
            case 0xd:
277
              break;
278
            case 0xe:
279
              break;
280
            case 0xf:
281
              break;
282
            default:
283
              printf("Unknown lv.alu_xx insn");
284 17 julius
              return 1;
285 16 julius
            }
286
          break;
287
        case 0x6:
288
          switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
289
            {
290
            case 0x0:
291
              break;
292
            case 0x1:
293
              break;
294
            case 0x2:
295
              break;
296
            case 0x3:
297
              break;
298
            case 0x4:
299
              break;
300
            case 0x5:
301
              break;
302
            case 0x6:
303
              break;
304
            case 0x7:
305
              break;
306
            case 0x8:
307
              break;
308
            case 0x9:
309
              break;
310
            case 0xa:
311
              break;
312
            case 0xb:
313
              break;
314
            case 0xc:
315
              break;
316
            case 0xd:
317
              break;
318
            case 0xe:
319
              break;
320
            case 0xf:
321
              break;
322
            default:
323
              printf("Unknown lv.pack_xx insn");
324 17 julius
              return 1;
325 16 julius
            }
326
          break;
327
        case 0x7:
328
          switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
329
            {
330
            case 0x0:
331
              break;
332
            case 0x1:
333
              break;
334
            case 0x2:
335
              break;
336
            case 0x3:
337
              break;
338
            case 0x4:
339
              break;
340
            case 0x5:
341
              break;
342
            case 0x6:
343
              break;
344
            case 0x7:
345
              break;
346
            case 0x8:
347
              break;
348
            case 0x9:
349
              break;
350
            case 0xa:
351
              break;
352
            case 0xb:
353
              break;
354
            default:
355
              printf("Unknown lv.sub/unpack/xor_xx insn");
356 17 julius
              return 1;
357 16 julius
            }
358
          break;
359
        case 0xc:
360
          break;
361
        case 0xd:
362
          break;
363
        case 0xe:
364
          break;
365
        case 0xf:
366
          break;
367
        default:
368
          printf("Unknown lv.xxx insn hi op");
369 17 julius
          return 1;
370 16 julius
          break;
371
        }
372
      break;
373
 
374
    case 0x11:
375
      insn_props->insn_string="l.jr";
376 18 julius
      insn_props->insn_index=13;
377 16 julius
      insn_props->has_rB = 1;
378
      break;
379
 
380
    case 0x12:
381
      insn_props->insn_string="l.jalr";
382 18 julius
      insn_props->insn_index=14;
383 16 julius
      insn_props->has_rB = 1;
384
      break;
385
 
386
    case 0x13:
387
      insn_props->insn_string="l.maci";
388 18 julius
      insn_props->insn_index=15;
389 16 julius
      break;
390
 
391
    case 0x1c:
392
      insn_props->insn_string="l.cust1";
393 18 julius
      insn_props->insn_index=16;
394 16 julius
      break;
395
 
396
    case 0x1d:
397
      insn_props->insn_string="l.cust2";
398 18 julius
      insn_props->insn_index=17;
399 16 julius
      break;
400
 
401
    case 0x1e:
402
      insn_props->insn_string="l.cust3";
403 18 julius
      insn_props->insn_index=18;
404 16 julius
      break;
405
 
406
    case 0x1f:
407
      insn_props->insn_string="l.cust4";
408 18 julius
      insn_props->insn_index=19;
409 16 julius
      break;
410
 
411
    case 0x20:
412
      insn_props->insn_string="l.ld";
413 18 julius
      insn_props->insn_index=20;
414 16 julius
      insn_props->has_rD = 1;
415
      insn_props->has_rA = 1;
416
      insn_props->has_imm = 1;
417
      break;
418
 
419
    case 0x21:
420
      insn_props->insn_string="l.lwz";
421 18 julius
      insn_props->insn_index=21;
422 16 julius
      insn_props->has_rD = 1;
423
      insn_props->has_rA = 1;
424
      insn_props->has_imm = 1;
425
      break;
426
 
427
    case 0x22:
428
      insn_props->insn_string="l.lws";
429 18 julius
      insn_props->insn_index=22;
430 16 julius
      insn_props->has_rD = 1;
431
      insn_props->has_rA = 1;
432
      insn_props->has_imm = 1;
433
      break;
434
 
435
    case 0x23:
436
      insn_props->insn_string="l.lbz";
437 18 julius
      insn_props->insn_index=23;
438 16 julius
      insn_props->has_rD = 1;
439
      insn_props->has_rA = 1;
440
      insn_props->has_imm = 1;
441
      break;
442
 
443
    case 0x24:
444
      insn_props->insn_string="l.lbs";
445 18 julius
      insn_props->insn_index=24;
446 16 julius
      insn_props->has_rD = 1;
447
      insn_props->has_rA = 1;
448
      insn_props->has_imm = 1;
449
      break;
450
 
451
    case 0x25:
452
      insn_props->insn_string="l.lhz";
453 18 julius
      insn_props->insn_index=25;
454 16 julius
      insn_props->has_rD = 1;
455
      insn_props->has_rA = 1;
456
      insn_props->has_imm = 1;
457
      break;
458
 
459
    case 0x26:
460
      insn_props->insn_string="l.lhs";
461 18 julius
      insn_props->insn_index=26;
462 16 julius
      insn_props->has_rD = 1;
463
      insn_props->has_rA = 1;
464
      insn_props->has_imm = 1;
465
      break;
466
 
467
 
468
    case 0x27:
469
      insn_props->insn_string="l.addi";
470 18 julius
      insn_props->insn_index=27;
471 16 julius
      insn_props->has_rD = 1;
472
      insn_props->has_rA = 1;
473
      insn_props->has_imm = 1;
474
      break;
475
 
476
    case 0x28:
477
      insn_props->insn_string="l.addic";
478 18 julius
      insn_props->insn_index=28;
479 16 julius
      insn_props->has_rD = 1;
480
      insn_props->has_rA = 1;
481
      insn_props->has_imm = 1;
482
      break;
483
 
484
    case 0x29:
485
      insn_props->insn_string="l.andi";
486 18 julius
      insn_props->insn_index=29;
487 16 julius
      insn_props->has_rD = 1;
488
      insn_props->has_rA = 1;
489
      insn_props->has_imm = 1;
490
      break;
491
 
492
    case 0x2a:
493
      insn_props->insn_string="l.ori";
494 18 julius
      insn_props->insn_index=30;
495 16 julius
      insn_props->has_rD = 1;
496
      insn_props->has_rA = 1;
497
      insn_props->has_imm = 1;
498
      break;
499
 
500
    case 0x2b:
501
      insn_props->insn_string="l.xori";
502 18 julius
      insn_props->insn_index=31;
503 16 julius
      insn_props->has_rD = 1;
504
      insn_props->has_rA = 1;
505
      insn_props->has_imm = 1;
506
      break;
507
 
508
    case 0x2c:
509
      insn_props->insn_string="l.muli";
510 18 julius
      insn_props->insn_index=32;
511 16 julius
      insn_props->has_rD = 1;
512
      insn_props->has_rA = 1;
513
      insn_props->has_imm = 1;
514
      break;
515
 
516
    case 0x2d:
517
      insn_props->insn_string="l.mfspr";
518 18 julius
      insn_props->insn_index=33;
519 16 julius
      insn_props->has_rD = 1;
520
      insn_props->has_rA = 1;
521
      insn_props->has_imm = 1;
522
      break;
523
 
524
    case 0x2e:
525
      switch(insn_or1k_opcode_0x2e_get_op(insn))
526
        {
527
        case 0x0:
528
          insn_props->insn_string="l.slli";
529 18 julius
          insn_props->insn_index=34;
530 16 julius
          break;
531
        case 0x1:
532
          insn_props->insn_string="l.srli";
533 18 julius
          insn_props->insn_index=35;
534 16 julius
          break;
535
        case 0x2:
536
          insn_props->insn_string="l.srai";
537 18 julius
          insn_props->insn_index=36;
538 16 julius
          break;
539
        case 0x3:
540
          insn_props->insn_string="l.rori";
541 18 julius
          insn_props->insn_index=37;
542 16 julius
          break;
543
        default:
544
          printf("Unknown shift op (0x%x)",
545
                 insn_or1k_opcode_0x2e_get_op(insn));
546 17 julius
          return 1;
547 16 julius
          break;
548
        }
549
      break;
550
 
551
    case 0x2f:
552
      switch(insn_or1k_opcode_0x2f_get_op(insn))
553
        {
554
        case 0x0:
555
          insn_props->insn_string="l.sfeqi";
556 18 julius
          insn_props->insn_index=38;
557 16 julius
          break;
558
        case 0x1:
559
          insn_props->insn_string="l.sfnei";
560 18 julius
          insn_props->insn_index=39;
561 16 julius
          break;
562
        case 0x2:
563
          insn_props->insn_string="l.sfgtui";
564 18 julius
          insn_props->insn_index=40;
565 16 julius
          break;
566
        case 0x3:
567
          insn_props->insn_string="l.sfgeui";
568 18 julius
          insn_props->insn_index=41;
569 16 julius
          break;
570
        case 0x4:
571
          insn_props->insn_string="l.sfltui";
572 18 julius
          insn_props->insn_index=42;
573 16 julius
          break;
574
        case 0x5:
575
          insn_props->insn_string="l.sfleui";
576 18 julius
          insn_props->insn_index=43;
577 16 julius
          break;
578
        case 0xa:
579
          insn_props->insn_string="l.sfgtsi";
580 18 julius
          insn_props->insn_index=44;
581 16 julius
          break;
582
        case 0xb:
583
          insn_props->insn_string="l.sfgesi";
584 18 julius
          insn_props->insn_index=45;
585 16 julius
          break;
586
        case 0xc:
587
          insn_props->insn_string="l.sfltsi";
588 18 julius
          insn_props->insn_index=46;
589 16 julius
          break;
590
        case 0xd:
591
          insn_props->insn_string="l.sflesi";
592 18 julius
          insn_props->insn_index=47;
593 16 julius
          break;
594
 
595
        default:
596
          printf("Unknown set flag op (0x%x)",
597
                 insn_or1k_opcode_0x2f_get_op(insn));
598 17 julius
          return 1;
599 16 julius
          break;
600
        }
601
      insn_props->has_rA = 1;
602
      insn_props->has_imm = 1;
603
      break;
604
 
605
 
606
    case 0x30:
607
      insn_props->insn_string="l.mtspr";
608 18 julius
      insn_props->insn_index=48;
609 16 julius
      break;
610
 
611
    case 0x31:
612
      switch (insn_or1k_opcode_0x31_get_op(insn))
613
        {
614
        case 0x1:
615
          insn_props->insn_string="l.mac";
616 18 julius
          insn_props->insn_index=49;
617 16 julius
          break;
618
        case 0x2:
619
          insn_props->insn_string="l.msb";
620 18 julius
          insn_props->insn_index=50;
621 16 julius
          break;
622
        default:
623
          printf("Unknown mac op (0x%x)",
624
                 insn_or1k_opcode_0x31_get_op(insn));
625 17 julius
          return 1;
626 16 julius
        }
627
      break;
628
 
629
    case 0x32:
630
      switch(insn_or1k_opcode_0x32_get_op_hi(insn))
631
        {
632
        case 0x0:
633
          switch(insn_or1k_opcode_0x32_get_op_lo(insn))
634
            {
635
            case 0x0:
636
              insn_props->insn_string="lf.add.s";
637 18 julius
              insn_props->insn_index=51;
638 16 julius
              break;
639
            case 0x1:
640
              insn_props->insn_string="lf.sub.s";
641 18 julius
              insn_props->insn_index=52;
642 16 julius
              break;
643
            case 0x2:
644
              insn_props->insn_string="lf.mul.s";
645 18 julius
              insn_props->insn_index=53;
646 16 julius
              break;
647
            case 0x3:
648
              insn_props->insn_string="lf.div.s";
649 18 julius
              insn_props->insn_index=54;
650 16 julius
              break;
651
            case 0x4:
652
              insn_props->insn_string="lf.itof.s";
653 18 julius
              insn_props->insn_index=55;
654 16 julius
              break;
655
            case 0x5:
656
              insn_props->insn_string="lf.ftoi.s";
657 18 julius
              insn_props->insn_index=56;
658 16 julius
              break;
659
            case 0x6:
660
              insn_props->insn_string="lf.rem.s";
661 18 julius
              insn_props->insn_index=57;
662 16 julius
              break;
663
            case 0x7:
664
              insn_props->insn_string="lf.madd.s";
665 18 julius
              insn_props->insn_index=58;
666 16 julius
              break;
667
            case 0x8:
668
              insn_props->insn_string="lf.sfeq.s";
669 18 julius
              insn_props->insn_index=59;
670 16 julius
              break;
671
            case 0x9:
672
              insn_props->insn_string="lf.sfne.s";
673 18 julius
              insn_props->insn_index=60;
674 16 julius
              break;
675
            case 0xa:
676
              insn_props->insn_string="lf.sfgt.s";
677 18 julius
              insn_props->insn_index=61;
678 16 julius
              break;
679
            case 0xb:
680
              insn_props->insn_string="lf.sfge.s";
681 18 julius
              insn_props->insn_index=62;
682 16 julius
              break;
683
            case 0xc:
684
              insn_props->insn_string="lf.sflt.s";
685 18 julius
              insn_props->insn_index=63;
686 16 julius
              break;
687
            case 0xd:
688
              insn_props->insn_string="lf.sfle.s";
689 18 julius
              insn_props->insn_index=64;
690 16 julius
              break;
691
            default:
692
              printf("Unknown lf.xxx.s op (0x%x)",
693
                     insn_or1k_opcode_0x32_get_op_lo(insn));
694
              break;
695
            }
696
          break;
697
 
698
        case 0x1:
699
          switch(insn_or1k_opcode_0x32_get_op_lo(insn))
700
            {
701
            case 0x0:
702
              insn_props->insn_string="lf.add.d";
703 18 julius
              insn_props->insn_index=65;
704 16 julius
              break;
705
            case 0x1:
706
              insn_props->insn_string="lf.sub.d";
707 18 julius
              insn_props->insn_index=66;
708 16 julius
              break;
709
            case 0x2:
710
              insn_props->insn_string="lf.mul.d";
711 18 julius
              insn_props->insn_index=67;
712 16 julius
              break;
713
            case 0x3:
714
              insn_props->insn_string="lf.div.d";
715 18 julius
              insn_props->insn_index=68;
716 16 julius
              break;
717
            case 0x4:
718
              insn_props->insn_string="lf.itof.d";
719 18 julius
              insn_props->insn_index=69;
720 16 julius
              break;
721
            case 0x5:
722
              insn_props->insn_string="lf.ftoi.d";
723 18 julius
              insn_props->insn_index=70;
724 16 julius
              break;
725
            case 0x6:
726
              insn_props->insn_string="lf.rem.d";
727 18 julius
              insn_props->insn_index=71;
728 16 julius
              break;
729
            case 0x7:
730
              insn_props->insn_string="lf.madd.d";
731 18 julius
              insn_props->insn_index=72;
732 16 julius
              break;
733
            case 0x8:
734
              insn_props->insn_string="lf.sfeq.d";
735 18 julius
              insn_props->insn_index=73;
736 16 julius
              break;
737
            case 0x9:
738
              insn_props->insn_string="lf.sfne.d";
739 18 julius
              insn_props->insn_index=74;
740 16 julius
              break;
741
            case 0xa:
742
              insn_props->insn_string="lf.sfgt.d";
743 18 julius
              insn_props->insn_index=75;
744 16 julius
              break;
745
            case 0xb:
746
              insn_props->insn_string="lf.sfge.d";
747 18 julius
              insn_props->insn_index=76;
748 16 julius
              break;
749
            case 0xc:
750
              insn_props->insn_string="lf.sflt.d";
751 18 julius
              insn_props->insn_index=77;
752 16 julius
              break;
753
            case 0xd:
754
              insn_props->insn_string="lf.sfle.d";
755 18 julius
              insn_props->insn_index=78;
756 16 julius
              break;
757
            default:
758
              printf("Unknown lf.xxx.d op (0x%x)",
759
                     insn_or1k_opcode_0x32_get_op_lo(insn));
760
              break;
761
            }
762
          break;
763
 
764
        case 0xd:
765
          insn_props->insn_string="lf.cust1.s";
766 18 julius
          insn_props->insn_index=79;
767 16 julius
          break;
768
 
769
        case 0xe:
770
          insn_props->insn_string="lf.cust1.d";
771 18 julius
          insn_props->insn_index=80;
772 16 julius
          break;
773
 
774
        default:
775
          printf("Unknown lf.xxx opcode hi (0x%x)",
776
                 insn_or1k_opcode_0x32_get_op_hi(insn));
777 17 julius
          return 1;
778 16 julius
          break;
779
        }
780
      break;
781
 
782
    case 0x34:
783
      insn_props->insn_string="l.sd";
784 18 julius
      insn_props->insn_index=81;
785 16 julius
      break;
786
 
787
    case 0x35:
788
      insn_props->insn_string="l.sw";
789 20 julius
      insn_props->has_split_imm = 1;
790 18 julius
      insn_props->insn_index=82;
791 16 julius
      break;
792
 
793
    case 0x36:
794
      insn_props->insn_string="l.sb";
795 20 julius
      insn_props->has_split_imm = 1;
796 18 julius
      insn_props->insn_index=83;
797 16 julius
      break;
798
 
799
    case 0x37:
800
      insn_props->insn_string="l.sh";
801 20 julius
      insn_props->has_split_imm = 1;
802 18 julius
      insn_props->insn_index=84;
803 16 julius
      break;
804
 
805
    case 0x38:
806 17 julius
       insn_props->has_rD = 1;
807
       insn_props->has_rA = 1;
808
       insn_props->has_rB = 1;
809
       switch(insn_or1k_opcode_0x38_get_op_lo(insn))
810
         {
811
         case 0x0:
812 16 julius
          insn_props->insn_string="l.add";
813 18 julius
          insn_props->insn_index=85;
814 16 julius
          break;
815
        case 0x1:
816
          insn_props->insn_string="l.addc";
817 18 julius
          insn_props->insn_index=86;
818 16 julius
          break;
819
        case 0x2:
820
          insn_props->insn_string="l.sub";
821 18 julius
          insn_props->insn_index=87;
822 16 julius
          break;
823
        case 0x3:
824
          insn_props->insn_string="l.and";
825 18 julius
          insn_props->insn_index=88;
826 16 julius
          break;
827
        case 0x4:
828
          insn_props->insn_string="l.or";
829 18 julius
          insn_props->insn_index=89;
830 16 julius
          break;
831
        case 0x5:
832
          insn_props->insn_string="l.xor";
833 18 julius
          insn_props->insn_index=90;
834 16 julius
          break;
835
        case 0x6:
836
          insn_props->insn_string="l.mul";
837 18 julius
          insn_props->insn_index=91;
838 16 julius
          break;
839
        case 0x8:
840
          switch (insn_or1k_opcode_0x38_get_op_hi_4bit(insn))
841
            {
842
            case 0x0:
843
              insn_props->insn_string="l.sll";
844 18 julius
              insn_props->insn_index=92;
845 16 julius
              break;
846
            case 0x1:
847
              insn_props->insn_string="l.srl";
848 18 julius
              insn_props->insn_index=93;
849 16 julius
              break;
850
            case 0x2:
851
              insn_props->insn_string="l.sra";
852 18 julius
              insn_props->insn_index=94;
853 16 julius
              break;
854
            case 0x3:
855
              insn_props->insn_string="l.ror";
856 18 julius
              insn_props->insn_index=95;
857 16 julius
              break;
858
            default:
859
              printf("Unknown ALU op 0x8 hi op (0x%x)",
860
                     insn_or1k_opcode_0x38_get_op_hi_4bit(insn));
861 17 julius
              return 1;
862 16 julius
              break;
863
            }
864
          break;
865
        case 0x9:
866
          insn_props->insn_string="l.div";
867 18 julius
          insn_props->insn_index=96;
868 16 julius
          break;
869
        case 0xa:
870
          insn_props->insn_string="l.divu";
871 18 julius
          insn_props->insn_index=97;
872 16 julius
          break;
873
        case 0xb:
874
          insn_props->insn_string="l.mulu";
875 18 julius
          insn_props->insn_index=98;
876 16 julius
          break;
877
        case 0xc:
878
          switch(insn_or1k_opcode_0x38_get_op_hi_4bit(insn))
879
            {
880
            case 0x0:
881
              insn_props->insn_string="l.exths";
882 18 julius
              insn_props->insn_index=99;
883 16 julius
              break;
884
            case 0x1:
885
              insn_props->insn_string="l.extbs";
886 18 julius
              insn_props->insn_index=100;
887 16 julius
              break;
888
            case 0x2:
889
              insn_props->insn_string="l.exthz";
890 18 julius
              insn_props->insn_index=101;
891 16 julius
              break;
892
            case 0x3:
893
              insn_props->insn_string="l.extbz";
894 18 julius
              insn_props->insn_index=102;
895 16 julius
              break;
896
            }
897
          insn_props->has_rB = 0;
898
          break;
899
 
900
        case 0xd:
901 26 julius
          switch(insn_or1k_opcode_0x38_get_op_hi_4bit(insn))
902
            {
903
            case 0x0:
904
              insn_props->insn_string="l.extws";
905
              insn_props->insn_index=103;
906
              break;
907
            case 0x1:
908
              insn_props->insn_string="l.extwz";
909
              insn_props->insn_index=104;
910
              break;
911
            }
912 16 julius
          insn_props->has_rB = 0;
913
          break;
914
 
915
        case 0xe:
916
          insn_props->insn_string="l.cmov";
917 26 julius
          insn_props->insn_index=105;
918 16 julius
          break;
919
 
920
        case 0xf:
921
          if (insn_or1k_opcode_0x38_get_op_hi_2bit(insn) & 0x1)
922 18 julius
            {
923
              insn_props->insn_string="l.fl1";
924 26 julius
              insn_props->insn_index=106;
925 18 julius
            }
926 16 julius
          else
927 18 julius
            {
928
              insn_props->insn_string="l.ff1";
929 26 julius
              insn_props->insn_index=107;
930 18 julius
            }
931 16 julius
          insn_props->has_rB = 0;
932
          break;
933
 
934
        default:
935
          printf("Unknown ALU lo op (0x%x)",
936
                 insn_or1k_opcode_0x38_get_op_lo(insn));
937 17 julius
          return 1;
938 16 julius
          break;
939
        }
940
      break;
941
 
942
    case 0x39:
943 17 julius
      insn_props->has_rA = 1;
944
      insn_props->has_rB = 1;
945 16 julius
      switch (insn_or1k_opcode_0x39_get_op(insn))
946
        {
947
        case 0x0:
948
          insn_props->insn_string="l.sfeq";
949 26 julius
          insn_props->insn_index=108;
950 16 julius
          break;
951
        case 0x1:
952
          insn_props->insn_string="l.sfne";
953 26 julius
          insn_props->insn_index=109;
954 16 julius
          break;
955
        case 0x2:
956
          insn_props->insn_string="l.sfgtu";
957 26 julius
          insn_props->insn_index=110;
958 16 julius
          break;
959
        case 0x3:
960
          insn_props->insn_string="l.sfgeu";
961 26 julius
          insn_props->insn_index=111;
962 16 julius
          break;
963
        case 0x4:
964
          insn_props->insn_string="l.sfltu";
965 26 julius
          insn_props->insn_index=112;
966 16 julius
          break;
967
        case 0x5:
968
          insn_props->insn_string="l.sfleu";
969 26 julius
          insn_props->insn_index=113;
970 16 julius
          break;
971
        case 0xa:
972
          insn_props->insn_string="l.sfgts";
973 26 julius
          insn_props->insn_index=114;
974 16 julius
          break;
975
        case 0xb:
976
          insn_props->insn_string="l.sfges";
977 26 julius
          insn_props->insn_index=115;
978 16 julius
          break;
979
        case 0xc:
980
          insn_props->insn_string="l.sflts";
981 26 julius
          insn_props->insn_index=116;
982 16 julius
          break;
983
        case 0xd:
984
          insn_props->insn_string="l.sfles";
985 26 julius
          insn_props->insn_index=117;
986 16 julius
          break;
987
        default:
988
          printf("Unknown opcode for l.sfxxx opcode (0x%x)",
989
                 insn_or1k_opcode_0x39_get_op(insn));
990 17 julius
          return 1;
991 16 julius
          break;
992
        }
993
      break;
994
 
995
    default:
996
      printf("Unknown opcode 0x%x",insn_or1k_opcode(insn));
997
      return 1;
998
      break;
999
    }
1000
 
1001
  return 0;
1002
}
1003
 
1004
 
1005 22 julius
// Entry point for statistics collection.
1006
// Passed binary copy of instruction, and pointer to properties struct
1007
// Each function that can collect staistics is called.
1008 16 julius
void or1k_32_collect_stats(uint32_t insn,
1009
                         struct or1k_32_instruction_properties  * insn_props)
1010
{
1011 25 julius
  // Add this instruction's occurrence to our data
1012 18 julius
  insn_lists_add(insn, insn_props);
1013 16 julius
 
1014 19 julius
  // n-tuple groupings stats recording here!  
1015
  // only if we've seen enough to do all the sequence analysis
1016
  if (num_seen_insns > OR1K_MAX_GROUPINGS_ANALYSIS+1)
1017
    {
1018
      int n;
1019
      for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
1020
        insn_lists_group_add(n, insn_props);
1021
    }
1022
 
1023
  // Finished adding to stats for this instruction
1024 16 julius
 
1025
 
1026 19 julius
}
1027 16 julius
 
1028 18 julius
// Function to add entry to, or increment incidences of, value in the value list
1029
void or1k_add_in_list(struct or1k_value_list * list, int32_t value)
1030
{
1031
  int i;
1032
  // See if it's already in the list
1033
  i=list->count;
1034
 
1035
  while(i)
1036
    {
1037
      i--;
1038
      if(list->values[i][0] == value)
1039
        {
1040
          (list->values[i][1])++;
1041
          return;
1042
        }
1043
    }
1044
 
1045
  if (list->count < OR1K_VALUE_MAX_ENTRIES)
1046
    {
1047
      // Not found, add it to the list
1048
      list->values[(list->count)][0] = value;
1049
      list->values[(list->count)][1] = 1;
1050
      list->count++;
1051 19 julius
    }
1052 18 julius
}
1053
 
1054 16 julius
// List management/analysis functions - accessed through insn_lists() set of
1055
// functions
1056
 
1057 22 julius
// Clear the list structs
1058 16 julius
void or1k_32_insn_lists_init(void)
1059
{
1060 18 julius
  num_setup_insns = 0;
1061 16 julius
  num_seen_insns = 0;
1062 18 julius
  // Clear the pointer array so we can tell if things are used or not
1063
  memset(or1k_32_insns, '\0',
1064
         sizeof(struct or1k_insn_info *)*OR1K_32_MAX_INSNS);
1065 16 julius
}
1066
 
1067 18 julius
// Alloc struct and put it into the list
1068
void or1k_32_insn_lists_init_insn(uint32_t insn,
1069
                        struct or1k_32_instruction_properties *insn_props)
1070 16 julius
{
1071
  // Add an instruction in or1k_32_insns[num_unique_instructions];
1072
  // use calloc() so it clears it all first (hopefully!).. assumption!
1073
  struct or1k_insn_info * new_insn
1074
    = (struct or1k_insn_info *) calloc (sizeof(struct or1k_insn_info), 1);
1075
 
1076 18 julius
  // Copy the string pointer
1077
  new_insn->insn_string = insn_props->insn_string,
1078 16 julius
 
1079 18 julius
  // Install the pointer for this newly allocated struct in its corresponding
1080
  // index, as set when we decode the instruction
1081
  or1k_32_insns[insn_props->insn_index] = new_insn;
1082 16 julius
 
1083 19 julius
  // Clear the set statistics counters
1084
  int set_itr;
1085
  for(set_itr=0;set_itr<OR1K_MAX_GROUPINGS_ANALYSIS;set_itr++)
1086
    or1k_32_insns[insn_props->insn_index]->groupings[set_itr][0][0] = 0;
1087
 
1088 18 julius
  // Increment number of instructions we have set up
1089
  num_setup_insns++;
1090 17 julius
 
1091
  // Debugging:
1092
  //printf("Adding %dth instruction - %s\n",
1093 18 julius
  //num_setup_insns, new_insn->insn_string);
1094 16 julius
 
1095
}
1096
 
1097
 
1098 17 julius
 
1099 16 julius
// Add stats for this instruction
1100 18 julius
void or1k_32_insn_lists_add(uint32_t insn,
1101 16 julius
                            struct or1k_32_instruction_properties *insn_props)
1102
{
1103 18 julius
  // Check if the entry for this instruction has been setup yet
1104
  if (or1k_32_insns[insn_props->insn_index] == NULL)
1105
    {
1106
      // Here we allocate space for the instruction's stats
1107
      or1k_32_insn_lists_init_insn(insn, insn_props);
1108
    }
1109 16 julius
 
1110 25 julius
  // Increment occurrence count
1111 18 julius
  ((or1k_32_insns[insn_props->insn_index])->count)++;
1112 16 julius
 
1113
  // Add branch target value information, if instruction has it
1114
  if (insn_props->has_branchtarg)
1115
    {
1116 18 julius
      (or1k_32_insns[insn_props->insn_index])->has_branchtarg = 1;
1117
      or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->branch_info),
1118 17 julius
                       (int32_t)insn_or1k_opcode_0x03_get_branchoff(insn));
1119 16 julius
    }
1120
 
1121
  // Add immediate value if it's got one
1122
  if (insn_props->has_imm)
1123
    {
1124 18 julius
      (or1k_32_insns[insn_props->insn_index])->has_imm = 1;
1125
      or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->imm_info),
1126 17 julius
                       (int32_t)insn_or1k_32_imm(insn));
1127 16 julius
    }
1128
 
1129
  // Add split immediate value if it's got one
1130
  if (insn_props->has_split_imm)
1131 17 julius
    {
1132 18 julius
      (or1k_32_insns[insn_props->insn_index])->has_imm = 1;
1133
      or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->imm_info),
1134 17 julius
                       (int32_t)insn_or1k_32_split_imm(insn));
1135 16 julius
    }
1136
 
1137
 
1138
  // Increment count of use for particular rD
1139
  if (insn_props->has_rD)
1140
    {
1141 18 julius
      (or1k_32_insns[insn_props->insn_index])->has_rD = 1;
1142
      ((or1k_32_insns[insn_props->insn_index])->rD_use_freq[insn_or1k_32_rD(insn)])++;
1143 16 julius
    }
1144
 
1145
  // Increment count of use for particular rA
1146
  if (insn_props->has_rA)
1147
    {
1148 18 julius
      (or1k_32_insns[insn_props->insn_index])->has_rA = 1;
1149
      ((or1k_32_insns[insn_props->insn_index])->rA_use_freq[insn_or1k_32_rA(insn)])++;
1150 16 julius
    }
1151
 
1152
  // Increment count of use for particular rB
1153
  if (insn_props->has_rB)
1154
    {
1155 18 julius
      (or1k_32_insns[insn_props->insn_index])->has_rB = 1;
1156
      ((or1k_32_insns[insn_props->insn_index])->rB_use_freq[insn_or1k_32_rB(insn)])++;
1157 16 julius
    }
1158
 
1159
  // Increment overall instructions "seen" counter
1160
  num_seen_insns++;
1161
 
1162 19 julius
  // Shift along the recently seen instructions
1163
  int i;
1164
  for(i=OR1K_MAX_GROUPINGS_ANALYSIS-1;i>0;i--)
1165
    or1k_32_recent_insns[i] = or1k_32_recent_insns[i-1];
1166
  or1k_32_recent_insns[0] = insn_props->insn_index;
1167
 
1168 16 julius
}
1169
 
1170
 
1171 19 julius
 
1172
 
1173 22 julius
// Do the n-tuple set checking for the current instruction
1174 19 julius
void or1k_32_ntuple_add(int n,
1175
                        struct or1k_32_instruction_properties *insn_props)
1176 16 julius
{
1177 19 julius
 
1178
  if (n<2)
1179 16 julius
    {
1180 19 julius
      fprintf(stderr,"or1k_32_ntuple_add: tuple number < 2 (%d)",n);
1181
      return;
1182 16 julius
    }
1183 19 julius
 
1184
  struct or1k_insn_info * insn_info = or1k_32_insns[insn_props->insn_index];
1185
 
1186
  // Get the number of sets for these n-tuple groups we've seen so far.
1187
  int sets_for_ntuple = insn_info->groupings[n-1][0][0];
1188 20 julius
#if DEBUG_PRINT
1189 22 julius
  printf("%s\t:\t%d-tuple add - sets so far : %d\n",
1190
         insn_info->insn_string, n, sets_for_ntuple);
1191 20 julius
#endif
1192 19 julius
 
1193 20 julius
  int set_match_index;
1194
  int tuple_set_itr, tuple_set_match;
1195
 
1196
  tuple_set_match = 0;
1197 19 julius
 
1198
  // now find if the current n instructions in or1k_32_recent_insns[] matches
1199
  // any set of n instructions we're keeping track of in groupings[][][].
1200 20 julius
#if DEBUG_PRINT
1201 22 julius
  printf("%s\tChecking\t%d\tsets for ntuple:\t",
1202
         insn_info->insn_string,sets_for_ntuple);
1203 20 julius
  for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
1204
    printf("%s ",
1205
           or1k_32_insns[(or1k_32_recent_insns[n - 1 - tuple_set_itr])]->insn_string);
1206
  printf("\n");
1207
#endif  
1208 19 julius
  for (set_match_index=0; set_match_index<sets_for_ntuple; set_match_index++)
1209
    {
1210
      // Check this set for a match with our existing trace
1211
      // Example:
1212
      // In case of a triple (n=3), 1st set, [3][1][0] corresponds to the third
1213
      // instruction in the trace (or1k_32_recent_insns[2]), [3][1][1] should 
1214
      // be the second in the trace, and [3][1][2] should be the first in the 
1215
      // trace (same index as insn_props->insn_index)
1216 20 julius
 
1217
#if DEBUG_PRINT
1218
      printf("Chk:\t");
1219
      for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
1220
        printf("%s ",
1221
               or1k_32_insns[(insn_info->groupings[n-1][set_match_index+1][tuple_set_itr])]->insn_string);
1222
      printf("\t(%d)\n", insn_info->groupings[n-1][set_match_index+1][n]);
1223
#endif      
1224
      tuple_set_match = 1;
1225 19 julius
      // Presuppose a match, de-assert and break out of the loop as soon as we
1226
      // detect a mismatch.
1227
      for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
1228
        {
1229 20 julius
 
1230 19 julius
          if (insn_info->groupings[n-1][set_match_index+1][tuple_set_itr]
1231 20 julius
              != or1k_32_recent_insns[n - 1 - tuple_set_itr])
1232 19 julius
            {
1233
              tuple_set_match = 0;
1234
              break; // No match, so break out of this for() loop
1235
            }
1236
        }
1237
 
1238
      if (!tuple_set_match)
1239
        continue; // go again...
1240 20 julius
      else
1241
        break; // Bail out, we've found our match
1242 19 julius
    }
1243
 
1244
  if (tuple_set_match)
1245 20 julius
    {
1246
      // Found a match - just increment the counter (set_match_index should
1247
      // be pointing at the right set)            
1248
#if DEBUG_PRINT
1249
      printf("Match!\n");
1250
#endif
1251
 
1252
      (insn_info->groupings[n-1][set_match_index+1][n])++;
1253
    }
1254 19 julius
  else
1255
    {
1256
      // If we can record a new set
1257
      if (sets_for_ntuple < OR1K_MAX_ENTRIES_PER_GROUP)
1258
        {
1259 20 julius
#if DEBUG_PRINT
1260
          printf("New entry\n");
1261
#endif
1262
 
1263 19 julius
          // Increment the number of sets we have for this n-tuple starting
1264
          // on the current instruction  
1265
          sets_for_ntuple++;
1266
          // Add new set to the end (all n instructions, copy in)
1267
          for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
1268
            insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr]
1269 20 julius
              = or1k_32_recent_insns[n - 1 - tuple_set_itr];
1270 19 julius
          // Set the count for this set to 1
1271 20 julius
          (insn_info->groupings[n-1][sets_for_ntuple][n]) = 1;
1272 19 julius
          // Increment the counter of these n-tuple sets
1273 20 julius
          insn_info->groupings[n-1][0][0] = sets_for_ntuple;
1274 19 julius
        }
1275 20 julius
    }
1276
 
1277
#if DEBUG_PRINT
1278 22 julius
  // Verbose announcement of found instruction
1279 20 julius
   if (tuple_set_match)
1280
  {
1281
     printf("%s\t:\tMatch for %d-tuple - set %d - cnt: %d - ",
1282
      insn_info->insn_string, n, set_match_index,
1283
             insn_info->groupings[n-1][set_match_index+1][n]);
1284
    for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
1285
        printf("%s ",
1286
               or1k_32_insns[(insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr])]->insn_string);
1287
    printf("\n");
1288
  }
1289
  else
1290
    {
1291
     printf("%s\t:\tNew %d-tuple - set %d - cnt: %d - ",
1292
             insn_info->insn_string, n, sets_for_ntuple,
1293
             insn_info->groupings[n-1][sets_for_ntuple][n]);
1294
    for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
1295
        printf("%s ",
1296
               or1k_32_insns[(insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr])]->insn_string);
1297
    printf("\n");
1298
  }
1299
#endif
1300
 
1301 16 julius
}
1302 17 julius
 
1303 22 julius
// Generate a list for the most-frequently seen instructions
1304 17 julius
void or1k_32_most_freq_insn(FILE * stream)
1305
{
1306
  // Print out most frequent instruction
1307
  int i, largest, largest_index;
1308 18 julius
  int instructions_to_print = num_setup_insns;
1309 22 julius
 
1310
#ifdef DISPLAY_CSV
1311
  fprintf(stream,"\"Most frequent instructions, descending\",\n");
1312 25 julius
  fprintf(stream,"\"Instruction\",\"Occurrences\",\"Frequency\",\n");
1313 22 julius
#endif
1314
 
1315 17 julius
  while (instructions_to_print)
1316
    {
1317
      --instructions_to_print;
1318
      largest=0;
1319
      // Go through the list, find the largest, print it, eliminate it
1320 18 julius
      for(i=0;i<OR1K_32_MAX_INSNS;i++)
1321
        if (or1k_32_insns[i]!=NULL){
1322
          if(((or1k_32_insns[i])->count) > largest)
1323
            {
1324
              largest = ((or1k_32_insns[i])->count);
1325
              largest_index = i;
1326
            }
1327
        }
1328 17 julius
      fprintf(stream,
1329
#ifdef DISPLAY_STRING      
1330
             "Insn:\t%s\t\tCount:\t\t%d\t(%f%%)\n",
1331
#endif
1332
#ifdef DISPLAY_CSV
1333
             // CSV format - "opcode string",frequency,percentage
1334
             "\"%s\",%d,%f\n",
1335
#endif
1336
             ((or1k_32_insns[largest_index])->insn_string),
1337
             ((or1k_32_insns[largest_index])->count),
1338
             (float)(((float)((or1k_32_insns[largest_index])->count))/
1339
                     ((float)num_seen_insns))*100.f);
1340
 
1341
 
1342
      ((or1k_32_insns[largest_index])->count) = -1; // Eliminate this one
1343
 
1344
    }
1345
}
1346
 
1347
 
1348 22 julius
// Generate a list for the most-frequently seen n-tuple set
1349
void or1k_32_most_freq_ntuple(int n, FILE * stream, int max_stats)
1350
{
1351
 
1352
  fprintf(stream,
1353
#ifdef DISPLAY_STRING
1354
          "Top %d %d-tuple groupings of instructions\n",
1355
#endif
1356
#ifdef DISPLAY_CSV
1357
          "\"Top %d %d-tuple groupings of instructions\",\n",
1358
#endif
1359
          max_stats, n);
1360
 
1361
  // First get a copy of all the n-tuple values for each applicable
1362
  // instruction.
1363
  int set_counts[OR1K_32_MAX_INSNS][OR1K_MAX_ENTRIES_PER_GROUP];
1364
  int insn_index;
1365
  int set_index;
1366
  int num_sets;
1367
  struct or1k_insn_info *insn_info;
1368
 
1369
  // Copy each instruction's set totals into our local array
1370
  for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
1371
    {
1372
      if (or1k_32_insns[insn_index] != NULL)
1373
        {
1374
          insn_info = or1k_32_insns[insn_index];
1375
          num_sets = insn_info->groupings[n-1][0][0];
1376
          for(set_index=0;set_index<num_sets;set_index++)
1377
            set_counts[insn_index][set_index] =
1378
              insn_info->groupings[n-1][set_index+1][n];
1379
        }
1380
    }
1381
 
1382
  // Go through the set numbers, look at the most frequent one, print it out
1383
  // clear its count and continue
1384
 
1385
 
1386
  int largest_insn_index, largest_set_index, largest_count;
1387
  int tuple_set_itr;
1388
 
1389
 
1390
#ifdef DISPLAY_CSV
1391
  for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
1392
    fprintf(stream, "\"insn%d\",",n-1-tuple_set_itr);
1393
  fprintf(stream, "\"count\",\n");
1394
#endif
1395
 
1396
  while(max_stats--)
1397
    {
1398
      largest_count = 0;
1399
      // Go through each instruction we have
1400
      for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
1401
        {
1402
          if (or1k_32_insns[insn_index] != NULL)
1403
            {
1404
              insn_info = or1k_32_insns[insn_index];
1405
              // Get the total number of sets for the n-tup. of this instruction
1406
              num_sets = insn_info->groupings[n-1][0][0];
1407
              for(set_index=0;set_index<num_sets;set_index++)
1408
                {
1409
                  // Go through each set, check if it's largest
1410
                  if (set_counts[insn_index][set_index] >
1411
                      largest_count)
1412
                    {
1413
                      largest_insn_index = insn_index;
1414
                      largest_set_index = set_index;
1415
                      largest_count = set_counts[insn_index][set_index];
1416
                    }
1417
                }
1418
            }
1419
        }
1420 23 julius
 
1421
      // We now have indexes of the next largest n-tuple, print it out.
1422
 
1423 22 julius
      insn_info = or1k_32_insns[largest_insn_index];
1424 23 julius
 
1425 22 julius
#ifdef DISPLAY_STRING
1426
      fprintf(stream,"set :");
1427
#endif
1428 23 julius
 
1429 22 julius
      for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
1430
        fprintf(stream,
1431
#ifdef DISPLAY_STRING
1432
                " %s",
1433
#endif
1434
#ifdef DISPLAY_CSV
1435
                "\"%s\",",
1436
#endif
1437 23 julius
                or1k_32_insns[(insn_info->groupings[n-1][largest_set_index+1][tuple_set_itr])]->insn_string);
1438 22 julius
 
1439
      fprintf(stream,
1440
#ifdef DISPLAY_STRING
1441
              "\tcount: %d\n",
1442
#endif
1443
#ifdef DISPLAY_CSV
1444
              "%d,\n",
1445
#endif
1446
              set_counts[largest_insn_index][largest_set_index]);
1447
 
1448
        // Remove this value from getting selected from largest again
1449
        set_counts[largest_insn_index][largest_set_index] = -1;
1450
    }
1451
 
1452
}
1453
 
1454
 
1455
 
1456
 
1457
// Print out top n of each kept statistic for the requested instruction
1458
void or1k_32_insn_top_n(struct or1k_insn_info *insn_info, FILE * stream,
1459 18 julius
                        int max_stats)
1460 17 julius
{
1461 20 julius
  int i, j, largest_i;
1462 17 julius
 
1463 18 julius
  fprintf(stream,
1464 22 julius
#ifdef DISPLAY_STRING
1465
          "Insn: \"%s\" statistics (%d times (%f%%))\n",
1466
#endif
1467
#ifdef DISPLAY_CSV
1468 26 julius
          "\"Instruction:\",\"%s\",\"occurrences:\",%d,%f%%\n",
1469 22 julius
#endif
1470 18 julius
          insn_info->insn_string,
1471
          insn_info->count,
1472
          (float)(((float)((insn_info)->count))/
1473
                  ((float)num_seen_insns))*100.f
1474
          );
1475 17 julius
 
1476
 
1477
 
1478 18 julius
  // Start dumping applicable stats
1479 17 julius
 
1480
  // Print out top max_stats branch targets
1481 18 julius
  if (insn_info->has_branchtarg)
1482 17 julius
    {
1483 22 julius
      fprintf(stream,
1484
#ifdef DISPLAY_STRING
1485 26 julius
              "Branch immediates:\n"
1486 22 julius
#endif
1487
#ifdef DISPLAY_CSV
1488 26 julius
              "\"branch imm\",\"occurrences\",\"frequency\"\n"
1489 22 julius
#endif
1490
              );
1491 17 julius
      i = 0;
1492 18 julius
      while(i<insn_info->branch_info.count && i < max_stats)
1493 17 julius
        {
1494
          largest_i=0;
1495 18 julius
          for(j=0;j<insn_info->branch_info.count;j++)
1496
            largest_i = (insn_info->branch_info.values[j][1] >
1497
                         insn_info->branch_info.values[largest_i][1]) ?
1498 17 julius
              j : largest_i;
1499
 
1500
          // largest_i has index of most frequent value
1501
          fprintf(stream,
1502 22 julius
#ifdef DISPLAY_STRING
1503 26 julius
                  "value:\t0x%x\tcount:\t%d,\tfreq:\t%f%%\n",
1504 22 julius
#endif
1505
#ifdef DISPLAY_CSV
1506 26 julius
                  "0x%x,%d,%f\n",
1507 22 julius
#endif
1508 18 julius
                  insn_info->branch_info.values[largest_i][0],
1509 26 julius
                  insn_info->branch_info.values[largest_i][1],
1510
                  (float)(((float)insn_info->branch_info.values[largest_i][1])
1511
                          /((float)((insn_info)->count)))*100.0f);
1512 18 julius
          insn_info->branch_info.values[largest_i][1] = -1; // clear this one
1513 17 julius
          i++;
1514
        }
1515
    }
1516 18 julius
  if (insn_info->has_imm)
1517 17 julius
    {
1518 22 julius
      fprintf(stream,
1519
#ifdef DISPLAY_STRING
1520
              "Immediate values:\n"
1521
#endif
1522
#ifdef DISPLAY_CSV
1523 26 julius
              "\"immediate value\",\"count\",\"frequency\"\n"
1524 22 julius
#endif
1525
              );
1526 17 julius
      i = 0;
1527 18 julius
      while(i<insn_info->imm_info.count && i < max_stats)
1528 17 julius
        {
1529
          largest_i=0;
1530 18 julius
          for(j=0;j<insn_info->imm_info.count;j++)
1531
            largest_i = (insn_info->imm_info.values[j][1] >
1532
                         insn_info->imm_info.values[largest_i][1]) ?
1533 17 julius
              j : largest_i;
1534
 
1535
          // largest_i has index of most frequent value
1536
          fprintf(stream,
1537 22 julius
#ifdef DISPLAY_STRING
1538 26 julius
                  "value:\t0x%x\tcount:\t%d\tfreq:\t%f%%\n",
1539 22 julius
#endif
1540
#ifdef DISPLAY_CSV
1541 26 julius
                  "0x%x,%d,%f\n",
1542 22 julius
#endif
1543 18 julius
                  insn_info->imm_info.values[largest_i][0],
1544 26 julius
                  insn_info->imm_info.values[largest_i][1],
1545
                  (float)(((float)insn_info->imm_info.values[largest_i][1])
1546
                          /((float)((insn_info)->count)))*100.0f);
1547 18 julius
          insn_info->imm_info.values[largest_i][1] = -1; // clear this one
1548 17 julius
          i++;
1549
        }
1550
    }
1551 22 julius
 
1552 18 julius
  if (insn_info->has_rD)
1553 17 julius
    {
1554 22 julius
      fprintf(stream,
1555
#ifdef DISPLAY_STRING
1556
              "rD usage:\n"
1557
#endif
1558
#ifdef DISPLAY_CSV
1559 26 julius
              "\"rD\",\"count\",\"frequency\"\n"
1560 22 julius
#endif
1561
              );
1562 17 julius
      i = 0;
1563
      while(i<32 && i < max_stats)
1564
        {
1565
          largest_i=0;
1566
          for(j=0;j<32;j++)
1567 18 julius
            largest_i = (insn_info->rD_use_freq[j] >
1568
                         insn_info->rD_use_freq[largest_i]) ?
1569 17 julius
              j : largest_i;
1570
 
1571
          // No more interesting numbers
1572 18 julius
          if (insn_info->rD_use_freq[largest_i] == 0)
1573 17 julius
            break;
1574
 
1575
          // largest_i has index of most frequent value
1576
          fprintf(stream,
1577 22 julius
#ifdef DISPLAY_STRING
1578 26 julius
                  "r%d\tcount:\t%d\tfreq:\t%f%%\n",
1579 22 julius
#endif
1580
#ifdef DISPLAY_CSV
1581 26 julius
                  "\"r%d\",%d,%f\n",
1582 22 julius
#endif
1583 17 julius
                  largest_i,
1584 26 julius
                  insn_info->rD_use_freq[largest_i],
1585
                  (float)(((float)insn_info->rD_use_freq[largest_i])
1586
                          /((float)((insn_info)->count)))*100.0f);
1587 18 julius
          insn_info->rD_use_freq[largest_i] = -1; // clear this one
1588 17 julius
          i++;
1589
        }
1590
    }
1591
 
1592 18 julius
  if (insn_info->has_rA)
1593 17 julius
    {
1594 22 julius
      fprintf(stream,
1595
#ifdef DISPLAY_STRING
1596
              "rA usage:\n"
1597
#endif
1598
#ifdef DISPLAY_CSV
1599 26 julius
              "\"rA\",\"count\",\"frequency\"\n"
1600 22 julius
#endif
1601
              );
1602 17 julius
      i = 0;
1603
      while(i<32 && i < max_stats)
1604
        {
1605
          largest_i=0;
1606
          for(j=0;j<32;j++)
1607 18 julius
            largest_i = (insn_info->rA_use_freq[j] >
1608
                         insn_info->rA_use_freq[largest_i]) ?
1609 17 julius
              j : largest_i;
1610
 
1611
          // No more interesting numbers
1612 18 julius
          if (insn_info->rA_use_freq[largest_i] == 0)
1613 17 julius
            break;
1614
 
1615
 
1616
          // largest_i has index of most frequent value
1617
          fprintf(stream,
1618 22 julius
#ifdef DISPLAY_STRING
1619 26 julius
                  "r%d\tcount:\t%d\tfreq:\t%f%%\n",
1620 22 julius
#endif
1621
#ifdef DISPLAY_CSV
1622 26 julius
                  "\"r%d\",%d,%f\n",
1623 22 julius
#endif
1624 17 julius
                  largest_i,
1625 26 julius
                  insn_info->rA_use_freq[largest_i],
1626
                  (float)(((float)insn_info->rA_use_freq[largest_i])
1627
                          /((float)((insn_info)->count)))*100.0f);
1628 18 julius
          insn_info->rA_use_freq[largest_i] = -1; // clear this one
1629 17 julius
          i++;
1630
        }
1631
    }
1632
 
1633 18 julius
  if (insn_info->has_rB)
1634 17 julius
    {
1635 22 julius
      fprintf(stream,
1636
#ifdef DISPLAY_STRING
1637
              "rB usage:\n"
1638
#endif
1639
#ifdef DISPLAY_CSV
1640 26 julius
              "\"rB\",\"count\",\"frequency\"\n"
1641 22 julius
#endif
1642
              );
1643 17 julius
      i = 0;
1644
      while(i<32 && i < max_stats)
1645
        {
1646
          largest_i=0;
1647
          for(j=0;j<32;j++)
1648 18 julius
            largest_i = (insn_info->rB_use_freq[j] >
1649
                         insn_info->rB_use_freq[largest_i]) ?
1650 17 julius
              j : largest_i;
1651
 
1652
          // No more interesting numbers
1653 18 julius
          if (insn_info->rB_use_freq[largest_i] == 0)
1654 17 julius
            break;
1655
 
1656
 
1657
          // largest_i has index of most frequent value
1658
          fprintf(stream,
1659 22 julius
#ifdef DISPLAY_STRING
1660 26 julius
                  "r%d\tcount:\t%d\tfreq:\t%f%%\n",
1661 22 julius
#endif
1662
#ifdef DISPLAY_CSV
1663 26 julius
                  "\"r%d\",%d,%f\n",
1664 22 julius
#endif
1665 17 julius
                  largest_i,
1666 26 julius
                  insn_info->rB_use_freq[largest_i],
1667
                  (float)(((float)insn_info->rB_use_freq[largest_i])
1668
                          /((float)((insn_info)->count)))*100.0f);
1669 18 julius
          insn_info->rB_use_freq[largest_i] = -1; // clear this one
1670 17 julius
          i++;
1671
        }
1672
    }
1673
}
1674 19 julius
 
1675 20 julius
 
1676
 
1677 19 julius
// Print out the most common n-tuple groupings for an instruction
1678
void or1k_32_generate_ntuple_stats(int n, struct or1k_insn_info *insn_info,
1679
                                   FILE * stream)
1680
{
1681 20 julius
  // Maximum number we'll print out
1682
#define MAX_NTUPLE_LISTING 5
1683
 
1684
  int (*ntuplelist)[OR1K_MAX_GROUPINGS_ANALYSIS+1];
1685
  int *set;
1686
  int set_count, set_count2;
1687
 
1688
  // Get total number of sets for this n-tuple, eg:
1689 22 julius
  // if n=2 (pairs) then groupings[1] is where our list is, and we store the 
1690
  // number of sets in [0][0] of that n-tuple data.
1691 19 julius
  int total_sets_for_ntuple =  insn_info->groupings[n-1][0][0];
1692
 
1693
  if (total_sets_for_ntuple == 0)
1694
    return;
1695
 
1696 22 julius
  fprintf(stream,
1697
#ifdef DISPLAY_STRING     
1698
          "%d-tuple groupings finishing with %s (%d)\n",
1699
#endif
1700
#ifdef DISPLAY_CSV
1701
          "\"%d-tuple groupings\",\n",
1702
#endif     
1703
          n, insn_info->insn_string, total_sets_for_ntuple);
1704 19 julius
 
1705 22 julius
 
1706 20 julius
  // Debug - dump out all of the info for the sets
1707
#if DEBUG_PRINT
1708
  for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
1709
    {
1710
 
1711 22 julius
      printf("set: %d - count %d - set: ", set_count,
1712
             insn_info->groupings[n-1][set_count+1][n]);
1713 20 julius
 
1714
      for(set_count2=0;set_count2<n;set_count2++)
1715
        fprintf(stream, "%s\t",
1716
                or1k_32_insns[(insn_info->groupings[n-1][set_count+1][set_count2])]->insn_string);
1717
      printf("\n");
1718
    }
1719
#endif
1720
 
1721
  // A pointer to the n-tuple sets
1722 19 julius
  // This is actually a pointer to a 2-dimensional integer array, looking like:
1723 22 julius
  // [OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1], so in 
1724
  // 2-dimensional array pointer fashion, we should provide the "column" sizing.
1725 20 julius
      ntuplelist = insn_info->groupings[n-1];
1726 19 julius
 
1727
  // Let's make a copy of the counts for each... so we don't trash them
1728
  int set_count_copy[OR1K_MAX_ENTRIES_PER_GROUP+1];
1729 20 julius
 
1730
  assert(total_sets_for_ntuple <= OR1K_MAX_ENTRIES_PER_GROUP);
1731
 
1732 19 julius
  // Go through the list, copy the counts for each
1733
  for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
1734
    {
1735 20 julius
      // Pointer to a set's data
1736
      set = ntuplelist[set_count+1];
1737 22 julius
      // Fish out the copy (0 to n-1 will be the instruction index, n will be 
1738
      // the count)
1739 20 julius
      set_count_copy[set_count+1] = set[n];
1740 19 julius
    }
1741 24 julius
 
1742
 
1743
#ifdef DISPLAY_CSV
1744
      for(set_count2=0;set_count2<n;set_count2++)
1745
        fprintf(stream, "\"insn%d\",",n-1-set_count2);
1746
      fprintf(stream, "\"count\",\n");
1747
#endif
1748
 
1749 19 julius
 
1750
  // Now go through, finding the most frequent n-tuple of instructions and
1751
  // print it out
1752
  int largest_indx = 0;
1753
  set_count=0;
1754
  while(set_count < total_sets_for_ntuple && set_count < MAX_NTUPLE_LISTING)
1755
    {
1756
      largest_indx = 0;
1757
      for(set_count2=0;set_count2<total_sets_for_ntuple;set_count2++)
1758
        largest_indx = (set_count_copy[set_count2 + 1] >
1759
                        set_count_copy[largest_indx + 1]) ?
1760
          set_count2 : largest_indx;
1761 25 julius
      // largest_indx is the index of the set with the highest occurrence, so
1762 19 julius
      // let's print it out, but first get a pointer to the set's data
1763
      set = (int*)ntuplelist[largest_indx+1];
1764 20 julius
 
1765 19 julius
      // Print out the sequence of prior isntructions
1766 22 julius
#ifdef DISPLAY_STRING
1767 19 julius
      fprintf(stream,"Seq:\t");
1768 22 julius
#endif
1769 19 julius
      // Go through the indexes of the previous instructions, get their
1770
      // strings, and print them out
1771
      for(set_count2=0;set_count2<n;set_count2++)
1772 22 julius
        fprintf(stream,
1773
#ifdef DISPLAY_STRING
1774
                "%s\t",
1775
#endif
1776
#ifdef DISPLAY_CSV
1777
                "\"%s\",",
1778
#endif
1779
                or1k_32_insns[(set[set_count2])]->insn_string);
1780 19 julius
 
1781 25 julius
      // now print out the occurrences
1782 22 julius
      fprintf(stream,
1783
#ifdef DISPLAY_STRING
1784
              "\t%d\ttimes (%f%%)\n",
1785
#endif
1786
#ifdef DISPLAY_CSV
1787
              "%d,\n",
1788
#endif
1789
              set[n],
1790 21 julius
              (float)((float)set[n]/(float)insn_info->count)*100.0f);
1791
 
1792 19 julius
      // done printing this one out.. let's clear its count
1793
      set_count_copy[largest_indx + 1] = -1;
1794
 
1795
      set_count++;
1796
    }
1797
 
1798
  return;
1799
 
1800
}
1801
 
1802
 
1803
// Print out the stats relating to the sequences of instructions most
1804
// common before seeing this instruction
1805
void or1k_32_generate_groupings_stats(struct or1k_insn_info *insn_info,
1806
                                      FILE * stream)
1807
{
1808
  int n;
1809
  for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
1810
    or1k_32_generate_ntuple_stats(n, insn_info, stream);
1811
 
1812
}
1813 22 julius
 
1814
// Entry point for statistics generation.    
1815 17 julius
void or1k_32_generate_stats(FILE * stream)
1816
{
1817 22 julius
#ifdef DISPLAY_STRING
1818 17 julius
  // Generate some useful things
1819
  fprintf(stream, "Analysis output:\n");
1820 22 julius
#endif  
1821 17 julius
  // 
1822
 
1823
  // Print out all stats for every instruction we saw!
1824 18 julius
  int insn_index;
1825
  for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
1826 17 julius
    {
1827 18 julius
      if (or1k_32_insns[insn_index] != NULL)
1828 19 julius
        {
1829 22 julius
#ifdef DISPLAY_STRING
1830 21 julius
          fprintf(stream, "\t---\t---\t---\t---\n");
1831 22 julius
#endif
1832 25 julius
#ifdef DISPLAY_CSV
1833
          fprintf(stream, ",\n");
1834
#endif
1835
          or1k_32_insn_top_n(or1k_32_insns[insn_index],stream,10);
1836
          or1k_32_generate_groupings_stats(or1k_32_insns[insn_index],stream);
1837
 
1838 19 julius
        }
1839 17 julius
    }
1840
 
1841 25 julius
#ifdef DISPLAY_STRING
1842
          fprintf(stream, "\t---\t---\t---\t---\n");
1843
#endif
1844
#ifdef DISPLAY_CSV
1845
          fprintf(stream, ",\n");
1846
#endif
1847
 
1848
 
1849 22 julius
  // print out most frequent n-tuple
1850
  int ntuple;
1851
  for(ntuple=2;ntuple<5;ntuple++)
1852
    or1k_32_most_freq_ntuple(ntuple, stream, 10);
1853 25 julius
 
1854
 
1855
#ifdef DISPLAY_STRING
1856
          fprintf(stream, "\t---\t---\t---\t---\n");
1857
#endif
1858
#ifdef DISPLAY_CSV
1859
          fprintf(stream, ",\n");
1860
#endif
1861
 
1862 22 julius
 
1863 17 julius
  // Do most frequent instruction analysis -- note this trashes instruction
1864
  // frequency count - should be fixed
1865 22 julius
#ifdef DISPLAY_STRING
1866 21 julius
  fprintf(stream, "Individual instruction frequency:\n");
1867 22 julius
#endif
1868 17 julius
  or1k_32_most_freq_insn(stream);
1869
 
1870
}
1871 19 julius
 
1872
 
1873
 
1874
 
1875
// Free up all added instruction statistic tracking structs
1876
void or1k_32_insn_lists_free(void)
1877
{
1878
  // Free all entries we m/calloc()'d
1879
  int insn_index;
1880
  for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
1881
    {
1882
      if (or1k_32_insns[insn_index] != NULL)
1883
        free(or1k_32_insns[insn_index]);
1884
    }
1885
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.