📄 inst.c
字号:
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 + -