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 24

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

powered by: WebSVN 2.1.0

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