Example #1
0
/* disassemble a SimpleScalar instruction */
void
md_print_insn(md_inst_t inst,		/* instruction to disassemble */
	      md_addr_t pc,		/* addr of inst, used for PC-rels */
	      FILE *stream)		/* output stream */
{
  enum md_opcode op;

  /* use stderr as default output stream */
  if (!stream)
    stream = stderr;

  /* decode the instruction, assumes predecoded text segment */
  MD_SET_OPCODE(op, inst);

  /* disassemble the instruction */
  if (op == OP_NA || op >= OP_MAX)
    {
      /* bogus instruction */
      fprintf(stream, "<invalid inst: 0x%08x:%08x>", inst.a, inst.b);
    }
  else
    {
      char *s;

      fprintf(stream, "%-10s", MD_OP_NAME(op));

      s = MD_OP_FORMAT(op);
      while (*s) {
	switch (*s) {
	case 'd':
	  fprintf(stream, "r%d", RD);
	  break;
	case 's':
	  fprintf(stream, "r%d", RS);
	  break;
	case 't':
	  fprintf(stream, "r%d", RT);
	  break;
	case 'b':
	  fprintf(stream, "r%d", BS);
	  break;
	case 'D':
	  fprintf(stream, "f%d", FD);
	  break;
	case 'S':
	  fprintf(stream, "f%d", FS);
	  break;
	case 'T':
	  fprintf(stream, "f%d", FT);
	  break;
	case 'j':
	  fprintf(stream, "0x%x", (pc + 8 + (OFS << 2)));
	  break;
	case 'o':
	case 'i':
	  fprintf(stream, "%d", IMM);
	  break;
	case 'H':
	  fprintf(stream, "%d", SHAMT);
	  break;
	case 'u':
	  fprintf(stream, "%u", UIMM);
	  break;
	case 'U':
	  fprintf(stream, "0x%x", UIMM);
	  break;
	case 'J':
	  fprintf(stream, "0x%x", ((pc & 036000000000) | (TARG << 2)));
	  break;
	case 'B':
	  fprintf(stream, "0x%x", BCODE);
	  break;
#if 0 /* FIXME: obsolete... */
	case ')':
	  /* handle pre- or post-inc/dec */
	  if (SS_COMP_OP == SS_COMP_NOP)
	    fprintf(stream, ")");
	  else if (SS_COMP_OP == SS_COMP_POST_INC)
	    fprintf(stream, ")+");
	  else if (SS_COMP_OP == SS_COMP_POST_DEC)
	    fprintf(stream, ")-");
	  else if (SS_COMP_OP == SS_COMP_PRE_INC)
	    fprintf(stream, ")^+");
	  else if (SS_COMP_OP == SS_COMP_PRE_DEC)
	    fprintf(stream, ")^-");
	  else if (SS_COMP_OP == SS_COMP_POST_DBL_INC)
	    fprintf(stream, ")++");
	  else if (SS_COMP_OP == SS_COMP_POST_DBL_DEC)
	    fprintf(stream, ")--");
	  else if (SS_COMP_OP == SS_COMP_PRE_DBL_INC)
	    fprintf(stream, ")^++");
	  else if (SS_COMP_OP == SS_COMP_PRE_DBL_DEC)
	    fprintf(stream, ")^--");
	  else
	    panic("bogus SS_COMP_OP");
	  break;
#endif
	default:
	  /* anything unrecognized, e.g., '.' is just passed through */
	  fputc(*s, stream);
	}
	s++;
      }
    }
}
Example #2
0
File: alpha.c Project: palmerc/lab
/* disassemble an Alpha instruction */
void
md_print_insn(md_inst_t inst,		/* instruction to disassemble */
	      md_addr_t pc,		/* addr of inst, used for PC-rels */
	      FILE *stream)		/* output stream */
{
  enum md_opcode op;

  /* use stderr as default output stream */
  if (!stream)
    stream = stderr;

  /* decode the instruction, assumes predecoded text segment */
  MD_SET_OPCODE(op, inst);

  /* disassemble the instruction */
  if (op <= OP_NA || op >= OP_MAX)
    {
      /* bogus instruction */
      fprintf(stream, "<invalid inst: 0x%08x>", inst);
    }
  else
    {
      char *s;

      fprintf(stream, "%-10s", MD_OP_NAME(op));

      s = MD_OP_FORMAT(op);
      while (*s) {
	switch (*s) {
	case 'a':
	  fprintf(stream, "r%d", RA);
	  break;
	case 'b':
	  fprintf(stream, "r%d", RB);
	  break;
	case 'c':
	  fprintf(stream, "r%d", RC);
	  break;
	case 'A':
	  fprintf(stream, "f%d", RA);
	  break;
	case 'B':
	  fprintf(stream, "f%d", RB);
	  break;
	case 'C':
	  fprintf(stream, "f%d", RC);
	  break;
	case 'o':
	  fprintf(stream, "%d", (sword_t)SEXT(OFS));
	  break;
	case 'j':
	  myfprintf(stream, "0x%p", pc + (SEXT(OFS) << 2) + 4);
	  break;
	case 'J':
	  myfprintf(stream, "0x%p", pc + (SEXT21(TARG) << 2) + 4);
	  break;
	case 'i':
	  fprintf(stream, "%d", (word_t)IMM);
	  break;
	default:
	  /* anything unrecognized, e.g., '.' is just passed through */
	  fputc(*s, stream);
	}
	s++;
      }
    }
}
Example #3
0
/* start simulation, program loaded, processor precise state initialized */
void
sim_main(void)
{
  md_inst_t inst;
  register md_addr_t addr, target_PC;
  enum md_opcode op;
  register int is_write;
  int stack_idx;
  enum md_fault_type fault;

  int out1, out2, in1, in2, in3;	  /* register names */
  int v_out1, v_out2, v_in1, v_in2, v_in3;/* register values */
  int vl_out1, vl_out2, vl_in1, vl_in2, vl_in3;
  md_addr_t addr_dispatch;              /* access_address */
  int m_size;                           /* access_size */
  FILE *stream;
  md_addr_t predicted_PC;

  fprintf(stderr, "sim: ** starting functional simulation w/ predictors **\n");

  /* set up initial default next PC */
  regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t);

  /* check for DLite debugger entry condition */
  if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0))
    dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC,
	       sim_num_insn, &regs, mem);

  while (TRUE)
    {
      /* maintain $r0 semantics */
      regs.regs_R[MD_REG_ZERO] = 0;
#ifdef TARGET_ALPHA
      regs.regs_F.d[MD_REG_ZERO] = 0.0;
#endif /* TARGET_ALPHA */

      /* get the next instruction to execute */
      mem_access(mem, Read, regs.regs_PC, &inst, sizeof(md_inst_t));

      /* keep an instruction count */
      sim_num_insn++;

      /* set default reference address and access mode */
      addr = 0; is_write = FALSE;

      /* set default fault - none */
      fault = md_fault_none;

      /* decode the instruction */
      MD_SET_OPCODE(op, inst);

      /* execute the instruction */
      switch (op)
	{
#define DEFINST(OP,MSK,NAME,OPFORM,RES,CLASS,O1,O2,I1,I2,I3,            \
                VO1,LO1,VO2,LO2,ADDR,VI1,LI1,VI2,LI2,VI3,LI3,M_Size)    \
	case OP:							\
	  in1 = I1; in2 = I2; in3 = I3;					\
	  v_in1 = VI1; v_in2 = VI2; v_in3 = VI3;			\
	  vl_in1 = LI1; vl_in2 = LI2; vl_in3 = LI3;			\
          SYMCAT(OP,_IMPL);						\
	  out1 = O1; out2 = O2;						\
	  v_out1 = VO1; v_out2 = VO2;					\
	  vl_out1 = LO1; vl_out2 = LO2;					\
	  addr_dispatch = ADDR;						\
	  m_size = M_Size;						\
          break;
#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)					\
        case OP:							\
          panic("attempted to execute a linking opcode");
#define CONNECT(OP)
#define DECLARE_FAULT(FAULT)						\
	  { fault = (FAULT); break; }
#include "operand.def"
	default:
	  panic("attempted to execute a bogus opcode");
      }

      if (fault != md_fault_none)
	fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC);

      if (MD_OP_FLAGS(op) & F_MEM)
	{
	  sim_num_refs++;
	  if (MD_OP_FLAGS(op) & F_STORE)
	    is_write = TRUE;
	}

      if (MD_OP_FLAGS(op) & F_CTRL)
	{
	  md_addr_t pred_PC;
	  struct bpred_update_t update_rec;

	  sim_num_branches++;

	  if (pred)
	    {
	      /* get the next predicted fetch address */
	      pred_PC = bpred_lookup(pred,
				     /* branch addr */regs.regs_PC,
				     /* target */target_PC,
				     /* inst opcode */op,
				     /* call? */MD_IS_CALL(op),
				     /* return? */MD_IS_RETURN(op),
				     /* stash an update ptr */&update_rec,
				     /* stash return stack ptr */&stack_idx);

	      /* valid address returned from branch predictor? */
	      if (!pred_PC)
		{
		  /* no predicted taken target, attempt not taken target */
		  pred_PC = regs.regs_PC + sizeof(md_inst_t);
		}

	      bpred_update(pred,
			   /* branch addr */regs.regs_PC,
			   /* resolved branch target */regs.regs_NPC,
			   /* taken? */regs.regs_NPC != (regs.regs_PC +
							 sizeof(md_inst_t)),
			   /* pred taken? */pred_PC != (regs.regs_PC +
							sizeof(md_inst_t)),
			   /* correct pred? */pred_PC == regs.regs_NPC,
			   /* opcode */op,
			   /* predictor update pointer */&update_rec);
	    }
	  predicted_PC = pred_PC;
	}

      /*   ここから下を見ればどの変数に何が入っているか分かるはず。 */
      stream = stdout;
      fprintf(stream, "############################################################ \n");
      fprintf(stream, " --- trace count(%d) \n", (int)sim_num_insn);
      fprintf(sim_fd, "%s, inst: `",
      fprintf(stream, "       opcode: %s, inst: `",
	      MD_OP_NAME(op));
      md_print_insn(inst, regs.regs_PC, stream);
      fprintf(stream, "'\n");
      myfprintf(stream, "         PC: 0x%08p, NPC: 0x%08p",
		regs.regs_PC, regs.regs_NPC);
      if(pred)
	myfprintf(stream, " (pred_PC: 0x%08p)\n",
		  regs.regs_PC, regs.regs_NPC, predicted_PC);
      else
	myfprintf(stream, "\n");
      fprintf(stream," |  in(r%02d,r%02d,r%02d),out(r%02d,r%02d),\n",
	      in1, in2, in3, out1, out2);
      fprintf(stream," |  IN(%8x,%8x,%8x),OUT(%8x,%8x)addr(%8x)|\n",
	      v_in1, v_in2, v_in3, v_out1, v_out2, addr_dispatch);
      /* ダブルワードだった場合,この変数がセットされる */
      fprintf(stream," |  in(%8x,%8x,%8x),out(%8x,%8x)         |\n",
	      vl_in1, vl_in2, vl_in3, vl_out1, vl_out2);

      /* machine.h をみるとopから命令の種類を判別する方法が分かる。以下は例 */
      if (op == MD_NOP_OP)
	{
	  fprintf(stream, "   NOP instruction \n");
	}
      else if (MD_OP_FLAGS(op) & F_MEM)
	{
	  fprintf(stream, "   MEMORY instruction \n");
	  if (MD_OP_FLAGS(op) & F_STORE)
	    fprintf(stream, "        store instruction \n");
	  else if (MD_OP_FLAGS(op) & F_LOAD)
	    fprintf(stream, "        load instruction \n");
	  fprintf(stream, "          ld/st address is %010x\n",
		  addr_dispatch);
	  fprintf(stream, "          ld/st size is %2d\n",
		  m_size);
	  /* ロードストアがバイト単位なのか,ワード単位なのか,
	     ハーフワード単位なのかは,opを見て判断できる。
	     例えば, md_op2name[op] が "sh"ならハーフワードである。
	     しかし、これだと面倒なのでoperand.defを改良した方が良い
	     かも知れない。これはおまかせ。
	     */
	  
	  /* ロードストアの詳細に関しては,machine.def を参照。
	     例えば,store halfの場合,(machine.def をエディタで開いて
	     "sh"と言う文字列をサーチすれば該当箇所が見つかる)
	     以下のようにかかれている。*/
	  /*
                #define SH_IMPL                                     
                  {                                                 
                    half_t _src;                                    
                    enum md_fault_type _fault;                      
                    _src = (half_t)(word_t)GPR(RT);                 
                    WRITE_HALF(_src, GPR(BS) + OFS, _fault);        
                    if (_fault != md_fault_none)                    
                      DECLARE_FAULT(_fault);                        
                   }
		   */
	  /*ここで、GPR(BS)はBS番レジスタの値 OFS はオフセットを示す。
	    そして,GPR(RT)はRT番レジスタの値を示す。
	    そしてWRITE_HALF(_src, GPR(BS) + OFS, _fault);は
	    値 _src をアドレス GPR(BS) + OFS に書き込む事を意味する。
	    書き込みのサイズは,halfワードである。*/
	}
      else if (MD_OP_FLAGS(op) & F_CTRL)
	{
	  fprintf(stream, "   BRANCH instruction \n");
	  if (MD_IS_CALL(op))
	    fprintf(stream, "        function call \n");
	  else if (MD_IS_RETURN(op))
	    fprintf(stream, "        function return \n");
	  else if (MD_IS_INDIR(op))
	    fprintf(stream, "        indirect jump \n");
	  else if ((MD_OP_FLAGS(op) & (F_CTRL|F_DIRJMP)) == (F_CTRL|F_DIRJMP))
	    fprintf(stream, "        direct jump \n");
	}
      else
	{
	  fprintf(stream, "   other instruction \n");
	}
      /* この応用として,いきなりopからstoreを判別するには,以下のようにすれば良い*/
      if ((MD_OP_FLAGS(op) & (F_MEM|F_STORE)) == (F_MEM|F_STORE))
	{
	  /*fprintf(stream, "   store instruction \n");*/
	}
      else if ((MD_OP_FLAGS(op) & (F_MEM|F_LOAD)) == (F_MEM|F_LOAD))
	{
	  /*fprintf(stream, "   load instruction \n");*/
	}

      /* ここまで */


      /* check for DLite debugger entry condition */
      if (dlite_check_break(regs.regs_NPC,
			    is_write ? ACCESS_WRITE : ACCESS_READ,
			    addr, sim_num_insn, sim_num_insn))
	dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, &regs, mem);

      /* go to the next instruction */
      regs.regs_PC = regs.regs_NPC;
      regs.regs_NPC += sizeof(md_inst_t);

      /* finish early? */
      if (max_insts && sim_num_insn >= max_insts)
	return;
    }
}