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

Subversion Repositories or2k

[/] [or2k/] [trunk/] [analysis-bin/] [insnanalysis/] [or1k-32-insn.c] - Rev 18

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

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

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

powered by: WebSVN 2.1.0

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