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

📄 inst.c

📁 用汇编语言编程源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
  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. */#ifdef __STDC__static char*print_imm_expr (char *buf, unsigned int length, imm_expr *expr, int base_reg)#elsestatic char*print_imm_expr (buf, length, expr, base_reg)     char *buf;     int length;     imm_expr *expr;     int base_reg;#endif{  char lbuf[100];  char* lbp = lbuf;  if (expr->symbol != NULL)    {      unsigned int n = strlen (expr->symbol->name);      if (n < length)	{	  strncpy (buf, expr->symbol->name, length);	  buf += n;	  length -= n;	}      else	{	  strncpy (buf, expr->symbol->name, length - 3);	  strncpy (buf + length - 3, "...", 3);	  buf += length;	  length = 0;	}    }  *lbp = '\0';  if (expr->pc_relative)    sprintf (lbp, "-0x%08x", -expr->offset);  else if (expr->offset < -10)    sprintf (lbp, "-%d (-0x%08x)", -expr->offset, -expr->offset);  else if (expr->offset > 10)    sprintf (lbp, "+%d (0x%08x)", expr->offset, expr->offset);  lbp += strlen(lbp);  if (base_reg != -1 && expr->symbol != NULL &&      (expr->offset > 10 || expr->offset < -10))    {      if (expr->offset == 0 && base_reg != 0)	sprintf (lbp, "+0");      if (expr->offset != 0 || base_reg != 0)	sprintf (lbp, "($%d)", base_reg);    }  lbp += strlen (lbp);  if (length <= 0)    ;  else if (strlen (lbuf) < length)    {      strncpy (buf, lbuf, length);      buf += strlen (buf);    }  else    {      strncpy (buf, lbuf, length - 3);      strncpy (buf + length - 3, "...", 3);      buf += length;    }  return (buf);}/* Return non-zero if the EXPRESSION is a constant 0. */#ifdef __STDC__intzero_imm (imm_expr *expr)#elseintzero_imm (expr)     imm_expr *expr;#endif{  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. */#ifdef __STDC__addr_expr *make_addr_expr (int offs, char *sym, int reg_no)#elseaddr_expr *make_addr_expr (offs, sym, reg_no)     int offs;     char *sym;     int reg_no;#endif{  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);}#ifdef __STDC__imm_expr *addr_expr_imm (addr_expr *expr)#elseimm_expr *addr_expr_imm (expr)addr_expr *expr;#endif{  return (expr->imm);}#ifdef __STDC__intaddr_expr_reg (addr_expr *expr)#elseintaddr_expr_reg (expr)addr_expr *expr;#endif{  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. */static int sorted_i_opcode_table = 0; /* Non-zero => table sorted *//* Map from internal opcode -> real opcode */static inst_info 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). */#ifdef __STDC__static voidsort_i_opcode_table (void)#elsestatic voidsort_i_opcode_table ()#endif{  qsort (i_opcode_tbl,	 sizeof (i_opcode_tbl) / sizeof (inst_info),	 sizeof (inst_info),	 (QSORT_FUNC) compare_pair_value);  sorted_i_opcode_table = 1;}#define REGS(R,O) (((R) & 0x1f) << O)#ifdef __STDC__int32inst_encode (instruction *inst)#elseint32inst_encode (inst)     instruction *inst;#endif{  int32 a_opcode = 0;  inst_info *entry;  if (inst == NULL)    return (0);  if (!sorted_i_opcode_table)    sort_i_opcode_table ();  if (!sorted_name_table)    sort_name_table ();  entry = map_int_to_inst_info (i_opcode_tbl,				sizeof (i_opcode_tbl) / sizeof (inst_info),				OPCODE (inst));  if (entry == NULL)    return 0;  a_opcode = entry->value2;  entry = map_int_to_inst_info (name_tbl,				sizeof (name_tbl) / sizeof (inst_info),				OPCODE (inst));  switch (entry->value2)    {    case B0_TYPE_INST:      return (a_opcode	      | (IOFFSET (inst) & 0xffff));    case B1_TYPE_INST:      return (a_opcode	      | REGS (RS (inst), 21)	      | (IOFFSET (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_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_MOV_TYPE_INST:      return (a_opcode	      | REGS (FS (inst), 11)	      | REGS (FD (inst), 6));    case J_TYPE_INST:      return (a_opcode	      | TARGET (inst));    case CP_TYPE_INST:      return (a_opcode	      | REGS (RT (inst), 16)	      | REGS (RD (inst), 11));    case NOARG_TYPE_INST:      return (a_opcode);    case ASM_DIR:    case PSEUDO_OP:    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. */static int sorted_a_opcode_table = 0; /* Non-zero => table sorted *//* Map from internal opcode -> real opcode */static inst_info 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). */#ifdef __STDC__static voidsort_a_opcode_table (void)#elsestatic voidsort_a_opcode_table ()#endif{  qsort (a_opcode_tbl,	 sizeof (a_opcode_tbl) / sizeof (inst_info),	 sizeof (inst_info),	 (QSORT_FUNC) compare_pair_value);  sorted_a_opcode_table = 1;}#define REG(V,O) ((V) >> O) & 0x1f#ifdef __STDC__instruction *  inst_decode (uint32 value)#elseinstruction *  inst_decode (value)uint32 value;#endif{  int32 a_opcode = value & 0xfc000000;  inst_info *entry;  int32 i_opcode;  if (a_opcode == 0)		/* SPECIAL */    a_opcode |= (value & 0x3f);  else if (a_opcode == 0x04000000) /* BCOND */    a_opcode |= (value & 0x001f0000);  else if (a_opcode == 0x40000000) /* COP0 */    a_opcode |= (value & 0x03e00000) | (value & 0x1f);  else if (a_opcode == 0x44000000) /* COP1 */    {      a_opcode |= (value & 0x03e00000);      if ((value & 0xff000000) == 0x45000000)	a_opcode |= (value & 0x00010000); /* BC1f/t */      else	a_opcode |= (value & 0x3f);    }  else if (a_opcode == 0x48000000 /* COPz */	   || a_opcode == 0x4c000000)    a_opcode |= (value & 0x03e00000);  if (!sorted_a_opcode_table)    sort_a_opcode_table ();  if (!sorted_name_table)    sort_name_table ();  entry = map_int_to_inst_info (a_opcode_tbl,				sizeof (a_opcode_tbl) / sizeof (inst_info),				a_opcode);  if (entry == NULL)    return (mk_r_inst (value, 0, 0, 0, 0, 0)); /* Invalid inst */  i_opcode = entry->value2;  switch (map_int_to_inst_info (name_tbl,				sizeof (name_tbl) / sizeof (inst_info),				i_opcode)->value2)    {    case B0_TYPE_INST:      return (mk_i_inst (value, i_opcode, 0, 0, value & 0xffff));    case B1_TYPE_INST:      return (mk_i_inst (value, i_opcode, REG (value, 21), 0, value & 0xffff));    case I1t_TYPE_INST:      return (mk_i_inst (value, i_opcode, REG (value, 21), REG (value, 16),			 value & 0xffff));    case I2_TYPE_INST:    case B2_TYPE_INST:      return (mk_i_inst (value, i_opcode, REG (value, 21), REG (value, 16),			 value & 0xffff));    case I2a_TYPE_INST:      return (mk_i_inst (value, i_opcode, REG (value, 21), REG (value, 16),			 value & 0xffff));    case R1s_TYPE_INST:      return (mk_r_inst (value, i_opcode, REG (value, 21), 0, 0, 0));    case R1d_TYPE_INST:      return (mk_r_inst (value, i_opcode, 0, 0, REG (value, 11), 0));    case R2td_TYPE_INST:      return (mk_r_inst (value, i_opcode, 0, REG (value, 16), REG (value, 11),			 0));    case R2st_TYPE_INST:      return (mk_r_inst (value, i_opcode, REG (value, 21), REG (value, 16),			 0, 0));    case R2ds_TYPE_INST:      return (mk_r_inst (value, i_opcode, REG (value, 21), 0, REG (value, 11),			 0));    case R2sh_TYPE_INST:      return (mk_r_inst (value, i_opcode, 0, REG (value, 16), REG (value, 11),			 REG (value, 6)));    case R3_TYPE_INST:      return (mk_r_inst (value, i_opcode, REG (value, 21), REG (value, 16),			 REG (value, 11), 0));    case R3sh_TYPE_INST:      return (mk_r_inst (value, i_opcode, REG (value, 21), REG (value, 16),			 REG (value, 11), 0));    case FP_I2a_TYPE_INST:      return (mk_i_inst (value, i_opcode, REG (value, 21), REG (value, 16),			 value & 0xffff));    case FP_R2ds_TYPE_INST:      return (mk_r_inst (value, i_opcode, REG (value, 11), 0, REG (value, 6),			 0));    case FP_CMP_TYPE_INST:      {	instruction *inst = mk_r_inst (value, i_opcode, REG (value, 11),				       REG (value, 16), 0, 0);	SET_COND (inst, value & 0xf);	return (inst);      }    case FP_R3_TYPE_INST:      return (mk_r_inst (value, i_opcode, REG (value, 11), REG (value, 16),			 REG (value, 6), 0));    case FP_MOV_TYPE_INST:      return (mk_r_inst (value, i_opcode, REG (value, 11), 0, REG (value, 6),			 0));    case J_TYPE_INST:      return (mk_j_inst (value, i_opcode, value & 0x2ffffff));    case CP_TYPE_INST:      return (mk_r_inst (value, i_opcode, 0, REG (value, 16), REG (value, 11),			 0));    case NOARG_TYPE_INST:      return (mk_r_inst (value, i_opcode, 0, 0, 0, 0));    case ASM_DIR:    case PSEUDO_OP:    default:      return (mk_r_inst (value, 0, 0, 0, 0, 0)); /* Invalid inst */    }}#ifdef __STDC__static instruction *mk_r_inst (uint32 value, int opcode, int rs, int rt, int rd, int shamt)#elsestatic instruction *mk_r_inst (value, opcode, rs, rt, rd, shamt)     uint32 value;     int opcode, rs, rt, rd, shamt;#endif{  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, value);  SET_EXPR (inst, NULL);  return (inst);}#ifdef __STDC__static instruction *mk_i_inst (uint32 value, int opcode, int rs, int rt, int offset)#elsestatic instruction *mk_i_inst (value, opcode, rs, rt, offset)     uint32 value;     int opcode, rs, rt, offset;#endif{  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, value);  SET_EXPR (inst, NULL);  return (inst);}#ifdef __STDC__static instruction *mk_j_inst (uint32 value, int opcode, int target)#elsestatic instruction *mk_j_inst (value, opcode, target)     uint32 value;     int opcode, target;#endif{  instruction *inst = (instruction *) zmalloc (sizeof (instruction));  SET_OPCODE (inst, opcode);  SET_TARGET (inst, target);  SET_ENCODING (inst, value);  SET_EXPR (inst, NULL);  return (inst);}/* Code to test encode/decode of instructions. */#ifdef __STDC__voidtest_assembly (instruction *inst)#elsevoidtest_assembly (inst)     instruction *inst;#endif{  instruction *new_inst = inst_decode (inst_encode (inst));  inst_cmp (inst, new_inst);  free_inst (new_inst);}#ifdef __STDC__static voidinst_cmp (instruction *inst1, instruction *inst2)#elsestatic voidinst_cmp (inst1, inst2)     instruction *inst1, *inst2;#endif{  char buf[1024];  if (memcmp (inst1, inst2, sizeof (instruction) - 4) != 0)    {      printf ("=================== Not Equal ===================\n");      print_inst_internal (buf, sizeof(buf), inst1, 0);      printf ("%s\n", buf);      print_inst_internal (buf, sizeof(buf), inst2, 0);      printf ("%s\n", buf);      printf ("=================== Not Equal ===================\n");    }}

⌨️ 快捷键说明

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