⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inst.c

📁 Spim软件的一些源码。其中有Xspim的
💻 C
📖 第 1 页 / 共 3 页
字号:
  expr->bits = -1;  return (expr);}/* Return an instruction expression for a constant VALUE. */imm_expr *const_imm_expr (int32 value){  return (make_imm_expr (value, NULL, 0));}/* Return a shallow copy of the EXPRESSION with the offset field   incremented by the given amount. */imm_expr *incr_expr_offset (imm_expr *expr, int32 value){  imm_expr *new_expr = copy_imm_expr (expr);  new_expr->offset += value;  return (new_expr);}/* Return the value of the EXPRESSION. */int32eval_imm_expr (imm_expr *expr){  int32 value;  if (expr->symbol == NULL)    value = expr->offset;  else if (SYMBOL_IS_DEFINED (expr->symbol))    {      value = expr->offset + expr->symbol->addr;      if (expr->symbol->gp_flag) /* Addr is offset from $gp */	value += gp_midpoint;    }  else    {      error ("Evaluated undefined symbol: %s\n", expr->symbol->name);      value = 0;    }  if (expr->bits > 0)    return ((value >> 16) & 0xffff);  /* Use upper bits of result */  else if (expr->bits < 0)    return (value & 0xffff);	      /* Use lower bits */  else    return (value);}/* Print the EXPRESSION. */static voidformat_imm_expr (str_stream *ss, imm_expr *expr, int base_reg){  if (expr->symbol != NULL)    {      ss_printf (ss, "%s", expr->symbol->name);    }  if (expr->pc_relative)    ss_printf (ss, "-0x%08x", (unsigned int)-expr->offset);  else if (expr->offset < -10)    ss_printf (ss, "-%d (-0x%08x)", -expr->offset, (unsigned int)-expr->offset);  else if (expr->offset > 10)    ss_printf (ss, "+%d (0x%08x)", expr->offset, (unsigned int)expr->offset);  if (base_reg != -1 && expr->symbol != NULL &&      (expr->offset > 10 || expr->offset < -10))    {      if (expr->offset == 0 && base_reg != 0)	ss_printf (ss, "+0");      if (expr->offset != 0 || base_reg != 0)	ss_printf (ss, "($%d)", base_reg);    }}/* Return non-zero if the EXPRESSION is a constant 0. */intzero_imm (imm_expr *expr){  return (expr->offset == 0 && expr->symbol == NULL);}/* Return an address expression of the form SYMBOL +/- IOFFSET (REGISTER).   Any of the three parts may be omitted. */addr_expr *make_addr_expr (int offs, char *sym, int reg_no){  addr_expr *expr = (addr_expr *) xmalloc (sizeof (addr_expr));  label *lab;  if (reg_no == 0 && sym != NULL && (lab = lookup_label (sym))->gp_flag)    {      expr->reg_no = REG_GP;      expr->imm = make_imm_expr (offs + lab->addr - gp_midpoint, NULL, 0);    }  else    {      expr->reg_no = (unsigned char)reg_no;      expr->imm = make_imm_expr (offs, (sym ? str_copy (sym) : sym), 0);    }  return (expr);}imm_expr *addr_expr_imm (addr_expr *expr){  return (expr->imm);}intaddr_expr_reg (addr_expr *expr){  return (expr->reg_no);}/* Map between a SPIM instruction and the binary representation of the   instruction. *//* Maintain a table mapping from internal opcode (i_opcode) to actual   opcode (a_opcode).  Table must be sorted before first use since its   entries are alphabetical on name, not ordered by opcode. *//* Map from internal opcode -> real opcode */static name_val_val i_opcode_tbl [] = {#undef OP#define OP(NAME, I_OPCODE, TYPE, A_OPCODE) {NAME, I_OPCODE, (int)A_OPCODE},#include "op.h"};/* Sort the opcode table on their key (the interal opcode value). */static voidsort_i_opcode_table (){  qsort (i_opcode_tbl,	 sizeof (i_opcode_tbl) / sizeof (name_val_val),	 sizeof (name_val_val),	 (QSORT_FUNC) compare_pair_value);}#define REGS(R,O) (((R) & 0x1f) << O)int32inst_encode (instruction *inst){  int32 a_opcode = 0;  name_val_val *entry;  if (inst == NULL)    return (0);  entry = map_int_to_name_val_val (i_opcode_tbl,				sizeof (i_opcode_tbl) / sizeof (name_val_val),				OPCODE (inst));  if (entry == NULL)    return 0;  a_opcode = entry->value2;  entry = map_int_to_name_val_val (name_tbl,				sizeof (name_tbl) / sizeof (name_val_val),				OPCODE (inst));  switch (entry->value2)    {    case BC_TYPE_INST:      return (a_opcode	      | REGS (CC (inst) << 2, 16)	      | (IOFFSET (inst) & 0xffff));    case B1_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21)	      | (IOFFSET (inst) & 0xffff));    case I1s_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21)	      | (IMM (inst) & 0xffff));    case I1t_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21)	      | REGS (RT (inst), 16)	      | (IMM (inst) & 0xffff));    case I2_TYPE_INST:    case B2_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21)	      | REGS (RT (inst), 16)	      | (IMM (inst) & 0xffff));    case I2a_TYPE_INST:      return (a_opcode	      | REGS (BASE (inst), 21)	      | REGS (RT (inst), 16)	      | (IOFFSET (inst) & 0xffff));    case R1s_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21));    case R1d_TYPE_INST:      return (a_opcode	      | REGS (RD (inst), 11));    case R2td_TYPE_INST:      return (a_opcode	      | REGS (RT (inst), 16)	      | REGS (RD (inst), 11));    case R2st_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21)	      | REGS (RT (inst), 16));    case R2ds_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21)	      | REGS (RD (inst), 11));    case R2sh_TYPE_INST:      return (a_opcode	      | REGS (RT (inst), 16)	      | REGS (RD (inst), 11)	      | REGS (SHAMT (inst), 6));    case R3_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21)	      | REGS (RT (inst), 16)	      | REGS (RD (inst), 11));    case R3sh_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21)	      | REGS (RT (inst), 16)	      | REGS (RD (inst), 11));    case FP_I2a_TYPE_INST:      return (a_opcode	      | REGS (BASE (inst), 21)	      | REGS (RT (inst), 16)	      | (IOFFSET (inst) & 0xffff));    case FP_R2ds_TYPE_INST:      return (a_opcode	      | REGS (FS (inst), 11)	      | REGS (FD (inst), 6));    case FP_R2ts_TYPE_INST:      return (a_opcode	      | REGS (RT (inst), 16)	      | REGS (FS (inst), 11));    case FP_CMP_TYPE_INST:      return (a_opcode	      | REGS (FT (inst), 16)	      | REGS (FS (inst), 11)	      | (COND (inst) & 0xf));    case FP_R3_TYPE_INST:      return (a_opcode	      | REGS (FT (inst), 16)	      | REGS (FS (inst), 11)	      | REGS (FD (inst), 6));    case FP_MOVC_TYPE_INST:      return (a_opcode	      | REGS (CC (inst), 18)	      | REGS (FS (inst), 11)	      | REGS (FD (inst), 6));    case J_TYPE_INST:      return (a_opcode	      | TARGET (inst));    case NOARG_TYPE_INST:      return (a_opcode);    default:      fatal_error ("Unknown instruction type in inst_encoding\n");      return (0);		/* Not reached */    }}/* Maintain a table mapping from actual opcode to interal opcode.   Table must be sorted before first use since its entries are   alphabetical on name, not ordered by opcode. *//* Map from internal opcode -> real opcode */static name_val_val a_opcode_tbl [] = {#undef OP#define OP(NAME, I_OPCODE, TYPE, A_OPCODE) {NAME, (int)A_OPCODE, (int)I_OPCODE},#include "op.h"};/* Sort the opcode table on their key (the interal opcode value). */static voidsort_a_opcode_table (){  qsort (a_opcode_tbl,	 sizeof (a_opcode_tbl) / sizeof (name_val_val),	 sizeof (name_val_val),	 (QSORT_FUNC) compare_pair_value);}instruction *inst_decode (int32 val){  int32 a_opcode = val & 0xfc000000;  name_val_val *entry;  int32 i_opcode;  if (a_opcode == 0)		/* SPECIAL */    a_opcode |= (val & 0x3f);  else if (a_opcode == 0x04000000) /* BCOND */    a_opcode |= (val & 0x001f0000);  else if (a_opcode == 0x40000000) /* COP0 */    a_opcode |= (val & 0x03e00000) | (val & 0x1f);  else if (a_opcode == 0x44000000) /* COP1 */    {      a_opcode |= (val & 0x03e00000);      if ((val & 0xff000000) == 0x45000000)	a_opcode |= (val & 0x00010000); /* BC1f/t */      else	a_opcode |= (val & 0x3f);    }  else if (a_opcode == 0x48000000 /* COPz */	   || a_opcode == 0x4c000000)    a_opcode |= (val & 0x03e00000);  entry = map_int_to_name_val_val (a_opcode_tbl,				sizeof (a_opcode_tbl) / sizeof (name_val_val),				a_opcode);  if (entry == NULL)    return (mk_r_inst (val, 0, 0, 0, 0, 0)); /* Invalid inst */  i_opcode = entry->value2;  switch (map_int_to_name_val_val (name_tbl,				sizeof (name_tbl) / sizeof (name_val_val),				i_opcode)->value2)    {    case BC_TYPE_INST:      return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val),			 val & 0xffff));    case B1_TYPE_INST:      return (mk_i_inst (val, i_opcode, BIN_RS(val), 0, val & 0xffff));    case I1s_TYPE_INST:      return (mk_i_inst (val, i_opcode, BIN_RS(val), 0, val & 0xffff));    case I1t_TYPE_INST:      return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val),			 val & 0xffff));    case I2_TYPE_INST:    case B2_TYPE_INST:      return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val),			 val & 0xffff));    case I2a_TYPE_INST:      return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val),			 val & 0xffff));    case R1s_TYPE_INST:      return (mk_r_inst (val, i_opcode, BIN_RS(val), 0, 0, 0));    case R1d_TYPE_INST:      return (mk_r_inst (val, i_opcode, 0, 0, BIN_RD(val), 0));    case R2td_TYPE_INST:      return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_RD(val), 0));    case R2st_TYPE_INST:      return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), 0, 0));    case R2ds_TYPE_INST:      return (mk_r_inst (val, i_opcode, BIN_RS(val), 0, BIN_RD(val), 0));    case R2sh_TYPE_INST:      return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_RD(val), BIN_SA(val)));    case R3_TYPE_INST:      return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0));    case R3sh_TYPE_INST:      return(mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0));    case FP_I2a_TYPE_INST:      return (mk_i_inst (val, i_opcode, BIN_BASE(val), BIN_FT(val), val & 0xffff));    case FP_R2ds_TYPE_INST:      return (mk_r_inst (val, i_opcode, BIN_FS(val), 0, BIN_FD(val), 0));    case FP_R2ts_TYPE_INST:      return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_FS(val), 0));    case FP_CMP_TYPE_INST:      {	instruction *inst = mk_r_inst (val, i_opcode, BIN_FS (val), BIN_FT (val), 0, 0);	SET_COND (inst, val & 0xf);	return (inst);      }    case FP_R3_TYPE_INST:      return (mk_r_inst (val, i_opcode, BIN_FS(val), BIN_FT(val), BIN_FD(val), 0));    case FP_MOVC_TYPE_INST:      return (mk_r_inst (val, i_opcode, BIN_FS(val), BIN_RT(val), BIN_FD(val), 0));    case J_TYPE_INST:      return (mk_j_inst (val, i_opcode, val & 0x2ffffff));    case NOARG_TYPE_INST:      return (mk_r_inst (val, i_opcode, 0, 0, 0, 0));    default:      return (mk_r_inst (val, 0, 0, 0, 0, 0)); /* Invalid inst */    }}static instruction *mk_r_inst (int32 val, int opcode, int rs, int rt, int rd, int shamt){  instruction *inst = (instruction *) zmalloc (sizeof (instruction));  SET_OPCODE (inst, opcode);  SET_RS (inst, rs);  SET_RT (inst, rt);  SET_RD (inst, rd);  SET_SHAMT (inst, shamt);  SET_ENCODING (inst, val);  SET_EXPR (inst, NULL);  return (inst);}static instruction *mk_i_inst (int32 val, int opcode, int rs, int rt, int offset){  instruction *inst = (instruction *) zmalloc (sizeof (instruction));  SET_OPCODE (inst, opcode);  SET_RS (inst, rs);  SET_RT (inst, rt);  SET_IOFFSET (inst, offset);  SET_ENCODING (inst, val);  SET_EXPR (inst, NULL);  return (inst);}static instruction *mk_j_inst (int32 val, int opcode, int target){  instruction *inst = (instruction *) zmalloc (sizeof (instruction));  SET_OPCODE (inst, opcode);  SET_TARGET (inst, target);  SET_ENCODING (inst, val);  SET_EXPR (inst, NULL);  return (inst);}/* Code to test encode/decode of instructions. */voidtest_assembly (instruction *inst){  instruction *new_inst = inst_decode (inst_encode (inst));  inst_cmp (inst, new_inst);  free_inst (new_inst);}static voidinst_cmp (instruction *inst1, instruction *inst2){  static str_stream ss;  ss_clear (&ss);  if (memcmp (inst1, inst2, sizeof (instruction) - 4) != 0)    {      ss_printf (&ss, "=================== Not Equal ===================\n");      format_an_inst (&ss, inst1, 0);      format_an_inst (&ss, inst2, 0);      ss_printf (&ss, "=================== Not Equal ===================\n");    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -