/*
|
/*
|
Or1K instruction set-specific decoding and analysis functions.
|
Or1K instruction set-specific decoding and analysis functions.
|
|
|
Julius Baxter, julius.baxter@orsoc.se
|
Julius Baxter, julius.baxter@orsoc.se
|
|
|
*/
|
*/
|
|
|
|
|
#include "stdio.h"
|
#include "stdio.h"
|
#include "stdint.h"
|
#include "stdint.h"
|
#include "stdlib.h"
|
#include "stdlib.h"
|
#include "string.h"
|
#include "string.h"
|
#include "assert.h"
|
#include "assert.h"
|
#include "or1k-32-insn.h"
|
#include "or1k-32-insn.h"
|
|
|
// These should also be in insnanalysis.h insnanalysis.h
|
// Define the appropriate instruction type, and instruction_properties type
|
|
// These should also be defined in insnanalysis.h
|
typedef uint32_t instruction;
|
typedef uint32_t instruction;
|
typedef struct or1k_32_instruction_properties instruction_properties ;
|
typedef struct or1k_32_instruction_properties instruction_properties ;
|
|
|
#include "insn-lists.h"
|
#include "insn-lists.h"
|
|
|
|
// Enable debug printf'ing straight to stdout -- will be a LOT of output
|
#define DEBUG_PRINT 0
|
#define DEBUG_PRINT 0
|
|
|
|
// Choose the output format, uncomment only one
|
|
//#define DISPLAY_STRING
|
|
#define DISPLAY_CSV
|
|
|
|
|
// Variable to keep track of unique instructions we have
|
// Variable to keep track of unique instructions we have
|
int num_setup_insns;
|
int num_setup_insns;
|
int num_seen_insns;
|
int num_seen_insns;
|
|
|
struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS];
|
struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS];
|
|
|
// Keep enough instructions required to do the maximum n-tuple set
|
// Keep enough instructions required to do the maximum n-tuple set
|
// analysis.
|
// analysis.
|
int or1k_32_recent_insns[OR1K_MAX_GROUPINGS_ANALYSIS];
|
int or1k_32_recent_insns[OR1K_MAX_GROUPINGS_ANALYSIS];
|
|
|
|
// Function to take the raw binary instruction, and configure the insn_props
|
|
// struct with the appropriate settings for that instruction (string, attributes
|
|
// etc.)
|
|
// TODO: vector instructions aren't picked up - but compiler never generates
|
|
// them, so not a big issue.
|
int or1k_32_analyse_insn(uint32_t insn,
|
int or1k_32_analyse_insn(uint32_t insn,
|
struct or1k_32_instruction_properties * insn_props)
|
struct or1k_32_instruction_properties * insn_props)
|
{
|
{
|
|
|
switch(insn_or1k_opcode(insn))
|
switch(insn_or1k_opcode(insn))
|
{
|
{
|
case 0x00:
|
case 0x00:
|
insn_props->insn_string="l.j";
|
insn_props->insn_string="l.j";
|
insn_props->insn_index=0;
|
insn_props->insn_index=0;
|
insn_props->has_jumptarg = 1;
|
insn_props->has_jumptarg = 1;
|
break;
|
break;
|
|
|
case 0x01:
|
case 0x01:
|
insn_props->insn_string="l.jal";
|
insn_props->insn_string="l.jal";
|
insn_props->insn_index=1;
|
insn_props->insn_index=1;
|
insn_props->has_jumptarg = 1;
|
insn_props->has_jumptarg = 1;
|
break;
|
break;
|
|
|
case 0x03:
|
case 0x03:
|
insn_props->insn_string="l.bnf";
|
insn_props->insn_string="l.bnf";
|
insn_props->insn_index=2;
|
insn_props->insn_index=2;
|
insn_props->has_branchtarg = 1;
|
insn_props->has_branchtarg = 1;
|
break;
|
break;
|
|
|
case 0x04:
|
case 0x04:
|
insn_props->insn_string="l.bf";
|
insn_props->insn_string="l.bf";
|
insn_props->insn_index=3;
|
insn_props->insn_index=3;
|
insn_props->has_branchtarg = 1;
|
insn_props->has_branchtarg = 1;
|
break;
|
break;
|
|
|
case 0x05:
|
case 0x05:
|
insn_props->insn_string="l.nop";
|
insn_props->insn_string="l.nop";
|
insn_props->insn_index=4;
|
insn_props->insn_index=4;
|
break;
|
break;
|
|
|
case 0x06:
|
case 0x06:
|
if((insn_or1k_opcode_0x06_get_id(insn)))
|
if((insn_or1k_opcode_0x06_get_id(insn)))
|
{
|
{
|
insn_props->insn_string="l.macrc";
|
insn_props->insn_string="l.macrc";
|
insn_props->insn_index=5;
|
insn_props->insn_index=5;
|
}
|
}
|
else
|
else
|
{
|
{
|
insn_props->insn_string="l.movhi";
|
insn_props->insn_string="l.movhi";
|
insn_props->insn_index=6;
|
insn_props->insn_index=6;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
}
|
}
|
|
|
break;
|
break;
|
|
|
case 0x08:
|
case 0x08:
|
|
|
switch(insn_or1k_opcode_0x08_get_id(insn))
|
switch(insn_or1k_opcode_0x08_get_id(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="l.sys";
|
insn_props->insn_string="l.sys";
|
insn_props->insn_index=7;
|
insn_props->insn_index=7;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="l.trap";
|
insn_props->insn_string="l.trap";
|
insn_props->insn_index=8;
|
insn_props->insn_index=8;
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
insn_props->insn_string="l.msync";
|
insn_props->insn_string="l.msync";
|
insn_props->insn_index=9;
|
insn_props->insn_index=9;
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
insn_props->insn_string="l.psync";
|
insn_props->insn_string="l.psync";
|
insn_props->insn_index=10;
|
insn_props->insn_index=10;
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
insn_props->insn_string="l.csync";
|
insn_props->insn_string="l.csync";
|
insn_props->insn_index=11;
|
insn_props->insn_index=11;
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown id (0x%x) in opcode 0x8",
|
printf("Unknown id (0x%x) in opcode 0x8",
|
insn_or1k_opcode_0x08_get_id(insn) );
|
insn_or1k_opcode_0x08_get_id(insn) );
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
case 0x09:
|
case 0x09:
|
insn_props->insn_string="l.rfe";
|
insn_props->insn_string="l.rfe";
|
insn_props->insn_index=12;
|
insn_props->insn_index=12;
|
break;
|
break;
|
|
|
case 0x0a:
|
case 0x0a:
|
switch(insn_or1k_opcode_0x0a_get_op_hi(insn))
|
switch(insn_or1k_opcode_0x0a_get_op_hi(insn))
|
{
|
{
|
case 0x1:
|
case 0x1:
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lv.all_xx insn");
|
printf("Unknown lv.all_xx insn");
|
return 1;
|
return 1;
|
}
|
}
|
case 0x2:
|
case 0x2:
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lv.any_xx insn");
|
printf("Unknown lv.any_xx insn");
|
return 1;
|
return 1;
|
}
|
}
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lv.add/and/avg_xx insn");
|
printf("Unknown lv.add/and/avg_xx insn");
|
return 1;
|
return 1;
|
}
|
}
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lv.cmp_xx insn");
|
printf("Unknown lv.cmp_xx insn");
|
return 1;
|
return 1;
|
}
|
}
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
{
|
{
|
case 0x4:
|
case 0x4:
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
break;
|
break;
|
case 0xc:
|
case 0xc:
|
break;
|
break;
|
case 0xd:
|
case 0xd:
|
break;
|
break;
|
case 0xe:
|
case 0xe:
|
break;
|
break;
|
case 0xf:
|
case 0xf:
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lv.alu_xx insn");
|
printf("Unknown lv.alu_xx insn");
|
return 1;
|
return 1;
|
}
|
}
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
break;
|
break;
|
case 0xc:
|
case 0xc:
|
break;
|
break;
|
case 0xd:
|
case 0xd:
|
break;
|
break;
|
case 0xe:
|
case 0xe:
|
break;
|
break;
|
case 0xf:
|
case 0xf:
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lv.pack_xx insn");
|
printf("Unknown lv.pack_xx insn");
|
return 1;
|
return 1;
|
}
|
}
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x0a_get_op_lo(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lv.sub/unpack/xor_xx insn");
|
printf("Unknown lv.sub/unpack/xor_xx insn");
|
return 1;
|
return 1;
|
}
|
}
|
break;
|
break;
|
case 0xc:
|
case 0xc:
|
break;
|
break;
|
case 0xd:
|
case 0xd:
|
break;
|
break;
|
case 0xe:
|
case 0xe:
|
break;
|
break;
|
case 0xf:
|
case 0xf:
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lv.xxx insn hi op");
|
printf("Unknown lv.xxx insn hi op");
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
case 0x11:
|
case 0x11:
|
insn_props->insn_string="l.jr";
|
insn_props->insn_string="l.jr";
|
insn_props->insn_index=13;
|
insn_props->insn_index=13;
|
insn_props->has_rB = 1;
|
insn_props->has_rB = 1;
|
break;
|
break;
|
|
|
case 0x12:
|
case 0x12:
|
insn_props->insn_string="l.jalr";
|
insn_props->insn_string="l.jalr";
|
insn_props->insn_index=14;
|
insn_props->insn_index=14;
|
insn_props->has_rB = 1;
|
insn_props->has_rB = 1;
|
break;
|
break;
|
|
|
case 0x13:
|
case 0x13:
|
insn_props->insn_string="l.maci";
|
insn_props->insn_string="l.maci";
|
insn_props->insn_index=15;
|
insn_props->insn_index=15;
|
break;
|
break;
|
|
|
case 0x1c:
|
case 0x1c:
|
insn_props->insn_string="l.cust1";
|
insn_props->insn_string="l.cust1";
|
insn_props->insn_index=16;
|
insn_props->insn_index=16;
|
break;
|
break;
|
|
|
case 0x1d:
|
case 0x1d:
|
insn_props->insn_string="l.cust2";
|
insn_props->insn_string="l.cust2";
|
insn_props->insn_index=17;
|
insn_props->insn_index=17;
|
break;
|
break;
|
|
|
case 0x1e:
|
case 0x1e:
|
insn_props->insn_string="l.cust3";
|
insn_props->insn_string="l.cust3";
|
insn_props->insn_index=18;
|
insn_props->insn_index=18;
|
break;
|
break;
|
|
|
case 0x1f:
|
case 0x1f:
|
insn_props->insn_string="l.cust4";
|
insn_props->insn_string="l.cust4";
|
insn_props->insn_index=19;
|
insn_props->insn_index=19;
|
break;
|
break;
|
|
|
case 0x20:
|
case 0x20:
|
insn_props->insn_string="l.ld";
|
insn_props->insn_string="l.ld";
|
insn_props->insn_index=20;
|
insn_props->insn_index=20;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x21:
|
case 0x21:
|
insn_props->insn_string="l.lwz";
|
insn_props->insn_string="l.lwz";
|
insn_props->insn_index=21;
|
insn_props->insn_index=21;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x22:
|
case 0x22:
|
insn_props->insn_string="l.lws";
|
insn_props->insn_string="l.lws";
|
insn_props->insn_index=22;
|
insn_props->insn_index=22;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x23:
|
case 0x23:
|
insn_props->insn_string="l.lbz";
|
insn_props->insn_string="l.lbz";
|
insn_props->insn_index=23;
|
insn_props->insn_index=23;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x24:
|
case 0x24:
|
insn_props->insn_string="l.lbs";
|
insn_props->insn_string="l.lbs";
|
insn_props->insn_index=24;
|
insn_props->insn_index=24;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x25:
|
case 0x25:
|
insn_props->insn_string="l.lhz";
|
insn_props->insn_string="l.lhz";
|
insn_props->insn_index=25;
|
insn_props->insn_index=25;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x26:
|
case 0x26:
|
insn_props->insn_string="l.lhs";
|
insn_props->insn_string="l.lhs";
|
insn_props->insn_index=26;
|
insn_props->insn_index=26;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
|
|
case 0x27:
|
case 0x27:
|
insn_props->insn_string="l.addi";
|
insn_props->insn_string="l.addi";
|
insn_props->insn_index=27;
|
insn_props->insn_index=27;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x28:
|
case 0x28:
|
insn_props->insn_string="l.addic";
|
insn_props->insn_string="l.addic";
|
insn_props->insn_index=28;
|
insn_props->insn_index=28;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x29:
|
case 0x29:
|
insn_props->insn_string="l.andi";
|
insn_props->insn_string="l.andi";
|
insn_props->insn_index=29;
|
insn_props->insn_index=29;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x2a:
|
case 0x2a:
|
insn_props->insn_string="l.ori";
|
insn_props->insn_string="l.ori";
|
insn_props->insn_index=30;
|
insn_props->insn_index=30;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x2b:
|
case 0x2b:
|
insn_props->insn_string="l.xori";
|
insn_props->insn_string="l.xori";
|
insn_props->insn_index=31;
|
insn_props->insn_index=31;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x2c:
|
case 0x2c:
|
insn_props->insn_string="l.muli";
|
insn_props->insn_string="l.muli";
|
insn_props->insn_index=32;
|
insn_props->insn_index=32;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x2d:
|
case 0x2d:
|
insn_props->insn_string="l.mfspr";
|
insn_props->insn_string="l.mfspr";
|
insn_props->insn_index=33;
|
insn_props->insn_index=33;
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
case 0x2e:
|
case 0x2e:
|
switch(insn_or1k_opcode_0x2e_get_op(insn))
|
switch(insn_or1k_opcode_0x2e_get_op(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="l.slli";
|
insn_props->insn_string="l.slli";
|
insn_props->insn_index=34;
|
insn_props->insn_index=34;
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
insn_props->insn_string="l.srli";
|
insn_props->insn_string="l.srli";
|
insn_props->insn_index=35;
|
insn_props->insn_index=35;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="l.srai";
|
insn_props->insn_string="l.srai";
|
insn_props->insn_index=36;
|
insn_props->insn_index=36;
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
insn_props->insn_string="l.rori";
|
insn_props->insn_string="l.rori";
|
insn_props->insn_index=37;
|
insn_props->insn_index=37;
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown shift op (0x%x)",
|
printf("Unknown shift op (0x%x)",
|
insn_or1k_opcode_0x2e_get_op(insn));
|
insn_or1k_opcode_0x2e_get_op(insn));
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
case 0x2f:
|
case 0x2f:
|
switch(insn_or1k_opcode_0x2f_get_op(insn))
|
switch(insn_or1k_opcode_0x2f_get_op(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="l.sfeqi";
|
insn_props->insn_string="l.sfeqi";
|
insn_props->insn_index=38;
|
insn_props->insn_index=38;
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
insn_props->insn_string="l.sfnei";
|
insn_props->insn_string="l.sfnei";
|
insn_props->insn_index=39;
|
insn_props->insn_index=39;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="l.sfgtui";
|
insn_props->insn_string="l.sfgtui";
|
insn_props->insn_index=40;
|
insn_props->insn_index=40;
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
insn_props->insn_string="l.sfgeui";
|
insn_props->insn_string="l.sfgeui";
|
insn_props->insn_index=41;
|
insn_props->insn_index=41;
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
insn_props->insn_string="l.sfltui";
|
insn_props->insn_string="l.sfltui";
|
insn_props->insn_index=42;
|
insn_props->insn_index=42;
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
insn_props->insn_string="l.sfleui";
|
insn_props->insn_string="l.sfleui";
|
insn_props->insn_index=43;
|
insn_props->insn_index=43;
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
insn_props->insn_string="l.sfgtsi";
|
insn_props->insn_string="l.sfgtsi";
|
insn_props->insn_index=44;
|
insn_props->insn_index=44;
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
insn_props->insn_string="l.sfgesi";
|
insn_props->insn_string="l.sfgesi";
|
insn_props->insn_index=45;
|
insn_props->insn_index=45;
|
break;
|
break;
|
case 0xc:
|
case 0xc:
|
insn_props->insn_string="l.sfltsi";
|
insn_props->insn_string="l.sfltsi";
|
insn_props->insn_index=46;
|
insn_props->insn_index=46;
|
break;
|
break;
|
case 0xd:
|
case 0xd:
|
insn_props->insn_string="l.sflesi";
|
insn_props->insn_string="l.sflesi";
|
insn_props->insn_index=47;
|
insn_props->insn_index=47;
|
break;
|
break;
|
|
|
default:
|
default:
|
printf("Unknown set flag op (0x%x)",
|
printf("Unknown set flag op (0x%x)",
|
insn_or1k_opcode_0x2f_get_op(insn));
|
insn_or1k_opcode_0x2f_get_op(insn));
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_imm = 1;
|
insn_props->has_imm = 1;
|
break;
|
break;
|
|
|
|
|
case 0x30:
|
case 0x30:
|
insn_props->insn_string="l.mtspr";
|
insn_props->insn_string="l.mtspr";
|
insn_props->insn_index=48;
|
insn_props->insn_index=48;
|
break;
|
break;
|
|
|
case 0x31:
|
case 0x31:
|
switch (insn_or1k_opcode_0x31_get_op(insn))
|
switch (insn_or1k_opcode_0x31_get_op(insn))
|
{
|
{
|
case 0x1:
|
case 0x1:
|
insn_props->insn_string="l.mac";
|
insn_props->insn_string="l.mac";
|
insn_props->insn_index=49;
|
insn_props->insn_index=49;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="l.msb";
|
insn_props->insn_string="l.msb";
|
insn_props->insn_index=50;
|
insn_props->insn_index=50;
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown mac op (0x%x)",
|
printf("Unknown mac op (0x%x)",
|
insn_or1k_opcode_0x31_get_op(insn));
|
insn_or1k_opcode_0x31_get_op(insn));
|
return 1;
|
return 1;
|
}
|
}
|
break;
|
break;
|
|
|
case 0x32:
|
case 0x32:
|
switch(insn_or1k_opcode_0x32_get_op_hi(insn))
|
switch(insn_or1k_opcode_0x32_get_op_hi(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
switch(insn_or1k_opcode_0x32_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x32_get_op_lo(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="lf.add.s";
|
insn_props->insn_string="lf.add.s";
|
insn_props->insn_index=51;
|
insn_props->insn_index=51;
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
insn_props->insn_string="lf.sub.s";
|
insn_props->insn_string="lf.sub.s";
|
insn_props->insn_index=52;
|
insn_props->insn_index=52;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="lf.mul.s";
|
insn_props->insn_string="lf.mul.s";
|
insn_props->insn_index=53;
|
insn_props->insn_index=53;
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
insn_props->insn_string="lf.div.s";
|
insn_props->insn_string="lf.div.s";
|
insn_props->insn_index=54;
|
insn_props->insn_index=54;
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
insn_props->insn_string="lf.itof.s";
|
insn_props->insn_string="lf.itof.s";
|
insn_props->insn_index=55;
|
insn_props->insn_index=55;
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
insn_props->insn_string="lf.ftoi.s";
|
insn_props->insn_string="lf.ftoi.s";
|
insn_props->insn_index=56;
|
insn_props->insn_index=56;
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
insn_props->insn_string="lf.rem.s";
|
insn_props->insn_string="lf.rem.s";
|
insn_props->insn_index=57;
|
insn_props->insn_index=57;
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
insn_props->insn_string="lf.madd.s";
|
insn_props->insn_string="lf.madd.s";
|
insn_props->insn_index=58;
|
insn_props->insn_index=58;
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
insn_props->insn_string="lf.sfeq.s";
|
insn_props->insn_string="lf.sfeq.s";
|
insn_props->insn_index=59;
|
insn_props->insn_index=59;
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
insn_props->insn_string="lf.sfne.s";
|
insn_props->insn_string="lf.sfne.s";
|
insn_props->insn_index=60;
|
insn_props->insn_index=60;
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
insn_props->insn_string="lf.sfgt.s";
|
insn_props->insn_string="lf.sfgt.s";
|
insn_props->insn_index=61;
|
insn_props->insn_index=61;
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
insn_props->insn_string="lf.sfge.s";
|
insn_props->insn_string="lf.sfge.s";
|
insn_props->insn_index=62;
|
insn_props->insn_index=62;
|
break;
|
break;
|
case 0xc:
|
case 0xc:
|
insn_props->insn_string="lf.sflt.s";
|
insn_props->insn_string="lf.sflt.s";
|
insn_props->insn_index=63;
|
insn_props->insn_index=63;
|
break;
|
break;
|
case 0xd:
|
case 0xd:
|
insn_props->insn_string="lf.sfle.s";
|
insn_props->insn_string="lf.sfle.s";
|
insn_props->insn_index=64;
|
insn_props->insn_index=64;
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lf.xxx.s op (0x%x)",
|
printf("Unknown lf.xxx.s op (0x%x)",
|
insn_or1k_opcode_0x32_get_op_lo(insn));
|
insn_or1k_opcode_0x32_get_op_lo(insn));
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
case 0x1:
|
case 0x1:
|
switch(insn_or1k_opcode_0x32_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x32_get_op_lo(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="lf.add.d";
|
insn_props->insn_string="lf.add.d";
|
insn_props->insn_index=65;
|
insn_props->insn_index=65;
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
insn_props->insn_string="lf.sub.d";
|
insn_props->insn_string="lf.sub.d";
|
insn_props->insn_index=66;
|
insn_props->insn_index=66;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="lf.mul.d";
|
insn_props->insn_string="lf.mul.d";
|
insn_props->insn_index=67;
|
insn_props->insn_index=67;
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
insn_props->insn_string="lf.div.d";
|
insn_props->insn_string="lf.div.d";
|
insn_props->insn_index=68;
|
insn_props->insn_index=68;
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
insn_props->insn_string="lf.itof.d";
|
insn_props->insn_string="lf.itof.d";
|
insn_props->insn_index=69;
|
insn_props->insn_index=69;
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
insn_props->insn_string="lf.ftoi.d";
|
insn_props->insn_string="lf.ftoi.d";
|
insn_props->insn_index=70;
|
insn_props->insn_index=70;
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
insn_props->insn_string="lf.rem.d";
|
insn_props->insn_string="lf.rem.d";
|
insn_props->insn_index=71;
|
insn_props->insn_index=71;
|
break;
|
break;
|
case 0x7:
|
case 0x7:
|
insn_props->insn_string="lf.madd.d";
|
insn_props->insn_string="lf.madd.d";
|
insn_props->insn_index=72;
|
insn_props->insn_index=72;
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
insn_props->insn_string="lf.sfeq.d";
|
insn_props->insn_string="lf.sfeq.d";
|
insn_props->insn_index=73;
|
insn_props->insn_index=73;
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
insn_props->insn_string="lf.sfne.d";
|
insn_props->insn_string="lf.sfne.d";
|
insn_props->insn_index=74;
|
insn_props->insn_index=74;
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
insn_props->insn_string="lf.sfgt.d";
|
insn_props->insn_string="lf.sfgt.d";
|
insn_props->insn_index=75;
|
insn_props->insn_index=75;
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
insn_props->insn_string="lf.sfge.d";
|
insn_props->insn_string="lf.sfge.d";
|
insn_props->insn_index=76;
|
insn_props->insn_index=76;
|
break;
|
break;
|
case 0xc:
|
case 0xc:
|
insn_props->insn_string="lf.sflt.d";
|
insn_props->insn_string="lf.sflt.d";
|
insn_props->insn_index=77;
|
insn_props->insn_index=77;
|
break;
|
break;
|
case 0xd:
|
case 0xd:
|
insn_props->insn_string="lf.sfle.d";
|
insn_props->insn_string="lf.sfle.d";
|
insn_props->insn_index=78;
|
insn_props->insn_index=78;
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown lf.xxx.d op (0x%x)",
|
printf("Unknown lf.xxx.d op (0x%x)",
|
insn_or1k_opcode_0x32_get_op_lo(insn));
|
insn_or1k_opcode_0x32_get_op_lo(insn));
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
case 0xd:
|
case 0xd:
|
insn_props->insn_string="lf.cust1.s";
|
insn_props->insn_string="lf.cust1.s";
|
insn_props->insn_index=79;
|
insn_props->insn_index=79;
|
break;
|
break;
|
|
|
case 0xe:
|
case 0xe:
|
insn_props->insn_string="lf.cust1.d";
|
insn_props->insn_string="lf.cust1.d";
|
insn_props->insn_index=80;
|
insn_props->insn_index=80;
|
break;
|
break;
|
|
|
default:
|
default:
|
printf("Unknown lf.xxx opcode hi (0x%x)",
|
printf("Unknown lf.xxx opcode hi (0x%x)",
|
insn_or1k_opcode_0x32_get_op_hi(insn));
|
insn_or1k_opcode_0x32_get_op_hi(insn));
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
case 0x34:
|
case 0x34:
|
insn_props->insn_string="l.sd";
|
insn_props->insn_string="l.sd";
|
insn_props->insn_index=81;
|
insn_props->insn_index=81;
|
break;
|
break;
|
|
|
case 0x35:
|
case 0x35:
|
insn_props->insn_string="l.sw";
|
insn_props->insn_string="l.sw";
|
insn_props->has_split_imm = 1;
|
insn_props->has_split_imm = 1;
|
insn_props->insn_index=82;
|
insn_props->insn_index=82;
|
break;
|
break;
|
|
|
case 0x36:
|
case 0x36:
|
insn_props->insn_string="l.sb";
|
insn_props->insn_string="l.sb";
|
insn_props->has_split_imm = 1;
|
insn_props->has_split_imm = 1;
|
insn_props->insn_index=83;
|
insn_props->insn_index=83;
|
break;
|
break;
|
|
|
case 0x37:
|
case 0x37:
|
insn_props->insn_string="l.sh";
|
insn_props->insn_string="l.sh";
|
insn_props->has_split_imm = 1;
|
insn_props->has_split_imm = 1;
|
insn_props->insn_index=84;
|
insn_props->insn_index=84;
|
break;
|
break;
|
|
|
case 0x38:
|
case 0x38:
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rB = 1;
|
insn_props->has_rB = 1;
|
switch(insn_or1k_opcode_0x38_get_op_lo(insn))
|
switch(insn_or1k_opcode_0x38_get_op_lo(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="l.add";
|
insn_props->insn_string="l.add";
|
insn_props->insn_index=85;
|
insn_props->insn_index=85;
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
insn_props->insn_string="l.addc";
|
insn_props->insn_string="l.addc";
|
insn_props->insn_index=86;
|
insn_props->insn_index=86;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="l.sub";
|
insn_props->insn_string="l.sub";
|
insn_props->insn_index=87;
|
insn_props->insn_index=87;
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
insn_props->insn_string="l.and";
|
insn_props->insn_string="l.and";
|
insn_props->insn_index=88;
|
insn_props->insn_index=88;
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
insn_props->insn_string="l.or";
|
insn_props->insn_string="l.or";
|
insn_props->insn_index=89;
|
insn_props->insn_index=89;
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
insn_props->insn_string="l.xor";
|
insn_props->insn_string="l.xor";
|
insn_props->insn_index=90;
|
insn_props->insn_index=90;
|
break;
|
break;
|
case 0x6:
|
case 0x6:
|
insn_props->insn_string="l.mul";
|
insn_props->insn_string="l.mul";
|
insn_props->insn_index=91;
|
insn_props->insn_index=91;
|
break;
|
break;
|
case 0x8:
|
case 0x8:
|
switch (insn_or1k_opcode_0x38_get_op_hi_4bit(insn))
|
switch (insn_or1k_opcode_0x38_get_op_hi_4bit(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="l.sll";
|
insn_props->insn_string="l.sll";
|
insn_props->insn_index=92;
|
insn_props->insn_index=92;
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
insn_props->insn_string="l.srl";
|
insn_props->insn_string="l.srl";
|
insn_props->insn_index=93;
|
insn_props->insn_index=93;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="l.sra";
|
insn_props->insn_string="l.sra";
|
insn_props->insn_index=94;
|
insn_props->insn_index=94;
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
insn_props->insn_string="l.ror";
|
insn_props->insn_string="l.ror";
|
insn_props->insn_index=95;
|
insn_props->insn_index=95;
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown ALU op 0x8 hi op (0x%x)",
|
printf("Unknown ALU op 0x8 hi op (0x%x)",
|
insn_or1k_opcode_0x38_get_op_hi_4bit(insn));
|
insn_or1k_opcode_0x38_get_op_hi_4bit(insn));
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
insn_props->insn_string="l.div";
|
insn_props->insn_string="l.div";
|
insn_props->insn_index=96;
|
insn_props->insn_index=96;
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
insn_props->insn_string="l.divu";
|
insn_props->insn_string="l.divu";
|
insn_props->insn_index=97;
|
insn_props->insn_index=97;
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
insn_props->insn_string="l.mulu";
|
insn_props->insn_string="l.mulu";
|
insn_props->insn_index=98;
|
insn_props->insn_index=98;
|
break;
|
break;
|
case 0xc:
|
case 0xc:
|
switch(insn_or1k_opcode_0x38_get_op_hi_4bit(insn))
|
switch(insn_or1k_opcode_0x38_get_op_hi_4bit(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="l.exths";
|
insn_props->insn_string="l.exths";
|
insn_props->insn_index=99;
|
insn_props->insn_index=99;
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
insn_props->insn_string="l.extbs";
|
insn_props->insn_string="l.extbs";
|
insn_props->insn_index=100;
|
insn_props->insn_index=100;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="l.exthz";
|
insn_props->insn_string="l.exthz";
|
insn_props->insn_index=101;
|
insn_props->insn_index=101;
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
insn_props->insn_string="l.extbz";
|
insn_props->insn_string="l.extbz";
|
insn_props->insn_index=102;
|
insn_props->insn_index=102;
|
break;
|
break;
|
}
|
}
|
insn_props->has_rB = 0;
|
insn_props->has_rB = 0;
|
break;
|
break;
|
|
|
case 0xd:
|
case 0xd:
|
insn_props->insn_string="l.extws";
|
insn_props->insn_string="l.extws";
|
insn_props->insn_index=103;
|
insn_props->insn_index=103;
|
insn_props->has_rB = 0;
|
insn_props->has_rB = 0;
|
break;
|
break;
|
|
|
case 0xe:
|
case 0xe:
|
insn_props->insn_string="l.cmov";
|
insn_props->insn_string="l.cmov";
|
insn_props->insn_index=104;
|
insn_props->insn_index=104;
|
break;
|
break;
|
|
|
case 0xf:
|
case 0xf:
|
if (insn_or1k_opcode_0x38_get_op_hi_2bit(insn) & 0x1)
|
if (insn_or1k_opcode_0x38_get_op_hi_2bit(insn) & 0x1)
|
{
|
{
|
insn_props->insn_string="l.fl1";
|
insn_props->insn_string="l.fl1";
|
insn_props->insn_index=105;
|
insn_props->insn_index=105;
|
}
|
}
|
else
|
else
|
{
|
{
|
insn_props->insn_string="l.ff1";
|
insn_props->insn_string="l.ff1";
|
insn_props->insn_index=106;
|
insn_props->insn_index=106;
|
}
|
}
|
insn_props->has_rB = 0;
|
insn_props->has_rB = 0;
|
break;
|
break;
|
|
|
default:
|
default:
|
printf("Unknown ALU lo op (0x%x)",
|
printf("Unknown ALU lo op (0x%x)",
|
insn_or1k_opcode_0x38_get_op_lo(insn));
|
insn_or1k_opcode_0x38_get_op_lo(insn));
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
case 0x39:
|
case 0x39:
|
insn_props->has_rA = 1;
|
insn_props->has_rA = 1;
|
insn_props->has_rB = 1;
|
insn_props->has_rB = 1;
|
switch (insn_or1k_opcode_0x39_get_op(insn))
|
switch (insn_or1k_opcode_0x39_get_op(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="l.sfeq";
|
insn_props->insn_string="l.sfeq";
|
insn_props->insn_index=107;
|
insn_props->insn_index=107;
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
insn_props->insn_string="l.sfne";
|
insn_props->insn_string="l.sfne";
|
insn_props->insn_index=108;
|
insn_props->insn_index=108;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="l.sfgtu";
|
insn_props->insn_string="l.sfgtu";
|
insn_props->insn_index=109;
|
insn_props->insn_index=109;
|
break;
|
break;
|
case 0x3:
|
case 0x3:
|
insn_props->insn_string="l.sfgeu";
|
insn_props->insn_string="l.sfgeu";
|
insn_props->insn_index=110;
|
insn_props->insn_index=110;
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
insn_props->insn_string="l.sfltu";
|
insn_props->insn_string="l.sfltu";
|
insn_props->insn_index=111;
|
insn_props->insn_index=111;
|
break;
|
break;
|
case 0x5:
|
case 0x5:
|
insn_props->insn_string="l.sfleu";
|
insn_props->insn_string="l.sfleu";
|
insn_props->insn_index=112;
|
insn_props->insn_index=112;
|
break;
|
break;
|
case 0xa:
|
case 0xa:
|
insn_props->insn_string="l.sfgts";
|
insn_props->insn_string="l.sfgts";
|
insn_props->insn_index=113;
|
insn_props->insn_index=113;
|
break;
|
break;
|
case 0xb:
|
case 0xb:
|
insn_props->insn_string="l.sfges";
|
insn_props->insn_string="l.sfges";
|
insn_props->insn_index=114;
|
insn_props->insn_index=114;
|
break;
|
break;
|
case 0xc:
|
case 0xc:
|
insn_props->insn_string="l.sflts";
|
insn_props->insn_string="l.sflts";
|
insn_props->insn_index=115;
|
insn_props->insn_index=115;
|
break;
|
break;
|
case 0xd:
|
case 0xd:
|
insn_props->insn_string="l.sfles";
|
insn_props->insn_string="l.sfles";
|
insn_props->insn_index=116;
|
insn_props->insn_index=116;
|
break;
|
break;
|
default:
|
default:
|
printf("Unknown opcode for l.sfxxx opcode (0x%x)",
|
printf("Unknown opcode for l.sfxxx opcode (0x%x)",
|
insn_or1k_opcode_0x39_get_op(insn));
|
insn_or1k_opcode_0x39_get_op(insn));
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
|
default:
|
default:
|
printf("Unknown opcode 0x%x",insn_or1k_opcode(insn));
|
printf("Unknown opcode 0x%x",insn_or1k_opcode(insn));
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
|
// Entry point for statistics collection.
|
|
// Passed binary copy of instruction, and pointer to properties struct
|
|
// Each function that can collect staistics is called.
|
void or1k_32_collect_stats(uint32_t insn,
|
void or1k_32_collect_stats(uint32_t insn,
|
struct or1k_32_instruction_properties * insn_props)
|
struct or1k_32_instruction_properties * insn_props)
|
{
|
{
|
// Add this instruction's occurance to our data
|
// Add this instruction's occurance to our data
|
insn_lists_add(insn, insn_props);
|
insn_lists_add(insn, insn_props);
|
|
|
// n-tuple groupings stats recording here!
|
// n-tuple groupings stats recording here!
|
// only if we've seen enough to do all the sequence analysis
|
// only if we've seen enough to do all the sequence analysis
|
if (num_seen_insns > OR1K_MAX_GROUPINGS_ANALYSIS+1)
|
if (num_seen_insns > OR1K_MAX_GROUPINGS_ANALYSIS+1)
|
{
|
{
|
int n;
|
int n;
|
for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
|
for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
|
insn_lists_group_add(n, insn_props);
|
insn_lists_group_add(n, insn_props);
|
}
|
}
|
|
|
// Finished adding to stats for this instruction
|
// Finished adding to stats for this instruction
|
|
|
|
|
}
|
}
|
|
|
// Function to add entry to, or increment incidences of, value in the value list
|
// 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)
|
void or1k_add_in_list(struct or1k_value_list * list, int32_t value)
|
{
|
{
|
int i;
|
int i;
|
// See if it's already in the list
|
// See if it's already in the list
|
i=list->count;
|
i=list->count;
|
|
|
while(i)
|
while(i)
|
{
|
{
|
i--;
|
i--;
|
if(list->values[i][0] == value)
|
if(list->values[i][0] == value)
|
{
|
{
|
(list->values[i][1])++;
|
(list->values[i][1])++;
|
return;
|
return;
|
}
|
}
|
}
|
}
|
|
|
if (list->count < OR1K_VALUE_MAX_ENTRIES)
|
if (list->count < OR1K_VALUE_MAX_ENTRIES)
|
{
|
{
|
// Not found, add it to the list
|
// Not found, add it to the list
|
list->values[(list->count)][0] = value;
|
list->values[(list->count)][0] = value;
|
list->values[(list->count)][1] = 1;
|
list->values[(list->count)][1] = 1;
|
list->count++;
|
list->count++;
|
}
|
}
|
}
|
}
|
|
|
// List management/analysis functions - accessed through insn_lists() set of
|
// List management/analysis functions - accessed through insn_lists() set of
|
// functions
|
// functions
|
|
|
|
// Clear the list structs
|
void or1k_32_insn_lists_init(void)
|
void or1k_32_insn_lists_init(void)
|
{
|
{
|
num_setup_insns = 0;
|
num_setup_insns = 0;
|
num_seen_insns = 0;
|
num_seen_insns = 0;
|
// Clear the pointer array so we can tell if things are used or not
|
// Clear the pointer array so we can tell if things are used or not
|
memset(or1k_32_insns, '\0',
|
memset(or1k_32_insns, '\0',
|
sizeof(struct or1k_insn_info *)*OR1K_32_MAX_INSNS);
|
sizeof(struct or1k_insn_info *)*OR1K_32_MAX_INSNS);
|
}
|
}
|
|
|
// Alloc struct and put it into the list
|
// Alloc struct and put it into the list
|
void or1k_32_insn_lists_init_insn(uint32_t insn,
|
void or1k_32_insn_lists_init_insn(uint32_t insn,
|
struct or1k_32_instruction_properties *insn_props)
|
struct or1k_32_instruction_properties *insn_props)
|
{
|
{
|
// Add an instruction in or1k_32_insns[num_unique_instructions];
|
// Add an instruction in or1k_32_insns[num_unique_instructions];
|
// use calloc() so it clears it all first (hopefully!).. assumption!
|
// use calloc() so it clears it all first (hopefully!).. assumption!
|
struct or1k_insn_info * new_insn
|
struct or1k_insn_info * new_insn
|
= (struct or1k_insn_info *) calloc (sizeof(struct or1k_insn_info), 1);
|
= (struct or1k_insn_info *) calloc (sizeof(struct or1k_insn_info), 1);
|
|
|
// Copy the string pointer
|
// Copy the string pointer
|
new_insn->insn_string = insn_props->insn_string,
|
new_insn->insn_string = insn_props->insn_string,
|
|
|
// Install the pointer for this newly allocated struct in its corresponding
|
// Install the pointer for this newly allocated struct in its corresponding
|
// index, as set when we decode the instruction
|
// index, as set when we decode the instruction
|
or1k_32_insns[insn_props->insn_index] = new_insn;
|
or1k_32_insns[insn_props->insn_index] = new_insn;
|
|
|
// Clear the set statistics counters
|
// Clear the set statistics counters
|
int set_itr;
|
int set_itr;
|
for(set_itr=0;set_itr<OR1K_MAX_GROUPINGS_ANALYSIS;set_itr++)
|
for(set_itr=0;set_itr<OR1K_MAX_GROUPINGS_ANALYSIS;set_itr++)
|
or1k_32_insns[insn_props->insn_index]->groupings[set_itr][0][0] = 0;
|
or1k_32_insns[insn_props->insn_index]->groupings[set_itr][0][0] = 0;
|
|
|
// Increment number of instructions we have set up
|
// Increment number of instructions we have set up
|
num_setup_insns++;
|
num_setup_insns++;
|
|
|
// Debugging:
|
// Debugging:
|
//printf("Adding %dth instruction - %s\n",
|
//printf("Adding %dth instruction - %s\n",
|
//num_setup_insns, new_insn->insn_string);
|
//num_setup_insns, new_insn->insn_string);
|
|
|
}
|
}
|
|
|
|
|
|
|
// Add stats for this instruction
|
// Add stats for this instruction
|
void or1k_32_insn_lists_add(uint32_t insn,
|
void or1k_32_insn_lists_add(uint32_t insn,
|
struct or1k_32_instruction_properties *insn_props)
|
struct or1k_32_instruction_properties *insn_props)
|
{
|
{
|
// Check if the entry for this instruction has been setup yet
|
// Check if the entry for this instruction has been setup yet
|
if (or1k_32_insns[insn_props->insn_index] == NULL)
|
if (or1k_32_insns[insn_props->insn_index] == NULL)
|
{
|
{
|
// Here we allocate space for the instruction's stats
|
// Here we allocate space for the instruction's stats
|
or1k_32_insn_lists_init_insn(insn, insn_props);
|
or1k_32_insn_lists_init_insn(insn, insn_props);
|
}
|
}
|
|
|
// Increment occurance count
|
// Increment occurance count
|
((or1k_32_insns[insn_props->insn_index])->count)++;
|
((or1k_32_insns[insn_props->insn_index])->count)++;
|
|
|
// Add branch target value information, if instruction has it
|
// Add branch target value information, if instruction has it
|
if (insn_props->has_branchtarg)
|
if (insn_props->has_branchtarg)
|
{
|
{
|
(or1k_32_insns[insn_props->insn_index])->has_branchtarg = 1;
|
(or1k_32_insns[insn_props->insn_index])->has_branchtarg = 1;
|
or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->branch_info),
|
or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->branch_info),
|
(int32_t)insn_or1k_opcode_0x03_get_branchoff(insn));
|
(int32_t)insn_or1k_opcode_0x03_get_branchoff(insn));
|
}
|
}
|
|
|
// Add immediate value if it's got one
|
// Add immediate value if it's got one
|
if (insn_props->has_imm)
|
if (insn_props->has_imm)
|
{
|
{
|
(or1k_32_insns[insn_props->insn_index])->has_imm = 1;
|
(or1k_32_insns[insn_props->insn_index])->has_imm = 1;
|
or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->imm_info),
|
or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->imm_info),
|
(int32_t)insn_or1k_32_imm(insn));
|
(int32_t)insn_or1k_32_imm(insn));
|
}
|
}
|
|
|
// Add split immediate value if it's got one
|
// Add split immediate value if it's got one
|
if (insn_props->has_split_imm)
|
if (insn_props->has_split_imm)
|
{
|
{
|
(or1k_32_insns[insn_props->insn_index])->has_imm = 1;
|
(or1k_32_insns[insn_props->insn_index])->has_imm = 1;
|
or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->imm_info),
|
or1k_add_in_list(&((or1k_32_insns[insn_props->insn_index])->imm_info),
|
(int32_t)insn_or1k_32_split_imm(insn));
|
(int32_t)insn_or1k_32_split_imm(insn));
|
}
|
}
|
|
|
|
|
// Increment count of use for particular rD
|
// Increment count of use for particular rD
|
if (insn_props->has_rD)
|
if (insn_props->has_rD)
|
{
|
{
|
(or1k_32_insns[insn_props->insn_index])->has_rD = 1;
|
(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)])++;
|
((or1k_32_insns[insn_props->insn_index])->rD_use_freq[insn_or1k_32_rD(insn)])++;
|
}
|
}
|
|
|
// Increment count of use for particular rA
|
// Increment count of use for particular rA
|
if (insn_props->has_rA)
|
if (insn_props->has_rA)
|
{
|
{
|
(or1k_32_insns[insn_props->insn_index])->has_rA = 1;
|
(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)])++;
|
((or1k_32_insns[insn_props->insn_index])->rA_use_freq[insn_or1k_32_rA(insn)])++;
|
}
|
}
|
|
|
// Increment count of use for particular rB
|
// Increment count of use for particular rB
|
if (insn_props->has_rB)
|
if (insn_props->has_rB)
|
{
|
{
|
(or1k_32_insns[insn_props->insn_index])->has_rB = 1;
|
(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)])++;
|
((or1k_32_insns[insn_props->insn_index])->rB_use_freq[insn_or1k_32_rB(insn)])++;
|
}
|
}
|
|
|
// Increment overall instructions "seen" counter
|
// Increment overall instructions "seen" counter
|
num_seen_insns++;
|
num_seen_insns++;
|
|
|
// Shift along the recently seen instructions
|
// Shift along the recently seen instructions
|
int i;
|
int i;
|
for(i=OR1K_MAX_GROUPINGS_ANALYSIS-1;i>0;i--)
|
for(i=OR1K_MAX_GROUPINGS_ANALYSIS-1;i>0;i--)
|
or1k_32_recent_insns[i] = or1k_32_recent_insns[i-1];
|
or1k_32_recent_insns[i] = or1k_32_recent_insns[i-1];
|
or1k_32_recent_insns[0] = insn_props->insn_index;
|
or1k_32_recent_insns[0] = insn_props->insn_index;
|
|
|
}
|
}
|
|
|
|
|
|
|
|
|
// Do the n-tuple set analysis for the most recently added instruction
|
// Do the n-tuple set checking for the current instruction
|
void or1k_32_ntuple_add(int n,
|
void or1k_32_ntuple_add(int n,
|
struct or1k_32_instruction_properties *insn_props)
|
struct or1k_32_instruction_properties *insn_props)
|
{
|
{
|
|
|
if (n<2)
|
if (n<2)
|
{
|
{
|
fprintf(stderr,"or1k_32_ntuple_add: tuple number < 2 (%d)",n);
|
fprintf(stderr,"or1k_32_ntuple_add: tuple number < 2 (%d)",n);
|
return;
|
return;
|
}
|
}
|
|
|
struct or1k_insn_info * insn_info = or1k_32_insns[insn_props->insn_index];
|
struct or1k_insn_info * insn_info = or1k_32_insns[insn_props->insn_index];
|
|
|
// Get the number of sets for these n-tuple groups we've seen so far.
|
// Get the number of sets for these n-tuple groups we've seen so far.
|
int sets_for_ntuple = insn_info->groupings[n-1][0][0];
|
int sets_for_ntuple = insn_info->groupings[n-1][0][0];
|
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
printf("%s\t:\t%d-tuple add - sets so far : %d\n",insn_info->insn_string, n, sets_for_ntuple);
|
printf("%s\t:\t%d-tuple add - sets so far : %d\n",
|
|
insn_info->insn_string, n, sets_for_ntuple);
|
#endif
|
#endif
|
|
|
int set_match_index;
|
int set_match_index;
|
int tuple_set_itr, tuple_set_match;
|
int tuple_set_itr, tuple_set_match;
|
|
|
tuple_set_match = 0;
|
tuple_set_match = 0;
|
|
|
// now find if the current n instructions in or1k_32_recent_insns[] matches
|
// now find if the current n instructions in or1k_32_recent_insns[] matches
|
// any set of n instructions we're keeping track of in groupings[][][].
|
// any set of n instructions we're keeping track of in groupings[][][].
|
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
printf("%s\tChecking\t%d\tsets for ntuple:\t",insn_info->insn_string,sets_for_ntuple);
|
printf("%s\tChecking\t%d\tsets for ntuple:\t",
|
|
insn_info->insn_string,sets_for_ntuple);
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
printf("%s ",
|
printf("%s ",
|
or1k_32_insns[(or1k_32_recent_insns[n - 1 - tuple_set_itr])]->insn_string);
|
or1k_32_insns[(or1k_32_recent_insns[n - 1 - tuple_set_itr])]->insn_string);
|
printf("\n");
|
printf("\n");
|
#endif
|
#endif
|
for (set_match_index=0; set_match_index<sets_for_ntuple; set_match_index++)
|
for (set_match_index=0; set_match_index<sets_for_ntuple; set_match_index++)
|
{
|
{
|
// Check this set for a match with our existing trace
|
// Check this set for a match with our existing trace
|
// Example:
|
// Example:
|
// In case of a triple (n=3), 1st set, [3][1][0] corresponds to the third
|
// In case of a triple (n=3), 1st set, [3][1][0] corresponds to the third
|
// instruction in the trace (or1k_32_recent_insns[2]), [3][1][1] should
|
// instruction in the trace (or1k_32_recent_insns[2]), [3][1][1] should
|
// be the second in the trace, and [3][1][2] should be the first in the
|
// be the second in the trace, and [3][1][2] should be the first in the
|
// trace (same index as insn_props->insn_index)
|
// trace (same index as insn_props->insn_index)
|
|
|
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
printf("Chk:\t");
|
printf("Chk:\t");
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
printf("%s ",
|
printf("%s ",
|
or1k_32_insns[(insn_info->groupings[n-1][set_match_index+1][tuple_set_itr])]->insn_string);
|
or1k_32_insns[(insn_info->groupings[n-1][set_match_index+1][tuple_set_itr])]->insn_string);
|
printf("\t(%d)\n", insn_info->groupings[n-1][set_match_index+1][n]);
|
printf("\t(%d)\n", insn_info->groupings[n-1][set_match_index+1][n]);
|
#endif
|
#endif
|
tuple_set_match = 1;
|
tuple_set_match = 1;
|
// Presuppose a match, de-assert and break out of the loop as soon as we
|
// Presuppose a match, de-assert and break out of the loop as soon as we
|
// detect a mismatch.
|
// detect a mismatch.
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
{
|
{
|
|
|
if (insn_info->groupings[n-1][set_match_index+1][tuple_set_itr]
|
if (insn_info->groupings[n-1][set_match_index+1][tuple_set_itr]
|
!= or1k_32_recent_insns[n - 1 - tuple_set_itr])
|
!= or1k_32_recent_insns[n - 1 - tuple_set_itr])
|
{
|
{
|
tuple_set_match = 0;
|
tuple_set_match = 0;
|
break; // No match, so break out of this for() loop
|
break; // No match, so break out of this for() loop
|
}
|
}
|
}
|
}
|
|
|
if (!tuple_set_match)
|
if (!tuple_set_match)
|
continue; // go again...
|
continue; // go again...
|
else
|
else
|
break; // Bail out, we've found our match
|
break; // Bail out, we've found our match
|
}
|
}
|
|
|
if (tuple_set_match)
|
if (tuple_set_match)
|
{
|
{
|
// Found a match - just increment the counter (set_match_index should
|
// Found a match - just increment the counter (set_match_index should
|
// be pointing at the right set)
|
// be pointing at the right set)
|
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
printf("Match!\n");
|
printf("Match!\n");
|
#endif
|
#endif
|
|
|
(insn_info->groupings[n-1][set_match_index+1][n])++;
|
(insn_info->groupings[n-1][set_match_index+1][n])++;
|
}
|
}
|
else
|
else
|
{
|
{
|
// If we can record a new set
|
// If we can record a new set
|
if (sets_for_ntuple < OR1K_MAX_ENTRIES_PER_GROUP)
|
if (sets_for_ntuple < OR1K_MAX_ENTRIES_PER_GROUP)
|
{
|
{
|
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
printf("New entry\n");
|
printf("New entry\n");
|
#endif
|
#endif
|
|
|
// Increment the number of sets we have for this n-tuple starting
|
// Increment the number of sets we have for this n-tuple starting
|
// on the current instruction
|
// on the current instruction
|
sets_for_ntuple++;
|
sets_for_ntuple++;
|
// Add new set to the end (all n instructions, copy in)
|
// Add new set to the end (all n instructions, copy in)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr]
|
insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr]
|
= or1k_32_recent_insns[n - 1 - tuple_set_itr];
|
= or1k_32_recent_insns[n - 1 - tuple_set_itr];
|
// Set the count for this set to 1
|
// Set the count for this set to 1
|
(insn_info->groupings[n-1][sets_for_ntuple][n]) = 1;
|
(insn_info->groupings[n-1][sets_for_ntuple][n]) = 1;
|
// Increment the counter of these n-tuple sets
|
// Increment the counter of these n-tuple sets
|
insn_info->groupings[n-1][0][0] = sets_for_ntuple;
|
insn_info->groupings[n-1][0][0] = sets_for_ntuple;
|
}
|
}
|
}
|
}
|
|
|
// Debugging :
|
|
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
|
// Verbose announcement of found instruction
|
if (tuple_set_match)
|
if (tuple_set_match)
|
{
|
{
|
printf("%s\t:\tMatch for %d-tuple - set %d - cnt: %d - ",
|
printf("%s\t:\tMatch for %d-tuple - set %d - cnt: %d - ",
|
insn_info->insn_string, n, set_match_index,
|
insn_info->insn_string, n, set_match_index,
|
insn_info->groupings[n-1][set_match_index+1][n]);
|
insn_info->groupings[n-1][set_match_index+1][n]);
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
printf("%s ",
|
printf("%s ",
|
or1k_32_insns[(insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr])]->insn_string);
|
or1k_32_insns[(insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr])]->insn_string);
|
printf("\n");
|
printf("\n");
|
}
|
}
|
else
|
else
|
{
|
{
|
printf("%s\t:\tNew %d-tuple - set %d - cnt: %d - ",
|
printf("%s\t:\tNew %d-tuple - set %d - cnt: %d - ",
|
insn_info->insn_string, n, sets_for_ntuple,
|
insn_info->insn_string, n, sets_for_ntuple,
|
insn_info->groupings[n-1][sets_for_ntuple][n]);
|
insn_info->groupings[n-1][sets_for_ntuple][n]);
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
printf("%s ",
|
printf("%s ",
|
or1k_32_insns[(insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr])]->insn_string);
|
or1k_32_insns[(insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr])]->insn_string);
|
printf("\n");
|
printf("\n");
|
}
|
}
|
#endif
|
#endif
|
|
|
}
|
}
|
|
|
|
// Generate a list for the most-frequently seen instructions
|
#define DISPLAY_STRING
|
|
//#define DISPLAY_CSV
|
|
|
|
void or1k_32_most_freq_insn(FILE * stream)
|
void or1k_32_most_freq_insn(FILE * stream)
|
{
|
{
|
// Print out most frequent instruction
|
// Print out most frequent instruction
|
int i, largest, largest_index;
|
int i, largest, largest_index;
|
int instructions_to_print = num_setup_insns;
|
int instructions_to_print = num_setup_insns;
|
|
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream,"\"Most frequent instructions, descending\",\n");
|
|
fprintf(stream,"\"Instruction\",\"Occurances\",\"Frequency\",\n");
|
|
#endif
|
|
|
while (instructions_to_print)
|
while (instructions_to_print)
|
{
|
{
|
--instructions_to_print;
|
--instructions_to_print;
|
largest=0;
|
largest=0;
|
// Go through the list, find the largest, print it, eliminate it
|
// Go through the list, find the largest, print it, eliminate it
|
for(i=0;i<OR1K_32_MAX_INSNS;i++)
|
for(i=0;i<OR1K_32_MAX_INSNS;i++)
|
if (or1k_32_insns[i]!=NULL){
|
if (or1k_32_insns[i]!=NULL){
|
if(((or1k_32_insns[i])->count) > largest)
|
if(((or1k_32_insns[i])->count) > largest)
|
{
|
{
|
largest = ((or1k_32_insns[i])->count);
|
largest = ((or1k_32_insns[i])->count);
|
largest_index = i;
|
largest_index = i;
|
}
|
}
|
}
|
}
|
fprintf(stream,
|
fprintf(stream,
|
#ifdef DISPLAY_STRING
|
#ifdef DISPLAY_STRING
|
"Insn:\t%s\t\tCount:\t\t%d\t(%f%%)\n",
|
"Insn:\t%s\t\tCount:\t\t%d\t(%f%%)\n",
|
#endif
|
#endif
|
#ifdef DISPLAY_CSV
|
#ifdef DISPLAY_CSV
|
// CSV format - "opcode string",frequency,percentage
|
// CSV format - "opcode string",frequency,percentage
|
"\"%s\",%d,%f\n",
|
"\"%s\",%d,%f\n",
|
#endif
|
#endif
|
((or1k_32_insns[largest_index])->insn_string),
|
((or1k_32_insns[largest_index])->insn_string),
|
((or1k_32_insns[largest_index])->count),
|
((or1k_32_insns[largest_index])->count),
|
(float)(((float)((or1k_32_insns[largest_index])->count))/
|
(float)(((float)((or1k_32_insns[largest_index])->count))/
|
((float)num_seen_insns))*100.f);
|
((float)num_seen_insns))*100.f);
|
|
|
|
|
((or1k_32_insns[largest_index])->count) = -1; // Eliminate this one
|
((or1k_32_insns[largest_index])->count) = -1; // Eliminate this one
|
|
|
}
|
}
|
}
|
}
|
|
|
|
|
// Print out top x of each kept statistic for the requested instruction
|
// Generate a list for the most-frequently seen n-tuple set
|
void or1k_32_insn_top_x(struct or1k_insn_info *insn_info, FILE * stream,
|
void or1k_32_most_freq_ntuple(int n, FILE * stream, int max_stats)
|
|
{
|
|
|
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
"Top %d %d-tuple groupings of instructions\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"Top %d %d-tuple groupings of instructions\",\n",
|
|
#endif
|
|
max_stats, n);
|
|
|
|
// First get a copy of all the n-tuple values for each applicable
|
|
// instruction.
|
|
int set_counts[OR1K_32_MAX_INSNS][OR1K_MAX_ENTRIES_PER_GROUP];
|
|
int insn_index;
|
|
int set_index;
|
|
int num_sets;
|
|
struct or1k_insn_info *insn_info;
|
|
|
|
// Copy each instruction's set totals into our local array
|
|
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
|
{
|
|
if (or1k_32_insns[insn_index] != NULL)
|
|
{
|
|
insn_info = or1k_32_insns[insn_index];
|
|
num_sets = insn_info->groupings[n-1][0][0];
|
|
for(set_index=0;set_index<num_sets;set_index++)
|
|
set_counts[insn_index][set_index] =
|
|
insn_info->groupings[n-1][set_index+1][n];
|
|
}
|
|
}
|
|
|
|
// Go through the set numbers, look at the most frequent one, print it out
|
|
// clear its count and continue
|
|
|
|
|
|
int largest_insn_index, largest_set_index, largest_count;
|
|
int tuple_set_itr;
|
|
|
|
|
|
#ifdef DISPLAY_CSV
|
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
|
fprintf(stream, "\"insn%d\",",n-1-tuple_set_itr);
|
|
fprintf(stream, "\"count\",\n");
|
|
#endif
|
|
|
|
while(max_stats--)
|
|
{
|
|
largest_count = 0;
|
|
// Go through each instruction we have
|
|
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
|
{
|
|
if (or1k_32_insns[insn_index] != NULL)
|
|
{
|
|
insn_info = or1k_32_insns[insn_index];
|
|
// Get the total number of sets for the n-tup. of this instruction
|
|
num_sets = insn_info->groupings[n-1][0][0];
|
|
for(set_index=0;set_index<num_sets;set_index++)
|
|
{
|
|
// Go through each set, check if it's largest
|
|
if (set_counts[insn_index][set_index] >
|
|
largest_count)
|
|
{
|
|
largest_insn_index = insn_index;
|
|
largest_set_index = set_index;
|
|
largest_count = set_counts[insn_index][set_index];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Have indexes of the next largest n-tuple, print it out.
|
|
|
|
insn_info = or1k_32_insns[largest_insn_index];
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream,"set :");
|
|
#endif
|
|
|
|
// insn_info->insn_string, n, set_match_index,
|
|
// insn_info->groupings[n-1][set_match_index+1][n]);
|
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
" %s",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"%s\",",
|
|
#endif
|
|
or1k_32_insns[(insn_info->groupings[n-1][largest_set_index][tuple_set_itr])]->insn_string);
|
|
|
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
"\tcount: %d\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"%d,\n",
|
|
#endif
|
|
set_counts[largest_insn_index][largest_set_index]);
|
|
|
|
// Remove this value from getting selected from largest again
|
|
set_counts[largest_insn_index][largest_set_index] = -1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Print out top n of each kept statistic for the requested instruction
|
|
void or1k_32_insn_top_n(struct or1k_insn_info *insn_info, FILE * stream,
|
int max_stats)
|
int max_stats)
|
{
|
{
|
int i, j, largest_i;
|
int i, j, largest_i;
|
|
|
fprintf(stream,
|
fprintf(stream,
|
"Insn: \"%s\" statistics (%d times (%f%%)):\n",
|
#ifdef DISPLAY_STRING
|
|
"Insn: \"%s\" statistics (%d times (%f%%))\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"Insn:\",\"%s\",\"occurances:\",%d,%f\n",
|
|
#endif
|
insn_info->insn_string,
|
insn_info->insn_string,
|
insn_info->count,
|
insn_info->count,
|
(float)(((float)((insn_info)->count))/
|
(float)(((float)((insn_info)->count))/
|
((float)num_seen_insns))*100.f
|
((float)num_seen_insns))*100.f
|
);
|
);
|
|
|
|
|
|
|
// Start dumping applicable stats
|
// Start dumping applicable stats
|
|
|
// Print out top max_stats branch targets
|
// Print out top max_stats branch targets
|
if (insn_info->has_branchtarg)
|
if (insn_info->has_branchtarg)
|
{
|
{
|
fprintf(stream,"Branch values:\n");
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
"Branch values:\n"
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"branch distance\",\"occurances\"\n"
|
|
#endif
|
|
);
|
i = 0;
|
i = 0;
|
while(i<insn_info->branch_info.count && i < max_stats)
|
while(i<insn_info->branch_info.count && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<insn_info->branch_info.count;j++)
|
for(j=0;j<insn_info->branch_info.count;j++)
|
largest_i = (insn_info->branch_info.values[j][1] >
|
largest_i = (insn_info->branch_info.values[j][1] >
|
insn_info->branch_info.values[largest_i][1]) ?
|
insn_info->branch_info.values[largest_i][1]) ?
|
j : largest_i;
|
j : largest_i;
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"value:\t0x%x\tcount:\t%d\n",
|
"value:\t0x%x\tcount:\t%d\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"0x%x,%d\n",
|
|
#endif
|
insn_info->branch_info.values[largest_i][0],
|
insn_info->branch_info.values[largest_i][0],
|
insn_info->branch_info.values[largest_i][1]);
|
insn_info->branch_info.values[largest_i][1]);
|
insn_info->branch_info.values[largest_i][1] = -1; // clear this one
|
insn_info->branch_info.values[largest_i][1] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
if (insn_info->has_imm)
|
if (insn_info->has_imm)
|
{
|
{
|
fprintf(stream,"Immediate values:\n");
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
"Immediate values:\n"
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"immediate value\",\"count\"\n"
|
|
#endif
|
|
);
|
i = 0;
|
i = 0;
|
while(i<insn_info->imm_info.count && i < max_stats)
|
while(i<insn_info->imm_info.count && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<insn_info->imm_info.count;j++)
|
for(j=0;j<insn_info->imm_info.count;j++)
|
largest_i = (insn_info->imm_info.values[j][1] >
|
largest_i = (insn_info->imm_info.values[j][1] >
|
insn_info->imm_info.values[largest_i][1]) ?
|
insn_info->imm_info.values[largest_i][1]) ?
|
j : largest_i;
|
j : largest_i;
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"value:\t0x%x\tcount:\t%d\n",
|
"value:\t0x%x\tcount:\t%d\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"0x%x,%d\n",
|
|
#endif
|
insn_info->imm_info.values[largest_i][0],
|
insn_info->imm_info.values[largest_i][0],
|
insn_info->imm_info.values[largest_i][1]);
|
insn_info->imm_info.values[largest_i][1]);
|
insn_info->imm_info.values[largest_i][1] = -1; // clear this one
|
insn_info->imm_info.values[largest_i][1] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
|
|
if (insn_info->has_rD)
|
if (insn_info->has_rD)
|
{
|
{
|
fprintf(stream,"rD usage:\n");
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
"rD usage:\n"
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"rD\",\"count\"\n"
|
|
#endif
|
|
);
|
i = 0;
|
i = 0;
|
while(i<32 && i < max_stats)
|
while(i<32 && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<32;j++)
|
for(j=0;j<32;j++)
|
largest_i = (insn_info->rD_use_freq[j] >
|
largest_i = (insn_info->rD_use_freq[j] >
|
insn_info->rD_use_freq[largest_i]) ?
|
insn_info->rD_use_freq[largest_i]) ?
|
j : largest_i;
|
j : largest_i;
|
|
|
// No more interesting numbers
|
// No more interesting numbers
|
if (insn_info->rD_use_freq[largest_i] == 0)
|
if (insn_info->rD_use_freq[largest_i] == 0)
|
break;
|
break;
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"r%d\tcount:\t%d\n",
|
"r%d\tcount:\t%d\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"r%d\",%d\n",
|
|
#endif
|
largest_i,
|
largest_i,
|
insn_info->rD_use_freq[largest_i]);
|
insn_info->rD_use_freq[largest_i]);
|
insn_info->rD_use_freq[largest_i] = -1; // clear this one
|
insn_info->rD_use_freq[largest_i] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
|
|
if (insn_info->has_rA)
|
if (insn_info->has_rA)
|
{
|
{
|
fprintf(stream,"rA usage:\n");
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
"rA usage:\n"
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"rA\",\"count\"\n"
|
|
#endif
|
|
);
|
i = 0;
|
i = 0;
|
while(i<32 && i < max_stats)
|
while(i<32 && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<32;j++)
|
for(j=0;j<32;j++)
|
largest_i = (insn_info->rA_use_freq[j] >
|
largest_i = (insn_info->rA_use_freq[j] >
|
insn_info->rA_use_freq[largest_i]) ?
|
insn_info->rA_use_freq[largest_i]) ?
|
j : largest_i;
|
j : largest_i;
|
|
|
// No more interesting numbers
|
// No more interesting numbers
|
if (insn_info->rA_use_freq[largest_i] == 0)
|
if (insn_info->rA_use_freq[largest_i] == 0)
|
break;
|
break;
|
|
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"r%d\tcount:\t%d\n",
|
"r%d\tcount:\t%d\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"r%d\",%d\n",
|
|
#endif
|
largest_i,
|
largest_i,
|
insn_info->rA_use_freq[largest_i]);
|
insn_info->rA_use_freq[largest_i]);
|
insn_info->rA_use_freq[largest_i] = -1; // clear this one
|
insn_info->rA_use_freq[largest_i] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
|
|
if (insn_info->has_rB)
|
if (insn_info->has_rB)
|
{
|
{
|
fprintf(stream,"rB usage:\n");
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
"rB usage:\n"
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"rB\",\"count\"\n"
|
|
#endif
|
|
);
|
i = 0;
|
i = 0;
|
while(i<32 && i < max_stats)
|
while(i<32 && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<32;j++)
|
for(j=0;j<32;j++)
|
largest_i = (insn_info->rB_use_freq[j] >
|
largest_i = (insn_info->rB_use_freq[j] >
|
insn_info->rB_use_freq[largest_i]) ?
|
insn_info->rB_use_freq[largest_i]) ?
|
j : largest_i;
|
j : largest_i;
|
|
|
// No more interesting numbers
|
// No more interesting numbers
|
if (insn_info->rB_use_freq[largest_i] == 0)
|
if (insn_info->rB_use_freq[largest_i] == 0)
|
break;
|
break;
|
|
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"r%d\tcount:\t%d\n",
|
"r%d\tcount:\t%d\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"r%d\",%d\n",
|
|
#endif
|
largest_i,
|
largest_i,
|
insn_info->rB_use_freq[largest_i]);
|
insn_info->rB_use_freq[largest_i]);
|
insn_info->rB_use_freq[largest_i] = -1; // clear this one
|
insn_info->rB_use_freq[largest_i] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
|
|
// Print out the most common n-tuple groupings for an instruction
|
// Print out the most common n-tuple groupings for an instruction
|
void or1k_32_generate_ntuple_stats(int n, struct or1k_insn_info *insn_info,
|
void or1k_32_generate_ntuple_stats(int n, struct or1k_insn_info *insn_info,
|
FILE * stream)
|
FILE * stream)
|
{
|
{
|
// Maximum number we'll print out
|
// Maximum number we'll print out
|
#define MAX_NTUPLE_LISTING 5
|
#define MAX_NTUPLE_LISTING 5
|
|
|
|
|
int (*ntuplelist)[OR1K_MAX_GROUPINGS_ANALYSIS+1];
|
int (*ntuplelist)[OR1K_MAX_GROUPINGS_ANALYSIS+1];
|
int *set;
|
int *set;
|
int set_count, set_count2;
|
int set_count, set_count2;
|
|
|
// Get total number of sets for this n-tuple, eg:
|
// Get total number of sets for this n-tuple, eg:
|
// if n=2 (pairs) then groupings[1] is where our list is, and we store the number
|
// if n=2 (pairs) then groupings[1] is where our list is, and we store the
|
// of sets in [0][0] of that n-tuple data.
|
// number of sets in [0][0] of that n-tuple data.
|
int total_sets_for_ntuple = insn_info->groupings[n-1][0][0];
|
int total_sets_for_ntuple = insn_info->groupings[n-1][0][0];
|
|
|
if (total_sets_for_ntuple == 0)
|
if (total_sets_for_ntuple == 0)
|
return;
|
return;
|
|
|
fprintf(stream, "%d-tuple groupings finishing with %s (%d)\n",n, insn_info->insn_string,
|
fprintf(stream,
|
total_sets_for_ntuple);
|
#ifdef DISPLAY_STRING
|
|
"%d-tuple groupings finishing with %s (%d)\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"%d-tuple groupings\",\n",
|
|
#endif
|
|
n, insn_info->insn_string, total_sets_for_ntuple);
|
|
|
|
|
// Debug - dump out all of the info for the sets
|
// Debug - dump out all of the info for the sets
|
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
|
for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
|
{
|
{
|
|
|
printf("set: %d - count %d - set: ", set_count, insn_info->groupings[n-1][set_count+1][n]);
|
printf("set: %d - count %d - set: ", set_count,
|
|
insn_info->groupings[n-1][set_count+1][n]);
|
|
|
for(set_count2=0;set_count2<n;set_count2++)
|
for(set_count2=0;set_count2<n;set_count2++)
|
fprintf(stream, "%s\t",
|
fprintf(stream, "%s\t",
|
or1k_32_insns[(insn_info->groupings[n-1][set_count+1][set_count2])]->insn_string);
|
or1k_32_insns[(insn_info->groupings[n-1][set_count+1][set_count2])]->insn_string);
|
printf("\n");
|
printf("\n");
|
}
|
}
|
#endif
|
#endif
|
|
|
// A pointer to the n-tuple sets
|
// A pointer to the n-tuple sets
|
// This is actually a pointer to a 2-dimensional integer array, looking like:
|
// This is actually a pointer to a 2-dimensional integer array, looking like:
|
// [OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1], so in 2-dimensional
|
// [OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1], so in
|
// array pointer fashion, we should provide the "column" sizing.
|
// 2-dimensional array pointer fashion, we should provide the "column" sizing.
|
ntuplelist = insn_info->groupings[n-1];
|
ntuplelist = insn_info->groupings[n-1];
|
|
|
// Let's make a copy of the counts for each... so we don't trash them
|
// Let's make a copy of the counts for each... so we don't trash them
|
int set_count_copy[OR1K_MAX_ENTRIES_PER_GROUP+1];
|
int set_count_copy[OR1K_MAX_ENTRIES_PER_GROUP+1];
|
|
|
assert(total_sets_for_ntuple <= OR1K_MAX_ENTRIES_PER_GROUP);
|
assert(total_sets_for_ntuple <= OR1K_MAX_ENTRIES_PER_GROUP);
|
|
|
// Go through the list, copy the counts for each
|
// Go through the list, copy the counts for each
|
for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
|
for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
|
{
|
{
|
// Pointer to a set's data
|
// Pointer to a set's data
|
set = ntuplelist[set_count+1];
|
set = ntuplelist[set_count+1];
|
// Fish out the copy (0 to n-1 will be the instruction index, n will be the count)
|
// Fish out the copy (0 to n-1 will be the instruction index, n will be
|
|
// the count)
|
set_count_copy[set_count+1] = set[n];
|
set_count_copy[set_count+1] = set[n];
|
//printf("Set %d, count %d (%d) (%d)\n", set_count+1, set_count_copy[set_count+1],
|
|
//set[n], insn_info->groupings[n-1][set_count+1][n] );
|
|
}
|
}
|
|
|
// Now go through, finding the most frequent n-tuple of instructions and
|
// Now go through, finding the most frequent n-tuple of instructions and
|
// print it out
|
// print it out
|
int largest_indx = 0;
|
int largest_indx = 0;
|
set_count=0;
|
set_count=0;
|
while(set_count < total_sets_for_ntuple && set_count < MAX_NTUPLE_LISTING)
|
while(set_count < total_sets_for_ntuple && set_count < MAX_NTUPLE_LISTING)
|
{
|
{
|
largest_indx = 0;
|
largest_indx = 0;
|
for(set_count2=0;set_count2<total_sets_for_ntuple;set_count2++)
|
for(set_count2=0;set_count2<total_sets_for_ntuple;set_count2++)
|
largest_indx = (set_count_copy[set_count2 + 1] >
|
largest_indx = (set_count_copy[set_count2 + 1] >
|
set_count_copy[largest_indx + 1]) ?
|
set_count_copy[largest_indx + 1]) ?
|
set_count2 : largest_indx;
|
set_count2 : largest_indx;
|
// largest_indx is the index of the set with the highest occurance, so
|
// largest_indx is the index of the set with the highest occurance, so
|
// let's print it out, but first get a pointer to the set's data
|
// let's print it out, but first get a pointer to the set's data
|
set = (int*)ntuplelist[largest_indx+1];
|
set = (int*)ntuplelist[largest_indx+1];
|
|
|
// Print out the sequence of prior isntructions
|
// Print out the sequence of prior isntructions
|
|
#ifdef DISPLAY_STRING
|
fprintf(stream,"Seq:\t");
|
fprintf(stream,"Seq:\t");
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
for(set_count2=0;set_count2<n;set_count2++)
|
|
fprintf(stream, "\"insn%d\",",n-1-set_count2);
|
|
fprintf(stream, "\"count\",\n");
|
|
#endif
|
// Go through the indexes of the previous instructions, get their
|
// Go through the indexes of the previous instructions, get their
|
// strings, and print them out
|
// strings, and print them out
|
for(set_count2=0;set_count2<n;set_count2++)
|
for(set_count2=0;set_count2<n;set_count2++)
|
fprintf(stream, "%s\t", or1k_32_insns[(set[set_count2])]->insn_string);
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
"%s\t",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"%s\",",
|
|
#endif
|
|
or1k_32_insns[(set[set_count2])]->insn_string);
|
|
|
// now print out the occurances
|
// now print out the occurances
|
fprintf(stream, "\t%d\ttimes (%f%%)\n", set[n],
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
|
"\t%d\ttimes (%f%%)\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"%d,\n",
|
|
#endif
|
|
set[n],
|
(float)((float)set[n]/(float)insn_info->count)*100.0f);
|
(float)((float)set[n]/(float)insn_info->count)*100.0f);
|
|
|
// done printing this one out.. let's clear its count
|
// done printing this one out.. let's clear its count
|
set_count_copy[largest_indx + 1] = -1;
|
set_count_copy[largest_indx + 1] = -1;
|
|
|
set_count++;
|
set_count++;
|
}
|
}
|
|
|
return;
|
return;
|
|
|
}
|
}
|
|
|
|
|
// Print out the stats relating to the sequences of instructions most
|
// Print out the stats relating to the sequences of instructions most
|
// common before seeing this instruction
|
// common before seeing this instruction
|
void or1k_32_generate_groupings_stats(struct or1k_insn_info *insn_info,
|
void or1k_32_generate_groupings_stats(struct or1k_insn_info *insn_info,
|
FILE * stream)
|
FILE * stream)
|
{
|
{
|
int n;
|
int n;
|
for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
|
for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
|
or1k_32_generate_ntuple_stats(n, insn_info, stream);
|
or1k_32_generate_ntuple_stats(n, insn_info, stream);
|
|
|
}
|
}
|
|
|
|
// Entry point for statistics generation.
|
void or1k_32_generate_stats(FILE * stream)
|
void or1k_32_generate_stats(FILE * stream)
|
{
|
{
|
|
#ifdef DISPLAY_STRING
|
// Generate some useful things
|
// Generate some useful things
|
fprintf(stream, "Analysis output:\n");
|
fprintf(stream, "Analysis output:\n");
|
|
#endif
|
//
|
//
|
|
|
// Print out all stats for every instruction we saw!
|
// Print out all stats for every instruction we saw!
|
int insn_index;
|
int insn_index;
|
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
{
|
{
|
if (or1k_32_insns[insn_index] != NULL)
|
if (or1k_32_insns[insn_index] != NULL)
|
{
|
{
|
or1k_32_insn_top_x(or1k_32_insns[insn_index],stream,10);
|
or1k_32_insn_top_n(or1k_32_insns[insn_index],stream,10);
|
or1k_32_generate_groupings_stats(or1k_32_insns[insn_index],stream);
|
or1k_32_generate_groupings_stats(or1k_32_insns[insn_index],stream);
|
|
#ifdef DISPLAY_STRING
|
fprintf(stream, "\t---\t---\t---\t---\n");
|
fprintf(stream, "\t---\t---\t---\t---\n");
|
|
#endif
|
}
|
}
|
}
|
}
|
|
|
|
// print out most frequent n-tuple
|
|
int ntuple;
|
|
for(ntuple=2;ntuple<5;ntuple++)
|
|
or1k_32_most_freq_ntuple(ntuple, stream, 10);
|
|
|
// Do most frequent instruction analysis -- note this trashes instruction
|
// Do most frequent instruction analysis -- note this trashes instruction
|
// frequency count - should be fixed
|
// frequency count - should be fixed
|
|
#ifdef DISPLAY_STRING
|
fprintf(stream, "Individual instruction frequency:\n");
|
fprintf(stream, "Individual instruction frequency:\n");
|
|
#endif
|
or1k_32_most_freq_insn(stream);
|
or1k_32_most_freq_insn(stream);
|
|
|
}
|
}
|
|
|
|
|
|
|
|
|
// Free up all added instruction statistic tracking structs
|
// Free up all added instruction statistic tracking structs
|
void or1k_32_insn_lists_free(void)
|
void or1k_32_insn_lists_free(void)
|
{
|
{
|
// Free all entries we m/calloc()'d
|
// Free all entries we m/calloc()'d
|
int insn_index;
|
int insn_index;
|
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
{
|
{
|
if (or1k_32_insns[insn_index] != NULL)
|
if (or1k_32_insns[insn_index] != NULL)
|
free(or1k_32_insns[insn_index]);
|
free(or1k_32_insns[insn_index]);
|
}
|
}
|
}
|
}
|
|
|