URL
https://opencores.org/ocsvn/or2k/or2k/trunk
Subversion Repositories or2k
[/] [or2k/] [trunk/] [analysis-bin/] [insnanalysis/] [or1k-32-insn.c] - Rev 18
Go to most recent revision | Compare with Previous | Blame | View Log
/* Or1K instruction set-specific decoding and analysis functions. Julius Baxter, julius.baxter@orsoc.se */ #include "stdio.h" #include "stdint.h" #include "stdlib.h" #include "string.h" #include "or1k-32-insn.h" // These should also be in insnanalysis.h insnanalysis.h typedef uint32_t instruction; typedef struct or1k_32_instruction_properties instruction_properties ; #include "insn-lists.h" int or1k_32_analyse_insn(uint32_t insn, struct or1k_32_instruction_properties * insn_props) { switch(insn_or1k_opcode(insn)) { case 0x00: insn_props->insn_string="l.j"; insn_props->insn_index=0; insn_props->has_jumptarg = 1; break; case 0x01: insn_props->insn_string="l.jal"; insn_props->insn_index=1; insn_props->has_jumptarg = 1; break; case 0x03: insn_props->insn_string="l.bnf"; insn_props->insn_index=2; insn_props->has_branchtarg = 1; break; case 0x04: insn_props->insn_string="l.bf"; insn_props->insn_index=3; insn_props->has_branchtarg = 1; break; case 0x05: insn_props->insn_string="l.nop"; insn_props->insn_index=4; break; case 0x06: if((insn_or1k_opcode_0x06_get_id(insn))) { insn_props->insn_string="l.macrc"; insn_props->insn_index=5; } else { insn_props->insn_string="l.movhi"; insn_props->insn_index=6; insn_props->has_rD = 1; insn_props->has_imm = 1; } break; case 0x08: switch(insn_or1k_opcode_0x08_get_id(insn)) { case 0x0: insn_props->insn_string="l.sys"; insn_props->insn_index=7; break; case 0x2: insn_props->insn_string="l.trap"; insn_props->insn_index=8; break; case 0x4: insn_props->insn_string="l.msync"; insn_props->insn_index=9; break; case 0x5: insn_props->insn_string="l.psync"; insn_props->insn_index=10; break; case 0x6: insn_props->insn_string="l.csync"; insn_props->insn_index=11; break; default: printf("Unknown id (0x%x) in opcode 0x8", insn_or1k_opcode_0x08_get_id(insn) ); return 1; break; } break; case 0x09: insn_props->insn_string="l.rfe"; insn_props->insn_index=12; break; case 0x0a: switch(insn_or1k_opcode_0x0a_get_op_hi(insn)) { case 0x1: switch(insn_or1k_opcode_0x0a_get_op_lo(insn)) { case 0x0: break; case 0x1: break; case 0x2: break; case 0x3: break; case 0x4: break; case 0x5: break; case 0x6: break; case 0x7: break; case 0x8: break; case 0x9: break; case 0xa: break; case 0xb: break; default: printf("Unknown lv.all_xx insn"); return 1; } case 0x2: switch(insn_or1k_opcode_0x0a_get_op_lo(insn)) { case 0x0: break; case 0x1: break; case 0x2: break; case 0x3: break; case 0x4: break; case 0x5: break; case 0x6: break; case 0x7: break; case 0x8: break; case 0x9: break; case 0xa: break; case 0xb: break; default: printf("Unknown lv.any_xx insn"); return 1; } break; case 0x3: switch(insn_or1k_opcode_0x0a_get_op_lo(insn)) { case 0x0: break; case 0x1: break; case 0x2: break; case 0x3: break; case 0x4: break; case 0x5: break; case 0x6: break; case 0x7: break; case 0x8: break; case 0x9: break; case 0xa: break; default: printf("Unknown lv.add/and/avg_xx insn"); return 1; } break; case 0x4: switch(insn_or1k_opcode_0x0a_get_op_lo(insn)) { case 0x0: break; case 0x1: break; case 0x2: break; case 0x3: break; case 0x4: break; case 0x5: break; case 0x6: break; case 0x7: break; case 0x8: break; case 0x9: break; case 0xa: break; case 0xb: break; default: printf("Unknown lv.cmp_xx insn"); return 1; } break; case 0x5: switch(insn_or1k_opcode_0x0a_get_op_lo(insn)) { case 0x4: break; case 0x5: break; case 0x6: break; case 0x7: break; case 0x8: break; case 0x9: break; case 0xa: break; case 0xb: break; case 0xc: break; case 0xd: break; case 0xe: break; case 0xf: break; default: printf("Unknown lv.alu_xx insn"); return 1; } break; case 0x6: switch(insn_or1k_opcode_0x0a_get_op_lo(insn)) { case 0x0: break; case 0x1: break; case 0x2: break; case 0x3: break; case 0x4: break; case 0x5: break; case 0x6: break; case 0x7: break; case 0x8: break; case 0x9: break; case 0xa: break; case 0xb: break; case 0xc: break; case 0xd: break; case 0xe: break; case 0xf: break; default: printf("Unknown lv.pack_xx insn"); return 1; } break; case 0x7: switch(insn_or1k_opcode_0x0a_get_op_lo(insn)) { case 0x0: break; case 0x1: break; case 0x2: break; case 0x3: break; case 0x4: break; case 0x5: break; case 0x6: break; case 0x7: break; case 0x8: break; case 0x9: break; case 0xa: break; case 0xb: break; default: printf("Unknown lv.sub/unpack/xor_xx insn"); return 1; } break; case 0xc: break; case 0xd: break; case 0xe: break; case 0xf: break; default: printf("Unknown lv.xxx insn hi op"); return 1; break; } break; case 0x11: insn_props->insn_string="l.jr"; insn_props->insn_index=13; insn_props->has_rB = 1; break; case 0x12: insn_props->insn_string="l.jalr"; insn_props->insn_index=14; insn_props->has_rB = 1; break; case 0x13: insn_props->insn_string="l.maci"; insn_props->insn_index=15; break; case 0x1c: insn_props->insn_string="l.cust1"; insn_props->insn_index=16; break; case 0x1d: insn_props->insn_string="l.cust2"; insn_props->insn_index=17; break; case 0x1e: insn_props->insn_string="l.cust3"; insn_props->insn_index=18; break; case 0x1f: insn_props->insn_string="l.cust4"; insn_props->insn_index=19; break; case 0x20: insn_props->insn_string="l.ld"; insn_props->insn_index=20; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x21: insn_props->insn_string="l.lwz"; insn_props->insn_index=21; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x22: insn_props->insn_string="l.lws"; insn_props->insn_index=22; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x23: insn_props->insn_string="l.lbz"; insn_props->insn_index=23; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x24: insn_props->insn_string="l.lbs"; insn_props->insn_index=24; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x25: insn_props->insn_string="l.lhz"; insn_props->insn_index=25; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x26: insn_props->insn_string="l.lhs"; insn_props->insn_index=26; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x27: insn_props->insn_string="l.addi"; insn_props->insn_index=27; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x28: insn_props->insn_string="l.addic"; insn_props->insn_index=28; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x29: insn_props->insn_string="l.andi"; insn_props->insn_index=29; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x2a: insn_props->insn_string="l.ori"; insn_props->insn_index=30; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x2b: insn_props->insn_string="l.xori"; insn_props->insn_index=31; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x2c: insn_props->insn_string="l.muli"; insn_props->insn_index=32; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x2d: insn_props->insn_string="l.mfspr"; insn_props->insn_index=33; insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x2e: switch(insn_or1k_opcode_0x2e_get_op(insn)) { case 0x0: insn_props->insn_string="l.slli"; insn_props->insn_index=34; break; case 0x1: insn_props->insn_string="l.srli"; insn_props->insn_index=35; break; case 0x2: insn_props->insn_string="l.srai"; insn_props->insn_index=36; break; case 0x3: insn_props->insn_string="l.rori"; insn_props->insn_index=37; break; default: printf("Unknown shift op (0x%x)", insn_or1k_opcode_0x2e_get_op(insn)); return 1; break; } break; case 0x2f: switch(insn_or1k_opcode_0x2f_get_op(insn)) { case 0x0: insn_props->insn_string="l.sfeqi"; insn_props->insn_index=38; break; case 0x1: insn_props->insn_string="l.sfnei"; insn_props->insn_index=39; break; case 0x2: insn_props->insn_string="l.sfgtui"; insn_props->insn_index=40; break; case 0x3: insn_props->insn_string="l.sfgeui"; insn_props->insn_index=41; break; case 0x4: insn_props->insn_string="l.sfltui"; insn_props->insn_index=42; break; case 0x5: insn_props->insn_string="l.sfleui"; insn_props->insn_index=43; break; case 0xa: insn_props->insn_string="l.sfgtsi"; insn_props->insn_index=44; break; case 0xb: insn_props->insn_string="l.sfgesi"; insn_props->insn_index=45; break; case 0xc: insn_props->insn_string="l.sfltsi"; insn_props->insn_index=46; break; case 0xd: insn_props->insn_string="l.sflesi"; insn_props->insn_index=47; break; default: printf("Unknown set flag op (0x%x)", insn_or1k_opcode_0x2f_get_op(insn)); return 1; break; } insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x30: insn_props->insn_string="l.mtspr"; insn_props->insn_index=48; break; case 0x31: switch (insn_or1k_opcode_0x31_get_op(insn)) { case 0x1: insn_props->insn_string="l.mac"; insn_props->insn_index=49; break; case 0x2: insn_props->insn_string="l.msb"; insn_props->insn_index=50; break; default: printf("Unknown mac op (0x%x)", insn_or1k_opcode_0x31_get_op(insn)); return 1; } break; case 0x32: switch(insn_or1k_opcode_0x32_get_op_hi(insn)) { case 0x0: switch(insn_or1k_opcode_0x32_get_op_lo(insn)) { case 0x0: insn_props->insn_string="lf.add.s"; insn_props->insn_index=51; break; case 0x1: insn_props->insn_string="lf.sub.s"; insn_props->insn_index=52; break; case 0x2: insn_props->insn_string="lf.mul.s"; insn_props->insn_index=53; break; case 0x3: insn_props->insn_string="lf.div.s"; insn_props->insn_index=54; break; case 0x4: insn_props->insn_string="lf.itof.s"; insn_props->insn_index=55; break; case 0x5: insn_props->insn_string="lf.ftoi.s"; insn_props->insn_index=56; break; case 0x6: insn_props->insn_string="lf.rem.s"; insn_props->insn_index=57; break; case 0x7: insn_props->insn_string="lf.madd.s"; insn_props->insn_index=58; break; case 0x8: insn_props->insn_string="lf.sfeq.s"; insn_props->insn_index=59; break; case 0x9: insn_props->insn_string="lf.sfne.s"; insn_props->insn_index=60; break; case 0xa: insn_props->insn_string="lf.sfgt.s"; insn_props->insn_index=61; break; case 0xb: insn_props->insn_string="lf.sfge.s"; insn_props->insn_index=62; break; case 0xc: insn_props->insn_string="lf.sflt.s"; insn_props->insn_index=63; break; case 0xd: insn_props->insn_string="lf.sfle.s"; insn_props->insn_index=64; break; default: printf("Unknown lf.xxx.s op (0x%x)", insn_or1k_opcode_0x32_get_op_lo(insn)); break; } break; case 0x1: switch(insn_or1k_opcode_0x32_get_op_lo(insn)) { case 0x0: insn_props->insn_string="lf.add.d"; insn_props->insn_index=65; break; case 0x1: insn_props->insn_string="lf.sub.d"; insn_props->insn_index=66; break; case 0x2: insn_props->insn_string="lf.mul.d"; insn_props->insn_index=67; break; case 0x3: insn_props->insn_string="lf.div.d"; insn_props->insn_index=68; break; case 0x4: insn_props->insn_string="lf.itof.d"; insn_props->insn_index=69; break; case 0x5: insn_props->insn_string="lf.ftoi.d"; insn_props->insn_index=70; break; case 0x6: insn_props->insn_string="lf.rem.d"; insn_props->insn_index=71; break; case 0x7: insn_props->insn_string="lf.madd.d"; insn_props->insn_index=72; break; case 0x8: insn_props->insn_string="lf.sfeq.d"; insn_props->insn_index=73; break; case 0x9: insn_props->insn_string="lf.sfne.d"; insn_props->insn_index=74; break; case 0xa: insn_props->insn_string="lf.sfgt.d"; insn_props->insn_index=75; break; case 0xb: insn_props->insn_string="lf.sfge.d"; insn_props->insn_index=76; break; case 0xc: insn_props->insn_string="lf.sflt.d"; insn_props->insn_index=77; break; case 0xd: insn_props->insn_string="lf.sfle.d"; insn_props->insn_index=78; break; default: printf("Unknown lf.xxx.d op (0x%x)", insn_or1k_opcode_0x32_get_op_lo(insn)); break; } break; case 0xd: insn_props->insn_string="lf.cust1.s"; insn_props->insn_index=79; break; case 0xe: insn_props->insn_string="lf.cust1.d"; insn_props->insn_index=80; break; default: printf("Unknown lf.xxx opcode hi (0x%x)", insn_or1k_opcode_0x32_get_op_hi(insn)); return 1; break; } break; case 0x34: insn_props->insn_string="l.sd"; insn_props->insn_index=81; break; case 0x35: insn_props->insn_string="l.sw"; insn_props->insn_index=82; break; case 0x36: insn_props->insn_string="l.sb"; insn_props->insn_index=83; break; case 0x37: insn_props->insn_string="l.sh"; insn_props->insn_index=84; break; case 0x38: insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_rB = 1; switch(insn_or1k_opcode_0x38_get_op_lo(insn)) { case 0x0: insn_props->insn_string="l.add"; insn_props->insn_index=85; break; case 0x1: insn_props->insn_string="l.addc"; insn_props->insn_index=86; break; case 0x2: insn_props->insn_string="l.sub"; insn_props->insn_index=87; break; case 0x3: insn_props->insn_string="l.and"; insn_props->insn_index=88; break; case 0x4: insn_props->insn_string="l.or"; insn_props->insn_index=89; break; case 0x5: insn_props->insn_string="l.xor"; insn_props->insn_index=90; break; case 0x6: insn_props->insn_string="l.mul"; insn_props->insn_index=91; break; case 0x8: switch (insn_or1k_opcode_0x38_get_op_hi_4bit(insn)) { case 0x0: insn_props->insn_string="l.sll"; insn_props->insn_index=92; break; case 0x1: insn_props->insn_string="l.srl"; insn_props->insn_index=93; break; case 0x2: insn_props->insn_string="l.sra"; insn_props->insn_index=94; break; case 0x3: insn_props->insn_string="l.ror"; insn_props->insn_index=95; break; default: printf("Unknown ALU op 0x8 hi op (0x%x)", insn_or1k_opcode_0x38_get_op_hi_4bit(insn)); return 1; break; } break; case 0x9: insn_props->insn_string="l.div"; insn_props->insn_index=96; break; case 0xa: insn_props->insn_string="l.divu"; insn_props->insn_index=97; break; case 0xb: insn_props->insn_string="l.mulu"; insn_props->insn_index=98; break; case 0xc: switch(insn_or1k_opcode_0x38_get_op_hi_4bit(insn)) { case 0x0: insn_props->insn_string="l.exths"; insn_props->insn_index=99; break; case 0x1: insn_props->insn_string="l.extbs"; insn_props->insn_index=100; break; case 0x2: insn_props->insn_string="l.exthz"; insn_props->insn_index=101; break; case 0x3: insn_props->insn_string="l.extbz"; insn_props->insn_index=102; break; } insn_props->has_rB = 0; break; case 0xd: insn_props->insn_string="l.extws"; insn_props->insn_index=103; insn_props->has_rB = 0; break; case 0xe: insn_props->insn_string="l.cmov"; insn_props->insn_index=104; break; case 0xf: if (insn_or1k_opcode_0x38_get_op_hi_2bit(insn) & 0x1) { insn_props->insn_string="l.fl1"; insn_props->insn_index=105; } else { insn_props->insn_string="l.ff1"; insn_props->insn_index=106; } insn_props->has_rB = 0; break; default: printf("Unknown ALU lo op (0x%x)", insn_or1k_opcode_0x38_get_op_lo(insn)); return 1; break; } break; case 0x39: insn_props->has_rA = 1; insn_props->has_rB = 1; switch (insn_or1k_opcode_0x39_get_op(insn)) { case 0x0: insn_props->insn_string="l.sfeq"; insn_props->insn_index=107; break; case 0x1: insn_props->insn_string="l.sfne"; insn_props->insn_index=108; break; case 0x2: insn_props->insn_string="l.sfgtu"; insn_props->insn_index=109; break; case 0x3: insn_props->insn_string="l.sfgeu"; insn_props->insn_index=110; break; case 0x4: insn_props->insn_string="l.sfltu"; insn_props->insn_index=111; break; case 0x5: insn_props->insn_string="l.sfleu"; insn_props->insn_index=112; break; case 0xa: insn_props->insn_string="l.sfgts"; insn_props->insn_index=113; break; case 0xb: insn_props->insn_string="l.sfges"; insn_props->insn_index=114; break; case 0xc: insn_props->insn_string="l.sflts"; insn_props->insn_index=115; break; case 0xd: insn_props->insn_string="l.sfles"; insn_props->insn_index=116; break; default: printf("Unknown opcode for l.sfxxx opcode (0x%x)", insn_or1k_opcode_0x39_get_op(insn)); return 1; break; } break; default: printf("Unknown opcode 0x%x",insn_or1k_opcode(insn)); return 1; break; } return 0; } void or1k_32_collect_stats(uint32_t insn, struct or1k_32_instruction_properties * insn_props) { // Add this instruction's occurance to our data insn_lists_add(insn, insn_props); } struct or1k_value_list { #define OR1K_VALUE_MAX_ENTRIES 64 int count; // [value][occurances_of_value] int32_t values[OR1K_VALUE_MAX_ENTRIES][2]; }; // Function to add entry to, or increment incidences of, value in the value list void or1k_add_in_list(struct or1k_value_list * list, int32_t value) { int i; // See if it's already in the list i=list->count; while(i) { i--; if(list->values[i][0] == value) { (list->values[i][1])++; return; } } if (list->count < OR1K_VALUE_MAX_ENTRIES) { // Not found, add it to the list list->values[(list->count)][0] = value; list->values[(list->count)][1] = 1; list->count++; } } struct or1k_insn_info { char* insn_string; int count; int has_branchtarg; struct or1k_value_list branch_info; int has_imm; struct or1k_value_list imm_info; int has_rD; int rD_use_freq[32]; int has_rA; int rA_use_freq[32]; int has_rB; int rB_use_freq[32]; // Set maximum instructions in a row we'll keep track of, starting at pairs #define OR1K_MAX_GROUPINGS_ANALYSIS 4 #define OR1K_MAX_ENTRIES_PER_GROUP 1000 // Format of grouping data: // // 1st dimension: A list for each n-tuple group we're keeping track of // (starting at pairs of instructions) // // 2nd dimension: Stores the list entries for the 1st dimension-tuple // grouping. The number in [x][0][0] is the number of entries in the list so // far, beginning at 0. The actual entries with data for grouping x start at // [x][1][], where that entry holds the 1st x+2-tuple grouping information // (eg. at x=0, [0][1][] is the first entry for/ pair instruction // information, x=1, is for triples, x=2 quadruples, etc) // // 3rd dimension: Store up to x+2 instruction indexes (where x is the first // dimension index, meaning this particular data is for a (x+2)-tuple set) // and then a frequency count for this set (in index (x+2) of the third // dimension array). Note we will have the index for the instruction this // struct corresponds to in [x][n][(x+2)-1], which seems redundant, but can // help processing later on. // // Note that we will have empty entries in the third dimension arrays for all // but the last in the list of n-tuples. This is to save doing tricky naming // defines and, in the future, if we would like to analyse sets that are // bigger or smaller, hopefully all we need to do is change a single define. // int groupings[OR1K_MAX_GROUPINGS_ANALYSIS][OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1]; }; // This number should correspond to the maximum insn_index we assign in the // analyse function #define OR1K_32_MAX_INSNS 117 struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS]; // List management/analysis functions - accessed through insn_lists() set of // functions // Variable to keep track of unique instructions we have int num_setup_insns; int num_seen_insns; void or1k_32_insn_lists_init(void) { num_setup_insns = 0; num_seen_insns = 0; // Clear the pointer array so we can tell if things are used or not memset(or1k_32_insns, '\0', sizeof(struct or1k_insn_info *)*OR1K_32_MAX_INSNS); } // Alloc struct and put it into the list void or1k_32_insn_lists_init_insn(uint32_t insn, struct or1k_32_instruction_properties *insn_props) { // Add an instruction in or1k_32_insns[num_unique_instructions]; // use calloc() so it clears it all first (hopefully!).. assumption! struct or1k_insn_info * new_insn = (struct or1k_insn_info *) calloc (sizeof(struct or1k_insn_info), 1); // Copy the string pointer new_insn->insn_string = insn_props->insn_string, // Install the pointer for this newly allocated struct in its corresponding // index, as set when we decode the instruction or1k_32_insns[insn_props->insn_index] = new_insn; // Increment number of instructions we have set up num_setup_insns++; // Debugging: //printf("Adding %dth instruction - %s\n", //num_setup_insns, new_insn->insn_string); } // Add stats for this instruction void or1k_32_insn_lists_add(uint32_t insn, struct or1k_32_instruction_properties *insn_props) { // Check if the entry for this instruction has been setup yet if (or1k_32_insns[insn_props->insn_index] == NULL) { // Here we allocate space for the instruction's stats or1k_32_insn_lists_init_insn(insn, insn_props); } // Increment occurance count ((or1k_32_insns[insn_props->insn_index])->count)++; // Add branch target value information, if instruction has it if (insn_props->has_branchtarg) { (or1k_32_insns[insn_props->insn_index])->has_branchtarg = 1; or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->branch_info), (int32_t)insn_or1k_opcode_0x03_get_branchoff(insn)); } // Add immediate value if it's got one if (insn_props->has_imm) { (or1k_32_insns[insn_props->insn_index])->has_imm = 1; or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->imm_info), (int32_t)insn_or1k_32_imm(insn)); } // Add split immediate value if it's got one if (insn_props->has_split_imm) { (or1k_32_insns[insn_props->insn_index])->has_imm = 1; or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->imm_info), (int32_t)insn_or1k_32_split_imm(insn)); } // Increment count of use for particular rD if (insn_props->has_rD) { (or1k_32_insns[insn_props->insn_index])->has_rD = 1; ((or1k_32_insns[insn_props->insn_index])->rD_use_freq[insn_or1k_32_rD(insn)])++; } // Increment count of use for particular rA if (insn_props->has_rA) { (or1k_32_insns[insn_props->insn_index])->has_rA = 1; ((or1k_32_insns[insn_props->insn_index])->rA_use_freq[insn_or1k_32_rA(insn)])++; } // Increment count of use for particular rB if (insn_props->has_rB) { (or1k_32_insns[insn_props->insn_index])->has_rB = 1; ((or1k_32_insns[insn_props->insn_index])->rB_use_freq[insn_or1k_32_rB(insn)])++; } // TODO: n-tuple groupings stats recording here! // Finished adding to stats for this instruction // Increment overall instructions "seen" counter num_seen_insns++; } // Free up all added instruction statistic tracking structs void or1k_32_insn_lists_free(void) { // Free all entries we m/calloc()'d int insn_index; for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++) { if (or1k_32_insns[insn_index] != NULL) free(or1k_32_insns[insn_index]); } } #define DISPLAY_STRING //#define DISPLAY_CSV void or1k_32_most_freq_insn(FILE * stream) { // Print out most frequent instruction int i, largest, largest_index; int instructions_to_print = num_setup_insns; while (instructions_to_print) { --instructions_to_print; largest=0; // Go through the list, find the largest, print it, eliminate it for(i=0;i<OR1K_32_MAX_INSNS;i++) if (or1k_32_insns[i]!=NULL){ if(((or1k_32_insns[i])->count) > largest) { largest = ((or1k_32_insns[i])->count); largest_index = i; } } fprintf(stream, #ifdef DISPLAY_STRING "Insn:\t%s\t\tCount:\t\t%d\t(%f%%)\n", #endif #ifdef DISPLAY_CSV // CSV format - "opcode string",frequency,percentage "\"%s\",%d,%f\n", #endif ((or1k_32_insns[largest_index])->insn_string), ((or1k_32_insns[largest_index])->count), (float)(((float)((or1k_32_insns[largest_index])->count))/ ((float)num_seen_insns))*100.f); ((or1k_32_insns[largest_index])->count) = -1; // Eliminate this one } } // Print out top x of each kept statistic for the requested instruction void or1k_32_insn_top_x(struct or1k_insn_info *insn_info, FILE * stream, int max_stats) { int i, j, largest, largest_i; fprintf(stream, "Insn: \"%s\" statistics (%d times (%f%%)):\n", insn_info->insn_string, insn_info->count, (float)(((float)((insn_info)->count))/ ((float)num_seen_insns))*100.f ); // Start dumping applicable stats // Print out top max_stats branch targets if (insn_info->has_branchtarg) { fprintf(stream,"Branch values:\n"); i = 0; while(i<insn_info->branch_info.count && i < max_stats) { largest_i=0; for(j=0;j<insn_info->branch_info.count;j++) largest_i = (insn_info->branch_info.values[j][1] > insn_info->branch_info.values[largest_i][1]) ? j : largest_i; // largest_i has index of most frequent value fprintf(stream, "value:\t0x%x\tcount:\t%d\n", insn_info->branch_info.values[largest_i][0], insn_info->branch_info.values[largest_i][1]); insn_info->branch_info.values[largest_i][1] = -1; // clear this one i++; } } if (insn_info->has_imm) { fprintf(stream,"Immediate values:\n"); i = 0; while(i<insn_info->imm_info.count && i < max_stats) { largest_i=0; for(j=0;j<insn_info->imm_info.count;j++) largest_i = (insn_info->imm_info.values[j][1] > insn_info->imm_info.values[largest_i][1]) ? j : largest_i; // largest_i has index of most frequent value fprintf(stream, "value:\t0x%x\tcount:\t%d\n", insn_info->imm_info.values[largest_i][0], insn_info->imm_info.values[largest_i][1]); insn_info->imm_info.values[largest_i][1] = -1; // clear this one i++; } } if (insn_info->has_rD) { fprintf(stream,"rD usage:\n"); i = 0; while(i<32 && i < max_stats) { largest_i=0; for(j=0;j<32;j++) largest_i = (insn_info->rD_use_freq[j] > insn_info->rD_use_freq[largest_i]) ? j : largest_i; // No more interesting numbers if (insn_info->rD_use_freq[largest_i] == 0) break; // largest_i has index of most frequent value fprintf(stream, "r%d\tcount:\t%d\n", largest_i, insn_info->rD_use_freq[largest_i]); insn_info->rD_use_freq[largest_i] = -1; // clear this one i++; } } if (insn_info->has_rA) { fprintf(stream,"rA usage:\n"); i = 0; while(i<32 && i < max_stats) { largest_i=0; for(j=0;j<32;j++) largest_i = (insn_info->rA_use_freq[j] > insn_info->rA_use_freq[largest_i]) ? j : largest_i; // No more interesting numbers if (insn_info->rA_use_freq[largest_i] == 0) break; // largest_i has index of most frequent value fprintf(stream, "r%d\tcount:\t%d\n", largest_i, insn_info->rA_use_freq[largest_i]); insn_info->rA_use_freq[largest_i] = -1; // clear this one i++; } } if (insn_info->has_rB) { fprintf(stream,"rB usage:\n"); i = 0; while(i<32 && i < max_stats) { largest_i=0; for(j=0;j<32;j++) largest_i = (insn_info->rB_use_freq[j] > insn_info->rB_use_freq[largest_i]) ? j : largest_i; // No more interesting numbers if (insn_info->rB_use_freq[largest_i] == 0) break; // largest_i has index of most frequent value fprintf(stream, "r%d\tcount:\t%d\n", largest_i, insn_info->rB_use_freq[largest_i]); insn_info->rB_use_freq[largest_i] = -1; // clear this one i++; } } } void or1k_32_generate_stats(FILE * stream) { // Generate some useful things fprintf(stream, "Analysis output:\n"); // // Print out all stats for every instruction we saw! int insn_index; for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++) { if (or1k_32_insns[insn_index] != NULL) or1k_32_insn_top_x(or1k_32_insns[insn_index],stream,10); } // Do most frequent instruction analysis -- note this trashes instruction // frequency count - should be fixed or1k_32_most_freq_insn(stream); }
Go to most recent revision | Compare with Previous | Blame | View Log