URL
https://opencores.org/ocsvn/or2k/or2k/trunk
Subversion Repositories or2k
[/] [or2k/] [trunk/] [analysis-bin/] [insnanalysis/] [or1k-32-insn.c] - Rev 16
Go to most recent revision | Compare with Previous | Blame | View Log
#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->has_jumptarg = 1; break; case 0x01: insn_props->insn_string="l.jal"; insn_props->has_jumptarg = 1; break; case 0x03: insn_props->insn_string="l.bnf"; insn_props->has_branchtarg = 1; break; case 0x04: insn_props->insn_string="l.bf"; insn_props->has_branchtarg = 1; break; case 0x05: insn_props->insn_string="l.nop"; break; case 0x06: if((insn_or1k_opcode_0x06_get_id(insn))) insn_props->insn_string="l.macrc"; else { insn_props->insn_string="l.movhi"; 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"; break; case 0x2: insn_props->insn_string="l.trap"; break; case 0x4: insn_props->insn_string="l.msync"; break; case 0x5: insn_props->insn_string="l.psync"; break; case 0x6: insn_props->insn_string="l.csync"; 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"; 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"); } 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"); } 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"); } 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"); } 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"); } 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"); } 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"); } break; case 0xc: break; case 0xd: break; case 0xe: break; case 0xf: break; default: printf("Unknown lv.xxx insn hi op"); break; } break; case 0x11: insn_props->insn_string="l.jr"; insn_props->has_rB = 1; break; case 0x12: insn_props->insn_string="l.jalr"; insn_props->has_rB = 1; break; case 0x13: insn_props->insn_string="l.maci"; break; case 0x1c: insn_props->insn_string="l.cust1"; break; case 0x1d: insn_props->insn_string="l.cust2"; break; case 0x1e: insn_props->insn_string="l.cust3"; break; case 0x1f: insn_props->insn_string="l.cust4"; break; case 0x20: insn_props->insn_string="l.ld"; 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->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x22: insn_props->insn_string="l.lws"; 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->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x24: insn_props->insn_string="l.lbs"; 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->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x26: insn_props->insn_string="l.lhs"; 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->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x28: insn_props->insn_string="l.addic"; 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->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x2a: insn_props->insn_string="l.ori"; 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->has_rD = 1; insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x2c: insn_props->insn_string="l.muli"; 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->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"; break; case 0x1: insn_props->insn_string="l.srli"; break; case 0x2: insn_props->insn_string="l.srai"; break; case 0x3: insn_props->insn_string="l.rori"; break; default: printf("Unknown shift op (0x%x)", insn_or1k_opcode_0x2e_get_op(insn)); break; } break; case 0x2f: switch(insn_or1k_opcode_0x2f_get_op(insn)) { case 0x0: insn_props->insn_string="l.sfeqi"; break; case 0x1: insn_props->insn_string="l.sfnei"; break; case 0x2: insn_props->insn_string="l.sfgtui"; break; case 0x3: insn_props->insn_string="l.sfgeui"; break; case 0x4: insn_props->insn_string="l.sfltui"; break; case 0x5: insn_props->insn_string="l.sfleui"; break; case 0xa: insn_props->insn_string="l.sfgtsi"; break; case 0xb: insn_props->insn_string="l.sfgesi"; break; case 0xc: insn_props->insn_string="l.sfltsi"; break; case 0xd: insn_props->insn_string="l.sflesi"; break; default: printf("Unknown set flag op (0x%x)", insn_or1k_opcode_0x2f_get_op(insn)); break; } insn_props->has_rA = 1; insn_props->has_imm = 1; break; case 0x30: insn_props->insn_string="l.mtspr"; break; case 0x31: switch (insn_or1k_opcode_0x31_get_op(insn)) { case 0x1: insn_props->insn_string="l.mac"; break; case 0x2: insn_props->insn_string="l.msb"; break; default: printf("Unknown mac op (0x%x)", insn_or1k_opcode_0x31_get_op(insn)); } 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"; break; case 0x1: insn_props->insn_string="lf.sub.s"; break; case 0x2: insn_props->insn_string="lf.mul.s"; break; case 0x3: insn_props->insn_string="lf.div.s"; break; case 0x4: insn_props->insn_string="lf.itof.s"; break; case 0x5: insn_props->insn_string="lf.ftoi.s"; break; case 0x6: insn_props->insn_string="lf.rem.s"; break; case 0x7: insn_props->insn_string="lf.madd.s"; break; case 0x8: insn_props->insn_string="lf.sfeq.s"; break; case 0x9: insn_props->insn_string="lf.sfne.s"; break; case 0xa: insn_props->insn_string="lf.sfgt.s"; break; case 0xb: insn_props->insn_string="lf.sfge.s"; break; case 0xc: insn_props->insn_string="lf.sflt.s"; break; case 0xd: insn_props->insn_string="lf.sfle.s"; 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"; break; case 0x1: insn_props->insn_string="lf.sub.d"; break; case 0x2: insn_props->insn_string="lf.mul.d"; break; case 0x3: insn_props->insn_string="lf.div.d"; break; case 0x4: insn_props->insn_string="lf.itof.d"; break; case 0x5: insn_props->insn_string="lf.ftoi.d"; break; case 0x6: insn_props->insn_string="lf.rem.d"; break; case 0x7: insn_props->insn_string="lf.madd.d"; break; case 0x8: insn_props->insn_string="lf.sfeq.d"; break; case 0x9: insn_props->insn_string="lf.sfne.d"; break; case 0xa: insn_props->insn_string="lf.sfgt.d"; break; case 0xb: insn_props->insn_string="lf.sfge.d"; break; case 0xc: insn_props->insn_string="lf.sflt.d"; break; case 0xd: insn_props->insn_string="lf.sfle.d"; 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"; break; case 0xe: insn_props->insn_string="lf.cust1.d"; break; default: printf("Unknown lf.xxx opcode hi (0x%x)", insn_or1k_opcode_0x32_get_op_hi(insn)); break; } break; case 0x34: insn_props->insn_string="l.sd"; break; case 0x35: insn_props->insn_string="l.sw"; break; case 0x36: insn_props->insn_string="l.sb"; break; case 0x37: insn_props->insn_string="l.sh"; break; case 0x38: switch(insn_or1k_opcode_0x38_get_op_lo(insn)) { insn_props->has_rD = 1; insn_props->has_rA = 1; insn_props->has_rB = 1; case 0x0: insn_props->insn_string="l.add"; break; case 0x1: insn_props->insn_string="l.addc"; break; case 0x2: insn_props->insn_string="l.sub"; break; case 0x3: insn_props->insn_string="l.and"; break; case 0x4: insn_props->insn_string="l.or"; break; case 0x5: insn_props->insn_string="l.xor"; break; case 0x6: insn_props->insn_string="l.mul"; break; case 0x8: switch (insn_or1k_opcode_0x38_get_op_hi_4bit(insn)) { case 0x0: insn_props->insn_string="l.sll"; break; case 0x1: insn_props->insn_string="l.srl"; break; case 0x2: insn_props->insn_string="l.sra"; break; case 0x3: insn_props->insn_string="l.ror"; break; default: printf("Unknown ALU op 0x8 hi op (0x%x)", insn_or1k_opcode_0x38_get_op_hi_4bit(insn)); break; } break; case 0x9: insn_props->insn_string="l.div"; break; case 0xa: insn_props->insn_string="l.divu"; break; case 0xb: insn_props->insn_string="l.mulu"; break; case 0xc: switch(insn_or1k_opcode_0x38_get_op_hi_4bit(insn)) { case 0x0: insn_props->insn_string="l.exths"; break; case 0x1: insn_props->insn_string="l.extbs"; break; case 0x2: insn_props->insn_string="l.exthz"; break; case 0x3: insn_props->insn_string="l.extbz"; break; } insn_props->has_rB = 0; break; case 0xd: insn_props->insn_string="l.extws"; insn_props->has_rB = 0; break; case 0xe: insn_props->insn_string="l.cmov"; break; case 0xf: if (insn_or1k_opcode_0x38_get_op_hi_2bit(insn) & 0x1) insn_props->insn_string="l.fl1"; else insn_props->insn_string="l.ff1"; insn_props->has_rB = 0; break; default: printf("Unknown ALU lo op (0x%x)", insn_or1k_opcode_0x38_get_op_lo(insn)); break; } break; case 0x39: switch (insn_or1k_opcode_0x39_get_op(insn)) { insn_props->has_rA = 0; insn_props->has_rB = 0; case 0x0: insn_props->insn_string="l.sfeq"; break; case 0x1: insn_props->insn_string="l.sfne"; break; case 0x2: insn_props->insn_string="l.sfgtu"; break; case 0x3: insn_props->insn_string="l.sfgeu"; break; case 0x4: insn_props->insn_string="l.sfltu"; break; case 0x5: insn_props->insn_string="l.sfleu"; break; case 0xa: insn_props->insn_string="l.sfgts"; break; case 0xb: insn_props->insn_string="l.sfges"; break; case 0xc: insn_props->insn_string="l.sflts"; break; case 0xd: insn_props->insn_string="l.sfles"; break; default: printf("Unknown opcode for l.sfxxx opcode (0x%x)", insn_or1k_opcode_0x39_get_op(insn)); 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) { // First calculate frequency int index = insn_lists_check(insn, insn_props); // Create new entry in list if (index == IS_UNIQUE) index = insn_lists_add_unique_insn(insn, insn_props); // Now count it insn_lists_add(index, insn, insn_props); } struct or1k_value_list { #define OR1K_VALUE_MAX_ENTRIES 64 int count; // [value][occurances_of_value] int values[OR1K_VALUE_MAX_ENTRIES][2]; }; 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]; }; #define OR1K_32_MAX_INSNS 120 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_unique_insns; int num_seen_insns; void or1k_32_insn_lists_init(void) { num_unique_insns = 0; num_seen_insns = 0; } // List management/analysis functions int or1k_32_insn_lists_check(uint32_t insn, struct or1k_32_instruction_properties *insn_props) { int num_to_check = num_unique_insns; int insn_strlen = strlen(insn_props->insn_string); while (num_to_check) { --num_to_check; if ((strncmp(insn_props->insn_string, or1k_32_insns[num_to_check]->insn_string, insn_strlen) == 0) && (insn_strlen == strlen(or1k_32_insns[num_to_check]->insn_string))) { // Found match by string return num_to_check; } } return IS_UNIQUE; } // Add a unique instruction int or1k_32_insn_lists_add_unique_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); // Calloc() space for the string new_insn->insn_string = (char *) calloc(strlen(insn_props->insn_string), 1); // Copy in the instruction string strncpy(new_insn->insn_string, insn_props->insn_string, strlen(insn_props->insn_string)); // Install the pointer for this new instruction in the list or1k_32_insns[num_unique_insns] = new_insn;; // Increment number of instructions we have num_unique_insns++; // Return index of newly created instruction return (num_unique_insns - 1); } // Add to, or increment incidences of, value in the value list void or1k_add_in_list(struct or1k_value_list * list, int 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; } } // Not found, add it to the list list->values[(list->count)][0] = value; list->values[(list->count)][1] = 1; } // Add stats for this instruction void or1k_32_insn_lists_add(int index, uint32_t insn, struct or1k_32_instruction_properties *insn_props) { // Add stats for this instruction // Increment count ((or1k_32_insns[index])->count)++; // Add branch target value information, if instruction has it if (insn_props->has_branchtarg) { (or1k_32_insns[index])->has_branchtarg = 1; or1k_add_in_list(&((or1k_32_insns[index])->branch_info), (int)insn_or1k_opcode_0x03_get_branchoff(insn)); } // Add immediate value if it's got one if (insn_props->has_imm) { (or1k_32_insns[index])->has_imm = 1; or1k_add_in_list(&((or1k_32_insns[index])->imm_info), (int)insn_or1k_32_imm(insn)); } // Add split immediate value if it's got one if (insn_props->has_split_imm) { (or1k_32_insns[index])->has_imm = 1; or1k_add_in_list(&((or1k_32_insns[index])->imm_info), (int)insn_or1k_32_split_imm(insn)); } // Increment count of use for particular rD if (insn_props->has_rD) { (or1k_32_insns[index])->has_rD = 1; ((or1k_32_insns[index])->rD_use_freq[insn_or1k_32_rD(insn)])++; } // Increment count of use for particular rA if (insn_props->has_rA) { (or1k_32_insns[index])->has_rA = 1; ((or1k_32_insns[index])->rA_use_freq[insn_or1k_32_rA(insn)])++; } // Increment count of use for particular rB if (insn_props->has_rB) { (or1k_32_insns[index])->has_rB = 1; ((or1k_32_insns[index])->rB_use_freq[insn_or1k_32_rB(insn)])++; } // 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) { while (num_unique_insns) { num_unique_insns--; free(or1k_32_insns[num_unique_insns]); } }
Go to most recent revision | Compare with Previous | Blame | View Log